create-baton 1.0.0 → 1.1.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.
@@ -0,0 +1,241 @@
1
+ ---
2
+ name: typescript
3
+ description: >-
4
+ TypeScript patterns — type safety without over-engineering, practical typing
5
+ strategies, common patterns, and when to use strict vs pragmatic approaches.
6
+ Load at Session 0-1 when using TypeScript. Use when discussing types or
7
+ fixing type errors.
8
+ ---
9
+
10
+ # TypeScript Skill
11
+
12
+ > Types prevent bugs. Over-typing prevents progress. Find the balance.
13
+
14
+ ---
15
+
16
+ ## Pragmatic TypeScript Rules
17
+
18
+ ### Type What Matters
19
+
20
+ ```typescript
21
+ // DO type: function signatures, API responses, props
22
+ function createUser(data: CreateUserInput): Promise<User> { ... }
23
+
24
+ // DON'T over-type: obvious local variables
25
+ const count = items.length; // TypeScript infers `number`
26
+ const name = 'hello'; // TypeScript infers `string`
27
+ ```
28
+
29
+ ### When to Use `any` (Seriously)
30
+
31
+ ```typescript
32
+ // Temporary during prototyping — add a TODO
33
+ const data: any = await weirdApi.call(); // TODO: type this
34
+
35
+ // Third-party library without types
36
+ declare module 'untyped-lib' {
37
+ const lib: any;
38
+ export default lib;
39
+ }
40
+ ```
41
+
42
+ **Rule:** `any` is a tool, not a sin. Use it sparingly, mark it with TODO, fix later.
43
+
44
+ ### Prefer `unknown` Over `any` for Safety
45
+
46
+ ```typescript
47
+ // BAD — any lets you do anything without checking
48
+ function process(data: any) {
49
+ data.whatever(); // No error, crashes at runtime
50
+ }
51
+
52
+ // GOOD — unknown forces you to check first
53
+ function process(data: unknown) {
54
+ if (typeof data === 'string') {
55
+ data.toUpperCase(); // Safe
56
+ }
57
+ }
58
+ ```
59
+
60
+ ---
61
+
62
+ ## Essential Patterns
63
+
64
+ ### API Response Types
65
+
66
+ ```typescript
67
+ // Define once, use everywhere
68
+ interface User {
69
+ id: string;
70
+ email: string;
71
+ name: string;
72
+ createdAt: string;
73
+ }
74
+
75
+ // For create/update, make fields optional
76
+ type CreateUserInput = Pick<User, 'email' | 'name'>;
77
+ type UpdateUserInput = Partial<Pick<User, 'name'>>;
78
+ ```
79
+
80
+ ### Component Props
81
+
82
+ ```typescript
83
+ // Simple props
84
+ interface ButtonProps {
85
+ label: string;
86
+ onClick: () => void;
87
+ variant?: 'primary' | 'secondary';
88
+ disabled?: boolean;
89
+ }
90
+
91
+ // Props that extend HTML elements
92
+ interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
93
+ label: string;
94
+ error?: string;
95
+ }
96
+ ```
97
+
98
+ ### Server Action Return Types
99
+
100
+ ```typescript
101
+ // Consistent return type for all server actions
102
+ type ActionResult<T = void> =
103
+ | { success: true; data: T }
104
+ | { success: false; error: string };
105
+
106
+ // Usage
107
+ export async function createItem(input: CreateItemInput): Promise<ActionResult<Item>> {
108
+ try {
109
+ const item = await db.insert(items).values(input).returning();
110
+ return { success: true, data: item };
111
+ } catch {
112
+ return { success: false, error: 'Failed to create item' };
113
+ }
114
+ }
115
+ ```
116
+
117
+ ---
118
+
119
+ ## Zod for Runtime Validation
120
+
121
+ Types only exist at compile time. Use Zod for runtime:
122
+
123
+ ```typescript
124
+ import { z } from 'zod';
125
+
126
+ // Define schema (runtime validation)
127
+ const createItemSchema = z.object({
128
+ name: z.string().min(1).max(255),
129
+ price: z.number().positive(),
130
+ category: z.enum(['electronics', 'clothing', 'food']),
131
+ });
132
+
133
+ // Infer TypeScript type from schema (compile-time type)
134
+ type CreateItemInput = z.infer<typeof createItemSchema>;
135
+
136
+ // Validate at runtime
137
+ const parsed = createItemSchema.safeParse(userInput);
138
+ if (!parsed.success) {
139
+ // Handle validation error
140
+ }
141
+ ```
142
+
143
+ **Rule:** Use Zod at system boundaries (API routes, server actions, form submissions). Don't validate internal function calls.
144
+
145
+ ---
146
+
147
+ ## Common Type Utilities
148
+
149
+ ```typescript
150
+ // Make some fields required
151
+ type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };
152
+
153
+ // Database row type (from Supabase or Prisma)
154
+ type Item = Database['public']['Tables']['items']['Row'];
155
+
156
+ // Omit fields you don't want to expose
157
+ type PublicUser = Omit<User, 'passwordHash' | 'internalNotes'>;
158
+
159
+ // Record for key-value maps
160
+ const featureFlags: Record<string, boolean> = {
161
+ darkMode: true,
162
+ betaFeatures: false,
163
+ };
164
+ ```
165
+
166
+ ---
167
+
168
+ ## tsconfig Best Practices
169
+
170
+ ```json
171
+ {
172
+ "compilerOptions": {
173
+ "strict": true,
174
+ "noUncheckedIndexedAccess": true,
175
+ "forceConsistentCasingInFileNames": true,
176
+ "skipLibCheck": true
177
+ }
178
+ }
179
+ ```
180
+
181
+ - **strict: true** — enables all strict checks (do this from day 1)
182
+ - **noUncheckedIndexedAccess** — catches `array[0]` potentially being undefined
183
+ - **skipLibCheck** — faster compilation, skip checking node_modules types
184
+
185
+ ---
186
+
187
+ ## Fixing Common Type Errors
188
+
189
+ ### "Type X is not assignable to type Y"
190
+
191
+ Usually means you're passing the wrong shape. Check:
192
+ 1. Are you passing all required fields?
193
+ 2. Are field names spelled correctly?
194
+ 3. Is the data coming from an untyped source (API, form)?
195
+
196
+ ### "Object is possibly undefined"
197
+
198
+ ```typescript
199
+ // BAD
200
+ const name = user.name; // Error if user might be null
201
+
202
+ // GOOD — optional chaining
203
+ const name = user?.name;
204
+
205
+ // GOOD — early return
206
+ if (!user) return null;
207
+ const name = user.name; // TypeScript knows user exists here
208
+ ```
209
+
210
+ ### "Property does not exist on type"
211
+
212
+ ```typescript
213
+ // Usually from untyped API responses
214
+ const data = await fetch('/api').then(r => r.json());
215
+ // TypeScript doesn't know what `data` is
216
+
217
+ // Fix: type the response
218
+ const data: ApiResponse = await fetch('/api').then(r => r.json());
219
+ ```
220
+
221
+ ---
222
+
223
+ ## Don'ts
224
+
225
+ | Don't | Do Instead |
226
+ |-------|-----------|
227
+ | Type every variable | Let TypeScript infer obvious types |
228
+ | Create types for one-time objects | Inline the type or use `typeof` |
229
+ | Use `as` to silence errors | Fix the actual type mismatch |
230
+ | Create separate type files for everything | Co-locate types with the code that uses them |
231
+ | Use `enum` | Use `as const` objects or union types |
232
+
233
+ ```typescript
234
+ // Instead of enum
235
+ const Status = { ACTIVE: 'active', ARCHIVED: 'archived' } as const;
236
+ type Status = typeof Status[keyof typeof Status]; // 'active' | 'archived'
237
+ ```
238
+
239
+ ---
240
+
241
+ *Last updated: Baton Protocol v3.1*
@@ -0,0 +1,232 @@
1
+ ---
2
+ name: vercel
3
+ description: >-
4
+ Vercel deployment patterns — project setup, environment variables, domains,
5
+ preview deployments, and edge functions. Load at Session 3+ when deploying
6
+ to Vercel. Use when setting up deployment or troubleshooting builds.
7
+ ---
8
+
9
+ # Vercel Skill
10
+
11
+ > Deploy first, polish later. A live URL changes everything.
12
+
13
+ ---
14
+
15
+ ## First Deployment (Session 3)
16
+
17
+ ### Connect Repository
18
+
19
+ 1. Go to vercel.com → New Project
20
+ 2. Import your GitHub repo
21
+ 3. Vercel auto-detects Next.js (or other frameworks)
22
+ 4. Click Deploy
23
+
24
+ That's it. Every push to `main` auto-deploys.
25
+
26
+ ### Or Use CLI
27
+
28
+ ```bash
29
+ npm i -g vercel
30
+ vercel # Deploy preview
31
+ vercel --prod # Deploy to production
32
+ ```
33
+
34
+ ---
35
+
36
+ ## Environment Variables
37
+
38
+ ### Setting Them
39
+
40
+ ```
41
+ Vercel Dashboard → Project → Settings → Environment Variables
42
+ ```
43
+
44
+ ### Environment Scoping
45
+
46
+ | Scope | When Applied |
47
+ |-------|-------------|
48
+ | Production | `vercel.com` (main branch) |
49
+ | Preview | PR deployments, branches |
50
+ | Development | `vercel dev` locally |
51
+
52
+ **Rule:** Always set variables for all three environments. Missing preview env vars = broken PR previews.
53
+
54
+ ### Naming
55
+
56
+ ```
57
+ DATABASE_URL=... # Server only
58
+ STRIPE_SECRET_KEY=... # Server only
59
+ NEXT_PUBLIC_APP_URL=... # Client + server (public)
60
+ NEXT_PUBLIC_SUPABASE_URL=... # Client + server (public)
61
+ ```
62
+
63
+ **`NEXT_PUBLIC_` prefix = exposed to browser.** Never put secrets in `NEXT_PUBLIC_` variables.
64
+
65
+ ---
66
+
67
+ ## Custom Domain
68
+
69
+ ### Setup
70
+
71
+ ```
72
+ Vercel Dashboard → Project → Settings → Domains → Add
73
+ ```
74
+
75
+ ### DNS Configuration
76
+
77
+ | Type | Name | Value |
78
+ |------|------|-------|
79
+ | A | @ | 76.76.21.21 |
80
+ | CNAME | www | cname.vercel-dns.com |
81
+
82
+ ### SSL
83
+
84
+ Automatic. Vercel provisions Let's Encrypt certificates. Nothing to configure.
85
+
86
+ ---
87
+
88
+ ## Preview Deployments
89
+
90
+ Every PR gets its own URL: `project-git-branch-name-username.vercel.app`
91
+
92
+ ### Uses
93
+
94
+ - Test features before merging
95
+ - Share with teammates for review
96
+ - QA on a real URL
97
+ - Test with preview environment variables
98
+
99
+ ### Preview Comments
100
+
101
+ Enable in project settings. Team members can comment directly on preview deployments.
102
+
103
+ ---
104
+
105
+ ## Build Configuration
106
+
107
+ ### Next.js Defaults (Usually No Config Needed)
108
+
109
+ Vercel auto-detects:
110
+ - Build command: `next build`
111
+ - Output directory: `.next`
112
+ - Install command: `npm install`
113
+
114
+ ### Custom Build Settings
115
+
116
+ Only change if needed:
117
+
118
+ ```
119
+ Vercel Dashboard → Project → Settings → General → Build & Development Settings
120
+ ```
121
+
122
+ ### Build Troubleshooting
123
+
124
+ | Problem | Fix |
125
+ |---------|-----|
126
+ | Build fails locally works | Check Node.js version matches (Settings → General) |
127
+ | Missing env vars | Add to Vercel dashboard, not just .env.local |
128
+ | Type errors in build | Run `npx tsc --noEmit` locally first |
129
+ | Module not found | Check imports, case sensitivity (Linux is case-sensitive) |
130
+
131
+ ---
132
+
133
+ ## Serverless Functions
134
+
135
+ ### API Routes (Automatic)
136
+
137
+ Next.js API routes automatically become serverless functions:
138
+
139
+ ```typescript
140
+ // app/api/hello/route.ts → deployed as serverless function
141
+ export async function GET() {
142
+ return Response.json({ message: 'hello' });
143
+ }
144
+ ```
145
+
146
+ ### Limits
147
+
148
+ | Limit | Free | Pro |
149
+ |-------|------|-----|
150
+ | Duration | 10s | 60s |
151
+ | Memory | 1024MB | 3008MB |
152
+ | Size | 4.5MB | 4.5MB |
153
+
154
+ **If your function times out:** Optimize the query, add caching, or upgrade to Pro.
155
+
156
+ ---
157
+
158
+ ## Edge Functions
159
+
160
+ ### When to Use
161
+
162
+ - Middleware (auth checks, redirects)
163
+ - Geolocation-based responses
164
+ - A/B testing
165
+ - When you need <50ms response times globally
166
+
167
+ ### When NOT to Use
168
+
169
+ - Database queries (most databases aren't at the edge)
170
+ - Heavy computation
171
+ - Node.js-specific APIs
172
+
173
+ ```typescript
174
+ // middleware.ts runs on the edge by default
175
+ export function middleware(request: NextRequest) {
176
+ // Fast, runs in 50+ global locations
177
+ }
178
+ ```
179
+
180
+ ---
181
+
182
+ ## Caching
183
+
184
+ ### Static Pages (Automatic)
185
+
186
+ Pages without dynamic data are statically generated at build time. Served from CDN. Instant.
187
+
188
+ ### ISR (Incremental Static Regeneration)
189
+
190
+ ```typescript
191
+ // Revalidate every 60 seconds
192
+ export const revalidate = 60;
193
+
194
+ export default async function Page() {
195
+ const data = await getData();
196
+ return <div>{data}</div>;
197
+ }
198
+ ```
199
+
200
+ ### On-Demand Revalidation
201
+
202
+ ```typescript
203
+ // app/api/revalidate/route.ts
204
+ import { revalidatePath } from 'next/cache';
205
+
206
+ export async function POST(request: Request) {
207
+ const { path } = await request.json();
208
+ revalidatePath(path);
209
+ return Response.json({ revalidated: true });
210
+ }
211
+ ```
212
+
213
+ ---
214
+
215
+ ## Deployment Checklist
216
+
217
+ ### Before First Deploy
218
+ - [ ] Build passes locally (`npm run build`)
219
+ - [ ] No TypeScript errors (`npx tsc --noEmit`)
220
+ - [ ] Environment variables set in Vercel dashboard
221
+ - [ ] `.env.local` is in `.gitignore`
222
+
223
+ ### Before Going Live
224
+ - [ ] Custom domain configured
225
+ - [ ] Production environment variables set
226
+ - [ ] Preview deployments working
227
+ - [ ] Test the production URL (not just preview)
228
+ - [ ] Error tracking installed (Sentry)
229
+
230
+ ---
231
+
232
+ *Last updated: Baton Protocol v3.1*