@donotdev/cli 0.0.18 → 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 (131) hide show
  1. package/dependencies-matrix.json +55 -156
  2. package/dist/bin/commands/coach.js +8177 -0
  3. package/dist/bin/commands/create-app.js +5 -5
  4. package/dist/bin/commands/create-project.js +10 -7
  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 -185
  16. package/dist/bin/donotdev.js +913 -185
  17. package/dist/index.js +96 -65
  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/AI.md.example +4 -3
  51. package/templates/root-consumer/guides/dndev/AGENT_START_HERE.md.example +21 -6
  52. package/templates/root-consumer/guides/dndev/COMPONENTS_ADV.md.example +16 -179
  53. package/templates/root-consumer/guides/dndev/ENV_SETUP.md.example +19 -21
  54. package/templates/root-consumer/guides/dndev/GOTCHAS.md.example +14 -3
  55. package/templates/root-consumer/guides/dndev/INDEX.md.example +2 -2
  56. package/templates/root-consumer/guides/dndev/SETUP_APP_CONFIG.md.example +3 -3
  57. package/templates/root-consumer/guides/dndev/SETUP_BLOG.md.example +19 -2
  58. package/templates/root-consumer/guides/dndev/SETUP_CRUD.md.example +35 -1
  59. package/templates/root-consumer/guides/dndev/SETUP_FIREBASE.md.example +17 -12
  60. package/templates/root-consumer/guides/dndev/SETUP_LAYOUTS.md.example +32 -0
  61. package/templates/root-consumer/guides/dndev/SETUP_OAUTH_PROVIDERS.md.example +1 -1
  62. package/templates/root-consumer/guides/dndev/SETUP_PAGES.md.example +19 -15
  63. package/templates/root-consumer/guides/dndev/SETUP_STRIPE.md.example +2 -2
  64. package/templates/root-consumer/guides/dndev/SETUP_SUPABASE.md.example +17 -12
  65. package/templates/root-consumer/guides/dndev/SETUP_VERCEL.md.example +37 -16
  66. package/templates/root-consumer/guides/dndev/USE_ROUTING.md.example +18 -18
  67. package/templates/root-consumer/guides/dndev/essences_reference.css.example +119 -2
  68. package/templates/root-consumer/guides/wai-way/blueprints/1_scaffold.md.example +14 -0
  69. package/templates/root-consumer/guides/wai-way/blueprints/2_entities.md.example +6 -0
  70. package/templates/root-consumer/guides/wai-way/blueprints/3_compose.md.example +14 -0
  71. package/templates/root-consumer/guides/wai-way/entity_patterns.md.example +4 -5
  72. package/templates/root-consumer/guides/wai-way/page_patterns.md.example +2 -2
  73. package/dist/bin/commands/agent-setup.d.ts +0 -6
  74. package/dist/bin/commands/agent-setup.d.ts.map +0 -1
  75. package/dist/bin/commands/agent-setup.js.map +0 -1
  76. package/dist/bin/commands/build.d.ts +0 -11
  77. package/dist/bin/commands/build.d.ts.map +0 -1
  78. package/dist/bin/commands/build.js.map +0 -1
  79. package/dist/bin/commands/bump.d.ts +0 -11
  80. package/dist/bin/commands/bump.d.ts.map +0 -1
  81. package/dist/bin/commands/bump.js.map +0 -1
  82. package/dist/bin/commands/cacheout.d.ts +0 -11
  83. package/dist/bin/commands/cacheout.d.ts.map +0 -1
  84. package/dist/bin/commands/cacheout.js.map +0 -1
  85. package/dist/bin/commands/create-app.d.ts +0 -11
  86. package/dist/bin/commands/create-app.d.ts.map +0 -1
  87. package/dist/bin/commands/create-app.js.map +0 -1
  88. package/dist/bin/commands/create-project.d.ts +0 -11
  89. package/dist/bin/commands/create-project.d.ts.map +0 -1
  90. package/dist/bin/commands/create-project.js.map +0 -1
  91. package/dist/bin/commands/deploy.d.ts +0 -11
  92. package/dist/bin/commands/deploy.d.ts.map +0 -1
  93. package/dist/bin/commands/deploy.js.map +0 -1
  94. package/dist/bin/commands/dev.d.ts +0 -11
  95. package/dist/bin/commands/dev.d.ts.map +0 -1
  96. package/dist/bin/commands/dev.js.map +0 -1
  97. package/dist/bin/commands/doctor.d.ts +0 -6
  98. package/dist/bin/commands/doctor.d.ts.map +0 -1
  99. package/dist/bin/commands/doctor.js.map +0 -1
  100. package/dist/bin/commands/emu.d.ts +0 -11
  101. package/dist/bin/commands/emu.d.ts.map +0 -1
  102. package/dist/bin/commands/emu.js.map +0 -1
  103. package/dist/bin/commands/format.d.ts +0 -11
  104. package/dist/bin/commands/format.d.ts.map +0 -1
  105. package/dist/bin/commands/format.js.map +0 -1
  106. package/dist/bin/commands/make-admin.d.ts +0 -11
  107. package/dist/bin/commands/make-admin.d.ts.map +0 -1
  108. package/dist/bin/commands/make-admin.js.map +0 -1
  109. package/dist/bin/commands/preview.d.ts +0 -11
  110. package/dist/bin/commands/preview.d.ts.map +0 -1
  111. package/dist/bin/commands/preview.js.map +0 -1
  112. package/dist/bin/commands/setup.d.ts +0 -6
  113. package/dist/bin/commands/setup.d.ts.map +0 -1
  114. package/dist/bin/commands/setup.js.map +0 -1
  115. package/dist/bin/commands/sync-secrets.d.ts +0 -11
  116. package/dist/bin/commands/sync-secrets.d.ts.map +0 -1
  117. package/dist/bin/commands/sync-secrets.js.map +0 -1
  118. package/dist/bin/commands/type-check.d.ts +0 -14
  119. package/dist/bin/commands/type-check.d.ts.map +0 -1
  120. package/dist/bin/commands/type-check.js.map +0 -1
  121. package/dist/bin/commands/wai.d.ts +0 -11
  122. package/dist/bin/commands/wai.d.ts.map +0 -1
  123. package/dist/bin/commands/wai.js.map +0 -1
  124. package/dist/index.d.ts +0 -8
  125. package/dist/index.d.ts.map +0 -1
  126. package/dist/index.js.map +0 -1
  127. package/templates/app-demo/src/components/ThemeToggle.tsx.example +0 -48
  128. package/templates/app-demo/src/pages/DetailPage.tsx.example +0 -103
  129. package/templates/app-demo/src/pages/FullPage.tsx.example +0 -142
  130. package/templates/app-demo/src/pages/components/DemoLayout.tsx.example +0 -266
  131. package/templates/app-demo/src/pages/components/LayoutRoute.tsx.example +0 -20
@@ -36,6 +36,38 @@ All presets automatically include these components when applicable:
36
36
 
37
37
  ---
38
38
 
39
+ ## Per-Route Layout Switching
40
+
41
+ **Override the app preset on a per-page basis via `PageMeta.preset`:**
42
+
43
+ ```tsx
44
+ // src/pages/DashboardPage.tsx
45
+ import type { PageMeta } from '@donotdev/core';
46
+
47
+ export const meta: PageMeta = {
48
+ preset: 'admin', // This route uses admin layout (sidebar, compact density)
49
+ auth: true,
50
+ };
51
+ ```
52
+
53
+ - If `preset` is set → that route uses the specified layout
54
+ - If `preset` is absent → the app's `appConfig.preset` is used
55
+ - The override is **transient** — navigating away restores the next route's preset or the app default
56
+ - No localStorage pollution — route presets are not persisted
57
+
58
+ **Common pattern (SaaS app):**
59
+ | Route | Preset | Purpose |
60
+ |-------|--------|---------|
61
+ | `/` | (app default: `landing`) | Marketing landing page |
62
+ | `/pricing` | (app default: `landing`) | Pricing page |
63
+ | `/dashboard` | `admin` | Dashboard with sidebar |
64
+ | `/products` | `admin` | CRUD with sidebar |
65
+ | `/changelog` | `docs` | Documentation layout |
66
+
67
+ **Reference implementation:** See `packages/cli/templates/app-demo/` for a working example of per-route switching.
68
+
69
+ ---
70
+
39
71
  ## Advanced: Slot Overrides
40
72
 
41
73
  **Customize zones:**
@@ -1,7 +1,7 @@
1
1
  # OAuth Provider Setup Guide
2
2
 
3
3
  Each OAuth provider requires manual registration in their developer console.
4
- `dndev setup oauth` computes the correct redirect URI for you.
4
+ `dndev coach` shows the correct redirect URI and setup steps for each provider.
5
5
 
6
6
  ## Redirect URIs
7
7
 
@@ -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
@@ -141,17 +146,15 @@ import { Link } from '@donotdev/ui';
141
146
  **Always import from `@donotdev/<package>` top-level.** Never use sub-paths.
142
147
 
143
148
  ```tsx
144
- // CORRECT
145
149
  import { PageContainer, Link, useNavigate } from '@donotdev/ui';
146
150
  import { Card, Button, Input } from '@donotdev/components';
147
151
  import { useCrud } from '@donotdev/crud';
148
-
149
- // WRONG — sub-paths do not exist
150
- import { Link } from '@donotdev/ui/routing';
151
- import { Card } from '@donotdev/components/card';
152
152
  ```
153
153
 
154
- **Exceptions** (server/config only): `@donotdev/core/server`, `@donotdev/core/vite`, `@donotdev/core/next`, `@donotdev/core/functions`.
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`
155
158
 
156
159
  ---
157
160
 
@@ -172,8 +175,7 @@ src/pages/
172
175
 
173
176
  ```tsx
174
177
  // src/pages/HomePage.tsx — SaaS pattern
175
- import { useAuth } from '@donotdev/auth';
176
- import { useNavigate, PageContainer } from '@donotdev/ui';
178
+ import { useAuthSafe, useNavigate, PageContainer } from '@donotdev/ui';
177
179
  import { LoginForm } from '@donotdev/templates';
178
180
 
179
181
  export const meta: PageMeta = {
@@ -182,7 +184,7 @@ export const meta: PageMeta = {
182
184
  };
183
185
 
184
186
  export default function HomePage() {
185
- const { user } = useAuth();
187
+ const user = useAuthSafe('user');
186
188
  const navigate = useNavigate();
187
189
 
188
190
  // Redirect authenticated users to dashboard
@@ -196,6 +198,8 @@ export default function HomePage() {
196
198
  }
197
199
  ```
198
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
+
199
203
  ---
200
204
 
201
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
+ }
@@ -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