create-m5kdev 0.38.15 → 0.38.16
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/dist/src/catalog.cjs +5 -1
- package/dist/src/catalog.cjs.map +1 -1
- package/dist/src/catalog.d.cts +2 -1
- package/dist/src/create.cjs +6 -3
- package/dist/src/create.cjs.map +1 -1
- package/dist/src/doctor.cjs +5 -0
- package/dist/src/doctor.cjs.map +1 -1
- package/dist/src/fs.cjs +5 -2
- package/dist/src/fs.cjs.map +1 -1
- package/dist/src/init.cjs +2 -1
- package/dist/src/init.cjs.map +1 -1
- package/dist/src/prompts.cjs +28 -4
- package/dist/src/prompts.cjs.map +1 -1
- package/dist/src/prompts.d.cts +11 -2
- package/dist/src/reconcile.cjs +2 -3
- package/dist/src/reconcile.cjs.map +1 -1
- package/dist/src/runCli.cjs +21 -11
- package/dist/src/runCli.cjs.map +1 -1
- package/dist/src/template.cjs +21 -4
- package/dist/src/template.cjs.map +1 -1
- package/dist/src/template.d.cts +6 -3
- package/dist/src/types.d.cts +1 -1
- package/dist/src/update.cjs +91 -6
- package/dist/src/update.cjs.map +1 -1
- package/dist/src/update.d.cts +5 -0
- package/package.json +1 -1
- package/templates/minimal-app/.gitignore.tpl +1 -0
- package/templates/minimal-app/AGENTS.md.tpl +14 -2
- package/templates/minimal-app/CLAUDE.md.tpl +12 -1
- package/templates/minimal-app/README.md.tpl +32 -14
- package/templates/minimal-app/apps/landing/.env.example.tpl +1 -0
- package/templates/minimal-app/apps/landing/.env.tpl +1 -0
- package/templates/minimal-app/apps/landing/src/LandingPage.tsx.tpl +3 -9
- package/templates/minimal-app/apps/landing/vite.config.ts.tpl +2 -0
- package/templates/minimal-app/package.json.tpl +2 -0
- package/templates/minimal-app/pnpm-workspace.yaml.tpl +12 -12
- package/templates/minimal-app/template.manifest.json +8 -3
|
@@ -8,12 +8,20 @@
|
|
|
8
8
|
|
|
9
9
|
## Repository Structure
|
|
10
10
|
|
|
11
|
+
- `apps/landing` holds the public one-page site and its Fly adapter.
|
|
12
|
+
// m5k:server:start
|
|
11
13
|
- `apps/shared` holds shared Zod schemas, constants, and the product Deploy home.
|
|
12
14
|
- `apps/server` holds the backend composition root, modules, auth wiring, and database scripts.
|
|
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.
|
|
15
15
|
- `apps/email` holds the email templates used by auth flows and local email delivery.
|
|
16
|
+
// m5k:server:end
|
|
17
|
+
// m5k:webapp:start
|
|
18
|
+
- `apps/webapp` holds the React app shell, routes, providers, and the `posts` feature.
|
|
19
|
+
// m5k:webapp:end
|
|
20
|
+
// m5k:expo:start
|
|
21
|
+
- `apps/expo` holds the Expo (React Native) client.
|
|
22
|
+
// m5k:expo:end
|
|
16
23
|
|
|
24
|
+
// m5k:server:start
|
|
17
25
|
## Backend Conventions
|
|
18
26
|
|
|
19
27
|
- Keep repository, service, and transport layers separate inside each module.
|
|
@@ -26,7 +34,9 @@
|
|
|
26
34
|
- Renaming a dependency method, repackaging arguments, constructing a prompt, or forwarding actor/context data alone does not justify a service wrapper.
|
|
27
35
|
- Do not create Drizzle migrations by hand. Use the scaffolded config and your project migration workflow later if you need generated migrations.
|
|
28
36
|
- Server event: emit through Auth from Workflow job handlers (and similar background work) when the UI must refresh a change the triggering mutation did not return. See `.cursor/rules/server-event-emit.mdc`.
|
|
37
|
+
// m5k:server:end
|
|
29
38
|
|
|
39
|
+
// m5k:webapp:start
|
|
30
40
|
## Frontend Conventions
|
|
31
41
|
|
|
32
42
|
- Keep the app shell shape: `NuqsAdapter` + `BrowserRouter` + `Providers`.
|
|
@@ -45,3 +55,5 @@
|
|
|
45
55
|
- Forms are uncontrolled HeroUI `Form` + `TextField`/`TextArea` with native HTML validation (`isRequired`, `type`, `minLength`) and `FieldError`; read values from `FormData` on submit. Never add form libraries (react-hook-form, formik). Validation that HTML cannot express (e.g. confirm-password) happens in the submit handler.
|
|
46
56
|
- All user-facing copy goes through i18next (`useTranslation`); keys live in `apps/webapp/translations/`.
|
|
47
57
|
- The `posts` feature (`apps/webapp/src/modules/posts/`) is the reference implementation for these conventions; see `.cursor/rules/frontend-*.mdc` for the detailed guides.
|
|
58
|
+
// m5k:webapp:end
|
|
59
|
+
|
|
@@ -11,7 +11,9 @@ This is a pnpm + Turborepo monorepo built on the **m5kdev framework**:
|
|
|
11
11
|
- `@m5kdev/backend` — backend kernel: Express, Better Auth, Drizzle (LibSQL), and tRPC. Apps compose it via `createBackendApp(config, [modules])`.
|
|
12
12
|
- `@m5kdev/commons` — shared runtime utilities and contracts.
|
|
13
13
|
- `@m5kdev/config` — configuration loading and validation.
|
|
14
|
+
// m5k:server:start
|
|
14
15
|
- `@m5kdev/email` — email rendering and local delivery used by auth flows.
|
|
16
|
+
// m5k:server:end
|
|
15
17
|
// m5k:webapp:start
|
|
16
18
|
- `@m5kdev/frontend` — framework-level React providers (`AppConfigProvider`, `AppTrpcQueryProvider`) and hooks.
|
|
17
19
|
- `@m5kdev/web-ui` — web UI components built on HeroUI v3.
|
|
@@ -21,16 +23,20 @@ The framework owns the plumbing (auth, database wiring, tRPC composition, permis
|
|
|
21
23
|
|
|
22
24
|
## Workspace
|
|
23
25
|
|
|
26
|
+
// m5k:server:start
|
|
24
27
|
- `apps/shared` — shared Zod schemas, constants, and the `.env` file every app reads.
|
|
25
28
|
- `apps/server` — backend composition root (`src/app.ts`), app modules (`src/modules/`), hand-registered table list (`src/schema.ts`), and Drizzle scripts.
|
|
29
|
+
// m5k:server:end
|
|
26
30
|
// m5k:webapp:start
|
|
27
31
|
- `apps/webapp` — Vite + React 19 frontend: app shell, routes, providers, and feature modules.
|
|
28
32
|
// m5k:webapp:end
|
|
29
33
|
// m5k:expo:start
|
|
30
34
|
- `apps/expo` — Expo (React Native) app sharing the same server and shared contracts.
|
|
31
35
|
// m5k:expo:end
|
|
32
|
-
- `apps/landing` — public one-page site (app name, pitch
|
|
36
|
+
- `apps/landing` — public one-page site (app name, pitch) with its own Dockerfile and `fly.toml`.
|
|
37
|
+
// m5k:server:start
|
|
33
38
|
- `apps/email` — email templates and the local delivery registry.
|
|
39
|
+
// m5k:server:end
|
|
34
40
|
// m5k:test-harness:start
|
|
35
41
|
- `apps/e2e` — Playwright end-to-end tests; the server exposes a test-harness module for them.
|
|
36
42
|
// m5k:test-harness:end
|
|
@@ -44,6 +50,7 @@ pnpm lint # biome check
|
|
|
44
50
|
pnpm lint:fix # biome check --write
|
|
45
51
|
pnpm check-types # tsc --noEmit everywhere
|
|
46
52
|
```
|
|
53
|
+
// m5k:server:start
|
|
47
54
|
|
|
48
55
|
Database (Drizzle, run from the repo root):
|
|
49
56
|
|
|
@@ -62,7 +69,9 @@ End-to-end tests: `pnpm --filter ./apps/e2e test:e2e` (Playwright).
|
|
|
62
69
|
// m5k:test-harness:end
|
|
63
70
|
|
|
64
71
|
The local database is a LibSQL file; local auth emails are written to `apps/server/.emails`. Demo login: `admin@{{APP_SLUG}}.local` / `password1234`.
|
|
72
|
+
// m5k:server:end
|
|
65
73
|
|
|
74
|
+
// m5k:server:start
|
|
66
75
|
## Framework Architecture
|
|
67
76
|
|
|
68
77
|
### Backend: kernel + modules
|
|
@@ -131,3 +140,5 @@ The framework's detailed conventions live in `.cursor/rules/*.mdc`. Cursor appli
|
|
|
131
140
|
// m5k:webapp:end
|
|
132
141
|
|
|
133
142
|
`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.
|
|
143
|
+
// m5k:server:end
|
|
144
|
+
|
|
@@ -4,19 +4,32 @@
|
|
|
4
4
|
|
|
5
5
|
## Workspace
|
|
6
6
|
|
|
7
|
+
- `apps/landing` contains the public marketing site (one page) and its Fly adapter.
|
|
8
|
+
// m5k:server:start
|
|
7
9
|
- `apps/shared` contains shared contracts, constants, and the product Deploy home (Dockerfile, `fly.toml`).
|
|
8
10
|
- `apps/server` contains the Express, Better Auth, Drizzle, and tRPC backend.
|
|
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.
|
|
11
11
|
- `apps/email` contains the email templates and local delivery registry used by the starter.
|
|
12
|
+
// m5k:server:end
|
|
13
|
+
// m5k:webapp:start
|
|
14
|
+
- `apps/webapp` contains the Vite, React Router, HeroUI, and `nuqs` frontend.
|
|
15
|
+
// m5k:webapp:end
|
|
16
|
+
// m5k:expo:start
|
|
17
|
+
- `apps/expo` contains the Expo (React Native) client.
|
|
18
|
+
// m5k:expo:end
|
|
12
19
|
|
|
13
20
|
## Getting Started
|
|
14
21
|
|
|
15
22
|
```sh
|
|
16
23
|
pnpm install
|
|
24
|
+
pnpm dev
|
|
25
|
+
```
|
|
26
|
+
// m5k:server:start
|
|
27
|
+
|
|
28
|
+
Then migrate and seed the local database:
|
|
29
|
+
|
|
30
|
+
```sh
|
|
17
31
|
pnpm --filter ./apps/server drizzle:migrate
|
|
18
32
|
pnpm --filter ./apps/server drizzle:seed
|
|
19
|
-
pnpm dev
|
|
20
33
|
```
|
|
21
34
|
|
|
22
35
|
The starter uses a local LibSQL file by default and writes local auth emails to `apps/server/.emails`.
|
|
@@ -26,6 +39,7 @@ Database tables are registered by hand in `apps/server/src/schema.ts`; after cha
|
|
|
26
39
|
|
|
27
40
|
- Email: `admin@{{APP_SLUG}}.local`
|
|
28
41
|
- Password: `password1234`
|
|
42
|
+
// m5k:server:end
|
|
29
43
|
|
|
30
44
|
## Typical Commands
|
|
31
45
|
|
|
@@ -58,26 +72,30 @@ The Dockerfile is the portable image. Fly is the adapter this starter ships —
|
|
|
58
72
|
yours.
|
|
59
73
|
|
|
60
74
|
`.env*` files are excluded from the image. Copy the examples, then pass values
|
|
61
|
-
as Fly **build secrets**
|
|
62
|
-
secrets** (`REDIS_URL`, `DATABASE_URL`, auth).
|
|
75
|
+
as Fly **build secrets** and **runtime secrets**.
|
|
63
76
|
|
|
64
77
|
```sh
|
|
65
|
-
cp apps/shared/.env.production.example apps/shared/.env.production
|
|
66
78
|
cp apps/landing/.env.production.example apps/landing/.env.production
|
|
79
|
+
// m5k:server:start
|
|
80
|
+
cp apps/shared/.env.production.example apps/shared/.env.production
|
|
67
81
|
# fill in URLs, BETTER_AUTH_SECRET, REDIS_URL, …
|
|
68
82
|
|
|
69
83
|
fly apps create {{APP_SLUG}}-app
|
|
70
|
-
fly apps create {{APP_SLUG}}-landing
|
|
71
84
|
fly volumes create libsql_data --app {{APP_SLUG}}-app --region iad --size 1
|
|
72
85
|
pnpm app:secrets
|
|
73
|
-
pnpm landing:secrets
|
|
74
86
|
pnpm app:deploy
|
|
87
|
+
// m5k:server:end
|
|
88
|
+
fly apps create {{APP_SLUG}}-landing
|
|
89
|
+
pnpm landing:secrets
|
|
75
90
|
pnpm landing:deploy
|
|
76
91
|
```
|
|
77
92
|
|
|
78
|
-
`
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
93
|
+
`landing:deploy` reads that app’s `.env.production` and forwards every key as
|
|
94
|
+
`fly deploy --build-secret` via Kernel bins (`m5kdev-fly-deploy` /
|
|
95
|
+
`m5kdev-fly-secrets`). A missing env file errors with a copy-the-example
|
|
96
|
+
message.
|
|
97
|
+
// m5k:server:start
|
|
98
|
+
`app:deploy` does the same for the product image. Product data lives on the
|
|
99
|
+
`libsql_data` volume at `/app/data` (`DATABASE_URL=file:/app/data/local.db`).
|
|
100
|
+
Redis is a runtime secret, not an image layer.
|
|
101
|
+
// m5k:server:end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
VITE_APP_NAME={{APP_NAME}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
VITE_APP_NAME={{APP_NAME}}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Card } from "@heroui/react";
|
|
2
2
|
|
|
3
3
|
export function LandingPage() {
|
|
4
4
|
const appName = import.meta.env.VITE_APP_NAME ?? "{{APP_NAME}}";
|
|
5
|
-
const appUrl = import.meta.env.VITE_APP_URL ?? "http://localhost:5173";
|
|
6
5
|
|
|
7
6
|
return (
|
|
8
7
|
<main className="relative flex min-h-dvh flex-col items-center justify-center overflow-hidden px-6 py-16">
|
|
@@ -15,7 +14,7 @@ export function LandingPage() {
|
|
|
15
14
|
className="pointer-events-none absolute inset-0 opacity-[0.12] [background-image:repeating-linear-gradient(0deg,transparent,transparent_23px,var(--color-rule)_24px)]"
|
|
16
15
|
/>
|
|
17
16
|
<Card className="relative max-w-xl border border-[var(--color-rule)] bg-[color-mix(in_oklch,var(--color-paper)_92%,white)] shadow-none">
|
|
18
|
-
<Card.Header className="grid gap-4 p-8
|
|
17
|
+
<Card.Header className="grid gap-4 p-8 sm:p-10">
|
|
19
18
|
<p className="text-xs font-medium tracking-[0.28em] text-[color-mix(in_oklch,var(--color-ink)_55%,transparent)] uppercase">
|
|
20
19
|
Public site
|
|
21
20
|
</p>
|
|
@@ -23,14 +22,9 @@ export function LandingPage() {
|
|
|
23
22
|
{appName}
|
|
24
23
|
</Card.Title>
|
|
25
24
|
<Card.Description className="max-w-md text-base leading-relaxed text-[color-mix(in_oklch,var(--color-ink)_72%,transparent)]">
|
|
26
|
-
An AI SaaS workspace.
|
|
25
|
+
An AI SaaS workspace.
|
|
27
26
|
</Card.Description>
|
|
28
27
|
</Card.Header>
|
|
29
|
-
<Card.Footer className="p-8 pt-2 sm:p-10 sm:pt-2">
|
|
30
|
-
<Button variant="primary" onPress={() => window.location.assign(appUrl)}>
|
|
31
|
-
Open app
|
|
32
|
-
</Button>
|
|
33
|
-
</Card.Footer>
|
|
34
28
|
</Card>
|
|
35
29
|
</main>
|
|
36
30
|
);
|
|
@@ -8,8 +8,10 @@
|
|
|
8
8
|
"lint": "turbo run lint",
|
|
9
9
|
"lint:fix": "turbo run lint:fix",
|
|
10
10
|
"check-types": "turbo run check-types",
|
|
11
|
+
// m5k:server:start
|
|
11
12
|
"app:deploy": "m5kdev-fly-deploy --config apps/shared/fly.toml --dockerfile apps/shared/Dockerfile --env apps/shared/.env.production",
|
|
12
13
|
"app:secrets": "m5kdev-fly-secrets --config apps/shared/fly.toml --env apps/shared/.env.production",
|
|
14
|
+
// m5k:server:end
|
|
13
15
|
"landing:deploy": "m5kdev-fly-deploy --config apps/landing/fly.toml --dockerfile apps/landing/Dockerfile --env apps/landing/.env.production",
|
|
14
16
|
"landing:secrets": "m5kdev-fly-secrets --config apps/landing/fly.toml --env apps/landing/.env.production"
|
|
15
17
|
},
|
|
@@ -7,18 +7,18 @@ catalogs:
|
|
|
7
7
|
"@heroui/react": 3.0.3
|
|
8
8
|
"@heroui/styles": 3.0.3
|
|
9
9
|
"@libsql/client": 0.17.4
|
|
10
|
-
"@m5kdev/backend": 0.38.
|
|
11
|
-
"@m5kdev/commons": 0.38.
|
|
12
|
-
"@m5kdev/config": 0.38.
|
|
13
|
-
"@m5kdev/email": 0.38.
|
|
14
|
-
"@m5kdev/expo": 0.38.
|
|
15
|
-
"@m5kdev/frontend": 0.38.
|
|
16
|
-
"@m5kdev/module-clay": 0.38.
|
|
17
|
-
"@m5kdev/module-docx": 0.38.
|
|
18
|
-
"@m5kdev/module-pdf": 0.38.
|
|
19
|
-
"@m5kdev/module-social": 0.38.
|
|
20
|
-
"@m5kdev/module-video": 0.38.
|
|
21
|
-
"@m5kdev/web-ui": 0.38.
|
|
10
|
+
"@m5kdev/backend": 0.38.16
|
|
11
|
+
"@m5kdev/commons": 0.38.16
|
|
12
|
+
"@m5kdev/config": 0.38.16
|
|
13
|
+
"@m5kdev/email": 0.38.16
|
|
14
|
+
"@m5kdev/expo": 0.38.16
|
|
15
|
+
"@m5kdev/frontend": 0.38.16
|
|
16
|
+
"@m5kdev/module-clay": 0.38.16
|
|
17
|
+
"@m5kdev/module-docx": 0.38.16
|
|
18
|
+
"@m5kdev/module-pdf": 0.38.16
|
|
19
|
+
"@m5kdev/module-social": 0.38.16
|
|
20
|
+
"@m5kdev/module-video": 0.38.16
|
|
21
|
+
"@m5kdev/web-ui": 0.38.16
|
|
22
22
|
"@mastra/core": 1.51.0
|
|
23
23
|
"@openrouter/ai-sdk-provider": 3.0.0
|
|
24
24
|
"@opentelemetry/api": 1.9.0
|
|
@@ -21,6 +21,14 @@
|
|
|
21
21
|
"apps/expo/"
|
|
22
22
|
]
|
|
23
23
|
},
|
|
24
|
+
"server": {
|
|
25
|
+
"kind": "platform",
|
|
26
|
+
"paths": [
|
|
27
|
+
"apps/server/",
|
|
28
|
+
"apps/email/",
|
|
29
|
+
"apps/shared/"
|
|
30
|
+
]
|
|
31
|
+
},
|
|
24
32
|
"billing": {
|
|
25
33
|
"kind": "module",
|
|
26
34
|
"label": "Billing",
|
|
@@ -97,9 +105,6 @@
|
|
|
97
105
|
"requiredPaths": [
|
|
98
106
|
"package.json",
|
|
99
107
|
"pnpm-workspace.yaml",
|
|
100
|
-
"apps/shared/package.json",
|
|
101
|
-
"apps/server/package.json",
|
|
102
|
-
"apps/email/package.json",
|
|
103
108
|
"apps/landing/package.json"
|
|
104
109
|
],
|
|
105
110
|
"sync": {
|