anhedral 0.4.1 → 0.6.0
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/README.md +29 -256
- package/assets/anhedral-cli-init-technical.svg +322 -0
- package/assets/anhedral-cli-init.svg +257 -173
- package/dist/bin.js +28 -162
- package/dist/dependencies.d.ts +7 -56
- package/dist/dependencies.js +96 -305
- package/dist/index.d.ts +2 -7
- package/dist/index.js +1 -4
- package/dist/{templates → platforms}/desktop.d.ts +1 -1
- package/dist/{templates → platforms}/desktop.js +28 -266
- package/dist/{templates → platforms}/extension.d.ts +1 -1
- package/dist/platforms/extension.js +401 -0
- package/dist/{templates → platforms}/mobile.d.ts +1 -1
- package/dist/platforms/mobile.js +232 -0
- package/dist/project.d.ts +4 -0
- package/dist/project.js +1 -0
- package/dist/standard-products.d.ts +2 -0
- package/dist/standard-products.js +6 -0
- package/dist/standard.d.ts +18 -0
- package/dist/standard.js +578 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/application-stack-standard.md +700 -0
- package/package.json +34 -49
- package/CHANGELOG.md +0 -132
- package/CONTRIBUTING.md +0 -73
- package/SECURITY.md +0 -37
- package/SKILL.md +0 -244
- package/assets/images/svg/ably-symbol-color.svg +0 -8
- package/bin/anhedral.js +0 -2
- package/dist/architecture/contributions.d.ts +0 -28
- package/dist/architecture/contributions.js +0 -125
- package/dist/architecture/index.d.ts +0 -12
- package/dist/architecture/index.js +0 -6
- package/dist/architecture/manifest.d.ts +0 -53
- package/dist/architecture/manifest.js +0 -283
- package/dist/architecture/modules.d.ts +0 -37
- package/dist/architecture/modules.js +0 -184
- package/dist/architecture/plan.d.ts +0 -58
- package/dist/architecture/plan.js +0 -145
- package/dist/architecture/templates.d.ts +0 -10
- package/dist/architecture/templates.js +0 -23
- package/dist/cli.d.ts +0 -32
- package/dist/cli.js +0 -235
- package/dist/composers/root.d.ts +0 -6
- package/dist/composers/root.js +0 -35
- package/dist/print.d.ts +0 -8
- package/dist/print.js +0 -48
- package/dist/prompts.d.ts +0 -5
- package/dist/prompts.js +0 -19
- package/dist/scaffold.d.ts +0 -76
- package/dist/scaffold.js +0 -1895
- package/dist/template-source.d.ts +0 -20
- package/dist/template-source.js +0 -180
- package/dist/templates/api.d.ts +0 -2
- package/dist/templates/api.js +0 -3122
- package/dist/templates/assets-private-proxy.d.ts +0 -3
- package/dist/templates/assets-private-proxy.js +0 -277
- package/dist/templates/electron-updater.d.ts +0 -3
- package/dist/templates/electron-updater.js +0 -358
- package/dist/templates/extension.js +0 -732
- package/dist/templates/mobile.js +0 -720
- package/dist/templates/shared.d.ts +0 -2
- package/dist/templates/shared.js +0 -520
- package/dist/templates/web.d.ts +0 -2
- package/dist/templates/web.js +0 -412
- package/dist/toolchain.d.ts +0 -3
- package/dist/toolchain.js +0 -8
- package/dist/ui.d.ts +0 -33
- package/dist/ui.js +0 -199
- package/dist/workspace-config.d.ts +0 -11
- package/dist/workspace-config.js +0 -372
- package/docs/conventions.md +0 -92
- package/docs/master-stack-map.md +0 -199
- package/docs/output-tree-contract.md +0 -482
- package/docs/references/manual-scaffolding.md +0 -403
- package/docs/references/provisioning.md +0 -220
- package/scripts/render-master-stack-map.mjs +0 -510
- package/templates/api-fastify/apps/api/tsconfig.json +0 -20
- package/templates/catalog.json +0 -23
- package/templates/db-drizzle/packages/db/tsconfig.json +0 -14
- package/templates/desktop-electron/apps/desktop/tsconfig.json +0 -37
- package/templates/extension-wxt/apps/extension/tsconfig.json +0 -41
- package/templates/mobile-expo/apps/mobile/expo-env.d.ts +0 -1
- package/templates/web-next/apps/web/next-env.d.ts +0 -6
|
@@ -1,403 +0,0 @@
|
|
|
1
|
-
# Manual Anhedral scaffolding
|
|
2
|
-
|
|
3
|
-
Use this procedure to build an Anhedral-style workspace without invoking the Anhedral CLI or importing its generator. Complete the phases in order. Do not stop after framework initialization: shared contracts, integration wiring, tests, root scripts, environment examples, CI, and deployment files are part of the scaffold.
|
|
4
|
-
|
|
5
|
-
## Contents
|
|
6
|
-
|
|
7
|
-
1. Record inputs and resolve modules
|
|
8
|
-
2. Establish the workspace contract
|
|
9
|
-
3. Create root configuration
|
|
10
|
-
4. Create shared packages
|
|
11
|
-
5. Create the API
|
|
12
|
-
6. Create client surfaces
|
|
13
|
-
7. Wire optional features
|
|
14
|
-
8. Configure environments and providers
|
|
15
|
-
9. Install, migrate, and verify
|
|
16
|
-
10. Audit completeness
|
|
17
|
-
11. Work from the Anhedral source repository
|
|
18
|
-
|
|
19
|
-
## 1. Record inputs and resolve modules
|
|
20
|
-
|
|
21
|
-
Record these values before editing:
|
|
22
|
-
|
|
23
|
-
- `projectName`: a valid npm package name; use it for the root package and child package prefixes.
|
|
24
|
-
- `displayName`: human-readable product name; escape it for every JSON, JavaScript, HTML, and Markdown context.
|
|
25
|
-
- requested app surfaces: `web`, `mobile`, `api`, `desktop`, `extension`.
|
|
26
|
-
- requested features: `db`, `auth`, `billing`, `storage`, `native-subscriptions`, `electron-updater`.
|
|
27
|
-
- toolchain policy: exact tested versions for reproducibility, or current compatible versions when the user explicitly wants upgrades.
|
|
28
|
-
|
|
29
|
-
Resolve the transitive closure before writing files:
|
|
30
|
-
|
|
31
|
-
```text
|
|
32
|
-
auth -> api + db
|
|
33
|
-
billing -> auth -> api + db
|
|
34
|
-
storage -> auth -> api + db
|
|
35
|
-
native-subscriptions -> mobile + billing -> auth + api + db
|
|
36
|
-
electron-updater -> desktop
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
If no modules were specified, select all five surfaces and all six features. Never create a feature without its prerequisites. Keep normalized order `web, mobile, api, desktop, extension, db, auth, billing, storage, native-subscriptions, electron-updater` when displaying or recording a plan.
|
|
40
|
-
|
|
41
|
-
Choose Node `^20.19.0 || >=22.12.0` unless mobile is selected. Expo mobile requires `^22.13.0 || ^24.3.0 || >=25`. Use one root pnpm workspace and one root lockfile; never leave nested lockfiles, workspaces, `.git` directories, or `node_modules` inside apps.
|
|
42
|
-
|
|
43
|
-
Use this stable baseline when current source is unavailable. It was verified on 2026-07-15; keep each version exact and update the baseline as one tested set rather than upgrading packages independently:
|
|
44
|
-
|
|
45
|
-
```text
|
|
46
|
-
pnpm 10.34.5; turbo 2.9.14; TypeScript 5.9.3; @types/node 20.19.43
|
|
47
|
-
contracts: zod 4.2.1
|
|
48
|
-
db: @neondatabase/serverless 1.0.2, drizzle-orm 0.45.2,
|
|
49
|
-
drizzle-kit 0.31.7, dotenv 17.2.3, tsx 4.20.6
|
|
50
|
-
api: fastify 5.8.5, @fastify/cors 11.1.0, @fastify/compress 8.3.0,
|
|
51
|
-
@fastify/helmet 13.0.2, @fastify/rate-limit 10.3.0,
|
|
52
|
-
@clerk/fastify 3.1.51, @aws-sdk/client-s3 3.1047.0,
|
|
53
|
-
@aws-sdk/s3-request-presigner 3.1047.0, ably 2.24.0, vitest 4.1.0
|
|
54
|
-
web: next 16.2.11, react/react-dom 19.2.3, @clerk/nextjs 7.5.18,
|
|
55
|
-
@clerk/ui 1.25.3, tailwindcss and @tailwindcss/postcss 4.1.18
|
|
56
|
-
mobile: expo 56.0.16, expo-router 56.2.15, react-native 0.85.3,
|
|
57
|
-
@clerk/expo 3.7.5, expo-secure-store 56.0.4,
|
|
58
|
-
react-native-purchases/react-native-purchases-ui 10.4.2
|
|
59
|
-
desktop: electron 43.1.1, electron-builder 26.15.3, vite 7.3.6,
|
|
60
|
-
@vitejs/plugin-react 5.2.0, @clerk/clerk-js 6.25.3,
|
|
61
|
-
electron-updater 6.8.9 when electron-updater is selected
|
|
62
|
-
extension: wxt 0.20.27, @wxt-dev/module-react 1.2.2,
|
|
63
|
-
@clerk/chrome-extension 3.1.52, tailwindcss 3.4.19
|
|
64
|
-
shared UI: clsx 2.1.1, tailwind-merge 3.4.0
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
Expo's package uses TypeScript 6.0.3 and its SDK-compatible React Native support packages from `src/dependencies.ts`; do not force the root TypeScript version into mobile.
|
|
68
|
-
|
|
69
|
-
## 2. Establish the workspace contract
|
|
70
|
-
|
|
71
|
-
Create only selected branches of this tree. A bracketed condition makes the file required exactly when true.
|
|
72
|
-
|
|
73
|
-
```text
|
|
74
|
-
<root>/
|
|
75
|
-
.env.example
|
|
76
|
-
.github/workflows/anhedral-ci.yml
|
|
77
|
-
.gitignore
|
|
78
|
-
.vercelignore
|
|
79
|
-
README.md
|
|
80
|
-
PRODUCTION.md
|
|
81
|
-
package.json
|
|
82
|
-
pnpm-workspace.yaml
|
|
83
|
-
turbo.json
|
|
84
|
-
vercel.json
|
|
85
|
-
scripts/verify-db-migrations.mjs [db]
|
|
86
|
-
packages/contracts/{package.json,tsconfig.json,src/index.ts} [api]
|
|
87
|
-
packages/api-client/{package.json,tsconfig.json,src/index.ts} [api + any client]
|
|
88
|
-
packages/realtime/{package.json,tsconfig.json,src/index.ts} [billing + any client]
|
|
89
|
-
packages/db/{package.json,tsconfig.json,drizzle.config.ts,.env.example} [db]
|
|
90
|
-
packages/db/src/{index.ts,migrate.ts,schema.ts} [db]
|
|
91
|
-
packages/db/migrations/.gitkeep [db]
|
|
92
|
-
apps/api/{package.json,tsconfig.json,vitest.config.ts,.env.example,.gitignore} [api]
|
|
93
|
-
apps/api/src/{application.ts,env.ts,index.ts,routes.ts} [api]
|
|
94
|
-
apps/api/src/auth.ts [auth]
|
|
95
|
-
apps/api/src/billing.ts [billing]
|
|
96
|
-
apps/api/src/realtime.ts [billing]
|
|
97
|
-
apps/api/src/storage.ts [storage]
|
|
98
|
-
apps/api/tests/{health.test.ts,env.test.ts} [api]
|
|
99
|
-
apps/api/tests/revenuecat-webhook.test.ts [billing]
|
|
100
|
-
apps/api/tests/storage.test.ts [storage]
|
|
101
|
-
apps/assets-private-proxy/{package.json,wrangler.jsonc} [storage]
|
|
102
|
-
apps/assets-private-proxy/src/index.js [storage]
|
|
103
|
-
cloudflare/{README.md,r2-cors.template.json} [storage]
|
|
104
|
-
apps/web/{package.json,tsconfig.json,next-env.d.ts,next.config.ts,postcss.config.mjs,components.json,.env.example} [web]
|
|
105
|
-
apps/web/app/{layout.tsx,page.tsx,globals.css} [web]
|
|
106
|
-
apps/web/components/ui/{button.tsx,card.tsx} [web]
|
|
107
|
-
apps/web/lib/utils.ts [web]
|
|
108
|
-
apps/web/{lib/api.ts,hooks/use-api-client.ts} [web + api]
|
|
109
|
-
apps/web/components/account-actions.tsx [web + auth]
|
|
110
|
-
apps/web/{hooks/use-entitlement.ts,components/subscription-status.tsx} [web + billing]
|
|
111
|
-
apps/mobile/{package.json,app.json,tsconfig.json,expo-env.d.ts,eas.json,.env.example,.gitignore} [mobile]
|
|
112
|
-
apps/mobile/app/{_layout.tsx,index.tsx} [mobile]
|
|
113
|
-
apps/mobile/{lib/api.ts,hooks/use-api-client.ts} [mobile + api]
|
|
114
|
-
apps/mobile/components/account-controls.tsx [mobile + auth]
|
|
115
|
-
apps/mobile/hooks/use-entitlement.ts [mobile + billing]
|
|
116
|
-
apps/mobile/lib/subscriptions.ts [native-subscriptions]
|
|
117
|
-
apps/desktop/{package.json,tsconfig.json,tsconfig.main.json,vite.config.ts,postcss.config.mjs,components.json,index.html,.env.example} [desktop]
|
|
118
|
-
apps/desktop/scripts/dev.mjs [desktop]
|
|
119
|
-
apps/desktop/src/main/{main.ts,preload.cts} [desktop]
|
|
120
|
-
apps/desktop/src/renderer/{main.tsx,styles.css,lib/utils.ts} [desktop]
|
|
121
|
-
apps/desktop/src/renderer/components/ui/button.tsx [desktop]
|
|
122
|
-
apps/desktop/src/renderer/lib/api.ts [desktop + api]
|
|
123
|
-
apps/desktop/src/renderer/lib/auth.ts [desktop + auth]
|
|
124
|
-
apps/desktop/src/renderer/hooks/use-entitlement.ts [desktop + billing]
|
|
125
|
-
apps/desktop/electron-builder.env.example [electron-updater]
|
|
126
|
-
apps/desktop/scripts/publish-updates.mjs [electron-updater]
|
|
127
|
-
apps/desktop-updater-worker/{package.json,wrangler.jsonc} [electron-updater]
|
|
128
|
-
apps/desktop-updater-worker/src/index.js [electron-updater]
|
|
129
|
-
cloudflare/desktop-updates.md [electron-updater]
|
|
130
|
-
apps/extension/{package.json,tsconfig.json,wxt.config.ts,postcss.config.cjs,tailwind.config.cjs,components.json,.env.example,README.md} [extension]
|
|
131
|
-
apps/extension/src/{styles/main.css,lib/utils.ts} [extension]
|
|
132
|
-
apps/extension/src/components/ui/button.tsx [extension]
|
|
133
|
-
apps/extension/src/entrypoints/{background.ts,sidepanel/index.html,sidepanel/main.tsx,sidepanel/app.tsx} [extension]
|
|
134
|
-
apps/extension/src/contexts/auth-context.tsx [extension + auth]
|
|
135
|
-
apps/extension/src/lib/api.ts [extension + api]
|
|
136
|
-
apps/extension/src/hooks/use-entitlement.ts [extension + billing]
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
Do not create `anhedral.json` manually. Its schema-v5 hashes, modes, ownership classes, template and UI-provider provenance, module resolution, generator version, and toolchain channel form a trust boundary for `add` and `doctor`. Invented records are worse than no manifest. Also omit `ANHEDRAL.md`, whose CLI-management claims would be false for a manual workspace.
|
|
140
|
-
|
|
141
|
-
## 3. Create root configuration
|
|
142
|
-
|
|
143
|
-
### Root package
|
|
144
|
-
|
|
145
|
-
Create a private `package.json` with version `0.1.0`, the selected Node engine, the pnpm version being used, `turbo` as an exact dev dependency, and `workspaces` containing `apps/*` when any app exists and `packages/*` when API or database exists.
|
|
146
|
-
|
|
147
|
-
Always add `build: turbo build` and `typecheck: turbo typecheck`. Set `dev` to
|
|
148
|
-
the primary product loop: run the first selected client in canonical module
|
|
149
|
-
order plus API when present, or API alone for a backend-only project. When the
|
|
150
|
-
project has additional app surfaces, add `dev:all` to run every selected app in
|
|
151
|
-
parallel. Each command uses `turbo dev --parallel` with explicit
|
|
152
|
-
`--filter=./apps/<surface>` arguments. Add only selected scripts:
|
|
153
|
-
|
|
154
|
-
```text
|
|
155
|
-
web: dev:web, verify:web = typecheck + build
|
|
156
|
-
mobile: dev:mobile, verify:mobile = typecheck + build:web
|
|
157
|
-
api: dev:api, verify:api = test:coverage + build
|
|
158
|
-
desktop: dev:desktop, desktop:build, verify:desktop = typecheck + build
|
|
159
|
-
electron-updater: desktop:updates:cloudflare:login,
|
|
160
|
-
desktop:updates:bucket:create, desktop:updates:first-provision,
|
|
161
|
-
desktop:updates:worker:{check,dev,deploy,types},
|
|
162
|
-
desktop:updates:build:{mac,win,linux},
|
|
163
|
-
desktop:updates:publish, verify:desktop-updates
|
|
164
|
-
extension: dev:extension, extension:zip, verify:extension = typecheck + zip
|
|
165
|
-
db: db:generate, db:migrate, db:check, db:studio, verify:db
|
|
166
|
-
storage: r2:login, r2:bucket:create, r2:cors:list, r2:cors:set,
|
|
167
|
-
assets:proxy:check, assets:proxy:dev, assets:proxy:deploy,
|
|
168
|
-
verify:assets-proxy
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
Set root `verify` to every selected `verify:<module>` joined with `&&`; include `verify:db`. If no app exists, begin it with `pnpm typecheck`.
|
|
172
|
-
|
|
173
|
-
### pnpm workspace
|
|
174
|
-
|
|
175
|
-
Create `pnpm-workspace.yaml` with the same workspace globs as the root package. Set `autoInstallPeers: false`, then add:
|
|
176
|
-
|
|
177
|
-
```yaml
|
|
178
|
-
onlyBuiltDependencies:
|
|
179
|
-
- electron
|
|
180
|
-
- esbuild
|
|
181
|
-
- sharp
|
|
182
|
-
ignoredBuiltDependencies:
|
|
183
|
-
- browser-tabs-lock
|
|
184
|
-
- bufferutil
|
|
185
|
-
- core-js
|
|
186
|
-
- electron-winstaller
|
|
187
|
-
- spawn-sync
|
|
188
|
-
- utf-8-validate
|
|
189
|
-
peerDependencyRules:
|
|
190
|
-
ignoreMissing:
|
|
191
|
-
- '@solana/web3.js'
|
|
192
|
-
- bs58
|
|
193
|
-
- react-native
|
|
194
|
-
allowedVersions:
|
|
195
|
-
esbuild: '>=0.25.0'
|
|
196
|
-
utf-8-validate: '>=5.0.2'
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
Pin current security overrides for `@vitejs/plugin-react`, `postcss`, vulnerable `esbuild` ranges, `shell-quote`, `tmp`, and `uuid`. Inside the Anhedral repository, copy exact override keys and values from `SECURITY_OVERRIDES` in `src/dependencies.ts`.
|
|
200
|
-
|
|
201
|
-
### Turbo, ignore files, Vercel, and CI
|
|
202
|
-
|
|
203
|
-
Create `turbo.json` using `https://turborepo.dev/schema.json` with:
|
|
204
|
-
|
|
205
|
-
- `build.dependsOn = ["^build"]` and outputs `.next/**`, `!.next/cache/**`, `.output/**`, `dist/**`.
|
|
206
|
-
- `typecheck.dependsOn = ["^build"]`.
|
|
207
|
-
- `dev.cache = false` and `dev.persistent = true`.
|
|
208
|
-
|
|
209
|
-
Ignore `node_modules`, framework/build caches, coverage, release output, every `.env` variant except `.env.example`, and `*.tsbuildinfo`. Put extension output, mobile web export, desktop release output, `apps/assets-private-proxy`, and `apps/desktop-updater-worker` in `.vercelignore`.
|
|
210
|
-
|
|
211
|
-
Create the single root `vercel.json` using `https://openapi.vercel.sh/vercel.json`. Add service `api` rooted at `apps/api` and service `web` rooted at `apps/web` as selected. Put the `/api/(.*)` rewrite before the web `/(.*)` catch-all. If billing is selected, add `*/5 * * * *` for `/api/internal/realtime/flush`; if storage is selected, add `0 3 * * *` for `/api/internal/storage/cleanup`. Protect both internal routes with the same high-entropy `CRON_SECRET` bearer token.
|
|
212
|
-
|
|
213
|
-
Create `.github/workflows/anhedral-ci.yml` with read-only contents permission, concurrency cancellation, pinned action commit SHAs, pnpm setup, Node `22.13.0` for mobile or `20.19.0` otherwise, and frozen installation. Run `pnpm typecheck`, API coverage tests when API exists, and `pnpm build`. For database workspaces also run `pnpm verify:db`, run `pnpm db:generate`, fail on any migration diff, and fail on untracked migration artifacts.
|
|
214
|
-
|
|
215
|
-
Create `README.md` containing selected modules and first-run commands. Create `PRODUCTION.md` containing provider and deployment requirements from sections 8 and 9. These two files become user-owned; do not rewrite them during later manual module additions.
|
|
216
|
-
|
|
217
|
-
## 4. Create shared packages
|
|
218
|
-
|
|
219
|
-
Use strict TypeScript with `moduleResolution: Bundler`, `noEmit`, `skipLibCheck`, and `noUncheckedIndexedAccess`. Export source TypeScript directly inside the workspace.
|
|
220
|
-
|
|
221
|
-
### Contracts
|
|
222
|
-
|
|
223
|
-
Create `@shared/contracts` whenever API is selected. Depend on Zod. Define and export schemas plus inferred types for health and readiness; authenticated user when auth is selected; revisioned entitlement, realtime token request, and `subscription.changed` invalidation when billing is selected; and strict create-upload, confirm-upload, upload-record, and route-param data when storage is selected.
|
|
224
|
-
|
|
225
|
-
Keep the upload content-type allowlist and maximum upload size in contracts so API and clients share one source of truth. Validate API response bodies in the client package before returning them.
|
|
226
|
-
|
|
227
|
-
### API client
|
|
228
|
-
|
|
229
|
-
Create `@shared/api-client` when API and at least one client surface are selected. Depend on contracts and Zod. Implement:
|
|
230
|
-
|
|
231
|
-
- strict absolute `http:`/`https:` base-URL normalization with no credentials, query, or fragment;
|
|
232
|
-
- an `ApiError` carrying HTTP status, stable code, details, and cause;
|
|
233
|
-
- optional async token retrieval;
|
|
234
|
-
- timeout and caller-abort composition with listener/timer cleanup;
|
|
235
|
-
- JSON parsing and Zod response validation;
|
|
236
|
-
- typed methods for health/readiness and only selected auth, billing, and storage routes.
|
|
237
|
-
|
|
238
|
-
Do not make server-only provider SDKs dependencies of clients.
|
|
239
|
-
|
|
240
|
-
### Realtime client
|
|
241
|
-
|
|
242
|
-
Create `@shared/realtime` only when billing and at least one client are selected. Depend on Ably and contracts. Accept an async API-token callback, connect with `authCallback`, subscribe only to `private:users/<userId>/subscriptions`, validate every `subscription.changed` payload, expose connection errors, and return an idempotent cleanup function that unsubscribes and closes the client. Never put `ABLY_API_KEY` or a broad Ably capability in a client package.
|
|
243
|
-
|
|
244
|
-
### Database
|
|
245
|
-
|
|
246
|
-
Create `@shared/db` when `db` is selected. Use Neon serverless, Drizzle ORM, dotenv, Drizzle Kit, and tsx. Provide `db:generate`, `db:migrate`, `db:check`, and `db:studio`. Configure PostgreSQL with `src/schema.ts` and `migrations/`.
|
|
247
|
-
|
|
248
|
-
Always define an `items` table. For billing, add `subscriptions` with a monotonic integer `revision`, idempotent `webhookEvents`, and `realtimeOutbox` with user, topic, revision, attempt/error, delivery, and creation fields. Add `uploads` for storage, including user ownership, staging/final keys, declared and actual metadata, status/rejection fields, expiry, cleanup, confirmation, and creation timestamps. Export the Drizzle client and schema, and fail immediately when `DATABASE_URL` is absent.
|
|
249
|
-
|
|
250
|
-
Create `scripts/verify-db-migrations.mjs`. It must recursively find committed SQL files, fail when none exist, fail when SQL is untracked inside a Git worktree, and require a Git worktree in CI.
|
|
251
|
-
|
|
252
|
-
## 5. Create the API
|
|
253
|
-
|
|
254
|
-
Create a Fastify TypeScript package with `dev`, `build`, `typecheck`, `test`, and `test:coverage`. Use Fastify, CORS, compression, Helmet, rate limiting, Zod, and only provider/database dependencies selected by the module plan.
|
|
255
|
-
|
|
256
|
-
Implement these layers:
|
|
257
|
-
|
|
258
|
-
- `env.ts`: validate selected values, exact CORS origins, port, proxy hops, demo mode, production key prefixes, URL forms, secret strength, and provider identifier formats. Never silently fall back to demo behavior in production.
|
|
259
|
-
- `application.ts`: construct the app, set proxy trust, register security plugins, expose shutdown state, centralize safe error serialization, and register routes under `/api`.
|
|
260
|
-
- `routes.ts`: register health/readiness unconditionally and provider routes conditionally.
|
|
261
|
-
- `index.ts`: listen on `0.0.0.0`, handle `SIGINT`/`SIGTERM` once, begin draining, close gracefully, and enforce a shutdown deadline.
|
|
262
|
-
|
|
263
|
-
Always provide `GET /api/health` and `GET /api/ready`. Readiness returns 503 for dependency failure or shutdown. Do not leak internal errors, stack traces, credentials, or arbitrary details in 5xx responses. Allow safe details only for intentional 4xx errors.
|
|
264
|
-
|
|
265
|
-
When auth is selected, verify Clerk requests server-side and expose protected `/api/me`. When billing is selected, implement a RevenueCat webhook with constant-time secret comparison, shape validation, durable idempotency, claim/retry handling, monotonic event timestamps, and server-side subscriber reconciliation. In the same database transaction as every accepted subscription mutation, increment its revision and insert an outbox record. Expose authenticated `GET /api/subscriptions/me`, `POST /api/subscriptions/refresh`, and `POST /api/realtime/token`; issue a short-lived Ably token request limited to the authenticated Clerk user's subscribe-only channel. Publish only `{ type, revision }`, mark delivery after publish, retain failures for retry, and expose `GET /api/internal/realtime/flush` behind `CRON_SECRET`. When storage is selected, issue short-lived R2 presigned PUTs bound to content type and length, persist pending uploads, verify object metadata before confirmation, isolate every key below `R2_PREFIX`, expose an owner-authorized read-URL endpoint with a bounded presigned-GET TTL, and provide an authenticated cleanup endpoint for the scheduled cron.
|
|
266
|
-
|
|
267
|
-
Test health, readiness, shutdown state, safe errors, and exact CORS behavior. Test environment validation. Add replay/out-of-order/retry tests for billing and size/type/ownership/cleanup tests for storage.
|
|
268
|
-
|
|
269
|
-
## 6. Create client surfaces
|
|
270
|
-
|
|
271
|
-
Every client with API access must use `@shared/api-client`; do not duplicate fetch/error logic. Every authenticated client supplies its Clerk session token to that client. Require HTTPS for configured production API URLs. Billing clients load the authoritative entitlement first, subscribe through `@shared/realtime`, ignore invalidation revisions they already hold, and refetch rather than trusting event payloads. They must also refetch after visibility/foreground recovery so missed or delayed events cannot leave stale access.
|
|
272
|
-
|
|
273
|
-
### Web
|
|
274
|
-
|
|
275
|
-
Create a Next.js App Router app with Tailwind and shadcn-style `Button` and `Card` primitives. Use strict TypeScript, the `@/*` alias, a development rewrite from `/api/:path*` to `http://localhost:8787/api/:path*`, and same-origin `/api` in production. Wrap the layout in Clerk only for auth. Add account controls for auth and typed API status UI for API. For billing, render a subscription-status component backed by a realtime entitlement hook and refetch on document visibility.
|
|
276
|
-
|
|
277
|
-
### Mobile
|
|
278
|
-
|
|
279
|
-
Create an Expo Router app with static web export, a normalized URL scheme, strict TypeScript, and EAS production profiles. Add Clerk plus secure token caching only for auth. Add the typed API hook only for API. For billing, subscribe to realtime invalidations and refetch when `AppState` returns active. For native subscriptions, configure RevenueCat independently for iOS and Android public SDK keys, synchronize the RevenueCat app-user ID after Clerk loads, log RevenueCat out when Clerk signs out, expose retryable synchronization errors, register one global customer-info update listener, and present the configured entitlement paywall. After purchase/restore success or a RevenueCat customer-info callback, call the authenticated refresh endpoint so every other surface updates without waiting for webhook delivery.
|
|
280
|
-
|
|
281
|
-
### Desktop
|
|
282
|
-
|
|
283
|
-
Create Electron main/preload and a Vite React renderer. Keep `contextIsolation: true`, `nodeIntegration: false`, sandboxing enabled, and navigation/window-open restricted to trusted targets. Use a preload bridge rather than exposing Node. Add Tailwind/shadcn-style UI. Add typed API and Clerk browser auth only when selected. For billing, expose the current Clerk user ID to a realtime entitlement hook and refetch when the renderer becomes visible. Provide development orchestration plus current-host and platform-specific electron-builder scripts.
|
|
284
|
-
|
|
285
|
-
### Extension
|
|
286
|
-
|
|
287
|
-
Create a WXT React side-panel extension with Tailwind/shadcn-style UI. Generate permissions from selected features and host permissions only from validated API/Clerk origins. Require HTTPS in production. Add Clerk's extension provider/context only for auth and typed API only for API. For billing, consume the authenticated user ID/API client from that context, subscribe to invalidations, and refetch when the side panel becomes visible. Include `storage` and `cookies` permissions only when Clerk needs them. Provide `dev`, `build`, `zip`, `postinstall`, and `typecheck`.
|
|
288
|
-
|
|
289
|
-
## 7. Wire optional features
|
|
290
|
-
|
|
291
|
-
After selected surfaces exist, perform a cross-surface pass:
|
|
292
|
-
|
|
293
|
-
- `auth`: Clerk server verification; protected API route; provider/account UI in every selected client; token-aware API hooks; client publishable keys and server secret separated.
|
|
294
|
-
- `billing`: revisioned database state and transactional outbox; RevenueCat webhook/direct refresh; entitlement, scoped-token, and retry routes; Ably publisher and shared subscriber; contracts/API-client methods; live hooks in every client. Never expose RevenueCat or Ably secret keys.
|
|
295
|
-
- `storage`: upload tables; R2 presign/confirm/cleanup; owner-authorized presigned GET URLs; contracts and client methods; Vercel cron; generated R2 CORS/lifecycle guidance; and `apps/assets-private-proxy` with Worker name `assets-private-proxy`, private bucket binding `ASSETS`, `workers.dev` disabled, a user-owned custom-domain config, confirmed-prefix-only streaming GET/HEAD delivery, ranges, conditionals, cache, method/host validation, and no bucket listing.
|
|
296
|
-
- `native-subscriptions`: mobile RevenueCat SDKs, platform keys, Clerk identity synchronization, entitlement/paywall behavior, and error recovery.
|
|
297
|
-
|
|
298
|
-
Search the finished workspace for imports of unselected providers. Remove both source branches and dependencies when a feature is absent.
|
|
299
|
-
|
|
300
|
-
## 8. Configure environments and providers
|
|
301
|
-
|
|
302
|
-
The root `.env.example` is an inventory, not a runtime file. Create package-local examples and copy them to ignored runtime files:
|
|
303
|
-
|
|
304
|
-
```text
|
|
305
|
-
apps/api/.env.example -> apps/api/.env
|
|
306
|
-
packages/db/.env.example -> packages/db/.env
|
|
307
|
-
apps/web/.env.example -> apps/web/.env.local
|
|
308
|
-
apps/mobile/.env.example -> apps/mobile/.env
|
|
309
|
-
apps/desktop/.env.example -> apps/desktop/.env
|
|
310
|
-
apps/extension/.env.example -> apps/extension/.env
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
Include only selected values:
|
|
314
|
-
|
|
315
|
-
```text
|
|
316
|
-
API: NODE_ENV, PORT, TRUST_PROXY_HOPS, CORS_ORIGINS, ANHEDRAL_DEMO
|
|
317
|
-
db: DATABASE_URL
|
|
318
|
-
auth: CLERK_PUBLISHABLE_KEY, CLERK_SECRET_KEY
|
|
319
|
-
web: NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY, NEXT_PUBLIC_API_URL
|
|
320
|
-
mobile: EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY, EXPO_PUBLIC_API_URL
|
|
321
|
-
desktop: VITE_CLERK_PUBLISHABLE_KEY, VITE_API_URL
|
|
322
|
-
extension: VITE_CLERK_PUBLISHABLE_KEY, VITE_CLERK_FRONTEND_API_URL,
|
|
323
|
-
VITE_CLERK_SYNC_HOST, VITE_API_URL, optional VITE_CRX_PUBLIC_KEY
|
|
324
|
-
billing: RC_WEBHOOK_SECRET, RC_SECRET_API_KEY, RC_ENTITLEMENT_ID,
|
|
325
|
-
ABLY_API_KEY, CRON_SECRET
|
|
326
|
-
native: EXPO_PUBLIC_RC_API_KEY_IOS, EXPO_PUBLIC_RC_API_KEY_ANDROID,
|
|
327
|
-
EXPO_PUBLIC_RC_ENTITLEMENT_ID
|
|
328
|
-
storage: BASE_URL, R2_ACCOUNT_ID, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY,
|
|
329
|
-
R2_BUCKET_NAME, R2_PREFIX=storage,
|
|
330
|
-
R2_PROXY_READ_URL_TTL_SECONDS=600, CLOUDFLARE_API_TOKEN (ops/CI only),
|
|
331
|
-
CRON_SECRET
|
|
332
|
-
```
|
|
333
|
-
|
|
334
|
-
Use explicit local CORS origins for selected browser clients. Include `null` only for Electron's file origin. Production uses exact HTTPS origins. Keep `ANHEDRAL_DEMO=false`, server secrets server-only, and real environment files out of Git.
|
|
335
|
-
|
|
336
|
-
For R2, generate a user-owned `cloudflare/r2-cors.template.json`, list the live policy before replacing it, and retain every exact upload origin. Add a lifecycle rule for `storage/staging/` whose age exceeds the application cleanup grace period. Keep `r2.dev` and R2 bucket custom domains disabled. Use the generated Worker Custom Domain at `assets.<domain>` for public-by-key `storage/confirmed/` objects only. Use the authenticated upload-owner read-URL route for private delivery; it returns a short-lived presigned GET governed by `R2_PROXY_READ_URL_TTL_SECONDS`.
|
|
337
|
-
|
|
338
|
-
## 9. Install, migrate, and verify
|
|
339
|
-
|
|
340
|
-
Run from the root:
|
|
341
|
-
|
|
342
|
-
```sh
|
|
343
|
-
pnpm install
|
|
344
|
-
pnpm typecheck
|
|
345
|
-
```
|
|
346
|
-
|
|
347
|
-
For a database workspace, copy its environment, generate and review the initial migration, and add it to Git before the gate:
|
|
348
|
-
|
|
349
|
-
```sh
|
|
350
|
-
pnpm db:generate
|
|
351
|
-
git add packages/db/migrations
|
|
352
|
-
pnpm verify:db
|
|
353
|
-
pnpm db:migrate
|
|
354
|
-
```
|
|
355
|
-
|
|
356
|
-
Then run every selected package verification, root verification, and build:
|
|
357
|
-
|
|
358
|
-
```sh
|
|
359
|
-
pnpm verify
|
|
360
|
-
pnpm build
|
|
361
|
-
```
|
|
362
|
-
|
|
363
|
-
Run API coverage when API exists, Expo compatibility checks when mobile exists, a packaged Electron smoke test when desktop exists, and load unpacked WXT output when extension exists. Exercise one authenticated API call per selected client. For billing, replay a webhook, send an older event, verify an outbox record is committed atomically, verify the scoped token cannot publish or subscribe to another user, and observe one native purchase/refresh update web, Android, extension, and desktop sessions. Disconnect one client, mutate the entitlement, reconnect/foreground it, and confirm authoritative recovery. For storage, perform browser preflight, presigned upload, confirmation, cross-user private-read rejection, read-URL TTL verification, cleanup, Worker syntax/Wrangler dry-run validation, GET/HEAD/range/conditional/cache behavior, forbidden methods, unexpected hosts, missing keys, staging/private-prefix rejection, and direct-bucket inaccessibility.
|
|
364
|
-
|
|
365
|
-
Do not weaken types, tests, provider validation, security headers, or migration checks to make verification green. Report the failing package and command, fix the owning layer, and rerun the narrow check before root verification.
|
|
366
|
-
|
|
367
|
-
## 10. Audit completeness
|
|
368
|
-
|
|
369
|
-
Answer yes to every applicable item:
|
|
370
|
-
|
|
371
|
-
- Were prerequisites resolved before creation?
|
|
372
|
-
- Is there exactly one pnpm workspace and lockfile?
|
|
373
|
-
- Do root scripts reference only selected modules?
|
|
374
|
-
- Does every selected conditional file exist and every unselected one stay absent?
|
|
375
|
-
- Are contracts shared by API and clients?
|
|
376
|
-
- Are provider dependencies and environment keys gated by selection?
|
|
377
|
-
- Are secrets absent from clients and committed files?
|
|
378
|
-
- Are optional flows wired end to end rather than represented by placeholders?
|
|
379
|
-
- For billing, are revisions monotonic, outbox writes atomic, Ably capabilities user-scoped, and all clients recovery-safe?
|
|
380
|
-
- Is a reviewed, committed migration present for `db`?
|
|
381
|
-
- Do CI, Vercel services/rewrites, cron, CORS, and local ports agree?
|
|
382
|
-
- For storage, is the bucket private, is the hostname attached to the Worker rather than R2, and does the documented public-key or authenticated download policy match the code?
|
|
383
|
-
- Did `pnpm verify` and `pnpm build` pass?
|
|
384
|
-
- Is `anhedral.json` absent unless produced by the matching CLI?
|
|
385
|
-
|
|
386
|
-
## 11. Work from the Anhedral source repository
|
|
387
|
-
|
|
388
|
-
Inside the Anhedral repository, treat current source as higher authority than copied versions or prose. Read before exact reconstruction:
|
|
389
|
-
|
|
390
|
-
```text
|
|
391
|
-
src/architecture/modules.ts dependency closure and canonical module IDs
|
|
392
|
-
src/dependencies.ts exact versions, engines, and overrides
|
|
393
|
-
src/scaffold.ts root config, CI, docs, env inventory, manifest boundary
|
|
394
|
-
src/templates/shared.ts contracts, API client, and database
|
|
395
|
-
src/templates/api.ts Fastify source, providers, and tests
|
|
396
|
-
src/templates/web.ts Next.js source and conditional wiring
|
|
397
|
-
src/templates/mobile.ts Expo source and RevenueCat integration
|
|
398
|
-
src/templates/desktop.ts Electron/Vite source and security settings
|
|
399
|
-
src/templates/extension.ts WXT source, permissions, auth, and side panel
|
|
400
|
-
docs/output-tree-contract.md expected paths for representative plans
|
|
401
|
-
```
|
|
402
|
-
|
|
403
|
-
Render selected branches manually and replace project/display-name literals safely. Do not execute `dist/bin.js`, `bin/anhedral.js`, `scaffoldProject`, or template scaffold functions. Compare against the relevant output-tree contract, but never copy `demo/`: demos can contain installed artifacts or lag current templates. If source and this guide disagree, follow source and update this guide in the same change.
|
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
# Agent-run Anhedral provisioning
|
|
2
|
-
|
|
3
|
-
Use this checklist after the user asks a coding agent to create or provision an
|
|
4
|
-
Anhedral project. Keep one lead agent responsible for the plan, names, secrets,
|
|
5
|
-
and final verification.
|
|
6
|
-
|
|
7
|
-
## 1. Start with user inputs
|
|
8
|
-
|
|
9
|
-
Before running `anhedral new` or opening a provider dashboard, ask the user:
|
|
10
|
-
|
|
11
|
-
1. What is the project name? Derive one stable lowercase kebab-case resource
|
|
12
|
-
stem from it and show the proposed value.
|
|
13
|
-
2. Do they already own a custom domain for this product? If yes, record the
|
|
14
|
-
exact domain, registrar, current DNS provider, and whether production email
|
|
15
|
-
already uses it. If no, ask for the desired domain and obtain explicit
|
|
16
|
-
approval before any paid purchase.
|
|
17
|
-
3. Which surfaces and features do they want? If they want the complete product,
|
|
18
|
-
use every module. Otherwise record explicit modules.
|
|
19
|
-
4. Which provider organizations/teams should own Cloudflare, Vercel, GitHub,
|
|
20
|
-
Neon, Clerk, RevenueCat, Ably, Expo, Apple, Google Play, and Chrome Web Store
|
|
21
|
-
resources that apply to the selected modules?
|
|
22
|
-
5. Is this development, preview, or production? Never point a preview at live
|
|
23
|
-
users, billing, or production data without explicit direction.
|
|
24
|
-
|
|
25
|
-
Do not improvise names independently in provider dashboards. Maintain a small
|
|
26
|
-
resource ledger containing the project stem, display name, domain, selected
|
|
27
|
-
modules, provider team, resource name, hostname, environment, status, and next
|
|
28
|
-
user action. Never put credential values in the ledger.
|
|
29
|
-
|
|
30
|
-
## 2. Discover agent capabilities
|
|
31
|
-
|
|
32
|
-
Inspect the environment before planning execution:
|
|
33
|
-
|
|
34
|
-
- If Computer Use or an authenticated browser-control tool is available, use it
|
|
35
|
-
for provider dashboards after the user requests provisioning.
|
|
36
|
-
- If subagents are available, keep the lead agent in control and delegate only
|
|
37
|
-
bounded, independent work. Good tasks are reading generated documentation,
|
|
38
|
-
checking current DNS records without changing them, and producing a
|
|
39
|
-
selection-specific environment-variable inventory.
|
|
40
|
-
- Do not give subagents passwords, session cookies, secret values, or concurrent
|
|
41
|
-
control of the same browser/profile. Do not let two agents mutate DNS or the
|
|
42
|
-
same provider resource.
|
|
43
|
-
- If neither capability exists, use generated CLI commands and give the user
|
|
44
|
-
exact dashboard instructions for the remaining steps.
|
|
45
|
-
|
|
46
|
-
Recommended subagent sequence:
|
|
47
|
-
|
|
48
|
-
1. Lead: collect inputs, resolve modules, choose canonical names, and run init.
|
|
49
|
-
2. Documentation subagent: read the generated `README.md`, `PRODUCTION.md`, and
|
|
50
|
-
package-local `.env.example` files; return the provider/resource checklist.
|
|
51
|
-
3. DNS subagent: perform read-only registrar, nameserver, DNS, and hostname
|
|
52
|
-
collision checks; return existing records that must be preserved.
|
|
53
|
-
4. Verification subagent: after provisioning, run read-only domain, health,
|
|
54
|
-
Worker, and configuration checks. The lead performs or approves mutations.
|
|
55
|
-
|
|
56
|
-
If subagents are unavailable, perform the same phases serially. Their absence is
|
|
57
|
-
not a blocker.
|
|
58
|
-
|
|
59
|
-
## 3. Generate the project
|
|
60
|
-
|
|
61
|
-
Prefer the skill-guided CLI path:
|
|
62
|
-
|
|
63
|
-
```sh
|
|
64
|
-
pnpm dlx anhedral@latest new <project-name> <explicit-modules...> --toolchain stable
|
|
65
|
-
cd <project-name>
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
Omit module arguments only when the user chose the complete stack. Examples:
|
|
69
|
-
|
|
70
|
-
```sh
|
|
71
|
-
pnpm dlx anhedral@latest new acme --web --api --db --auth --toolchain stable
|
|
72
|
-
pnpm dlx anhedral@latest new acme desktop electron-updater --toolchain stable
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
Then:
|
|
76
|
-
|
|
77
|
-
1. Read the generated `README.md` and `PRODUCTION.md` completely.
|
|
78
|
-
2. Read `anhedral.json` and confirm the resolved module closure with the user.
|
|
79
|
-
3. Copy only package-local environment examples that exist.
|
|
80
|
-
4. Run `pnpm dlx anhedral@latest doctor`, `pnpm verify`, and `pnpm build` before
|
|
81
|
-
provisioning. Fix code-generation or build failures before creating cloud
|
|
82
|
-
resources.
|
|
83
|
-
|
|
84
|
-
## 4. Authentication and secret boundaries
|
|
85
|
-
|
|
86
|
-
Computer Use may navigate dashboards, fill non-secret settings, create approved
|
|
87
|
-
resources, deploy, configure DNS, and verify results. Apply these hard stops:
|
|
88
|
-
|
|
89
|
-
- Stop at every sign-in, password, passkey, MFA, CAPTCHA, device-approval, or
|
|
90
|
-
provider-consent boundary. Tell the user which provider is requesting access
|
|
91
|
-
and wait for them to complete it. Resume only after they say it is complete.
|
|
92
|
-
- Stop immediately before a paid purchase, registrar transfer, destructive
|
|
93
|
-
replacement, production release, store submission, or other consequential
|
|
94
|
-
final confirmation. Show the exact action, target, and cost/impact and obtain
|
|
95
|
-
approval.
|
|
96
|
-
- Stop at the final **Create**, **Generate**, **Reveal**, or **Rotate secret**
|
|
97
|
-
action. Tell the user the exact button to click, exact variable name, and exact
|
|
98
|
-
local uncommitted environment file to receive the value. The user must paste
|
|
99
|
-
it directly into that file or the provider's secret field, never into chat.
|
|
100
|
-
- Never read a populated `.env` file back into tool output, screenshots, logs,
|
|
101
|
-
the resource ledger, or a subagent message. Validate names and presence with a
|
|
102
|
-
redacting parser or the generated application checks.
|
|
103
|
-
- Public identifiers such as publishable keys, project IDs, account IDs, bucket
|
|
104
|
-
names, and hostnames may be recorded where their generated examples expect
|
|
105
|
-
them. Treat any provider value marked secret as secret even if it appears in a
|
|
106
|
-
browser page.
|
|
107
|
-
|
|
108
|
-
When the user finishes a secret step, ask only for confirmation such as
|
|
109
|
-
"`CLERK_SECRET_KEY` is saved in `apps/api/.env`". Do not ask them to repeat the
|
|
110
|
-
value. Mirror production secrets into Vercel or another deployment provider by
|
|
111
|
-
having the user paste into that provider's protected environment-variable UI,
|
|
112
|
-
or by using an approved secret-input flow that never prints the value.
|
|
113
|
-
|
|
114
|
-
## 5. Domain foundation
|
|
115
|
-
|
|
116
|
-
Use Cloudflare as authoritative DNS and Vercel as the web/API runtime. A domain
|
|
117
|
-
can remain registered at GoDaddy; changing nameservers is not a registrar
|
|
118
|
-
transfer.
|
|
119
|
-
|
|
120
|
-
1. If the user has no domain, use Computer Use to search the approved registrar
|
|
121
|
-
(usually GoDaddy), select the exact domain, and fill registration settings.
|
|
122
|
-
Stop before the paid purchase confirmation. Ask the user to review price,
|
|
123
|
-
renewal terms, registrant, and organization ownership and submit it.
|
|
124
|
-
2. Inventory existing DNS before changing nameservers. Preserve MX, TXT, SPF,
|
|
125
|
-
DKIM, DMARC, verification, CAA, and application records. A domain with active
|
|
126
|
-
email requires an explicit preservation review.
|
|
127
|
-
3. Add the domain as a Cloudflare zone. Stop for Cloudflare authentication. Copy
|
|
128
|
-
the two assigned authoritative nameservers.
|
|
129
|
-
4. At the registrar, replace the authoritative nameservers with Cloudflare's
|
|
130
|
-
exact values. Disable conflicting registrar DNSSEC/DS records first when
|
|
131
|
-
required; wait until Cloudflare reports the zone **Active**, then enable
|
|
132
|
-
DNSSEC in Cloudflare and publish the requested DS record at the registrar.
|
|
133
|
-
5. Do not transfer registration unless the user separately requests it. A
|
|
134
|
-
transfer changes billing/registrar ownership and may be subject to locks.
|
|
135
|
-
|
|
136
|
-
Use distinct hostnames:
|
|
137
|
-
|
|
138
|
-
```text
|
|
139
|
-
app.example.com Vercel web/API custom domain
|
|
140
|
-
assets.example.com assets-private-proxy Worker Custom Domain
|
|
141
|
-
updates.example.com desktop-updater Worker Custom Domain
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
`app.example.com` is a Vercel project domain whose A/CNAME/TXT records are
|
|
145
|
-
managed in Cloudflare DNS. Add the domain to Vercel first, inspect the exact
|
|
146
|
-
records Vercel requests, then add those records in Cloudflare. Keep the Vercel
|
|
147
|
-
origin record DNS-only unless current Vercel guidance and the user's architecture
|
|
148
|
-
explicitly require another topology.
|
|
149
|
-
|
|
150
|
-
Worker hostnames are Cloudflare **Worker Custom Domains**, not CNAMEs to Vercel
|
|
151
|
-
or R2. Configure `custom_domain: true` in the generated Wrangler file and deploy;
|
|
152
|
-
Cloudflare creates the DNS record and certificate. Remove any conflicting A,
|
|
153
|
-
AAAA, or CNAME record before attaching the Worker hostname.
|
|
154
|
-
|
|
155
|
-
## 6. Provision selected providers
|
|
156
|
-
|
|
157
|
-
Follow the generated `PRODUCTION.md`; it is the selection-specific authority.
|
|
158
|
-
Use this dependency order so downstream configuration receives real URLs and
|
|
159
|
-
public identifiers:
|
|
160
|
-
|
|
161
|
-
1. **GitHub**: create or select the organization repository, review the initial
|
|
162
|
-
diff, and push. Stop before changing repository visibility or overwriting an
|
|
163
|
-
existing remote.
|
|
164
|
-
2. **Neon (`db`)**: create separate development/preview/production projects or
|
|
165
|
-
branches. At connection-string generation, stop and have the user save the
|
|
166
|
-
pooled URL as `DATABASE_URL` in `packages/db/.env`, `apps/api/.env` when
|
|
167
|
-
required, and the protected Vercel API environment.
|
|
168
|
-
3. **Clerk (`auth`)**: create development and production instances and configure
|
|
169
|
-
allowed origins, redirect URLs, and native/extension identifiers. Stop at key
|
|
170
|
-
generation/reveal. Put the secret key only in server environments and the
|
|
171
|
-
publishable key in each selected client's documented public variable.
|
|
172
|
-
4. **RevenueCat and Ably (`billing`)**: create projects/apps, entitlement,
|
|
173
|
-
products, webhook URL/secret, and Ably API key. Stop at every secret creation.
|
|
174
|
-
Keep RevenueCat secret and Ably API keys server-only; clients receive only
|
|
175
|
-
documented public SDK keys or scoped Ably tokens.
|
|
176
|
-
5. **Cloudflare R2 (`storage`)**: run the generated login, bucket, CORS, Worker
|
|
177
|
-
check, and Worker deploy commands. Keep R2 private and `r2.dev` disabled.
|
|
178
|
-
Stop when Cloudflare requests authentication or before creating S3/API token
|
|
179
|
-
secrets; have the user save them under the exact `R2_*` names. Attach
|
|
180
|
-
`assets.<domain>` as the generated Worker Custom Domain.
|
|
181
|
-
6. **Vercel (`web`/`api`)**: link/import the root repository, select the generated
|
|
182
|
-
Services configuration, populate Development/Preview/Production variables,
|
|
183
|
-
deploy, then add `app.<domain>`. Inspect Vercel's exact DNS requirements and
|
|
184
|
-
create them in Cloudflare DNS. Verify domain status and TLS after propagation.
|
|
185
|
-
7. **Electron updater (`electron-updater`)**: edit both generated
|
|
186
|
-
`updates.example.com` values, set the matching HTTPS origin in
|
|
187
|
-
`apps/desktop/electron-builder.env`, run
|
|
188
|
-
`pnpm desktop:updates:first-provision` exactly once, and verify the private R2 binding plus
|
|
189
|
-
Worker Custom Domain. Build/sign on each native OS and upload artifacts
|
|
190
|
-
before channel metadata with the generated publish command.
|
|
191
|
-
8. **Expo/EAS and stores (`mobile`)**: create/link the EAS project, configure
|
|
192
|
-
public build variables and signing credentials, and build internal releases.
|
|
193
|
-
Stop at Apple/Google sign-in, credential, paid membership, agreement, and
|
|
194
|
-
store-submission boundaries.
|
|
195
|
-
9. **Chrome Web Store (`extension`)**: configure a stable extension ID, test the
|
|
196
|
-
generated ZIP as trusted/unlisted, and complete listing/privacy fields. Stop
|
|
197
|
-
before developer registration payment and final store submission.
|
|
198
|
-
|
|
199
|
-
Create strong `CRON_SECRET` and webhook secrets through a password manager or a
|
|
200
|
-
local non-logging generator. The user places them directly into server and
|
|
201
|
-
deployment environments.
|
|
202
|
-
|
|
203
|
-
## 7. Verify and hand off
|
|
204
|
-
|
|
205
|
-
After configuration:
|
|
206
|
-
|
|
207
|
-
1. Run `pnpm verify`, `pnpm build`, and `anhedral doctor`.
|
|
208
|
-
2. Verify Vercel deployment health, custom-domain status, DNS answers, and TLS.
|
|
209
|
-
3. Verify every selected Worker accepts its intended GET/HEAD behavior, rejects
|
|
210
|
-
forbidden methods/hosts, and cannot expose or list the private bucket.
|
|
211
|
-
4. Verify database migration status, auth redirect/sign-out, billing webhook and
|
|
212
|
-
entitlement refresh, storage upload/read policy, and scheduled jobs as
|
|
213
|
-
selected.
|
|
214
|
-
5. Record resource names, URLs, provider teams, and remaining manual approvals.
|
|
215
|
-
Record no secrets.
|
|
216
|
-
6. Stop before production/store release and give the user a concise checklist of
|
|
217
|
-
the exact final buttons or approvals still required.
|
|
218
|
-
|
|
219
|
-
Do not claim completion while a dashboard is merely open, DNS is still pending,
|
|
220
|
-
TLS is unissued, an environment value is absent, or verification has not run.
|