@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.
- package/dependencies-matrix.json +42 -55
- package/dist/bin/commands/bump.js +5 -2
- package/dist/bin/commands/coach.js +8177 -0
- package/dist/bin/commands/create-app.js +6 -6
- package/dist/bin/commands/create-project.js +23 -9
- package/dist/bin/commands/deploy.js +99 -59
- package/dist/bin/commands/doctor.js +243 -698
- package/dist/bin/commands/emu.js +2 -2
- package/dist/bin/commands/format.js +4 -1
- package/dist/bin/commands/get-demo.js +8351 -0
- package/dist/bin/commands/make-admin.js +773 -152
- package/dist/bin/commands/setup.js +524 -1713
- package/dist/bin/commands/staging.js +17870 -0
- package/dist/bin/commands/sync-secrets.js +2 -11
- package/dist/bin/commands/type-check.js +7738 -1712
- package/dist/bin/dndev.js +868 -199
- package/dist/bin/donotdev.js +868 -199
- package/dist/index.js +127 -67
- package/package.json +1 -1
- package/templates/app-demo/index.html.example +147 -10
- package/templates/app-demo/public/apple-touch-icon.png.example +0 -0
- package/templates/app-demo/public/favicon.svg.example +1 -0
- package/templates/app-demo/public/icon-192x192.png.example +0 -0
- package/templates/app-demo/public/icon-512x512.png.example +0 -0
- package/templates/app-demo/src/App.tsx.example +7 -11
- package/templates/app-demo/src/config/app.ts.example +13 -48
- package/templates/app-demo/src/entities/booking.ts.example +75 -0
- package/templates/app-demo/src/entities/onboarding.ts.example +160 -0
- package/templates/app-demo/src/entities/product.ts.example +50 -0
- package/templates/app-demo/src/entities/quote.ts.example +70 -0
- package/templates/app-demo/src/globals.css.example +5 -1
- package/templates/app-demo/src/main.tsx.example +13 -7
- package/templates/app-demo/src/pages/ChangelogPage.tsx.example +41 -0
- package/templates/app-demo/src/pages/ConditionalFormPage.tsx.example +88 -0
- package/templates/app-demo/src/pages/DashboardPage.tsx.example +17 -0
- package/templates/app-demo/src/pages/HomePage.tsx.example +339 -60
- package/templates/app-demo/src/pages/OnboardingPage.tsx.example +47 -0
- package/templates/app-demo/src/pages/PricingPage.tsx.example +41 -0
- package/templates/app-demo/src/pages/ProductsPage.tsx.example +19 -0
- package/templates/app-demo/src/pages/ProfilePage.tsx.example +18 -0
- package/templates/app-demo/src/pages/SettingsPage.tsx.example +17 -0
- package/templates/app-demo/src/pages/ShowcaseDetailPage.tsx.example +118 -0
- package/templates/app-demo/src/pages/ShowcasePage.tsx.example +93 -0
- package/templates/app-demo/src/pages/components/ComponentRenderer.tsx.example +147 -51
- package/templates/app-demo/src/pages/components/ComponentsData.tsx.example +103 -21
- package/templates/app-demo/src/pages/components/componentConfig.ts.example +139 -59
- package/templates/app-demo/src/pages/legal/LegalPage.tsx.example +25 -0
- package/templates/app-demo/src/pages/legal/PrivacyPage.tsx.example +23 -0
- package/templates/app-demo/src/pages/legal/TermsPage.tsx.example +23 -0
- package/templates/app-demo/src/themes.css.example +289 -77
- package/templates/app-demo/stats.html.example +4949 -0
- package/templates/app-demo/tsconfig.json.example +1 -1
- package/templates/app-demo/vite.config.ts.example +23 -48
- package/templates/app-expo/README.md.example +1 -1
- package/templates/app-expo/app/index.tsx.example +1 -1
- package/templates/app-next/src/locales/home_en.json.example +6 -6
- package/templates/app-vite/src/locales/home_en.json.example +6 -6
- package/templates/app-vite/src/pages/HomePage.tsx.example +8 -10
- package/templates/overlay-firebase/env.fragment.example +1 -1
- package/templates/overlay-firebase/env.fragment.expo.example +1 -1
- package/templates/overlay-firebase/env.fragment.nextjs.example +1 -1
- package/templates/overlay-supabase/env.fragment.example +1 -1
- package/templates/overlay-supabase/env.fragment.expo.example +1 -1
- package/templates/overlay-supabase/env.fragment.nextjs.example +1 -1
- package/templates/overlay-vercel/env.fragment.example +1 -1
- package/templates/overlay-vercel/env.fragment.nextjs.example +1 -1
- package/templates/root-consumer/AI.md.example +4 -3
- package/templates/root-consumer/guides/dndev/AGENT_START_HERE.md.example +21 -6
- package/templates/root-consumer/guides/dndev/COMPONENTS_ADV.md.example +16 -179
- package/templates/root-consumer/guides/dndev/ENV_SETUP.md.example +19 -21
- package/templates/root-consumer/guides/dndev/GOTCHAS.md.example +14 -3
- package/templates/root-consumer/guides/dndev/INDEX.md.example +2 -2
- package/templates/root-consumer/guides/dndev/SETUP_APP_CONFIG.md.example +3 -3
- package/templates/root-consumer/guides/dndev/SETUP_BLOG.md.example +19 -2
- package/templates/root-consumer/guides/dndev/SETUP_CRUD.md.example +35 -1
- package/templates/root-consumer/guides/dndev/SETUP_FIREBASE.md.example +17 -12
- package/templates/root-consumer/guides/dndev/SETUP_LAYOUTS.md.example +32 -0
- package/templates/root-consumer/guides/dndev/SETUP_OAUTH_PROVIDERS.md.example +1 -1
- package/templates/root-consumer/guides/dndev/SETUP_PAGES.md.example +19 -15
- package/templates/root-consumer/guides/dndev/SETUP_STRIPE.md.example +2 -2
- package/templates/root-consumer/guides/dndev/SETUP_SUPABASE.md.example +17 -12
- package/templates/root-consumer/guides/dndev/SETUP_VERCEL.md.example +37 -16
- package/templates/root-consumer/guides/dndev/USE_ROUTING.md.example +18 -18
- package/templates/root-consumer/guides/dndev/advanced/COOKIE_REFERENCE.md.example +252 -252
- package/templates/root-consumer/guides/dndev/advanced/VERSION_CONTROL.md.example +174 -174
- package/templates/root-consumer/guides/dndev/essences_reference.css.example +119 -2
- package/templates/root-consumer/guides/wai-way/blueprints/1_scaffold.md.example +14 -0
- package/templates/root-consumer/guides/wai-way/blueprints/2_entities.md.example +6 -0
- package/templates/root-consumer/guides/wai-way/blueprints/3_compose.md.example +14 -0
- package/templates/root-consumer/guides/wai-way/entity_patterns.md.example +4 -5
- package/templates/root-consumer/guides/wai-way/page_patterns.md.example +2 -2
- package/dist/bin/commands/agent-setup.d.ts +0 -6
- package/dist/bin/commands/agent-setup.d.ts.map +0 -1
- package/dist/bin/commands/agent-setup.js.map +0 -1
- package/dist/bin/commands/build.d.ts +0 -11
- package/dist/bin/commands/build.d.ts.map +0 -1
- package/dist/bin/commands/build.js.map +0 -1
- package/dist/bin/commands/bump.d.ts +0 -11
- package/dist/bin/commands/bump.d.ts.map +0 -1
- package/dist/bin/commands/bump.js.map +0 -1
- package/dist/bin/commands/cacheout.d.ts +0 -11
- package/dist/bin/commands/cacheout.d.ts.map +0 -1
- package/dist/bin/commands/cacheout.js.map +0 -1
- package/dist/bin/commands/create-app.d.ts +0 -11
- package/dist/bin/commands/create-app.d.ts.map +0 -1
- package/dist/bin/commands/create-app.js.map +0 -1
- package/dist/bin/commands/create-project.d.ts +0 -11
- package/dist/bin/commands/create-project.d.ts.map +0 -1
- package/dist/bin/commands/create-project.js.map +0 -1
- package/dist/bin/commands/deploy.d.ts +0 -11
- package/dist/bin/commands/deploy.d.ts.map +0 -1
- package/dist/bin/commands/deploy.js.map +0 -1
- package/dist/bin/commands/dev.d.ts +0 -11
- package/dist/bin/commands/dev.d.ts.map +0 -1
- package/dist/bin/commands/dev.js.map +0 -1
- package/dist/bin/commands/doctor.d.ts +0 -6
- package/dist/bin/commands/doctor.d.ts.map +0 -1
- package/dist/bin/commands/doctor.js.map +0 -1
- package/dist/bin/commands/emu.d.ts +0 -11
- package/dist/bin/commands/emu.d.ts.map +0 -1
- package/dist/bin/commands/emu.js.map +0 -1
- package/dist/bin/commands/format.d.ts +0 -11
- package/dist/bin/commands/format.d.ts.map +0 -1
- package/dist/bin/commands/format.js.map +0 -1
- package/dist/bin/commands/make-admin.d.ts +0 -11
- package/dist/bin/commands/make-admin.d.ts.map +0 -1
- package/dist/bin/commands/make-admin.js.map +0 -1
- package/dist/bin/commands/preview.d.ts +0 -11
- package/dist/bin/commands/preview.d.ts.map +0 -1
- package/dist/bin/commands/preview.js.map +0 -1
- package/dist/bin/commands/setup.d.ts +0 -6
- package/dist/bin/commands/setup.d.ts.map +0 -1
- package/dist/bin/commands/setup.js.map +0 -1
- package/dist/bin/commands/sync-secrets.d.ts +0 -11
- package/dist/bin/commands/sync-secrets.d.ts.map +0 -1
- package/dist/bin/commands/sync-secrets.js.map +0 -1
- package/dist/bin/commands/type-check.d.ts +0 -14
- package/dist/bin/commands/type-check.d.ts.map +0 -1
- package/dist/bin/commands/type-check.js.map +0 -1
- package/dist/bin/commands/wai.d.ts +0 -11
- package/dist/bin/commands/wai.d.ts.map +0 -1
- package/dist/bin/commands/wai.js.map +0 -1
- package/dist/index.d.ts +0 -8
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/templates/app-demo/src/components/ThemeToggle.tsx.example +0 -48
- package/templates/app-demo/src/pages/DetailPage.tsx.example +0 -103
- package/templates/app-demo/src/pages/FullPage.tsx.example +0 -142
- package/templates/app-demo/src/pages/components/DemoLayout.tsx.example +0 -266
- 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/
|
|
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
|
|
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
|
|
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
|
|
15
|
-
- [SETUP_SUPABASE.md](./SETUP_SUPABASE.md) - Supabase project setup (`dndev
|
|
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
|
|
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
|
|
119
|
-
VITE_FIREBASE_PROJECT_ID=... # Written by dndev setup
|
|
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
|
-
**
|
|
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
|
|
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
|
|
7
|
+
## Step 1: Run Coach + Fill .env
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
dndev
|
|
10
|
+
dndev coach
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
This
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
|
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`
|
|
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
|
|
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
|
|
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
|
-
**
|
|
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 {
|
|
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
|
|
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
|
|
56
|
-
dndev doctor #
|
|
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
|
|
7
|
+
## Step 1: Run Coach + Fill .env
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
dndev
|
|
10
|
+
dndev coach
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
This
|
|
14
|
-
-
|
|
15
|
-
-
|
|
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
|
-
|
|
17
|
+
Get these from: [Supabase Dashboard](https://supabase.com/dashboard) → your project → **Settings → API**.
|
|
19
18
|
|
|
20
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
32
|
+
## Step 2: Add Credentials to `.env.local`
|
|
33
33
|
|
|
34
|
-
|
|
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
|
|
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
|
-
|
|
86
|
+
dndev deploy
|
|
68
87
|
```
|
|
69
88
|
|
|
70
|
-
|
|
89
|
+
That's it. The CLI reads your credentials from `.env.local` and deploys to production.
|
|
71
90
|
|
|
72
|
-
|
|
73
|
-
dndev deploy
|
|
74
|
-
```
|
|
91
|
+
**Option B — Git push (auto-deploy)**
|
|
75
92
|
|
|
76
|
-
|
|
93
|
+
If your repo is connected to Vercel, pushing to your branch auto-deploys:
|
|
77
94
|
|
|
78
95
|
```bash
|
|
79
|
-
|
|
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` |
|
|
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
|
-
**
|
|
214
|
+
**3 values in `.env.local` → `dndev deploy` → done.**
|