@donotdev/cli 0.0.15 → 0.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/dependencies-matrix.json +36 -20
  2. package/dist/bin/commands/build.js +69 -52
  3. package/dist/bin/commands/bump.js +7 -13
  4. package/dist/bin/commands/create-app.js +77 -29
  5. package/dist/bin/commands/create-project.js +109 -135
  6. package/dist/bin/commands/deploy.js +97 -45
  7. package/dist/bin/commands/dev.js +43 -24
  8. package/dist/bin/commands/doctor.d.ts +6 -0
  9. package/dist/bin/commands/doctor.d.ts.map +1 -0
  10. package/dist/bin/commands/{lint.js → doctor.js} +1178 -147
  11. package/dist/bin/commands/doctor.js.map +1 -0
  12. package/dist/bin/commands/emu.js +297 -107
  13. package/dist/bin/commands/make-admin.js +77499 -11
  14. package/dist/bin/commands/preview.js +44 -25
  15. package/dist/bin/commands/setup.d.ts +6 -0
  16. package/dist/bin/commands/setup.d.ts.map +1 -0
  17. package/dist/bin/commands/setup.js +11733 -0
  18. package/dist/bin/commands/setup.js.map +1 -0
  19. package/dist/bin/commands/type-check.js +2018 -283
  20. package/dist/bin/dndev.js +54 -58
  21. package/dist/bin/donotdev.js +28 -44
  22. package/dist/index.js +633 -416
  23. package/package.json +2 -2
  24. package/templates/app-expo/.env.example +2 -22
  25. package/templates/app-expo/README.md.example +1 -1
  26. package/templates/app-expo/assets/adaptive-icon.png +0 -0
  27. package/templates/app-expo/assets/favicon.png +0 -0
  28. package/templates/app-expo/assets/icon.png +0 -0
  29. package/templates/app-expo/assets/splash.png +0 -0
  30. package/templates/app-expo/src/config/app.ts.example +46 -0
  31. package/templates/app-expo/src/config/providers.ts.example +7 -0
  32. package/templates/app-next/src/config/providers.ts.example +7 -0
  33. package/templates/app-vite/src/config/providers.ts.example +7 -0
  34. package/templates/app-vite/src/pages/HomePage.tsx.example +1 -1
  35. package/templates/functions-firebase/README.md.example +1 -1
  36. package/templates/functions-firebase/functions-firebase/.env.example.example +1 -1
  37. package/templates/functions-firebase/functions-firebase/README.md.example +1 -1
  38. package/templates/functions-firebase/functions-firebase/tsconfig.json.example +1 -1
  39. package/templates/functions-firebase/functions.config.js.example +1 -1
  40. package/templates/functions-supabase/supabase/config.toml.example +59 -0
  41. package/templates/functions-supabase/supabase/functions/.env.example +13 -0
  42. package/templates/functions-supabase/supabase/functions/deno.json.example +8 -0
  43. package/templates/overlay-firebase/env.fragment.example +1 -1
  44. package/templates/overlay-firebase/env.fragment.expo.example +1 -1
  45. package/templates/overlay-firebase/env.fragment.nextjs.example +1 -1
  46. package/templates/overlay-supabase/env.fragment.example +8 -3
  47. package/templates/overlay-supabase/env.fragment.expo.example +8 -3
  48. package/templates/overlay-supabase/env.fragment.nextjs.example +8 -3
  49. package/templates/overlay-vercel/env.fragment.example +1 -1
  50. package/templates/overlay-vercel/env.fragment.nextjs.example +1 -1
  51. package/templates/root-consumer/AI.md.example +15 -0
  52. package/templates/root-consumer/guides/dndev/AGENT_START_HERE.md.example +2 -2
  53. package/templates/root-consumer/guides/dndev/ENV_SETUP.md.example +6 -6
  54. package/templates/root-consumer/guides/dndev/INDEX.md.example +2 -2
  55. package/templates/root-consumer/guides/dndev/SETUP_APP_CONFIG.md.example +3 -3
  56. package/templates/root-consumer/guides/dndev/SETUP_CRUD.md.example +98 -0
  57. package/templates/root-consumer/guides/dndev/SETUP_FIREBASE.md.example +4 -4
  58. package/templates/root-consumer/guides/dndev/SETUP_OAUTH_PROVIDERS.md.example +60 -0
  59. package/templates/root-consumer/guides/dndev/SETUP_STRIPE.md.example +62 -0
  60. package/templates/root-consumer/guides/dndev/SETUP_SUPABASE.md.example +3 -3
  61. package/templates/root-consumer/guides/dndev/SETUP_VERCEL.md.example +2 -2
  62. package/templates/root-consumer/guides/wai-way/WAI_WAY_CLI.md.example +7 -8
  63. package/templates/root-consumer/guides/wai-way/blueprints/1_scaffold.md.example +9 -5
  64. package/dist/bin/commands/lint.d.ts +0 -11
  65. package/dist/bin/commands/lint.d.ts.map +0 -1
  66. package/dist/bin/commands/lint.js.map +0 -1
  67. package/dist/bin/commands/staging.d.ts +0 -11
  68. package/dist/bin/commands/staging.d.ts.map +0 -1
  69. package/dist/bin/commands/staging.js +0 -12
  70. package/dist/bin/commands/staging.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@donotdev/cli",
3
- "version": "0.0.15",
3
+ "version": "0.0.16",
4
4
  "description": "Command-line interface for DoNotDev Framework",
5
5
  "type": "module",
6
6
  "private": false,
@@ -30,7 +30,7 @@
30
30
  "build": "dndev bundle --package @donotdev/cli",
31
31
  "dev": "tsc --watch",
32
32
  "clean": "rimraf dist tsconfig.tsbuildinfo",
33
- "type-check": "tsc --noEmit"
33
+ "type-check": "bunx tsc --noEmit"
34
34
  },
35
35
  "dependencies": {
36
36
  "@clack/prompts": "^1.0.1",
@@ -28,29 +28,9 @@ EXPO_PUBLIC_DONOTDEV_LICENSE_KEY=dndev_your_key_here
28
28
  # EXPO_PUBLIC_SPOTIFY_CLIENT_ID=your_spotify_client_id
29
29
 
30
30
  # =============================================================================
31
- # Firebase Configuration
31
+ # Backend-specific vars are appended below by your backend choice
32
+ # (Firebase, Supabase, etc.) — see overlay templates
32
33
  # =============================================================================
33
- # Get these values from your Firebase project settings
34
- # Run `dndev firebase:setup` to auto-populate, or copy from Firebase Console
35
- EXPO_PUBLIC_FIREBASE_API_KEY=
36
- EXPO_PUBLIC_FIREBASE_PROJECT_ID=
37
- EXPO_PUBLIC_FIREBASE_AUTH_DOMAIN=
38
- EXPO_PUBLIC_FIREBASE_STORAGE_BUCKET=
39
- EXPO_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=
40
- EXPO_PUBLIC_FIREBASE_APP_ID=
41
- EXPO_PUBLIC_FIREBASE_MEASUREMENT_ID=
42
- EXPO_PUBLIC_FIREBASE_FUNCTIONS_REGION=
43
-
44
- # =============================================================================
45
- # Firebase Emulator (Development only)
46
- # =============================================================================
47
- # Set to true to use Firebase emulators instead of production services
48
- EXPO_PUBLIC_USE_FIREBASE_EMULATOR=false
49
- EXPO_PUBLIC_FIREBASE_EMULATOR_HOST=localhost
50
- EXPO_PUBLIC_FIREBASE_EMULATOR_PORT=9099
51
- EXPO_PUBLIC_FIREBASE_AUTH_EMULATOR_HOST=http://localhost:9099
52
- EXPO_PUBLIC_FIREBASE_FIRESTORE_EMULATOR_HOST=localhost:8080
53
- EXPO_PUBLIC_FIREBASE_FUNCTIONS_EMULATOR_PORT=5001
54
34
 
55
35
  # =============================================================================
56
36
  # Stripe Configuration (if using billing)
@@ -8,7 +8,7 @@ Mobile app built with DoNotDev Framework and Expo.
8
8
 
9
9
  - Node.js 20+ and Bun 1.3+
10
10
  - Expo Go app on your phone (for development)
11
- - Firebase project (run `dndev firebase:setup`)
11
+ - Firebase project (run `dndev setup firebase`)
12
12
 
13
13
  ### Development
14
14
 
@@ -0,0 +1,46 @@
1
+ /**
2
+ * @fileoverview Application Configuration (Expo)
3
+ *
4
+ * THIS FILE IS YOUR MAIN CONFIGURATION. Update the values below.
5
+ *
6
+ * QUICK START:
7
+ * 1. Set APP_NAME and APP_SHORT_NAME
8
+ * 2. Run `bun dev` - everything else is automatic
9
+ */
10
+
11
+ import type { AppConfig } from '@donotdev/core';
12
+
13
+ // ============================================================================
14
+ // APP IDENTITY - Update these values
15
+ // ============================================================================
16
+
17
+ export const APP_NAME = '{{appName}}';
18
+ export const APP_SHORT_NAME = '{{appShortName}}';
19
+ export const APP_DESCRIPTION = 'Built with DoNotDev Framework';
20
+
21
+ // ============================================================================
22
+ // MAIN CONFIGURATION
23
+ // ============================================================================
24
+
25
+ export const appConfig: AppConfig = {
26
+ app: {
27
+ name: APP_NAME,
28
+ shortName: APP_SHORT_NAME,
29
+ description: APP_DESCRIPTION,
30
+ },
31
+
32
+ // ==========================================================================
33
+ // FEATURES - Uncomment to enable
34
+ // ==========================================================================
35
+ features: {
36
+ // debug: true, // Enable debug tools in development
37
+ },
38
+
39
+ // ==========================================================================
40
+ // AUTH CONFIG - Uncomment to customize
41
+ // ==========================================================================
42
+ // auth: {
43
+ // authRoute: '/signin',
44
+ // profilePath: '/profile',
45
+ // },
46
+ };
@@ -0,0 +1,7 @@
1
+ // src/config/providers.ts — Provider bootstrap
2
+ // Auto-generated by DoNotDev scaffolding. Edit freely.
3
+ // When you add a backend (Firebase, Supabase), replace this file with the appropriate provider setup.
4
+ // See: guides/dndev/SETUP_PROVIDERS.md
5
+
6
+ // No backend configured — nothing to register.
7
+ // To add a backend later, run: dndev create-app (in an existing project, it merges)
@@ -0,0 +1,7 @@
1
+ // src/config/providers.ts — Provider bootstrap
2
+ // Auto-generated by DoNotDev scaffolding. Edit freely.
3
+ // When you add a backend (Firebase, Supabase), replace this file with the appropriate provider setup.
4
+ // See: guides/dndev/SETUP_PROVIDERS.md
5
+
6
+ // No backend configured — nothing to register.
7
+ // To add a backend later, run: dndev create-app (in an existing project, it merges)
@@ -0,0 +1,7 @@
1
+ // src/config/providers.ts — Provider bootstrap
2
+ // Auto-generated by DoNotDev scaffolding. Edit freely.
3
+ // When you add a backend (Firebase, Supabase), replace this file with the appropriate provider setup.
4
+ // See: guides/dndev/SETUP_PROVIDERS.md
5
+
6
+ // No backend configured — nothing to register.
7
+ // To add a backend later, run: dndev create-app (in an existing project, it merges)
@@ -53,7 +53,7 @@ export default function HomePage() {
53
53
  <Card
54
54
  title="2. Firebase Setup"
55
55
  content={[
56
- 'Run: dndev firebase:setup',
56
+ 'Run: dndev setup firebase',
57
57
  'This will:',
58
58
  ' - Create or select a Firebase project',
59
59
  ' - Create a web app if needed',
@@ -76,7 +76,7 @@ GITHUB_REPO_NAME=your-repo
76
76
 
77
77
  # Firebase Configuration
78
78
  FIREBASE_PROJECT_ID=your-project-id
79
- FIREBASE_REGION=us-central1
79
+ FIREBASE_REGION={{YOUR_REGION}}
80
80
  ```
81
81
 
82
82
  ### Setup Instructions
@@ -35,7 +35,7 @@ STRIPE_WEBHOOK_SECRET=whsec_...
35
35
  # Firebase Configuration (auto-detected, rarely needed manually)
36
36
  # =============================================================================
37
37
  FIREBASE_PROJECT_ID=your-project-id
38
- FIREBASE_REGION=us-central1
38
+ FIREBASE_REGION={{YOUR_REGION}}
39
39
 
40
40
  # =============================================================================
41
41
  # Development
@@ -49,7 +49,7 @@ GITHUB_REPO_NAME=your-repo
49
49
 
50
50
  # Firebase Configuration
51
51
  FIREBASE_PROJECT_ID=your-project-id
52
- FIREBASE_REGION=us-central1
52
+ FIREBASE_REGION={{YOUR_REGION}}
53
53
  ```
54
54
 
55
55
  ### Setup Instructions
@@ -1,5 +1,5 @@
1
1
  {
2
- "extends": "../../../tsconfig.functions.json",
2
+ "extends": "../../../../tsconfig.functions.json",
3
3
  "compilerOptions": {
4
4
  "outDir": "./lib",
5
5
  "rootDir": "./src",
@@ -14,7 +14,7 @@
14
14
 
15
15
  export const functionsConfig = {
16
16
  defaults: {
17
- region: ['us-central1'],
17
+ region: ['{{YOUR_REGION}}'],
18
18
  platform: 'gcfv2',
19
19
  labels: { app: '{{APP_NAME}}' },
20
20
  },
@@ -0,0 +1,59 @@
1
+ # For detailed configuration reference documentation, visit:
2
+ # https://supabase.com/docs/guides/local-development/cli/config
3
+ project_id = "{{projectName}}"
4
+
5
+ [api]
6
+ enabled = true
7
+ port = 54321
8
+ schemas = ["public", "graphql_public"]
9
+ extra_search_path = ["public", "extensions"]
10
+ max_rows = 1000
11
+
12
+ [db]
13
+ port = 54322
14
+ shadow_port = 54320
15
+ major_version = 17
16
+
17
+ [db.pooler]
18
+ enabled = false
19
+ port = 54329
20
+ pool_mode = "transaction"
21
+ default_pool_size = 20
22
+ max_client_conn = 100
23
+
24
+ [db.migrations]
25
+ enabled = true
26
+
27
+ [db.seed]
28
+ enabled = true
29
+ sql_paths = ["./seed.sql"]
30
+
31
+ [auth]
32
+ enabled = true
33
+ site_url = "http://127.0.0.1:3000"
34
+ additional_redirect_urls = ["https://127.0.0.1:3000"]
35
+ jwt_expiry = 3600
36
+ enable_refresh_token_rotation = true
37
+ refresh_token_reuse_interval = 10
38
+ enable_signup = true
39
+ enable_anonymous_sign_ins = false
40
+ minimum_password_length = 6
41
+
42
+ [auth.email]
43
+ enable_signup = true
44
+ double_confirm_changes = true
45
+ enable_confirmations = false
46
+
47
+ [storage]
48
+ enabled = true
49
+ file_size_limit = "50MiB"
50
+
51
+ [edge_runtime]
52
+ enabled = true
53
+ policy = "per_worker"
54
+ inspector_port = 8083
55
+
56
+ [analytics]
57
+ enabled = true
58
+ port = 54327
59
+ backend = "postgres"
@@ -0,0 +1,13 @@
1
+ # =============================================================================
2
+ # Supabase Edge Functions — Secret Keys (DO NOT COMMIT)
3
+ # =============================================================================
4
+ # Get these from: https://supabase.com/dashboard > your project > Settings
5
+ #
6
+ # Secret key: Settings > API > service_role key (or "Secret key" on new projects)
7
+ # DB URL: Settings > Database > Connection string > URI
8
+ #
9
+ # These are SERVER-SIDE ONLY. Never expose in client code.
10
+ # =============================================================================
11
+
12
+ SUPABASE_SECRET_KEY=
13
+ SUPABASE_DB_URL=
@@ -0,0 +1,8 @@
1
+ {
2
+ "imports": {
3
+ "@donotdev/functions/supabase": "npm:@donotdev/functions/supabase",
4
+ "@donotdev/core/server": "npm:@donotdev/core/server",
5
+ "@supabase/supabase-js": "npm:@supabase/supabase-js",
6
+ "valibot": "npm:valibot"
7
+ }
8
+ }
@@ -3,7 +3,7 @@
3
3
  # Firebase Configuration
4
4
  # =============================================================================
5
5
  # Get these values from your Firebase project settings
6
- # Run `dndev firebase:setup` to auto-populate, or copy from Firebase Console
6
+ # Run `dndev setup firebase` to auto-populate, or copy from Firebase Console
7
7
  VITE_FIREBASE_API_KEY=
8
8
  VITE_FIREBASE_PROJECT_ID=
9
9
  # Copy from Firebase Console. Framework uses APP_URL hostname in production automatically.
@@ -3,7 +3,7 @@
3
3
  # Firebase Configuration
4
4
  # =============================================================================
5
5
  # Get these values from your Firebase project settings
6
- # Run `dndev firebase:setup` to auto-populate, or copy from Firebase Console
6
+ # Run `dndev setup firebase` to auto-populate, or copy from Firebase Console
7
7
  EXPO_PUBLIC_FIREBASE_API_KEY=
8
8
  EXPO_PUBLIC_FIREBASE_PROJECT_ID=
9
9
  # Copy from Firebase Console. Framework uses APP_URL hostname in production automatically.
@@ -3,7 +3,7 @@
3
3
  # Firebase Configuration
4
4
  # =============================================================================
5
5
  # Get these values from your Firebase project settings
6
- # Run `dndev firebase:setup` to auto-populate, or copy from Firebase Console
6
+ # Run `dndev setup firebase` to auto-populate, or copy from Firebase Console
7
7
  NEXT_PUBLIC_FIREBASE_API_KEY=
8
8
  NEXT_PUBLIC_FIREBASE_PROJECT_ID=
9
9
  # Copy from Firebase Console. Framework uses APP_URL hostname in production automatically.
@@ -1,7 +1,12 @@
1
1
 
2
2
  # =============================================================================
3
- # Supabase Configuration
3
+ # Supabase Configuration (PUBLIC — safe to commit)
4
+ # =============================================================================
5
+ # Get these from: https://supabase.com/dashboard > your project > Settings > API
6
+ # - Project URL: the https://xxx.supabase.co URL
7
+ # - Public key: "Publishable key" (sb_publishable_...) or legacy "anon key" (eyJ...)
8
+ #
9
+ # Then run: dndev setup supabase
4
10
  # =============================================================================
5
- # Get these values from your Supabase project settings > API
6
11
  VITE_SUPABASE_URL=
7
- VITE_SUPABASE_ANON_KEY=
12
+ VITE_SUPABASE_PUBLIC_KEY=
@@ -1,7 +1,12 @@
1
1
 
2
2
  # =============================================================================
3
- # Supabase Configuration
3
+ # Supabase Configuration (PUBLIC — safe to commit)
4
+ # =============================================================================
5
+ # Get these from: https://supabase.com/dashboard > your project > Settings > API
6
+ # - Project URL: the https://xxx.supabase.co URL
7
+ # - Public key: "Publishable key" (sb_publishable_...) or legacy "anon key" (eyJ...)
8
+ #
9
+ # Then run: dndev setup supabase
4
10
  # =============================================================================
5
- # Get these values from your Supabase project settings > API
6
11
  EXPO_PUBLIC_SUPABASE_URL=
7
- EXPO_PUBLIC_SUPABASE_ANON_KEY=
12
+ EXPO_PUBLIC_SUPABASE_PUBLIC_KEY=
@@ -1,7 +1,12 @@
1
1
 
2
2
  # =============================================================================
3
- # Supabase Configuration
3
+ # Supabase Configuration (PUBLIC — safe to commit)
4
+ # =============================================================================
5
+ # Get these from: https://supabase.com/dashboard > your project > Settings > API
6
+ # - Project URL: the https://xxx.supabase.co URL
7
+ # - Public key: "Publishable key" (sb_publishable_...) or legacy "anon key" (eyJ...)
8
+ #
9
+ # Then run: dndev setup supabase
4
10
  # =============================================================================
5
- # Get these values from your Supabase project settings > API
6
11
  NEXT_PUBLIC_SUPABASE_URL=
7
- NEXT_PUBLIC_SUPABASE_ANON_KEY=
12
+ NEXT_PUBLIC_SUPABASE_PUBLIC_KEY=
@@ -3,7 +3,7 @@
3
3
  # Firebase Configuration (data layer for Vercel-hosted app)
4
4
  # =============================================================================
5
5
  # Get these values from your Firebase project settings
6
- # Run `dndev firebase:setup` to auto-populate, or copy from Firebase Console
6
+ # Run `dndev setup firebase` to auto-populate, or copy from Firebase Console
7
7
  VITE_FIREBASE_API_KEY=
8
8
  VITE_FIREBASE_PROJECT_ID=
9
9
  # Copy from Firebase Console. Framework uses APP_URL hostname in production automatically.
@@ -3,7 +3,7 @@
3
3
  # Firebase Configuration (data layer for Vercel-hosted app)
4
4
  # =============================================================================
5
5
  # Get these values from your Firebase project settings
6
- # Run `dndev firebase:setup` to auto-populate, or copy from Firebase Console
6
+ # Run `dndev setup firebase` to auto-populate, or copy from Firebase Console
7
7
  NEXT_PUBLIC_FIREBASE_API_KEY=
8
8
  NEXT_PUBLIC_FIREBASE_PROJECT_ID=
9
9
  # Copy from Firebase Console. Framework uses APP_URL hostname in production automatically.
@@ -36,6 +36,21 @@ approve_phase() → phase done, move to next
36
36
 
37
37
  Without MCP: read `.d.ts` files directly from `node_modules/@donotdev/*/dist/`.
38
38
 
39
+ ## CLI Commands
40
+
41
+ `dndev` is an **installed CLI** (globally via `npm install -g @donotdev/cli`). Run it directly — **never** use `bunx dndev` or `npx dndev`.
42
+
43
+ | Command | What it does |
44
+ |---------|-------------|
45
+ | `dndev create-app` | Interactive wizard — creates a new app in the monorepo |
46
+ | `dndev dev` | Start the dev server (Vite/Next.js via Turbo) |
47
+ | `dndev emu start` | Start Firebase emulators |
48
+ | `dndev deploy` | Deploy to production |
49
+ | `dndev setup firebase` | Configure Firebase project + .env |
50
+ | `dndev setup supabase` | Configure Supabase project + .env |
51
+
52
+ `dndev create-app` is **interactive** — it prompts for builder (Vite/Next.js/Expo), backend (Firebase/Supabase/none), and features. There is no `--preset` flag.
53
+
39
54
  ## Rules
40
55
 
41
56
  - **ESM only** — never `require()`
@@ -46,7 +46,7 @@ Call `start_phase(N)` to begin each phase. It returns the blueprint, agent perso
46
46
 
47
47
  ### Phase 1: SCAFFOLD (Extractor)
48
48
  - **MCP:** `start_phase(1)`
49
- - **Goal:** Running skeleton. Use `dndev create-app` and create `*Page.tsx` stubs.
49
+ - **Goal:** Running skeleton. Run `dndev create-app` (interactive wizard, run directly — never `bunx`) and create `*Page.tsx` stubs.
50
50
 
51
51
  ### Phase 2: ENTITIES (Architect)
52
52
  - **MCP:** `start_phase(2)`
@@ -81,7 +81,7 @@ Check that the user has completed environment setup:
81
81
  2. Service account key exists? (`service-account-key.json` in app root)
82
82
  3. Emulators work? (`dndev emu start` runs without errors)
83
83
 
84
- If not, coach them: "Run `dndev firebase:setup` first, then follow the prompts." See [SETUP_FIREBASE.md](./SETUP_FIREBASE.md).
84
+ If not, coach them: "Run `dndev setup firebase` first, then follow the prompts." See [SETUP_FIREBASE.md](./SETUP_FIREBASE.md).
85
85
 
86
86
  ---
87
87
 
@@ -11,9 +11,9 @@ If you haven’t run `dndev init` yet, see [AGENT_START_HERE.md](./AGENT_START_H
11
11
  ```
12
12
  bun install -> install dependencies
13
13
  bun dev -> start app, read the homepage setup guide
14
- dndev firebase:setup -> configure Firebase project + .env
14
+ dndev setup firebase -> configure Firebase project + .env
15
15
  -- or --
16
- dndev supabase:setup -> configure Supabase project + .env
16
+ dndev setup supabase -> configure Supabase project + .env
17
17
  dndev emu start -> test locally with emulators (Firebase)
18
18
  dndev deploy -> deploy to production
19
19
  ```
@@ -52,7 +52,7 @@ git push -u origin main
52
52
  ### Firebase
53
53
 
54
54
  ```bash
55
- dndev firebase:setup
55
+ dndev setup firebase
56
56
  ```
57
57
 
58
58
  Automates: project selection/creation, web app, SDK config -> `.env`, `.firebaserc`.
@@ -66,7 +66,7 @@ See [SETUP_FIREBASE.md](./SETUP_FIREBASE.md) for full details.
66
66
  ### Supabase
67
67
 
68
68
  ```bash
69
- dndev supabase:setup
69
+ dndev setup supabase
70
70
  ```
71
71
 
72
72
  Asks for your **public** project URL and anon key (both safe to share -- shipped in client bundle).
@@ -188,8 +188,8 @@ my-project/
188
188
  |---------|-------------|
189
189
  | `bun dev` | Start dev server |
190
190
  | `dndev emu start` | Start Firebase emulators |
191
- | `dndev firebase:setup` | Configure Firebase project + .env |
192
- | `dndev supabase:setup` | Configure Supabase project + .env |
191
+ | `dndev setup firebase` | Configure Firebase project + .env |
192
+ | `dndev setup supabase` | Configure Supabase project + .env |
193
193
  | `dndev deploy` | **Firebase:** hosting + functions + rules. **Supabase:** deploys frontend to [Vercel](https://vercel.com) (via scaffolded vercel.json) and Edge Functions to Supabase. Set `VITE_SUPABASE_*` in Vercel project env. |
194
194
  | `dndev staging` | Deploy to staging environment |
195
195
  | `dndev sync-secrets` | Push functions/.env to runtime (Firebase/Vercel) |
@@ -11,8 +11,8 @@
11
11
  - **Human flow:** P0 (Bun/Node + AI IDE) → Install CLI & `dndev init` → Run **AI.md** → Enjoy. See [AGENT_START_HERE.md](./AGENT_START_HERE.md) § Getting started (for humans).
12
12
  - [ENV_SETUP.md](./ENV_SETUP.md) — After `dndev init`: env, Firebase/Supabase, deploy
13
13
  - [GOTCHAS.md](./GOTCHAS.md) - **Common mistakes & pitfalls** (phase-tagged, read before coding)
14
- - [SETUP_FIREBASE.md](./SETUP_FIREBASE.md) - Firebase project setup (`dndev firebase:setup`)
15
- - [SETUP_SUPABASE.md](./SETUP_SUPABASE.md) - Supabase project setup (`dndev supabase:setup`, `dn generate sql`)
14
+ - [SETUP_FIREBASE.md](./SETUP_FIREBASE.md) - Firebase project setup (`dndev setup firebase`)
15
+ - [SETUP_SUPABASE.md](./SETUP_SUPABASE.md) - Supabase project setup (`dndev setup supabase`, `dn generate sql`)
16
16
  - [SETUP_TESTING.md](./SETUP_TESTING.md) - Test generation (Phase 4)
17
17
 
18
18
  ---
@@ -109,14 +109,14 @@ export default defineViteConfig({
109
109
 
110
110
  **Vite loads `.env` from the app directory only.** Not the repo root.
111
111
 
112
- Run `dndev firebase:setup` to auto-populate Firebase config. See [SETUP_FIREBASE.md](./SETUP_FIREBASE.md).
112
+ Run `dndev setup firebase` to auto-populate Firebase config. See [SETUP_FIREBASE.md](./SETUP_FIREBASE.md).
113
113
 
114
114
  ```bash
115
115
  # apps/<your-app>/.env — client-side variables (exposed to browser)
116
116
  VITE_APP_URL=http://localhost:5173
117
117
  VITE_DONOTDEV_LICENSE_KEY=dndev_your_key_here
118
- VITE_FIREBASE_API_KEY=... # Written by dndev firebase:setup
119
- VITE_FIREBASE_PROJECT_ID=... # Written by dndev firebase:setup
118
+ VITE_FIREBASE_API_KEY=... # Written by dndev setup firebase
119
+ VITE_FIREBASE_PROJECT_ID=... # Written by dndev setup firebase
120
120
  VITE_AUTH_PARTNERS=github,google
121
121
  VITE_STRIPE_PUBLISHABLE_KEY=pk_test_...
122
122
 
@@ -866,6 +866,104 @@ declare module '@donotdev/core' {
866
866
 
867
867
  Then in entity fields you can use `type: 'repairOperations'` and `options: { fieldSpecific: { maxItems: 10 } }` without type errors or `as any`.
868
868
 
869
+ ### Reference Select Fields (Entity Lookup)
870
+
871
+ A common pattern: a field stores a **reference ID** (e.g. `author_ref`) pointing to another entity (e.g. `Author`). The form needs a select/combobox populated with that entity's records, and list/detail views need to display a human-readable label instead of a raw ID.
872
+
873
+ The framework's built-in `reference` type uses `fieldSpecific.displayField` and `fieldSpecific.searchFields`. For **custom** reference types (e.g. `author-select`), follow the same pattern with `fieldSpecific.labelFields`.
874
+
875
+ **Step 1: Augment `CustomFieldOptionsMap`** so `labelFields` is typed:
876
+
877
+ ```typescript
878
+ // entities/crud.d.ts
879
+ import '@donotdev/core';
880
+ declare module '@donotdev/core' {
881
+ interface CustomFieldOptionsMap {
882
+ 'author-select': { labelFields: string[] };
883
+ }
884
+ }
885
+ ```
886
+
887
+ **Step 2: Declare `labelFields` in the entity definition** (SSOT — never hardcode field names in components):
888
+
889
+ ```typescript
890
+ // entities/book.ts
891
+ import { defineEntity } from '@donotdev/core';
892
+
893
+ export const bookEntity = defineEntity({
894
+ name: 'Book',
895
+ collection: 'books',
896
+ fields: {
897
+ author_ref: {
898
+ name: 'author_ref',
899
+ label: 'fields.author',
900
+ type: 'author-select',
901
+ visibility: 'admin',
902
+ validation: { required: false, reference: 'authors' },
903
+ options: { fieldSpecific: { labelFields: ['first_name', 'last_name'] } },
904
+ },
905
+ // ...
906
+ },
907
+ });
908
+ ```
909
+
910
+ **Step 3: Build labels from `labelFields`** in your shared formatters:
911
+
912
+ ```typescript
913
+ // entities/formatters.ts
914
+ /**
915
+ * Build a display label from a record using labelFields from entity field config.
916
+ * Handles Supabase fieldMapper camelCase conversion: tries camelCase first, then snake_case.
917
+ */
918
+ export function buildRecordLabel(
919
+ record: Record<string, unknown>,
920
+ labelFields: string[],
921
+ ): string {
922
+ return labelFields
923
+ .map((field) => {
924
+ const camel = field.replace(/_([a-z])/g, (_, c: string) => c.toUpperCase());
925
+ return record[camel] ?? record[field] ?? '';
926
+ })
927
+ .join(' ')
928
+ .trim();
929
+ }
930
+ ```
931
+
932
+ **Step 4: Read `labelFields` in your custom component** (never hardcode field names):
933
+
934
+ ```typescript
935
+ // components/fields/AuthorSelectField.tsx
936
+ import { buildRecordLabel } from 'entities/formatters';
937
+
938
+ // Inside the component:
939
+ const labelFields: string[] =
940
+ fieldConfig.options?.fieldSpecific?.labelFields ?? [];
941
+
942
+ const options = useMemo(() => {
943
+ return items.map((item) => ({
944
+ value: String(item.id ?? ''),
945
+ label: buildRecordLabel(item, labelFields),
946
+ }));
947
+ }, [items, labelFields]);
948
+ ```
949
+
950
+ **Step 5: Use the same utility for `displayFormatter`** so list/detail views resolve IDs to labels:
951
+
952
+ ```typescript
953
+ // In registerFieldType or in your display formatter
954
+ displayFormatter: (value, config) => {
955
+ if (value == null) return '';
956
+ const options = config?.validation?.options;
957
+ if (Array.isArray(options)) {
958
+ const match = options.find((opt: any) => opt.value === value);
959
+ if (match?.label) return String(match.label);
960
+ }
961
+ return String(value);
962
+ }
963
+ ```
964
+
965
+ > **Key principle:** Entity field definitions are SSOT. Components read `fieldConfig.options.fieldSpecific.labelFields` — they never hardcode which fields to display. This means changing the label format (e.g. adding `company_name`) only requires editing the entity definition, not every component.
966
+
869
967
  ### Custom Schemas (No Custom UI)
870
968
 
871
969
  For custom validation without custom UI, just define the schema:
@@ -7,7 +7,7 @@
7
7
  ## Step 1: Run Firebase Setup
8
8
 
9
9
  ```bash
10
- dndev firebase:setup
10
+ dndev setup firebase
11
11
  ```
12
12
 
13
13
  This command:
@@ -94,7 +94,7 @@ This handles everything:
94
94
  | `functions/.env` | Server secrets: STRIPE_SECRET_KEY, OAuth secrets | Cloud Functions runtime |
95
95
  | Root `.env` | **Not read by Vite.** Reference only. | Nothing |
96
96
 
97
- **`dndev firebase:setup` writes Firebase vars to `apps/<app>/.env` automatically.**
97
+ **`dndev setup firebase` writes Firebase vars to `apps/<app>/.env` automatically.**
98
98
 
99
99
  **Custom domains:** Framework uses `APP_URL` hostname as `authDomain` in production (not Firebase's `projectId.firebaseapp.com`). Copy/paste `FIREBASE_AUTH_DOMAIN` from Firebase Console in both `.env.local` and `.env.production` — framework handles the rest.
100
100
 
@@ -103,7 +103,7 @@ This handles everything:
103
103
  ## Staging Environment (Optional)
104
104
 
105
105
  1. Create a second Firebase project (e.g., `my-app-staging`)
106
- 2. Run `dndev firebase:setup` again and select the staging project
106
+ 2. Run `dndev setup firebase` again and select the staging project
107
107
  3. Add to `.firebaserc`: `{ "projects": { "staging": "my-app-staging" } }`
108
108
  4. Create `service-account-key.staging.json` (same steps as production)
109
109
  5. Deploy: `dndev staging`
@@ -171,4 +171,4 @@ If you deploy manually with `firebase deploy`, you'll need to run this yourself.
171
171
 
172
172
  ---
173
173
 
174
- **`dndev firebase:setup` → download service account key → enable Auth + Firestore → `dndev emu start` → `dndev deploy`. That's it.**
174
+ **`dndev setup firebase` → download service account key → enable Auth + Firestore → `dndev emu start` → `dndev deploy`. That's it.**