CF-TUTORIAL
95 questions. AI grading. Know Cloudflare or get roasted.
Problem: You think you know Cloudflare. You've read the docs. You've deployed a Worker. But do you actually understand the platform?
Solution: 95 questions across 24 categories. Answer in your own words. Workers AI judges you. No multiple choice safety net.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β CF-TUTORIAL β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€ β β β βββββββββββββββ ββββββββββββββββ βββββββββββββ β β β SvelteKit βββββΆβ Worker βββββΆβ Workers β β β β Frontend β β + D1 β β AI β β β βββββββββββββββ ββββββββββββββββ βββββββββββββ β β β β β β β β β β β β βΌ βΌ βΌ β β βββββββββββββββ ββββββββββββββββ βββββββββββββ β β β Quiz UI β β Progress β β Llama β β β β 95 Questionsβ β Tracking β β 3.1 8B β β β βββββββββββββββ ββββββββββββββββ βββββββββββββ β β β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
HOW IT WORKS
1. PICK YOUR POISON
Full quiz (95 questions), Quick mode (20 random), or drill a specific category.
2. WRITE YOUR ANSWER
No multiple choice. Type what you know. The AI doesn't care about perfect wording.
3. GET JUDGED
Llama 3.1 compares your answer to the reference. Core concept right? You pass.
4. ASK FOLLOW-UPS
Confused? Ask the AI to clarify. It knows the Cloudflare docs better than you.
24 CATEGORIES
// 24 categories, 95+ questions
const categories = [
"Workers Fundamentals", // V8 isolates, CPU limits, handlers
"Execution Context", // waitUntil, lifecycle
"Workers KV", // Eventually consistent storage
"Durable Objects", // Strong consistency, WebSockets
"D1", // SQLite at the edge
"R2", // S3-compatible object storage
"Queues", // At-least-once delivery
"Service Bindings", // Worker-to-Worker RPC
"Workflows", // Durable execution
"Agents SDK", // AI agent framework
"MCP", // Model Context Protocol
"Browser Rendering", // Headless Chrome
"Containers", // Run any runtime
"AI Gateway", // AI proxy & guardrails
"Workers AI", // Edge inference
"Vectorize", // Vector database
"Hyperdrive", // Database connection pooling
"Pipelines", // Event ingestion
"Pages", // Static + functions
"Wrangler", // CLI tooling
"HTMLRewriter", // Streaming HTML transforms
"Smart Placement", // Auto-optimization
"System Design", // Architecture patterns
"Gotchas" // Common pitfalls
]; AI EVALUATION
Your answer goes to Llama 3.1 8B running on Workers AI. It's lenientβif you got the core concept, you pass.
// data.remote.ts - Server-side AI evaluation
import { flashcards } from '$lib/flashcards';
export async function evaluateAnswer(
questionId: string,
userAnswer: string,
platform: App.Platform
): Promise<{ correct: boolean; feedback: string }> {
const question = flashcards.find(f => f.id === questionId);
if (!question) throw new Error('Question not found');
const response = await platform.env.AI.run(
'@cf/meta/llama-3.1-8b-instruct',
{
messages: [
{
role: 'system',
content: `You are evaluating quiz answers about Cloudflare.
Compare the user's answer to the reference answer.
Be lenient - if they got the core concept right, mark correct.
Respond with JSON: { "correct": boolean, "feedback": "brief explanation" }`
},
{
role: 'user',
content: `Question: ${question.question}
Reference: ${question.answer}
User's answer: ${userAnswer}`
}
]
}
);
return JSON.parse(response.response);
}
export async function askFollowUp(
questionId: string,
followUp: string,
platform: App.Platform
): Promise<string> {
const question = flashcards.find(f => f.id === questionId);
if (!question) throw new Error('Question not found');
const response = await platform.env.AI.run(
'@cf/meta/llama-3.1-8b-instruct',
{
messages: [
{
role: 'system',
content: `You're a Cloudflare expert. The user just answered a quiz question and wants clarification. Be concise but thorough.`
},
{
role: 'user',
content: `Original question: ${question.question}
Reference answer: ${question.answer}
User's follow-up: ${followUp}`
}
]
}
);
return response.response;
}SVELTE 5 STATE
Pure Svelte 5 runes. No external state library. Progress persists in localStorage.
// quiz-store.svelte.ts - Svelte 5 reactive state
import { flashcards, type Flashcard } from './flashcards';
class QuizStore {
questions = $state<Flashcard[]>([]);
currentIndex = $state(0);
answers = $state<Map<string, UserAnswer>>(new Map());
mode = $state<'full' | 'quick' | 'category'>('full');
get current() {
return this.questions[this.currentIndex];
}
get progress() {
return this.answers.size / this.questions.length;
}
get categoryScores() {
const scores = new Map<string, { correct: number; total: number }>();
for (const [id, answer] of this.answers) {
const q = flashcards.find(f => f.id === id);
if (!q) continue;
const cat = scores.get(q.category) ?? { correct: 0, total: 0 };
cat.total++;
if (answer.correct) cat.correct++;
scores.set(q.category, cat);
}
return scores;
}
startQuiz(mode: 'full' | 'quick' | 'category', category?: string) {
this.mode = mode;
this.currentIndex = 0;
this.answers.clear();
if (mode === 'quick') {
// Random 20 questions
this.questions = shuffle(flashcards).slice(0, 20);
} else if (mode === 'category' && category) {
this.questions = flashcards.filter(f => f.category === category);
} else {
this.questions = [...flashcards];
}
}
}
export const quiz = new QuizStore();SAMPLE QUESTIONS
Workers Fundamentals
"What runtime do Cloudflare Workers use and why?"
Durable Objects
"When would you choose Durable Objects over KV?"
Gotchas
"What happens if you return a Response after calling waitUntil?"
System Design
"Design a rate limiter using Cloudflare primitives."
ALCHEMY DEPLOYMENT
One file. Zero config. D1, Durable Objects, Workers AIβall wired up.
// alchemy.run.ts - Zero-config Cloudflare deployment
import alchemy from "alchemy";
import { D1Database, DurableObjectNamespace, Worker } from "alchemy/cloudflare";
const db = await D1Database("cf-tutorial-db", {
migrationsPath: "./migrations"
});
const doNamespace = await DurableObjectNamespace("quiz-sessions");
await Worker("cf-tutorial", {
name: "cf-tutorial",
entrypoint: "./worker/index.ts",
compatibilityDate: "2024-01-01",
bindings: {
DB: db,
QUIZ_SESSIONS: doNamespace,
AI: { type: "ai" }
}
});STACK
| Layer | Tech |
|---|---|
| Frontend | SvelteKit 5 + Tailwind CSS 4 |
| Backend | Cloudflare Workers |
| Database | D1 (SQLite at the edge) |
| AI | Workers AI (Llama 3.1 8B Instruct) |
| State | Svelte 5 runes + localStorage |
| Deploy | Alchemy (zero-config Cloudflare) |
RESULTS BREAKDOWN
Category-by-category scores. See exactly where you're weak. The quiz tells you what to study.
βββββββββββββββββββββββββββββββββββββββ β YOUR RESULTS β βββββββββββββββββββββββββββββββββββββββ€ β Workers Fundamentals ββββββββ 8/8β β Durable Objects ββββββββ 4/6β β Workflows ββββββββ 4/8β β Gotchas ββββββββ 1/5β βββββββββββββββββββββββββββββββββββββββ€ β STUDY: Gotchas, Workflows β βββββββββββββββββββββββββββββββββββββββ
RUN IT YOURSELF
git clone https://github.com/acoyfellow/cf-tutorial.git cd cf-tutorial bun install echo 'ALCHEMY_PASSWORD=your-password' > .env bun run dev
WHY THIS EXISTS
I kept forgetting the edge cases. "What's the CPU limit again?" "When does KV actually propagate?" Reading docs doesn't stick. Being wrong in front of an AI does. The embarrassment is the learning.
PROVE YOU KNOW CLOUDFLARE
95 questions. No excuses.
START THE QUIZ