@mars-stack/cli 0.2.0 → 1.0.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 (175) hide show
  1. package/dist/index.js +137 -12
  2. package/dist/index.js.map +1 -1
  3. package/package.json +4 -3
  4. package/template/.cursor/rules/composition-patterns.mdc +186 -0
  5. package/template/.cursor/rules/data-access.mdc +29 -0
  6. package/template/.cursor/rules/project-structure.mdc +34 -0
  7. package/template/.cursor/rules/security.mdc +25 -0
  8. package/template/.cursor/rules/testing.mdc +24 -0
  9. package/template/.cursor/rules/ui-conventions.mdc +29 -0
  10. package/template/.cursor/skills/add-api-route/SKILL.md +122 -0
  11. package/template/.cursor/skills/add-audit-log/SKILL.md +375 -0
  12. package/template/.cursor/skills/add-blog/SKILL.md +447 -0
  13. package/template/.cursor/skills/add-command-palette/SKILL.md +438 -0
  14. package/template/.cursor/skills/add-component/SKILL.md +158 -0
  15. package/template/.cursor/skills/add-crud-routes/SKILL.md +221 -0
  16. package/template/.cursor/skills/add-e2e-test/SKILL.md +227 -0
  17. package/template/.cursor/skills/add-error-boundary/SKILL.md +472 -0
  18. package/template/.cursor/skills/add-feature/SKILL.md +174 -0
  19. package/template/.cursor/skills/add-middleware/SKILL.md +135 -0
  20. package/template/.cursor/skills/add-page/SKILL.md +151 -0
  21. package/template/.cursor/skills/add-prisma-model/SKILL.md +148 -0
  22. package/template/.cursor/skills/add-protected-resource/SKILL.md +192 -0
  23. package/template/.cursor/skills/add-role/SKILL.md +156 -0
  24. package/template/.cursor/skills/add-server-action/SKILL.md +167 -0
  25. package/template/.cursor/skills/add-webhook/SKILL.md +192 -0
  26. package/template/.cursor/skills/build-complete-feature/SKILL.md +227 -0
  27. package/template/.cursor/skills/build-dashboard/SKILL.md +211 -0
  28. package/template/.cursor/skills/build-data-table/SKILL.md +283 -0
  29. package/template/.cursor/skills/build-form/SKILL.md +231 -0
  30. package/template/.cursor/skills/build-landing-page/SKILL.md +248 -0
  31. package/template/.cursor/skills/configure-ai/SKILL.md +617 -0
  32. package/template/.cursor/skills/configure-analytics/SKILL.md +413 -0
  33. package/template/.cursor/skills/configure-dark-mode/SKILL.md +309 -0
  34. package/template/.cursor/skills/configure-email/SKILL.md +170 -0
  35. package/template/.cursor/skills/configure-email-verification/SKILL.md +333 -0
  36. package/template/.cursor/skills/configure-feature-flags/SKILL.md +361 -0
  37. package/template/.cursor/skills/configure-i18n/SKILL.md +518 -0
  38. package/template/.cursor/skills/configure-jobs/SKILL.md +500 -0
  39. package/template/.cursor/skills/configure-magic-links/SKILL.md +385 -0
  40. package/template/.cursor/skills/configure-multi-tenancy/SKILL.md +611 -0
  41. package/template/.cursor/skills/configure-notifications/SKILL.md +569 -0
  42. package/template/.cursor/skills/configure-oauth/SKILL.md +217 -0
  43. package/template/.cursor/skills/configure-onboarding/SKILL.md +483 -0
  44. package/template/.cursor/skills/configure-payments/SKILL.md +243 -0
  45. package/template/.cursor/skills/configure-realtime/SKILL.md +733 -0
  46. package/template/.cursor/skills/configure-search/SKILL.md +581 -0
  47. package/template/.cursor/skills/configure-storage/SKILL.md +273 -0
  48. package/template/.cursor/skills/configure-two-factor/SKILL.md +518 -0
  49. package/template/.cursor/skills/create-execution-plan/SKILL.md +204 -0
  50. package/template/.cursor/skills/create-seed/SKILL.md +191 -0
  51. package/template/.cursor/skills/deploy-to-vercel/SKILL.md +300 -0
  52. package/template/.cursor/skills/design-tokens/SKILL.md +138 -0
  53. package/template/.cursor/skills/mars-capture-conversation-context/SKILL.md +119 -0
  54. package/template/.cursor/skills/setup-billing/SKILL.md +322 -0
  55. package/template/.cursor/skills/setup-project/SKILL.md +104 -0
  56. package/template/.cursor/skills/setup-teams/SKILL.md +682 -0
  57. package/template/.cursor/skills/test-api-route/SKILL.md +219 -0
  58. package/template/.cursor/skills/update-architecture-docs/SKILL.md +99 -0
  59. package/template/AGENTS.md +104 -0
  60. package/template/ARCHITECTURE.md +102 -0
  61. package/template/docs/QUALITY_SCORE.md +20 -0
  62. package/template/docs/design-docs/conversation-as-system-record.md +70 -0
  63. package/template/docs/design-docs/core-beliefs.md +43 -0
  64. package/template/docs/design-docs/index.md +8 -0
  65. package/template/docs/exec-plans/active/.gitkeep +0 -0
  66. package/template/docs/exec-plans/completed/.gitkeep +0 -0
  67. package/template/docs/exec-plans/tech-debt.md +7 -0
  68. package/template/docs/generated/.gitkeep +0 -0
  69. package/template/docs/product-specs/index.md +7 -0
  70. package/template/docs/references/index.md +18 -0
  71. package/template/e2e/api.spec.ts +20 -0
  72. package/template/e2e/auth.spec.ts +24 -0
  73. package/template/e2e/public.spec.ts +25 -0
  74. package/template/eslint.config.mjs +24 -0
  75. package/template/next-env.d.ts +6 -0
  76. package/template/next.config.ts +45 -0
  77. package/template/package.json +80 -0
  78. package/template/playwright.config.ts +31 -0
  79. package/template/postcss.config.mjs +8 -0
  80. package/template/prisma/generated/prisma/browser.ts +49 -0
  81. package/template/prisma/generated/prisma/client.ts +73 -0
  82. package/template/prisma/generated/prisma/commonInputTypes.ts +406 -0
  83. package/template/prisma/generated/prisma/enums.ts +15 -0
  84. package/template/prisma/generated/prisma/internal/class.ts +254 -0
  85. package/template/prisma/generated/prisma/internal/prismaNamespace.ts +1240 -0
  86. package/template/prisma/generated/prisma/internal/prismaNamespaceBrowser.ts +190 -0
  87. package/template/prisma/generated/prisma/models/Account.ts +1543 -0
  88. package/template/prisma/generated/prisma/models/File.ts +1529 -0
  89. package/template/prisma/generated/prisma/models/Session.ts +1415 -0
  90. package/template/prisma/generated/prisma/models/Subscription.ts +1455 -0
  91. package/template/prisma/generated/prisma/models/User.ts +2235 -0
  92. package/template/prisma/generated/prisma/models/VerificationToken.ts +1099 -0
  93. package/template/prisma/generated/prisma/models.ts +17 -0
  94. package/template/prisma/schema/auth.prisma +69 -0
  95. package/template/prisma/schema/base.prisma +8 -0
  96. package/template/prisma/schema/file.prisma +15 -0
  97. package/template/prisma/schema/subscription.prisma +17 -0
  98. package/template/prisma.config.ts +13 -0
  99. package/template/scripts/check-architecture.ts +221 -0
  100. package/template/scripts/check-doc-freshness.ts +242 -0
  101. package/template/scripts/ensure-db.mjs +291 -0
  102. package/template/scripts/generate-docs.ts +143 -0
  103. package/template/scripts/generate-env-example.ts +89 -0
  104. package/template/scripts/seed.ts +56 -0
  105. package/template/scripts/update-quality-score.ts +263 -0
  106. package/template/src/__tests__/architecture.test.ts +114 -0
  107. package/template/src/app/(auth)/forgotten-password/page.tsx +92 -0
  108. package/template/src/app/(auth)/layout.tsx +11 -0
  109. package/template/src/app/(auth)/register/page.tsx +162 -0
  110. package/template/src/app/(auth)/reset-password/page.tsx +109 -0
  111. package/template/src/app/(auth)/sign-in/page.tsx +122 -0
  112. package/template/src/app/(auth)/verify/[token]/page.tsx +87 -0
  113. package/template/src/app/(auth)/verify/page.tsx +56 -0
  114. package/template/src/app/(protected)/admin/page.tsx +108 -0
  115. package/template/src/app/(protected)/dashboard/loading.tsx +20 -0
  116. package/template/src/app/(protected)/dashboard/page.tsx +22 -0
  117. package/template/src/app/(protected)/layout.tsx +262 -0
  118. package/template/src/app/(protected)/settings/page.tsx +370 -0
  119. package/template/src/app/api/auth/forgot/route.ts +63 -0
  120. package/template/src/app/api/auth/login/route.ts +121 -0
  121. package/template/src/app/api/auth/logout/route.ts +19 -0
  122. package/template/src/app/api/auth/me/route.ts +30 -0
  123. package/template/src/app/api/auth/reset/route.ts +45 -0
  124. package/template/src/app/api/auth/signup/route.ts +85 -0
  125. package/template/src/app/api/auth/verify/route.ts +46 -0
  126. package/template/src/app/api/csrf/route.ts +12 -0
  127. package/template/src/app/api/health/route.ts +10 -0
  128. package/template/src/app/api/protected/admin/users/route.ts +24 -0
  129. package/template/src/app/api/protected/billing/checkout/route.ts +83 -0
  130. package/template/src/app/api/protected/billing/portal/route.ts +39 -0
  131. package/template/src/app/api/protected/files/[fileId]/route.ts +86 -0
  132. package/template/src/app/api/protected/files/upload/route.ts +64 -0
  133. package/template/src/app/api/protected/user/password/route.ts +63 -0
  134. package/template/src/app/api/protected/user/profile/route.ts +35 -0
  135. package/template/src/app/api/protected/user/sessions/[sessionId]/route.ts +33 -0
  136. package/template/src/app/api/protected/user/sessions/route.ts +22 -0
  137. package/template/src/app/api/readiness/route.ts +15 -0
  138. package/template/src/app/api/webhooks/stripe/route.ts +166 -0
  139. package/template/src/app/error.tsx +33 -0
  140. package/template/src/app/layout.tsx +29 -0
  141. package/template/src/app/not-found.tsx +20 -0
  142. package/template/src/app/page.tsx +136 -0
  143. package/template/src/app/privacy/page.tsx +178 -0
  144. package/template/src/app/providers.tsx +8 -0
  145. package/template/src/app/terms/page.tsx +139 -0
  146. package/template/src/config/app.config.ts +70 -0
  147. package/template/src/config/routes.ts +17 -0
  148. package/template/src/features/admin/index.ts +11 -0
  149. package/template/src/features/admin/permissions.ts +64 -0
  150. package/template/src/features/auth/context/AuthContext.tsx +96 -0
  151. package/template/src/features/auth/context/index.ts +2 -0
  152. package/template/src/features/auth/index.ts +3 -0
  153. package/template/src/features/auth/server/consent.ts +66 -0
  154. package/template/src/features/auth/server/session-revocation.ts +20 -0
  155. package/template/src/features/auth/server/sessions.ts +66 -0
  156. package/template/src/features/auth/server/user.ts +166 -0
  157. package/template/src/features/auth/types.ts +19 -0
  158. package/template/src/features/auth/validators.ts +29 -0
  159. package/template/src/features/billing/server/index.ts +66 -0
  160. package/template/src/features/billing/types.ts +43 -0
  161. package/template/src/features/uploads/server/index.ts +49 -0
  162. package/template/src/features/uploads/types.ts +26 -0
  163. package/template/src/lib/core/email/templates/base-layout.ts +122 -0
  164. package/template/src/lib/core/email/templates/index.ts +4 -0
  165. package/template/src/lib/core/email/templates/password-reset-email.ts +42 -0
  166. package/template/src/lib/core/email/templates/verification-email.ts +41 -0
  167. package/template/src/lib/core/email/templates/welcome-email.ts +40 -0
  168. package/template/src/lib/mars.ts +56 -0
  169. package/template/src/lib/prisma.ts +19 -0
  170. package/template/src/proxy.ts +92 -0
  171. package/template/src/styles/brand.css +15 -0
  172. package/template/src/styles/globals.css +7 -0
  173. package/template/tsconfig.json +59 -0
  174. package/template/vitest.config.ts +41 -0
  175. package/template/vitest.setup.ts +24 -0
@@ -0,0 +1,227 @@
1
+ # Skill: Build Complete Feature (Meta-Skill)
2
+
3
+ Orchestrate the end-to-end implementation of a new feature from database schema through UI to tests and documentation. This meta-skill chains multiple sub-skills in the correct order.
4
+
5
+ ## When to Use
6
+
7
+ Use this skill when the user asks to:
8
+ - Build a complete feature end-to-end
9
+ - Add a new domain with full CRUD (e.g., "add blog posts", "add projects", "add invoices")
10
+ - Implement a feature from scratch with all layers (database, API, UI, tests)
11
+
12
+ This is the right skill when the request implies multiple layers of work, not just a single API route or page.
13
+
14
+ ## Prerequisites
15
+
16
+ - Read `AGENTS.md` to understand the project structure.
17
+ - Read `src/config/app.config.ts` to check existing feature flags.
18
+ - Read `prisma/schema/` to see existing models and relations.
19
+
20
+ ## Execution Order
21
+
22
+ ```
23
+ ┌─────────────────────────────────────────────────────┐
24
+ │ Phase 0: Plan │
25
+ │ create-execution-plan │
26
+ ├─────────────────────────────────────────────────────┤
27
+ │ Phase 1: Data Layer │
28
+ │ add-prisma-model → db:push │
29
+ ├─────────────────────────────────────────────────────┤
30
+ │ Phase 2: Feature Module │
31
+ │ add-feature (directory, types, validation, server) │
32
+ ├─────────────────────────────────────────────────────┤
33
+ │ Phase 3: API Layer │
34
+ │ add-api-route (collection) → add-crud-routes │
35
+ │ ↳ If webhooks needed: add-webhook │
36
+ ├─────────────────────────────────────────────────────┤
37
+ │ Phase 4: UI Layer │
38
+ │ add-page → add-component (list, form, detail) │
39
+ │ ↳ If data table needed: build-data-table │
40
+ │ ↳ If form needed: build-form │
41
+ ├─────────────────────────────────────────────────────┤
42
+ │ Phase 5: Testing │
43
+ │ test-api-route → add-e2e-test │
44
+ ├─────────────────────────────────────────────────────┤
45
+ │ Phase 6: Documentation │
46
+ │ update-architecture-docs │
47
+ └─────────────────────────────────────────────────────┘
48
+ ```
49
+
50
+ ## Phase 0: Create Execution Plan
51
+
52
+ **Skill:** `create-execution-plan`
53
+
54
+ Before writing any code, create an execution plan:
55
+
56
+ 1. Read existing code to understand the current state
57
+ 2. Create `docs/exec-plans/active/<feature-name>.md`
58
+ 3. List all tasks with phase prefixes
59
+ 4. Define verification criteria
60
+
61
+ ## Phase 1: Data Layer
62
+
63
+ **Skill:** `add-prisma-model`
64
+
65
+ 1. Design the data model based on requirements
66
+ 2. Create `prisma/schema/<feature>.prisma` with the model(s)
67
+ 3. Add relations to existing models (e.g., User) in their respective schema files
68
+ 4. Run `yarn db:push` to sync
69
+
70
+ **Outputs passed to Phase 2:**
71
+ - Model name(s) and field names
72
+ - Relation fields added to User or other models
73
+ - Index definitions
74
+
75
+ ### Decision: Does this feature need multiple models?
76
+
77
+ - **Single entity** (e.g., blog posts) → One model
78
+ - **Entity with metadata** (e.g., posts with tags) → Two+ models with relations
79
+ - **Entity with history** (e.g., orders with line items) → Parent-child models
80
+
81
+ ## Phase 2: Feature Module
82
+
83
+ **Skill:** `add-feature`
84
+
85
+ 1. Create the feature directory structure:
86
+ ```
87
+ src/features/<name>/
88
+ ├── components/
89
+ ├── server/
90
+ ├── hooks/ (optional)
91
+ ├── validation/
92
+ └── types.ts
93
+ ```
94
+
95
+ 2. Create types based on the Prisma model
96
+ 3. Create Zod validation schemas for create/update inputs
97
+ 4. Create server module with queries and mutations (import `'server-only'`)
98
+
99
+ **Outputs passed to Phase 3:**
100
+ - Validation schema exports
101
+ - Server function exports (findAll, findById, create, update, delete)
102
+ - Type exports
103
+
104
+ ## Phase 3: API Layer
105
+
106
+ **Skill:** `add-api-route` + `add-crud-routes`
107
+
108
+ 1. Create collection route: `src/app/api/protected/<name>/route.ts` (GET list, POST create)
109
+ 2. Create item route: `src/app/api/protected/<name>/[id]/route.ts` (GET one, PUT update, DELETE)
110
+
111
+ **Conditional branches:**
112
+
113
+ - **If the feature needs admin-only routes:**
114
+ Use `withRole(['admin'], ...)` for admin routes under `src/app/api/protected/admin/<name>/`
115
+
116
+ - **If the feature receives external callbacks:**
117
+ **Skill:** `add-webhook` — Create webhook handler at `src/app/api/webhooks/<service>/`
118
+
119
+ - **If the feature needs ownership-gated access:**
120
+ Use `withOwnership` in the item route to verify the user owns the resource
121
+
122
+ **Outputs passed to Phase 4:**
123
+ - API endpoint paths for client-side data fetching
124
+ - Response shapes for TypeScript types
125
+
126
+ ## Phase 4: UI Layer
127
+
128
+ **Skill:** `add-page` + `add-component`
129
+
130
+ 1. Create the main page: `src/app/(protected)/<name>/page.tsx`
131
+ 2. Create `loading.tsx` for Suspense fallback
132
+ 3. Create feature components in `src/features/<name>/components/`:
133
+
134
+ **Conditional branches:**
135
+
136
+ - **If the feature has a list view:**
137
+ **Skill:** `build-data-table` — Create a data table component with sorting, filtering, pagination
138
+
139
+ - **If the feature has a create/edit form:**
140
+ **Skill:** `build-form` — Create a form component with validation, error handling, loading states
141
+
142
+ - **If the feature has a detail view:**
143
+ Create a detail component that fetches a single item by ID
144
+
145
+ 4. Add route to `src/config/routes.ts`
146
+ 5. Add navigation link (if applicable)
147
+
148
+ ### Component breakdown
149
+
150
+ | Component | Location | Purpose |
151
+ |-----------|----------|---------|
152
+ | `<Feature>List` | `src/features/<name>/components/` | List view with data table |
153
+ | `<Feature>Form` | `src/features/<name>/components/` | Create/edit form |
154
+ | `<Feature>Detail` | `src/features/<name>/components/` | Single item detail view |
155
+
156
+ ## Phase 5: Testing
157
+
158
+ **Skill:** `test-api-route` + `add-e2e-test`
159
+
160
+ 1. Create unit tests for each API route (`route.test.ts` next to `route.ts`)
161
+ 2. Create unit tests for server module functions
162
+ 3. Create E2E tests for critical user flows:
163
+ - Can create a new item
164
+ - Can view the list
165
+ - Can edit an item
166
+ - Can delete an item
167
+ - Unauthorised access is rejected
168
+
169
+ ## Phase 6: Documentation
170
+
171
+ **Skill:** `update-architecture-docs`
172
+
173
+ 1. Update `docs/QUALITY_SCORE.md` with the new feature grade
174
+ 2. Update `AGENTS.md` if the feature introduces new patterns
175
+ 3. Mark the execution plan as complete
176
+ 4. Move the plan from `active/` to `completed/`
177
+
178
+ ## Feature Flag Integration
179
+
180
+ If the feature should be toggleable:
181
+
182
+ 1. Add flag to `appConfig.features` in `src/config/app.config.ts`
183
+ 2. Gate the API routes:
184
+ ```typescript
185
+ if (!appConfig.features.<name>) {
186
+ return NextResponse.json({ error: 'Feature not available' }, { status: 404 });
187
+ }
188
+ ```
189
+ 3. Gate the navigation link
190
+ 4. Gate the page (redirect if disabled)
191
+
192
+ ## Complete Example: Adding a "Projects" Feature
193
+
194
+ ```
195
+ Phase 0: Create docs/exec-plans/active/add-projects.md
196
+ Phase 1: Create prisma/schema/projects.prisma (Project model)
197
+ Add projects relation to User in auth.prisma
198
+ Run yarn db:push
199
+ Phase 2: Create src/features/projects/ directory structure
200
+ Create types.ts, validation/schemas.ts, server/index.ts
201
+ Phase 3: Create src/app/api/protected/projects/route.ts (GET, POST)
202
+ Create src/app/api/protected/projects/[id]/route.ts (GET, PUT, DELETE)
203
+ Phase 4: Create src/app/(protected)/projects/page.tsx
204
+ Create ProjectList, ProjectForm components
205
+ Add to routes.ts
206
+ Phase 5: Write route.test.ts for both API routes
207
+ Write projects.spec.ts E2E test
208
+ Phase 6: Update QUALITY_SCORE.md
209
+ Complete execution plan
210
+ ```
211
+
212
+ ## Checklist
213
+
214
+ - [ ] Execution plan created before starting
215
+ - [ ] Prisma model(s) created and `db:push` run
216
+ - [ ] Feature directory with correct structure
217
+ - [ ] Server module with `'server-only'` import
218
+ - [ ] Validation schemas for all inputs
219
+ - [ ] CRUD API routes with auth wrappers
220
+ - [ ] Page with loading state
221
+ - [ ] List, form, and detail components
222
+ - [ ] Route added to `routes.ts`
223
+ - [ ] Feature flag in `app.config.ts` (if toggleable)
224
+ - [ ] Unit tests for API routes
225
+ - [ ] E2E tests for critical flows
226
+ - [ ] QUALITY_SCORE.md updated
227
+ - [ ] Execution plan marked complete
@@ -0,0 +1,211 @@
1
+ # Skill: Build a Dashboard
2
+
3
+ Create a dashboard page with stat cards, charts, recent activity, and quick actions using MARS design system components.
4
+
5
+ ## When to Use
6
+
7
+ Use this skill when the user asks to build a dashboard, overview page, home screen, or analytics view.
8
+
9
+ ## Layout Architecture
10
+
11
+ MARS dashboards use a responsive grid with Cards as the primary container:
12
+
13
+ ```tsx
14
+ <div className="mx-auto max-w-7xl space-y-6 p-6">
15
+ {/* Header */}
16
+ <div>
17
+ <H1>Dashboard</H1>
18
+ <Paragraph className="text-text-secondary">Overview of your account.</Paragraph>
19
+ </div>
20
+
21
+ {/* Stat Cards Row */}
22
+ <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
23
+ {/* ...stat cards */}
24
+ </div>
25
+
26
+ {/* Main Content */}
27
+ <div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
28
+ <div className="lg:col-span-2">{/* Primary content */}</div>
29
+ <div>{/* Sidebar content */}</div>
30
+ </div>
31
+ </div>
32
+ ```
33
+
34
+ ## Template: Stat Card
35
+
36
+ ```tsx
37
+ import { Card, CardBody } from '@mars-stack/ui';
38
+
39
+ interface StatCardProps {
40
+ title: string;
41
+ value: string | number;
42
+ change?: { value: number; label: string };
43
+ icon?: React.ReactNode;
44
+ }
45
+
46
+ function StatCard({ title, value, change, icon }: StatCardProps) {
47
+ return (
48
+ <Card>
49
+ <CardBody className="flex items-start justify-between">
50
+ <div>
51
+ <p className="text-sm font-medium text-text-secondary">{title}</p>
52
+ <p className="mt-1 text-2xl font-bold text-text-primary">{value}</p>
53
+ {change && (
54
+ <p className={`mt-1 text-sm ${change.value >= 0 ? 'text-text-success' : 'text-text-error'}`}>
55
+ {change.value >= 0 ? '↑' : '↓'} {Math.abs(change.value)}% {change.label}
56
+ </p>
57
+ )}
58
+ </div>
59
+ {icon && (
60
+ <div className="rounded-lg bg-brand-primary-muted p-2 text-brand-primary">
61
+ {icon}
62
+ </div>
63
+ )}
64
+ </CardBody>
65
+ </Card>
66
+ );
67
+ }
68
+ ```
69
+
70
+ ## Template: Full Dashboard Page
71
+
72
+ ```tsx
73
+ import { Card, CardHeader, CardBody, Badge, Spinner, H1, Paragraph } from '@mars-stack/ui';
74
+ import type { Metadata } from 'next';
75
+
76
+ export const metadata: Metadata = { title: 'Dashboard' };
77
+
78
+ export default function DashboardPage() {
79
+ return (
80
+ <div className="mx-auto max-w-7xl space-y-6 p-6">
81
+ <div>
82
+ <H1>Dashboard</H1>
83
+ <Paragraph className="text-text-secondary">
84
+ Welcome back. Here&apos;s what&apos;s happening.
85
+ </Paragraph>
86
+ </div>
87
+
88
+ {/* Stats Row */}
89
+ <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
90
+ <StatCard title="Total Users" value="1,234" change={{ value: 12, label: 'vs last month' }} />
91
+ <StatCard title="Revenue" value="£9,450" change={{ value: 8, label: 'vs last month' }} />
92
+ <StatCard title="Active Projects" value="23" />
93
+ <StatCard title="Completion Rate" value="94%" change={{ value: -2, label: 'vs last month' }} />
94
+ </div>
95
+
96
+ {/* Main Content Grid */}
97
+ <div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
98
+ {/* Recent Activity */}
99
+ <Card className="lg:col-span-2">
100
+ <CardHeader>
101
+ <h2 className="text-lg font-semibold text-text-primary">Recent Activity</h2>
102
+ </CardHeader>
103
+ <CardBody>
104
+ <RecentActivityList />
105
+ </CardBody>
106
+ </Card>
107
+
108
+ {/* Quick Actions */}
109
+ <Card>
110
+ <CardHeader>
111
+ <h2 className="text-lg font-semibold text-text-primary">Quick Actions</h2>
112
+ </CardHeader>
113
+ <CardBody className="space-y-2">
114
+ <QuickActionButton label="Create New Project" href="/projects/new" />
115
+ <QuickActionButton label="Invite Team Member" href="/settings/team" />
116
+ <QuickActionButton label="View Reports" href="/reports" />
117
+ </CardBody>
118
+ </Card>
119
+ </div>
120
+ </div>
121
+ );
122
+ }
123
+ ```
124
+
125
+ ## Template: Recent Activity List
126
+
127
+ ```tsx
128
+ interface ActivityItem {
129
+ id: string;
130
+ action: string;
131
+ subject: string;
132
+ timestamp: string;
133
+ status?: 'success' | 'warning' | 'error' | 'info';
134
+ }
135
+
136
+ function RecentActivityList({ items }: { items: ActivityItem[] }) {
137
+ return (
138
+ <ul className="divide-y divide-border-divider">
139
+ {items.map((item) => (
140
+ <li key={item.id} className="flex items-center justify-between py-3">
141
+ <div>
142
+ <p className="text-sm font-medium text-text-primary">{item.action}</p>
143
+ <p className="text-sm text-text-secondary">{item.subject}</p>
144
+ </div>
145
+ <div className="flex items-center gap-3">
146
+ {item.status && <Badge variant={item.status}>{item.status}</Badge>}
147
+ <span className="text-xs text-text-muted whitespace-nowrap">
148
+ {new Date(item.timestamp).toLocaleDateString()}
149
+ </span>
150
+ </div>
151
+ </li>
152
+ ))}
153
+ </ul>
154
+ );
155
+ }
156
+ ```
157
+
158
+ ## Template: Quick Action Button
159
+
160
+ ```tsx
161
+ import { LinkButton } from '@mars-stack/ui';
162
+
163
+ function QuickActionButton({ label, href }: { label: string; href: string }) {
164
+ return (
165
+ <LinkButton href={href} variant="subtle" className="w-full justify-start">
166
+ {label}
167
+ </LinkButton>
168
+ );
169
+ }
170
+ ```
171
+
172
+ ## Data Fetching Pattern
173
+
174
+ Dashboards typically aggregate data from multiple sources. Use parallel fetches:
175
+
176
+ ```typescript
177
+ // API route: /api/protected/dashboard/route.ts
178
+ export const GET = withAuthNoParams(async (request: AuthenticatedRequest) => {
179
+ try {
180
+ const userId = request.session.userId;
181
+
182
+ const [stats, recentActivity] = await Promise.all([
183
+ getDashboardStats(userId),
184
+ getRecentActivity(userId, 10),
185
+ ]);
186
+
187
+ return NextResponse.json({ stats, recentActivity });
188
+ } catch (error) {
189
+ return handleApiError(error, { endpoint: '/api/protected/dashboard' });
190
+ }
191
+ });
192
+ ```
193
+
194
+ ## Responsive Breakpoints
195
+
196
+ | Breakpoint | Stat Cards | Main Grid |
197
+ |-----------|-----------|-----------|
198
+ | Mobile (`< sm`) | 1 column | 1 column |
199
+ | Tablet (`sm`) | 2 columns | 1 column |
200
+ | Desktop (`lg`) | 4 columns | 2:1 ratio |
201
+
202
+ ## Checklist
203
+
204
+ - [ ] Page wrapped in max-width container with padding
205
+ - [ ] Stat cards in responsive grid (1/2/4 columns)
206
+ - [ ] Main content in 2:1 grid layout at `lg`
207
+ - [ ] All colours use semantic tokens
208
+ - [ ] Loading state for async data
209
+ - [ ] Empty states for sections with no data
210
+ - [ ] SEO metadata exported
211
+ - [ ] Data fetched via protected API route