@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.
- package/package.json +2 -2
- package/template/.cursor/rules/composition-patterns.mdc +186 -0
- package/template/.cursor/rules/data-access.mdc +29 -0
- package/template/.cursor/rules/project-structure.mdc +34 -0
- package/template/.cursor/rules/security.mdc +25 -0
- package/template/.cursor/rules/testing.mdc +24 -0
- package/template/.cursor/rules/ui-conventions.mdc +29 -0
- package/template/.cursor/skills/add-api-route/SKILL.md +122 -0
- package/template/.cursor/skills/add-audit-log/SKILL.md +373 -0
- package/template/.cursor/skills/add-blog/SKILL.md +447 -0
- package/template/.cursor/skills/add-command-palette/SKILL.md +438 -0
- package/template/.cursor/skills/add-component/SKILL.md +158 -0
- package/template/.cursor/skills/add-crud-routes/SKILL.md +221 -0
- package/template/.cursor/skills/add-e2e-test/SKILL.md +227 -0
- package/template/.cursor/skills/add-error-boundary/SKILL.md +472 -0
- package/template/.cursor/skills/add-feature/SKILL.md +174 -0
- package/template/.cursor/skills/add-middleware/SKILL.md +135 -0
- package/template/.cursor/skills/add-page/SKILL.md +151 -0
- package/template/.cursor/skills/add-prisma-model/SKILL.md +148 -0
- package/template/.cursor/skills/add-protected-resource/SKILL.md +192 -0
- package/template/.cursor/skills/add-role/SKILL.md +156 -0
- package/template/.cursor/skills/add-server-action/SKILL.md +167 -0
- package/template/.cursor/skills/add-webhook/SKILL.md +192 -0
- package/template/.cursor/skills/build-complete-feature/SKILL.md +227 -0
- package/template/.cursor/skills/build-dashboard/SKILL.md +211 -0
- package/template/.cursor/skills/build-data-table/SKILL.md +283 -0
- package/template/.cursor/skills/build-form/SKILL.md +231 -0
- package/template/.cursor/skills/build-landing-page/SKILL.md +248 -0
- package/template/.cursor/skills/configure-ai/SKILL.md +617 -0
- package/template/.cursor/skills/configure-analytics/SKILL.md +413 -0
- package/template/.cursor/skills/configure-dark-mode/SKILL.md +309 -0
- package/template/.cursor/skills/configure-email/SKILL.md +170 -0
- package/template/.cursor/skills/configure-email-verification/SKILL.md +333 -0
- package/template/.cursor/skills/configure-feature-flags/SKILL.md +361 -0
- package/template/.cursor/skills/configure-i18n/SKILL.md +518 -0
- package/template/.cursor/skills/configure-jobs/SKILL.md +500 -0
- package/template/.cursor/skills/configure-magic-links/SKILL.md +385 -0
- package/template/.cursor/skills/configure-multi-tenancy/SKILL.md +611 -0
- package/template/.cursor/skills/configure-notifications/SKILL.md +569 -0
- package/template/.cursor/skills/configure-oauth/SKILL.md +217 -0
- package/template/.cursor/skills/configure-onboarding/SKILL.md +483 -0
- package/template/.cursor/skills/configure-payments/SKILL.md +243 -0
- package/template/.cursor/skills/configure-realtime/SKILL.md +733 -0
- package/template/.cursor/skills/configure-search/SKILL.md +581 -0
- package/template/.cursor/skills/configure-storage/SKILL.md +273 -0
- package/template/.cursor/skills/configure-two-factor/SKILL.md +518 -0
- package/template/.cursor/skills/create-execution-plan/SKILL.md +204 -0
- package/template/.cursor/skills/create-seed/SKILL.md +191 -0
- package/template/.cursor/skills/deploy-to-vercel/SKILL.md +300 -0
- package/template/.cursor/skills/design-tokens/SKILL.md +138 -0
- package/template/.cursor/skills/mars-capture-conversation-context/SKILL.md +119 -0
- package/template/.cursor/skills/setup-billing/SKILL.md +322 -0
- package/template/.cursor/skills/setup-project/SKILL.md +104 -0
- package/template/.cursor/skills/setup-teams/SKILL.md +682 -0
- package/template/.cursor/skills/test-api-route/SKILL.md +219 -0
- package/template/.cursor/skills/update-architecture-docs/SKILL.md +99 -0
- package/template/AGENTS.md +104 -0
- package/template/ARCHITECTURE.md +102 -0
- package/template/docs/QUALITY_SCORE.md +20 -0
- package/template/docs/design-docs/conversation-as-system-record.md +70 -0
- package/template/docs/design-docs/core-beliefs.md +43 -0
- package/template/docs/design-docs/index.md +8 -0
- package/template/docs/exec-plans/active/.gitkeep +0 -0
- package/template/docs/exec-plans/completed/.gitkeep +0 -0
- package/template/docs/exec-plans/tech-debt.md +7 -0
- package/template/docs/generated/.gitkeep +0 -0
- package/template/docs/product-specs/index.md +7 -0
- package/template/docs/references/index.md +18 -0
- package/template/e2e/api.spec.ts +20 -0
- package/template/e2e/auth.spec.ts +24 -0
- package/template/e2e/public.spec.ts +25 -0
- package/template/eslint.config.mjs +24 -0
- package/template/next-env.d.ts +6 -0
- package/template/next.config.ts +45 -0
- package/template/package.json +80 -0
- package/template/playwright.config.ts +31 -0
- package/template/postcss.config.mjs +8 -0
- package/template/prisma/generated/prisma/browser.ts +49 -0
- package/template/prisma/generated/prisma/client.ts +73 -0
- package/template/prisma/generated/prisma/commonInputTypes.ts +406 -0
- package/template/prisma/generated/prisma/enums.ts +15 -0
- package/template/prisma/generated/prisma/internal/class.ts +254 -0
- package/template/prisma/generated/prisma/internal/prismaNamespace.ts +1240 -0
- package/template/prisma/generated/prisma/internal/prismaNamespaceBrowser.ts +190 -0
- package/template/prisma/generated/prisma/models/Account.ts +1543 -0
- package/template/prisma/generated/prisma/models/File.ts +1529 -0
- package/template/prisma/generated/prisma/models/Session.ts +1415 -0
- package/template/prisma/generated/prisma/models/Subscription.ts +1455 -0
- package/template/prisma/generated/prisma/models/User.ts +2235 -0
- package/template/prisma/generated/prisma/models/VerificationToken.ts +1099 -0
- package/template/prisma/generated/prisma/models.ts +17 -0
- package/template/prisma/schema/auth.prisma +69 -0
- package/template/prisma/schema/base.prisma +8 -0
- package/template/prisma/schema/file.prisma +15 -0
- package/template/prisma/schema/subscription.prisma +17 -0
- package/template/prisma.config.ts +13 -0
- package/template/scripts/check-architecture.ts +221 -0
- package/template/scripts/check-doc-freshness.ts +242 -0
- package/template/scripts/ensure-db.mjs +291 -0
- package/template/scripts/generate-docs.ts +143 -0
- package/template/scripts/generate-env-example.ts +89 -0
- package/template/scripts/seed.ts +56 -0
- package/template/scripts/update-quality-score.ts +263 -0
- package/template/src/__tests__/architecture.test.ts +114 -0
- package/template/src/app/(auth)/forgotten-password/page.tsx +92 -0
- package/template/src/app/(auth)/layout.tsx +11 -0
- package/template/src/app/(auth)/register/page.tsx +162 -0
- package/template/src/app/(auth)/reset-password/page.tsx +109 -0
- package/template/src/app/(auth)/sign-in/page.tsx +122 -0
- package/template/src/app/(auth)/verify/[token]/page.tsx +87 -0
- package/template/src/app/(auth)/verify/page.tsx +56 -0
- package/template/src/app/(protected)/admin/page.tsx +108 -0
- package/template/src/app/(protected)/dashboard/loading.tsx +20 -0
- package/template/src/app/(protected)/dashboard/page.tsx +22 -0
- package/template/src/app/(protected)/layout.tsx +262 -0
- package/template/src/app/(protected)/settings/page.tsx +370 -0
- package/template/src/app/api/auth/forgot/route.ts +63 -0
- package/template/src/app/api/auth/login/route.ts +121 -0
- package/template/src/app/api/auth/logout/route.ts +19 -0
- package/template/src/app/api/auth/me/route.ts +30 -0
- package/template/src/app/api/auth/reset/route.ts +45 -0
- package/template/src/app/api/auth/signup/route.ts +85 -0
- package/template/src/app/api/auth/verify/route.ts +46 -0
- package/template/src/app/api/csrf/route.ts +12 -0
- package/template/src/app/api/health/route.ts +10 -0
- package/template/src/app/api/protected/admin/users/route.ts +24 -0
- package/template/src/app/api/protected/billing/checkout/route.ts +83 -0
- package/template/src/app/api/protected/billing/portal/route.ts +39 -0
- package/template/src/app/api/protected/files/[fileId]/route.ts +86 -0
- package/template/src/app/api/protected/files/upload/route.ts +64 -0
- package/template/src/app/api/protected/user/password/route.ts +63 -0
- package/template/src/app/api/protected/user/profile/route.ts +35 -0
- package/template/src/app/api/protected/user/sessions/[sessionId]/route.ts +33 -0
- package/template/src/app/api/protected/user/sessions/route.ts +22 -0
- package/template/src/app/api/readiness/route.ts +15 -0
- package/template/src/app/api/webhooks/stripe/route.ts +166 -0
- package/template/src/app/error.tsx +33 -0
- package/template/src/app/layout.tsx +29 -0
- package/template/src/app/not-found.tsx +20 -0
- package/template/src/app/page.tsx +136 -0
- package/template/src/app/privacy/page.tsx +178 -0
- package/template/src/app/providers.tsx +8 -0
- package/template/src/app/terms/page.tsx +139 -0
- package/template/src/config/app.config.ts +70 -0
- package/template/src/config/routes.ts +17 -0
- package/template/src/features/admin/index.ts +11 -0
- package/template/src/features/admin/permissions.ts +64 -0
- package/template/src/features/auth/context/AuthContext.tsx +96 -0
- package/template/src/features/auth/context/index.ts +2 -0
- package/template/src/features/auth/index.ts +3 -0
- package/template/src/features/auth/server/consent.ts +66 -0
- package/template/src/features/auth/server/session-revocation.ts +20 -0
- package/template/src/features/auth/server/sessions.ts +66 -0
- package/template/src/features/auth/server/user.ts +166 -0
- package/template/src/features/auth/types.ts +19 -0
- package/template/src/features/auth/validators.ts +29 -0
- package/template/src/features/billing/server/index.ts +66 -0
- package/template/src/features/billing/types.ts +43 -0
- package/template/src/features/uploads/server/index.ts +49 -0
- package/template/src/features/uploads/types.ts +26 -0
- package/template/src/lib/core/email/templates/base-layout.ts +122 -0
- package/template/src/lib/core/email/templates/index.ts +4 -0
- package/template/src/lib/core/email/templates/password-reset-email.ts +42 -0
- package/template/src/lib/core/email/templates/verification-email.ts +41 -0
- package/template/src/lib/core/email/templates/welcome-email.ts +40 -0
- package/template/src/lib/mars.ts +56 -0
- package/template/src/lib/prisma.ts +19 -0
- package/template/src/proxy.ts +92 -0
- package/template/src/styles/brand.css +17 -0
- package/template/src/styles/globals.css +6 -0
- package/template/tsconfig.json +59 -0
- package/template/vitest.config.ts +41 -0
- package/template/vitest.setup.ts +24 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# Skill: Build a Landing Page
|
|
2
|
+
|
|
3
|
+
Create a marketing landing page with hero, features, CTA sections using MARS design system tokens.
|
|
4
|
+
|
|
5
|
+
## When to Use
|
|
6
|
+
|
|
7
|
+
Use this skill when the user asks to build a landing page, marketing page, home page, or public-facing product page.
|
|
8
|
+
|
|
9
|
+
## Architecture
|
|
10
|
+
|
|
11
|
+
Landing pages are server components (no `'use client'`) for optimal SEO and performance. They live in the public route group.
|
|
12
|
+
|
|
13
|
+
## Directory
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
src/app/(public)/page.tsx # Home landing page
|
|
17
|
+
src/app/(public)/pricing/page.tsx # Pricing page
|
|
18
|
+
src/app/(public)/about/page.tsx # About page
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Template: Full Landing Page
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
import { Button, LinkButton, H1, H2, Paragraph } from '@mars-stack/ui';
|
|
25
|
+
import { appConfig } from '@/config/app.config';
|
|
26
|
+
import type { Metadata } from 'next';
|
|
27
|
+
|
|
28
|
+
export const metadata: Metadata = {
|
|
29
|
+
title: `${appConfig.name} - ${appConfig.tagline}`,
|
|
30
|
+
description: appConfig.description,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export default function HomePage() {
|
|
34
|
+
return (
|
|
35
|
+
<main>
|
|
36
|
+
<HeroSection />
|
|
37
|
+
<FeaturesSection />
|
|
38
|
+
<CTASection />
|
|
39
|
+
</main>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function HeroSection() {
|
|
44
|
+
return (
|
|
45
|
+
<section className="relative overflow-hidden bg-surface-background px-4 py-24 sm:py-32">
|
|
46
|
+
<div className="mx-auto max-w-4xl text-center">
|
|
47
|
+
<h1 className="text-4xl font-bold tracking-tight text-text-primary sm:text-6xl">
|
|
48
|
+
{appConfig.tagline}
|
|
49
|
+
</h1>
|
|
50
|
+
<p className="mx-auto mt-6 max-w-2xl text-lg leading-8 text-text-secondary">
|
|
51
|
+
{appConfig.description}
|
|
52
|
+
</p>
|
|
53
|
+
<div className="mt-10 flex items-center justify-center gap-4">
|
|
54
|
+
<LinkButton href="/register" size="lg">
|
|
55
|
+
Get Started Free
|
|
56
|
+
</LinkButton>
|
|
57
|
+
<LinkButton href="#features" variant="secondary" size="lg">
|
|
58
|
+
Learn More
|
|
59
|
+
</LinkButton>
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
</section>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function FeaturesSection() {
|
|
67
|
+
const features = [
|
|
68
|
+
{
|
|
69
|
+
title: 'Lightning Fast',
|
|
70
|
+
description: 'Built on Next.js 15 with Turbopack for instant feedback during development.',
|
|
71
|
+
icon: '⚡',
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
title: 'Secure by Default',
|
|
75
|
+
description: 'Authentication, CSRF protection, rate limiting, and input validation out of the box.',
|
|
76
|
+
icon: '🔒',
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
title: 'Beautiful UI',
|
|
80
|
+
description: 'A design token system that ensures consistency across every component.',
|
|
81
|
+
icon: '🎨',
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<section id="features" className="bg-surface-card px-4 py-24">
|
|
87
|
+
<div className="mx-auto max-w-6xl">
|
|
88
|
+
<div className="text-center">
|
|
89
|
+
<H2>Everything you need</H2>
|
|
90
|
+
<Paragraph className="mx-auto mt-4 max-w-2xl text-text-secondary">
|
|
91
|
+
All the tools and infrastructure to build and ship your product.
|
|
92
|
+
</Paragraph>
|
|
93
|
+
</div>
|
|
94
|
+
<div className="mt-16 grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-3">
|
|
95
|
+
{features.map((feature) => (
|
|
96
|
+
<div
|
|
97
|
+
key={feature.title}
|
|
98
|
+
className="rounded-xl border border-border-default bg-surface-background p-6"
|
|
99
|
+
>
|
|
100
|
+
<div className="mb-4 text-3xl">{feature.icon}</div>
|
|
101
|
+
<h3 className="text-lg font-semibold text-text-primary">{feature.title}</h3>
|
|
102
|
+
<p className="mt-2 text-text-secondary">{feature.description}</p>
|
|
103
|
+
</div>
|
|
104
|
+
))}
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
</section>
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function CTASection() {
|
|
112
|
+
return (
|
|
113
|
+
<section className="bg-brand-primary px-4 py-24">
|
|
114
|
+
<div className="mx-auto max-w-4xl text-center">
|
|
115
|
+
<h2 className="text-3xl font-bold text-text-on-brand sm:text-4xl">
|
|
116
|
+
Ready to get started?
|
|
117
|
+
</h2>
|
|
118
|
+
<p className="mx-auto mt-4 max-w-xl text-lg text-text-on-brand/80">
|
|
119
|
+
Create your account in 30 seconds. No credit card required.
|
|
120
|
+
</p>
|
|
121
|
+
<div className="mt-8">
|
|
122
|
+
<LinkButton
|
|
123
|
+
href="/register"
|
|
124
|
+
variant="secondary"
|
|
125
|
+
size="lg"
|
|
126
|
+
className="bg-white text-brand-primary hover:bg-white/90"
|
|
127
|
+
>
|
|
128
|
+
Start Building
|
|
129
|
+
</LinkButton>
|
|
130
|
+
</div>
|
|
131
|
+
</div>
|
|
132
|
+
</section>
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Common Sections
|
|
138
|
+
|
|
139
|
+
### Social Proof / Logos
|
|
140
|
+
|
|
141
|
+
```tsx
|
|
142
|
+
function LogoCloud() {
|
|
143
|
+
return (
|
|
144
|
+
<section className="bg-surface-background px-4 py-16">
|
|
145
|
+
<div className="mx-auto max-w-6xl">
|
|
146
|
+
<p className="text-center text-sm font-medium text-text-muted uppercase tracking-wide">
|
|
147
|
+
Trusted by teams at
|
|
148
|
+
</p>
|
|
149
|
+
<div className="mt-8 flex flex-wrap items-center justify-center gap-8 opacity-60">
|
|
150
|
+
{/* Logo images or SVGs */}
|
|
151
|
+
</div>
|
|
152
|
+
</div>
|
|
153
|
+
</section>
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Testimonials
|
|
159
|
+
|
|
160
|
+
```tsx
|
|
161
|
+
function TestimonialsSection() {
|
|
162
|
+
const testimonials = [
|
|
163
|
+
{ quote: '...', author: 'Jane', role: 'CTO at Acme' },
|
|
164
|
+
];
|
|
165
|
+
|
|
166
|
+
return (
|
|
167
|
+
<section className="bg-surface-background px-4 py-24">
|
|
168
|
+
<div className="mx-auto max-w-6xl">
|
|
169
|
+
<H2 className="text-center">What people say</H2>
|
|
170
|
+
<div className="mt-12 grid grid-cols-1 gap-8 md:grid-cols-3">
|
|
171
|
+
{testimonials.map((t, i) => (
|
|
172
|
+
<div key={i} className="rounded-xl border border-border-default bg-surface-card p-6">
|
|
173
|
+
<p className="text-text-primary italic">“{t.quote}”</p>
|
|
174
|
+
<div className="mt-4">
|
|
175
|
+
<p className="font-medium text-text-primary">{t.author}</p>
|
|
176
|
+
<p className="text-sm text-text-secondary">{t.role}</p>
|
|
177
|
+
</div>
|
|
178
|
+
</div>
|
|
179
|
+
))}
|
|
180
|
+
</div>
|
|
181
|
+
</div>
|
|
182
|
+
</section>
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Pricing Cards
|
|
188
|
+
|
|
189
|
+
```tsx
|
|
190
|
+
function PricingCard({ name, price, features, highlighted }: PricingCardProps) {
|
|
191
|
+
return (
|
|
192
|
+
<div className={clsx(
|
|
193
|
+
'rounded-xl border p-8',
|
|
194
|
+
highlighted
|
|
195
|
+
? 'border-brand-primary bg-surface-card shadow-lg ring-2 ring-brand-primary'
|
|
196
|
+
: 'border-border-default bg-surface-card'
|
|
197
|
+
)}>
|
|
198
|
+
<h3 className="text-lg font-semibold text-text-primary">{name}</h3>
|
|
199
|
+
<p className="mt-4">
|
|
200
|
+
<span className="text-4xl font-bold text-text-primary">£{price}</span>
|
|
201
|
+
<span className="text-text-secondary">/month</span>
|
|
202
|
+
</p>
|
|
203
|
+
<ul className="mt-6 space-y-3">
|
|
204
|
+
{features.map((f) => (
|
|
205
|
+
<li key={f} className="flex items-center gap-2 text-text-secondary">
|
|
206
|
+
<span className="text-text-success">✓</span> {f}
|
|
207
|
+
</li>
|
|
208
|
+
))}
|
|
209
|
+
</ul>
|
|
210
|
+
<LinkButton
|
|
211
|
+
href="/register"
|
|
212
|
+
variant={highlighted ? 'primary' : 'secondary'}
|
|
213
|
+
className="mt-8 w-full"
|
|
214
|
+
>
|
|
215
|
+
Get Started
|
|
216
|
+
</LinkButton>
|
|
217
|
+
</div>
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## SEO
|
|
223
|
+
|
|
224
|
+
Landing pages should export `metadata` with:
|
|
225
|
+
- `title` -- from `appConfig.name` + tagline
|
|
226
|
+
- `description` -- from `appConfig.description`
|
|
227
|
+
- `openGraph` -- images, type, url
|
|
228
|
+
- Structured data via `JsonLd` component
|
|
229
|
+
|
|
230
|
+
```tsx
|
|
231
|
+
import { JsonLd } from '@mars-stack/ui';
|
|
232
|
+
import { buildOrganizationJsonLd } from '@/lib/mars';
|
|
233
|
+
|
|
234
|
+
// In the page:
|
|
235
|
+
<JsonLd data={buildOrganizationJsonLd()} />
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## Checklist
|
|
239
|
+
|
|
240
|
+
- [ ] Server component (no `'use client'`)
|
|
241
|
+
- [ ] SEO metadata exported
|
|
242
|
+
- [ ] Hero with clear value proposition and CTA
|
|
243
|
+
- [ ] Features section with grid layout
|
|
244
|
+
- [ ] CTA section with brand background
|
|
245
|
+
- [ ] All colours use semantic tokens
|
|
246
|
+
- [ ] Responsive at all breakpoints
|
|
247
|
+
- [ ] Uses `appConfig` for dynamic content (name, tagline, description)
|
|
248
|
+
- [ ] `JsonLd` structured data included
|