Claude-skill-registry cloudflare-full-stack-scaffold
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/cloudflare-full-stack-scaffold" ~/.claude/skills/majiayu000-claude-skill-registry-cloudflare-full-stack-scaffold && rm -rf "$T"
skills/data/cloudflare-full-stack-scaffold/SKILL.mdCloudflare Full-Stack Scaffold
Complete, production-ready starter project for building full-stack applications on Cloudflare with React, Hono, AI SDK, and all Cloudflare services pre-configured.
When to Use This Skill
Use this skill when you need to:
- Start a new full-stack Cloudflare project in minutes instead of hours
- Build AI-powered applications with chat interfaces, RAG, or tool calling
- Have core Cloudflare services ready (D1, KV, R2, Workers AI)
- Opt-in to advanced features (Clerk Auth, AI Chat, Queues, Vectorize)
- Use modern best practices (Tailwind v4, shadcn/ui, AI SDK, React 19)
- Include planning docs and session handoff from the start
- Choose your AI provider (Workers AI, OpenAI, Anthropic, Gemini)
- Enable features only when needed with simple npm scripts
- Avoid configuration errors and integration issues
What This Skill Provides
Complete Scaffold Project
A fully working application you can copy, customize, and deploy immediately:
# Copy the scaffold cp -r scaffold/ my-new-app/ cd my-new-app/ # Install dependencies npm install # Initialize core services (D1, KV, R2) ./scripts/init-services.sh # Create database tables npm run d1:local # Start developing npm run dev
Result: Full-stack app running in ~5 minutes with:
- ✅ Frontend and backend connected
- ✅ Core Cloudflare services configured (D1, KV, R2, Workers AI)
- ✅ AI SDK ready with multiple providers
- ✅ Planning docs and session handoff protocol
- ✅ Dark mode, theming, UI components
- ✅ Optional features (1 script each to enable):
- Clerk Auth (
)npm run enable-auth - AI Chat UI (
)npm run enable-ai-chat - Queues (
)npm run enable-queues - Vectorize (
)npm run enable-vectorize
- Clerk Auth (
Scaffold Structure
scaffold/ ├── package.json # All dependencies (React, Hono, AI SDK, Clerk) ├── tsconfig.json # TypeScript config ├── vite.config.ts # Cloudflare Vite plugin ├── wrangler.jsonc # All Cloudflare services configured ├── .dev.vars.example # Environment variables template ├── .gitignore # Standard ignores ├── README.md # Project-specific readme ├── CLAUDE.md # Project instructions for Claude ├── SCRATCHPAD.md # Session handoff protocol ├── CHANGELOG.md # Version history ├── schema.sql # D1 database schema │ ├── docs/ # Complete planning docs │ ├── ARCHITECTURE.md │ ├── DATABASE_SCHEMA.md │ ├── API_ENDPOINTS.md │ ├── IMPLEMENTATION_PHASES.md │ ├── UI_COMPONENTS.md │ └── TESTING.md │ ├── migrations/ # D1 migrations │ └── 0001_initial.sql │ ├── src/ # Frontend (React + Vite + Tailwind v4) │ ├── main.tsx │ ├── App.tsx │ ├── index.css # Tailwind v4 theming │ ├── components/ │ │ ├── ui/ # shadcn/ui components │ │ ├── ThemeProvider.tsx │ │ ├── ProtectedRoute.tsx # Auth (COMMENTED) │ │ └── ChatInterface.tsx # AI chat (COMMENTED) │ ├── lib/ │ │ ├── utils.ts # cn() utility │ │ └── api-client.ts # Fetch wrapper │ └── pages/ │ ├── Home.tsx │ ├── Dashboard.tsx │ └── Chat.tsx # AI chat page (COMMENTED) │ └── backend/ # Backend (Hono + Cloudflare) ├── src/ │ └── index.ts # Main Worker entry ├── middleware/ │ ├── cors.ts │ └── auth.ts # JWT (COMMENTED) ├── routes/ │ ├── api.ts # Basic API routes │ ├── d1.ts # D1 examples │ ├── kv.ts # KV examples │ ├── r2.ts # R2 examples │ ├── ai.ts # Workers AI (direct binding) │ ├── ai-sdk.ts # AI SDK examples (multiple providers) │ ├── vectorize.ts # Vectorize examples │ └── queues.ts # Queues examples └── db/ └── queries.ts # D1 typed query helpers
Helper Scripts
:scripts/setup-project.sh
- Copies scaffold to new directory
- Renames project in package.json
- Initializes git repository
- Runs npm install
- Prompts to initialize services
:scripts/init-services.sh
- Creates D1 database via wrangler
- Creates KV namespace
- Creates R2 bucket
- Updates wrangler.jsonc with IDs
- (Queues and Vectorize created when enabled)
:scripts/enable-auth.sh
- Uncomments all Clerk auth patterns
- Enables ProtectedRoute component
- Enables auth middleware
- Prompts for Clerk API keys
- Updates .dev.vars
:scripts/enable-ai-chat.sh
- Uncomments ChatInterface component
- Uncomments Chat page
- Enables AI SDK UI patterns
- Adds chat route to App.tsx
- Prompts for AI provider API keys
:scripts/enable-queues.sh
- Uncomments Queues routes and bindings
- Enables async message processing
- Provides queue creation instructions
- Updates backend and config files
:scripts/enable-vectorize.sh
- Uncomments Vectorize routes and bindings
- Enables vector search and RAG
- Provides index creation instructions
- Configures embedding dimensions
Reference Documentation
:references/quick-start-guide.md
- 5-minute setup walkthrough
- First deployment guide
- Common customizations
:references/service-configuration.md
- Details on each Cloudflare service
- When to use each one
- Configuration options
:references/ai-sdk-guide.md
- AI SDK Core vs UI
- Provider switching patterns
- Streaming and tool calling
- RAG implementation
:references/customization-guide.md
- Removing unused services
- Adding new routes/pages
- Customizing theme
- Project structure best practices
:references/enabling-auth.md
- Clerk setup walkthrough
- JWT template configuration
- Testing auth flow
Key Integrations
1. AI SDK Integration (Three Approaches)
Direct Workers AI Binding (fastest):
// Already works, no API key needed const result = await c.env.AI.run('@cf/meta/llama-3-8b-instruct', { messages: [{ role: 'user', content: 'Hello' }] })
AI SDK with Workers AI (portable code, same infrastructure):
import { streamText } from 'ai' import { createWorkersAI } from 'workers-ai-provider' const workersai = createWorkersAI({ binding: c.env.AI }) const result = await streamText({ model: workersai('@cf/meta/llama-3-8b-instruct'), messages: [{ role: 'user', content: 'Hello' }] })
AI SDK with External Providers (OpenAI, Anthropic, Gemini):
import { openai } from '@ai-sdk/openai' import { anthropic } from '@ai-sdk/anthropic' // Switch providers in 1 line const result = await streamText({ model: openai('gpt-4o'), // or anthropic('claude-sonnet-4-5') messages: [{ role: 'user', content: 'Hello' }] })
AI SDK v5 UI - Chat Interface (COMMENTED, enable with script):
import { useChat } from '@ai-sdk/react' import { DefaultChatTransport } from 'ai' import { useState } from 'react' function ChatInterface() { const [input, setInput] = useState('') const { messages, sendMessage, status } = useChat({ transport: new DefaultChatTransport({ api: '/api/ai-sdk/chat', }), }) // Send message on Enter key const handleKeyDown = (e) => { if (e.key === 'Enter' && status === 'ready' && input.trim()) { sendMessage({ text: input }) setInput('') } } // Render messages (v5 uses message.parts[]) return ( <div> {messages.map(m => ( <div key={m.id}> {m.parts.map(part => { if (part.type === 'text') return <div>{part.text}</div> })} </div> ))} <input value={input} onChange={e => setInput(e.target.value)} onKeyDown={handleKeyDown} disabled={status !== 'ready'} /> </div> ) }
2. Forms & Data Fetching (React Hook Form + Zod + TanStack Query)
Industry-Standard Libraries for Production Apps:
React Hook Form - Performant form state management:
import { useForm } from 'react-hook-form' import { zodResolver } from '@hookform/resolvers/zod' const form = useForm({ resolver: zodResolver(userSchema), // Zod validation }) <input {...register('name')} /> {errors.name && <span>{errors.name.message}</span>}
Zod v4 - TypeScript-first schema validation:
// Define schema once const userSchema = z.object({ name: z.string().min(2), email: z.string().email(), age: z.number().int().positive().optional(), }) // Infer TypeScript type type User = z.infer<typeof userSchema> // Use in frontend (React Hook Form) resolver: zodResolver(userSchema) // Use in backend (same schema!) const validated = userSchema.parse(requestBody)
TanStack Query v5 - Smart data fetching & caching:
// Fetch data with automatic caching const { data, isLoading } = useQuery({ queryKey: ['users'], queryFn: () => apiClient.get('/api/users'), }) // Update data with mutations const mutation = useMutation({ mutationFn: (newUser) => apiClient.post('/api/users', newUser), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['users'] }) }, })
Full-Stack Validation Pattern:
- ✅ Define schema in
(single source of truth)shared/schemas/ - ✅ Frontend validates instantly (React Hook Form + Zod)
- ✅ Backend validates securely (same Zod schema)
- ✅ TypeScript types inferred automatically
- ✅ Update validation once, applies everywhere
Complete Working Examples:
- Profile page with form:
route/profile - Dashboard with queries:
route/dashboard - Form component:
src/components/UserProfileForm.tsx - Backend validation:
backend/routes/forms.ts - Shared schemas:
shared/schemas/userSchema.ts
See
references/supporting-libraries-guide.md for comprehensive guide.
3. All Cloudflare Services Pre-Configured
Database (D1):
- Schema file with example tables
- Migrations directory
- Typed query helpers
- Example CRUD routes
Key-Value Storage (KV):
- Get/put/delete examples
- TTL patterns
- Bulk operations
Object Storage (R2):
- Upload/download examples
- Presigned URLs
- Streaming large files
AI Inference (Workers AI):
- Text generation
- Embeddings
- Image generation (Stable Diffusion)
Vector Database (Vectorize):
- Insert/query embeddings
- RAG patterns
- Similarity search
Message Queues:
- Producer examples
- Consumer patterns
- Batch processing
3. Optional Clerk Authentication
All auth patterns included but COMMENTED - uncomment to enable:
./scripts/enable-auth.sh # Prompts for Clerk keys, uncomments all patterns
What gets enabled:
- Frontend: ProtectedRoute component, auth in api-client
- Backend: JWT verification middleware
- Protected API routes
- Auth loading states
- Session management
4. Planning Docs + Session Handoff Protocol
docs/ directory - Complete planning structure:
- ARCHITECTURE.md: System design
- DATABASE_SCHEMA.md: D1 schema docs
- API_ENDPOINTS.md: All routes documented
- IMPLEMENTATION_PHASES.md: Phased build approach
- UI_COMPONENTS.md: Component hierarchy
- TESTING.md: Test strategy
SCRATCHPAD.md - Session handoff protocol:
- Current phase tracking
- Progress checkpoints
- Next actions
- References to planning docs
Usage Guide
Quick Start (5 Minutes)
# 1. Copy scaffold cd /path/to/skills/cloudflare-full-stack-scaffold cp -r scaffold/ ~/projects/my-new-app/ cd ~/projects/my-new-app/ # 2. Run setup npm install # 3. Initialize Cloudflare services npx wrangler d1 create my-app-db npx wrangler kv:namespace create my-app-kv npx wrangler r2 bucket create my-app-bucket npx wrangler vectorize create my-app-index --dimensions=1536 npx wrangler queues create my-app-queue # 4. Update wrangler.jsonc with IDs from step 3 # 5. Create D1 tables npx wrangler d1 execute my-app-db --local --file=schema.sql # 6. Start dev server npm run dev
Visit: http://localhost:5173
Enable Authentication (Optional)
./scripts/enable-auth.sh # Prompts for Clerk publishable and secret keys # Uncomments all auth patterns # Updates .dev.vars npm run dev
Enable AI Chat Interface (Optional)
./scripts/enable-ai-chat.sh # Uncomments ChatInterface component # Uncomments Chat page # Prompts for OpenAI/Anthropic API keys (optional) npm run dev
Visit: http://localhost:5173/chat
Deploy to Production
# Build npm run build # Deploy npx wrangler deploy # Migrate production database npx wrangler d1 execute my-app-db --remote --file=schema.sql # Set production secrets npx wrangler secret put CLERK_SECRET_KEY npx wrangler secret put OPENAI_API_KEY
Customization Patterns
Remove Unused Services
Don't need Vectorize?
- Delete
backend/routes/vectorize.ts - Remove vectorize binding from
wrangler.jsonc - Remove from
cloudflare pluginvite.config.ts - Remove route registration in
backend/src/index.ts
Add New API Routes
// backend/routes/my-feature.ts import { Hono } from 'hono' export const myFeatureRoutes = new Hono() myFeatureRoutes.get('/hello', (c) => { return c.json({ message: 'Hello from my feature!' }) }) // backend/src/index.ts import { myFeatureRoutes } from './routes/my-feature' app.route('/api/my-feature', myFeatureRoutes)
Switch AI Providers
// Change this line: model: openai('gpt-4o'), // To this: model: anthropic('claude-sonnet-4-5'), // Or this: model: google('gemini-2.5-flash'), // Or use Workers AI: const workersai = createWorkersAI({ binding: c.env.AI }) model: workersai('@cf/meta/llama-3-8b-instruct'),
Customize Theme
All theming in
src/index.css:
:root { --background: hsl(0 0% 100%); /* Change colors here */ --foreground: hsl(0 0% 3.9%); --primary: hsl(220 90% 56%); /* etc */ }
Architecture Highlights
Frontend-Backend Connection
Key Insight: The Vite plugin runs your Worker on the SAME port as Vite.
// ✅ CORRECT: Use relative URLs fetch('/api/data') // ❌ WRONG: Don't use absolute URLs fetch('http://localhost:8787/api/data')
No proxy configuration needed!
Environment Variables
Frontend (.env):
VITE_CLERK_PUBLISHABLE_KEY=pk_test_xxx
Backend (.dev.vars):
CLERK_SECRET_KEY=sk_test_xxx OPENAI_API_KEY=sk-xxx
CORS Configuration
Critical: CORS middleware must be applied BEFORE routes:
// ✅ CORRECT ORDER app.use('/api/*', corsMiddleware) app.post('/api/data', handler) // ❌ WRONG - Will cause CORS errors app.post('/api/data', handler) app.use('/api/*', corsMiddleware)
Auth Pattern (When Enabled)
Frontend: Check
isLoaded before making API calls:
const { isLoaded, isSignedIn } = useSession() useEffect(() => { if (!isLoaded) return // Wait for auth fetch('/api/protected').then(/* ... */) }, [isLoaded])
Backend: JWT verification middleware:
import { jwtAuthMiddleware } from './middleware/auth' app.use('/api/protected/*', jwtAuthMiddleware)
Dependencies Included
{ "dependencies": { "react": "^19.2.0", "react-dom": "^19.2.0", "hono": "^4.10.2", "@cloudflare/vite-plugin": "^1.13.14", "ai": "^5.0.76", "@ai-sdk/openai": "^1.0.0", "@ai-sdk/anthropic": "^1.0.0", "@ai-sdk/google": "^1.0.0", "workers-ai-provider": "^2.0.0", "@ai-sdk/react": "^1.0.0", "@clerk/clerk-react": "^5.53.3", "@clerk/backend": "^2.19.0", "tailwindcss": "^4.1.14", "@tailwindcss/vite": "^4.1.14", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "tailwind-merge": "^2.5.4", "zod": "^3.24.1", "react-hook-form": "^7.54.2", "@hookform/resolvers": "^3.9.1", "@tanstack/react-query": "^5.62.11", "@radix-ui/react-slot": "^1.1.1", "@radix-ui/react-dropdown-menu": "^2.1.4" }, "devDependencies": { "@types/react": "^19.0.0", "@types/react-dom": "^19.0.0", "typescript": "^5.7.2", "vite": "^7.1.11", "wrangler": "^4.0.0" } }
Token Efficiency
| Scenario | Without Scaffold | With Scaffold | Savings |
|---|---|---|---|
| Initial setup | ~18-22k tokens | ~3-5k tokens | ~80% |
| Service configuration | ~8-10k tokens | 0 tokens (done) | 100% |
| Frontend-backend connection | ~5-7k tokens | 0 tokens (done) | 100% |
| AI SDK setup | ~4-6k tokens | 0 tokens (done) | 100% |
| Auth integration | ~6-8k tokens | ~500 tokens | ~90% |
| Planning docs | ~3-5k tokens | 0 tokens (included) | 100% |
| Total | ~44-58k tokens | ~3-6k tokens | ~90% |
Time Savings: 3-4 hours → 5-10 minutes (~95% faster)
Common Issues Prevented
| Issue | How Scaffold Prevents It |
|---|---|
| Service binding errors | All bindings pre-configured and tested |
| CORS errors | Middleware in correct order |
| Auth race conditions | Proper loading state patterns |
| Frontend-backend connection | Vite plugin correctly configured |
| AI SDK setup confusion | Multiple working examples |
| Missing planning docs | Complete docs/ structure included |
| Environment variable mix-ups | Clear .dev.vars.example with comments |
| Missing migrations | migrations/ directory with examples |
| Inconsistent file structure | Standard, tested structure |
| Database type errors | Typed query helpers included |
| Theme configuration | Tailwind v4 theming pre-configured |
| Build errors | Working build config (vite + wrangler) |
Total Errors Prevented: 12+ common setup and integration errors
When NOT to Use This Scaffold
- ❌ Building a static site (no backend needed)
- ❌ Using Next.js, Remix, or other meta-framework
- ❌ Need SSR (use framework-specific Cloudflare adapter)
- ❌ Building backend-only API (no frontend needed)
- ❌ Extremely simple single-page app
For these cases: Use minimal templates or official framework starters.
Production Evidence
Based on:
- Cloudflare's official agents-starter template (AI SDK patterns)
- cloudflare-full-stack-integration skill (tested frontend-backend patterns)
- session-handoff-protocol skill (planning docs + SCRATCHPAD.md)
- tailwind-v4-shadcn skill (UI component patterns)
- Multiple production Jezweb projects
Package versions verified: 2025-10-23
Works with:
- Cloudflare Workers (production environment)
- Wrangler 4.0+
- Node.js 18+
- npm/pnpm/yarn
Quick Reference
Setup new project:
cp -r scaffold/ my-app/ cd my-app/ npm install # Follow quick-start-guide.md
Enable auth:
./scripts/enable-auth.sh
Enable AI chat:
./scripts/enable-ai-chat.sh
Deploy:
npm run build npx wrangler deploy
Key Files:
- Service configurationwrangler.jsonc
- Build configurationvite.config.ts
- Environment variables template.dev.vars.example
- System designdocs/ARCHITECTURE.md
- Session handoff protocolSCRATCHPAD.md
Remember: This scaffold is a starting point, not a constraint. Customize everything to match your needs. The value is in having a working foundation with all the integration patterns already figured out, saving hours of setup and debugging time.