# Build — {{PROJECT_NAME}} Implements any feature end-to-end: deep research → TDD → integration tests → external setup checklist → verified PR. Stack: **{{STATE_MANAGEMENT}}** / **{{ARCHITECTURE}}** / **{{BACKEND}}** / {{PLATFORMS_LIST}}. ## Usage ``` /build ``` **Examples:** - `/build implement notification module end-to-end` - `/build add biometric auth` - `/build integrate Stripe payments` - `/build add deep linking for shared product pages` - `/build implement analytics event tracking` --- ## FEATURE_REGISTRY The AI reads this registry to classify the request and load the right research, test scenarios, and setup steps. ```yaml feature_registry: notifications: keywords: [notification, push, fcm, apns, alert, badge, silent push, remote notification, local notification, firebase messaging] pub_packages: [firebase_messaging, flutter_local_notifications, firebase_core] rules_to_load: [security-standards.mdc, platform-ios.mdc, platform-android.mdc] unit_test_scenarios: - parse notification payload to domain model - FCM token generation and storage - token refresh triggers re-registration - notification permission denied returns graceful fallback - notification service initialisation is idempotent widget_test_scenarios: - notification banner renders correct title and body - tap on notification navigates to correct route - badge count updates on new message integration_test_scenarios: - foreground notification receipt and display - background notification receipt (app backgrounded, not killed) - killed-state notification receipt (cold launch from notification tap) - tap-to-open in foreground state routes correctly - tap-to-open in background state routes correctly - tap-to-open in killed state routes correctly - notification payload parsing end-to-end - deep link routing from notification data field - multiple simultaneous notifications (ordering and dedup) external_setup: firebase: [Enable Cloud Messaging, download google-services.json, download GoogleService-Info.plist] ios: [Push Notifications capability, Background Modes remote notifications, APNs .p8 key upload to Firebase] android: [POST_NOTIFICATIONS permission, RECEIVE_BOOT_COMPLETED permission, google-services plugin] files_to_touch: new: [lib/features/notifications/, integration_test/notifications/] modified: [lib/main.dart, android/app/src/main/AndroidManifest.xml, ios/Runner/Info.plist, ios/Runner/AppDelegate.swift, pubspec.yaml] auth: keywords: [auth, authentication, login, sign in, sign out, logout, biometric, face id, touch id, fingerprint, oauth, jwt, session, token refresh, social login, google sign-in] pub_packages: [firebase_auth, supabase_flutter, local_auth, flutter_secure_storage, google_sign_in] rules_to_load: [security-standards.mdc, platform-ios.mdc, platform-android.mdc] unit_test_scenarios: - login success stores token securely - login failure (wrong password) returns typed error - login failure (network) returns typed error - token refresh succeeds and updates stored token - token refresh failure triggers logout - biometric auth success grants access - biometric auth failure falls back to password - biometric not enrolled returns correct error state - logout clears all stored credentials - session persistence: token loaded on cold start widget_test_scenarios: - login form renders correctly - validation errors shown inline - loading state disables submit button - biometric prompt shown when available integration_test_scenarios: - complete login flow (email and password) - login then logout then login again - invalid credentials shows error and stays on login - biometric login flow on enrolled device - biometric fallback to password - token refresh in background while user navigates - cold start with stored valid session skips login - cold start with expired session redirects to login - social auth OAuth redirect and return - deep link into protected route redirects to login then back external_setup: firebase: [Enable Email/Password provider, Enable Google provider, download updated config files] ios: [NSFaceIDUsageDescription in Info.plist, LocalAuthentication.framework in Xcode] android: [USE_BIOMETRIC permission, USE_FINGERPRINT permission, minSdkVersion 23 for biometric] files_to_touch: new: [lib/features/auth/, integration_test/auth/] modified: [lib/main.dart, lib/core/di/injection.dart, pubspec.yaml] payments: keywords: [payment, stripe, in-app purchase, iap, checkout, subscription, billing, apple pay, google pay, card, transaction, refund, revenue cat] pub_packages: [flutter_stripe, purchases_flutter, in_app_purchase] rules_to_load: [security-standards.mdc, platform-ios.mdc, platform-android.mdc] unit_test_scenarios: - checkout request builds correct PaymentIntent params - payment success updates order state - payment failure (card declined) returns typed error - webhook event parsed to domain model - refund request constructs correct API call - subscription status checked on app resume widget_test_scenarios: - checkout form renders with correct amount - payment loading state shown during processing - success confirmation screen renders - error state with retry option integration_test_scenarios: - end-to-end checkout with test card (Stripe test mode) - checkout with 3D Secure challenge - card declined shows error then retry succeeds - Apple Pay / Google Pay sheet appears (device capability check) - subscription purchase and entitlement unlock - subscription restore flow - refund flow from order history external_setup: stripe: [publishable and secret keys in flavor .env files, webhook endpoint in Stripe Dashboard, Apple Pay domain registration] ios: [In-App Purchase capability, Apple Pay capability and merchant identifier, com.apple.developer.in-app-payments entitlement] android: [Google Pay Console setup, BILLING permission for in_app_purchase] files_to_touch: new: [lib/features/payments/, integration_test/payments/] modified: [ios/Runner/Runner.entitlements, android/app/src/main/AndroidManifest.xml, pubspec.yaml] deep_links: keywords: [deep link, deep linking, universal link, app link, deferred deep link, dynamic link, branch, uri scheme, custom scheme, url scheme] pub_packages: [go_router, app_links, uni_links] rules_to_load: [platform-ios.mdc, platform-android.mdc] unit_test_scenarios: - URI parsed to correct route and parameters - unknown URI falls back to home - authenticated-only route redirects to login when unauthenticated - deep link preserves query parameters widget_test_scenarios: - navigation guard redirects unauthenticated deep link integration_test_scenarios: - cold start from Universal Link routes to correct screen - cold start from custom URI scheme routes correctly - backgrounded app receives deep link and navigates - foreground app receives deep link and navigates - deep link to authenticated route redirects to login then original destination - deep link with path parameters loads correct content - invalid or malformed deep link shows 404 screen external_setup: ios: [Associated Domains capability applinks:yourdomain.com, host apple-app-site-association file at /.well-known/] android: [intent-filter with android:autoVerify=true in AndroidManifest.xml, host assetlinks.json at /.well-known/] files_to_touch: new: [lib/core/routing/deep_link_handler.dart, integration_test/deep_links/] modified: [lib/core/routing/router.dart, android/app/src/main/AndroidManifest.xml, ios/Runner/Runner.entitlements, ios/Runner/Info.plist] analytics: keywords: [analytics, tracking, event, mixpanel, amplitude, firebase analytics, segment, posthog, screen view, funnel, cohort] pub_packages: [firebase_analytics, mixpanel_flutter, amplitude_flutter, posthog_flutter] rules_to_load: [security-standards.mdc] unit_test_scenarios: - analytics service logs correct event name and params - PII fields stripped before event sent - analytics disabled in dev flavor - screen name logged on navigation widget_test_scenarios: - RouteObserver triggers screen_view event integration_test_scenarios: - user action triggers expected event (verify via debug view) - screen transitions log screen_view with correct names - opt-out disables all tracking external_setup: firebase: [Enable Analytics in Firebase Console, enable DebugView for local testing, configure conversion events] files_to_touch: new: [lib/core/analytics/analytics_service.dart, lib/core/analytics/analytics_events.dart, integration_test/analytics/] modified: [lib/main.dart, pubspec.yaml] storage: keywords: [storage, file upload, download, cloud storage, firebase storage, supabase storage, s3, image upload, document, file picker, offline, cache, hive, isar, objectbox, sqflite, drift] pub_packages: [firebase_storage, supabase_flutter, hive_flutter, isar, drift, file_picker, image_picker, path_provider] rules_to_load: [security-standards.mdc, platform-ios.mdc, platform-android.mdc] unit_test_scenarios: - upload returns public URL on success - upload failure returns typed error - local cache read before remote fetch (offline-first) - cache invalidation on TTL expiry - large file upload uses resumable upload widget_test_scenarios: - file picker button triggers picker - upload progress indicator shown - image preview renders after selection integration_test_scenarios: - end-to-end file upload and retrieval - offline mode: local cache serves data - background upload completes when connectivity restored - file size limit enforced external_setup: firebase: [Enable Firebase Storage, configure Storage security rules, set CORS policy for web if applicable] ios: [NSPhotoLibraryUsageDescription in Info.plist, NSCameraUsageDescription in Info.plist] android: [READ_EXTERNAL_STORAGE or READ_MEDIA_IMAGES permission] files_to_touch: new: [lib/features/storage/, integration_test/storage/] modified: [android/app/src/main/AndroidManifest.xml, ios/Runner/Info.plist, pubspec.yaml] camera_media: keywords: [camera, photo, video, image picker, qr code, barcode scanner, ar, augmented reality, gallery, media, record, capture] pub_packages: [camera, image_picker, mobile_scanner, qr_flutter, image_cropper, video_player] rules_to_load: [security-standards.mdc, platform-ios.mdc, platform-android.mdc] unit_test_scenarios: - QR/barcode parsed to correct domain model - image compressed before upload - camera permission denied returns typed error widget_test_scenarios: - camera preview widget renders - capture button triggers photo take integration_test_scenarios: - camera opens and captures photo on real device - gallery picker selects image and returns - QR scan decodes valid code correctly - permission denied shows correct error UI external_setup: ios: [NSCameraUsageDescription, NSPhotoLibraryUsageDescription, NSMicrophoneUsageDescription for video] android: [CAMERA permission, READ_MEDIA_IMAGES for gallery access] files_to_touch: new: [lib/features/camera/, integration_test/camera/] modified: [android/app/src/main/AndroidManifest.xml, ios/Runner/Info.plist, pubspec.yaml] ``` --- ## Phase 1: Context Loading **When the user types `/build `, do the following before writing a single line of code:** 1. Read `project-brief.yaml` from the repo root. Extract and hold in context: - `stack.state_management` → **{{STATE_MGMT_RAW}}** - `stack.architecture` → **{{ARCH_RAW}}** - `stack.routing` → **{{ROUTING_RAW}}** - `stack.backend` → **{{BACKENDS_LIST}}** - `stack.platforms` → **{{PLATFORMS_LIST}}** - `stack.codegen` → **{{CODEGEN_LIST}}** - `testing.depth` → **{{TESTING_DEPTH}}** - `testing.e2e_tool` → **{{E2E_TOOL}}** - `features.modules` (existing features) → **{{FEATURES_LIST}}** - `features.special` → **{{SPECIAL_FEATURES}}** - `environments.flavors` → **{{FLAVORS_LIST}}** - `environments.cicd` → **{{CICD_RAW}}** 2. Parse the user's free-text request. Match against `FEATURE_REGISTRY` keywords using longest-match. Multiple types are allowed if the request spans features. 3. Load `.cursor/rules/` files listed under `rules_to_load` for the matched feature type. 4. If the user's message contains a URL or GitHub repo reference, fetch and index it for pattern reference. 5. Check `features.modules` — if the feature already exists in the list, ask: "This feature is already listed in project-brief.yaml. Building additional capability on top of it? (y/n)" 6. Print the context summary table before proceeding: ``` | Field | Value | |------------------|------------------------------| | Feature type | [detected type] | | State management | {{STATE_MANAGEMENT}} | | Architecture | {{ARCHITECTURE}} | | Backend | {{BACKEND}} | | Platforms | {{PLATFORMS_LIST}} | | E2E tool | {{E2E_TOOL}} | | Rules loaded | [list from rules_to_load] | | Existing modules | {{FEATURES_LIST}} | ``` --- ## Phase 2: Deep Research **Before touching any file, print the full research output.** 1. From the FEATURE_REGISTRY, enumerate all `pub_packages` for the detected type. For each, determine the correct version compatible with current Flutter stable (`flutter --version`). Print the full `pubspec.yaml` additions. 2. Build the complete file manifest, adapting to `{{ARCHITECTURE}}`: **For {{ARCHITECTURE}} ({{ARCH_RAW}}):** - `clean`: expand each feature layer explicitly → `domain/entities/`, `domain/repositories/`, `domain/usecases/`, `data/models/`, `data/datasources/`, `data/repositories/`, `presentation/` - `feature_first`: `[feature]/[feature]_screen.dart`, `[feature]_provider.dart` or `[feature]_bloc.dart`, `[feature]_repository.dart`, `[feature]_model.dart`, `widgets/` - `mvc`: `[feature]/model/`, `[feature]/view/`, `[feature]/controller/` **State management file naming ({{STATE_MANAGEMENT}} / {{STATE_MGMT_RAW}}):** - `bloc`: `[feature]_bloc.dart`, `[feature]_event.dart`, `[feature]_state.dart` - `riverpod`: `[feature]_provider.dart`, `[feature]_notifier.dart` - `getx`: `[feature]_controller.dart`, `[feature]_binding.dart` 3. List all modified files from `files_to_touch.modified` — show exactly what change goes in each file. 4. List all external service configuration required per platform (from `external_setup`). Only show platforms present in `{{PLATFORMS_LIST}}`. 5. Print research results in this format: ``` ## Research Results ### Packages to add to pubspec.yaml - [package_name]: ^[version] ### Files to create ({{ARCHITECTURE}} / {{STATE_MANAGEMENT}}) lib/features/[name]/... (full list) ### Files to modify [file_path] — [what changes] ### External services requiring configuration - [Service] ([platform]) — [what to do] ``` Do not touch any file until the user has seen this output. --- ## Phase 3: TDD Implementation > **Invoke skill: `superpowers:test-driven-development`** Follow Red → Green → Refactor strictly. Show actual terminal output at each step. ### Step 3a — Red: Write all failing tests first 1. Mirror the feature directory under `test/features/[feature]/`. 2. Write unit tests for **every scenario** in `FEATURE_REGISTRY.unit_test_scenarios` for the detected type. 3. Write widget tests for **every scenario** in `FEATURE_REGISTRY.widget_test_scenarios`. 4. Use `mocktail` for all dependencies. 5. Test naming convention: `'given [precondition], when [action], then [expected outcome]'` 6. Use the state management test pattern for **{{STATE_MANAGEMENT}}**: ``` {{TEST_PATTERN}} ``` 7. Run and confirm red: ``` flutter test test/features/[feature]/ --no-pub ``` **Paste the actual output here before proceeding.** ### Step 3b — Green: Implement 1. Create domain entities and repository interfaces. 2. Create data-layer implementations wiring to `{{BACKEND}}`. 3. Create presentation layer using **{{STATE_MANAGEMENT}}** patterns. 4. Register in DI container — follow `{{ARCH_IMPORT_RULES}}`. 5. Wire the route in `{{ROUTING}}` router. 6. If `{{CODEGEN_LIST}}` is not `none`: run `dart run build_runner build --delete-conflicting-outputs` after adding models. 7. Run tests and confirm green: ``` flutter test test/features/[feature]/ --no-pub ``` **Paste the actual output here before proceeding.** ### Step 3c — Refactor 1. Review for duplication, naming, and layer boundary violations per `.cursor/rules/flutter-core.mdc`. 2. Run and confirm clean: ``` flutter analyze ``` **Paste the actual output here before proceeding.** 3. Run tests once more to confirm still green. --- ## Phase 4: Integration Test Generation **Generate `integration_test/[feature_type]/` before asking the user to run anything.** ### Integration test file structure Each test file follows this template: ```dart // integration_test/[feature]/[scenario]_test.dart // Generated by /build — {{PROJECT_NAME}} // Feature: [feature_type] | Scenario: [scenario_name] // Run with: flutter test integration_test/[feature]/[scenario]_test.dart -d import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; import 'package:{{PACKAGE_ID}}/main.dart' as app; void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); group('[FeatureType] — [Scenario Name]', () { setUp(() async { // Seed state / configure mocks / reset storage }); tearDown(() async { // Cleanup }); testWidgets( 'given [precondition], when [action], then [expected outcome]', (tester) async { app.main(); await tester.pumpAndSettle(); // test body }, ); }); } ``` **For `{{E2E_TOOL}}` (patrol):** swap `flutter_test` imports for `package:patrol` and use Patrol's `$` NativeAutomator selector syntax. ### Files to generate Create one file per logical scenario cluster from `FEATURE_REGISTRY.integration_test_scenarios`. Also generate `integration_test/[feature]/README.md` with the full test matrix and run commands. ### PAUSE GATE — user must run on device After generating all files, print this table and **stop**. Wait for the user to paste device output before Phase 6. ``` ## ACTION REQUIRED — Run Integration Tests on Real Device | File | Covers | Requires Hardware | |------|--------|------------------| | integration_test/[feature]/[scenario]_test.dart | [what it covers] | Yes/No | ... Run on iOS: flutter test integration_test/[feature]/ -d Run on Android: flutter test integration_test/[feature]/ -d Paste the output here to continue. ``` --- ## Phase 5: External Setup Checklist **Print before asking the user to verify anything. Group by service/platform. Only show sections for platforms in `{{PLATFORMS_LIST}}`.** ### Format for console/service steps (numbered list): ```markdown ### Firebase (backend: {{BACKEND}}) - [ ] 1. Open Firebase Console → [exact menu path] - [ ] 2. [Specific action] - [ ] 3. Download updated config file → place at [exact path] ``` ### Format for native platform steps (table): ```markdown ### iOS Setup | Step | Where | What | How to Verify | |------|-------|------|---------------| | [Step name] | [Xcode location / file path] | [Exact change] | [Verification method] | ``` ```markdown ### Android Setup - [ ] 1. Open `android/app/src/main/AndroidManifest.xml` - Add: `` - [ ] 2. [Next step with exact value] ``` ### Flavor scoping note (flavors: {{FLAVORS_LIST}}) Config files and API keys must be scoped per flavor. Never place production keys in `dev` flavor files. Follow the pattern established in `.cursor/rules/` for flavor-based configuration. --- ## Phase 6: Verification Gate > **Invoke skill: `superpowers:verification-before-completion`** **Do not claim completion without pasting real output for every item below.** ``` VERIFICATION REQUIRED — paste real output for each: [ ] flutter test test/features/[feature]/ --no-pub Required: "All N tests passed." [ ] flutter analyze Required: "No issues found!" [ ] Integration test device output (from Phase 4 pause gate) Required: actual device test output [ ] lefthook run pre-commit Required: all hooks passed ``` If any check fails: invoke `superpowers:systematic-debugging` to diagnose before retrying. Do not proceed to Phase 7 until all four checks are green. --- ## Phase 7: PR Preparation > **Invoke skill: `superpowers:finishing-a-development-branch`** 1. **Commit message** (conventional commits format): ``` feat([feature_type]): implement [feature] end-to-end ``` 2. **PR description template:** ```markdown ## What [One sentence: what feature was implemented] ## Test coverage - Unit/widget tests: N passing - Integration test matrix: | Scenario | iOS | Android | |----------|-----|---------| | [scenario] | ✅ | ✅ | ## External setup completed - [ ] [Service 1 setup] - [ ] [Service 2 setup] ## Notes [Any follow-up TODOs or known limitations] ``` 3. **CI/CD advice for {{CICD_TOOL}} ({{CICD_RAW}}):** Ensure workflow secrets are scoped per flavor ({{FLAVORS_LIST}}). Never expose production keys in dev environment secrets. Verify the CI workflow runs `flutter test` and `flutter analyze` before deploy steps. --- ## Rules applied every phase Always active — read before writing any code: - `.cursor/rules/flutter-core.mdc` - `.cursor/rules/security-standards.mdc` - `.cursor/rules/project-context.mdc` - Feature-type-specific rules from `FEATURE_REGISTRY.rules_to_load` Architecture import rules for **{{ARCHITECTURE}}**: {{ARCH_IMPORT_RULES}} --- ## Code generation notes **Codegen tools configured: {{CODEGEN_LIST}}** After adding any new model or injectable class, run: ``` dart run build_runner build --delete-conflicting-outputs ``` Commit generated files (`.g.dart`, `.freezed.dart`, `injection.config.dart`) — do not gitignore them. **Template version:** {{TEMPLATE_VERSION}}