create-baton 1.0.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/README.md +58 -0
- package/bin/create-baton.js +9 -0
- package/package.json +36 -0
- package/src/constants.js +30 -0
- package/src/index.js +35 -0
- package/src/prompts.js +54 -0
- package/src/scaffold.js +193 -0
- package/templates/BATON_v3.1.md +849 -0
- package/templates/ide/CLAUDE.md.template +105 -0
- package/templates/ide/cursorrules.template +64 -0
- package/templates/skills/core/anti-overengineering/SKILL.md +180 -0
- package/templates/skills/core/cost-awareness/SKILL.md +207 -0
- package/templates/skills/core/launch-prep/SKILL.md +232 -0
- package/templates/skills/core/milestones/SKILL.md +167 -0
- package/templates/skills/core/production-readiness/SKILL.md +307 -0
- package/templates/skills/core/security/SKILL.md +309 -0
- package/templates/skills/core/testing/SKILL.md +307 -0
- package/templates/skills/core/ui-ux/SKILL.md +155 -0
- package/templates/skills/patterns/api-integration/SKILL.md +143 -0
- package/templates/skills/stacks/nextjs/SKILL.md +230 -0
- package/templates/skills/stacks/supabase/SKILL.md +402 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ui-ux
|
|
3
|
+
description: >-
|
|
4
|
+
UI/UX design defaults and polish standards for AI-generated interfaces.
|
|
5
|
+
Covers layout, typography, color, responsive rules, component libraries,
|
|
6
|
+
and accessibility basics. Use when building UI, reviewing design quality,
|
|
7
|
+
or when screens look unpolished.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# UI/UX Skill — Look Good Out of the Gate
|
|
11
|
+
|
|
12
|
+
> Every screen should look polished on first build. No "we'll fix the UI later."
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## The Problem
|
|
17
|
+
|
|
18
|
+
AI-generated UIs are functional but ugly. Common issues:
|
|
19
|
+
- Inconsistent spacing and sizing
|
|
20
|
+
- No visual hierarchy — everything looks the same importance
|
|
21
|
+
- Missing loading, empty, and error states
|
|
22
|
+
- Looks broken on mobile
|
|
23
|
+
- No feedback when users click things
|
|
24
|
+
|
|
25
|
+
**If it looks bad, users don't trust it — even if it works perfectly.**
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Design Defaults (Use Unless Told Otherwise)
|
|
30
|
+
|
|
31
|
+
### Layout
|
|
32
|
+
- **Mobile-first** — design for phone, scale up to desktop
|
|
33
|
+
- **Max content width:** 1200px centered, with side padding
|
|
34
|
+
- **Consistent spacing:** pick a scale (4, 8, 12, 16, 24, 32, 48, 64px) and stick to it
|
|
35
|
+
- **White space is good** — when in doubt, add more breathing room
|
|
36
|
+
|
|
37
|
+
### Typography
|
|
38
|
+
- **One font family** — system font stack or one Google Font, never more
|
|
39
|
+
- **3 sizes max** for body text: small (14px), normal (16px), large (18px)
|
|
40
|
+
- **Headings:** clear size steps (h1: 36px, h2: 28px, h3: 22px)
|
|
41
|
+
- **Line height:** 1.5 for body, 1.2 for headings
|
|
42
|
+
- **Max line width:** 65-75 characters for readability
|
|
43
|
+
|
|
44
|
+
### Color
|
|
45
|
+
- **2-3 colors max** — primary, neutral, one accent
|
|
46
|
+
- **Use opacity/shades** of your primary instead of adding more colors
|
|
47
|
+
- **Text contrast:** minimum 4.5:1 ratio (WCAG AA)
|
|
48
|
+
- **Don't convey meaning with color alone** — add icons or labels too
|
|
49
|
+
|
|
50
|
+
### Components
|
|
51
|
+
- **Use a component library** — shadcn/ui (recommended), Radix, or Headless UI
|
|
52
|
+
- **Don't build custom components** when a library has them
|
|
53
|
+
- **Consistent border radius** — pick one (6px or 8px) and use everywhere
|
|
54
|
+
- **Consistent shadows** — one subtle shadow for elevation, not five different ones
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Every Screen Must Have
|
|
59
|
+
|
|
60
|
+
### 1. Loading State
|
|
61
|
+
```
|
|
62
|
+
Show skeleton or spinner while data loads.
|
|
63
|
+
Never show a blank screen or flash of unstyled content.
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 2. Empty State
|
|
67
|
+
```
|
|
68
|
+
When there's no data, show:
|
|
69
|
+
- A clear message explaining what goes here
|
|
70
|
+
- A call to action (button to create first item)
|
|
71
|
+
Never show an empty table or blank page.
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 3. Error State
|
|
75
|
+
```
|
|
76
|
+
When something fails, show:
|
|
77
|
+
- What went wrong (in human language, not error codes)
|
|
78
|
+
- What to do about it (retry button, contact support, etc.)
|
|
79
|
+
Never show a raw error message or silent failure.
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 4. Success Feedback
|
|
83
|
+
```
|
|
84
|
+
When an action succeeds:
|
|
85
|
+
- Toast notification, or
|
|
86
|
+
- Inline confirmation, or
|
|
87
|
+
- Redirect with success message
|
|
88
|
+
Never let the user wonder "did that work?"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Responsive Rules
|
|
94
|
+
|
|
95
|
+
| Breakpoint | Width | Layout |
|
|
96
|
+
|-----------|-------|--------|
|
|
97
|
+
| Mobile | < 640px | Single column, stacked |
|
|
98
|
+
| Tablet | 640-1024px | Adjusted spacing, may show sidebar |
|
|
99
|
+
| Desktop | > 1024px | Full layout |
|
|
100
|
+
|
|
101
|
+
**Test every screen at 375px width (iPhone SE).** If it breaks there, fix it.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Quick Wins That Make Everything Look Better
|
|
106
|
+
|
|
107
|
+
1. **Add padding to containers** — 16px mobile, 24px+ desktop
|
|
108
|
+
2. **Align everything to a grid** — no random positioning
|
|
109
|
+
3. **Use subtle borders or backgrounds** to separate sections, not heavy lines
|
|
110
|
+
4. **Make buttons look clickable** — clear hover/active states
|
|
111
|
+
5. **Size touch targets 44px minimum** — fingers are bigger than cursors
|
|
112
|
+
6. **Add transitions** — 150ms ease on hover states, nothing flashy
|
|
113
|
+
7. **Consistent icon style** — all outline OR all filled, never mixed (use Lucide)
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Don'ts
|
|
118
|
+
|
|
119
|
+
| Don't | Do Instead |
|
|
120
|
+
|-------|-----------|
|
|
121
|
+
| Rainbow of colors | 2-3 color palette |
|
|
122
|
+
| Five font sizes on one page | Consistent type scale |
|
|
123
|
+
| Custom scrollbars, animations | Subtle, standard interactions |
|
|
124
|
+
| Auto-playing anything | User-initiated actions |
|
|
125
|
+
| Walls of text | Short copy, clear hierarchy |
|
|
126
|
+
| Pixel-perfect custom everything | Component library + small tweaks |
|
|
127
|
+
| Different button styles everywhere | One primary, one secondary, one ghost |
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Accessibility Basics (Non-Negotiable)
|
|
132
|
+
|
|
133
|
+
- All images have `alt` text
|
|
134
|
+
- All form inputs have labels (not just placeholders)
|
|
135
|
+
- Keyboard navigation works (Tab through the page)
|
|
136
|
+
- Focus states are visible (don't remove outline without replacing)
|
|
137
|
+
- Color is not the only indicator (add icons/text to status)
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## When User Doesn't Specify Design
|
|
142
|
+
|
|
143
|
+
Default to:
|
|
144
|
+
1. **Clean and minimal** — white/light gray background, dark text
|
|
145
|
+
2. **shadcn/ui components** (if using React/Next.js)
|
|
146
|
+
3. **Lucide icons** (consistent, clean)
|
|
147
|
+
4. **Inter or system font**
|
|
148
|
+
5. **Rounded corners (8px), subtle shadows**
|
|
149
|
+
6. **Blue primary color** (#2563EB or similar)
|
|
150
|
+
|
|
151
|
+
This gives a professional baseline. User can customize later.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
*Last updated: Baton Protocol v3.1*
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: api-integration
|
|
3
|
+
description: >-
|
|
4
|
+
External API integration patterns. Covers retry logic, error handling,
|
|
5
|
+
AI/LLM API specifics, rate limiting, and environment variable management.
|
|
6
|
+
Use when integrating external APIs, calling AI model APIs, or when
|
|
7
|
+
dealing with API failures and rate limits.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# API Integration Skill
|
|
11
|
+
|
|
12
|
+
> External APIs fail. Plan for it from line one.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Before Writing Any API Code
|
|
17
|
+
|
|
18
|
+
1. **Read the official documentation** — don't guess endpoints, auth methods, or model names
|
|
19
|
+
2. **Check for SDKs** — official client libraries are always better than raw HTTP calls
|
|
20
|
+
3. **Note rate limits** — know your ceiling before you hit it
|
|
21
|
+
4. **Check pricing** — free tiers have limits, know what they are
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Retry Logic (Implement From the Start)
|
|
26
|
+
|
|
27
|
+
Every external API call must have retry logic. Don't add it later when things break.
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
Minimum: 3 retry attempts
|
|
31
|
+
Strategy: Exponential backoff (1s, 2s, 4s)
|
|
32
|
+
Retry on: 429 (rate limit), 500, 502, 503, 504
|
|
33
|
+
Don't retry: 400 (bad request), 401 (auth), 403 (forbidden), 404
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Pattern
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
try call → if transient error → wait → retry → if still failing → graceful error to user
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Always log which attempt succeeded. If retries are frequent, something is wrong.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## AI/LLM API Specifics
|
|
47
|
+
|
|
48
|
+
When calling AI model APIs (Gemini, OpenAI, Anthropic, etc.):
|
|
49
|
+
|
|
50
|
+
### Token Limits
|
|
51
|
+
- Set `max_tokens` higher than you think you need
|
|
52
|
+
- Shorter prompts = more room for output
|
|
53
|
+
- If responses feel cut off, you're hitting the limit
|
|
54
|
+
|
|
55
|
+
### Check Finish Reasons
|
|
56
|
+
```
|
|
57
|
+
"stop" → completed normally ✓
|
|
58
|
+
"length" → truncated — increase max_tokens
|
|
59
|
+
"safety" → content filtered — adjust prompt
|
|
60
|
+
"error" → something broke — retry
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**Always check the finish reason.** Truncated responses without checking = silent bugs.
|
|
64
|
+
|
|
65
|
+
### Prompt Efficiency
|
|
66
|
+
- Shorter, clearer prompts perform better AND cost less
|
|
67
|
+
- Put instructions first, data second
|
|
68
|
+
- Don't repeat yourself in prompts
|
|
69
|
+
- Use structured output (JSON mode) when parsing responses
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Error Handling
|
|
74
|
+
|
|
75
|
+
### What Users Should See
|
|
76
|
+
|
|
77
|
+
| Situation | Show User |
|
|
78
|
+
|-----------|----------|
|
|
79
|
+
| API timeout | "Taking longer than usual. Retrying..." |
|
|
80
|
+
| Rate limited | "Busy right now. Trying again in a moment..." |
|
|
81
|
+
| API down | "Service temporarily unavailable. Please try again." |
|
|
82
|
+
| Bad response | "Something went wrong. Please try again." |
|
|
83
|
+
| Auth failure | Nothing — this is a bug, log it, alert developer |
|
|
84
|
+
|
|
85
|
+
**Never show raw API errors to users.** No stack traces, no error codes, no JSON blobs.
|
|
86
|
+
|
|
87
|
+
### What Developers Should See
|
|
88
|
+
|
|
89
|
+
Log everything:
|
|
90
|
+
- Request timestamp
|
|
91
|
+
- Response status code
|
|
92
|
+
- Retry attempt number
|
|
93
|
+
- Finish reason (for AI APIs)
|
|
94
|
+
- Response time
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Environment Variables
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
API keys → environment variables, NEVER hardcoded
|
|
102
|
+
Model names → environment variables (models change, keys don't)
|
|
103
|
+
Base URLs → environment variables (staging vs production)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Pattern
|
|
107
|
+
```
|
|
108
|
+
GEMINI_API_KEY=xxx
|
|
109
|
+
GEMINI_MODEL=gemini-2.5-flash
|
|
110
|
+
OPENAI_API_KEY=xxx
|
|
111
|
+
OPENAI_MODEL=gpt-4o
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Make the model name configurable. New models drop constantly.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Rate Limiting Your Own Users
|
|
119
|
+
|
|
120
|
+
If your app calls an external API per user request:
|
|
121
|
+
- Add your own rate limiting (e.g., 10 requests/minute per user)
|
|
122
|
+
- Queue requests if needed
|
|
123
|
+
- Cache responses when possible (same input = same output)
|
|
124
|
+
- Show remaining quota to users if applicable
|
|
125
|
+
|
|
126
|
+
**Your free API tier is shared across ALL your users.** One heavy user can burn your quota.
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Checklist Before Shipping
|
|
131
|
+
|
|
132
|
+
- [ ] All API keys in environment variables
|
|
133
|
+
- [ ] Retry logic on every external call
|
|
134
|
+
- [ ] Graceful error messages for users
|
|
135
|
+
- [ ] Finish reason checked (AI APIs)
|
|
136
|
+
- [ ] Rate limiting on user-facing endpoints
|
|
137
|
+
- [ ] Timeouts set (don't wait forever)
|
|
138
|
+
- [ ] Logging on failures
|
|
139
|
+
- [ ] Tested with API returning errors (not just happy path)
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
*Last updated: Baton Protocol v3.1*
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nextjs
|
|
3
|
+
description: >-
|
|
4
|
+
Next.js App Router patterns and conventions for production applications.
|
|
5
|
+
Covers Server Components, Server Actions, route groups, loading/error
|
|
6
|
+
states, and common pitfalls. Use when working with Next.js 14+,
|
|
7
|
+
React Server Components, or App Router projects.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Next.js Skill File
|
|
11
|
+
|
|
12
|
+
> Proven patterns from production Next.js projects. Check here before searching the web.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Version Compatibility
|
|
17
|
+
|
|
18
|
+
This file covers Next.js 14-16 with App Router. Update version notes as needed.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Project Structure
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
src/
|
|
26
|
+
├── app/
|
|
27
|
+
│ ├── (auth)/ # Auth route group
|
|
28
|
+
│ ├── (dashboard)/ # Main app route group
|
|
29
|
+
│ ├── api/ # API routes
|
|
30
|
+
│ ├── layout.tsx # Root layout
|
|
31
|
+
│ └── page.tsx # Landing page
|
|
32
|
+
├── components/
|
|
33
|
+
│ ├── ui/ # shadcn/ui components
|
|
34
|
+
│ └── [feature]/ # Feature-specific components
|
|
35
|
+
├── lib/
|
|
36
|
+
│ ├── actions/ # Server actions
|
|
37
|
+
│ ├── db/ # Database utilities
|
|
38
|
+
│ └── utils.ts # Helper functions
|
|
39
|
+
└── types/
|
|
40
|
+
└── index.ts # Type definitions
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Key Patterns
|
|
46
|
+
|
|
47
|
+
### Server Components First
|
|
48
|
+
|
|
49
|
+
Default to Server Components. Only use `'use client'` when you need:
|
|
50
|
+
- useState, useEffect
|
|
51
|
+
- Event handlers (onClick, onChange)
|
|
52
|
+
- Browser APIs
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
// Server Component (default) - can fetch data directly
|
|
56
|
+
export default async function Page() {
|
|
57
|
+
const data = await getData()
|
|
58
|
+
return <div>{data}</div>
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Client Component - only when needed
|
|
62
|
+
'use client'
|
|
63
|
+
export function InteractiveButton() {
|
|
64
|
+
const [count, setCount] = useState(0)
|
|
65
|
+
return <button onClick={() => setCount(c => c + 1)}>{count}</button>
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Server Actions for Mutations
|
|
70
|
+
|
|
71
|
+
All data mutations go through Server Actions. Never mutate from client.
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
// lib/actions/items.ts
|
|
75
|
+
'use server'
|
|
76
|
+
|
|
77
|
+
import { revalidatePath } from 'next/cache'
|
|
78
|
+
import { z } from 'zod'
|
|
79
|
+
|
|
80
|
+
const schema = z.object({
|
|
81
|
+
name: z.string().min(1),
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
export async function createItem(formData: FormData) {
|
|
85
|
+
const parsed = schema.safeParse({
|
|
86
|
+
name: formData.get('name'),
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
if (!parsed.success) {
|
|
90
|
+
return { success: false, error: 'Invalid input' }
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Database operation here
|
|
94
|
+
|
|
95
|
+
revalidatePath('/items')
|
|
96
|
+
return { success: true }
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Route Groups for Layout Control
|
|
101
|
+
|
|
102
|
+
Use `(groupName)` folders to share layouts without affecting URLs.
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
app/
|
|
106
|
+
├── (marketing)/ # Marketing layout
|
|
107
|
+
│ ├── layout.tsx
|
|
108
|
+
│ ├── page.tsx # → /
|
|
109
|
+
│ └── pricing/page.tsx # → /pricing
|
|
110
|
+
└── (dashboard)/ # Dashboard layout
|
|
111
|
+
├── layout.tsx
|
|
112
|
+
└── dashboard/page.tsx # → /dashboard
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Loading and Error States
|
|
116
|
+
|
|
117
|
+
Every route group should have loading and error handling.
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
app/
|
|
121
|
+
└── dashboard/
|
|
122
|
+
├── page.tsx
|
|
123
|
+
├── loading.tsx # Shows while page loads
|
|
124
|
+
└── error.tsx # Shows on error (must be 'use client')
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Common Commands
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
# Development
|
|
133
|
+
npm run dev
|
|
134
|
+
|
|
135
|
+
# Build (always run before deploying)
|
|
136
|
+
npm run build
|
|
137
|
+
|
|
138
|
+
# Type check
|
|
139
|
+
npx tsc --noEmit
|
|
140
|
+
|
|
141
|
+
# Lint
|
|
142
|
+
npm run lint
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Pitfalls to Avoid
|
|
148
|
+
|
|
149
|
+
### 1. Importing Server-Only Code in Client Components
|
|
150
|
+
|
|
151
|
+
```tsx
|
|
152
|
+
// BAD - will break
|
|
153
|
+
'use client'
|
|
154
|
+
import { db } from '@/lib/db' // Server-only!
|
|
155
|
+
|
|
156
|
+
// GOOD - use Server Actions
|
|
157
|
+
'use client'
|
|
158
|
+
import { getData } from '@/lib/actions/data'
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### 2. Not Using revalidatePath After Mutations
|
|
162
|
+
|
|
163
|
+
```tsx
|
|
164
|
+
// BAD - UI won't update
|
|
165
|
+
export async function createItem() {
|
|
166
|
+
await db.insert(...)
|
|
167
|
+
return { success: true }
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// GOOD - UI updates
|
|
171
|
+
export async function createItem() {
|
|
172
|
+
await db.insert(...)
|
|
173
|
+
revalidatePath('/items')
|
|
174
|
+
return { success: true }
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### 3. Using useEffect for Data Fetching
|
|
179
|
+
|
|
180
|
+
```tsx
|
|
181
|
+
// BAD - unnecessary client-side fetch
|
|
182
|
+
'use client'
|
|
183
|
+
export function Items() {
|
|
184
|
+
const [items, setItems] = useState([])
|
|
185
|
+
useEffect(() => {
|
|
186
|
+
fetch('/api/items').then(...)
|
|
187
|
+
}, [])
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// GOOD - fetch in Server Component
|
|
191
|
+
export default async function Items() {
|
|
192
|
+
const items = await getItems()
|
|
193
|
+
return <ItemsList items={items} />
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### 4. Forgetting 'use client' for Interactive Components
|
|
198
|
+
|
|
199
|
+
If you use useState, useEffect, onClick, onChange — you need 'use client'.
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Recommended Libraries
|
|
204
|
+
|
|
205
|
+
| Need | Library | Why |
|
|
206
|
+
|------|---------|-----|
|
|
207
|
+
| UI Components | shadcn/ui | Customizable, accessible, copy-paste |
|
|
208
|
+
| Forms | react-hook-form + zod | Type-safe validation |
|
|
209
|
+
| Styling | Tailwind CSS | Utility-first, fast |
|
|
210
|
+
| Icons | Lucide React | Clean, consistent |
|
|
211
|
+
| Date handling | date-fns | Lightweight, tree-shakeable |
|
|
212
|
+
| Animation | Framer Motion | Powerful, declarative |
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Environment Variables
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
# .env.local (never commit)
|
|
220
|
+
DATABASE_URL=
|
|
221
|
+
NEXT_PUBLIC_SUPABASE_URL= # NEXT_PUBLIC_ = exposed to client
|
|
222
|
+
NEXT_PUBLIC_SUPABASE_ANON_KEY=
|
|
223
|
+
SUPABASE_SERVICE_ROLE_KEY= # No prefix = server-only
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
**Rule:** Never put sensitive keys in NEXT_PUBLIC_ variables.
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
*Last updated: Baton Protocol v3.1*
|