@mars-stack/cli 0.2.0 → 0.2.2

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 (173) hide show
  1. package/package.json +2 -2
  2. package/template/.cursor/rules/composition-patterns.mdc +186 -0
  3. package/template/.cursor/rules/data-access.mdc +29 -0
  4. package/template/.cursor/rules/project-structure.mdc +34 -0
  5. package/template/.cursor/rules/security.mdc +25 -0
  6. package/template/.cursor/rules/testing.mdc +24 -0
  7. package/template/.cursor/rules/ui-conventions.mdc +29 -0
  8. package/template/.cursor/skills/add-api-route/SKILL.md +122 -0
  9. package/template/.cursor/skills/add-audit-log/SKILL.md +373 -0
  10. package/template/.cursor/skills/add-blog/SKILL.md +447 -0
  11. package/template/.cursor/skills/add-command-palette/SKILL.md +438 -0
  12. package/template/.cursor/skills/add-component/SKILL.md +158 -0
  13. package/template/.cursor/skills/add-crud-routes/SKILL.md +221 -0
  14. package/template/.cursor/skills/add-e2e-test/SKILL.md +227 -0
  15. package/template/.cursor/skills/add-error-boundary/SKILL.md +472 -0
  16. package/template/.cursor/skills/add-feature/SKILL.md +174 -0
  17. package/template/.cursor/skills/add-middleware/SKILL.md +135 -0
  18. package/template/.cursor/skills/add-page/SKILL.md +151 -0
  19. package/template/.cursor/skills/add-prisma-model/SKILL.md +148 -0
  20. package/template/.cursor/skills/add-protected-resource/SKILL.md +192 -0
  21. package/template/.cursor/skills/add-role/SKILL.md +156 -0
  22. package/template/.cursor/skills/add-server-action/SKILL.md +167 -0
  23. package/template/.cursor/skills/add-webhook/SKILL.md +192 -0
  24. package/template/.cursor/skills/build-complete-feature/SKILL.md +227 -0
  25. package/template/.cursor/skills/build-dashboard/SKILL.md +211 -0
  26. package/template/.cursor/skills/build-data-table/SKILL.md +283 -0
  27. package/template/.cursor/skills/build-form/SKILL.md +231 -0
  28. package/template/.cursor/skills/build-landing-page/SKILL.md +248 -0
  29. package/template/.cursor/skills/configure-ai/SKILL.md +617 -0
  30. package/template/.cursor/skills/configure-analytics/SKILL.md +413 -0
  31. package/template/.cursor/skills/configure-dark-mode/SKILL.md +309 -0
  32. package/template/.cursor/skills/configure-email/SKILL.md +170 -0
  33. package/template/.cursor/skills/configure-email-verification/SKILL.md +333 -0
  34. package/template/.cursor/skills/configure-feature-flags/SKILL.md +361 -0
  35. package/template/.cursor/skills/configure-i18n/SKILL.md +518 -0
  36. package/template/.cursor/skills/configure-jobs/SKILL.md +500 -0
  37. package/template/.cursor/skills/configure-magic-links/SKILL.md +385 -0
  38. package/template/.cursor/skills/configure-multi-tenancy/SKILL.md +611 -0
  39. package/template/.cursor/skills/configure-notifications/SKILL.md +569 -0
  40. package/template/.cursor/skills/configure-oauth/SKILL.md +217 -0
  41. package/template/.cursor/skills/configure-onboarding/SKILL.md +483 -0
  42. package/template/.cursor/skills/configure-payments/SKILL.md +243 -0
  43. package/template/.cursor/skills/configure-realtime/SKILL.md +733 -0
  44. package/template/.cursor/skills/configure-search/SKILL.md +581 -0
  45. package/template/.cursor/skills/configure-storage/SKILL.md +273 -0
  46. package/template/.cursor/skills/configure-two-factor/SKILL.md +518 -0
  47. package/template/.cursor/skills/create-execution-plan/SKILL.md +204 -0
  48. package/template/.cursor/skills/create-seed/SKILL.md +191 -0
  49. package/template/.cursor/skills/deploy-to-vercel/SKILL.md +300 -0
  50. package/template/.cursor/skills/design-tokens/SKILL.md +138 -0
  51. package/template/.cursor/skills/mars-capture-conversation-context/SKILL.md +119 -0
  52. package/template/.cursor/skills/setup-billing/SKILL.md +322 -0
  53. package/template/.cursor/skills/setup-project/SKILL.md +104 -0
  54. package/template/.cursor/skills/setup-teams/SKILL.md +682 -0
  55. package/template/.cursor/skills/test-api-route/SKILL.md +219 -0
  56. package/template/.cursor/skills/update-architecture-docs/SKILL.md +99 -0
  57. package/template/AGENTS.md +104 -0
  58. package/template/ARCHITECTURE.md +102 -0
  59. package/template/docs/QUALITY_SCORE.md +20 -0
  60. package/template/docs/design-docs/conversation-as-system-record.md +70 -0
  61. package/template/docs/design-docs/core-beliefs.md +43 -0
  62. package/template/docs/design-docs/index.md +8 -0
  63. package/template/docs/exec-plans/active/.gitkeep +0 -0
  64. package/template/docs/exec-plans/completed/.gitkeep +0 -0
  65. package/template/docs/exec-plans/tech-debt.md +7 -0
  66. package/template/docs/generated/.gitkeep +0 -0
  67. package/template/docs/product-specs/index.md +7 -0
  68. package/template/docs/references/index.md +18 -0
  69. package/template/e2e/api.spec.ts +20 -0
  70. package/template/e2e/auth.spec.ts +24 -0
  71. package/template/e2e/public.spec.ts +25 -0
  72. package/template/eslint.config.mjs +24 -0
  73. package/template/next-env.d.ts +6 -0
  74. package/template/next.config.ts +45 -0
  75. package/template/package.json +80 -0
  76. package/template/playwright.config.ts +31 -0
  77. package/template/postcss.config.mjs +8 -0
  78. package/template/prisma/generated/prisma/browser.ts +49 -0
  79. package/template/prisma/generated/prisma/client.ts +73 -0
  80. package/template/prisma/generated/prisma/commonInputTypes.ts +406 -0
  81. package/template/prisma/generated/prisma/enums.ts +15 -0
  82. package/template/prisma/generated/prisma/internal/class.ts +254 -0
  83. package/template/prisma/generated/prisma/internal/prismaNamespace.ts +1240 -0
  84. package/template/prisma/generated/prisma/internal/prismaNamespaceBrowser.ts +190 -0
  85. package/template/prisma/generated/prisma/models/Account.ts +1543 -0
  86. package/template/prisma/generated/prisma/models/File.ts +1529 -0
  87. package/template/prisma/generated/prisma/models/Session.ts +1415 -0
  88. package/template/prisma/generated/prisma/models/Subscription.ts +1455 -0
  89. package/template/prisma/generated/prisma/models/User.ts +2235 -0
  90. package/template/prisma/generated/prisma/models/VerificationToken.ts +1099 -0
  91. package/template/prisma/generated/prisma/models.ts +17 -0
  92. package/template/prisma/schema/auth.prisma +69 -0
  93. package/template/prisma/schema/base.prisma +8 -0
  94. package/template/prisma/schema/file.prisma +15 -0
  95. package/template/prisma/schema/subscription.prisma +17 -0
  96. package/template/prisma.config.ts +13 -0
  97. package/template/scripts/check-architecture.ts +221 -0
  98. package/template/scripts/check-doc-freshness.ts +242 -0
  99. package/template/scripts/ensure-db.mjs +291 -0
  100. package/template/scripts/generate-docs.ts +143 -0
  101. package/template/scripts/generate-env-example.ts +89 -0
  102. package/template/scripts/seed.ts +56 -0
  103. package/template/scripts/update-quality-score.ts +263 -0
  104. package/template/src/__tests__/architecture.test.ts +114 -0
  105. package/template/src/app/(auth)/forgotten-password/page.tsx +92 -0
  106. package/template/src/app/(auth)/layout.tsx +11 -0
  107. package/template/src/app/(auth)/register/page.tsx +162 -0
  108. package/template/src/app/(auth)/reset-password/page.tsx +109 -0
  109. package/template/src/app/(auth)/sign-in/page.tsx +122 -0
  110. package/template/src/app/(auth)/verify/[token]/page.tsx +87 -0
  111. package/template/src/app/(auth)/verify/page.tsx +56 -0
  112. package/template/src/app/(protected)/admin/page.tsx +108 -0
  113. package/template/src/app/(protected)/dashboard/loading.tsx +20 -0
  114. package/template/src/app/(protected)/dashboard/page.tsx +22 -0
  115. package/template/src/app/(protected)/layout.tsx +262 -0
  116. package/template/src/app/(protected)/settings/page.tsx +370 -0
  117. package/template/src/app/api/auth/forgot/route.ts +63 -0
  118. package/template/src/app/api/auth/login/route.ts +121 -0
  119. package/template/src/app/api/auth/logout/route.ts +19 -0
  120. package/template/src/app/api/auth/me/route.ts +30 -0
  121. package/template/src/app/api/auth/reset/route.ts +45 -0
  122. package/template/src/app/api/auth/signup/route.ts +85 -0
  123. package/template/src/app/api/auth/verify/route.ts +46 -0
  124. package/template/src/app/api/csrf/route.ts +12 -0
  125. package/template/src/app/api/health/route.ts +10 -0
  126. package/template/src/app/api/protected/admin/users/route.ts +24 -0
  127. package/template/src/app/api/protected/billing/checkout/route.ts +83 -0
  128. package/template/src/app/api/protected/billing/portal/route.ts +39 -0
  129. package/template/src/app/api/protected/files/[fileId]/route.ts +86 -0
  130. package/template/src/app/api/protected/files/upload/route.ts +64 -0
  131. package/template/src/app/api/protected/user/password/route.ts +63 -0
  132. package/template/src/app/api/protected/user/profile/route.ts +35 -0
  133. package/template/src/app/api/protected/user/sessions/[sessionId]/route.ts +33 -0
  134. package/template/src/app/api/protected/user/sessions/route.ts +22 -0
  135. package/template/src/app/api/readiness/route.ts +15 -0
  136. package/template/src/app/api/webhooks/stripe/route.ts +166 -0
  137. package/template/src/app/error.tsx +33 -0
  138. package/template/src/app/layout.tsx +29 -0
  139. package/template/src/app/not-found.tsx +20 -0
  140. package/template/src/app/page.tsx +136 -0
  141. package/template/src/app/privacy/page.tsx +178 -0
  142. package/template/src/app/providers.tsx +8 -0
  143. package/template/src/app/terms/page.tsx +139 -0
  144. package/template/src/config/app.config.ts +70 -0
  145. package/template/src/config/routes.ts +17 -0
  146. package/template/src/features/admin/index.ts +11 -0
  147. package/template/src/features/admin/permissions.ts +64 -0
  148. package/template/src/features/auth/context/AuthContext.tsx +96 -0
  149. package/template/src/features/auth/context/index.ts +2 -0
  150. package/template/src/features/auth/index.ts +3 -0
  151. package/template/src/features/auth/server/consent.ts +66 -0
  152. package/template/src/features/auth/server/session-revocation.ts +20 -0
  153. package/template/src/features/auth/server/sessions.ts +66 -0
  154. package/template/src/features/auth/server/user.ts +166 -0
  155. package/template/src/features/auth/types.ts +19 -0
  156. package/template/src/features/auth/validators.ts +29 -0
  157. package/template/src/features/billing/server/index.ts +66 -0
  158. package/template/src/features/billing/types.ts +43 -0
  159. package/template/src/features/uploads/server/index.ts +49 -0
  160. package/template/src/features/uploads/types.ts +26 -0
  161. package/template/src/lib/core/email/templates/base-layout.ts +122 -0
  162. package/template/src/lib/core/email/templates/index.ts +4 -0
  163. package/template/src/lib/core/email/templates/password-reset-email.ts +42 -0
  164. package/template/src/lib/core/email/templates/verification-email.ts +41 -0
  165. package/template/src/lib/core/email/templates/welcome-email.ts +40 -0
  166. package/template/src/lib/mars.ts +56 -0
  167. package/template/src/lib/prisma.ts +19 -0
  168. package/template/src/proxy.ts +92 -0
  169. package/template/src/styles/brand.css +17 -0
  170. package/template/src/styles/globals.css +6 -0
  171. package/template/tsconfig.json +59 -0
  172. package/template/vitest.config.ts +41 -0
  173. package/template/vitest.setup.ts +24 -0
@@ -0,0 +1,204 @@
1
+ # Skill: Create Execution Plan
2
+
3
+ Create and manage execution plans in `docs/exec-plans/` to track multi-step implementation work with clear goals, tasks, and verification criteria.
4
+
5
+ ## When to Use
6
+
7
+ Use this skill when:
8
+ - Starting a large or multi-step implementation task
9
+ - The user asks to plan work, create a plan, or organise tasks
10
+ - A meta-skill needs to create a plan before executing
11
+ - You need to track progress across multiple related changes
12
+
13
+ ## Prerequisites
14
+
15
+ - Read `docs/exec-plans/` to see existing plans and the directory structure.
16
+ - Read `docs/QUALITY_SCORE.md` to understand current quality grades.
17
+
18
+ ## Plan Directory Structure
19
+
20
+ ```
21
+ docs/exec-plans/
22
+ ├── active/ # Plans currently being worked on
23
+ │ └── <plan-name>.md
24
+ ├── completed/ # Finished plans (moved from active/)
25
+ │ └── <plan-name>.md
26
+ └── templates/ # (optional) Plan templates
27
+ ```
28
+
29
+ ## Step 1: Choose a Plan Name
30
+
31
+ Use kebab-case that describes the goal, not the method:
32
+
33
+ | Good | Bad |
34
+ |------|-----|
35
+ | `add-billing-system` | `stripe-integration` |
36
+ | `fix-auth-redirects` | `update-middleware` |
37
+ | `setup-team-management` | `prisma-models` |
38
+
39
+ ## Step 2: Create the Plan File
40
+
41
+ ```markdown
42
+ # Execution Plan: <Title>
43
+
44
+ **Status:** Active
45
+ **Priority:** P0 / P1 / P2
46
+ **Created:** <YYYY-MM-DD>
47
+ **Estimated effort:** S / M / L / XL
48
+
49
+ ## Goal
50
+
51
+ <1-2 sentences describing the end state. What does "done" look like? Focus on user-visible outcomes.>
52
+
53
+ ## Context
54
+
55
+ <Why is this work needed? What problem does it solve? Link to related issues, quality score entries, or design docs.>
56
+
57
+ ## Tasks
58
+
59
+ - [ ] **1.1 <Task title>** — <Brief description of what to do and why>
60
+ - [ ] **1.2 <Task title>** — <Brief description>
61
+ - [ ] **2.1 <Task title>** — <Brief description (new section number = new phase)>
62
+ - [ ] **2.2 <Task title>** — <Brief description>
63
+
64
+ ## Verification
65
+
66
+ - [ ] <Concrete, testable assertion about the end state>
67
+ - [ ] <Another testable assertion>
68
+ - [ ] <Build passes: `yarn build` succeeds>
69
+ - [ ] <Tests pass: `yarn test` succeeds>
70
+
71
+ ## Quality Score Updates
72
+
73
+ After completion, update these entries in `docs/QUALITY_SCORE.md`:
74
+
75
+ | Domain | Current | Target | Notes |
76
+ |--------|---------|--------|-------|
77
+ | <domain> | <current grade> | <target grade> | <what changes> |
78
+
79
+ ## Notes
80
+
81
+ <Any constraints, risks, open questions, or design decisions made during planning.>
82
+ ```
83
+
84
+ ## Step 3: Writing Good Tasks
85
+
86
+ ### Task granularity
87
+
88
+ Each task should be completable in a single focused session. If a task would take multiple hours, break it down.
89
+
90
+ ### Task ordering
91
+
92
+ Number tasks with a phase prefix (`1.x`, `2.x`, `3.x`) where:
93
+ - **Phase 1** — Schema and data model changes
94
+ - **Phase 2** — Server-side logic (services, API routes)
95
+ - **Phase 3** — Client-side UI (pages, components)
96
+ - **Phase 4** — Testing and documentation
97
+
98
+ Tasks within a phase can be done in any order. Phases should be sequential.
99
+
100
+ ### Task dependencies
101
+
102
+ If a task depends on another, note it:
103
+
104
+ ```markdown
105
+ - [ ] **2.1 Create billing service** — Depends on 1.1. Server module in `src/features/billing/server/`.
106
+ ```
107
+
108
+ ## Step 4: Writing Verification Criteria
109
+
110
+ Verification items should be:
111
+ - **Specific** — Not "it works", but "navigating to `/billing` shows subscription status"
112
+ - **Testable** — Can be verified in under 2 minutes
113
+ - **User-centric** — Focus on observable behaviour, not implementation details
114
+
115
+ ```markdown
116
+ ## Verification
117
+
118
+ - [ ] `mars create test-app` produces a project that passes `yarn build`
119
+ - [ ] Navigating to `/billing` shows the current subscription status
120
+ - [ ] Clicking "Upgrade" creates a Stripe Checkout session and redirects
121
+ - [ ] Webhook processes `checkout.session.completed` and updates the DB
122
+ - [ ] Non-subscribed users see the pricing page instead of premium features
123
+ ```
124
+
125
+ ## Step 5: Update Progress
126
+
127
+ As work progresses, check off tasks and add notes:
128
+
129
+ ```markdown
130
+ - [x] **1.1 Add Subscription model** — Done. Added `prisma/schema/billing.prisma`.
131
+ - [ ] **1.2 Add webhook event model** — In progress.
132
+ ```
133
+
134
+ ## Step 6: Complete the Plan
135
+
136
+ When all tasks and verification criteria are met:
137
+
138
+ 1. Update the status to `Completed`:
139
+
140
+ ```markdown
141
+ **Status:** Completed
142
+ **Completed:** <YYYY-MM-DD>
143
+ ```
144
+
145
+ 2. Move the file from `active/` to `completed/`:
146
+
147
+ ```bash
148
+ mv docs/exec-plans/active/<plan>.md docs/exec-plans/completed/<plan>.md
149
+ ```
150
+
151
+ 3. Update `docs/QUALITY_SCORE.md` with new grades.
152
+
153
+ ## Step 7: Link from QUALITY_SCORE.md
154
+
155
+ When creating a plan that addresses quality score gaps, add a reference:
156
+
157
+ ```markdown
158
+ | Dashboard | D | Empty placeholder page | → [exec-plan: add-dashboard](exec-plans/active/add-dashboard.md) |
159
+ ```
160
+
161
+ ## Templates for Common Plans
162
+
163
+ ### Feature addition plan
164
+
165
+ ```markdown
166
+ ## Tasks
167
+
168
+ - [ ] **1.1 Prisma schema** — Add models to `prisma/schema/<name>.prisma`
169
+ - [ ] **1.2 Run db:push** — Sync schema to dev database
170
+ - [ ] **2.1 Feature directory** — Create `src/features/<name>/` with server/, components/, validation/
171
+ - [ ] **2.2 Server module** — Implement queries and mutations
172
+ - [ ] **2.3 Validation schemas** — Zod schemas for API inputs
173
+ - [ ] **3.1 API routes** — CRUD routes under `src/app/api/protected/<name>/`
174
+ - [ ] **3.2 Page** — Create page at `src/app/(protected)/<name>/page.tsx`
175
+ - [ ] **3.3 Components** — Feature-specific UI components
176
+ - [ ] **4.1 Tests** — API route tests with mocked Prisma and auth
177
+ - [ ] **4.2 E2E tests** — Playwright tests for critical user flows
178
+ - [ ] **4.3 Update docs** — Update ARCHITECTURE.md and QUALITY_SCORE.md
179
+ ```
180
+
181
+ ### Bug fix plan
182
+
183
+ ```markdown
184
+ ## Tasks
185
+
186
+ - [ ] **1.1 Reproduce** — Create a minimal reproduction of the issue
187
+ - [ ] **1.2 Root cause** — Identify why the bug occurs
188
+ - [ ] **2.1 Fix** — Implement the fix
189
+ - [ ] **2.2 Regression test** — Add test that would have caught this bug
190
+ - [ ] **3.1 Verify** — Confirm the fix in dev environment
191
+ - [ ] **3.2 Update quality score** — Update grades in QUALITY_SCORE.md
192
+ ```
193
+
194
+ ## Checklist
195
+
196
+ - [ ] Plan file created in `docs/exec-plans/active/`
197
+ - [ ] Title is descriptive and goal-oriented
198
+ - [ ] Status, priority, date, and effort estimate included
199
+ - [ ] Goal section describes the end state clearly
200
+ - [ ] Tasks are numbered with phase prefixes
201
+ - [ ] Each task has a title and brief description
202
+ - [ ] Verification criteria are specific and testable
203
+ - [ ] Quality Score update table included
204
+ - [ ] Plan linked from QUALITY_SCORE.md if addressing a gap
@@ -0,0 +1,191 @@
1
+ # Skill: Create a Database Seed
2
+
3
+ Create a Prisma seed script to populate the database with development data.
4
+
5
+ ## When to Use
6
+
7
+ Use this skill when the user asks to add seed data, test data, sample data, or wants to populate the database for development.
8
+
9
+ ## Setup
10
+
11
+ ### Step 1: Create the Seed File
12
+
13
+ Create `prisma/seed.ts`:
14
+
15
+ ```typescript
16
+ import { PrismaClient } from '@db';
17
+ import { PrismaPg } from '@prisma/adapter-pg';
18
+ import { hash } from 'bcryptjs';
19
+
20
+ const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL! });
21
+ const prisma = new PrismaClient({ adapter });
22
+
23
+ async function main() {
24
+ console.log('Seeding database...');
25
+
26
+ // Clean existing data (order matters for foreign keys)
27
+ await prisma.verificationToken.deleteMany();
28
+ await prisma.session.deleteMany();
29
+ await prisma.account.deleteMany();
30
+ await prisma.user.deleteMany();
31
+
32
+ // Create admin user
33
+ const adminPassword = await hash('admin123456', 12);
34
+ const admin = await prisma.user.create({
35
+ data: {
36
+ email: 'admin@example.com',
37
+ name: 'Admin User',
38
+ password: adminPassword,
39
+ role: 'admin',
40
+ emailVerified: new Date(),
41
+ termsAcceptedAt: new Date(),
42
+ privacyAcceptedAt: new Date(),
43
+ },
44
+ });
45
+ console.log(` Created admin: ${admin.email}`);
46
+
47
+ // Create regular users
48
+ const userPassword = await hash('user123456', 12);
49
+ const users = await Promise.all(
50
+ Array.from({ length: 5 }, (_, i) =>
51
+ prisma.user.create({
52
+ data: {
53
+ email: `user${i + 1}@example.com`,
54
+ name: `Test User ${i + 1}`,
55
+ password: userPassword,
56
+ role: 'user',
57
+ emailVerified: new Date(),
58
+ termsAcceptedAt: new Date(),
59
+ privacyAcceptedAt: new Date(),
60
+ },
61
+ }),
62
+ ),
63
+ );
64
+ console.log(` Created ${users.length} users`);
65
+
66
+ // Seed feature-specific data here
67
+ // Example: create items for the first user
68
+ // await prisma.item.createMany({
69
+ // data: Array.from({ length: 10 }, (_, i) => ({
70
+ // name: `Item ${i + 1}`,
71
+ // userId: users[0].id,
72
+ // })),
73
+ // });
74
+
75
+ console.log('Seeding complete.');
76
+ }
77
+
78
+ main()
79
+ .catch((error) => {
80
+ console.error('Seed error:', error);
81
+ process.exit(1);
82
+ })
83
+ .finally(() => prisma.$disconnect());
84
+ ```
85
+
86
+ ### Step 2: Configure package.json
87
+
88
+ Add the seed command to `package.json`:
89
+
90
+ ```json
91
+ {
92
+ "prisma": {
93
+ "schema": "prisma/schema",
94
+ "seed": "tsx prisma/seed.ts"
95
+ }
96
+ }
97
+ ```
98
+
99
+ ### Step 3: Install tsx (if not already)
100
+
101
+ ```bash
102
+ yarn add -D tsx
103
+ ```
104
+
105
+ ### Step 4: Run the Seed
106
+
107
+ ```bash
108
+ yarn db:seed
109
+ ```
110
+
111
+ Or automatically after reset:
112
+
113
+ ```bash
114
+ npx prisma migrate reset # Runs seed automatically after reset
115
+ ```
116
+
117
+ ## Patterns
118
+
119
+ ### Deterministic IDs (for testing)
120
+
121
+ Use fixed IDs so tests can reference specific records:
122
+
123
+ ```typescript
124
+ const admin = await prisma.user.create({
125
+ data: {
126
+ id: 'seed-admin-001',
127
+ email: 'admin@example.com',
128
+ // ...
129
+ },
130
+ });
131
+ ```
132
+
133
+ ### Realistic Data with Helpers
134
+
135
+ ```typescript
136
+ function randomDate(start: Date, end: Date): Date {
137
+ return new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime()));
138
+ }
139
+
140
+ function randomElement<T>(array: T[]): T {
141
+ return array[Math.floor(Math.random() * array.length)];
142
+ }
143
+
144
+ const statuses = ['draft', 'active', 'archived'] as const;
145
+
146
+ await prisma.item.createMany({
147
+ data: Array.from({ length: 50 }, (_, i) => ({
148
+ name: `Item ${i + 1}`,
149
+ status: randomElement(statuses),
150
+ createdAt: randomDate(new Date('2024-01-01'), new Date()),
151
+ userId: randomElement(users).id,
152
+ })),
153
+ });
154
+ ```
155
+
156
+ ### Conditional Seeding
157
+
158
+ Only seed data relevant to enabled features:
159
+
160
+ ```typescript
161
+ import { appConfig } from '../src/config/app.config';
162
+
163
+ if (appConfig.features.billing) {
164
+ // Seed subscription plans, etc.
165
+ }
166
+
167
+ if (appConfig.features.blog) {
168
+ // Seed blog posts, categories, etc.
169
+ }
170
+ ```
171
+
172
+ ## Rules
173
+
174
+ - **Never use seed scripts in production.** Guard with an environment check if needed.
175
+ - **Clean data in reverse dependency order** (child tables first, then parent tables).
176
+ - **Use `createMany` for bulk inserts** -- significantly faster than individual `create` calls.
177
+ - **Hash passwords properly** -- use the same `bcryptjs` library as the auth system.
178
+ - **Don't seed secrets** -- use placeholder values for development only.
179
+ - **Make seeds idempotent** -- always delete existing data before inserting.
180
+
181
+ ## Checklist
182
+
183
+ - [ ] Seed file at `prisma/seed.ts`
184
+ - [ ] `prisma.seed` configured in `package.json`
185
+ - [ ] `tsx` added as dev dependency
186
+ - [ ] Admin user with known credentials seeded
187
+ - [ ] Regular test users seeded
188
+ - [ ] Feature-specific data seeded
189
+ - [ ] Data cleaned before seeding (idempotent)
190
+ - [ ] Passwords hashed with bcryptjs
191
+ - [ ] `yarn db:seed` runs without errors
@@ -0,0 +1,300 @@
1
+ # Skill: Deploy to Vercel
2
+
3
+ Step-by-step guide for deploying a Mars application to Vercel, including CLI setup, environment variables, database provisioning, and post-deploy verification.
4
+
5
+ ## When to Use
6
+
7
+ Use this skill when the user asks to deploy to Vercel, set up hosting, go to production, configure deployment, or publish their application.
8
+
9
+ ## Prerequisites
10
+
11
+ - A Vercel account at [vercel.com](https://vercel.com)
12
+ - The application builds locally with `yarn build`
13
+ - Git repository initialized and pushed to GitHub/GitLab/Bitbucket
14
+
15
+ ## Step 1: Install Vercel CLI
16
+
17
+ ```bash
18
+ yarn global add vercel
19
+ # or
20
+ npm i -g vercel
21
+ ```
22
+
23
+ Login to Vercel:
24
+
25
+ ```bash
26
+ vercel login
27
+ ```
28
+
29
+ ## Step 2: Link the Project
30
+
31
+ From the project root:
32
+
33
+ ```bash
34
+ vercel link
35
+ ```
36
+
37
+ This creates `.vercel/project.json` with the project ID. Add `.vercel` to `.gitignore` if not already present.
38
+
39
+ ## Step 3: Provision Database
40
+
41
+ ### Option A: Vercel Postgres (recommended for simplicity)
42
+
43
+ ```bash
44
+ vercel env pull .env.local
45
+ ```
46
+
47
+ 1. Go to your Vercel project dashboard → Storage → Create Database → Postgres
48
+ 2. Vercel automatically adds `POSTGRES_URL`, `POSTGRES_PRISMA_URL`, etc. to your project env vars.
49
+
50
+ Update `prisma/schema/base.prisma` to use the Vercel Postgres URL:
51
+
52
+ ```prisma
53
+ datasource db {
54
+ provider = "postgresql"
55
+ url = env("POSTGRES_PRISMA_URL")
56
+ directUrl = env("POSTGRES_URL_NON_POOLING")
57
+ }
58
+ ```
59
+
60
+ ### Option B: Neon (recommended for production)
61
+
62
+ 1. Create a database at [neon.tech](https://neon.tech)
63
+ 2. Copy the connection string
64
+ 3. Set it in Vercel:
65
+
66
+ ```bash
67
+ vercel env add DATABASE_URL production
68
+ vercel env add DATABASE_URL preview
69
+ ```
70
+
71
+ ### Run Migrations
72
+
73
+ After database provisioning, push the schema:
74
+
75
+ ```bash
76
+ # Pull production env vars locally
77
+ vercel env pull .env.production.local
78
+
79
+ # Push schema to production database
80
+ DATABASE_URL="<production-url>" npx prisma db push
81
+ ```
82
+
83
+ ## Step 4: Provision KV Store (Rate Limiting)
84
+
85
+ Mars uses Upstash Redis for rate limiting in production.
86
+
87
+ ### Option A: Vercel KV
88
+
89
+ 1. Vercel Dashboard → Storage → Create Database → KV
90
+ 2. Vercel automatically adds `KV_REST_API_URL` and `KV_REST_API_TOKEN`
91
+
92
+ ### Option B: Upstash Directly
93
+
94
+ 1. Create a database at [upstash.com](https://upstash.com)
95
+ 2. Set environment variables:
96
+
97
+ ```bash
98
+ vercel env add UPSTASH_REDIS_REST_URL production
99
+ vercel env add UPSTASH_REDIS_REST_TOKEN production
100
+ ```
101
+
102
+ ## Step 5: Set Environment Variables
103
+
104
+ Required variables for a Mars app:
105
+
106
+ ```bash
107
+ # Authentication (REQUIRED)
108
+ vercel env add JWT_SECRET production # Generate: openssl rand -base64 32
109
+ vercel env add JWT_SECRET preview # Use a different secret for preview
110
+
111
+ # App URL (REQUIRED)
112
+ vercel env add APP_URL production # https://your-domain.com
113
+ vercel env add NEXT_PUBLIC_APP_URL production # Same as APP_URL
114
+
115
+ # Database (set during provisioning)
116
+ # POSTGRES_URL / DATABASE_URL — already set if using Vercel Postgres
117
+
118
+ # Rate Limiting (REQUIRED for production)
119
+ # UPSTASH_REDIS_REST_URL — already set if using Vercel KV
120
+ # UPSTASH_REDIS_REST_TOKEN — already set if using Vercel KV
121
+ ```
122
+
123
+ Optional variables based on enabled features:
124
+
125
+ ```bash
126
+ # Email (if appConfig.features.email is true)
127
+ vercel env add RESEND_API_KEY production
128
+ vercel env add EMAIL_FROM production # noreply@yourdomain.com
129
+
130
+ # Payments (if appConfig.features.billing is true)
131
+ vercel env add STRIPE_SECRET_KEY production
132
+ vercel env add STRIPE_WEBHOOK_SECRET production
133
+ vercel env add NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY production
134
+
135
+ # Storage (if appConfig.features.storage is true)
136
+ vercel env add BLOB_READ_WRITE_TOKEN production
137
+
138
+ # Error Reporting (optional)
139
+ vercel env add NEXT_PUBLIC_SENTRY_DSN production
140
+ vercel env add SENTRY_ORG production
141
+ vercel env add SENTRY_PROJECT production
142
+
143
+ # Cron Jobs (if using Vercel Cron)
144
+ vercel env add CRON_SECRET production # Generate: openssl rand -base64 32
145
+ ```
146
+
147
+ ## Step 6: Configure `vercel.json` (Optional)
148
+
149
+ ```json
150
+ {
151
+ "framework": "nextjs",
152
+ "buildCommand": "yarn build",
153
+ "installCommand": "yarn install --frozen-lockfile",
154
+ "regions": ["iad1"],
155
+ "headers": [
156
+ {
157
+ "source": "/api/(.*)",
158
+ "headers": [
159
+ { "key": "X-Content-Type-Options", "value": "nosniff" },
160
+ { "key": "X-Frame-Options", "value": "DENY" }
161
+ ]
162
+ }
163
+ ],
164
+ "crons": []
165
+ }
166
+ ```
167
+
168
+ ## Step 7: Deploy
169
+
170
+ ### First Deploy (Preview)
171
+
172
+ ```bash
173
+ vercel
174
+ ```
175
+
176
+ This deploys to a preview URL. Test thoroughly before promoting.
177
+
178
+ ### Production Deploy
179
+
180
+ ```bash
181
+ vercel --prod
182
+ ```
183
+
184
+ ### Git Integration (Recommended)
185
+
186
+ Push to your default branch for automatic production deployments:
187
+
188
+ ```bash
189
+ git push origin main
190
+ ```
191
+
192
+ Vercel automatically deploys:
193
+ - `main` branch → Production
194
+ - Other branches → Preview deployments
195
+
196
+ ## Step 8: Configure Custom Domain
197
+
198
+ 1. Vercel Dashboard → Settings → Domains
199
+ 2. Add your domain (e.g., `app.yourdomain.com`)
200
+ 3. Update DNS records as shown by Vercel
201
+ 4. Wait for SSL certificate provisioning
202
+
203
+ After domain is live, update:
204
+
205
+ ```bash
206
+ vercel env add APP_URL production # https://app.yourdomain.com
207
+ vercel env add NEXT_PUBLIC_APP_URL production # https://app.yourdomain.com
208
+ ```
209
+
210
+ Redeploy to pick up the new URL:
211
+
212
+ ```bash
213
+ vercel --prod
214
+ ```
215
+
216
+ ## Step 9: Post-Deploy Verification
217
+
218
+ Run through this checklist after each production deployment:
219
+
220
+ ### Automated checks
221
+
222
+ ```bash
223
+ # Health check (if endpoint exists)
224
+ curl -f https://your-app.vercel.app/api/health
225
+
226
+ # Check the deployment is accessible
227
+ curl -s -o /dev/null -w "%{http_code}" https://your-app.vercel.app
228
+ ```
229
+
230
+ ### Manual verification
231
+
232
+ 1. **Auth flow** — Register, login, logout, password reset
233
+ 2. **CSRF protection** — API calls include CSRF token, reject without it
234
+ 3. **Rate limiting** — Rapid requests get 429 responses
235
+ 4. **Protected routes** — Unauthenticated access redirects to login
236
+ 5. **Email delivery** — Test verification and password reset emails
237
+ 6. **Database connectivity** — Data persists across requests
238
+ 7. **Environment** — `process.env.NODE_ENV === 'production'` in server logs
239
+
240
+ ### Monitoring
241
+
242
+ - Vercel Dashboard → Logs for runtime errors
243
+ - Vercel Dashboard → Analytics for performance metrics
244
+ - Vercel Dashboard → Speed Insights for Core Web Vitals
245
+
246
+ ## Stripe Webhook Setup (If Billing Enabled)
247
+
248
+ After deployment, configure the production webhook:
249
+
250
+ 1. Go to [Stripe Dashboard → Webhooks](https://dashboard.stripe.com/webhooks)
251
+ 2. Add endpoint: `https://your-domain.com/api/webhooks/stripe`
252
+ 3. Select events: `checkout.session.completed`, `customer.subscription.updated`, `customer.subscription.deleted`
253
+ 4. Copy the webhook signing secret
254
+ 5. Set it in Vercel:
255
+
256
+ ```bash
257
+ vercel env add STRIPE_WEBHOOK_SECRET production
258
+ vercel --prod # Redeploy
259
+ ```
260
+
261
+ ## Troubleshooting
262
+
263
+ | Issue | Cause | Fix |
264
+ |-------|-------|-----|
265
+ | Build fails | Missing env vars | Check Vercel build logs, add missing vars |
266
+ | 500 errors | Database not connected | Verify `DATABASE_URL` env var is set correctly |
267
+ | CSRF errors | `APP_URL` mismatch | Ensure `APP_URL` matches the actual deployment URL |
268
+ | Rate limiting disabled | Missing Upstash vars | Provision KV store and set `UPSTASH_*` variables |
269
+ | Emails not sending | Missing `RESEND_API_KEY` | Add the key and verify domain in Resend dashboard |
270
+
271
+ ## Preview Deployments
272
+
273
+ Preview deployments use separate env vars. Set preview-specific values:
274
+
275
+ ```bash
276
+ vercel env add JWT_SECRET preview
277
+ vercel env add APP_URL preview # Will be overridden by VERCEL_URL
278
+ ```
279
+
280
+ For preview deployments, consider using `VERCEL_URL`:
281
+
282
+ ```typescript
283
+ const appUrl = process.env.APP_URL
284
+ ?? (process.env.VERCEL_URL ? `https://${process.env.VERCEL_URL}` : 'http://localhost:3000');
285
+ ```
286
+
287
+ ## Checklist
288
+
289
+ - [ ] Vercel CLI installed and logged in
290
+ - [ ] Project linked with `vercel link`
291
+ - [ ] Database provisioned and schema pushed
292
+ - [ ] KV store provisioned for rate limiting
293
+ - [ ] All required environment variables set
294
+ - [ ] `JWT_SECRET` is unique per environment (production/preview)
295
+ - [ ] `APP_URL` matches the deployment URL
296
+ - [ ] Custom domain configured (optional)
297
+ - [ ] Stripe webhook configured (if billing enabled)
298
+ - [ ] Post-deploy verification completed
299
+ - [ ] Git integration working (push = deploy)
300
+ - [ ] Preview deployments tested