create-claude-webapp 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/acceptance-test-generator.md +256 -0
- package/.claude/agents/auth-flow-designer.md +93 -0
- package/.claude/agents/code-reviewer.md +193 -0
- package/.claude/agents/code-verifier.md +194 -0
- package/.claude/agents/deployment-executor.md +90 -0
- package/.claude/agents/design-sync.md +226 -0
- package/.claude/agents/document-reviewer.md +304 -0
- package/.claude/agents/environment-validator.md +100 -0
- package/.claude/agents/integration-test-reviewer.md +196 -0
- package/.claude/agents/investigator.md +162 -0
- package/.claude/agents/prd-creator.md +220 -0
- package/.claude/agents/quality-fixer-frontend.md +323 -0
- package/.claude/agents/quality-fixer.md +280 -0
- package/.claude/agents/requirement-analyzer.md +149 -0
- package/.claude/agents/rls-policy-designer.md +86 -0
- package/.claude/agents/rule-advisor.md +123 -0
- package/.claude/agents/scope-discoverer.md +231 -0
- package/.claude/agents/solver.md +173 -0
- package/.claude/agents/supabase-migration-generator.md +85 -0
- package/.claude/agents/task-decomposer.md +246 -0
- package/.claude/agents/task-executor-frontend.md +264 -0
- package/.claude/agents/task-executor.md +261 -0
- package/.claude/agents/technical-designer-frontend.md +444 -0
- package/.claude/agents/technical-designer.md +370 -0
- package/.claude/agents/verifier.md +193 -0
- package/.claude/agents/work-planner.md +211 -0
- package/.claude/commands/add-integration-tests.md +116 -0
- package/.claude/commands/build.md +77 -0
- package/.claude/commands/db-migrate.md +96 -0
- package/.claude/commands/deploy.md +95 -0
- package/.claude/commands/design.md +75 -0
- package/.claude/commands/diagnose.md +202 -0
- package/.claude/commands/front-build.md +116 -0
- package/.claude/commands/front-design.md +61 -0
- package/.claude/commands/front-plan.md +53 -0
- package/.claude/commands/front-reverse-design.md +183 -0
- package/.claude/commands/front-review.md +89 -0
- package/.claude/commands/implement.md +80 -0
- package/.claude/commands/local-dev.md +94 -0
- package/.claude/commands/plan.md +61 -0
- package/.claude/commands/project-inject.md +76 -0
- package/.claude/commands/refine-skill.md +207 -0
- package/.claude/commands/reverse-engineer.md +301 -0
- package/.claude/commands/review.md +88 -0
- package/.claude/commands/setup-auth.md +68 -0
- package/.claude/commands/setup-supabase.md +66 -0
- package/.claude/commands/setup-vercel.md +71 -0
- package/.claude/commands/sync-skills.md +116 -0
- package/.claude/commands/task.md +13 -0
- package/.claude/skills/coding-standards/SKILL.md +246 -0
- package/.claude/skills/documentation-criteria/SKILL.md +184 -0
- package/.claude/skills/documentation-criteria/references/adr-template.md +64 -0
- package/.claude/skills/documentation-criteria/references/design-template.md +263 -0
- package/.claude/skills/documentation-criteria/references/plan-template.md +130 -0
- package/.claude/skills/documentation-criteria/references/prd-template.md +109 -0
- package/.claude/skills/documentation-criteria/references/task-template.md +38 -0
- package/.claude/skills/frontend/technical-spec/SKILL.md +147 -0
- package/.claude/skills/frontend/typescript-rules/SKILL.md +136 -0
- package/.claude/skills/frontend/typescript-testing/SKILL.md +129 -0
- package/.claude/skills/fullstack-integration/SKILL.md +466 -0
- package/.claude/skills/implementation-approach/SKILL.md +141 -0
- package/.claude/skills/integration-e2e-testing/SKILL.md +146 -0
- package/.claude/skills/interview/SKILL.md +345 -0
- package/.claude/skills/project-context/SKILL.md +53 -0
- package/.claude/skills/stack-auth/SKILL.md +519 -0
- package/.claude/skills/subagents-orchestration-guide/SKILL.md +218 -0
- package/.claude/skills/supabase/SKILL.md +289 -0
- package/.claude/skills/supabase-edge-functions/SKILL.md +386 -0
- package/.claude/skills/supabase-local/SKILL.md +328 -0
- package/.claude/skills/supabase-testing/SKILL.md +513 -0
- package/.claude/skills/task-analyzer/SKILL.md +131 -0
- package/.claude/skills/task-analyzer/references/skills-index.yaml +375 -0
- package/.claude/skills/technical-spec/SKILL.md +86 -0
- package/.claude/skills/typescript-rules/SKILL.md +121 -0
- package/.claude/skills/typescript-testing/SKILL.md +155 -0
- package/.claude/skills/vercel-deployment/SKILL.md +355 -0
- package/.claude/skills/vercel-edge/SKILL.md +407 -0
- package/README.md +4 -17
- package/package.json +1 -1
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vercel-edge
|
|
3
|
+
description: Vercel Edge runtime, middleware patterns, and Edge Functions. Use when implementing edge logic, middleware, or geo-routing.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Vercel Edge Runtime
|
|
7
|
+
|
|
8
|
+
## Edge Runtime Constraints
|
|
9
|
+
|
|
10
|
+
### What's NOT Available
|
|
11
|
+
The Edge runtime uses V8 isolates, not Node.js. These APIs are unavailable:
|
|
12
|
+
|
|
13
|
+
| Unavailable | Alternative |
|
|
14
|
+
|-------------|-------------|
|
|
15
|
+
| `fs` module | Use fetch for remote files |
|
|
16
|
+
| `path` module | String manipulation |
|
|
17
|
+
| `crypto` (Node.js) | Web Crypto API |
|
|
18
|
+
| `Buffer` (full) | Use Uint8Array |
|
|
19
|
+
| Native modules | Pure JS alternatives |
|
|
20
|
+
| Long-running processes | Use serverless functions |
|
|
21
|
+
|
|
22
|
+
### What IS Available
|
|
23
|
+
- Web standard APIs (fetch, Request, Response)
|
|
24
|
+
- Web Crypto API
|
|
25
|
+
- TextEncoder/TextDecoder
|
|
26
|
+
- URL and URLSearchParams
|
|
27
|
+
- setTimeout (limited)
|
|
28
|
+
- console methods
|
|
29
|
+
|
|
30
|
+
### Execution Limits
|
|
31
|
+
| Limit | Value |
|
|
32
|
+
|-------|-------|
|
|
33
|
+
| Memory | 128 MB |
|
|
34
|
+
| CPU time | 50ms (Hobby), unlimited (Pro) |
|
|
35
|
+
| Duration | 30s |
|
|
36
|
+
| Response body | 4 MB |
|
|
37
|
+
|
|
38
|
+
## Middleware Patterns
|
|
39
|
+
|
|
40
|
+
### Basic Middleware Structure
|
|
41
|
+
```typescript
|
|
42
|
+
// middleware.ts (at project root)
|
|
43
|
+
import { NextResponse } from 'next/server'
|
|
44
|
+
import type { NextRequest } from 'next/server'
|
|
45
|
+
|
|
46
|
+
export function middleware(request: NextRequest) {
|
|
47
|
+
// Your logic here
|
|
48
|
+
return NextResponse.next()
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Configure which paths trigger middleware
|
|
52
|
+
export const config = {
|
|
53
|
+
matcher: [
|
|
54
|
+
/*
|
|
55
|
+
* Match all request paths except:
|
|
56
|
+
* - _next/static (static files)
|
|
57
|
+
* - _next/image (image optimization)
|
|
58
|
+
* - favicon.ico (favicon file)
|
|
59
|
+
* - public files
|
|
60
|
+
*/
|
|
61
|
+
'/((?!_next/static|_next/image|favicon.ico|.*\\..*$).*)',
|
|
62
|
+
],
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Authentication Middleware
|
|
67
|
+
```typescript
|
|
68
|
+
// middleware.ts
|
|
69
|
+
import { NextResponse } from 'next/server'
|
|
70
|
+
import type { NextRequest } from 'next/server'
|
|
71
|
+
|
|
72
|
+
const protectedPaths = ['/dashboard', '/settings', '/api/protected']
|
|
73
|
+
|
|
74
|
+
export function middleware(request: NextRequest) {
|
|
75
|
+
const { pathname } = request.nextUrl
|
|
76
|
+
|
|
77
|
+
// Check if path is protected
|
|
78
|
+
const isProtected = protectedPaths.some(path => pathname.startsWith(path))
|
|
79
|
+
|
|
80
|
+
if (!isProtected) {
|
|
81
|
+
return NextResponse.next()
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Check for auth token
|
|
85
|
+
const token = request.cookies.get('auth-token')?.value
|
|
86
|
+
|
|
87
|
+
if (!token) {
|
|
88
|
+
// Redirect to login
|
|
89
|
+
const loginUrl = new URL('/login', request.url)
|
|
90
|
+
loginUrl.searchParams.set('redirect', pathname)
|
|
91
|
+
return NextResponse.redirect(loginUrl)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Verify token (simplified - use proper JWT verification)
|
|
95
|
+
try {
|
|
96
|
+
// Token validation logic
|
|
97
|
+
return NextResponse.next()
|
|
98
|
+
} catch {
|
|
99
|
+
// Invalid token, redirect to login
|
|
100
|
+
const response = NextResponse.redirect(new URL('/login', request.url))
|
|
101
|
+
response.cookies.delete('auth-token')
|
|
102
|
+
return response
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export const config = {
|
|
107
|
+
matcher: ['/dashboard/:path*', '/settings/:path*', '/api/protected/:path*'],
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Geo-Routing Middleware
|
|
112
|
+
```typescript
|
|
113
|
+
// middleware.ts
|
|
114
|
+
import { NextResponse } from 'next/server'
|
|
115
|
+
import type { NextRequest } from 'next/server'
|
|
116
|
+
|
|
117
|
+
const COUNTRY_REDIRECTS: Record<string, string> = {
|
|
118
|
+
DE: '/de',
|
|
119
|
+
FR: '/fr',
|
|
120
|
+
ES: '/es',
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function middleware(request: NextRequest) {
|
|
124
|
+
const country = request.geo?.country || 'US'
|
|
125
|
+
|
|
126
|
+
// Skip if already on localized path
|
|
127
|
+
const { pathname } = request.nextUrl
|
|
128
|
+
if (pathname.startsWith('/de') || pathname.startsWith('/fr') || pathname.startsWith('/es')) {
|
|
129
|
+
return NextResponse.next()
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Redirect to localized version
|
|
133
|
+
const redirect = COUNTRY_REDIRECTS[country]
|
|
134
|
+
if (redirect && pathname === '/') {
|
|
135
|
+
return NextResponse.redirect(new URL(redirect, request.url))
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return NextResponse.next()
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export const config = {
|
|
142
|
+
matcher: '/',
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### A/B Testing Middleware
|
|
147
|
+
```typescript
|
|
148
|
+
// middleware.ts
|
|
149
|
+
import { NextResponse } from 'next/server'
|
|
150
|
+
import type { NextRequest } from 'next/server'
|
|
151
|
+
|
|
152
|
+
const EXPERIMENT_COOKIE = 'ab-experiment'
|
|
153
|
+
const VARIANTS = ['control', 'variant-a', 'variant-b']
|
|
154
|
+
|
|
155
|
+
export function middleware(request: NextRequest) {
|
|
156
|
+
// Check for existing experiment assignment
|
|
157
|
+
let variant = request.cookies.get(EXPERIMENT_COOKIE)?.value
|
|
158
|
+
|
|
159
|
+
// Assign variant if not already assigned
|
|
160
|
+
if (!variant || !VARIANTS.includes(variant)) {
|
|
161
|
+
variant = VARIANTS[Math.floor(Math.random() * VARIANTS.length)]
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Rewrite to variant path
|
|
165
|
+
const url = request.nextUrl.clone()
|
|
166
|
+
url.pathname = `/${variant}${url.pathname}`
|
|
167
|
+
|
|
168
|
+
const response = NextResponse.rewrite(url)
|
|
169
|
+
|
|
170
|
+
// Set cookie for consistent experience
|
|
171
|
+
response.cookies.set(EXPERIMENT_COOKIE, variant, {
|
|
172
|
+
maxAge: 60 * 60 * 24 * 30, // 30 days
|
|
173
|
+
httpOnly: true,
|
|
174
|
+
sameSite: 'lax',
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
return response
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export const config = {
|
|
181
|
+
matcher: '/landing-page',
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Rate Limiting Middleware
|
|
186
|
+
```typescript
|
|
187
|
+
// middleware.ts
|
|
188
|
+
import { NextResponse } from 'next/server'
|
|
189
|
+
import type { NextRequest } from 'next/server'
|
|
190
|
+
|
|
191
|
+
// Note: For production, use Edge Config or external store
|
|
192
|
+
const rateLimitMap = new Map<string, { count: number; timestamp: number }>()
|
|
193
|
+
|
|
194
|
+
const RATE_LIMIT = 100 // requests
|
|
195
|
+
const WINDOW_MS = 60 * 1000 // 1 minute
|
|
196
|
+
|
|
197
|
+
export function middleware(request: NextRequest) {
|
|
198
|
+
const ip = request.ip ?? request.headers.get('x-forwarded-for') ?? 'unknown'
|
|
199
|
+
|
|
200
|
+
const now = Date.now()
|
|
201
|
+
const record = rateLimitMap.get(ip)
|
|
202
|
+
|
|
203
|
+
if (!record || now - record.timestamp > WINDOW_MS) {
|
|
204
|
+
rateLimitMap.set(ip, { count: 1, timestamp: now })
|
|
205
|
+
return NextResponse.next()
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (record.count >= RATE_LIMIT) {
|
|
209
|
+
return new NextResponse('Too Many Requests', {
|
|
210
|
+
status: 429,
|
|
211
|
+
headers: {
|
|
212
|
+
'Retry-After': String(Math.ceil((WINDOW_MS - (now - record.timestamp)) / 1000)),
|
|
213
|
+
},
|
|
214
|
+
})
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
record.count++
|
|
218
|
+
return NextResponse.next()
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export const config = {
|
|
222
|
+
matcher: '/api/:path*',
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## Edge Functions
|
|
227
|
+
|
|
228
|
+
### Creating Edge API Routes
|
|
229
|
+
```typescript
|
|
230
|
+
// app/api/edge-example/route.ts
|
|
231
|
+
export const runtime = 'edge'
|
|
232
|
+
|
|
233
|
+
export async function GET(request: Request) {
|
|
234
|
+
const { searchParams } = new URL(request.url)
|
|
235
|
+
const name = searchParams.get('name') || 'World'
|
|
236
|
+
|
|
237
|
+
return Response.json({ message: `Hello ${name}!` })
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
export async function POST(request: Request) {
|
|
241
|
+
const body = await request.json()
|
|
242
|
+
|
|
243
|
+
return Response.json({ received: body })
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Edge Function with Geo Data
|
|
248
|
+
```typescript
|
|
249
|
+
// app/api/geo/route.ts
|
|
250
|
+
export const runtime = 'edge'
|
|
251
|
+
|
|
252
|
+
export async function GET(request: Request) {
|
|
253
|
+
// Access geo data from headers (Vercel sets these)
|
|
254
|
+
const country = request.headers.get('x-vercel-ip-country') || 'Unknown'
|
|
255
|
+
const city = request.headers.get('x-vercel-ip-city') || 'Unknown'
|
|
256
|
+
const region = request.headers.get('x-vercel-ip-country-region') || 'Unknown'
|
|
257
|
+
|
|
258
|
+
return Response.json({
|
|
259
|
+
country,
|
|
260
|
+
city,
|
|
261
|
+
region,
|
|
262
|
+
})
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Edge Config
|
|
267
|
+
|
|
268
|
+
### Setup
|
|
269
|
+
```bash
|
|
270
|
+
# Create Edge Config store in Vercel Dashboard
|
|
271
|
+
# Project > Storage > Create Edge Config
|
|
272
|
+
|
|
273
|
+
# Install SDK
|
|
274
|
+
npm install @vercel/edge-config
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Using Edge Config
|
|
278
|
+
```typescript
|
|
279
|
+
// app/api/feature-flags/route.ts
|
|
280
|
+
export const runtime = 'edge'
|
|
281
|
+
|
|
282
|
+
import { get } from '@vercel/edge-config'
|
|
283
|
+
|
|
284
|
+
export async function GET() {
|
|
285
|
+
const flags = await get('featureFlags')
|
|
286
|
+
|
|
287
|
+
return Response.json({ flags })
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### Feature Flags Pattern
|
|
292
|
+
```typescript
|
|
293
|
+
// lib/features.ts
|
|
294
|
+
import { get } from '@vercel/edge-config'
|
|
295
|
+
|
|
296
|
+
export interface FeatureFlags {
|
|
297
|
+
newDashboard: boolean
|
|
298
|
+
betaFeatures: boolean
|
|
299
|
+
maintenanceMode: boolean
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export async function getFeatureFlags(): Promise<FeatureFlags> {
|
|
303
|
+
const flags = await get<FeatureFlags>('featureFlags')
|
|
304
|
+
|
|
305
|
+
return flags ?? {
|
|
306
|
+
newDashboard: false,
|
|
307
|
+
betaFeatures: false,
|
|
308
|
+
maintenanceMode: false,
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Usage in Edge middleware
|
|
313
|
+
import { getFeatureFlags } from '@/lib/features'
|
|
314
|
+
|
|
315
|
+
export async function middleware(request: NextRequest) {
|
|
316
|
+
const flags = await getFeatureFlags()
|
|
317
|
+
|
|
318
|
+
if (flags.maintenanceMode) {
|
|
319
|
+
return NextResponse.rewrite(new URL('/maintenance', request.url))
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
return NextResponse.next()
|
|
323
|
+
}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### Updating Edge Config
|
|
327
|
+
```typescript
|
|
328
|
+
// Via API (from serverless function, not edge)
|
|
329
|
+
import { createClient } from '@vercel/edge-config'
|
|
330
|
+
|
|
331
|
+
const client = createClient(process.env.EDGE_CONFIG)
|
|
332
|
+
|
|
333
|
+
// Read
|
|
334
|
+
const value = await client.get('key')
|
|
335
|
+
|
|
336
|
+
// Note: Writing requires Vercel API
|
|
337
|
+
// Use Vercel dashboard or API for updates
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
## Caching at the Edge
|
|
341
|
+
|
|
342
|
+
### Cache Headers
|
|
343
|
+
```typescript
|
|
344
|
+
export const runtime = 'edge'
|
|
345
|
+
|
|
346
|
+
export async function GET() {
|
|
347
|
+
const data = await fetchData()
|
|
348
|
+
|
|
349
|
+
return Response.json(data, {
|
|
350
|
+
headers: {
|
|
351
|
+
'Cache-Control': 's-maxage=3600, stale-while-revalidate=86400',
|
|
352
|
+
},
|
|
353
|
+
})
|
|
354
|
+
}
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### Cache Strategies
|
|
358
|
+
|
|
359
|
+
| Strategy | Header | Use Case |
|
|
360
|
+
|----------|--------|----------|
|
|
361
|
+
| Static | `s-maxage=31536000, immutable` | Assets that never change |
|
|
362
|
+
| Revalidate | `s-maxage=60, stale-while-revalidate=3600` | Frequently updated content |
|
|
363
|
+
| No cache | `no-store` | Personalized/dynamic data |
|
|
364
|
+
|
|
365
|
+
## Best Practices
|
|
366
|
+
|
|
367
|
+
### Performance
|
|
368
|
+
- Keep middleware fast (<50ms)
|
|
369
|
+
- Avoid heavy computations
|
|
370
|
+
- Use Edge Config for configuration data
|
|
371
|
+
- Cache responses where possible
|
|
372
|
+
|
|
373
|
+
### Security
|
|
374
|
+
- Validate all inputs
|
|
375
|
+
- Use secure cookie settings
|
|
376
|
+
- Implement proper CORS
|
|
377
|
+
- Rate limit sensitive endpoints
|
|
378
|
+
|
|
379
|
+
### Error Handling
|
|
380
|
+
```typescript
|
|
381
|
+
export const runtime = 'edge'
|
|
382
|
+
|
|
383
|
+
export async function GET(request: Request) {
|
|
384
|
+
try {
|
|
385
|
+
const data = await riskyOperation()
|
|
386
|
+
return Response.json(data)
|
|
387
|
+
} catch (error) {
|
|
388
|
+
console.error('Edge function error:', error)
|
|
389
|
+
|
|
390
|
+
return Response.json(
|
|
391
|
+
{ error: 'Internal server error' },
|
|
392
|
+
{ status: 500 }
|
|
393
|
+
)
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### Debugging
|
|
399
|
+
```typescript
|
|
400
|
+
// Log request details
|
|
401
|
+
console.log('Request URL:', request.url)
|
|
402
|
+
console.log('Headers:', Object.fromEntries(request.headers))
|
|
403
|
+
console.log('Geo:', {
|
|
404
|
+
country: request.headers.get('x-vercel-ip-country'),
|
|
405
|
+
city: request.headers.get('x-vercel-ip-city'),
|
|
406
|
+
})
|
|
407
|
+
```
|
package/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# AI Coding Project Boilerplate 🤖
|
|
2
2
|
|
|
3
|
-
*Read this in other languages: [日本語](README.ja.md)*
|
|
4
|
-
|
|
5
3
|
[](https://www.typescriptlang.org/)
|
|
6
4
|
[](https://nodejs.org/)
|
|
7
5
|
[](https://claude.ai/code)
|
|
8
6
|
[](https://opensource.org/licenses/MIT)
|
|
9
7
|
[](https://github.com/svenmalvik/claude-boilerplate-4-web/pulls)
|
|
10
8
|
|
|
9
|
+
> 🔱 This is an opinionated version of [shinpr/ai-coding-project-boilerplate](https://github.com/shinpr/ai-coding-project-boilerplate)
|
|
10
|
+
|
|
11
11
|
⚡ **This boilerplate is for developers who want to:**
|
|
12
12
|
- Build **production-ready TypeScript projects** faster with AI
|
|
13
13
|
- Avoid **context exhaustion** in long AI coding sessions
|
|
@@ -23,14 +23,13 @@
|
|
|
23
23
|
7. [Development Workflow](#-claude-code-workflow)
|
|
24
24
|
8. [Project Structure](#-project-structure)
|
|
25
25
|
9. [Package Manager Configuration](#-package-manager-configuration)
|
|
26
|
-
10. [
|
|
27
|
-
11. [FAQ](#-faq)
|
|
26
|
+
10. [FAQ](#-faq)
|
|
28
27
|
|
|
29
28
|
## ⚡ Quick Start (3 Steps)
|
|
30
29
|
|
|
31
30
|
```bash
|
|
32
31
|
# 1. Create your project (30 seconds)
|
|
33
|
-
npx create-
|
|
32
|
+
npx create-claude-webapp my-project
|
|
34
33
|
|
|
35
34
|
# 2. Install dependencies (automatic)
|
|
36
35
|
cd my-project && npm install
|
|
@@ -247,18 +246,6 @@ The above are representative examples. The following scripts are referenced in r
|
|
|
247
246
|
|
|
248
247
|
`build`, `build:frontend`, `dev`, `preview`, `type-check`, `test`, `test:coverage`, `test:coverage:fresh`, `test:safe`, `cleanup:processes`, `check`, `check:fix`, `check:code`, `check:unused`, `check:deps`, `check:all`, `format`, `format:check`, `lint`, `lint:fix`
|
|
249
248
|
|
|
250
|
-
## 🌐 Multilingual Support
|
|
251
|
-
|
|
252
|
-
Full support for English and Japanese:
|
|
253
|
-
|
|
254
|
-
```bash
|
|
255
|
-
npm run lang:en # Switch to English
|
|
256
|
-
npm run lang:ja # Switch to Japanese
|
|
257
|
-
npm run lang:status # Check current language
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
Automatically updates all configurations, rules, and agent definitions.
|
|
261
|
-
|
|
262
249
|
## 🤔 FAQ
|
|
263
250
|
|
|
264
251
|
**Q: How do sub agents work?**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-claude-webapp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"packageManager": "npm@10.8.2",
|
|
5
5
|
"description": "TypeScript boilerplate with skills and sub-agents for Claude Code. Prevents context exhaustion through role-based task splitting.",
|
|
6
6
|
"keywords": [
|