@donotdev/cli 0.0.17 → 0.0.19

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 (183) hide show
  1. package/dependencies-matrix.json +67 -60
  2. package/dist/bin/commands/coach.js +8177 -0
  3. package/dist/bin/commands/create-app.js +94 -145
  4. package/dist/bin/commands/create-project.js +98 -149
  5. package/dist/bin/commands/deploy.js +81 -59
  6. package/dist/bin/commands/doctor.js +243 -698
  7. package/dist/bin/commands/emu.js +2 -2
  8. package/dist/bin/commands/format.js +4 -1
  9. package/dist/bin/commands/get-demo.js +8351 -0
  10. package/dist/bin/commands/make-admin.js +773 -152
  11. package/dist/bin/commands/setup.js +519 -1711
  12. package/dist/bin/commands/staging.js +17852 -0
  13. package/dist/bin/commands/sync-secrets.js +2 -11
  14. package/dist/bin/commands/type-check.js +7733 -1713
  15. package/dist/bin/dndev.js +913 -182
  16. package/dist/bin/donotdev.js +913 -182
  17. package/dist/index.js +191 -211
  18. package/package.json +1 -1
  19. package/templates/app-demo/index.html.example +147 -10
  20. package/templates/app-demo/src/App.tsx.example +7 -13
  21. package/templates/app-demo/src/config/app.ts.example +12 -48
  22. package/templates/app-demo/src/entities/product.ts.example +38 -0
  23. package/templates/app-demo/src/globals.css.example +5 -1
  24. package/templates/app-demo/src/main.tsx.example +13 -7
  25. package/templates/app-demo/src/pages/ChangelogPage.tsx.example +14 -0
  26. package/templates/app-demo/src/pages/DashboardPage.tsx.example +15 -0
  27. package/templates/app-demo/src/pages/HomePage.tsx.example +3 -77
  28. package/templates/app-demo/src/pages/PricingPage.tsx.example +14 -0
  29. package/templates/app-demo/src/pages/ProductsPage.tsx.example +17 -0
  30. package/templates/app-demo/src/pages/ProfilePage.tsx.example +16 -0
  31. package/templates/app-demo/src/pages/SettingsPage.tsx.example +15 -0
  32. package/templates/app-demo/src/pages/ShowcaseDetailPage.tsx.example +112 -0
  33. package/templates/app-demo/src/pages/ShowcasePage.tsx.example +91 -0
  34. package/templates/app-demo/src/pages/legal/LegalPage.tsx.example +14 -0
  35. package/templates/app-demo/src/pages/legal/PrivacyPage.tsx.example +14 -0
  36. package/templates/app-demo/src/pages/legal/TermsPage.tsx.example +14 -0
  37. package/templates/app-demo/tsconfig.json.example +1 -1
  38. package/templates/app-demo/vite.config.ts.example +23 -48
  39. package/templates/app-expo/README.md.example +1 -1
  40. package/templates/app-expo/app/index.tsx.example +1 -1
  41. package/templates/app-vite/src/pages/HomePage.tsx.example +8 -10
  42. package/templates/overlay-firebase/env.fragment.example +1 -1
  43. package/templates/overlay-firebase/env.fragment.expo.example +1 -1
  44. package/templates/overlay-firebase/env.fragment.nextjs.example +1 -1
  45. package/templates/overlay-supabase/env.fragment.example +1 -1
  46. package/templates/overlay-supabase/env.fragment.expo.example +1 -1
  47. package/templates/overlay-supabase/env.fragment.nextjs.example +1 -1
  48. package/templates/overlay-vercel/env.fragment.example +1 -1
  49. package/templates/overlay-vercel/env.fragment.nextjs.example +1 -1
  50. package/templates/root-consumer/.claude/commands/brainstorm.md.example +15 -1
  51. package/templates/root-consumer/.claude/commands/build.md.example +24 -2
  52. package/templates/root-consumer/.claude/commands/design.md.example +17 -0
  53. package/templates/root-consumer/.claude/commands/polish.md.example +17 -0
  54. package/templates/root-consumer/AI.md.example +54 -21
  55. package/templates/root-consumer/guides/dndev/AGENT_START_HERE.md.example +21 -6
  56. package/templates/root-consumer/guides/dndev/COMPONENTS_ADV.md.example +16 -179
  57. package/templates/root-consumer/guides/dndev/ENV_SETUP.md.example +19 -21
  58. package/templates/root-consumer/guides/dndev/GOTCHAS.md.example +14 -3
  59. package/templates/root-consumer/guides/dndev/INDEX.md.example +2 -2
  60. package/templates/root-consumer/guides/dndev/SETUP_APP_CONFIG.md.example +3 -3
  61. package/templates/root-consumer/guides/dndev/SETUP_BLOG.md.example +19 -2
  62. package/templates/root-consumer/guides/dndev/SETUP_CRUD.md.example +35 -1
  63. package/templates/root-consumer/guides/dndev/SETUP_FIREBASE.md.example +17 -12
  64. package/templates/root-consumer/guides/dndev/SETUP_LAYOUTS.md.example +32 -0
  65. package/templates/root-consumer/guides/dndev/SETUP_OAUTH_PROVIDERS.md.example +1 -1
  66. package/templates/root-consumer/guides/dndev/SETUP_PAGES.md.example +74 -6
  67. package/templates/root-consumer/guides/dndev/SETUP_STRIPE.md.example +2 -2
  68. package/templates/root-consumer/guides/dndev/SETUP_SUPABASE.md.example +17 -12
  69. package/templates/root-consumer/guides/dndev/SETUP_VERCEL.md.example +37 -16
  70. package/templates/root-consumer/guides/dndev/USE_ROUTING.md.example +18 -18
  71. package/templates/root-consumer/guides/dndev/essences_reference.css.example +119 -2
  72. package/templates/root-consumer/guides/wai-way/blueprints/0_brainstorm.md.example +1 -1
  73. package/templates/root-consumer/guides/wai-way/blueprints/1_scaffold.md.example +14 -0
  74. package/templates/root-consumer/guides/wai-way/blueprints/2_entities.md.example +6 -0
  75. package/templates/root-consumer/guides/wai-way/blueprints/3_compose.md.example +14 -0
  76. package/templates/root-consumer/guides/wai-way/entity_patterns.md.example +4 -5
  77. package/templates/root-consumer/guides/wai-way/page_patterns.md.example +2 -2
  78. package/dist/bin/commands/agent-setup.d.ts +0 -6
  79. package/dist/bin/commands/agent-setup.d.ts.map +0 -1
  80. package/dist/bin/commands/agent-setup.js.map +0 -1
  81. package/dist/bin/commands/build.d.ts +0 -11
  82. package/dist/bin/commands/build.d.ts.map +0 -1
  83. package/dist/bin/commands/build.js.map +0 -1
  84. package/dist/bin/commands/bump.d.ts +0 -11
  85. package/dist/bin/commands/bump.d.ts.map +0 -1
  86. package/dist/bin/commands/bump.js.map +0 -1
  87. package/dist/bin/commands/cacheout.d.ts +0 -11
  88. package/dist/bin/commands/cacheout.d.ts.map +0 -1
  89. package/dist/bin/commands/cacheout.js.map +0 -1
  90. package/dist/bin/commands/create-app.d.ts +0 -11
  91. package/dist/bin/commands/create-app.d.ts.map +0 -1
  92. package/dist/bin/commands/create-app.js.map +0 -1
  93. package/dist/bin/commands/create-project.d.ts +0 -11
  94. package/dist/bin/commands/create-project.d.ts.map +0 -1
  95. package/dist/bin/commands/create-project.js.map +0 -1
  96. package/dist/bin/commands/deploy.d.ts +0 -11
  97. package/dist/bin/commands/deploy.d.ts.map +0 -1
  98. package/dist/bin/commands/deploy.js.map +0 -1
  99. package/dist/bin/commands/dev.d.ts +0 -11
  100. package/dist/bin/commands/dev.d.ts.map +0 -1
  101. package/dist/bin/commands/dev.js.map +0 -1
  102. package/dist/bin/commands/doctor.d.ts +0 -6
  103. package/dist/bin/commands/doctor.d.ts.map +0 -1
  104. package/dist/bin/commands/doctor.js.map +0 -1
  105. package/dist/bin/commands/emu.d.ts +0 -11
  106. package/dist/bin/commands/emu.d.ts.map +0 -1
  107. package/dist/bin/commands/emu.js.map +0 -1
  108. package/dist/bin/commands/format.d.ts +0 -11
  109. package/dist/bin/commands/format.d.ts.map +0 -1
  110. package/dist/bin/commands/format.js.map +0 -1
  111. package/dist/bin/commands/make-admin.d.ts +0 -11
  112. package/dist/bin/commands/make-admin.d.ts.map +0 -1
  113. package/dist/bin/commands/make-admin.js.map +0 -1
  114. package/dist/bin/commands/preview.d.ts +0 -11
  115. package/dist/bin/commands/preview.d.ts.map +0 -1
  116. package/dist/bin/commands/preview.js.map +0 -1
  117. package/dist/bin/commands/setup.d.ts +0 -6
  118. package/dist/bin/commands/setup.d.ts.map +0 -1
  119. package/dist/bin/commands/setup.js.map +0 -1
  120. package/dist/bin/commands/sync-secrets.d.ts +0 -11
  121. package/dist/bin/commands/sync-secrets.d.ts.map +0 -1
  122. package/dist/bin/commands/sync-secrets.js.map +0 -1
  123. package/dist/bin/commands/type-check.d.ts +0 -14
  124. package/dist/bin/commands/type-check.d.ts.map +0 -1
  125. package/dist/bin/commands/type-check.js.map +0 -1
  126. package/dist/bin/commands/wai.d.ts +0 -11
  127. package/dist/bin/commands/wai.d.ts.map +0 -1
  128. package/dist/bin/commands/wai.js.map +0 -1
  129. package/dist/index.d.ts +0 -8
  130. package/dist/index.d.ts.map +0 -1
  131. package/dist/index.js.map +0 -1
  132. package/templates/app-demo/src/components/ThemeToggle.tsx.example +0 -48
  133. package/templates/app-demo/src/pages/DetailPage.tsx.example +0 -103
  134. package/templates/app-demo/src/pages/FullPage.tsx.example +0 -142
  135. package/templates/app-demo/src/pages/components/DemoLayout.tsx.example +0 -266
  136. package/templates/app-demo/src/pages/components/LayoutRoute.tsx.example +0 -20
  137. package/templates/functions-firebase/functions-firebase/README.md.example +0 -123
  138. package/templates/functions-firebase/functions-firebase/build.mjs.example +0 -5
  139. package/templates/functions-firebase/functions-firebase/src/auth/getCustomClaims.ts.example +0 -19
  140. package/templates/functions-firebase/functions-firebase/src/auth/getUserAuthStatus.ts.example +0 -21
  141. package/templates/functions-firebase/functions-firebase/src/auth/index.ts.example +0 -11
  142. package/templates/functions-firebase/functions-firebase/src/auth/removeCustomClaims.ts.example +0 -21
  143. package/templates/functions-firebase/functions-firebase/src/auth/setCustomClaims.ts.example +0 -21
  144. package/templates/functions-firebase/functions-firebase/src/billing/handleStripeWebhook.ts.example +0 -24
  145. package/templates/functions-firebase/functions-firebase/src/billing/index.ts.example +0 -10
  146. package/templates/functions-firebase/functions-firebase/src/billing/processPaymentSuccess.ts.example +0 -14
  147. package/templates/functions-firebase/functions-firebase/src/billing/refreshSubscriptionStatus.ts.example +0 -14
  148. package/templates/functions-firebase/functions-firebase/src/index.ts.example +0 -39
  149. package/templates/functions-firebase/functions-firebase/src/oauth/checkGitHubAccess.ts.example +0 -14
  150. package/templates/functions-firebase/functions-firebase/src/oauth/disconnect.ts.example +0 -14
  151. package/templates/functions-firebase/functions-firebase/src/oauth/exchangeToken.ts.example +0 -14
  152. package/templates/functions-firebase/functions-firebase/src/oauth/getConnections.ts.example +0 -14
  153. package/templates/functions-firebase/functions-firebase/src/oauth/grantGitHubAccess.ts.example +0 -14
  154. package/templates/functions-firebase/functions-firebase/src/oauth/index.ts.example +0 -17
  155. package/templates/functions-firebase/functions-firebase/src/oauth/refreshToken.ts.example +0 -14
  156. package/templates/functions-firebase/functions-firebase/src/oauth/revokeGitHubAccess.ts.example +0 -14
  157. package/templates/functions-firebase/functions-firebase/tsconfig.json.example +0 -21
  158. package/templates/functions-vercel/functions-vercel/README.md.example +0 -116
  159. package/templates/functions-vercel/functions-vercel/build.mjs.example +0 -52
  160. package/templates/functions-vercel/functions-vercel/src/api/auth/getCustomClaims.ts.example +0 -20
  161. package/templates/functions-vercel/functions-vercel/src/api/auth/getUserAuthStatus.ts.example +0 -20
  162. package/templates/functions-vercel/functions-vercel/src/api/auth/removeCustomClaims.ts.example +0 -20
  163. package/templates/functions-vercel/functions-vercel/src/api/auth/setCustomClaims.ts.example +0 -20
  164. package/templates/functions-vercel/functions-vercel/src/api/billing/handleStripeWebhook.ts.example +0 -20
  165. package/templates/functions-vercel/functions-vercel/src/api/billing/processPaymentSuccess.ts.example +0 -20
  166. package/templates/functions-vercel/functions-vercel/src/api/billing/refreshSubscriptionStatus.ts.example +0 -20
  167. package/templates/functions-vercel/functions-vercel/src/api/crud/createEntity.ts.example +0 -20
  168. package/templates/functions-vercel/functions-vercel/src/api/crud/deleteEntity.ts.example +0 -20
  169. package/templates/functions-vercel/functions-vercel/src/api/crud/getEntity.ts.example +0 -20
  170. package/templates/functions-vercel/functions-vercel/src/api/crud/listEntities.ts.example +0 -20
  171. package/templates/functions-vercel/functions-vercel/src/api/crud/updateEntity.ts.example +0 -20
  172. package/templates/functions-vercel/functions-vercel/src/api/oauth/checkGitHubAccess.ts.example +0 -20
  173. package/templates/functions-vercel/functions-vercel/src/api/oauth/disconnect.ts.example +0 -20
  174. package/templates/functions-vercel/functions-vercel/src/api/oauth/exchangeToken.ts.example +0 -20
  175. package/templates/functions-vercel/functions-vercel/src/api/oauth/getConnections.ts.example +0 -20
  176. package/templates/functions-vercel/functions-vercel/src/api/oauth/grantGitHubAccess.ts.example +0 -20
  177. package/templates/functions-vercel/functions-vercel/src/api/oauth/refreshToken.ts.example +0 -20
  178. package/templates/functions-vercel/functions-vercel/src/api/oauth/revokeGitHubAccess.ts.example +0 -20
  179. package/templates/functions-vercel/functions-vercel/tsconfig.json.example +0 -21
  180. package/templates/functions-vercel/functions-vercel/vercel.json.example +0 -14
  181. package/templates/github/github/workflows/firebase-deploy.yml.example +0 -79
  182. /package/templates/functions-firebase/{functions-firebase/.env.example.example → .env.example} +0 -0
  183. /package/templates/functions-vercel/{functions-vercel/.env.example.example → .env.example} +0 -0
@@ -64,32 +64,37 @@ export default function HomePage() {
64
64
  export const meta: PageMeta = {
65
65
  // Translation/SEO namespace
66
66
  namespace: NAMESPACE,
67
-
67
+
68
68
  // Route configuration
69
69
  route: '/custom-url', // Override auto-generated path
70
70
  route: { params: ['slug'] }, // Dynamic: /blog/:slug
71
-
71
+
72
72
  // Page title (optional - auto-extracted from filename)
73
73
  title: 'Custom Title',
74
-
74
+
75
75
  // Navigation icon (lucide-react JSX only)
76
76
  icon: <Rocket />, // Menu icon (default: Link)
77
-
77
+
78
78
  // Hide from navigation menu
79
79
  hideFromMenu: false, // Default: false (shows in nav)
80
-
80
+
81
+ // Layout preset override (per-route)
82
+ preset: 'admin', // Override app default for this route
83
+
81
84
  // Authentication
82
85
  auth: true, // Simple: auth required
83
86
  auth: { required: true }, // Explicit: auth required
84
87
  auth: { required: true, role: 'admin' }, // Role-based access
85
88
  auth: { required: true, tier: 'pro' }, // Tier-based access
86
- auth: {
89
+ auth: {
87
90
  required: true,
88
91
  validate: (role, tier) => role === 'admin' && tier === 'pro'
89
92
  }, // Custom validation
90
93
  };
91
94
  ```
92
95
 
96
+ **Reference implementation:** The demo app (`packages/cli/templates/app-demo/`) shows all these patterns working together — landing, admin, docs presets, auth, showcase, CRUD, legal pages.
97
+
93
98
  ---
94
99
 
95
100
  ## Advanced: Dynamic Routes & Navigation
@@ -134,4 +139,67 @@ import { Link } from '@donotdev/ui';
134
139
 
135
140
  ---
136
141
 
142
+ ---
143
+
144
+ ## Import Convention
145
+
146
+ **Always import from `@donotdev/<package>` top-level.** Never use sub-paths.
147
+
148
+ ```tsx
149
+ import { PageContainer, Link, useNavigate } from '@donotdev/ui';
150
+ import { Card, Button, Input } from '@donotdev/components';
151
+ import { useCrud } from '@donotdev/crud';
152
+ ```
153
+
154
+ **Sub-path exceptions** (server, config, and provider-specific):
155
+ - **Server:** `@donotdev/core/server`, `@donotdev/firebase/server`, `@donotdev/security/server`
156
+ - **Config:** `@donotdev/core/vite`, `@donotdev/core/next`, `@donotdev/core/functions`
157
+ - **Functions:** `@donotdev/functions/firebase`, `@donotdev/functions/vercel`, `@donotdev/functions/supabase`
158
+
159
+ ---
160
+
161
+ ## SaaS App Pattern
162
+
163
+ For SaaS apps, the standard page structure is:
164
+
165
+ ```
166
+ src/pages/
167
+ HomePage.tsx → / → No auth. Login form OR landing page.
168
+ Redirects to /dashboard when authenticated.
169
+ DashboardPage.tsx → /dashboard → auth: true. Main landing for logged-in users.
170
+ SettingsPage.tsx → /settings → auth: true.
171
+ ...
172
+ ```
173
+
174
+ **HomePage is never auth-guarded.** It's the entry point for unauthenticated users. Do NOT create a separate `LoginPage` — HomePage IS the login.
175
+
176
+ ```tsx
177
+ // src/pages/HomePage.tsx — SaaS pattern
178
+ import { useAuthSafe, useNavigate, PageContainer } from '@donotdev/ui';
179
+ import { LoginForm } from '@donotdev/templates';
180
+
181
+ export const meta: PageMeta = {
182
+ namespace: 'home',
183
+ // No auth — this is the public entry point
184
+ };
185
+
186
+ export default function HomePage() {
187
+ const user = useAuthSafe('user');
188
+ const navigate = useNavigate();
189
+
190
+ // Redirect authenticated users to dashboard
191
+ if (user) { navigate('/dashboard'); return null; }
192
+
193
+ return (
194
+ <PageContainer>
195
+ <LoginForm onSuccess={() => navigate('/dashboard')} />
196
+ </PageContainer>
197
+ );
198
+ }
199
+ ```
200
+
201
+ > **Why `useAuthSafe` instead of `useAuth`?** HomePage is public — it renders before auth is guaranteed to be initialized. `useAuthSafe` (from `@donotdev/ui`) gracefully degrades if `@donotdev/auth` isn't installed or still initializing. `useAuth` (from `@donotdev/auth`) throws if auth isn't available. Use `useAuthSafe` on any page without `auth: true` in its meta.
202
+
203
+ ---
204
+
137
205
  **Drop files, get routes. Framework handles the rest.**
@@ -52,8 +52,8 @@ For subscription testing without waiting for real billing cycles:
52
52
  ## 5. Verify
53
53
 
54
54
  ```bash
55
- dndev setup stripe # Interactive key setup + validation
56
- dndev doctor # Health check for all providers
55
+ dndev setup # Validates key formats + health check
56
+ dndev doctor # Full health check for all providers
57
57
  ```
58
58
 
59
59
  Check that:
@@ -4,29 +4,34 @@
4
4
 
5
5
  ---
6
6
 
7
- ## Step 1: Run Supabase Setup
7
+ ## Step 1: Run Coach + Fill .env
8
8
 
9
9
  ```bash
10
- dndev setup supabase
10
+ dndev coach
11
11
  ```
12
12
 
13
- This command:
14
- - Lets you choose the target app (if you have an `apps/` directory)
15
- - Asks for your **public** Supabase project URL and public key
16
- - Writes `VITE_SUPABASE_URL` and `VITE_SUPABASE_PUBLIC_KEY` to your app's `.env`
13
+ This prints a numbered checklist of what to configure. For Supabase, you'll need:
14
+ - **Project URL** and **public key** paste into your app's `.env`
15
+ - **service_role key** paste into `supabase/functions/.env`
17
16
 
18
- **We only ask for public credentials** (safe to ship in your client bundle). We never ask for the service_role key.
17
+ Get these from: [Supabase Dashboard](https://supabase.com/dashboard) your project **Settings API**.
19
18
 
20
- Get URL and public key from: [Supabase Dashboard](https://supabase.com/dashboard) → your project → **Settings → API**.
19
+ Then run setup to validate and automate:
20
+
21
+ ```bash
22
+ dndev setup
23
+ ```
24
+
25
+ Setup validates your .env values are present, links the Supabase CLI, generates SQL migrations, and runs an inline health check.
21
26
 
22
27
  ---
23
28
 
24
29
  ## Step 2: Generate Tables from Entities
25
30
 
26
- The framework generates PostgreSQL migrations from your entity definitions. This runs automatically as part of `dndev setup supabase`, or you can run it separately:
31
+ The framework generates PostgreSQL migrations from your entity definitions. This runs automatically as part of `dndev setup`, or you can run it separately:
27
32
 
28
33
  ```bash
29
- dndev setup supabase
34
+ dndev setup
30
35
  ```
31
36
 
32
37
  During setup, the wizard detects your entities and generates SQL migrations.
@@ -200,7 +205,7 @@ Or install the [Supabase CLI](https://supabase.com/docs/guides/cli) and run `sup
200
205
  ## Troubleshooting
201
206
 
202
207
  **"Table not found" / "relation does not exist"**
203
- → Run `dndev setup supabase` (generates SQL) then apply migrations with `supabase db push`
208
+ → Run `dndev setup` (generates SQL) then apply migrations with `supabase db push`
204
209
 
205
210
  **"Permission denied" / RLS errors**
206
211
  → Check RLS policies in Supabase Dashboard → Database → Policies
@@ -212,4 +217,4 @@ Or install the [Supabase CLI](https://supabase.com/docs/guides/cli) and run `sup
212
217
 
213
218
  ---
214
219
 
215
- **`dndev setup supabase` → paste URL + public key → apply migrations → `dndev dev`. The adapter normalizes everything automatically.**
220
+ **`dndev coach` → fill .env `dndev setup` → apply migrations → `dndev dev`. The adapter normalizes everything automatically.**
@@ -29,9 +29,32 @@ The framework scaffolds `vercel.json` with CSP headers, rewrites, and caching ru
29
29
 
30
30
  ---
31
31
 
32
- ## Step 2: Set Environment Variables
32
+ ## Step 2: Add Credentials to `.env.local`
33
33
 
34
- In Vercel Dashboard Settings → Environment Variables, copy the env vars from your `apps/<app>/.env`:
34
+ Add these 3 values to `apps/<your-app>/.env.local`:
35
+
36
+ ```env
37
+ # Vercel Deployment Credentials (gitignored — never commit these)
38
+ VERCEL_TOKEN=your_vercel_token
39
+ VERCEL_ORG_ID=your_team_id
40
+ VERCEL_PROJECT_ID=your_project_id
41
+ ```
42
+
43
+ **Where to find them:**
44
+
45
+ | Variable | Where |
46
+ |----------|-------|
47
+ | `VERCEL_TOKEN` | [vercel.com/account/tokens](https://vercel.com/account/tokens) — scope to your team |
48
+ | `VERCEL_ORG_ID` | Vercel Dashboard → Settings → General → **Team ID** |
49
+ | `VERCEL_PROJECT_ID` | Vercel Dashboard → Your Project → Settings → General → **Project ID** |
50
+
51
+ That's it. No `vercel login`, no `vercel link`, no interactive prompts.
52
+
53
+ ---
54
+
55
+ ## Step 3: Set App Environment Variables
56
+
57
+ In **Vercel Dashboard → Project → Settings → Environment Variables**, add your app's env vars:
35
58
 
36
59
  **If using Firebase:**
37
60
  - `VITE_FIREBASE_API_KEY`
@@ -57,26 +80,20 @@ For Next.js apps, replace the `VITE_` prefix with `NEXT_PUBLIC_` (same var names
57
80
 
58
81
  ---
59
82
 
60
- ## Step 3: Deploy
61
-
62
- **Option A — Git push (recommended)**
63
-
64
- Push to your connected branch. Vercel auto-deploys.
83
+ ## Step 4: Deploy
65
84
 
66
85
  ```bash
67
- git push origin main
86
+ dndev deploy
68
87
  ```
69
88
 
70
- **Option B CLI**
89
+ That's it. The CLI reads your credentials from `.env.local` and deploys to production.
71
90
 
72
- ```bash
73
- dndev deploy
74
- ```
91
+ **Option B — Git push (auto-deploy)**
75
92
 
76
- Or directly:
93
+ If your repo is connected to Vercel, pushing to your branch auto-deploys:
77
94
 
78
95
  ```bash
79
- bunx vercel --prod
96
+ git push origin main
80
97
  ```
81
98
 
82
99
  ---
@@ -140,7 +157,7 @@ Available: auth (claims, status, delete account), billing (checkout, cancel, por
140
157
  | File | What Goes Here | Loaded By |
141
158
  |------|---------------|-----------|
142
159
  | `apps/<app>/.env` | Public keys (backend config, license key, Stripe publishable) | Vite/Next.js (dev + build) |
143
- | `apps/<app>/.env.local` | Local overrides (gitignored) | Vite/Next.js (overrides .env) |
160
+ | `apps/<app>/.env.local` | Secrets: `VERCEL_TOKEN`, `VERCEL_ORG_ID`, `VERCEL_PROJECT_ID` (gitignored) | `dndev deploy` |
144
161
  | `apps/<app>/.env.production` | Production overrides | Vite/Next.js (build --mode production) |
145
162
  | Vercel Dashboard | All production env vars (client + server) | Vercel runtime |
146
163
 
@@ -175,6 +192,10 @@ dndev emu start
175
192
 
176
193
  ## Troubleshooting
177
194
 
195
+ **"Missing Vercel credentials"**
196
+ → Check `apps/<app>/.env.local` has all 3 vars: `VERCEL_TOKEN`, `VERCEL_ORG_ID`, `VERCEL_PROJECT_ID`
197
+ → Run `dndev setup` to validate
198
+
178
199
  **"Build fails on Vercel"**
179
200
  → Check Root Directory is set to your app directory
180
201
  → Ensure `package.json` has correct `build` script
@@ -190,4 +211,4 @@ dndev emu start
190
211
 
191
212
  ---
192
213
 
193
- **Import repo in Vercel → set env vars → `git push`. Vercel deploys automatically.**
214
+ **3 values in `.env.local` → `dndev deploy` done.**
@@ -13,7 +13,7 @@ import { Link, useNavigate, useParams } from 'react-router-dom'; // ❌ BREAKS F
13
13
 
14
14
  **✅ CORRECT:**
15
15
  ```tsx
16
- import { Link, useNavigate, useParams } from '@donotdev/ui/routing'; // ✅ Framework routing
16
+ import { Link, useNavigate, useParams } from '@donotdev/ui'; // ✅ Framework routing
17
17
  ```
18
18
 
19
19
  **Why?** The framework's routing components:
@@ -30,7 +30,7 @@ import { Link, useNavigate, useParams } from '@donotdev/ui/routing'; // ✅ Fram
30
30
  ### Components
31
31
 
32
32
  ```tsx
33
- import { Link, DnDevNavigationMenu } from '@donotdev/ui/routing';
33
+ import { Link, DnDevNavigationMenu } from '@donotdev/ui';
34
34
  ```
35
35
 
36
36
  **Link Component:**
@@ -55,7 +55,7 @@ import {
55
55
  useRouteParam,
56
56
  useSearchParams,
57
57
  useNavigationItems,
58
- } from '@donotdev/ui/routing';
58
+ } from '@donotdev/ui';
59
59
  ```
60
60
 
61
61
  ---
@@ -66,7 +66,7 @@ import {
66
66
 
67
67
  **✅ Use framework Link:**
68
68
  ```tsx
69
- import { Link } from '@donotdev/ui/routing';
69
+ import { Link } from '@donotdev/ui';
70
70
 
71
71
  function ProductCard({ product }) {
72
72
  return (
@@ -77,7 +77,7 @@ function ProductCard({ product }) {
77
77
 
78
78
  **✅ Use framework useNavigate:**
79
79
  ```tsx
80
- import { useNavigate } from '@donotdev/ui/routing';
80
+ import { useNavigate } from '@donotdev/ui';
81
81
 
82
82
  function ProductForm() {
83
83
  const navigate = useNavigate();
@@ -107,7 +107,7 @@ function ProductForm() {
107
107
 
108
108
  **✅ Use framework useRouteParam:**
109
109
  ```tsx
110
- import { useRouteParam } from '@donotdev/ui/routing';
110
+ import { useRouteParam } from '@donotdev/ui';
111
111
 
112
112
  function ProductPage() {
113
113
  const id = useRouteParam('id'); // ✅ Returns string | undefined
@@ -117,7 +117,7 @@ function ProductPage() {
117
117
 
118
118
  **✅ Or use framework useParams:**
119
119
  ```tsx
120
- import { useParams } from '@donotdev/ui/routing';
120
+ import { useParams } from '@donotdev/ui';
121
121
 
122
122
  function ProductPage() {
123
123
  const params = useParams();
@@ -136,7 +136,7 @@ import { useParams } from 'react-router-dom'; // ❌ Type issues, breaks framewo
136
136
 
137
137
  **✅ Use DnDevNavigationMenu (auto-fetches routes):**
138
138
  ```tsx
139
- import { DnDevNavigationMenu, DISPLAY } from '@donotdev/ui/routing';
139
+ import { DnDevNavigationMenu, DISPLAY } from '@donotdev/ui';
140
140
 
141
141
  function Sidebar() {
142
142
  return (
@@ -151,7 +151,7 @@ function Sidebar() {
151
151
 
152
152
  **✅ Or use useNavigationItems for custom sidebar:**
153
153
  ```tsx
154
- import { Link, useNavigationItems } from '@donotdev/ui/routing';
154
+ import { Link, useNavigationItems } from '@donotdev/ui';
155
155
 
156
156
  function CustomSidebar() {
157
157
  const menuItems = useNavigationItems(); // ✅ Auth-filtered routes
@@ -194,7 +194,7 @@ function Sidebar() {
194
194
 
195
195
  **✅ Use framework useNavigate:**
196
196
  ```tsx
197
- import { useNavigate } from '@donotdev/ui/routing';
197
+ import { useNavigate } from '@donotdev/ui';
198
198
 
199
199
  function LoginForm() {
200
200
  const navigate = useNavigate();
@@ -228,7 +228,7 @@ navigate('/products', {
228
228
 
229
229
  **✅ Use framework useSearchParams (read-only, returns URLSearchParams directly):**
230
230
  ```tsx
231
- import { useSearchParams } from '@donotdev/ui/routing';
231
+ import { useSearchParams } from '@donotdev/ui';
232
232
 
233
233
  function ProductList() {
234
234
  const searchParams = useSearchParams();
@@ -240,7 +240,7 @@ function ProductList() {
240
240
 
241
241
  **✅ Or use useQueryParams helper:**
242
242
  ```tsx
243
- import { useQueryParams } from '@donotdev/ui/routing';
243
+ import { useQueryParams } from '@donotdev/ui';
244
244
 
245
245
  function ProductList() {
246
246
  const { page, sort } = useQueryParams({ page: '1', sort: 'name' });
@@ -254,7 +254,7 @@ function ProductList() {
254
254
 
255
255
  **✅ Use framework useMatch:**
256
256
  ```tsx
257
- import { useMatch } from '@donotdev/ui/routing';
257
+ import { useMatch } from '@donotdev/ui';
258
258
 
259
259
  function NavigationItem({ path }) {
260
260
  const isActive = useMatch(path);
@@ -360,7 +360,7 @@ import { Link, useNavigate } from 'react-router-dom';
360
360
  **Fix:**
361
361
  ```tsx
362
362
  // ✅ CORRECT
363
- import { Link, useNavigate } from '@donotdev/ui/routing';
363
+ import { Link, useNavigate } from '@donotdev/ui';
364
364
  ```
365
365
 
366
366
  ---
@@ -416,7 +416,7 @@ function Sidebar() {
416
416
  **Fix:**
417
417
  ```tsx
418
418
  // ✅ CORRECT
419
- import { DnDevNavigationMenu } from '@donotdev/ui/routing';
419
+ import { DnDevNavigationMenu } from '@donotdev/ui';
420
420
 
421
421
  function Sidebar() {
422
422
  return <DnDevNavigationMenu vertical />; // Auto-fetches routes
@@ -437,7 +437,7 @@ import { Link } from 'react-router-dom';
437
437
  **Fix:**
438
438
  ```tsx
439
439
  // ✅ CORRECT
440
- import { Link } from '@donotdev/ui/routing';
440
+ import { Link } from '@donotdev/ui';
441
441
 
442
442
  <Link path="/products" label="Products" />
443
443
  ```
@@ -459,7 +459,7 @@ import {
459
459
  useSearchParams,
460
460
  useNavigationItems,
461
461
  DnDevNavigationMenu,
462
- } from '@donotdev/ui/routing';
462
+ } from '@donotdev/ui';
463
463
  ```
464
464
 
465
465
  ### Common Patterns
@@ -489,7 +489,7 @@ const menuItems = useNavigationItems(); // Auth-filtered routes
489
489
 
490
490
  ## Summary
491
491
 
492
- 1. **Always use `@donotdev/ui/routing`** - never `react-router-dom`
492
+ 1. **Always import from `@donotdev/ui`** never `react-router-dom`
493
493
  2. **Use `DnDevNavigationMenu`** for sidebars/headers
494
494
  3. **Use `useNavigationItems()`** for custom navigation
495
495
  4. **Don't use `<Outlet />` manually** - framework handles it
@@ -1,9 +1,10 @@
1
1
  /**
2
- * Reference: Framework essences (Brutalist, Luxury).
2
+ * Reference: Framework essences (Brutalist, Luxury, Retro).
3
3
  * Copy the blocks you need into your app's src/themes.css.
4
4
  * Default essence = SaaS (Inter); these do not apply until you set the class on <html>.
5
5
  *
6
- * Fonts: Space Grotesk (Brutalist), Playfair Display (Luxury), Inter, Roboto are bundled in @donotdev/ui (no external requests).
6
+ * Fonts: Space Grotesk (Brutalist), Playfair Display (Luxury), Press Start 2P (Retro),
7
+ * Inter, Roboto are bundled in @donotdev/ui (no external requests).
7
8
  */
8
9
 
9
10
  /** =========================================================================
@@ -172,3 +173,119 @@
172
173
  --shadow-md: 0 4px 12px var(--shadow-color);
173
174
  --shadow-xl: 0 8px 24px var(--shadow-color);
174
175
  }
176
+
177
+
178
+ /** =========================================================================
179
+ * Retro — 8-bit pixel aesthetic, Press Start 2P, neon on dark, CRT vibes.
180
+ * Set <html class="retro"> to apply.
181
+ * ========================================================================= */
182
+ .retro {
183
+ --theme-icon: 'Gamepad2';
184
+ --theme-label: 'Retro';
185
+ --theme-is-dark: 1;
186
+
187
+ /* 1. Core Colors - Muted neon on zinc */
188
+ --background: #1c1c22;
189
+ --foreground: #c8e6c9;
190
+ --primary: #5eead4;
191
+ --secondary: #c084fc;
192
+ --accent: #fbbf24;
193
+
194
+ /* 2. Semantic */
195
+ --success: #6ee7b7;
196
+ --warning: #fbbf24;
197
+ --destructive: #f87171;
198
+
199
+ /* 3. Surfaces - Zinc CRT glass */
200
+ --muted: #27272f;
201
+ --muted-foreground: #8bae8b;
202
+ --border: #4a6a4a;
203
+ --input: #1c1c22;
204
+ --ring: #5eead4;
205
+ --card: #222228;
206
+ --card-foreground: #c8e6c9;
207
+ --popover: #222228;
208
+ --popover-foreground: #c8e6c9;
209
+ --surface-1: #1e1e24;
210
+
211
+ /* 4. Text on Colors */
212
+ --primary-foreground: #0f172a;
213
+ --secondary-foreground: #0f172a;
214
+ --accent-foreground: #0f172a;
215
+ --success-foreground: #0f172a;
216
+ --warning-foreground: #0f172a;
217
+ --destructive-foreground: #ffffff;
218
+
219
+ /* 5. Radius - Hard pixel corners */
220
+ --radius-interactive: 0;
221
+ --radius-surface: 0;
222
+ --radius-floating: 0;
223
+
224
+ /* 6. Typography - Press Start 2P (pixel font, 400 only) */
225
+ --font-family: 'Press Start 2P', var(--font-mono);
226
+ --font-headline: 'Press Start 2P', var(--font-mono);
227
+ --font-weight-normal: 400;
228
+ --font-weight-medium: 400;
229
+ --font-weight-semibold: 400;
230
+ --font-weight-bold: 400;
231
+
232
+ /* 7. Font scale - smaller base (pixel font reads large) */
233
+ --font-size-xs: 0.5rem;
234
+ --font-size-sm: 0.625rem;
235
+ --font-size-base: 0.75rem;
236
+ --font-size-lg: 0.875rem;
237
+ --font-size-xl: 1rem;
238
+ --font-size-2xl: 1.25rem;
239
+ --font-size-3xl: 1.5rem;
240
+ --line-height: 1.6;
241
+
242
+ /* 8. Borders - Chunky pixel borders */
243
+ --border-width: 3px;
244
+ --border-huge: 4px;
245
+
246
+ /* 9. Shadows — soft neon glow */
247
+ --shadow-color: #5eead433;
248
+ --shadow-sm: 0 0 4px #5eead422;
249
+ --shadow-md: 0 0 8px #5eead433, 0 0 16px #5eead41a;
250
+ --shadow-xl: 0 0 12px #5eead444, 0 0 24px #5eead42a, 0 0 48px #c084fc1a;
251
+ --shadow-cta: 0 0 16px #5eead444, 0 0 32px #5eead422;
252
+
253
+ /* 10. Per-variant shadows — soft neon matching */
254
+ --shadow-primary: 0 0 8px #5eead42a;
255
+ --shadow-primary-xl: 0 0 16px #5eead444, 0 0 32px #5eead422;
256
+ --shadow-secondary: 0 0 8px #c084fc2a;
257
+ --shadow-secondary-xl: 0 0 16px #c084fc44, 0 0 32px #c084fc22;
258
+
259
+ /* 11. Header padding */
260
+ --header-shadow-padding: 0;
261
+ }
262
+
263
+ /* Body - subtle CRT scanlines */
264
+ .retro body {
265
+ background-color: var(--background);
266
+ background-image:
267
+ repeating-linear-gradient(
268
+ 0deg,
269
+ transparent,
270
+ transparent 2px,
271
+ rgba(0, 0, 0, 0.08) 2px,
272
+ rgba(0, 0, 0, 0.08) 4px
273
+ );
274
+ }
275
+
276
+ /* Uppercase headings (pixel fonts look best in caps) */
277
+ .retro {
278
+ :is(h1, h2, h3, h4, h5, h6),
279
+ [data-level^='h'] {
280
+ text-transform: uppercase;
281
+ }
282
+ }
283
+
284
+ /* Flat surfaces - no gradient, pixel-sharp */
285
+ .retro .dndev-surface { background: var(--card); }
286
+ .retro .dndev-surface[data-variant='outline'] { border: var(--border-width) solid var(--border); }
287
+
288
+ .retro .dndev-card[data-variant='outline'] {
289
+ background: transparent;
290
+ box-shadow: none;
291
+ }
@@ -3,7 +3,7 @@
3
3
  **Goal:** Deeply understand the app and document ALL requirements before any code.
4
4
 
5
5
  **MCP:** `start_phase(0)` to begin. `complete_phase()` when done.
6
- **Done when:** `spec_template.md` is COMPLETE and user has validated it.
6
+ **Done when:** `docs/HLD.md` is COMPLETE (using `guides/wai-way/spec_template.md` as template) and user has validated it.
7
7
 
8
8
  ---
9
9
 
@@ -37,6 +37,20 @@ Apply the chosen essence (SaaS, Luxury, Brutalist) to your `src/themes.css`.
37
37
 
38
38
  ---
39
39
 
40
+ ## Reference: Demo App
41
+
42
+ **Before creating pages, study the demo app:** `packages/cli/templates/app-demo/src/pages/`
43
+
44
+ It shows the canonical pattern:
45
+ - Thin page wrappers (~5 lines) that import templates
46
+ - `PageMeta.preset` for per-route layout switching (landing → admin → docs)
47
+ - Component showcase with filterable grid
48
+ - Entity definition with `defineEntity()`
49
+
50
+ **Copy from the demo app, customize for your spec.**
51
+
52
+ ---
53
+
40
54
  ## Step 3: Review Spec Pages
41
55
 
42
56
  From your spec, you have a list of pages. Now create them.
@@ -46,6 +46,12 @@ export const productEntity = defineEntity({
46
46
  });
47
47
  ```
48
48
 
49
+ > **Status field:** Auto-added with locked `type`, `visibility`, `editable`. Don't redefine those. To add custom options:
50
+ > ```typescript
51
+ > status: { validation: { options: [{ value: 'shipped', label: 'Shipped' }] } }
52
+ > // Merged result: [draft, available, deleted, shipped]
53
+ > ```
54
+
49
55
  ---
50
56
 
51
57
  ## Step 3: Export Entities
@@ -20,6 +20,20 @@
20
20
 
21
21
  ---
22
22
 
23
+ ## Reference: Demo App
24
+
25
+ **Before composing pages, study the demo app:** `packages/cli/templates/app-demo/src/pages/`
26
+
27
+ It shows the canonical pattern:
28
+ - Thin page wrappers (~5 lines) that import templates
29
+ - `PageMeta.preset` for per-route layout switching (landing → admin → docs)
30
+ - CRUD with `ProductCardListTemplate` + `defineEntity()`
31
+ - Component showcase with filterable grid
32
+
33
+ **Copy from the demo app, customize for your spec.**
34
+
35
+ ---
36
+
23
37
  ## Step 2: Read Page Patterns
24
38
 
25
39
  **READ:** `guides/wai-way/page_patterns.md` for all patterns:
@@ -309,12 +309,9 @@ export const orderEntity = defineEntity({
309
309
  visibility: 'owner',
310
310
  editable: 'never',
311
311
  },
312
+ // status is auto-added with type/visibility/editable locked.
313
+ // Only define validation.options — framework auto-adds [draft, available, deleted].
312
314
  status: {
313
- name: 'status',
314
- label: 'status',
315
- type: 'select',
316
- visibility: 'owner',
317
- editable: 'admin',
318
315
  validation: {
319
316
  options: [
320
317
  { value: 'pending', label: 'Pending' },
@@ -341,6 +338,8 @@ export const orderEntity = defineEntity({
341
338
  });
342
339
  ```
343
340
 
341
+ > **Merged status options:** `[draft, available, deleted, pending, paid, shipped, delivered, cancelled]`. The three defaults are always first and cannot be removed.
342
+
344
343
  ---
345
344
 
346
345
  ## Review
@@ -152,7 +152,7 @@ import { EntityFormRenderer, useCrud } from '@donotdev/crud';
152
152
  import { carEntity } from 'entities/car';
153
153
  import { useTranslation } from '@donotdev/core';
154
154
  import type { PageMeta } from '@donotdev/core';
155
- import { useParams } from '@donotdev/ui/routing';
155
+ import { useParams } from '@donotdev/ui';
156
156
 
157
157
  export const NAMESPACE = 'car';
158
158
 
@@ -523,7 +523,7 @@ import { Section, Card, Grid, Stack, Text, Button, Badge } from '@donotdev/compo
523
523
  import { useCrud } from '@donotdev/crud';
524
524
  import { productEntity } from 'entities/product';
525
525
  import type { PageMeta } from '@donotdev/core';
526
- import { useParams } from '@donotdev/ui/routing';
526
+ import { useParams } from '@donotdev/ui';
527
527
 
528
528
  export const NAMESPACE = 'product-detail';
529
529