create-m5kdev 0.41.0 → 0.41.1

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 (61) hide show
  1. package/package.json +1 -1
  2. package/templates/minimal-app/.cursor/rules/frontend-component-guide.mdc +95 -95
  3. package/templates/minimal-app/.cursor/rules/frontend-data-guide.mdc +103 -103
  4. package/templates/minimal-app/.cursor/rules/frontend-form-guide.mdc +80 -80
  5. package/templates/minimal-app/.cursor/rules/frontend-hook-guide.mdc +79 -79
  6. package/templates/minimal-app/.cursor/rules/frontend-i18n-guide.mdc +45 -45
  7. package/templates/minimal-app/.cursor/rules/module-dto-guide.mdc +60 -60
  8. package/templates/minimal-app/.cursor/rules/module-prompt-guide.mdc +214 -214
  9. package/templates/minimal-app/.cursor/rules/module-repository-guide.mdc +167 -167
  10. package/templates/minimal-app/.cursor/rules/module-schema-guide.mdc +53 -53
  11. package/templates/minimal-app/.cursor/rules/module-service-guide.mdc +367 -367
  12. package/templates/minimal-app/.cursor/rules/module-trpc-guide.mdc +71 -71
  13. package/templates/minimal-app/.github/workflows/check.yml.tpl +21 -0
  14. package/templates/minimal-app/AGENTS.md.tpl +22 -31
  15. package/templates/minimal-app/CLAUDE.md.tpl +15 -1
  16. package/templates/minimal-app/GLOSSARY.md.tpl +181 -0
  17. package/templates/minimal-app/README.md.tpl +2 -0
  18. package/templates/minimal-app/apps/.gitignore.tpl +13 -13
  19. package/templates/minimal-app/apps/e2e/package.json.tpl +23 -23
  20. package/templates/minimal-app/apps/email/package.json.tpl +34 -34
  21. package/templates/minimal-app/apps/expo/.gitignore.tpl +44 -44
  22. package/templates/minimal-app/apps/expo/.prettierignore +13 -13
  23. package/templates/minimal-app/apps/expo/.prettierrc.json.tpl +9 -9
  24. package/templates/minimal-app/apps/expo/CHANGELOG.md.tpl +156 -156
  25. package/templates/minimal-app/apps/expo/README.md.tpl +44 -44
  26. package/templates/minimal-app/apps/expo/expo-env.d.ts.tpl +3 -0
  27. package/templates/minimal-app/apps/expo/package.json.tpl +63 -63
  28. package/templates/minimal-app/apps/expo/uniwind-types.d.ts.tpl +10 -0
  29. package/templates/minimal-app/apps/landing/package.json.tpl +34 -34
  30. package/templates/minimal-app/apps/server/drizzle/0000_whole_echo.sql +366 -366
  31. package/templates/minimal-app/apps/server/drizzle/0002_crazy_lilith.sql +46 -46
  32. package/templates/minimal-app/apps/server/drizzle/0003_freezing_fantastic_four.sql +3 -3
  33. package/templates/minimal-app/apps/server/drizzle/0004_slow_ezekiel_stane.sql +98 -98
  34. package/templates/minimal-app/apps/server/drizzle/0005_wonderful_the_professor.sql +1 -1
  35. package/templates/minimal-app/apps/server/drizzle/0006_lazy_blue_marvel.sql +158 -158
  36. package/templates/minimal-app/apps/server/drizzle/0007_abnormal_ultimo.sql +1 -1
  37. package/templates/minimal-app/apps/server/drizzle/0008_steady_nekra.sql +86 -86
  38. package/templates/minimal-app/apps/server/drizzle/meta/0000_snapshot.json.tpl +2624 -2624
  39. package/templates/minimal-app/apps/server/drizzle/meta/0001_snapshot.json.tpl +2670 -2670
  40. package/templates/minimal-app/apps/server/drizzle/meta/0002_snapshot.json.tpl +2715 -2715
  41. package/templates/minimal-app/apps/server/drizzle/meta/0003_snapshot.json.tpl +2687 -2687
  42. package/templates/minimal-app/apps/server/drizzle/meta/0004_snapshot.json.tpl +2497 -2497
  43. package/templates/minimal-app/apps/server/drizzle/meta/0005_snapshot.json.tpl +2483 -2483
  44. package/templates/minimal-app/apps/server/drizzle/meta/0006_snapshot.json.tpl +3602 -3602
  45. package/templates/minimal-app/apps/server/drizzle/meta/0007_snapshot.json.tpl +3619 -3619
  46. package/templates/minimal-app/apps/server/drizzle/meta/0008_snapshot.json.tpl +3619 -3619
  47. package/templates/minimal-app/apps/server/drizzle/meta/_journal.json.tpl +76 -76
  48. package/templates/minimal-app/apps/server/package.json.tpl +57 -57
  49. package/templates/minimal-app/apps/server/src/app.ts.tpl +1 -0
  50. package/templates/minimal-app/apps/shared/package.json.tpl +27 -27
  51. package/templates/minimal-app/apps/webapp/AGENTS.md.tpl +24 -24
  52. package/templates/minimal-app/apps/webapp/index.html.tpl +22 -22
  53. package/templates/minimal-app/apps/webapp/package.json.tpl +53 -53
  54. package/templates/minimal-app/apps/webapp/public/logo.svg.tpl +6 -6
  55. package/templates/minimal-app/biome.json.tpl +1 -0
  56. package/templates/minimal-app/docs/adr/.gitkeep +0 -0
  57. package/templates/minimal-app/docs/agents/domain.md.tpl +38 -0
  58. package/templates/minimal-app/docs/agents/issue-tracker.md.tpl +45 -0
  59. package/templates/minimal-app/docs/agents/triage-labels.md.tpl +15 -0
  60. package/templates/minimal-app/pnpm-workspace.yaml.tpl +12 -12
  61. package/templates/minimal-app/template.manifest.json +12 -0
@@ -1,71 +1,71 @@
1
- ---
2
- globs: apps/**/server/src/modules/**/*.trpc.ts
3
- alwaysApply: false
4
- ---
5
-
6
- # Module tRPC File Style Guide
7
-
8
- Conventions for tRPC router files in app modules. Routers are thin wiring:
9
- they attach the module DTO schemas and delegate to the service. The router is
10
- also the type source for the client — the webapp infers all row/list types
11
- from `AppRouter`, so accurate `.input()`/`.output()` here is what makes
12
- end-to-end types work.
13
-
14
- ## File Location
15
-
16
- ```
17
- apps/<app>/server/src/modules/<module>/<module>.trpc.ts
18
- ```
19
-
20
- ## Conventions
21
-
22
- - Export a factory function named `create<Module>TRPC`.
23
- - Import the module DTO object (`postSchemas`) from `./<module>.dto` — not
24
- shared schemas, not hand-written types.
25
- - Use `handleTRPCResult` from `@m5kdev/backend/utils/trpc` to unwrap `Result`s.
26
- - Keep resolvers one-liners that delegate to the service; no business logic or
27
- DB access here.
28
- - Always pass `ctx` to service methods as the second argument. The first
29
- argument (`input`) can be `undefined` for optional-input queries.
30
-
31
- ## Factory Pattern
32
-
33
- ```typescript
34
- import { handleTRPCResult, type TRPCMethods } from "@m5kdev/backend/utils/trpc";
35
- import { postSchemas } from "./posts.dto";
36
- import type { PostsService } from "./posts.service";
37
-
38
- export function createPostsTRPC(
39
- { router, privateProcedure: procedure }: TRPCMethods,
40
- postsService: PostsService
41
- ) {
42
- return router({
43
- list: procedure
44
- .input(postSchemas.input.list)
45
- .output(postSchemas.output.list)
46
- .query(async ({ ctx, input }) => handleTRPCResult(await postsService.list(input ?? {}, ctx))),
47
-
48
- create: procedure
49
- .input(postSchemas.input.create)
50
- .output(postSchemas.output.single)
51
- .mutation(async ({ ctx, input }) => handleTRPCResult(await postsService.create(input, ctx))),
52
-
53
- softDelete: procedure
54
- .input(postSchemas.input.delete)
55
- .output(postSchemas.output.uuid)
56
- .mutation(async ({ ctx, input }) =>
57
- handleTRPCResult(await postsService.softDelete(input, ctx))
58
- ),
59
- });
60
- }
61
- ```
62
-
63
- ## Procedure Selection
64
-
65
- - `privateProcedure` — authenticated user (most module routes).
66
- - `organizationProcedure` — requires an active organization.
67
- - `adminProcedure` — admin role.
68
- - `publicProcedure` — unauthenticated; use sparingly.
69
-
70
- The service's own `.requireAuth()`/`.access()` still run — the tRPC procedure
71
- choice is transport-level gating, not a replacement for service checks.
1
+ ---
2
+ globs: apps/**/server/src/modules/**/*.trpc.ts
3
+ alwaysApply: false
4
+ ---
5
+
6
+ # Module tRPC File Style Guide
7
+
8
+ Conventions for tRPC router files in app modules. Routers are thin wiring:
9
+ they attach the module DTO schemas and delegate to the service. The router is
10
+ also the type source for the client — the webapp infers all row/list types
11
+ from `AppRouter`, so accurate `.input()`/`.output()` here is what makes
12
+ end-to-end types work.
13
+
14
+ ## File Location
15
+
16
+ ```
17
+ apps/<app>/server/src/modules/<module>/<module>.trpc.ts
18
+ ```
19
+
20
+ ## Conventions
21
+
22
+ - Export a factory function named `create<Module>TRPC`.
23
+ - Import the module DTO object (`postSchemas`) from `./<module>.dto` — not
24
+ shared schemas, not hand-written types.
25
+ - Use `handleTRPCResult` from `@m5kdev/backend/utils/trpc` to unwrap `Result`s.
26
+ - Keep resolvers one-liners that delegate to the service; no business logic or
27
+ DB access here.
28
+ - Always pass `ctx` to service methods as the second argument. The first
29
+ argument (`input`) can be `undefined` for optional-input queries.
30
+
31
+ ## Factory Pattern
32
+
33
+ ```typescript
34
+ import { handleTRPCResult, type TRPCMethods } from "@m5kdev/backend/utils/trpc";
35
+ import { postSchemas } from "./posts.dto";
36
+ import type { PostsService } from "./posts.service";
37
+
38
+ export function createPostsTRPC(
39
+ { router, privateProcedure: procedure }: TRPCMethods,
40
+ postsService: PostsService
41
+ ) {
42
+ return router({
43
+ list: procedure
44
+ .input(postSchemas.input.list)
45
+ .output(postSchemas.output.list)
46
+ .query(async ({ ctx, input }) => handleTRPCResult(await postsService.list(input ?? {}, ctx))),
47
+
48
+ create: procedure
49
+ .input(postSchemas.input.create)
50
+ .output(postSchemas.output.single)
51
+ .mutation(async ({ ctx, input }) => handleTRPCResult(await postsService.create(input, ctx))),
52
+
53
+ softDelete: procedure
54
+ .input(postSchemas.input.delete)
55
+ .output(postSchemas.output.uuid)
56
+ .mutation(async ({ ctx, input }) =>
57
+ handleTRPCResult(await postsService.softDelete(input, ctx))
58
+ ),
59
+ });
60
+ }
61
+ ```
62
+
63
+ ## Procedure Selection
64
+
65
+ - `privateProcedure` — authenticated user (most module routes).
66
+ - `organizationProcedure` — requires an active organization.
67
+ - `adminProcedure` — admin role.
68
+ - `publicProcedure` — unauthenticated; use sparingly.
69
+
70
+ The service's own `.requireAuth()`/`.access()` still run — the tRPC procedure
71
+ choice is transport-level gating, not a replacement for service checks.
@@ -0,0 +1,21 @@
1
+ name: check
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ check:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v4
12
+ - uses: pnpm/action-setup@v4
13
+ with:
14
+ version: 10.13.1
15
+ - uses: actions/setup-node@v4
16
+ with:
17
+ node-version: 24
18
+ cache: pnpm
19
+ - run: pnpm install
20
+ - run: pnpm lint
21
+ - run: pnpm check-types
@@ -22,38 +22,29 @@
22
22
  // m5k:expo:end
23
23
 
24
24
  // m5k:server:start
25
- ## Backend Conventions
26
-
27
- - Keep repository, service, and transport layers separate inside each module.
28
- - Register modules in `apps/server/src/app.ts` via `createBackendApp(config, [modules])`.
29
- - Import Kernel infrastructure (`BaseModule`, Grants, DTOs) from `@m5kdev/backend/base/*`. The `modules/base` path still re-exports.
30
- - 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.
31
- - Use `BaseModule` subclasses for app modules; the kernel wires repositories, services, and tRPC.
32
- - Keep tRPC files focused on input/output wiring and delegate logic to services.
33
- - 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.
34
- - Renaming a dependency method, repackaging arguments, constructing a prompt, or forwarding actor/context data alone does not justify a service wrapper.
35
- - Do not create Drizzle migrations by hand. Use the scaffolded config and your project migration workflow later if you need generated migrations.
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
25
+ ## Modules
26
+
27
+ `posts` is the reference module. Mirror its layout when adding a feature:
38
28
 
29
+ - `apps/shared/src/modules/posts/`
30
+ - `apps/server/src/modules/posts/`
39
31
  // m5k:webapp:start
40
- ## Frontend Conventions
41
-
42
- - Keep the app shell shape: `NuqsAdapter` + `BrowserRouter` + `Providers`.
43
- - Compose global providers only in `apps/webapp/src/Providers.tsx`.
44
- - Use `AppConfigProvider` and `AppTrpcQueryProvider` from `@m5kdev/frontend`; use `@m5kdev/web-ui` for web-only UI.
45
- - Define app roles in `apps/shared/src/modules/app/roles.constants.ts` and pass `roles: APP_ROLES_CONFIG` through `AppConfigProvider` and `createBackendApp` metadata.
46
- - Add role display labels in `apps/webapp/translations/app.json` using keys like `organization.role.editor` (resolved as `app:organization.role.editor`).
47
- - When adding custom roles, also extend module grants (for example `*.grants.ts`) so permissions match the new role keys.
48
- - For upgrading existing apps, see the docs site guide `apps/docs/docs/guides/custom-app-roles-migration.md`.
49
- - Use `nuqs` for URL state, React Router for routing, HeroUI for UI primitives, and Tailwind v4 for styling.
50
- - Prefer shared framework utilities from `@m5kdev/frontend` and `@m5kdev/web-ui` before adding local duplicates.
51
- - React 19 idioms: no `forwardRef` (pass `ref` as a prop), no `defaultProps`, use `startTransition`/`useDeferredValue` for low-priority updates.
52
- - Prefer HeroUI v3 components over hand-rolled HTML + Tailwind whenever an equivalent exists; Tailwind is for layout and styling on top of them.
53
- - Keep components display-focused: data fetching, mutations, URL state, and effect chains live in custom hooks under `modules/<feature>/hooks/` (small focused hooks composed into one screen-level hook, e.g. `usePostsRoute`). Ephemeral UI state (modal open, selected row) may stay in the component. Extract reusable tRPC actions (delete, publish) into their own hooks.
54
- - Fetch all server data with TanStack Query over tRPC (`useTRPC()` + `queryOptions`/`mutationOptions`); invalidate with the matching `queryFilter()` after mutations. No `fetch`/axios.
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.
56
- - All user-facing copy goes through i18next (`useTranslation`); keys live in `apps/webapp/translations/`.
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.
32
+ - `apps/webapp/src/modules/posts/`
58
33
  // m5k:webapp:end
59
34
 
35
+ Read the matching `.cursor/rules` guide before editing a module file.
36
+ // m5k:server:end
37
+
38
+ ## Agent skills
39
+
40
+ ### Issue tracker
41
+
42
+ Issues live in GitHub Issues. Use the `gh` CLI. See `docs/agents/issue-tracker.md`.
43
+
44
+ ### Triage labels
45
+
46
+ Default role labels: `needs-triage`, `needs-info`, `ready-for-agent`, `ready-for-human`, `wontfix`. See `docs/agents/triage-labels.md`.
47
+
48
+ ### Domain docs
49
+
50
+ Single-context: one root `GLOSSARY.md` and `docs/adr/`. See `docs/agents/domain.md`.
@@ -139,6 +139,20 @@ The framework's detailed conventions live in `.cursor/rules/*.mdc`. Cursor appli
139
139
  | `.cursor/rules/frontend-i18n-guide.mdc` | webapp user-facing copy |
140
140
  // m5k:webapp:end
141
141
 
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.
142
+ `AGENTS.md` (repo root and per-app) points at this file and `.cursor/rules`. This file plus the guides above are the authoritative conventions.
143
143
  // m5k:server:end
144
144
 
145
+ ## Agent skills
146
+
147
+ ### Issue tracker
148
+
149
+ Issues live in GitHub Issues. Use the `gh` CLI. See `docs/agents/issue-tracker.md`.
150
+
151
+ ### Triage labels
152
+
153
+ Default role labels: `needs-triage`, `needs-info`, `ready-for-agent`, `ready-for-human`, `wontfix`. See `docs/agents/triage-labels.md`.
154
+
155
+ ### Domain docs
156
+
157
+ Single-context: one root `GLOSSARY.md` and `docs/adr/`. See `docs/agents/domain.md`.
158
+
@@ -0,0 +1,181 @@
1
+ # {{APP_NAME}}
2
+
3
+ {{APP_DESCRIPTION}}
4
+
5
+ ## Language
6
+ # m5k:server:start
7
+
8
+ ### Tenancy
9
+
10
+ **Organization**:
11
+ The default tenancy unit. Signup creates one; a Closed Organization cannot be used.
12
+ _Avoid_: Workspace, tenant, account, company, Team
13
+
14
+ **Membership**:
15
+ A durable seat in an Organization. Invite can create it before a User exists; leave, cancel, and expiry soft-delete it; rejoin revives the same MemberId. An Organization has exactly one Owner.
16
+ _Avoid_: OrgUser; treating Invitation as the Membership; Seat (that is Seat billing)
17
+
18
+ **Member**:
19
+ The Membership principal used to attribute and authorize org-scoped assets, including invited Memberships that do not yet have a User.
20
+ _Avoid_: User (when you mean the membership), Invitation
21
+
22
+ **MemberId**:
23
+ The Membership id stamped on org-scoped rows. In organization context, `"own"` grants compare this, not UserId.
24
+ _Avoid_: UserId as the org ownership key
25
+
26
+ **User**:
27
+ The global sign-in identity. Owns personal resources that are not org tenancy. A Closed User cannot sign in.
28
+ _Avoid_: Account, Customer, Client, Member
29
+
30
+ **UserId**:
31
+ The User id. Correct key for personal resources. Not the org-scoped ownership key.
32
+ _Avoid_: MemberId
33
+
34
+ **Owner**:
35
+ The Organization Role `owner`. Exactly one per Organization. Invite and org self-service cannot grant or transfer it.
36
+ _Avoid_: multiple Owners as a product feature; inviting Owner
37
+
38
+ **Invitation**:
39
+ The accept token that attaches a User to an invited Membership. Not a person and not assignable.
40
+ _Avoid_: Waitlist code, pending Member
41
+
42
+ **Closed**:
43
+ A User or Organization in the restorable lockout state.
44
+ _Avoid_: soft-delete (that is Membership leave), deactivated, suspended, banned
45
+
46
+ **Restore**:
47
+ Returning a Closed User or Organization to usable state before Purge. Admin panel only.
48
+ _Avoid_: undelete, reactivate
49
+
50
+ **Purge**:
51
+ Permanent removal of a Closed User or Organization after the grace window.
52
+ _Avoid_: hard-delete as the User-facing noun
53
+
54
+ ### Identity and access
55
+
56
+ **Actor**:
57
+ Who a server call is made on behalf of: User, Organization, or Admin. Organization scope requires a live Membership and an Organization that is not Closed. Invited Members are not Actors.
58
+ _Avoid_: Session, Principal, Request, TeamActor
59
+
60
+ **Grant**:
61
+ A permission tuple: resource, level (`user` | `organization`), role, Action, Access.
62
+ _Avoid_: Permission, Policy, ACL
63
+
64
+ **Action**:
65
+ Canonical Grant verbs: `read`, `write`, `delete`, `publish`.
66
+ _Avoid_: update, create, patch, remove
67
+
68
+ **Access**:
69
+ How wide a Grant is: `all`, `own`, `org`, `none`.
70
+ _Avoid_: Scope, Role
71
+
72
+ **Role**:
73
+ A named key at User or Organization scope. Defaults: User `user`/`admin`; Organization `member`/`admin`/`owner`.
74
+ _Avoid_: Grant, Access, permission
75
+
76
+ ### Product surfaces
77
+
78
+ **Admin panel**:
79
+ The User-role admin UI at `/admin`. Organization Role `admin` does not see it.
80
+ _Avoid_: org Role admin, Billing Portal
81
+ # m5k:files:start
82
+
83
+ **File**:
84
+ An inventoried object in storage: a row plus the bytes. Personal Files stamp UserId; org-scoped Files stamp MemberId.
85
+ _Avoid_: Upload, Asset, Attachment, Blob
86
+ # m5k:files:end
87
+ # m5k:billing:start
88
+
89
+ **Plan**:
90
+ Named commercial offering in app code. Not a Stripe Product.
91
+ _Avoid_: Product, Tier, Subscription
92
+
93
+ **Subscription**:
94
+ The billed relationship for an Organization, not a User.
95
+ _Avoid_: Plan, personal User subscription
96
+
97
+ **Checkout**:
98
+ Hosted start of a Subscription when the Organization has none.
99
+ _Avoid_: Billing Portal
100
+
101
+ **Billing Portal**:
102
+ Hosted management of an existing Subscription.
103
+ _Avoid_: Checkout
104
+
105
+ **Seat billing**:
106
+ When on, billable quantity is the count of Memberships. Off (default): quantity is one.
107
+ _Avoid_: Seat as a synonym for Membership
108
+ # m5k:billing:end
109
+ # m5k:ai:start
110
+
111
+ **Conversation**:
112
+ Ordered UI transcript of AI turns.
113
+ _Avoid_: Chat, Thread (that is the store)
114
+
115
+ **Thread**:
116
+ The persisted AI memory thread behind a Conversation.
117
+ _Avoid_: using Thread for the UI surface
118
+
119
+ **Agent**:
120
+ A named AI agent the app registers. A Conversation selects which Agent answers.
121
+ _Avoid_: Assistant, Bot, MCP client
122
+ # m5k:ai:end
123
+ # m5k:mcp:start
124
+
125
+ **MCP client**:
126
+ A remote Model Context Protocol client that calls the app on behalf of a User.
127
+ _Avoid_: Agent, Connection
128
+
129
+ **MCP call**:
130
+ A tRPC procedure opted into the MCP catalog. Grant checks always run.
131
+ _Avoid_: a second tool catalog, Workflow job
132
+
133
+ **MCP allowlist**:
134
+ The Organizations a given OAuth client may pass as organizationId for a User.
135
+ _Avoid_: treating allowlist as permission to write
136
+ # m5k:mcp:end
137
+ # m5k:notifications:start
138
+
139
+ **Notification**:
140
+ A persisted inbox instance owned by a Member, classified by a Notification kind.
141
+ _Avoid_: UserId as the ownership key
142
+
143
+ **Notification kind**:
144
+ A developer-declared class of Notifications. Mute applies to the kind.
145
+ _Avoid_: Notification (that is the instance)
146
+
147
+ **Channel**:
148
+ A delivery means for a Notification: in-app, web push, mobile push, or email.
149
+ _Avoid_: Server event, Device
150
+ # m5k:notifications:end
151
+ # m5k:workflows:start
152
+
153
+ **Workflow**:
154
+ A persisted background run. Org-scoped runs stamp MemberId.
155
+ _Avoid_: Job, Queue, Task, Recurrence
156
+ # m5k:workflows:end
157
+ # m5k:tags:start
158
+
159
+ **Tag**:
160
+ A polymorphic label. Ownership is UserId, MemberId, or organizationId.
161
+ _Avoid_: Label, Category
162
+ # m5k:tags:end
163
+ # m5k:connect:start
164
+
165
+ **Connection**:
166
+ A linked third-party API account. Personal; keyed by UserId. The module id is `connect`.
167
+ _Avoid_: Connect as the product noun; login OAuth
168
+ # m5k:connect:end
169
+ # m5k:webhook:start
170
+
171
+ **Inbound callback**:
172
+ A one-shot inbound callback with an awaitable payload. Unattributed. The module id is `webhook`.
173
+ _Avoid_: Webhook (when you mean this vs Stripe Subscription sync); Connection
174
+ # m5k:webhook:end
175
+ # m5k:recurrence:start
176
+
177
+ **Recurrence**:
178
+ A repeating calendar pattern stored as a row. Not a Workflow.
179
+ _Avoid_: Workflow, cron
180
+ # m5k:recurrence:end
181
+ # m5k:server:end
@@ -39,6 +39,8 @@ Database tables are registered by hand in `apps/server/src/schema.ts`; after cha
39
39
 
40
40
  - Email: `admin@{{APP_SLUG}}.local`
41
41
  - Password: `password1234`
42
+
43
+ After sign-in, the index route (`/`) is the Posts list.
42
44
  // m5k:server:end
43
45
 
44
46
  ## Typical Commands
@@ -1,13 +1,13 @@
1
- # runtime artifacts
2
- server/local.db*
3
- server/.e2e/
4
- server/.emails/
5
- server/uploads/
6
-
7
- # e2e output
8
- e2e/test-results/
9
- e2e/playwright-report/
10
-
11
- # expo
12
- expo/.expo/
13
- expo/dist/
1
+ # runtime artifacts
2
+ server/local.db*
3
+ server/.e2e/
4
+ server/.emails/
5
+ server/uploads/
6
+
7
+ # e2e output
8
+ e2e/test-results/
9
+ e2e/playwright-report/
10
+
11
+ # expo
12
+ expo/.expo/
13
+ expo/dist/
@@ -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
+ }
@@ -1,34 +1,34 @@
1
- {
2
- "name": "{{PACKAGE_SCOPE}}/email",
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
- "email:dev": "react-email dev --dir src/emails"
11
- },
12
- "dependencies": {
13
- "@m5kdev/commons": "catalog:m5kdev",
14
- "@m5kdev/email": "catalog:m5kdev",
15
- "@react-email/components": "catalog:m5kdev",
16
- "react": "catalog:m5kdev",
17
- "react-dom": "catalog:m5kdev"
18
- },
19
- "devDependencies": {
20
- "@m5kdev/backend": "catalog:m5kdev",
21
- "@m5kdev/config": "catalog:m5kdev",
22
- "@types/node": "catalog:m5kdev",
23
- "@types/react": "catalog:m5kdev",
24
- "@types/react-dom": "catalog:m5kdev",
25
- "react-email": "catalog:m5kdev",
26
- "tslib": "catalog:m5kdev",
27
- "typescript": "catalog:m5kdev"
28
- },
29
- "main": "./src/index.ts",
30
- "exports": {
31
- ".": "./src/index.ts",
32
- "./resources": "./src/resources.ts"
33
- }
34
- }
1
+ {
2
+ "name": "{{PACKAGE_SCOPE}}/email",
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
+ "email:dev": "react-email dev --dir src/emails"
11
+ },
12
+ "dependencies": {
13
+ "@m5kdev/commons": "catalog:m5kdev",
14
+ "@m5kdev/email": "catalog:m5kdev",
15
+ "@react-email/components": "catalog:m5kdev",
16
+ "react": "catalog:m5kdev",
17
+ "react-dom": "catalog:m5kdev"
18
+ },
19
+ "devDependencies": {
20
+ "@m5kdev/backend": "catalog:m5kdev",
21
+ "@m5kdev/config": "catalog:m5kdev",
22
+ "@types/node": "catalog:m5kdev",
23
+ "@types/react": "catalog:m5kdev",
24
+ "@types/react-dom": "catalog:m5kdev",
25
+ "react-email": "catalog:m5kdev",
26
+ "tslib": "catalog:m5kdev",
27
+ "typescript": "catalog:m5kdev"
28
+ },
29
+ "main": "./src/index.ts",
30
+ "exports": {
31
+ ".": "./src/index.ts",
32
+ "./resources": "./src/resources.ts"
33
+ }
34
+ }
@@ -1,44 +1,44 @@
1
- # Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files
2
-
3
- # Dependencies
4
- node_modules/
5
-
6
- # Expo
7
- .expo/
8
- dist/
9
- web-build/
10
- expo-env.d.ts
11
-
12
- # Uniwind (generated on first `expo start`)
13
- uniwind-types.d.ts
14
-
15
- # Native
16
- .kotlin/
17
- *.orig.*
18
- *.jks
19
- *.p8
20
- *.p12
21
- *.key
22
- *.mobileprovision
23
-
24
- # Metro
25
- .metro-health-check*
26
-
27
- # Debug
28
- npm-debug.*
29
- yarn-debug.*
30
- yarn-error.*
31
-
32
- # macOS
33
- .DS_Store
34
- *.pem
35
-
36
- # Local env files
37
- .env*.local
38
-
39
- # TypeScript
40
- *.tsbuildinfo
41
-
42
- # Generated native folders
43
- /ios
44
- /android
1
+ # Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files
2
+
3
+ # Dependencies
4
+ node_modules/
5
+
6
+ # Expo
7
+ .expo/
8
+ dist/
9
+ web-build/
10
+ expo-env.d.ts
11
+
12
+ # Uniwind (generated on first `expo start`)
13
+ uniwind-types.d.ts
14
+
15
+ # Native
16
+ .kotlin/
17
+ *.orig.*
18
+ *.jks
19
+ *.p8
20
+ *.p12
21
+ *.key
22
+ *.mobileprovision
23
+
24
+ # Metro
25
+ .metro-health-check*
26
+
27
+ # Debug
28
+ npm-debug.*
29
+ yarn-debug.*
30
+ yarn-error.*
31
+
32
+ # macOS
33
+ .DS_Store
34
+ *.pem
35
+
36
+ # Local env files
37
+ .env*.local
38
+
39
+ # TypeScript
40
+ *.tsbuildinfo
41
+
42
+ # Generated native folders
43
+ /ios
44
+ /android