@donotdev/cli 0.0.18 → 0.0.20

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 (150) hide show
  1. package/dependencies-matrix.json +42 -55
  2. package/dist/bin/commands/bump.js +5 -2
  3. package/dist/bin/commands/coach.js +8177 -0
  4. package/dist/bin/commands/create-app.js +6 -6
  5. package/dist/bin/commands/create-project.js +23 -9
  6. package/dist/bin/commands/deploy.js +99 -59
  7. package/dist/bin/commands/doctor.js +243 -698
  8. package/dist/bin/commands/emu.js +2 -2
  9. package/dist/bin/commands/format.js +4 -1
  10. package/dist/bin/commands/get-demo.js +8351 -0
  11. package/dist/bin/commands/make-admin.js +773 -152
  12. package/dist/bin/commands/setup.js +524 -1713
  13. package/dist/bin/commands/staging.js +17870 -0
  14. package/dist/bin/commands/sync-secrets.js +2 -11
  15. package/dist/bin/commands/type-check.js +7738 -1712
  16. package/dist/bin/dndev.js +868 -199
  17. package/dist/bin/donotdev.js +868 -199
  18. package/dist/index.js +127 -67
  19. package/package.json +1 -1
  20. package/templates/app-demo/index.html.example +147 -10
  21. package/templates/app-demo/public/apple-touch-icon.png.example +0 -0
  22. package/templates/app-demo/public/favicon.svg.example +1 -0
  23. package/templates/app-demo/public/icon-192x192.png.example +0 -0
  24. package/templates/app-demo/public/icon-512x512.png.example +0 -0
  25. package/templates/app-demo/src/App.tsx.example +7 -11
  26. package/templates/app-demo/src/config/app.ts.example +13 -48
  27. package/templates/app-demo/src/entities/booking.ts.example +75 -0
  28. package/templates/app-demo/src/entities/onboarding.ts.example +160 -0
  29. package/templates/app-demo/src/entities/product.ts.example +50 -0
  30. package/templates/app-demo/src/entities/quote.ts.example +70 -0
  31. package/templates/app-demo/src/globals.css.example +5 -1
  32. package/templates/app-demo/src/main.tsx.example +13 -7
  33. package/templates/app-demo/src/pages/ChangelogPage.tsx.example +41 -0
  34. package/templates/app-demo/src/pages/ConditionalFormPage.tsx.example +88 -0
  35. package/templates/app-demo/src/pages/DashboardPage.tsx.example +17 -0
  36. package/templates/app-demo/src/pages/HomePage.tsx.example +339 -60
  37. package/templates/app-demo/src/pages/OnboardingPage.tsx.example +47 -0
  38. package/templates/app-demo/src/pages/PricingPage.tsx.example +41 -0
  39. package/templates/app-demo/src/pages/ProductsPage.tsx.example +19 -0
  40. package/templates/app-demo/src/pages/ProfilePage.tsx.example +18 -0
  41. package/templates/app-demo/src/pages/SettingsPage.tsx.example +17 -0
  42. package/templates/app-demo/src/pages/ShowcaseDetailPage.tsx.example +118 -0
  43. package/templates/app-demo/src/pages/ShowcasePage.tsx.example +93 -0
  44. package/templates/app-demo/src/pages/components/ComponentRenderer.tsx.example +147 -51
  45. package/templates/app-demo/src/pages/components/ComponentsData.tsx.example +103 -21
  46. package/templates/app-demo/src/pages/components/componentConfig.ts.example +139 -59
  47. package/templates/app-demo/src/pages/legal/LegalPage.tsx.example +25 -0
  48. package/templates/app-demo/src/pages/legal/PrivacyPage.tsx.example +23 -0
  49. package/templates/app-demo/src/pages/legal/TermsPage.tsx.example +23 -0
  50. package/templates/app-demo/src/themes.css.example +289 -77
  51. package/templates/app-demo/stats.html.example +4949 -0
  52. package/templates/app-demo/tsconfig.json.example +1 -1
  53. package/templates/app-demo/vite.config.ts.example +23 -48
  54. package/templates/app-expo/README.md.example +1 -1
  55. package/templates/app-expo/app/index.tsx.example +1 -1
  56. package/templates/app-next/src/locales/home_en.json.example +6 -6
  57. package/templates/app-vite/src/locales/home_en.json.example +6 -6
  58. package/templates/app-vite/src/pages/HomePage.tsx.example +8 -10
  59. package/templates/overlay-firebase/env.fragment.example +1 -1
  60. package/templates/overlay-firebase/env.fragment.expo.example +1 -1
  61. package/templates/overlay-firebase/env.fragment.nextjs.example +1 -1
  62. package/templates/overlay-supabase/env.fragment.example +1 -1
  63. package/templates/overlay-supabase/env.fragment.expo.example +1 -1
  64. package/templates/overlay-supabase/env.fragment.nextjs.example +1 -1
  65. package/templates/overlay-vercel/env.fragment.example +1 -1
  66. package/templates/overlay-vercel/env.fragment.nextjs.example +1 -1
  67. package/templates/root-consumer/AI.md.example +4 -3
  68. package/templates/root-consumer/guides/dndev/AGENT_START_HERE.md.example +21 -6
  69. package/templates/root-consumer/guides/dndev/COMPONENTS_ADV.md.example +16 -179
  70. package/templates/root-consumer/guides/dndev/ENV_SETUP.md.example +19 -21
  71. package/templates/root-consumer/guides/dndev/GOTCHAS.md.example +14 -3
  72. package/templates/root-consumer/guides/dndev/INDEX.md.example +2 -2
  73. package/templates/root-consumer/guides/dndev/SETUP_APP_CONFIG.md.example +3 -3
  74. package/templates/root-consumer/guides/dndev/SETUP_BLOG.md.example +19 -2
  75. package/templates/root-consumer/guides/dndev/SETUP_CRUD.md.example +35 -1
  76. package/templates/root-consumer/guides/dndev/SETUP_FIREBASE.md.example +17 -12
  77. package/templates/root-consumer/guides/dndev/SETUP_LAYOUTS.md.example +32 -0
  78. package/templates/root-consumer/guides/dndev/SETUP_OAUTH_PROVIDERS.md.example +1 -1
  79. package/templates/root-consumer/guides/dndev/SETUP_PAGES.md.example +19 -15
  80. package/templates/root-consumer/guides/dndev/SETUP_STRIPE.md.example +2 -2
  81. package/templates/root-consumer/guides/dndev/SETUP_SUPABASE.md.example +17 -12
  82. package/templates/root-consumer/guides/dndev/SETUP_VERCEL.md.example +37 -16
  83. package/templates/root-consumer/guides/dndev/USE_ROUTING.md.example +18 -18
  84. package/templates/root-consumer/guides/dndev/advanced/COOKIE_REFERENCE.md.example +252 -252
  85. package/templates/root-consumer/guides/dndev/advanced/VERSION_CONTROL.md.example +174 -174
  86. package/templates/root-consumer/guides/dndev/essences_reference.css.example +119 -2
  87. package/templates/root-consumer/guides/wai-way/blueprints/1_scaffold.md.example +14 -0
  88. package/templates/root-consumer/guides/wai-way/blueprints/2_entities.md.example +6 -0
  89. package/templates/root-consumer/guides/wai-way/blueprints/3_compose.md.example +14 -0
  90. package/templates/root-consumer/guides/wai-way/entity_patterns.md.example +4 -5
  91. package/templates/root-consumer/guides/wai-way/page_patterns.md.example +2 -2
  92. package/dist/bin/commands/agent-setup.d.ts +0 -6
  93. package/dist/bin/commands/agent-setup.d.ts.map +0 -1
  94. package/dist/bin/commands/agent-setup.js.map +0 -1
  95. package/dist/bin/commands/build.d.ts +0 -11
  96. package/dist/bin/commands/build.d.ts.map +0 -1
  97. package/dist/bin/commands/build.js.map +0 -1
  98. package/dist/bin/commands/bump.d.ts +0 -11
  99. package/dist/bin/commands/bump.d.ts.map +0 -1
  100. package/dist/bin/commands/bump.js.map +0 -1
  101. package/dist/bin/commands/cacheout.d.ts +0 -11
  102. package/dist/bin/commands/cacheout.d.ts.map +0 -1
  103. package/dist/bin/commands/cacheout.js.map +0 -1
  104. package/dist/bin/commands/create-app.d.ts +0 -11
  105. package/dist/bin/commands/create-app.d.ts.map +0 -1
  106. package/dist/bin/commands/create-app.js.map +0 -1
  107. package/dist/bin/commands/create-project.d.ts +0 -11
  108. package/dist/bin/commands/create-project.d.ts.map +0 -1
  109. package/dist/bin/commands/create-project.js.map +0 -1
  110. package/dist/bin/commands/deploy.d.ts +0 -11
  111. package/dist/bin/commands/deploy.d.ts.map +0 -1
  112. package/dist/bin/commands/deploy.js.map +0 -1
  113. package/dist/bin/commands/dev.d.ts +0 -11
  114. package/dist/bin/commands/dev.d.ts.map +0 -1
  115. package/dist/bin/commands/dev.js.map +0 -1
  116. package/dist/bin/commands/doctor.d.ts +0 -6
  117. package/dist/bin/commands/doctor.d.ts.map +0 -1
  118. package/dist/bin/commands/doctor.js.map +0 -1
  119. package/dist/bin/commands/emu.d.ts +0 -11
  120. package/dist/bin/commands/emu.d.ts.map +0 -1
  121. package/dist/bin/commands/emu.js.map +0 -1
  122. package/dist/bin/commands/format.d.ts +0 -11
  123. package/dist/bin/commands/format.d.ts.map +0 -1
  124. package/dist/bin/commands/format.js.map +0 -1
  125. package/dist/bin/commands/make-admin.d.ts +0 -11
  126. package/dist/bin/commands/make-admin.d.ts.map +0 -1
  127. package/dist/bin/commands/make-admin.js.map +0 -1
  128. package/dist/bin/commands/preview.d.ts +0 -11
  129. package/dist/bin/commands/preview.d.ts.map +0 -1
  130. package/dist/bin/commands/preview.js.map +0 -1
  131. package/dist/bin/commands/setup.d.ts +0 -6
  132. package/dist/bin/commands/setup.d.ts.map +0 -1
  133. package/dist/bin/commands/setup.js.map +0 -1
  134. package/dist/bin/commands/sync-secrets.d.ts +0 -11
  135. package/dist/bin/commands/sync-secrets.d.ts.map +0 -1
  136. package/dist/bin/commands/sync-secrets.js.map +0 -1
  137. package/dist/bin/commands/type-check.d.ts +0 -14
  138. package/dist/bin/commands/type-check.d.ts.map +0 -1
  139. package/dist/bin/commands/type-check.js.map +0 -1
  140. package/dist/bin/commands/wai.d.ts +0 -11
  141. package/dist/bin/commands/wai.d.ts.map +0 -1
  142. package/dist/bin/commands/wai.js.map +0 -1
  143. package/dist/index.d.ts +0 -8
  144. package/dist/index.d.ts.map +0 -1
  145. package/dist/index.js.map +0 -1
  146. package/templates/app-demo/src/components/ThemeToggle.tsx.example +0 -48
  147. package/templates/app-demo/src/pages/DetailPage.tsx.example +0 -103
  148. package/templates/app-demo/src/pages/FullPage.tsx.example +0 -142
  149. package/templates/app-demo/src/pages/components/DemoLayout.tsx.example +0 -266
  150. package/templates/app-demo/src/pages/components/LayoutRoute.tsx.example +0 -20
@@ -18,7 +18,7 @@ import { getFirestore } from '@donotdev/firebase';
18
18
  import { handleError } from '@donotdev/core';
19
19
  ```
20
20
 
21
- **Rule:** Always use `/server` suffix for `@donotdev/firebase/server`, `@donotdev/core/server`, `@donotdev/utils/server`.
21
+ **Rule:** Always use `/server` suffix for `@donotdev/core/server`, `@donotdev/firebase/server`, `@donotdev/security/server`.
22
22
 
23
23
  **ESM only — never use `require()`.**
24
24
 
@@ -49,7 +49,7 @@ One line for values, one line for types. Blank line between categories.
49
49
  import { Link, useNavigate, useParams } from 'react-router-dom';
50
50
 
51
51
  // ✅ CORRECT
52
- import { Link, useNavigate, useParams } from '@donotdev/ui/routing';
52
+ import { Link, useNavigate, useParams } from '@donotdev/ui';
53
53
  ```
54
54
 
55
55
  **Routes are auto-discovered** from `src/pages/*Page.tsx` with `pageMeta`. Don't use `<Routes>`, `<Route>`, or manual `<Outlet />`.
@@ -106,7 +106,18 @@ Common wrong props:
106
106
  ## CRUD [Phase 2, 3]
107
107
 
108
108
  **Hidden fields are auto-added by `defineEntity()` — don't define them manually:**
109
- - `id`, `createdAt`, `updatedAt`, `createdById`, `updatedById`, `status`
109
+ - `id`, `createdAt`, `updatedAt`, `createdById`, `updatedById`
110
+
111
+ **Status field — extend, don't redefine.**
112
+ The `status` field is auto-added with locked `visibility: 'admin'`, `editable: 'admin'`, `type: 'select'`. Only `validation.options` can be extended.
113
+
114
+ ```typescript
115
+ // ❌ WRONG - these properties are silently ignored
116
+ status: { type: 'select', visibility: 'owner', editable: 'admin', validation: { options: [...] } }
117
+
118
+ // ✅ CORRECT - only extend options (merged after defaults: draft, available, deleted)
119
+ status: { validation: { options: [{ value: 'shipped', label: 'Shipped' }] } }
120
+ ```
110
121
 
111
122
  **Scope field is auto-added** when `scope` is configured. Don't manually define the scope field (e.g., `companyId`).
112
123
 
@@ -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 setup firebase`)
15
- - [SETUP_SUPABASE.md](./SETUP_SUPABASE.md) - Supabase project setup (`dndev setup supabase`, `dndev generate sql`)
14
+ - [SETUP_FIREBASE.md](./SETUP_FIREBASE.md) - Firebase project setup (`dndev coach` `dndev setup`)
15
+ - [SETUP_SUPABASE.md](./SETUP_SUPABASE.md) - Supabase project setup (`dndev coach` `dndev setup`)
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 setup firebase` to auto-populate Firebase config. See [SETUP_FIREBASE.md](./SETUP_FIREBASE.md).
112
+ Run `dndev coach` to see what to configure, then `dndev setup` to validate and automate. 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 setup firebase
119
- VITE_FIREBASE_PROJECT_ID=... # Written by dndev setup firebase
118
+ VITE_FIREBASE_API_KEY=... # Written by dndev setup
119
+ VITE_FIREBASE_PROJECT_ID=... # Written by dndev setup
120
120
  VITE_AUTH_PARTNERS=github,google
121
121
  VITE_STRIPE_PUBLISHABLE_KEY=pk_test_...
122
122
 
@@ -212,14 +212,31 @@ const filtered = blog.getPostsByTag('react'); // Posts tagged 'react'
212
212
 
213
213
  ## RSS & Sitemap
214
214
 
215
- **Auto-generated at build time.** The SEO pipeline (Vite `SEOPlugin` / Next.js `SEOHandler`) automatically:
215
+ **Fully automatic zero configuration.** The framework handles everything:
216
+
217
+ ### Build-time generation
218
+
219
+ The SEO pipeline (Vite `SEOPlugin` / Next.js `SEOHandler`) automatically:
216
220
 
217
221
  1. Discovers `src/content/blog/*_en.md` files
218
222
  2. Appends blog post URLs to `sitemap.xml`
219
- 3. Generates `rss.xml` with all posts
223
+ 3. Generates `rss.xml` (RSS 2.0 with Atom self-link) with all posts
220
224
 
221
225
  No manual scripts needed. Just drop `.md` files and build.
222
226
 
227
+ ### RSS auto-discovery
228
+
229
+ A `<link rel="alternate" type="application/rss+xml">` tag is automatically injected in the `<head>` by `AutoMetaTags`. This lets browsers and feed readers detect the feed without users needing to know the URL.
230
+
231
+ **Requires:** `VITE_APP_URL` (or `NEXT_PUBLIC_APP_URL`) set in `.env` — the RSS link uses the base URL to construct `https://yourdomain.com/rss.xml`.
232
+
233
+ ### RSS feed contents
234
+
235
+ Each blog post entry includes:
236
+ - `<title>`, `<description>`, `<link>`, `<guid>`, `<pubDate>`
237
+ - `<category>` (from frontmatter `tags`)
238
+ - `<enclosure>` (from frontmatter `image`, if set)
239
+
223
240
  ---
224
241
 
225
242
  ## Scaling (50+ Posts)
@@ -28,6 +28,40 @@ export const productEntity = defineEntity({
28
28
 
29
29
  See `lookup_symbol("defineEntity")` for all options (scope, access, ownership, uniqueKeys, validation).
30
30
 
31
+ ### Status Field (auto-added)
32
+
33
+ The `status` field is auto-added by `defineEntity()` with **locked** properties:
34
+
35
+ | Property | Locked Value | Can Override? |
36
+ |----------|-------------|---------------|
37
+ | `type` | `'select'` | No |
38
+ | `visibility` | `'admin'` | No |
39
+ | `editable` | `'admin'` | No |
40
+ | `required` | `true` | No |
41
+
42
+ **Default options:** `draft`, `available`, `deleted` — always present, cannot be removed.
43
+ **Default value:** `available`.
44
+
45
+ To add custom options, define **only** `validation.options` — they merge after defaults:
46
+
47
+ ```typescript
48
+ fields: {
49
+ status: {
50
+ validation: {
51
+ options: [
52
+ { value: 'shipped', label: 'Shipped' },
53
+ { value: 'returned', label: 'Returned' },
54
+ ],
55
+ },
56
+ },
57
+ // Result: [draft, available, deleted, shipped, returned]
58
+ }
59
+ ```
60
+
61
+ **Do NOT** set `type`, `visibility`, or `editable` on `status` — they are silently ignored.
62
+
63
+ > `draft` and `deleted` items are hidden from non-admin users (server-side filtering).
64
+
31
65
  ---
32
66
 
33
67
  ## 2. Provider Setup (once)
@@ -111,7 +145,7 @@ access: { create: 'admin', read: 'guest', update: 'admin', delete: 'admin' }
111
145
  For marketplace patterns. See `lookup_symbol("defineEntity")` → `ownership`.
112
146
 
113
147
  **Firebase:** Enforced by generated secure Firebase Functions (server-side).
114
- **Supabase:** Enforced via RLS policies — generated by `dndev setup supabase`.
148
+ **Supabase:** Enforced via RLS policies — generated by `dndev setup`.
115
149
 
116
150
  ---
117
151
 
@@ -4,19 +4,24 @@
4
4
 
5
5
  ---
6
6
 
7
- ## Step 1: Run Firebase Setup
7
+ ## Step 1: Run Coach + Fill .env
8
8
 
9
9
  ```bash
10
- dndev setup firebase
10
+ dndev coach
11
11
  ```
12
12
 
13
- This command:
14
- - Checks Firebase CLI is installed and you're logged in
15
- - Lists your Firebase projects (or creates a new one)
16
- - Creates a web app if the project doesn't have one
17
- - Gets the SDK config and writes it to your app's `.env`
18
- - Updates `.firebaserc` with the project ID
19
- - Updates `firebase.json` placeholders
13
+ This prints a numbered checklist of what to configure. For Firebase, you'll need:
14
+ - **SDK config** (API key, project ID, auth domain, etc.) → paste into your app's `.env`
15
+ - **Service account key** download and save as `service-account-key.json`
16
+ - **Enable services** (Auth, Firestore, Storage) in Firebase Console
17
+
18
+ Then run setup to validate and automate:
19
+
20
+ ```bash
21
+ dndev setup
22
+ ```
23
+
24
+ Setup validates .env values, checks Firebase CLI, selects/creates a web app, updates `.firebaserc` and `firebase.json`.
20
25
 
21
26
  **After running, it will prompt you for 2 manual steps (below).**
22
27
 
@@ -154,7 +159,7 @@ If you deploy manually with `firebase deploy`, you'll see `403 Forbidden` on COR
154
159
  | `functions/.env` | Server secrets: STRIPE_SECRET_KEY, OAuth secrets | Cloud Functions runtime |
155
160
  | Root `.env` | **Not read by Vite.** Reference only. | Nothing |
156
161
 
157
- **`dndev setup firebase` writes Firebase vars to `apps/<app>/.env` automatically.**
162
+ **`dndev setup` writes Firebase vars to the app's `.env` automatically.**
158
163
 
159
164
  **Custom domains:** Framework uses `APP_URL` hostname as `authDomain` in production (not Firebase's `projectId.firebaseapp.com`). Set your `FIREBASE_AUTH_DOMAIN` env var (with the appropriate `VITE_` or `NEXT_PUBLIC_` prefix) in `.env.local` and `.env.production` — framework handles the rest.
160
165
 
@@ -163,7 +168,7 @@ If you deploy manually with `firebase deploy`, you'll see `403 Forbidden` on COR
163
168
  ## Staging Environment (Optional)
164
169
 
165
170
  1. Create a second Firebase project (e.g., `my-app-staging`)
166
- 2. Run `dndev setup firebase` again and select the staging project
171
+ 2. Run `dndev setup firebase` to configure the staging project
167
172
  3. The wizard updates `.firebaserc` — add a `"staging"` alias manually if the wizard only sets `"default"`:
168
173
  ```json
169
174
  { "projects": { "default": "my-app-prod", "staging": "my-app-staging" } }
@@ -223,4 +228,4 @@ See [ENV_SETUP.md → Secrets Philosophy](./ENV_SETUP.md#secrets-philosophy) for
223
228
 
224
229
  ---
225
230
 
226
- **`dndev setup firebase` → download service account key → enable Auth + Firestore → `dndev emu start` → `dndev deploy`. That's it.**
231
+ **`dndev coach` → fill .env → `dndev setup` → download service account key → enable Auth + Firestore → `dndev emu start` → `dndev deploy`. That's it.**
@@ -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.**