create-m5kdev 0.33.0 → 0.34.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 (147) hide show
  1. package/dist/src/catalog.cjs +21 -1
  2. package/dist/src/catalog.cjs.map +1 -1
  3. package/dist/src/catalog.d.cts +3 -1
  4. package/dist/src/create.cjs +6 -2
  5. package/dist/src/create.cjs.map +1 -1
  6. package/dist/src/doctor.cjs.map +1 -1
  7. package/dist/src/fs.cjs +10 -5
  8. package/dist/src/fs.cjs.map +1 -1
  9. package/dist/src/prompts.cjs +32 -0
  10. package/dist/src/prompts.cjs.map +1 -1
  11. package/dist/src/prompts.d.cts +7 -1
  12. package/dist/src/template.cjs +23 -4
  13. package/dist/src/template.cjs.map +1 -1
  14. package/dist/src/template.d.cts +17 -3
  15. package/dist/src/types.d.cts +11 -4
  16. package/package.json +4 -1
  17. package/templates/minimal-app/.cursor/rules/module-dto-guide.mdc +1 -1
  18. package/templates/minimal-app/.cursor/rules/module-grants-guide.mdc +3 -3
  19. package/templates/minimal-app/.cursor/rules/module-module-guide.mdc +3 -2
  20. package/templates/minimal-app/.cursor/rules/module-service-guide.mdc +1 -1
  21. package/templates/minimal-app/.dockerignore.tpl +31 -0
  22. package/templates/minimal-app/.gitignore.tpl +1 -0
  23. package/templates/minimal-app/AGENTS.md.tpl +13 -10
  24. package/templates/minimal-app/CLAUDE.md.tpl +132 -131
  25. package/templates/minimal-app/README.md.tpl +50 -19
  26. package/templates/minimal-app/apps/e2e/package.json.tpl +23 -23
  27. package/templates/minimal-app/apps/e2e/playwright.config.ts.tpl +51 -39
  28. package/templates/minimal-app/apps/e2e/playwright.expo.config.ts.tpl +38 -38
  29. package/templates/minimal-app/apps/e2e/servers.ts.tpl +136 -112
  30. package/templates/minimal-app/apps/e2e/tests/conversation.spec.ts.tpl +22 -0
  31. package/templates/minimal-app/apps/e2e/tests/email.spec.ts.tpl +47 -47
  32. package/templates/minimal-app/apps/e2e/tests/expo-helpers.ts.tpl +73 -73
  33. package/templates/minimal-app/apps/e2e/tests/expo-standard.spec.ts.tpl +517 -517
  34. package/templates/minimal-app/apps/e2e/tests/expo-waitlist.spec.ts.tpl +94 -94
  35. package/templates/minimal-app/apps/e2e/tests/files.spec.ts.tpl +35 -0
  36. package/templates/minimal-app/apps/e2e/tests/helpers.ts.tpl +289 -289
  37. package/templates/minimal-app/apps/e2e/tests/standard.spec.ts.tpl +516 -516
  38. package/templates/minimal-app/apps/e2e/tests/waitlist.spec.ts.tpl +107 -107
  39. package/templates/minimal-app/apps/e2e/tests/workflow.spec.ts.tpl +26 -0
  40. package/templates/minimal-app/apps/e2e/tsconfig.json.tpl +10 -10
  41. package/templates/minimal-app/apps/email/package.json.tpl +34 -34
  42. package/templates/minimal-app/apps/email/src/emails/trialEndingEmail.tsx.tpl +40 -0
  43. package/templates/minimal-app/apps/email/src/index.ts.tpl +7 -0
  44. package/templates/minimal-app/apps/email/src/resources.ts.tpl +72 -65
  45. package/templates/minimal-app/apps/expo/app.json.tpl +36 -36
  46. package/templates/minimal-app/apps/expo/eslint.config.js.tpl +8 -8
  47. package/templates/minimal-app/apps/expo/metro.config.js.tpl +16 -16
  48. package/templates/minimal-app/apps/expo/src/app/_layout.tsx.tpl +31 -31
  49. package/templates/minimal-app/apps/expo/src/app/claim-account.tsx.tpl +151 -151
  50. package/templates/minimal-app/apps/expo/src/app/forgot-password.tsx.tpl +53 -53
  51. package/templates/minimal-app/apps/expo/src/app/index.tsx.tpl +8 -8
  52. package/templates/minimal-app/apps/expo/src/app/login.tsx.tpl +71 -71
  53. package/templates/minimal-app/apps/expo/src/app/logout.tsx.tpl +19 -19
  54. package/templates/minimal-app/apps/expo/src/app/organization/accept-invitation.tsx.tpl +85 -85
  55. package/templates/minimal-app/apps/expo/src/app/posts.tsx.tpl +40 -40
  56. package/templates/minimal-app/apps/expo/src/app/reset-password.tsx.tpl +75 -75
  57. package/templates/minimal-app/apps/expo/src/app/signup.tsx.tpl +193 -193
  58. package/templates/minimal-app/apps/expo/src/components/AuthScaffold.tsx.tpl +34 -34
  59. package/templates/minimal-app/apps/expo/src/components/FormTextField.tsx.tpl +37 -37
  60. package/templates/minimal-app/apps/expo/src/components/LoadingScreen.tsx.tpl +10 -10
  61. package/templates/minimal-app/apps/expo/src/components/StatusText.tsx.tpl +22 -22
  62. package/templates/minimal-app/apps/expo/src/config.ts.tpl +9 -9
  63. package/templates/minimal-app/apps/expo/src/global.css.tpl +11 -11
  64. package/templates/minimal-app/apps/expo/src/lib/trpc.ts.tpl +20 -20
  65. package/templates/minimal-app/apps/expo/tsconfig.json.tpl +11 -11
  66. package/templates/minimal-app/apps/expo/uniwind-env.d.ts.tpl +1 -1
  67. package/templates/minimal-app/apps/landing/.env.production.example.tpl +7 -0
  68. package/templates/minimal-app/apps/landing/Dockerfile.tpl +39 -0
  69. package/templates/minimal-app/apps/landing/fly.toml.tpl +20 -0
  70. package/templates/minimal-app/apps/landing/index.html.tpl +35 -0
  71. package/templates/minimal-app/apps/landing/package.json.tpl +34 -0
  72. package/templates/minimal-app/apps/landing/scripts/fly-deploy.mjs.tpl +75 -0
  73. package/templates/minimal-app/apps/landing/scripts/fly-secrets.mjs.tpl +31 -0
  74. package/templates/minimal-app/apps/landing/src/App.tsx.tpl +12 -0
  75. package/templates/minimal-app/apps/landing/src/LandingPage.tsx.tpl +37 -0
  76. package/templates/minimal-app/apps/landing/src/index.css.tpl +24 -0
  77. package/templates/minimal-app/apps/landing/src/main.tsx.tpl +16 -0
  78. package/templates/minimal-app/apps/landing/src/vite-env.d.ts.tpl +11 -0
  79. package/templates/minimal-app/apps/landing/tsconfig.json.tpl +12 -0
  80. package/templates/minimal-app/apps/landing/vite.config.ts.tpl +25 -0
  81. package/templates/minimal-app/apps/server/AGENTS.md.tpl +54 -46
  82. package/templates/minimal-app/apps/server/{drizzle/seed.e2e.ts.tpl → db.e2e.ts.tpl} +57 -40
  83. package/templates/minimal-app/apps/server/{drizzle/seed.ts.tpl → db.ts.tpl} +27 -20
  84. package/templates/minimal-app/apps/server/drizzle/0003_silly_the_liberteens.sql +27 -0
  85. package/templates/minimal-app/apps/server/drizzle/meta/0000_snapshot.json.tpl +56 -166
  86. package/templates/minimal-app/apps/server/drizzle/meta/0001_snapshot.json.tpl +1796 -1910
  87. package/templates/minimal-app/apps/server/drizzle/meta/0002_snapshot.json.tpl +1818 -1932
  88. package/templates/minimal-app/apps/server/drizzle/meta/0003_snapshot.json.tpl +2137 -0
  89. package/templates/minimal-app/apps/server/drizzle/meta/_journal.json.tpl +8 -1
  90. package/templates/minimal-app/apps/server/drizzle.config.ts.tpl +3 -33
  91. package/templates/minimal-app/apps/server/package.json.tpl +5 -3
  92. package/templates/minimal-app/apps/server/src/app.ts.tpl +36 -0
  93. package/templates/minimal-app/apps/server/src/modules/conversation/conversation.mastra.ts.tpl +26 -0
  94. package/templates/minimal-app/apps/server/src/modules/demo-workflow/demo-workflow.module.ts.tpl +47 -0
  95. package/templates/minimal-app/apps/server/src/modules/demo-workflow/demo-workflow.service.ts.tpl +43 -0
  96. package/templates/minimal-app/apps/server/src/modules/demo-workflow/demo-workflow.trpc.ts.tpl +16 -0
  97. package/templates/minimal-app/apps/server/src/modules/posts/posts.db.ts.tpl +28 -28
  98. package/templates/minimal-app/apps/server/src/modules/posts/posts.grants.ts.tpl +28 -28
  99. package/templates/minimal-app/apps/server/src/modules/posts/posts.module.ts.tpl +54 -54
  100. package/templates/minimal-app/apps/server/src/modules/posts/posts.repository.ts.tpl +67 -67
  101. package/templates/minimal-app/apps/server/src/modules/posts/posts.service.ts.tpl +116 -116
  102. package/templates/minimal-app/apps/server/src/modules/posts/posts.trpc.ts.tpl +37 -37
  103. package/templates/minimal-app/apps/server/src/modules/test-harness/test-harness.module.ts.tpl +279 -279
  104. package/templates/minimal-app/apps/server/src/schema.ts.tpl +31 -20
  105. package/templates/minimal-app/apps/server/src/types.ts.tpl +12 -12
  106. package/templates/minimal-app/apps/server/tsconfig.json.tpl +1 -1
  107. package/templates/minimal-app/apps/server/tsup.config.ts.tpl +23 -9
  108. package/templates/minimal-app/apps/shared/.env.example.tpl +5 -0
  109. package/templates/minimal-app/apps/shared/.env.production.example.tpl +23 -0
  110. package/templates/minimal-app/apps/shared/.env.tpl +5 -0
  111. package/templates/minimal-app/apps/shared/Dockerfile.tpl +48 -0
  112. package/templates/minimal-app/apps/shared/fly.toml.tpl +24 -0
  113. package/templates/minimal-app/apps/shared/package.json.tpl +25 -24
  114. package/templates/minimal-app/apps/shared/scripts/fly-deploy.mjs.tpl +75 -0
  115. package/templates/minimal-app/apps/shared/scripts/fly-secrets.mjs.tpl +31 -0
  116. package/templates/minimal-app/apps/shared/src/modules/app/app.constants.ts.tpl +28 -28
  117. package/templates/minimal-app/apps/shared/src/modules/conversation/conversation.constants.ts.tpl +1 -0
  118. package/templates/minimal-app/apps/shared/src/modules/notification/notification.schema.ts.tpl +3 -3
  119. package/templates/minimal-app/apps/shared/src/modules/posts/posts.constants.ts.tpl +5 -5
  120. package/templates/minimal-app/apps/shared/src/modules/posts/posts.schema.ts.tpl +25 -25
  121. package/templates/minimal-app/apps/webapp/package.json.tpl +53 -53
  122. package/templates/minimal-app/apps/webapp/public/push-sw.js.tpl +34 -34
  123. package/templates/minimal-app/apps/webapp/src/App.tsx.tpl +46 -44
  124. package/templates/minimal-app/apps/webapp/src/Layout.tsx.tpl +96 -65
  125. package/templates/minimal-app/apps/webapp/src/Router.tsx.tpl +114 -93
  126. package/templates/minimal-app/apps/webapp/src/index.css.tpl +15 -15
  127. package/templates/minimal-app/apps/webapp/src/main.tsx.tpl +26 -26
  128. package/templates/minimal-app/apps/webapp/src/modules/conversation/ConversationRoute.tsx.tpl +36 -0
  129. package/templates/minimal-app/apps/webapp/src/modules/files/FilesRoute.tsx.tpl +88 -0
  130. package/templates/minimal-app/apps/webapp/src/modules/files/hooks/useFilesRoute.ts.tpl +50 -0
  131. package/templates/minimal-app/apps/webapp/src/modules/workflows/WorkflowsRoute.tsx.tpl +97 -0
  132. package/templates/minimal-app/apps/webapp/src/modules/workflows/hooks/useWorkflowsRoute.ts.tpl +64 -0
  133. package/templates/minimal-app/apps/webapp/src/utils/i18n.ts.tpl +13 -13
  134. package/templates/minimal-app/apps/webapp/src/utils/trpc.ts.tpl +10 -10
  135. package/templates/minimal-app/apps/webapp/src/vite-env.d.ts.tpl +1 -1
  136. package/templates/minimal-app/apps/webapp/translations/en/app.json.tpl +7 -7
  137. package/templates/minimal-app/apps/webapp/translations/en/{{APP_SLUG}}.json.tpl +193 -135
  138. package/templates/minimal-app/apps/webapp/tsconfig.json.tpl +17 -17
  139. package/templates/minimal-app/apps/webapp/vite.config.ts.tpl +31 -31
  140. package/templates/minimal-app/biome.json.tpl +17 -12
  141. package/templates/minimal-app/package.json.tpl +6 -2
  142. package/templates/minimal-app/pnpm-workspace.yaml.tpl +14 -7
  143. package/templates/minimal-app/template.manifest.json +92 -2
  144. package/templates/minimal-app/apps/server/drizzle/db.ts.tpl +0 -26
  145. package/templates/minimal-app/apps/server/drizzle/guard.ts.tpl +0 -36
  146. package/templates/minimal-app/apps/server/drizzle/reset.ts.tpl +0 -40
  147. package/templates/minimal-app/apps/server/drizzle/sync.ts.tpl +0 -16
package/package.json CHANGED
@@ -1,7 +1,10 @@
1
1
  {
2
2
  "name": "create-m5kdev",
3
- "version": "0.33.0",
3
+ "version": "0.34.0",
4
4
  "license": "GPL-3.0-only",
5
+ "engines": {
6
+ "node": ">=24"
7
+ },
5
8
  "repository": {
6
9
  "type": "git",
7
10
  "url": "https://github.com/michalkow/m5kdev.git"
@@ -13,7 +13,7 @@ database schema first. Services, repositories, and tRPC files import the DTO
13
13
  ## The pattern
14
14
 
15
15
  ```ts
16
- import { createZodSchemas } from "@m5kdev/backend/modules/base/base.dto";
16
+ import { createZodSchemas } from "@m5kdev/backend/base/base.dto";
17
17
  import {
18
18
  postCreateInputSchema,
19
19
  postUpdateInputSchema,
@@ -22,10 +22,10 @@ apps/<app>/server/src/modules/<module>/<module>.grants.ts
22
22
 
23
23
  ## Grant Structure
24
24
 
25
- App modules use flat `ResourceGrant[]` arrays imported from `@m5kdev/backend/modules/base/base.grants`:
25
+ App modules use flat `ResourceGrant[]` arrays imported from `@m5kdev/backend/base/base.grants`:
26
26
 
27
27
  ```typescript
28
- import type { ResourceGrant } from "@m5kdev/backend/modules/base/base.grants";
28
+ import type { ResourceGrant } from "@m5kdev/backend/base/base.grants";
29
29
  ```
30
30
 
31
31
  Each `ResourceGrant` has four fields:
@@ -47,7 +47,7 @@ Each `ResourceGrant` has four fields:
47
47
  ## Example
48
48
 
49
49
  ```typescript
50
- import type { ResourceGrant } from "@m5kdev/backend/modules/base/base.grants";
50
+ import type { ResourceGrant } from "@m5kdev/backend/base/base.grants";
51
51
 
52
52
  export const postsGrants: ResourceGrant[] = [
53
53
  {
@@ -15,13 +15,14 @@ apps/<app>/server/src/modules/<module>/<module>.module.ts
15
15
 
16
16
  ## Conventions
17
17
 
18
- - Extend `BaseModule<Deps, Tables, Repositories, Services, Routers>` from `@m5kdev/backend/modules/base/base.module`.
18
+ - Extend `BaseModule<Deps, Tables, Repositories, Services, Routers>` from `@m5kdev/backend/base/base.module`.
19
19
  - Declare local type aliases for each generic slot (`*ModuleDeps`, `*ModuleTables`, `*ModuleRepositories`, `*ModuleServices`, `*ModuleRouters`).
20
20
  - Set `readonly id` to match the module directory name (e.g. `readonly id = "posts"`).
21
21
  - Declare `dbDependsOn` or `dependsOn` as a `readonly` tuple with `as const`. App modules that reference auth tables typically use `dbDependsOn: ["auth"]`.
22
22
  - Override only the hooks the module actually needs; omit the rest.
23
23
  - Keep hook bodies as pure wiring — no business logic.
24
24
  - Use `createBackendRouterMap(namespace, router)` from `@m5kdev/backend/app` in the `trpc()` hook.
25
+ - Register the module with `createBackendApp(config, [modules])`. Do not use `backendApp.use`.
25
26
  - Export a singleton instance at the bottom of the file.
26
27
 
27
28
  ## Generic Parameters
@@ -60,7 +61,7 @@ import {
60
61
  type ModuleRepositoriesContext,
61
62
  type ModuleServicesContext,
62
63
  type ModuleTRPCContext,
63
- } from "@m5kdev/backend/modules/base/base.module";
64
+ } from "@m5kdev/backend/base/base.module";
64
65
  import type * as postsTables from "./posts.db";
65
66
  import { postsGrants } from "./posts.grants";
66
67
  import { PostsRepository } from "./posts.repository";
@@ -298,7 +298,7 @@ readonly validateCode = this.procedure("validateCode")
298
298
  ## Example Skeleton
299
299
 
300
300
  ```typescript
301
- import { BasePermissionService } from "@m5kdev/backend/modules/base/base.service";
301
+ import { BasePermissionService } from "@m5kdev/backend/base/base.service";
302
302
  import { postSchemas } from "./posts.dto";
303
303
  import type { PostsRepository } from "./posts.repository";
304
304
 
@@ -0,0 +1,31 @@
1
+ # Dependencies
2
+ node_modules
3
+ **/node_modules
4
+ .pnpm-store
5
+ .pnp
6
+ .pnp.js
7
+
8
+ # Git
9
+ .git
10
+
11
+ # Local env files — never bake secrets into the image
12
+ .env*
13
+
14
+ # Testing
15
+ coverage
16
+
17
+ # Turbo
18
+ .turbo
19
+
20
+ # Build outputs
21
+ build
22
+ dist
23
+
24
+ # Debug
25
+ npm-debug.log*
26
+ yarn-debug.log*
27
+ yarn-error.log*
28
+
29
+ # Misc
30
+ .DS_Store
31
+ *.pem
@@ -7,3 +7,4 @@ coverage
7
7
  *.db-*
8
8
  apps/server/.emails
9
9
  apps/shared/.env
10
+ **/.env.production
@@ -8,20 +8,23 @@
8
8
 
9
9
  ## Repository Structure
10
10
 
11
- - `apps/shared` holds shared Zod schemas and constants.
11
+ - `apps/shared` holds shared Zod schemas, constants, and the product Deploy home.
12
12
  - `apps/server` holds the backend composition root, modules, auth wiring, and database scripts.
13
13
  - `apps/webapp` holds the React app shell, routes, providers, and the `posts` feature.
14
+ - `apps/landing` holds the public one-page site and its Fly adapter.
14
15
  - `apps/email` holds the email templates used by auth flows and local email delivery.
15
16
 
16
- ## Backend Conventions
17
-
18
- - Keep repository, service, and transport layers separate inside each module.
19
- - Register modules in `apps/server/src/app.ts` via `createBackendApp(config, [modules])`.
20
- - Use `BaseModule` subclasses for app modules; the kernel wires repositories, services, and tRPC.
21
- - Keep tRPC files focused on input/output wiring and delegate logic to services.
22
- - Do not add service methods that merely call another service. Call the owning service directly unless the method adds a business rule, authorization, validation, orchestration, a transaction boundary, or meaningful domain translation.
23
- - Renaming a dependency method, repackaging arguments, constructing a prompt, or forwarding actor/context data alone does not justify a service wrapper.
24
- - Do not create Drizzle migrations by hand. Use the scaffolded config and your project migration workflow later if you need generated migrations.
17
+ ## Backend Conventions
18
+
19
+ - Keep repository, service, and transport layers separate inside each module.
20
+ - Register modules in `apps/server/src/app.ts` via `createBackendApp(config, [modules])`.
21
+ - Import Kernel infrastructure (`BaseModule`, Grants, DTOs) from `@m5kdev/backend/base/*`. The `modules/base` path still re-exports.
22
+ - Clay, Docx, Pdf, Social, and Video are Optional Backend Module packages (`@m5kdev/module-<name>`). They are not scaffolded; add them only when the product needs them.
23
+ - Use `BaseModule` subclasses for app modules; the kernel wires repositories, services, and tRPC.
24
+ - Keep tRPC files focused on input/output wiring and delegate logic to services.
25
+ - Do not add service methods that merely call another service. Call the owning service directly unless the method adds a business rule, authorization, validation, orchestration, a transaction boundary, or meaningful domain translation.
26
+ - Renaming a dependency method, repackaging arguments, constructing a prompt, or forwarding actor/context data alone does not justify a service wrapper.
27
+ - Do not create Drizzle migrations by hand. Use the scaffolded config and your project migration workflow later if you need generated migrations.
25
28
 
26
29
  ## Frontend Conventions
27
30
 
@@ -1,131 +1,132 @@
1
- # CLAUDE.md
2
-
3
- Guidance for Claude Code when working in this repository.
4
-
5
- ## About This App
6
-
7
- **{{APP_NAME}}** — {{APP_DESCRIPTION}}
8
-
9
- This is a pnpm + Turborepo monorepo built on the **m5kdev framework**:
10
-
11
- - `@m5kdev/backend` — backend kernel: Express, Better Auth, Drizzle (LibSQL), and tRPC. Apps compose it via `createBackendApp(config, [modules])`.
12
- - `@m5kdev/commons` — shared runtime utilities and contracts.
13
- - `@m5kdev/config` — configuration loading and validation.
14
- - `@m5kdev/email` — email rendering and local delivery used by auth flows.
15
- // m5k:webapp:start
16
- - `@m5kdev/frontend` — framework-level React providers (`AppConfigProvider`, `AppTrpcQueryProvider`) and hooks.
17
- - `@m5kdev/web-ui` — web UI components built on HeroUI v3.
18
- // m5k:webapp:end
19
-
20
- The framework owns the plumbing (auth, database wiring, tRPC composition, permissions); app code supplies modules and screens that follow the conventions below.
21
-
22
- ## Workspace
23
-
24
- - `apps/shared` — shared Zod schemas, constants, and the `.env` file every app reads.
25
- - `apps/server` — backend composition root (`src/app.ts`), app modules (`src/modules/`), hand-registered table list (`src/schema.ts`), and Drizzle scripts.
26
- // m5k:webapp:start
27
- - `apps/webapp` — Vite + React 19 frontend: app shell, routes, providers, and feature modules.
28
- // m5k:webapp:end
29
- // m5k:expo:start
30
- - `apps/expo` — Expo (React Native) app sharing the same server and shared contracts.
31
- // m5k:expo:end
32
- - `apps/email` — email templates and the local delivery registry.
33
- // m5k:test-harness:start
34
- - `apps/e2e` — Playwright end-to-end tests; the server exposes a test-harness module for them.
35
- // m5k:test-harness:end
36
-
37
- ## Commands
38
-
39
- ```sh
40
- pnpm dev # run all apps in dev (turbo)
41
- pnpm build # build all apps
42
- pnpm lint # biome check
43
- pnpm lint:fix # biome check --write
44
- pnpm check-types # tsc --noEmit everywhere
45
- ```
46
-
47
- Database (Drizzle, run from the repo root):
48
-
49
- ```sh
50
- pnpm --filter ./apps/server drizzle:generate # generate migrations from *.db.ts changes
51
- pnpm --filter ./apps/server drizzle:migrate # apply migrations
52
- pnpm --filter ./apps/server drizzle:seed # seed the local database
53
- pnpm --filter ./apps/server drizzle:reset # reset the local database
54
- pnpm --filter ./apps/server drizzle:studio # inspect the database
55
- ```
56
-
57
- First-time setup: `pnpm install`, then `drizzle:migrate` and `drizzle:seed`, then `pnpm dev`.
58
- // m5k:test-harness:start
59
-
60
- End-to-end tests: `pnpm --filter ./apps/e2e test:e2e` (Playwright).
61
- // m5k:test-harness:end
62
-
63
- The local database is a LibSQL file; local auth emails are written to `apps/server/.emails`. Demo login: `admin@{{APP_SLUG}}.local` / `password1234`.
64
-
65
- ## Framework Architecture
66
-
67
- ### Backend: kernel + modules
68
-
69
- The backend kernel orchestrates modules. Each app module is a `BaseModule` subclass registered in `apps/server/src/app.ts` via `createBackendApp(config, [modules])` — the kernel wires its repositories, services, and tRPC routers.
70
-
71
- A module lives in `apps/server/src/modules/<name>/` and follows a strict file anatomy where **the Drizzle table is the source of truth** and types flow one way:
72
-
73
- ```
74
- <name>.db.ts table definition (source of truth; register it in src/schema.ts)
75
- └─ <name>.dto.ts Zod schemas derived from the table — the module's API surface
76
- ├─ <name>.repository.ts data access, consumes the DTO object
77
- ├─ <name>.service.ts business logic, consumes the DTO object
78
- └─ <name>.trpc.ts thin router: attaches DTO schemas, delegates to the service
79
- <name>.grants.ts permission grants for the module
80
- <name>.module.ts composition unit wiring the above into one class
81
- ```
82
-
83
- Clients infer all row/list types from `AppRouter` (`inferRouterOutputs`) — never hand-mirror server types anywhere. Never write Drizzle migrations by hand; change `*.db.ts`, register new tables in `src/schema.ts`, then run `drizzle:generate` + `drizzle:migrate`.
84
-
85
- Roles are defined in `apps/shared/src/modules/app/` and passed through both `createBackendApp` metadata and the frontend config provider; when adding roles, extend the module `*.grants.ts` files to match.
86
- // m5k:webapp:start
87
-
88
- ### Frontend: fixed stack, hooks own the logic
89
-
90
- The webapp stack is fixed — React 19, HeroUI v3, Tailwind CSS v4, react-router v7, `nuqs` for URL state, TanStack Query over tRPC, i18next. Do not introduce alternatives (no fetch/axios, no form libraries, no other UI kits).
91
-
92
- - App shell shape: `NuqsAdapter` + `BrowserRouter` + `Providers`; global providers are composed in one place only.
93
- - Components stay display-focused; data fetching, mutations, and effect chains live in custom hooks under `modules/<feature>/hooks/`, composed into one screen-level hook (e.g. `usePostsRoute`).
94
- - All server data goes through `useTRPC()` + `queryOptions`/`mutationOptions`; invalidate with the matching `queryFilter()` after mutations.
95
- - Forms are uncontrolled HeroUI `Form` components with native HTML validation; read values from `FormData` on submit.
96
- - All user-facing copy goes through i18next; keys live in `apps/webapp/translations/`.
97
- // m5k:webapp:end
98
-
99
- ### Reference implementation
100
-
101
- The **posts** feature is the canonical example of every convention. When adding a feature, mirror its structure:
102
-
103
- - `apps/shared/src/modules/posts/`
104
- - `apps/server/src/modules/posts/`
105
- // m5k:webapp:start
106
- - `apps/webapp/src/modules/posts/`
107
- // m5k:webapp:end
108
-
109
- ## Detailed Style Guides
110
-
111
- The framework's detailed conventions live in `.cursor/rules/*.mdc`. Cursor applies them by glob automatically; Claude does not — so **before creating or editing a file that matches a pattern below, read the matching guide first**. They describe how the framework is meant to be used, with correct/incorrect examples.
112
-
113
- | Guide | Read before touching |
114
- | --- | --- |
115
- | `.cursor/rules/module-db-guide.mdc` | `apps/server/src/modules/**/*.db.ts` |
116
- | `.cursor/rules/module-dto-guide.mdc` | `apps/server/src/modules/**/*.dto.ts` |
117
- | `.cursor/rules/module-repository-guide.mdc` | `apps/server/src/modules/**/*.repository.ts` |
118
- | `.cursor/rules/module-service-guide.mdc` | `apps/server/src/modules/**/*.service.ts` |
119
- | `.cursor/rules/module-trpc-guide.mdc` | `apps/server/src/modules/**/*.trpc.ts` |
120
- | `.cursor/rules/module-grants-guide.mdc` | `apps/server/src/modules/**/*.grants.ts` |
121
- | `.cursor/rules/module-module-guide.mdc` | `apps/server/src/modules/**/*.module.ts` |
122
- | `.cursor/rules/module-schema-guide.mdc` | `apps/shared/src/modules/**/*.schema.ts` |
123
- // m5k:webapp:start
124
- | `.cursor/rules/frontend-component-guide.mdc` | webapp `*.tsx` components |
125
- | `.cursor/rules/frontend-hook-guide.mdc` | webapp `hooks/**` |
126
- | `.cursor/rules/frontend-data-guide.mdc` | webapp data fetching / tRPC usage |
127
- | `.cursor/rules/frontend-form-guide.mdc` | webapp forms |
128
- | `.cursor/rules/frontend-i18n-guide.mdc` | webapp user-facing copy |
129
- // m5k:webapp:end
130
-
131
- `AGENTS.md` (repo root and per-app) carries a compact summary of the same conventions for other agents; this file plus the guides above are the authoritative version for Claude.
1
+ # CLAUDE.md
2
+
3
+ Guidance for Claude Code when working in this repository.
4
+
5
+ ## About This App
6
+
7
+ **{{APP_NAME}}** — {{APP_DESCRIPTION}}
8
+
9
+ This is a pnpm + Turborepo monorepo built on the **m5kdev framework**:
10
+
11
+ - `@m5kdev/backend` — backend kernel: Express, Better Auth, Drizzle (LibSQL), and tRPC. Apps compose it via `createBackendApp(config, [modules])`.
12
+ - `@m5kdev/commons` — shared runtime utilities and contracts.
13
+ - `@m5kdev/config` — configuration loading and validation.
14
+ - `@m5kdev/email` — email rendering and local delivery used by auth flows.
15
+ // m5k:webapp:start
16
+ - `@m5kdev/frontend` — framework-level React providers (`AppConfigProvider`, `AppTrpcQueryProvider`) and hooks.
17
+ - `@m5kdev/web-ui` — web UI components built on HeroUI v3.
18
+ // m5k:webapp:end
19
+
20
+ The framework owns the plumbing (auth, database wiring, tRPC composition, permissions); app code supplies modules and screens that follow the conventions below.
21
+
22
+ ## Workspace
23
+
24
+ - `apps/shared` — shared Zod schemas, constants, and the `.env` file every app reads.
25
+ - `apps/server` — backend composition root (`src/app.ts`), app modules (`src/modules/`), hand-registered table list (`src/schema.ts`), and Drizzle scripts.
26
+ // m5k:webapp:start
27
+ - `apps/webapp` — Vite + React 19 frontend: app shell, routes, providers, and feature modules.
28
+ // m5k:webapp:end
29
+ // m5k:expo:start
30
+ - `apps/expo` — Expo (React Native) app sharing the same server and shared contracts.
31
+ // m5k:expo:end
32
+ - `apps/landing` — public one-page site (app name, pitch, CTA) with its own Dockerfile and `fly.toml`.
33
+ - `apps/email` — email templates and the local delivery registry.
34
+ // m5k:test-harness:start
35
+ - `apps/e2e` — Playwright end-to-end tests; the server exposes a test-harness module for them.
36
+ // m5k:test-harness:end
37
+
38
+ ## Commands
39
+
40
+ ```sh
41
+ pnpm dev # run all apps in dev (turbo)
42
+ pnpm build # build all apps
43
+ pnpm lint # biome check
44
+ pnpm lint:fix # biome check --write
45
+ pnpm check-types # tsc --noEmit everywhere
46
+ ```
47
+
48
+ Database (Drizzle, run from the repo root):
49
+
50
+ ```sh
51
+ pnpm --filter ./apps/server drizzle:generate # generate migrations from *.db.ts changes
52
+ pnpm --filter ./apps/server drizzle:migrate # apply migrations
53
+ pnpm --filter ./apps/server drizzle:seed # seed the local database
54
+ pnpm --filter ./apps/server drizzle:reset # reset the local database
55
+ pnpm --filter ./apps/server drizzle:studio # inspect the database
56
+ ```
57
+
58
+ First-time setup: `pnpm install`, then `drizzle:migrate` and `drizzle:seed`, then `pnpm dev`.
59
+ // m5k:test-harness:start
60
+
61
+ End-to-end tests: `pnpm --filter ./apps/e2e test:e2e` (Playwright).
62
+ // m5k:test-harness:end
63
+
64
+ The local database is a LibSQL file; local auth emails are written to `apps/server/.emails`. Demo login: `admin@{{APP_SLUG}}.local` / `password1234`.
65
+
66
+ ## Framework Architecture
67
+
68
+ ### Backend: kernel + modules
69
+
70
+ The backend kernel orchestrates modules. Each app module is a `BaseModule` subclass registered in `apps/server/src/app.ts` via `createBackendApp(config, [modules])` — the kernel wires its repositories, services, and tRPC routers. Import Kernel infrastructure from `@m5kdev/backend/base/*`. Clay, Docx, Pdf, Social, and Video are Optional Backend Module packages (`@m5kdev/module-<name>`); they are not scaffolded.
71
+
72
+ A module lives in `apps/server/src/modules/<name>/` and follows a strict file anatomy where **the Drizzle table is the source of truth** and types flow one way:
73
+
74
+ ```
75
+ <name>.db.ts table definition (source of truth; register it in src/schema.ts)
76
+ └─ <name>.dto.ts Zod schemas derived from the table — the module's API surface
77
+ ├─ <name>.repository.ts data access, consumes the DTO object
78
+ ├─ <name>.service.ts business logic, consumes the DTO object
79
+ └─ <name>.trpc.ts thin router: attaches DTO schemas, delegates to the service
80
+ <name>.grants.ts permission grants for the module
81
+ <name>.module.ts composition unit wiring the above into one class
82
+ ```
83
+
84
+ Clients infer all row/list types from `AppRouter` (`inferRouterOutputs`) — never hand-mirror server types anywhere. Never write Drizzle migrations by hand; change `*.db.ts`, register new tables in `src/schema.ts`, then run `drizzle:generate` + `drizzle:migrate`.
85
+
86
+ Roles are defined in `apps/shared/src/modules/app/` and passed through both `createBackendApp` metadata and the frontend config provider; when adding roles, extend the module `*.grants.ts` files to match.
87
+ // m5k:webapp:start
88
+
89
+ ### Frontend: fixed stack, hooks own the logic
90
+
91
+ The webapp stack is fixed — React 19, HeroUI v3, Tailwind CSS v4, react-router v7, `nuqs` for URL state, TanStack Query over tRPC, i18next. Do not introduce alternatives (no fetch/axios, no form libraries, no other UI kits).
92
+
93
+ - App shell shape: `NuqsAdapter` + `BrowserRouter` + `Providers`; global providers are composed in one place only.
94
+ - Components stay display-focused; data fetching, mutations, and effect chains live in custom hooks under `modules/<feature>/hooks/`, composed into one screen-level hook (e.g. `usePostsRoute`).
95
+ - All server data goes through `useTRPC()` + `queryOptions`/`mutationOptions`; invalidate with the matching `queryFilter()` after mutations.
96
+ - Forms are uncontrolled HeroUI `Form` components with native HTML validation; read values from `FormData` on submit.
97
+ - All user-facing copy goes through i18next; keys live in `apps/webapp/translations/`.
98
+ // m5k:webapp:end
99
+
100
+ ### Reference implementation
101
+
102
+ The **posts** feature is the canonical example of every convention. When adding a feature, mirror its structure:
103
+
104
+ - `apps/shared/src/modules/posts/`
105
+ - `apps/server/src/modules/posts/`
106
+ // m5k:webapp:start
107
+ - `apps/webapp/src/modules/posts/`
108
+ // m5k:webapp:end
109
+
110
+ ## Detailed Style Guides
111
+
112
+ The framework's detailed conventions live in `.cursor/rules/*.mdc`. Cursor applies them by glob automatically; Claude does not — so **before creating or editing a file that matches a pattern below, read the matching guide first**. They describe how the framework is meant to be used, with correct/incorrect examples.
113
+
114
+ | Guide | Read before touching |
115
+ | --- | --- |
116
+ | `.cursor/rules/module-db-guide.mdc` | `apps/server/src/modules/**/*.db.ts` |
117
+ | `.cursor/rules/module-dto-guide.mdc` | `apps/server/src/modules/**/*.dto.ts` |
118
+ | `.cursor/rules/module-repository-guide.mdc` | `apps/server/src/modules/**/*.repository.ts` |
119
+ | `.cursor/rules/module-service-guide.mdc` | `apps/server/src/modules/**/*.service.ts` |
120
+ | `.cursor/rules/module-trpc-guide.mdc` | `apps/server/src/modules/**/*.trpc.ts` |
121
+ | `.cursor/rules/module-grants-guide.mdc` | `apps/server/src/modules/**/*.grants.ts` |
122
+ | `.cursor/rules/module-module-guide.mdc` | `apps/server/src/modules/**/*.module.ts` |
123
+ | `.cursor/rules/module-schema-guide.mdc` | `apps/shared/src/modules/**/*.schema.ts` |
124
+ // m5k:webapp:start
125
+ | `.cursor/rules/frontend-component-guide.mdc` | webapp `*.tsx` components |
126
+ | `.cursor/rules/frontend-hook-guide.mdc` | webapp `hooks/**` |
127
+ | `.cursor/rules/frontend-data-guide.mdc` | webapp data fetching / tRPC usage |
128
+ | `.cursor/rules/frontend-form-guide.mdc` | webapp forms |
129
+ | `.cursor/rules/frontend-i18n-guide.mdc` | webapp user-facing copy |
130
+ // m5k:webapp:end
131
+
132
+ `AGENTS.md` (repo root and per-app) carries a compact summary of the same conventions for other agents; this file plus the guides above are the authoritative version for Claude.
@@ -4,9 +4,10 @@
4
4
 
5
5
  ## Workspace
6
6
 
7
- - `apps/shared` contains shared contracts and constants for the app.
7
+ - `apps/shared` contains shared contracts, constants, and the product Deploy home (Dockerfile, `fly.toml`).
8
8
  - `apps/server` contains the Express, Better Auth, Drizzle, and tRPC backend.
9
9
  - `apps/webapp` contains the Vite, React Router, HeroUI, and `nuqs` frontend.
10
+ - `apps/landing` contains the public marketing site (one page) and its Fly adapter.
10
11
  - `apps/email` contains the email templates and local delivery registry used by the starter.
11
12
 
12
13
  ## Getting Started
@@ -26,26 +27,56 @@ Database tables are registered by hand in `apps/server/src/schema.ts`; after cha
26
27
  - Email: `admin@{{APP_SLUG}}.local`
27
28
  - Password: `password1234`
28
29
 
29
- ## Typical Commands
30
+ ## Typical Commands
30
31
 
31
32
  ```sh
32
33
  pnpm dev
33
34
  pnpm build
34
35
  pnpm check-types
35
- pnpm lint
36
- ```
37
-
38
- ## Managed framework updates
39
-
40
- This app records its generated baseline in `.m5kdev.json`. The updater is run
41
- explicitly from the package registry and is not installed as an app dependency:
42
-
43
- ```sh
44
- pnpm dlx create-m5kdev@<version> doctor
45
- pnpm dlx create-m5kdev@<version> update --dry-run
46
- pnpm dlx create-m5kdev@<version> update
47
- ```
48
-
49
- Use an exact target version in CI and when coordinating an upgrade. Existing
50
- projects without `.m5kdev.json` can enroll at their current compatible baseline
51
- with `pnpm dlx create-m5kdev@<version> init`.
36
+ pnpm lint
37
+ ```
38
+
39
+ ## Managed framework updates
40
+
41
+ This app records its generated baseline in `.m5kdev.json`. The updater is run
42
+ explicitly from the package registry and is not installed as an app dependency:
43
+
44
+ ```sh
45
+ pnpm dlx create-m5kdev@<version> doctor
46
+ pnpm dlx create-m5kdev@<version> update --dry-run
47
+ pnpm dlx create-m5kdev@<version> update
48
+ ```
49
+
50
+ Use an exact target version in CI and when coordinating an upgrade. Existing
51
+ projects without `.m5kdev.json` can enroll at their current compatible baseline
52
+ with `pnpm dlx create-m5kdev@<version> init`.
53
+
54
+ ## Deploy (Fly.io)
55
+
56
+ The Dockerfile is the portable image. Fly is the adapter this starter ships —
57
+ `fly.toml` is ignored by `create-m5kdev update` so your app name and region stay
58
+ yours.
59
+
60
+ `.env*` files are excluded from the image. Copy the examples, then pass values
61
+ as Fly **build secrets** (baked into the SPA at image build) and **runtime
62
+ secrets** (`REDIS_URL`, `DATABASE_URL`, auth).
63
+
64
+ ```sh
65
+ cp apps/shared/.env.production.example apps/shared/.env.production
66
+ cp apps/landing/.env.production.example apps/landing/.env.production
67
+ # fill in URLs, BETTER_AUTH_SECRET, REDIS_URL, …
68
+
69
+ fly apps create {{APP_SLUG}}-app
70
+ fly apps create {{APP_SLUG}}-landing
71
+ fly volumes create libsql_data --app {{APP_SLUG}}-app --region iad --size 1
72
+ pnpm app:secrets
73
+ pnpm landing:secrets
74
+ pnpm app:deploy
75
+ pnpm landing:deploy
76
+ ```
77
+
78
+ `app:deploy` / `landing:deploy` read that app’s `.env.production` and forward
79
+ every key as `fly deploy --build-secret`. A missing env file errors with a
80
+ copy-the-example message. Product data lives on the `libsql_data` volume at
81
+ `/app/data` (`DATABASE_URL=file:/app/data/local.db`). Redis is a runtime secret,
82
+ not an image layer.
@@ -1,23 +1,23 @@
1
- {
2
- "name": "{{PACKAGE_SCOPE}}/e2e",
3
- "version": "0.0.0",
4
- "private": true,
5
- "scripts": {
6
- "build": "tsc --noEmit",
7
- "lint": "biome check .",
8
- "lint:fix": "biome check . --write",
9
- "check-types": "tsc --noEmit",
10
- "test:e2e": "playwright test",
11
- "test:e2e:expo": "playwright test --config playwright.expo.config.ts --headed"
12
- },
13
- "devDependencies": {
14
- "@m5kdev/backend": "catalog:m5kdev",
15
- "@m5kdev/commons": "catalog:m5kdev",
16
- "@m5kdev/config": "catalog:m5kdev",
17
- "@playwright/test": "catalog:m5kdev",
18
- "{{PACKAGE_SCOPE}}/shared": "workspace:*",
19
- "@trpc/client": "catalog:m5kdev",
20
- "@types/node": "catalog:m5kdev",
21
- "typescript": "catalog:m5kdev"
22
- }
23
- }
1
+ {
2
+ "name": "{{PACKAGE_SCOPE}}/e2e",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "build": "tsc --noEmit",
7
+ "lint": "biome check .",
8
+ "lint:fix": "biome check . --write",
9
+ "check-types": "tsc --noEmit",
10
+ "test:e2e": "playwright test",
11
+ "test:e2e:expo": "playwright test --config playwright.expo.config.ts --headed"
12
+ },
13
+ "devDependencies": {
14
+ "@m5kdev/backend": "catalog:m5kdev",
15
+ "@m5kdev/commons": "catalog:m5kdev",
16
+ "@m5kdev/config": "catalog:m5kdev",
17
+ "@playwright/test": "catalog:m5kdev",
18
+ "{{PACKAGE_SCOPE}}/shared": "workspace:*",
19
+ "@trpc/client": "catalog:m5kdev",
20
+ "@types/node": "catalog:m5kdev",
21
+ "typescript": "catalog:m5kdev"
22
+ }
23
+ }