Cloudflare Workers: Deploy in a Naptime
As a SAHD, you know that naptime is precious. 90 minutes if you're lucky, 20 minutes if you're not. Either way, you need to make every minute count when building your side projects.
Today, we're going to deploy a fully functional serverless API using Cloudflare Workers before the kids wake up.
Why Cloudflare Workers?
Traditional server setup takes hours. Cloudflare Workers take minutes:
- No servers to manage - Deploy code, not infrastructure
- Global edge deployment - Your functions run worldwide instantly
- Zero cold starts - V8 isolates start in under 5ms
- Generous free tier - 100,000 requests/day for free
- Built-in TypeScript - Type safety without setup
Perfect for dad developers who need reliability without babysitting servers.
SAHD Reality Check
While the setup is quick, you'll still need to allocate focused time. Best done during naptime or after bedtime when you can concentrate without interruptions.
Quick Setup (5 minutes)
First, install Wrangler CLI:
npm install -g wrangler wrangler login
Create your first Worker:
npm create cloudflare@latest my-worker cd my-worker
Choose these options:
- Type: "Hello World" Worker
- TypeScript: Yes
- Git: Yes
Your First API Endpoint (10 minutes)
Replace the contents of src/index.ts
:
export interface Env { // Define your environment variables here }export default { async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> { const url = new URL(request.url);// Handle CORS for browser requests if (request.method === 'OPTIONS') { return new Response(null, { headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type', }, }); }// Simple routing switch (url.pathname) { case '/api/hello': return handleHello(request); case '/api/time': return handleTime(); case '/api/kids': return handleKidsStatus(); default: return new Response('Not Found', { status: 404 }); } }, };async function handleHello(request: Request): Promise<Response> { const data = { message: 'Hello from a SAHD developer!', timestamp: new Date().toISOString(), location: 'The edge (probably closer than the nearest coffee shop)' };return new Response(JSON.stringify(data), { headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' }, }); }async function handleTime(): Promise<Response> { const now = new Date(); const data = { utc: now.toISOString(), local: now.toLocaleString(), kidFriendly: now.getHours() < 7 || now.getHours() > 20 ? 'Coding time! ๐ฆ' : 'Family time! ๐จโ๐ฉโ๐งโ๐ฆ' };return new Response(JSON.stringify(data), { headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' }, }); }async function handleKidsStatus(): Promise<Response> { // Simulate some logic (in reality, this would connect to real data) const statuses = ['sleeping ๐ด', 'playing ๐ฎ', 'asking for snacks ๐', 'destroying the house ๐ช๏ธ']; const randomStatus = statuses[Math.floor(Math.random() * statuses.length)];const data = { status: randomStatus, codingWindow: randomStatus.includes('sleeping') ? 'WIDE OPEN' : 'Narrow', recommendation: randomStatus.includes('sleeping') ? 'Deploy now!' : 'Save for later' };return new Response(JSON.stringify(data), { headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' }, }); }
Real Talk
The kids status endpoint is obviously a joke, but the principle stands - your APIs should account for the realities of your development environment!
Deploy to Production (5 minutes)
Test locally first:
npm run dev
Visit http://localhost:8787/api/hello
to test.
When ready, deploy:
npm run deploy
Your API is now live at https://my-worker.your-subdomain.workers.dev
!
Adding Environment Variables
For real projects, you'll need secrets. Add them via Wrangler:
wrangler secret put DATABASE_URL wrangler secret put API_KEY
Update your Env
interface:
export interface Env { DATABASE_URL: string; API_KEY: string; }
Real-World Example: Simple Analytics
Here's a practical endpoint for tracking page views:
async function handleAnalytics(request: Request, env: Env): Promise<Response> { if (request.method !== 'POST') { return new Response('Method not allowed', { status: 405 }); }try { const { page, referrer } = await request.json();// In a real app, you'd store this in a database // For now, we'll just log it console.log('Page view:', { page, referrer, timestamp: new Date().toISOString(), userAgent: request.headers.get('user-agent') });return new Response(JSON.stringify({ success: true }), { headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' }, }); } catch (error) { return new Response('Invalid JSON', { status: 400 }); } }
Performance Tips for SAHDs
- Use Wrangler's local development - it's faster than deploying for every test
- Set up proper TypeScript - catch errors before deployment
- Use environment variables for everything configurable
- Add proper CORS headers if building SPAs
- Log everything - debugging in production is harder when you're interrupted every 10 minutes
Common Gotchas
Memory Limits
Workers have a 128MB memory limit. For SAHD projects, this is usually plenty, but keep it in mind.
Execution Time
10ms for free tier, 50ms for paid. Perfect for API endpoints, not for heavy processing.
Cold Starts
Cloudflare Workers don't have traditional cold starts, but your code still needs to be efficient.
Integration Examples
Frontend Integration
// Simple client-side integration async function fetchKidsStatus() { try { const response = await fetch('https://your-worker.workers.dev/api/kids'); const data = await response.json();console.log('Kids are:', data.status); console.log('Coding window:', data.codingWindow); } catch (error) { console.error('Failed to check kids status:', error); } }
React Hook
import { useState, useEffect } from 'react';function useKidsStatus() { const [status, setStatus] = useState('unknown'); const [loading, setLoading] = useState(true);useEffect(() => { async function checkStatus() { try { const response = await fetch('/api/kids'); const data = await response.json(); setStatus(data.status); } catch (error) { setStatus('probably causing chaos'); } finally { setLoading(false); } }checkStatus(); const interval = setInterval(checkStatus, 30000); // Check every 30 secondsreturn () => clearInterval(interval); }, []);return { status, loading }; }// Usage in component function CodingDashboard() { const { status, loading } = useKidsStatus();return ( <div> <h2>Development Environment Status</h2> <p>Kids are: {loading ? 'checking...' : status}</p> </div> ); }
Next Steps
Now that you have a basic Worker running, consider:
- Add a database - Use Cloudflare D1 for SQLite or connect to external services
- Implement authentication - JWT tokens work great with Workers
- Add rate limiting - Protect your APIs from abuse
- Set up monitoring - Use Cloudflare Analytics or external services
- Create a CI/CD pipeline - Deploy automatically when you push to GitHub
Mission Accomplished!
Congratulations! You now have a fully functional serverless API running on Cloudflare's global network. Time to grab a coffee before the kids wake up! โ
Resources
Remember: The best code is the code that ships. Don't let perfect be the enemy of done, especially when naptime is ticking away! ๐