create-raredays-app 0.1.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.
Files changed (158) hide show
  1. package/README.md +89 -0
  2. package/bin/index.js +1024 -0
  3. package/package.json +43 -0
  4. package/scaffold-fragments/billing/files/app/api/billing/webhook/route.ts +5 -0
  5. package/scaffold-fragments/billing/module.json +31 -0
  6. package/scaffold-fragments/billing/runtime/config.ts +8 -0
  7. package/scaffold-fragments/billing/runtime/exports.ts +6 -0
  8. package/scaffold-fragments/billing/runtime/imports.ts +6 -0
  9. package/scaffold-fragments/billing/runtime/ports.ts +3 -0
  10. package/scaffold-fragments/cms/module.json +29 -0
  11. package/scaffold-fragments/cms/runtime/config.ts +4 -0
  12. package/scaffold-fragments/cms/runtime/exports.ts +1 -0
  13. package/scaffold-fragments/cms/runtime/imports.ts +1 -0
  14. package/scaffold-fragments/email/module.json +30 -0
  15. package/scaffold-fragments/email/runtime/config.ts +1 -0
  16. package/scaffold-fragments/email/runtime/imports.ts +1 -0
  17. package/scaffold-fragments/email/runtime/ports.ts +1 -0
  18. package/scaffold-fragments/feature-flags/files/app/lib/flags.ts +48 -0
  19. package/scaffold-fragments/feature-flags/module.json +66 -0
  20. package/scaffold-fragments/i18n/files/messages/en-US.json +15 -0
  21. package/scaffold-fragments/i18n/module.json +9 -0
  22. package/scaffold-fragments/i18n/runtime/config.ts +7 -0
  23. package/scaffold-fragments/i18n/runtime/exports.ts +1 -0
  24. package/scaffold-fragments/i18n/runtime/imports.ts +2 -0
  25. package/scaffold-fragments/i18n/runtime/ports.ts +1 -0
  26. package/scaffold-fragments/identity/module.json +30 -0
  27. package/scaffold-fragments/identity/vendors/better-auth/files/app/api/auth/[...all]/route.ts +15 -0
  28. package/scaffold-fragments/identity/vendors/better-auth/files/app/lib/auth.ts +20 -0
  29. package/scaffold-fragments/jobs/module.json +12 -0
  30. package/scaffold-fragments/jobs/runtime/config.ts +4 -0
  31. package/scaffold-fragments/jobs/runtime/imports.ts +1 -0
  32. package/scaffold-fragments/jobs/runtime/ports.ts +1 -0
  33. package/scaffold-fragments/notifications/module.json +12 -0
  34. package/scaffold-fragments/notifications/runtime/config.ts +8 -0
  35. package/scaffold-fragments/notifications/runtime/imports.ts +5 -0
  36. package/scaffold-fragments/notifications/runtime/ports.ts +1 -0
  37. package/scaffold-fragments/organizations/module.json +12 -0
  38. package/scaffold-fragments/telemetry/module.json +43 -0
  39. package/scaffold-fragments/telemetry/runtime/config.ts +7 -0
  40. package/scaffold-fragments/telemetry/runtime/imports.ts +7 -0
  41. package/scaffold-fragments/telemetry/runtime/ports.ts +1 -0
  42. package/skillex/private/contribute.md +193 -0
  43. package/skillex/public/consumer.md +157 -0
  44. package/templates/client/.storybook/main.ts +77 -0
  45. package/templates/client/.storybook/preview.ts +12 -0
  46. package/templates/client/CLAUDE.md +50 -0
  47. package/templates/client/_claude/settings.json +107 -0
  48. package/templates/client/_github/PULL_REQUEST_TEMPLATE.md +19 -0
  49. package/templates/client/_github/dependabot.yml +48 -0
  50. package/templates/client/_github/workflows/ci.yml +104 -0
  51. package/templates/client/_gitignore +15 -0
  52. package/templates/client/_npmrc +1 -0
  53. package/templates/client/app/(app)/layout.tsx +49 -0
  54. package/templates/client/app/(marketing)/layout.tsx +21 -0
  55. package/templates/client/app/(marketing)/page.tsx +34 -0
  56. package/templates/client/app/api/backend/[...path]/route.ts +37 -0
  57. package/templates/client/app/api/dev/login/route.ts +14 -0
  58. package/templates/client/app/api/dev/logout/route.ts +18 -0
  59. package/templates/client/app/globals.css +22 -0
  60. package/templates/client/app/home-auth-controls.tsx +28 -0
  61. package/templates/client/app/layout.tsx +38 -0
  62. package/templates/client/app/lib/backend-client.ts +55 -0
  63. package/templates/client/app/lib/runtime.test.ts +38 -0
  64. package/templates/client/app/lib/runtime.ts +54 -0
  65. package/templates/client/app/protected/page.tsx +31 -0
  66. package/templates/client/app/theme.override.css +9 -0
  67. package/templates/client/instrumentation.ts +10 -0
  68. package/templates/client/mocks/browser.tsx +28 -0
  69. package/templates/client/mocks/handlers.ts +20 -0
  70. package/templates/client/mocks/node.ts +7 -0
  71. package/templates/client/next.config.ts +8 -0
  72. package/templates/client/oxfmt.config.ts +8 -0
  73. package/templates/client/oxlint.config.ts +8 -0
  74. package/templates/client/package.json +61 -0
  75. package/templates/client/postcss.config.mjs +1 -0
  76. package/templates/client/public/mockServiceWorker.js +349 -0
  77. package/templates/client/scripts/build-theme.mjs +18 -0
  78. package/templates/client/site.spec.ts +58 -0
  79. package/templates/client/skillex.json +12 -0
  80. package/templates/client/skills/repo.md +56 -0
  81. package/templates/client/stylelint.config.mjs +4 -0
  82. package/templates/client/tsconfig.json +11 -0
  83. package/templates/client/vitest.config.ts +27 -0
  84. package/templates/client/vitest.setup.ts +18 -0
  85. package/templates/full-stack/.storybook/main.ts +77 -0
  86. package/templates/full-stack/.storybook/preview.ts +12 -0
  87. package/templates/full-stack/CLAUDE.md +50 -0
  88. package/templates/full-stack/_claude/settings.json +107 -0
  89. package/templates/full-stack/_github/PULL_REQUEST_TEMPLATE.md +19 -0
  90. package/templates/full-stack/_github/dependabot.yml +57 -0
  91. package/templates/full-stack/_github/workflows/ci.yml +109 -0
  92. package/templates/full-stack/_github/workflows/db-check.yml +36 -0
  93. package/templates/full-stack/_github/workflows/db-migrate.yml +39 -0
  94. package/templates/full-stack/_gitignore +15 -0
  95. package/templates/full-stack/_npmrc +1 -0
  96. package/templates/full-stack/app/(app)/layout.tsx +53 -0
  97. package/templates/full-stack/app/(marketing)/layout.tsx +21 -0
  98. package/templates/full-stack/app/(marketing)/page.tsx +38 -0
  99. package/templates/full-stack/app/api/dev/login/route.ts +14 -0
  100. package/templates/full-stack/app/api/dev/logout/route.ts +18 -0
  101. package/templates/full-stack/app/api/widgets/route.ts +10 -0
  102. package/templates/full-stack/app/demo/widgets/page.tsx +86 -0
  103. package/templates/full-stack/app/globals.css +22 -0
  104. package/templates/full-stack/app/home-auth-controls.tsx +28 -0
  105. package/templates/full-stack/app/layout.tsx +38 -0
  106. package/templates/full-stack/app/lib/runtime.test.ts +38 -0
  107. package/templates/full-stack/app/lib/runtime.ts +54 -0
  108. package/templates/full-stack/app/protected/page.tsx +31 -0
  109. package/templates/full-stack/app/theme.override.css +9 -0
  110. package/templates/full-stack/db/check.ts +46 -0
  111. package/templates/full-stack/db/index.ts +109 -0
  112. package/templates/full-stack/db/migrate.ts +66 -0
  113. package/templates/full-stack/db/migrations/.gitkeep +0 -0
  114. package/templates/full-stack/db/schema.ts +20 -0
  115. package/templates/full-stack/drizzle.config.ts +16 -0
  116. package/templates/full-stack/instrumentation.ts +10 -0
  117. package/templates/full-stack/mocks/browser.tsx +28 -0
  118. package/templates/full-stack/mocks/handlers.ts +34 -0
  119. package/templates/full-stack/mocks/node.ts +7 -0
  120. package/templates/full-stack/next.config.ts +8 -0
  121. package/templates/full-stack/oxfmt.config.ts +8 -0
  122. package/templates/full-stack/oxlint.config.ts +8 -0
  123. package/templates/full-stack/package.json +72 -0
  124. package/templates/full-stack/postcss.config.mjs +1 -0
  125. package/templates/full-stack/public/mockServiceWorker.js +349 -0
  126. package/templates/full-stack/scripts/build-theme.mjs +18 -0
  127. package/templates/full-stack/site.spec.ts +58 -0
  128. package/templates/full-stack/skillex.json +12 -0
  129. package/templates/full-stack/skills/repo.md +56 -0
  130. package/templates/full-stack/stylelint.config.mjs +4 -0
  131. package/templates/full-stack/tsconfig.json +11 -0
  132. package/templates/full-stack/vitest.config.ts +42 -0
  133. package/templates/full-stack/vitest.setup.ts +18 -0
  134. package/templates/static/.storybook/main.ts +77 -0
  135. package/templates/static/.storybook/preview.ts +12 -0
  136. package/templates/static/CLAUDE.md +50 -0
  137. package/templates/static/_claude/settings.json +107 -0
  138. package/templates/static/_github/PULL_REQUEST_TEMPLATE.md +18 -0
  139. package/templates/static/_github/dependabot.yml +43 -0
  140. package/templates/static/_github/workflows/ci.yml +91 -0
  141. package/templates/static/_gitignore +15 -0
  142. package/templates/static/_npmrc +1 -0
  143. package/templates/static/app/(marketing)/layout.tsx +21 -0
  144. package/templates/static/app/(marketing)/page.tsx +17 -0
  145. package/templates/static/app/globals.css +22 -0
  146. package/templates/static/app/layout.tsx +24 -0
  147. package/templates/static/app/theme.override.css +9 -0
  148. package/templates/static/next.config.ts +19 -0
  149. package/templates/static/oxfmt.config.ts +8 -0
  150. package/templates/static/oxlint.config.ts +8 -0
  151. package/templates/static/package.json +53 -0
  152. package/templates/static/postcss.config.mjs +1 -0
  153. package/templates/static/scripts/build-theme.mjs +18 -0
  154. package/templates/static/site.spec.ts +58 -0
  155. package/templates/static/skillex.json +12 -0
  156. package/templates/static/skills/repo.md +56 -0
  157. package/templates/static/stylelint.config.mjs +4 -0
  158. package/templates/static/tsconfig.json +11 -0
@@ -0,0 +1,193 @@
1
+ ---
2
+ name: "Contributing to create-raredays-app"
3
+ description: Deep guide to the app scaffolder — CLI flow, CRDA placeholder tokens, composeRuntime/composeHandlers internals, template file trees, customiseSiteSpec regex, fragment loading, env generation, --dev flag.
4
+ topics: [scaffolding, contributing]
5
+ tags: [scaffolding, cli, contributing]
6
+ ---
7
+
8
+ # Contributing to create-raredays-app
9
+
10
+ Location: `workspaces/app/cli/create-raredays-app/`
11
+
12
+ ## CLI Entry (`bin/index.js`)
13
+
14
+ Plain Node.js script (no build step). Uses `parseArgs` for flags:
15
+
16
+ | Flag | Default | Purpose |
17
+ | -------------------- | -------------- | ------------------------------------------- |
18
+ | `--template <name>` | `"full-stack"` | Template to scaffold |
19
+ | `--modules <list>` | — | Comma-separated module keys |
20
+ | `--vendors <list>` | — | Comma-separated `module:vendor` pairs |
21
+ | `--remote-url <url>` | — | Git remote origin URL |
22
+ | `--no-git` | — | Skip git init |
23
+ | `--no-install` | — | Skip pnpm install |
24
+ | `--dev` | — | Rewrite `@raredays/*` deps to `workspace:*` |
25
+
26
+ ### Interactive Mode (no positional arg)
27
+
28
+ Prompts in order via `@clack/prompts`:
29
+
30
+ 1. Project name (validates non-empty, no existing dir)
31
+ 2. Template selection: `static` | `client` | `full-stack`
32
+ 3. Display name (defaults to project name)
33
+ 4. Canonical domain (validates `/^[a-z0-9.-]+\.[a-z]{2,}$/i`)
34
+ 5. Brand primary color (hex, defaults `#10b981`, validates `/^#[0-9a-fA-F]{3,8}$/`)
35
+ 6. Module selection (multiselect, filtered by template's `templates` field)
36
+ 7. Vendor selection per module (format: `billing:stripe`)
37
+ 8. Git remote URL (optional)
38
+ 9. Init git repo (default: true)
39
+ 10. Run `pnpm install` (default: true)
40
+
41
+ ### Scaffold Flow
42
+
43
+ 1. Error if target dir exists
44
+ 2. Copy `templates/{template}/` recursively
45
+ 3. Rename stub files: `_gitignore` → `.gitignore`, `_npmrc` → `.npmrc`
46
+ 4. Derive slug: trim, lowercase, replace `[^a-z0-9]+` with `-`, strip leading/trailing `-`
47
+ 5. Substitute `__SLUG__` in `site.spec.ts`
48
+ 6. Apply `customiseSiteSpec()` regex replacements
49
+ 7. Load fragments, merge deps, copy fragment `files/` dirs, compose runtime
50
+ 8. Compose mock handlers if template ≠ `static`
51
+ 9. Merge deps into `package.json`, apply `--dev` rewrite if flagged
52
+ 10. Write `.env.example` if any env vars collected
53
+ 11. `git init --quiet --initial-branch=main` (+ remote if specified)
54
+ 12. `pnpm install` with `stdio: "inherit"`
55
+
56
+ ## CRDA Placeholder Tokens
57
+
58
+ ### In `app/lib/runtime.ts`:
59
+
60
+ | Token (exact string) | Replaced With | Empty Behavior |
61
+ | -------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------- |
62
+ | `// CRDA:imports` | Fragment `runtime/imports.ts` concatenated with newlines | Kept as-is |
63
+ | `// CRDA:config` | Fragment `runtime/config.ts` concatenated with double newlines | Comment: `// CRDA:config (no additional modules wired)` |
64
+ | ` // CRDA:ports` | Fragment `runtime/ports.ts` concatenated, trimmed (note 2-space indent) | Kept as-is |
65
+ | `// CRDA:exports` | Fragment `runtime/exports.ts` concatenated with double newlines | Kept as-is |
66
+
67
+ ### In `mocks/handlers.ts`:
68
+
69
+ | Token (exact string) | Replaced With |
70
+ | ------------------------ | ------------------------------------------------------- |
71
+ | `// CRDA:mocks-imports` | Import statements: `import { <named> } from <package>;` |
72
+ | ` // CRDA:mocks-spread` | Spread entries: ` <named>,` (2-space indent) |
73
+
74
+ ## composeRuntime(source, fragments)
75
+
76
+ Iterates fragments in order, collects all slot code per token, replaces all four tokens in a single pass.
77
+
78
+ ## composeHandlers(source, vendorMocks)
79
+
80
+ Builds import list + spread list from vendor mock metadata, replaces both tokens.
81
+
82
+ ## customiseSiteSpec(filePath, opts)
83
+
84
+ Three regex replacements on `site.spec.ts`:
85
+
86
+ 1. Display name: `/name:\s*"[^"]*"/` → `name: ${JSON.stringify(opts.displayName)}`
87
+ 2. Canonical domain: `/canonicalDomain:\s*"[^"]*/` → `canonicalDomain: ${JSON.stringify(opts.canonicalDomain)}`
88
+ 3. Brand primary: `/primary:\s*"#[0-9a-fA-F]+"/` → `primary: ${JSON.stringify(opts.brandPrimary)}`
89
+
90
+ `__SLUG__` token is a separate find-replace earlier in the flow.
91
+
92
+ ## Template File Trees
93
+
94
+ ### `full-stack` (39 files)
95
+
96
+ ```
97
+ app/api/dev/{login,logout}/route.ts, app/api/widgets/route.ts
98
+ app/demo/widgets/page.tsx, app/protected/page.tsx
99
+ app/globals.css, app/home-auth-controls.tsx, app/layout.tsx, app/page.tsx
100
+ app/lib/runtime.ts (CRDA placeholders), app/lib/runtime.test.ts
101
+ app/theme.override.css
102
+ db/index.ts, db/schema.ts, drizzle.config.ts
103
+ instrumentation.ts
104
+ mocks/browser.tsx, mocks/handlers.ts (CRDA placeholders), mocks/node.ts
105
+ next.config.ts, oxfmt.config.ts, oxlint.config.ts, package.json
106
+ postcss.config.mjs, scripts/build-theme.mjs, site.spec.ts
107
+ stylelint.config.mjs, tsconfig.json, vitest.config.ts, vitest.setup.ts
108
+ ```
109
+
110
+ ### `client` (28 files)
111
+
112
+ Same as full-stack minus `db/`, `drizzle.config.ts`, `app/api/widgets/`. Adds `app/api/backend/[...path]/route.ts` for upstream proxying and `app/lib/backend-client.ts`.
113
+
114
+ ### `static` (17 files)
115
+
116
+ Minimal: no `app/lib/`, no `app/api/`, no `mocks/`, no `instrumentation.ts`, no tests, no DB. Just layout, page, styling, and build config.
117
+
118
+ ## Fragment Structure
119
+
120
+ ```
121
+ scaffold-fragments/{key}/
122
+ ├── module.json # Manifest
123
+ ├── runtime/
124
+ │ ├── imports.ts # Injected at // CRDA:imports
125
+ │ ├── config.ts # Injected at // CRDA:config
126
+ │ ├── ports.ts # Injected at // CRDA:ports
127
+ │ └── exports.ts # Injected at // CRDA:exports
128
+ └── files/ # Overlay into target app
129
+ ```
130
+
131
+ ### module.json Schema
132
+
133
+ ```json
134
+ {
135
+ "key": "billing",
136
+ "label": "Billing (subscriptions + webhooks)",
137
+ "description": "...",
138
+ "deps": { "@raredays/billing": "0.0.1" },
139
+ "vendors": [
140
+ {
141
+ "key": "stripe",
142
+ "label": "Stripe",
143
+ "deps": { "@raredays/billing-stripe": "0.0.1" },
144
+ "env": ["STRIPE_SECRET_KEY", "STRIPE_WEBHOOK_SECRET"],
145
+ "mocks": { "package": "@raredays/billing-stripe/mocks", "named": "stripeMocks" }
146
+ }
147
+ ],
148
+ "templates": ["full-stack"]
149
+ }
150
+ ```
151
+
152
+ ### Available Fragments
153
+
154
+ | Fragment | Templates | Vendors | Env Vars |
155
+ | --------------- | ------------------ | ------------- | -------------------------------------------- |
156
+ | `billing` | full-stack | Stripe | `STRIPE_SECRET_KEY`, `STRIPE_WEBHOOK_SECRET` |
157
+ | `email` | full-stack | Resend | `RESEND_API_KEY` |
158
+ | `jobs` | full-stack | None | — |
159
+ | `notifications` | full-stack | None | — |
160
+ | `telemetry` | full-stack, client | Sentry, Axiom | `SENTRY_DSN`, `AXIOM_TOKEN`, `AXIOM_DATASET` |
161
+
162
+ ## .env.example Generation
163
+
164
+ Only written if `envVars.length > 0`. Format:
165
+
166
+ ```
167
+ # Environment variables required by the modules you selected.
168
+ # Copy to .env.local and fill in real values before running.
169
+
170
+ # Database (uncomment when wiring Drizzle queries)
171
+ # DATABASE_URL=
172
+
173
+ STRIPE_SECRET_KEY=
174
+ STRIPE_WEBHOOK_SECRET=
175
+ ```
176
+
177
+ ## --dev Flag
178
+
179
+ Rewrites every `@raredays/*` in both `dependencies` and `devDependencies` to `workspace:*`. Used for in-repo dogfooding (playground scaffolds).
180
+
181
+ ## Testing
182
+
183
+ No unit tests. Validated by:
184
+
185
+ - E2E scenarios in `/e2e/` (scaffold → build → serve → test)
186
+ - Manual: `pnpm playground:reset && pnpm playground`
187
+
188
+ ## Build and Test
189
+
190
+ ```sh
191
+ # No build step needed — plain Node.js script
192
+ pnpm --filter create-raredays-app test # if tests exist
193
+ ```
@@ -0,0 +1,157 @@
1
+ ---
2
+ name: "Consuming create-raredays-app"
3
+ description: How to scaffold new apps — interactive prompts sequence, CLI flags, three templates (full-stack/client/static) with output files, five available modules with vendor options, --dev flag for monorepo dogfooding.
4
+ topics: [scaffolding, consuming]
5
+ tags: [scaffolding, cli, consuming]
6
+ ---
7
+
8
+ # Consuming create-raredays-app
9
+
10
+ ## Interactive Mode
11
+
12
+ ```sh
13
+ pnpm create raredays-app
14
+ ```
15
+
16
+ Prompts in order:
17
+
18
+ 1. **Project name** — directory name and package slug (kebab-case, 1–64 chars)
19
+ 2. **Template** — `full-stack`, `client`, or `static`
20
+ 3. **Display name** — human-readable (defaults to project name)
21
+ 4. **Canonical domain** — optional, hostname only (e.g., `example.com`)
22
+ 5. **Brand primary color** — hex value (defaults to `#10b981`)
23
+ 6. **Modules** — multiselect (not shown for `static`)
24
+ 7. **Vendors** — multiselect for selected modules
25
+ 8. **Git remote URL** — optional
26
+ 9. **Initialize git?** — default yes
27
+ 10. **Run pnpm install?** — default yes
28
+
29
+ ## Non-Interactive Mode
30
+
31
+ ```sh
32
+ pnpm create raredays-app my-app \
33
+ --template full-stack \
34
+ --modules billing,email,telemetry \
35
+ --vendors billing:stripe,email:resend,telemetry:sentry,telemetry:axiom
36
+ ```
37
+
38
+ ## CLI Flags
39
+
40
+ | Flag | Description |
41
+ | -------------- | --------------------------------------------------------------------- |
42
+ | `--template` | `full-stack` (default), `client`, or `static` |
43
+ | `--modules` | Comma-separated module keys |
44
+ | `--vendors` | Comma-separated `MODULE:VENDOR` selectors |
45
+ | `--remote-url` | Git remote origin URL |
46
+ | `--no-git` | Skip git initialization |
47
+ | `--no-install` | Skip `pnpm install` |
48
+ | `--dev` | Rewrite all `@raredays/*` deps to `workspace:*` (monorepo dogfooding) |
49
+
50
+ ## Templates
51
+
52
+ ### full-stack
53
+
54
+ Complete Next.js + Drizzle ORM + PostgreSQL + framework modules.
55
+
56
+ Key output files:
57
+
58
+ - `app/lib/runtime.ts` — composition root with module ports wired
59
+ - `db/schema.ts` + `db/index.ts` — Drizzle schema and client
60
+ - `drizzle.config.ts` — Drizzle Kit configuration
61
+ - `mocks/handlers.ts` — MSW handlers composed from vendor mocks
62
+ - `site.spec.ts` — SiteSpec with your branding choices
63
+ - `app/api/widgets/route.ts` — demo API endpoint
64
+ - `instrumentation.ts` — telemetry instrumentation hook
65
+
66
+ All five modules available. Scripts include `db:generate`, `db:migrate`, `db:studio`.
67
+
68
+ ### client
69
+
70
+ Next.js BFF + SPA that proxies to an external backend.
71
+
72
+ Key output files:
73
+
74
+ - `app/lib/runtime.ts` — composition root (identity + mocks)
75
+ - `app/api/backend/[...path]/route.ts` — backend proxy
76
+ - `app/api/dev/login|logout/route.ts` — dev auth routes
77
+ - `mocks/handlers.ts` — MSW handlers
78
+
79
+ Only telemetry module available. No database.
80
+
81
+ ### static
82
+
83
+ CDN/edge-deployable static site. No modules, no database, no API routes.
84
+
85
+ Key output files:
86
+
87
+ - `site.spec.ts` — SiteSpec configuration
88
+ - `next.config.ts` — static export config
89
+
90
+ ## Available Modules
91
+
92
+ | Module | Label | Template | Vendor Options |
93
+ | --------------- | --------------------------- | ------------------ | -------------- |
94
+ | `billing` | Subscriptions + webhooks | full-stack | Stripe |
95
+ | `cms` | Headless CMS + rich text | full-stack, client | Hygraph |
96
+ | `email` | Transactional email | full-stack | Resend |
97
+ | `identity` | Auth, sessions, orgs, roles | full-stack, client | Better Auth |
98
+ | `jobs` | Background jobs | full-stack | — (in-memory) |
99
+ | `notifications` | Multi-channel notifications | full-stack | — (in-memory) |
100
+ | `telemetry` | Logging, errors, metrics | full-stack, client | Sentry, Axiom |
101
+
102
+ Identity is always wired with an in-memory dev provider (the template hard-codes
103
+ `createInMemoryProvider` so `pnpm dev` works out of the box). Selecting
104
+ `--modules identity --vendors identity:better-auth` adds the production adapter
105
+ package, env vars, mock handlers, and a Next.js auth route stub — you then
106
+ manually replace the in-memory provider in `app/lib/runtime.ts` with
107
+ `createBetterAuthProvider({ auth })`.
108
+
109
+ ### Vendor Environment Variables
110
+
111
+ When vendors are selected, `.env.example` is generated:
112
+
113
+ ```sh
114
+ # billing (stripe)
115
+ STRIPE_SECRET_KEY=
116
+ STRIPE_WEBHOOK_SECRET=
117
+
118
+ # cms (hygraph)
119
+ HYGRAPH_ENDPOINT=
120
+ HYGRAPH_TOKEN=
121
+
122
+ # email (resend)
123
+ RESEND_API_KEY=
124
+
125
+ # identity (better-auth)
126
+ BETTER_AUTH_SECRET=
127
+ BETTER_AUTH_URL=
128
+
129
+ # telemetry (sentry)
130
+ SENTRY_DSN=
131
+
132
+ # telemetry (axiom)
133
+ AXIOM_TOKEN=
134
+ AXIOM_DATASET=
135
+ ```
136
+
137
+ ## What You Get
138
+
139
+ A fully configured project with:
140
+
141
+ - `site.spec.ts` — SiteSpec with your name, domain, and brand color substituted
142
+ - `app/lib/runtime.ts` — composition root with selected modules wired via slot injection
143
+ - `app/theme.css` — generated `@theme` overrides from branding config
144
+ - `next.config.ts` — wraps `withRaredays()`
145
+ - `postcss.config.mjs` — re-exports from `@raredays/style/postcss`
146
+ - `mocks/` — MSW setup with vendor-specific handlers (client/full-stack)
147
+ - `.env.example` — required env vars for selected vendors
148
+
149
+ ## After Scaffolding
150
+
151
+ ```sh
152
+ cd my-app
153
+ pnpm install # if --no-install was used
154
+ cp .env.example .env.local # if modules with env vars
155
+ pnpm dev # standard dev server
156
+ pnpm dev:mocks # dev with MSW intercepting API calls
157
+ ```
@@ -0,0 +1,77 @@
1
+ import { dirname, resolve } from "node:path";
2
+ import { createRequire } from "node:module";
3
+ import type { StorybookConfig } from "@storybook/react-vite";
4
+ import react from "@vitejs/plugin-react";
5
+ import tailwindcss from "@tailwindcss/vite";
6
+
7
+ // Storybook config for the scaffolded app.
8
+ //
9
+ // Loads stories from two sources, namespaced separately:
10
+ //
11
+ // App/<...> → ../app/**/*.stories.@(ts|tsx)
12
+ // ../src/**/*.stories.@(ts|tsx)
13
+ //
14
+ // @raredays/components/<...> → resolved-package-root/dist/**/*.stories.js
15
+ //
16
+ // Framework stories are pre-compiled by the framework's build (vite
17
+ // `preserveModules: true`) — `@/` aliases are already resolved, so
18
+ // the consumer's Vite doesn't need any path-alias config to load
19
+ // them. To add more framework packages with stories, add a matching
20
+ // stories[] entry pointing at their dist/.
21
+ //
22
+ // We resolve `@raredays/components` via Node's module resolver rather
23
+ // than a literal `../node_modules/...` path because pnpm hoists
24
+ // workspace dependencies to the workspace root — under a workspace
25
+ // install the package may not exist in the app's own node_modules at
26
+ // all, and the literal path silently matches zero stories.
27
+ //
28
+ // `require.resolve("@raredays/components")` returns the package's
29
+ // main entry (`dist/index.js`); we walk up to the package root so the
30
+ // glob can target `dist/**/*.stories.js`. We avoid resolving
31
+ // `@raredays/components/package.json` directly because the package's
32
+ // `exports` map does not expose `./package.json`.
33
+ //
34
+ // Stories render in THIS Storybook's iframe — they inherit the
35
+ // consumer's theme.override.css, RaredaysProvider, fonts, and any
36
+ // other context loaded in .storybook/preview.ts. That's the whole
37
+ // point: see how framework components look with YOUR theme applied,
38
+ // not a generic one.
39
+ const require = createRequire(import.meta.url);
40
+ const componentsRoot = dirname(dirname(require.resolve("@raredays/components")));
41
+
42
+ const config: StorybookConfig = {
43
+ framework: "@storybook/react-vite",
44
+ stories: [
45
+ {
46
+ directory: "../app",
47
+ files: "**/*.stories.@(ts|tsx)",
48
+ titlePrefix: "App",
49
+ },
50
+ {
51
+ directory: "../src",
52
+ files: "**/*.stories.@(ts|tsx)",
53
+ titlePrefix: "App",
54
+ },
55
+ {
56
+ directory: `${componentsRoot}/dist`,
57
+ files: "**/*.stories.js",
58
+ titlePrefix: "@raredays/components",
59
+ },
60
+ ],
61
+ addons: [],
62
+ typescript: {
63
+ check: false,
64
+ reactDocgen: "react-docgen-typescript",
65
+ },
66
+ viteFinal: async (viteConfig) => {
67
+ viteConfig.plugins = [...(viteConfig.plugins ?? []), react(), tailwindcss()];
68
+ viteConfig.resolve ??= {};
69
+ viteConfig.resolve.alias = {
70
+ ...(viteConfig.resolve.alias as Record<string, string>),
71
+ "@": resolve(import.meta.dirname, "../app"),
72
+ };
73
+ return viteConfig;
74
+ },
75
+ };
76
+
77
+ export default config;
@@ -0,0 +1,12 @@
1
+ import type { Preview } from "@storybook/react-vite";
2
+ import "../app/globals.css";
3
+
4
+ const preview: Preview = {
5
+ parameters: {
6
+ controls: {
7
+ matchers: { color: /(background|color)$/i, date: /Date$/i },
8
+ },
9
+ },
10
+ };
11
+
12
+ export default preview;
@@ -0,0 +1,50 @@
1
+ # Project conventions
2
+
3
+ Always read `AGENTS.md` first — it lists every skill available via `@raredays/*`
4
+ packages. Use them before authoring components, modules, or providers from
5
+ scratch.
6
+
7
+ ## Quick orientation
8
+
9
+ This app was scaffolded with `create-raredays-app` and consumes the RareDays
10
+ framework via `@raredays/*` workspace deps. Conventions:
11
+
12
+ - **Components**: prefer composing from `@raredays/components` (shadcn-flavored,
13
+ Tailwind v4, browser-tested with vitest+playwright). When you do author new
14
+ components, follow the patterns documented in
15
+ `pnpm exec skillex query --package @raredays/components`.
16
+ - **Server logic**: use `@raredays/core`'s provider/port pattern. Identity,
17
+ billing, notifications, CMS, etc. are wired in `app/lib/runtime.ts` —
18
+ edit there to swap providers, don't sprinkle SDK calls through the codebase.
19
+ - **Tests**: vitest. Browser-mode tests use the `.browser.test.tsx` suffix and
20
+ run separately from node-mode tests. Conformance harnesses live in each
21
+ module's `src/testing/` directory and exercise every provider against the
22
+ same invariants.
23
+ - **Lint/format**: `pnpm check` runs lint + format-check + style + typecheck.
24
+ Pre-commit hook (if you add one) should call this.
25
+
26
+ ## Don't
27
+
28
+ - Re-implement primitives that already exist in `@raredays/*`. Always query
29
+ skillex first.
30
+ - Edit code in `node_modules/@raredays/*` directly. If a provider needs
31
+ changing, file a framework issue or PR upstream.
32
+ - Commit code with failing lint/format/style/test. `pnpm check` should be
33
+ green before every commit.
34
+
35
+ ## Skillex
36
+
37
+ Skills from installed `@raredays/*` packages are auto-discovered. To refresh
38
+ the index after adding a new dependency:
39
+
40
+ ```sh
41
+ pnpm exec skillex refresh
42
+ ```
43
+
44
+ Query patterns:
45
+
46
+ ```sh
47
+ pnpm exec skillex query --search "<concepts>"
48
+ pnpm exec skillex query --package "@raredays/components"
49
+ pnpm exec skillex query --topic identity
50
+ ```
@@ -0,0 +1,107 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/claude-code-settings.json",
3
+ "_comment": "Permissive defaults — agents can iterate without prompting on routine dev actions. Anything that mutates shared/remote state still requires explicit approval.",
4
+ "permissions": {
5
+ "allow": [
6
+ "Bash(pnpm install*)",
7
+ "Bash(pnpm run *)",
8
+ "Bash(pnpm exec *)",
9
+ "Bash(pnpm dev*)",
10
+ "Bash(pnpm build*)",
11
+ "Bash(pnpm test*)",
12
+ "Bash(pnpm lint*)",
13
+ "Bash(pnpm format*)",
14
+ "Bash(pnpm style*)",
15
+ "Bash(pnpm check*)",
16
+ "Bash(pnpm typecheck*)",
17
+ "Bash(pnpm db:*)",
18
+ "Bash(pnpm theme:build*)",
19
+ "Bash(pnpm dlx *)",
20
+ "Bash(pnpm --filter *)",
21
+ "Bash(pnpm -w *)",
22
+ "Bash(node *)",
23
+ "Bash(npx *)",
24
+ "Bash(git status*)",
25
+ "Bash(git diff*)",
26
+ "Bash(git log*)",
27
+ "Bash(git show*)",
28
+ "Bash(git branch*)",
29
+ "Bash(git ls-files*)",
30
+ "Bash(git ls-tree*)",
31
+ "Bash(git stash*)",
32
+ "Bash(git add*)",
33
+ "Bash(git checkout *)",
34
+ "Bash(git switch *)",
35
+ "Bash(git restore *)",
36
+ "Bash(git rev-parse*)",
37
+ "Bash(git remote -v)",
38
+ "Bash(git fetch*)",
39
+ "Bash(git pull --ff-only*)",
40
+ "Bash(mkdir *)",
41
+ "Bash(touch *)",
42
+ "Bash(ls *)",
43
+ "Bash(find *)",
44
+ "Bash(grep *)",
45
+ "Bash(rg *)",
46
+ "Bash(cat *)",
47
+ "Bash(head *)",
48
+ "Bash(tail *)",
49
+ "Bash(wc *)",
50
+ "Bash(sort *)",
51
+ "Bash(uniq *)",
52
+ "Bash(jq *)",
53
+ "Bash(curl http://localhost*)",
54
+ "Bash(curl http://127.0.0.1*)",
55
+ "Bash(pnpm exec skillex*)",
56
+ "Bash(pnpm exec playwright *)",
57
+ "Bash(pnpm exec vitest*)",
58
+ "Bash(pnpm exec drizzle-kit*)",
59
+ "Bash(pnpm exec next *)",
60
+ "Bash(pnpm exec tsc*)",
61
+ "Bash(pnpm exec oxlint*)",
62
+ "Bash(pnpm exec oxfmt*)",
63
+ "Bash(pnpm exec stylelint*)",
64
+ "Read",
65
+ "Edit",
66
+ "Write",
67
+ "Glob",
68
+ "Grep",
69
+ "WebFetch"
70
+ ],
71
+ "ask": [
72
+ "Bash(git commit*)",
73
+ "Bash(git push*)",
74
+ "Bash(git merge*)",
75
+ "Bash(git rebase*)",
76
+ "Bash(git reset*)",
77
+ "Bash(gh issue*)",
78
+ "Bash(gh pr*)",
79
+ "Bash(gh release*)",
80
+ "Bash(gh workflow*)",
81
+ "Bash(pnpm publish*)",
82
+ "Bash(pnpm nx release*)",
83
+ "Bash(npm publish*)"
84
+ ],
85
+ "deny": [
86
+ "Bash(git push --force*)",
87
+ "Bash(git push -f *)",
88
+ "Bash(git push * --force*)",
89
+ "Bash(rm -rf /*)",
90
+ "Bash(rm -rf ~)",
91
+ "Bash(rm -rf $HOME*)",
92
+ "Bash(cat .env*)",
93
+ "Bash(cat *.env)",
94
+ "Bash(cat *.env.local)",
95
+ "Bash(cat *.env.production)",
96
+ "Bash(printenv)",
97
+ "Bash(env)",
98
+ "Read(./.env)",
99
+ "Read(./.env.local)",
100
+ "Read(./.env.production)",
101
+ "Read(./.env.*)",
102
+ "Read(./**/.env)",
103
+ "Read(./**/.env.local)",
104
+ "Read(./**/.env.production)"
105
+ ]
106
+ }
107
+ }
@@ -0,0 +1,19 @@
1
+ <!-- Brief description of what this PR does and why. -->
2
+
3
+ ## Summary
4
+
5
+ -
6
+ -
7
+
8
+ ## Verification
9
+
10
+ - [ ] `pnpm lint` passes
11
+ - [ ] `pnpm format:check` passes
12
+ - [ ] `pnpm style` passes
13
+ - [ ] `pnpm typecheck` passes
14
+ - [ ] `pnpm test` passes
15
+ - [ ] `pnpm build` succeeds
16
+
17
+ ## Notes
18
+
19
+ <!-- Anything reviewers should know. -->
@@ -0,0 +1,48 @@
1
+ version: 2
2
+
3
+ updates:
4
+ - package-ecosystem: npm
5
+ directory: /
6
+ schedule:
7
+ interval: weekly
8
+ open-pull-requests-limit: 5
9
+ groups:
10
+ raredays:
11
+ patterns:
12
+ - "@raredays/*"
13
+ react:
14
+ patterns:
15
+ - react
16
+ - react-dom
17
+ - "@types/react"
18
+ - "@types/react-dom"
19
+ next:
20
+ patterns:
21
+ - next
22
+ tailwind:
23
+ patterns:
24
+ - tailwindcss
25
+ - "@tailwindcss/*"
26
+ storybook:
27
+ patterns:
28
+ - storybook
29
+ - "@storybook/*"
30
+ vitest:
31
+ patterns:
32
+ - vitest
33
+ - "@vitejs/*"
34
+ - happy-dom
35
+ dev-tooling:
36
+ dependency-type: development
37
+ patterns:
38
+ - "*"
39
+
40
+ - package-ecosystem: github-actions
41
+ directory: /
42
+ schedule:
43
+ interval: weekly
44
+ open-pull-requests-limit: 3
45
+ groups:
46
+ gha:
47
+ patterns:
48
+ - "*"