gspec 1.7.0 → 1.10.0
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/bin/gspec.js +275 -8
- package/commands/gspec.analyze.md +1 -1
- package/commands/gspec.implement.md +3 -3
- package/commands/gspec.practices.md +3 -1
- package/commands/gspec.stack.md +11 -6
- package/commands/gspec.style.md +18 -23
- package/dist/antigravity/gspec-analyze/SKILL.md +1 -1
- package/dist/antigravity/gspec-architect/SKILL.md +1 -1
- package/dist/antigravity/gspec-feature/SKILL.md +1 -1
- package/dist/antigravity/gspec-implement/SKILL.md +4 -4
- package/dist/antigravity/gspec-migrate/SKILL.md +5 -5
- package/dist/antigravity/gspec-practices/SKILL.md +4 -2
- package/dist/antigravity/gspec-profile/SKILL.md +1 -1
- package/dist/antigravity/gspec-research/SKILL.md +3 -3
- package/dist/antigravity/gspec-stack/SKILL.md +12 -7
- package/dist/antigravity/gspec-style/SKILL.md +19 -24
- package/dist/claude/gspec-analyze/SKILL.md +1 -1
- package/dist/claude/gspec-architect/SKILL.md +1 -1
- package/dist/claude/gspec-feature/SKILL.md +1 -1
- package/dist/claude/gspec-implement/SKILL.md +4 -4
- package/dist/claude/gspec-migrate/SKILL.md +5 -5
- package/dist/claude/gspec-practices/SKILL.md +4 -2
- package/dist/claude/gspec-profile/SKILL.md +1 -1
- package/dist/claude/gspec-research/SKILL.md +3 -3
- package/dist/claude/gspec-stack/SKILL.md +12 -7
- package/dist/claude/gspec-style/SKILL.md +19 -24
- package/dist/codex/gspec-analyze/SKILL.md +1 -1
- package/dist/codex/gspec-architect/SKILL.md +1 -1
- package/dist/codex/gspec-feature/SKILL.md +1 -1
- package/dist/codex/gspec-implement/SKILL.md +4 -4
- package/dist/codex/gspec-migrate/SKILL.md +5 -5
- package/dist/codex/gspec-practices/SKILL.md +4 -2
- package/dist/codex/gspec-profile/SKILL.md +1 -1
- package/dist/codex/gspec-research/SKILL.md +3 -3
- package/dist/codex/gspec-stack/SKILL.md +12 -7
- package/dist/codex/gspec-style/SKILL.md +19 -24
- package/dist/cursor/gspec-analyze.mdc +1 -1
- package/dist/cursor/gspec-architect.mdc +1 -1
- package/dist/cursor/gspec-feature.mdc +1 -1
- package/dist/cursor/gspec-implement.mdc +4 -4
- package/dist/cursor/gspec-migrate.mdc +5 -5
- package/dist/cursor/gspec-practices.mdc +4 -2
- package/dist/cursor/gspec-profile.mdc +1 -1
- package/dist/cursor/gspec-research.mdc +3 -3
- package/dist/cursor/gspec-stack.mdc +12 -7
- package/dist/cursor/gspec-style.mdc +19 -24
- package/dist/opencode/gspec-analyze/SKILL.md +168 -0
- package/dist/opencode/gspec-architect/SKILL.md +361 -0
- package/dist/opencode/gspec-feature/SKILL.md +204 -0
- package/dist/opencode/gspec-implement/SKILL.md +200 -0
- package/dist/opencode/gspec-migrate/SKILL.md +118 -0
- package/dist/opencode/gspec-practices/SKILL.md +137 -0
- package/dist/opencode/gspec-profile/SKILL.md +221 -0
- package/dist/opencode/gspec-research/SKILL.md +302 -0
- package/dist/opencode/gspec-stack/SKILL.md +305 -0
- package/dist/opencode/gspec-style/SKILL.md +224 -0
- package/package.json +3 -1
- package/starters/features/about-page.md +98 -0
- package/starters/features/contact-form.md +147 -0
- package/starters/features/contact-page.md +103 -0
- package/starters/features/home-page.md +103 -0
- package/starters/features/responsive-navbar.md +113 -0
- package/starters/features/services-page.md +103 -0
- package/starters/features/site-footer.md +121 -0
- package/starters/features/theme-switcher.md +124 -0
- package/starters/practices/tdd-pipeline-first.md +192 -0
- package/starters/stacks/astro-tailwind-github-pages.md +283 -0
- package/starters/stacks/nextjs-supabase-vercel.md +319 -0
- package/starters/stacks/nextjs-vercel-typescript.md +264 -0
- package/starters/styles/clean-professional.md +316 -0
- package/starters/styles/dark-minimal-developer.md +442 -0
- package/templates/spec-sync.md +1 -1
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
---
|
|
2
|
+
gspec-version: 1.8.0
|
|
3
|
+
description: Full-stack SaaS with Next.js App Router, Supabase (Postgres, Auth, RLS), and Vercel deployment
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Technology Stack
|
|
7
|
+
|
|
8
|
+
## 1. Overview
|
|
9
|
+
|
|
10
|
+
- **Architecture style:** Full-stack monolith — a single Next.js application handling both frontend rendering and API routes, backed by Supabase for managed database, authentication, and real-time capabilities.
|
|
11
|
+
- **Deployment target:** Vercel (serverless edge and Node.js runtimes). Supabase Cloud for managed Postgres and auth services.
|
|
12
|
+
- **Scale and performance requirements:** Early-stage SaaS supporting tens to low hundreds of concurrent users. Supabase connection pooling and Vercel's edge network handle initial scale. Architecture should support horizontal scaling without major refactoring.
|
|
13
|
+
|
|
14
|
+
## 2. Open Questions & Clarifications
|
|
15
|
+
|
|
16
|
+
None — all critical decisions are resolved.
|
|
17
|
+
|
|
18
|
+
## 3. Core Technology Stack
|
|
19
|
+
|
|
20
|
+
### Programming Languages
|
|
21
|
+
|
|
22
|
+
- **Primary language:** TypeScript (strict mode enabled)
|
|
23
|
+
- **Rationale:** Type safety across the full stack (frontend + API routes + database queries). Reduces bugs, improves IDE support, and is the standard for modern Next.js development.
|
|
24
|
+
- **Language-specific tooling:**
|
|
25
|
+
- ESLint for linting (with `@next/eslint-plugin-next`)
|
|
26
|
+
- Prettier for formatting
|
|
27
|
+
- `typescript` compiler in strict mode (`strict: true` in `tsconfig.json`)
|
|
28
|
+
|
|
29
|
+
### Runtime Environment
|
|
30
|
+
|
|
31
|
+
- **Runtime:** Node.js 20 LTS
|
|
32
|
+
- **Package manager:** pnpm
|
|
33
|
+
- **Rationale:** Faster installs, strict dependency resolution (prevents phantom dependencies), disk-efficient via content-addressable storage. Well-supported by Vercel.
|
|
34
|
+
- **Container runtime:** Not applicable — deployed as serverless functions on Vercel. Docker used only for local Supabase development via `supabase start`.
|
|
35
|
+
|
|
36
|
+
## 4. Frontend Stack
|
|
37
|
+
|
|
38
|
+
### Framework
|
|
39
|
+
|
|
40
|
+
- **Framework:** Next.js 15 (App Router)
|
|
41
|
+
- **Rationale:** React-based full-stack framework with server components, server actions, and API routes in a single project. First-class Vercel deployment support. App Router enables streaming, partial prerendering, and co-located data fetching.
|
|
42
|
+
- **React version:** React 19 (ships with Next.js 15)
|
|
43
|
+
- **Update strategy:** Stay on latest stable Next.js minor releases. Evaluate major upgrades within 2 weeks of release.
|
|
44
|
+
|
|
45
|
+
### Build Tools
|
|
46
|
+
|
|
47
|
+
- **Bundler:** Turbopack (Next.js built-in, used in development)
|
|
48
|
+
- **Production builds:** Next.js built-in compiler (SWC-based)
|
|
49
|
+
- **No additional bundler configuration needed** — Next.js handles transpilation, code splitting, tree shaking, and minification out of the box.
|
|
50
|
+
|
|
51
|
+
### State Management
|
|
52
|
+
|
|
53
|
+
- **Server state:** React Server Components for initial data loading. `@supabase/ssr` for authenticated server-side data fetching.
|
|
54
|
+
- **Client state:** React's built-in state (`useState`, `useReducer`, `useContext`) for local UI state. No external state management library needed at this stage.
|
|
55
|
+
- **Data fetching on the client:** Supabase client library for real-time subscriptions and client-initiated mutations. Consider adding `swr` or `@tanstack/react-query` only if caching/revalidation patterns become complex.
|
|
56
|
+
|
|
57
|
+
### Styling Technology
|
|
58
|
+
|
|
59
|
+
- **CSS framework:** Tailwind CSS v4
|
|
60
|
+
- **Rationale:** Utility-first approach enables rapid UI development. Excellent tree-shaking keeps bundle size small.
|
|
61
|
+
- **Component library:** shadcn/ui
|
|
62
|
+
- **Rationale:** Copy-paste component primitives built on Radix UI. Fully customizable (not a locked dependency), accessible by default, designed for Tailwind. Components live in the codebase, not `node_modules`.
|
|
63
|
+
- **Design token mapping:** Tailwind's CSS custom properties (defined in `app/globals.css`) serve as the bridge between design tokens documented in `gspec/style.md` and utility classes. shadcn/ui's theming uses these same CSS variables for consistent styling.
|
|
64
|
+
- **Note**: Icon library choices are defined in `gspec/style.md`. The stack defines the CSS framework and component library; the style defines the icon set.
|
|
65
|
+
|
|
66
|
+
### Progressive Web App
|
|
67
|
+
|
|
68
|
+
- **PWA implementation:** `next-pwa` (or `@serwist/next`) for service worker generation and caching.
|
|
69
|
+
- **Manifest:** `manifest.json` in the `public/` directory with app name, icons, theme color, and display mode (`standalone`).
|
|
70
|
+
- **Offline strategy:** Cache-first for static assets. Network-first for API calls with fallback to cached data where appropriate.
|
|
71
|
+
- **Install prompt:** Native browser install prompt. No custom install UI for MVP.
|
|
72
|
+
|
|
73
|
+
## 5. Backend Stack
|
|
74
|
+
|
|
75
|
+
### Framework
|
|
76
|
+
|
|
77
|
+
- **API layer:** Next.js Route Handlers (App Router `route.ts` files) for application API endpoints.
|
|
78
|
+
- **API style:** RESTful JSON APIs via Route Handlers. Supabase client SDK used directly in Server Components and Server Actions for database operations where no custom API logic is needed.
|
|
79
|
+
- **Server Actions:** Used for form mutations and simple data writes that don't need a formal API endpoint.
|
|
80
|
+
|
|
81
|
+
### Database
|
|
82
|
+
|
|
83
|
+
- **Primary database:** Supabase Postgres (managed PostgreSQL)
|
|
84
|
+
- **Rationale:** Managed Postgres with built-in auth, Row Level Security, real-time subscriptions, and a generous free tier. Eliminates the need for a separate auth service and reduces infrastructure complexity.
|
|
85
|
+
- **ORM / query builder:** Supabase JavaScript client (`@supabase/supabase-js`) for data access. Supabase auto-generates a typed client from the database schema.
|
|
86
|
+
- **Type generation:** Use `supabase gen types typescript` to generate TypeScript types from the database schema. Regenerate after every migration.
|
|
87
|
+
- **Migration strategy:** Supabase CLI migrations (`supabase migration new`, `supabase db push`). Migrations are SQL files stored in `supabase/migrations/` and version-controlled in git.
|
|
88
|
+
- **Connection pooling:** Supabase's built-in Supavisor connection pooler (transaction mode) for serverless function compatibility.
|
|
89
|
+
|
|
90
|
+
### Row Level Security (RLS)
|
|
91
|
+
|
|
92
|
+
- **RLS is mandatory on all tables.** Every table must have RLS enabled with appropriate policies before being used by the application.
|
|
93
|
+
- **Policy design:** Policies use `auth.uid()` to scope data access to the authenticated user's resources. Multi-tenant isolation is enforced at the database level, not the application level.
|
|
94
|
+
- **Service role:** The Supabase service role key is used only in server-side contexts (Route Handlers, Server Actions) when RLS bypass is explicitly needed (e.g., admin operations, background jobs). Never expose the service role key to the client.
|
|
95
|
+
|
|
96
|
+
### Caching Layer
|
|
97
|
+
|
|
98
|
+
- **No dedicated caching service for MVP.** Leverage:
|
|
99
|
+
- Next.js Data Cache and `revalidatePath`/`revalidateTag` for server-side caching
|
|
100
|
+
- Vercel Edge Cache for static and ISR pages
|
|
101
|
+
- Browser caching via service worker (PWA)
|
|
102
|
+
- **Upgrade path:** Add Redis (Upstash) if query patterns demand it post-launch.
|
|
103
|
+
|
|
104
|
+
### Message Queue / Event Bus
|
|
105
|
+
|
|
106
|
+
Not applicable for MVP. Background jobs (e.g., scheduled reports, data syncs) will use Vercel Cron to trigger Next.js Route Handlers on a schedule. This keeps all code in the single Next.js codebase. Upgrade to a dedicated queue if job volume or complexity warrants it.
|
|
107
|
+
|
|
108
|
+
## 6. Infrastructure & DevOps
|
|
109
|
+
|
|
110
|
+
### Cloud Provider
|
|
111
|
+
|
|
112
|
+
- **Primary:** Vercel for application hosting and edge network.
|
|
113
|
+
- **Database & Auth:** Supabase Cloud (runs on AWS under the hood).
|
|
114
|
+
- **Key services used:**
|
|
115
|
+
- Vercel: Serverless Functions, Edge Network, Preview Deployments, Analytics
|
|
116
|
+
- Supabase: Postgres, Auth, Realtime, Edge Functions, Storage (for file uploads if needed)
|
|
117
|
+
|
|
118
|
+
### Container Orchestration
|
|
119
|
+
|
|
120
|
+
Not applicable — fully serverless architecture. Vercel manages function scaling and routing. Supabase manages database scaling.
|
|
121
|
+
|
|
122
|
+
### CI/CD Pipeline
|
|
123
|
+
|
|
124
|
+
- **Platform:** GitHub Actions
|
|
125
|
+
- *Rationale:* Native GitHub integration for PRs and branch workflows. Pairs well with Vercel's GitHub integration for preview deployments.
|
|
126
|
+
- **Deployment trigger:** Merge to `main` branch.
|
|
127
|
+
- **Deployment method:** Vercel GitHub integration — automatic preview deploys on every PR, production deploy on merge to `main`.
|
|
128
|
+
- **Database migrations:** Applied manually via `supabase db push` or automated in the deploy pipeline for production.
|
|
129
|
+
- **Branch strategy:** Feature branches → PR → merge to `main` → auto-deploy to production.
|
|
130
|
+
- **Note:** Pipeline stages and structure (lint → typecheck → test → build → deploy) are defined in `gspec/practices.md`. This section defines the CI technology and deployment configuration.
|
|
131
|
+
|
|
132
|
+
### Infrastructure as Code
|
|
133
|
+
|
|
134
|
+
- **Supabase configuration:** `supabase/config.toml` for local dev settings. SQL migrations in `supabase/migrations/` for schema changes.
|
|
135
|
+
- **Vercel configuration:** `vercel.json` for redirects, headers, and function configuration. Environment variables managed via Vercel dashboard and `vercel env pull` for local dev.
|
|
136
|
+
- **No dedicated IaC tool** (Terraform, etc.) needed at this stage — both Vercel and Supabase are fully managed.
|
|
137
|
+
|
|
138
|
+
## 7. Data & Storage
|
|
139
|
+
|
|
140
|
+
### File Storage
|
|
141
|
+
|
|
142
|
+
- **Object storage:** Supabase Storage for user-uploaded files (e.g., business logos, report assets).
|
|
143
|
+
- **CDN:** Vercel Edge Network for static assets. Supabase Storage has built-in CDN via its transformation API.
|
|
144
|
+
- **Asset management:** Static assets (images, fonts, icons) in `public/` directory, served via Vercel's CDN.
|
|
145
|
+
|
|
146
|
+
### Data Warehouse / Analytics
|
|
147
|
+
|
|
148
|
+
Not applicable for MVP. Analytics via Vercel built-in analytics. Revisit when reporting features require historical data aggregation.
|
|
149
|
+
|
|
150
|
+
## 8. Authentication & Security
|
|
151
|
+
|
|
152
|
+
### Authentication
|
|
153
|
+
|
|
154
|
+
- **Auth provider:** Supabase Auth
|
|
155
|
+
- **Rationale:** Tightly integrated with Supabase Postgres and RLS. Supports email/password, magic links, and OAuth providers. Free tier is generous.
|
|
156
|
+
- **Authentication flow:**
|
|
157
|
+
- Email/password with email confirmation
|
|
158
|
+
- Magic link login as an alternative
|
|
159
|
+
- Google OAuth for quick signup
|
|
160
|
+
- Session management via Supabase Auth cookies (using `@supabase/ssr` for server-side session handling)
|
|
161
|
+
- **Custom login pages:** All auth UI is custom-built using shadcn/ui components. No Supabase-branded auth UI (`@supabase/auth-ui-react`) is used. Auth flows call `supabase.auth.signInWithPassword()`, `signUp()`, etc. directly.
|
|
162
|
+
- **Identity management:** Supabase Auth handles user records. Application-level user profiles stored in a `profiles` table linked to `auth.users` via foreign key.
|
|
163
|
+
|
|
164
|
+
### Authorization
|
|
165
|
+
|
|
166
|
+
- **Pattern:** Row Level Security (RLS) at the database layer for data access control. Application-level role checks for UI and API authorization.
|
|
167
|
+
- **Roles:** Users belong to organizations. Roles (e.g., owner, member) are stored in a membership table and checked in RLS policies and server-side logic.
|
|
168
|
+
- **Permission management:** RLS policies are the primary enforcement mechanism. Server-side middleware validates session and role before processing sensitive operations.
|
|
169
|
+
|
|
170
|
+
### Security Tools
|
|
171
|
+
|
|
172
|
+
- **Secrets management:** Environment variables stored in Vercel (production) and `.env.local` (development, git-ignored). Supabase service role key and other sensitive values never committed to source control.
|
|
173
|
+
- **Security headers:** Configured via `next.config.ts` security headers (CSP, HSTS, X-Frame-Options, etc.) and Vercel's built-in protections.
|
|
174
|
+
- **Dependency scanning:** Dependabot or Renovate for automated dependency updates. `pnpm audit` in CI pipeline.
|
|
175
|
+
|
|
176
|
+
## 9. Monitoring & Observability
|
|
177
|
+
|
|
178
|
+
### Application Monitoring
|
|
179
|
+
|
|
180
|
+
- **Primary:** Vercel Analytics (Web Vitals, page performance, function execution times).
|
|
181
|
+
- **Speed Insights:** Vercel Speed Insights for real-user Core Web Vitals monitoring.
|
|
182
|
+
- **Product analytics:** Google Analytics 4 (GA4) for user behavior tracking, acquisition channels, and conversion funnels. Integrated via `@next/third-parties` Google tag support for optimal Next.js compatibility (script loading, route change tracking). Measurement ID stored as a `NEXT_PUBLIC_GA_MEASUREMENT_ID` environment variable.
|
|
183
|
+
- **Upgrade path:** Add Sentry or Datadog if error volume or debugging complexity warrants it post-launch.
|
|
184
|
+
|
|
185
|
+
### Logging
|
|
186
|
+
|
|
187
|
+
- **Application logs:** `console.log` / `console.error` in server functions, captured by Vercel's built-in log drain.
|
|
188
|
+
- **Supabase logs:** Available via Supabase Dashboard (Postgres logs, Auth logs, Edge Function logs).
|
|
189
|
+
- **Structured logging:** Use a lightweight structured logger (e.g., `pino`) if log volume grows and needs parsing.
|
|
190
|
+
|
|
191
|
+
### Tracing
|
|
192
|
+
|
|
193
|
+
Not applicable for MVP — single-service architecture doesn't require distributed tracing. Vercel function logs provide request-level visibility.
|
|
194
|
+
|
|
195
|
+
### Error Tracking
|
|
196
|
+
|
|
197
|
+
- **Primary:** Vercel's built-in error reporting for function errors and build failures.
|
|
198
|
+
- **Client-side:** React Error Boundaries for graceful UI error handling. Errors logged to console and visible in Vercel logs.
|
|
199
|
+
- **Upgrade path:** Add Sentry for structured error tracking with stack traces and release correlation.
|
|
200
|
+
|
|
201
|
+
## 10. Testing Infrastructure
|
|
202
|
+
|
|
203
|
+
### Testing Frameworks
|
|
204
|
+
|
|
205
|
+
- **Unit & integration testing:** Vitest
|
|
206
|
+
- **Rationale:** Fast, Vite-native, excellent TypeScript support, Jest-compatible API. Runs significantly faster than Jest for modern TypeScript projects.
|
|
207
|
+
- **E2E testing:** Playwright
|
|
208
|
+
- **Rationale:** Cross-browser support, reliable auto-waiting, excellent developer tooling (codegen, trace viewer). Runs against actual Vercel preview deployments.
|
|
209
|
+
- **Component testing:** Vitest with `@testing-library/react` for testing React components in isolation.
|
|
210
|
+
|
|
211
|
+
### Test Data Management
|
|
212
|
+
|
|
213
|
+
- **Test database:** Local Supabase instance via `supabase start` (Docker-based) for integration tests.
|
|
214
|
+
- **Fixtures:** SQL seed files in `supabase/seed.sql` for consistent test data.
|
|
215
|
+
- **Mocking:** Vitest's built-in mocking for unit tests. MSW (Mock Service Worker) for mocking external API calls in integration tests.
|
|
216
|
+
|
|
217
|
+
### Performance Testing
|
|
218
|
+
|
|
219
|
+
Not applicable for MVP. Add load testing (k6 or similar) when approaching production scale.
|
|
220
|
+
|
|
221
|
+
## 11. Third-Party Integrations
|
|
222
|
+
|
|
223
|
+
### External Services
|
|
224
|
+
|
|
225
|
+
### API Clients
|
|
226
|
+
|
|
227
|
+
- **HTTP client:** Native `fetch` API (available in Node.js 20+ and Next.js server contexts). No Axios dependency needed.
|
|
228
|
+
- **SDK usage:** Use official SDKs where available (e.g., Google APIs client library). Fall back to `fetch` for APIs without official TypeScript SDKs.
|
|
229
|
+
- **API versioning:** Pin external API versions where possible. Abstract third-party API calls behind internal service modules to isolate breaking changes.
|
|
230
|
+
|
|
231
|
+
## 12. Development Tools
|
|
232
|
+
|
|
233
|
+
### Package Management
|
|
234
|
+
|
|
235
|
+
- **Package manager:** pnpm (v9+)
|
|
236
|
+
- **Dependency strategy:** Pin exact versions in `pnpm-lock.yaml`. Use `pnpm up --latest` for controlled upgrades. Automated dependency PRs via Dependabot or Renovate.
|
|
237
|
+
- **Private registry:** Not applicable.
|
|
238
|
+
|
|
239
|
+
### Code Quality Tools
|
|
240
|
+
|
|
241
|
+
- **Linter:** ESLint with `@next/eslint-plugin-next`, `eslint-plugin-react-hooks`, and `typescript-eslint`
|
|
242
|
+
- **Formatter:** Prettier (integrated with ESLint via `eslint-config-prettier`)
|
|
243
|
+
- **Pre-commit hooks:** `lint-staged` + `husky` for running lint and format checks on staged files before commit
|
|
244
|
+
|
|
245
|
+
### Local Development
|
|
246
|
+
|
|
247
|
+
- **Local environment:**
|
|
248
|
+
- `pnpm dev` — Next.js dev server with Turbopack
|
|
249
|
+
- `supabase start` — Local Supabase stack (Postgres, Auth, Storage, Realtime) via Docker
|
|
250
|
+
- `.env.local` — Local environment variables (Supabase URL, anon key, etc.)
|
|
251
|
+
- **Database GUI:** Supabase Studio (included with `supabase start`, available at `localhost:54323`)
|
|
252
|
+
- **Hot reload:** Turbopack provides fast refresh for frontend changes. Server-side changes auto-restart.
|
|
253
|
+
|
|
254
|
+
## 13. Migration & Compatibility
|
|
255
|
+
|
|
256
|
+
### Legacy System Integration
|
|
257
|
+
|
|
258
|
+
Not applicable — greenfield project with no legacy systems.
|
|
259
|
+
|
|
260
|
+
### Upgrade Path
|
|
261
|
+
|
|
262
|
+
- **Next.js:** Follow Vercel's upgrade guides for major versions. Canary testing on preview branches before upgrading production.
|
|
263
|
+
- **Supabase:** Managed upgrades handled by Supabase Cloud. Test migration compatibility against local Supabase instance before applying to production.
|
|
264
|
+
- **Breaking change management:** Automated dependency update PRs. CI pipeline catches regressions before merge.
|
|
265
|
+
|
|
266
|
+
## 14. Technology Decisions & Tradeoffs
|
|
267
|
+
|
|
268
|
+
### Key Architectural Decisions
|
|
269
|
+
|
|
270
|
+
| Decision | Rationale | Alternative Considered | Tradeoff |
|
|
271
|
+
|---|---|---|---|
|
|
272
|
+
| **Next.js App Router** | Server components, streaming, co-located data fetching. Vercel-optimized. | Pages Router | App Router is newer with some rough edges, but is the future of Next.js |
|
|
273
|
+
| **Supabase over custom backend** | Managed Postgres + Auth + Realtime eliminates boilerplate. RLS provides multi-tenant security at the DB layer. | Separate API server + Auth0 + managed Postgres | Less flexibility in auth flows and background job processing, but dramatically faster to ship |
|
|
274
|
+
| **shadcn/ui over a component library** | Components live in the codebase, fully customizable. No version lock-in. | MUI, Chakra, Mantine | More initial setup than a batteries-included library, but better long-term control |
|
|
275
|
+
| **Custom auth pages over Supabase Auth UI** | Full brand control, no Supabase branding, custom UX | `@supabase/auth-ui-react` | More code to maintain, but necessary for professional SaaS appearance |
|
|
276
|
+
| **Vercel over self-hosted** | Zero-config deploys, preview environments, edge network, analytics. | AWS (ECS/Lambda), Fly.io | Vendor lock-in to Vercel, higher costs at scale. Acceptable for early stage. |
|
|
277
|
+
| **RLS over application-level authorization** | Security enforced at DB layer — no way to accidentally bypass in application code | Middleware-only auth checks | RLS policies are harder to debug and test. Worth it for multi-tenant data isolation. |
|
|
278
|
+
|
|
279
|
+
### Risk Mitigation
|
|
280
|
+
|
|
281
|
+
- **Vercel vendor lock-in:** Next.js is open source and can be self-hosted. Migration path exists if Vercel costs become prohibitive.
|
|
282
|
+
- **Supabase availability:** Supabase is backed by standard Postgres. Data can be migrated to any Postgres host. Auth can be replaced with a custom solution or another provider.
|
|
283
|
+
- **Serverless cold starts:** Vercel's edge runtime and function warm-up mitigate most cold start issues. Monitor function execution times via Vercel Analytics.
|
|
284
|
+
|
|
285
|
+
## 15. Technology-Specific Practices
|
|
286
|
+
|
|
287
|
+
### Framework Conventions & Patterns
|
|
288
|
+
|
|
289
|
+
- **App Router structure:** Use the `app/` directory with route groups for logical organization (e.g., `(auth)` for login/signup, `(dashboard)` for authenticated pages, `(marketing)` for public pages).
|
|
290
|
+
- **Server vs Client Components:** Default to Server Components. Add `"use client"` only when the component needs browser APIs, event handlers, or React hooks (`useState`, `useEffect`).
|
|
291
|
+
- **Data fetching:** Fetch data in Server Components or Server Actions. Avoid `useEffect` for data fetching on the client. Use Supabase's real-time subscriptions for live updates on the client.
|
|
292
|
+
- **Route Handlers:** Use `app/api/` route handlers only for webhook endpoints, external API integrations, or operations that need explicit HTTP method handling. Prefer Server Actions for form mutations.
|
|
293
|
+
- **Loading and error states:** Use `loading.tsx` and `error.tsx` files at appropriate route levels for streaming UI and error boundaries.
|
|
294
|
+
|
|
295
|
+
### Library Usage Patterns
|
|
296
|
+
|
|
297
|
+
- **Supabase client initialization:**
|
|
298
|
+
- Server Components / Server Actions: Create a Supabase client per-request using `@supabase/ssr` with cookie-based session handling
|
|
299
|
+
- Client Components: Create a browser client using `createBrowserClient` from `@supabase/ssr`
|
|
300
|
+
- Route Handlers: Create a server client with cookie access
|
|
301
|
+
- Never instantiate the service role client on the client side
|
|
302
|
+
- **shadcn/ui usage:** Components installed into `components/ui/`. Customize via the CSS variables in `globals.css`, not by modifying component internals directly unless necessary. Compose complex UI from shadcn primitives.
|
|
303
|
+
- **Tailwind conventions:** Use Tailwind utility classes directly in JSX. Avoid `@apply` except in `globals.css` for base styles. Use `cn()` utility (from shadcn) for conditional class merging. Follow mobile-first responsive design (`sm:`, `md:`, `lg:` breakpoints).
|
|
304
|
+
|
|
305
|
+
### Language Idioms
|
|
306
|
+
|
|
307
|
+
- **TypeScript strict mode:** `strict: true` in `tsconfig.json`. No `any` types except in genuinely dynamic contexts. Use `unknown` and narrow with type guards.
|
|
308
|
+
- **Import organization:** Group imports in order: (1) React/Next.js, (2) third-party libraries, (3) internal modules, (4) relative imports. Enforce with ESLint import ordering rules.
|
|
309
|
+
- **Path aliases:** Use `@/` alias (configured in `tsconfig.json`) for imports from the project root. Example: `import { Button } from "@/components/ui/button"`.
|
|
310
|
+
- **Async patterns:** Use `async/await` consistently. Avoid `.then()` chains. Handle errors with try/catch in Server Actions and Route Handlers.
|
|
311
|
+
|
|
312
|
+
### Stack-Specific Anti-Patterns
|
|
313
|
+
|
|
314
|
+
- **Do not use the Supabase service role key in Client Components or expose it via environment variables prefixed with `NEXT_PUBLIC_`.** This bypasses RLS and is a critical security vulnerability.
|
|
315
|
+
- **Do not disable RLS on tables**, even temporarily. Create permissive policies for development if needed, but never turn RLS off.
|
|
316
|
+
- **Do not use `useEffect` for data fetching** when a Server Component or Server Action can do the same work. This leads to client-side waterfalls and loading spinners.
|
|
317
|
+
- **Do not import server-only modules in Client Components.** Use the `server-only` package to enforce boundaries.
|
|
318
|
+
- **Do not store Supabase sessions in localStorage.** Use `@supabase/ssr` cookie-based session handling for secure, server-compatible auth.
|
|
319
|
+
- **Avoid excessive `"use client"` directives.** Push interactivity to leaf components and keep parent layouts as Server Components for better performance and smaller client bundles.
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
---
|
|
2
|
+
gspec-version: 1.8.0
|
|
3
|
+
description: Next.js App Router, TypeScript, Tailwind CSS, deployed on Vercel
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Technology Stack Definition
|
|
7
|
+
|
|
8
|
+
## 1. Overview
|
|
9
|
+
|
|
10
|
+
- **Architecture style**: Server-rendered monolith (Next.js App Router with SSR/SSG)
|
|
11
|
+
- **Deployment target**: Cloud — Vercel (edge/serverless rendering with built-in CDN)
|
|
12
|
+
- **Scale & performance**: Core content loads within 2s on typical mobile networks; lean bundles via dynamic imports and tree-shaking; responsive across desktop and mobile viewports
|
|
13
|
+
|
|
14
|
+
## 2. Open Questions & Clarifications
|
|
15
|
+
|
|
16
|
+
None — all critical technology decisions are resolved.
|
|
17
|
+
|
|
18
|
+
## 3. Core Technology Stack
|
|
19
|
+
|
|
20
|
+
### Programming Languages
|
|
21
|
+
|
|
22
|
+
- **Primary**: TypeScript 5.x (strict mode enabled)
|
|
23
|
+
- *Rationale*: Type safety, predictable refactors, first-class Next.js support
|
|
24
|
+
- **Secondary**: N/A
|
|
25
|
+
- **Tooling**: ESLint (TypeScript rules), Prettier (formatting)
|
|
26
|
+
|
|
27
|
+
### Runtime Environment
|
|
28
|
+
|
|
29
|
+
- **Runtime**: Node.js 20+ LTS
|
|
30
|
+
- *Rationale*: Required for Next.js; LTS ensures stability and long-term security patches
|
|
31
|
+
- **Container runtime**: Not required — Vercel manages the runtime environment
|
|
32
|
+
|
|
33
|
+
## 4. Frontend Stack
|
|
34
|
+
|
|
35
|
+
### Framework
|
|
36
|
+
|
|
37
|
+
- **Framework**: Next.js (latest LTS release, App Router)
|
|
38
|
+
- *Rationale*: Server-rendered defaults with hydration as needed; App Router provides layouts, server components, and streaming out of the box; first-class Vercel deployment support
|
|
39
|
+
- **Update strategy**: Track Next.js LTS releases; upgrade within 30 days of new LTS availability
|
|
40
|
+
|
|
41
|
+
### Build Tools
|
|
42
|
+
|
|
43
|
+
- **Bundler**: Next.js built-in (SWC-based compiler + Turbopack for development)
|
|
44
|
+
- *Rationale*: Zero-config, optimized for the Next.js ecosystem; SWC provides fast TypeScript transpilation
|
|
45
|
+
- **Build optimization**: Dynamic imports for code-splitting, tree-shaking via ES module imports, Next.js image optimization pipeline
|
|
46
|
+
|
|
47
|
+
### State Management
|
|
48
|
+
|
|
49
|
+
- **Approach**: Server-first — lean on server components and server-rendered data; client-side state kept minimal
|
|
50
|
+
- **Libraries**: React built-in hooks (`useState`, `useReducer`, `useContext`) for local/client state
|
|
51
|
+
- *Rationale*: No global state library needed for a content-driven frontend; avoids unnecessary bundle weight
|
|
52
|
+
- **Data fetching**: Next.js `fetch` with caching directives in server components; SWR or server actions for any client-side data needs
|
|
53
|
+
|
|
54
|
+
### Styling Technology
|
|
55
|
+
|
|
56
|
+
- **Framework**: Tailwind CSS 4.x with design tokens for spacing, typography, colors, and elevation
|
|
57
|
+
- *Rationale*: Utility-first approach aligns with component-based architecture; shared configuration keeps styles cohesive; excellent tree-shaking for production
|
|
58
|
+
- **CSS-in-JS**: Not used — Tailwind utilities only; no raw CSS outside Tailwind conventions
|
|
59
|
+
- **Responsive design**: Tailwind responsive prefixes (`sm:`, `md:`, `lg:`, `xl:`) for mobile-first breakpoints
|
|
60
|
+
- **Note**: Icon library choices are defined in `gspec/style.md`. The stack defines the CSS framework and component library; the style defines the icon set.
|
|
61
|
+
|
|
62
|
+
## 5. Backend Stack
|
|
63
|
+
|
|
64
|
+
**Not Applicable** — this is a frontend-only / static site project deployed to Vercel. No database, API layer, or server-side auth is required.
|
|
65
|
+
|
|
66
|
+
### Database
|
|
67
|
+
|
|
68
|
+
N/A
|
|
69
|
+
|
|
70
|
+
### Caching Layer
|
|
71
|
+
|
|
72
|
+
N/A — Vercel edge caching and Next.js built-in caching handle content delivery.
|
|
73
|
+
|
|
74
|
+
### Message Queue / Event Bus
|
|
75
|
+
|
|
76
|
+
N/A
|
|
77
|
+
|
|
78
|
+
## 6. Infrastructure & DevOps
|
|
79
|
+
|
|
80
|
+
### Cloud Provider
|
|
81
|
+
|
|
82
|
+
- **Provider**: Vercel
|
|
83
|
+
- *Key services*: Edge network, serverless functions (if needed), image optimization, analytics
|
|
84
|
+
- *Rationale*: Purpose-built for Next.js; predictable builds, automatic edge caching, zero-config HTTPS
|
|
85
|
+
|
|
86
|
+
### Container Orchestration
|
|
87
|
+
|
|
88
|
+
N/A — Vercel manages scaling and deployment infrastructure automatically.
|
|
89
|
+
|
|
90
|
+
### CI/CD Pipeline
|
|
91
|
+
|
|
92
|
+
- **Platform:** GitLab CI
|
|
93
|
+
- *Rationale:* Aligns with existing team infrastructure and workflow.
|
|
94
|
+
- **Deployment trigger:** Merge to main branch after pipeline passes.
|
|
95
|
+
- **Deployment method:** Vercel Git integration for preview deployments on merge requests; production deploy on main branch merge.
|
|
96
|
+
- **Note:** Pipeline stages and structure (lint → typecheck → test → build → deploy) are defined in `gspec/practices.md`. This section defines the CI technology and deployment configuration.
|
|
97
|
+
|
|
98
|
+
### Infrastructure as Code
|
|
99
|
+
|
|
100
|
+
N/A — Vercel manages infrastructure. Project configuration lives in `next.config.ts` and `vercel.json` (if needed).
|
|
101
|
+
|
|
102
|
+
## 7. Data & Storage
|
|
103
|
+
|
|
104
|
+
### File Storage
|
|
105
|
+
|
|
106
|
+
- **Static assets**: Served via Vercel's built-in CDN from the `public/` directory
|
|
107
|
+
- **Images**: Next.js `<Image />` component with automatic optimization (WebP/AVIF, responsive sizing)
|
|
108
|
+
- **Asset management**: Styled placeholders used during development; final assets swapped in before release
|
|
109
|
+
|
|
110
|
+
### Data Warehouse / Analytics
|
|
111
|
+
|
|
112
|
+
N/A
|
|
113
|
+
|
|
114
|
+
## 8. Authentication & Security
|
|
115
|
+
|
|
116
|
+
N/A — no authentication or authorization layer for this frontend-only project.
|
|
117
|
+
|
|
118
|
+
### Security Tools
|
|
119
|
+
|
|
120
|
+
- **Secrets management**: Environment variables via Vercel project settings (build-time and runtime)
|
|
121
|
+
- **Security scanning**: `pnpm audit` for dependency vulnerabilities; Dependabot or Renovate for automated dependency updates
|
|
122
|
+
- **Compliance**: HTTPS enforced by Vercel; no user data collection requiring GDPR/CCPA compliance at this stage
|
|
123
|
+
|
|
124
|
+
## 9. Monitoring & Observability
|
|
125
|
+
|
|
126
|
+
Minimal for initial launch — to be revisited as the project scales.
|
|
127
|
+
|
|
128
|
+
### Application Monitoring
|
|
129
|
+
|
|
130
|
+
Deferred — Vercel provides basic deployment and function metrics out of the box.
|
|
131
|
+
|
|
132
|
+
### Logging
|
|
133
|
+
|
|
134
|
+
Deferred — Vercel function logs available via dashboard for debugging.
|
|
135
|
+
|
|
136
|
+
### Tracing
|
|
137
|
+
|
|
138
|
+
N/A
|
|
139
|
+
|
|
140
|
+
### Error Tracking
|
|
141
|
+
|
|
142
|
+
Deferred — can add Sentry when needed. Next.js has built-in error boundaries for graceful UI failure handling.
|
|
143
|
+
|
|
144
|
+
## 10. Testing Infrastructure
|
|
145
|
+
|
|
146
|
+
### Testing Frameworks
|
|
147
|
+
|
|
148
|
+
- **Unit / Integration**: Vitest
|
|
149
|
+
- *Rationale*: Fast, ESM-native, excellent TypeScript support; compatible with React Testing Library
|
|
150
|
+
- **Component testing**: React Testing Library
|
|
151
|
+
- *Rationale*: Tests components as users interact with them; encourages accessible markup
|
|
152
|
+
- **E2E**: Cypress (headless in CI)
|
|
153
|
+
- *Rationale*: Mature ecosystem, reliable deterministic tests with `cy.intercept()` for stubbing
|
|
154
|
+
|
|
155
|
+
### Test Data Management
|
|
156
|
+
|
|
157
|
+
- **Fixtures**: JSON fixtures in `tests/fixtures/` for consistent test data
|
|
158
|
+
- **Mocks**: Vitest built-in mocking for modules; `cy.intercept()` for network stubbing in E2E
|
|
159
|
+
- **Test isolation**: Each test suite manages its own state; no shared mutable state between tests
|
|
160
|
+
|
|
161
|
+
### Performance Testing
|
|
162
|
+
|
|
163
|
+
Deferred — Core Web Vitals monitored via Lighthouse CI or Vercel Analytics when enabled.
|
|
164
|
+
|
|
165
|
+
## 11. Third-Party Integrations
|
|
166
|
+
|
|
167
|
+
### External Services
|
|
168
|
+
|
|
169
|
+
- **Formspree** — Client-side form submission service for contact forms and visitor inquiries. Accepts POST requests directly from the browser — no server-side endpoint or backend code required.
|
|
170
|
+
- *Rationale*: This is a frontend-only project with no backend logic. Formspree provides form handling without requiring server actions or API routes, keeping the architecture static.
|
|
171
|
+
- Free tier supports up to 50 submissions per month.
|
|
172
|
+
- Submissions are forwarded to a configured email address.
|
|
173
|
+
|
|
174
|
+
### API Clients
|
|
175
|
+
|
|
176
|
+
- **HTTP client**: Native `fetch` API for Formspree form submissions. No SDK dependency needed — Formspree accepts standard `FormData` POST requests.
|
|
177
|
+
|
|
178
|
+
## 12. Development Tools
|
|
179
|
+
|
|
180
|
+
### Package Management
|
|
181
|
+
|
|
182
|
+
- **Package manager**: pnpm (latest stable)
|
|
183
|
+
- *Rationale*: Fast installs, strict dependency resolution prevents phantom dependencies, disk-efficient via content-addressable storage
|
|
184
|
+
- **Dependency management**: `pnpm-lock.yaml` committed to version control; `pnpm audit` run in CI
|
|
185
|
+
- **Private registry**: N/A
|
|
186
|
+
|
|
187
|
+
### Code Quality Tools
|
|
188
|
+
|
|
189
|
+
- **Linter**: ESLint with `eslint-config-next` and TypeScript rules
|
|
190
|
+
- **Formatter**: Prettier (configured to align with ESLint)
|
|
191
|
+
- **Pre-commit hooks**: Husky + lint-staged for running ESLint and Prettier on staged files
|
|
192
|
+
- **Type checking**: `tsc --noEmit` in CI pipeline
|
|
193
|
+
|
|
194
|
+
### Local Development
|
|
195
|
+
|
|
196
|
+
- **Project starter**: `create-next-app` (official Next.js scaffolding tool via `pnpm create next-app`)
|
|
197
|
+
- *Rationale*: Provides a well-structured starting point with recommended defaults, TypeScript config, and App Router setup
|
|
198
|
+
- **Setup**: `pnpm install` → `pnpm dev` (Next.js dev server with Turbopack)
|
|
199
|
+
- **Hot reload**: Built-in via Next.js Fast Refresh
|
|
200
|
+
- **Environment**: `.env.local` for local environment variables (gitignored)
|
|
201
|
+
|
|
202
|
+
## 13. Migration & Compatibility
|
|
203
|
+
|
|
204
|
+
### Legacy System Integration
|
|
205
|
+
|
|
206
|
+
N/A — greenfield project.
|
|
207
|
+
|
|
208
|
+
### Upgrade Path
|
|
209
|
+
|
|
210
|
+
- **Next.js**: Track LTS releases; review changelogs and run codemods when upgrading major versions
|
|
211
|
+
- **Tailwind CSS**: Follow major version migration guides; design tokens minimize breaking changes
|
|
212
|
+
- **Dependencies**: Automated update PRs via Renovate or Dependabot; reviewed weekly
|
|
213
|
+
|
|
214
|
+
## 14. Technology Decisions & Tradeoffs
|
|
215
|
+
|
|
216
|
+
### Key Architectural Decisions
|
|
217
|
+
|
|
218
|
+
| Decision | Choice | Alternatives Considered | Rationale |
|
|
219
|
+
|---|---|---|---|
|
|
220
|
+
| Framework | Next.js (App Router) | Remix, Astro, Nuxt | Best Vercel integration; mature SSR/SSG; React ecosystem |
|
|
221
|
+
| Styling | Tailwind CSS | CSS Modules, Styled Components | Utility-first aligns with component architecture; zero runtime cost; design token support |
|
|
222
|
+
| Testing | Vitest + Cypress | Jest + Playwright | Vitest is faster and ESM-native; Cypress is mature for E2E with reliable stubbing |
|
|
223
|
+
| Package manager | pnpm | npm, yarn | Strict resolution prevents phantom deps; faster installs; disk-efficient |
|
|
224
|
+
| Deployment | Vercel | Netlify, AWS Amplify, Cloudflare Pages | Purpose-built for Next.js; edge caching; zero-config previews |
|
|
225
|
+
| CI/CD | GitLab CI | GitHub Actions | Aligns with existing team infrastructure and workflow |
|
|
226
|
+
|
|
227
|
+
### Risk Mitigation
|
|
228
|
+
|
|
229
|
+
| Risk | Mitigation | Fallback |
|
|
230
|
+
|---|---|---|
|
|
231
|
+
| Next.js breaking changes on major upgrade | Pin to LTS; test upgrades in preview branch | Delay upgrade; apply security patches only |
|
|
232
|
+
| Vercel vendor lock-in | Keep Next.js config portable; avoid Vercel-only APIs where possible | Self-host via `next start` on any Node.js platform |
|
|
233
|
+
| Tailwind major version migration | Use design tokens abstraction layer; follow official migration guides | Gradual migration with compatibility layer |
|
|
234
|
+
|
|
235
|
+
## 15. Technology-Specific Practices
|
|
236
|
+
|
|
237
|
+
### Framework Conventions & Patterns
|
|
238
|
+
|
|
239
|
+
- **App Router structure:** Use the `app/` directory with route groups for logical organization (e.g., `(marketing)` for public pages). Keep layouts in `app/layout.tsx` and page-level layouts in route group folders.
|
|
240
|
+
- **Server vs Client Components:** Default to Server Components. Add `"use client"` only when the component needs browser APIs, event handlers, or React hooks (`useState`, `useEffect`). Push interactivity to leaf components.
|
|
241
|
+
- **Static generation:** Prefer static rendering (SSG) for content pages. Use `generateStaticParams()` for dynamic routes if applicable.
|
|
242
|
+
- **Loading and error states:** Use `loading.tsx` and `error.tsx` files at appropriate route levels for streaming UI and error boundaries.
|
|
243
|
+
- **Metadata:** Export `metadata` or `generateMetadata` from every page for SEO (title, description, Open Graph).
|
|
244
|
+
|
|
245
|
+
### Library Usage Patterns
|
|
246
|
+
|
|
247
|
+
- **Tailwind conventions:** Use Tailwind utility classes directly in JSX. Avoid `@apply` except in global styles for base resets. Use `cn()` or `clsx()` for conditional class merging. Follow mobile-first responsive design (`sm:`, `md:`, `lg:` breakpoints).
|
|
248
|
+
- **Design token mapping:** Map design tokens from `gspec/style.md` to Tailwind's theme configuration in `tailwind.config.ts` under `theme.extend`. Use CSS custom properties in `app/globals.css` for runtime theme switching (light/dark mode).
|
|
249
|
+
- **Image optimization:** Use Next.js `<Image />` component for all images. Set `priority` on above-the-fold hero images.
|
|
250
|
+
|
|
251
|
+
### Language Idioms
|
|
252
|
+
|
|
253
|
+
- **TypeScript strict mode:** `strict: true` in `tsconfig.json`. No `any` types — use `unknown` and narrow with type guards.
|
|
254
|
+
- **Path aliases:** Use `@/` alias (configured in `tsconfig.json`) for imports from the project root. Example: `import { Button } from "@/components/ui/button"`.
|
|
255
|
+
- **Import organization:** Group imports: (1) React/Next.js, (2) third-party libraries, (3) internal modules, (4) relative imports.
|
|
256
|
+
- **Async patterns:** Use `async/await` consistently. Avoid `.then()` chains.
|
|
257
|
+
|
|
258
|
+
### Stack-Specific Anti-Patterns
|
|
259
|
+
|
|
260
|
+
- **Don't use `useEffect` for data fetching** when a Server Component can do the same work — causes client-side waterfalls.
|
|
261
|
+
- **Don't add `"use client"` to layout files** unless absolutely necessary — this forces all children to be client components.
|
|
262
|
+
- **Don't import server-only modules in Client Components.** Use the `server-only` package to enforce boundaries.
|
|
263
|
+
- **Don't install a CSS-in-JS library** alongside Tailwind — pick one styling approach.
|
|
264
|
+
- **Don't use inline styles** for values that should be design tokens — map them through Tailwind configuration.
|