with one click
quiz-writing
Write engaging, educational quiz posts for DanLevy.net
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
Write engaging, educational quiz posts for DanLevy.net
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
Best practices for Remotion - Video creation in React
Generate and judge DanLevy.net article translations with AI SDK/OpenRouter candidate models, locale-prefixed Astro routes, and full Git provenance. Use when translating posts, adding i18n candidates, judging translations, preserving messy model history, or debugging translated article routing.
Use Langfuse with TypeScript LLM apps, especially Vercel AI SDK, Mastra, and REST API integrations. Trigger when Codex needs to add or debug Langfuse observability for AI SDK generateText/streamText telemetry, OpenTelemetry setup with @ai-sdk/otel and @langfuse/otel, Mastra observability with @mastra/langfuse, Mastra-to-AI-SDK streaming via @mastra/ai-sdk, RESTful management of prompts/datasets/scores/annotation queues, prompt/version metadata, datasets/evals, trace verification, or safe Langfuse environment configuration.
Comprehensive Mastra framework guide for building agents, workflows, tools, memory, workspaces, and storage with current APIs. Use for documentation lookup, API verification, TypeScript setup, common errors, migrations, and `mastra api` CLI tasks: inspect or call resources on local, Mastra platform, or remote servers.
Run iterative DanLevy.net translation eval improvement loops: baseline requested i18n eval commands, inspect raw streams and judge JSON, research prompt/QA ideas, tune prompts, validation, and pre/post-processing, rerun, measure, and record findings without confusing medium polish with hard failures.
Write DanLevy.net articles and blog posts in Dan Levy's voice, structure, humor, technical taste, and Astro MDX conventions. Use when Codex needs to draft, rewrite, expand, polish, or create non-quiz posts for this blog; create matching frontmatter, title/subtitle/tag/category metadata, post directory naming, image concepts, and social/cover image variants. For quiz posts, use the quiz-writing skill instead.
| name | quiz-writing |
| description | Write engaging, educational quiz posts for DanLevy.net |
Write engaging, educational quiz posts for DanLevy.net — an Astro 5 static blog with interactive React quiz components.
---
title: "Quiz: [Topic] Mastery"
subTitle: "[Catchy tagline with wordplay]"
label: "[Short label]"
category: Quiz
subCategory: [Topic]
date: YYYY-MM-DD
modified: YYYY-MM-DD
tags: [quiz, topic, difficulty-levels...]
cover_full_width: [unsplash]-wide.webp
cover_mobile: [unsplash]-square-200.webp
cover_icon: [unsplash]-square-200.webp
---
import Challenge from '../../../components/QuizUI/Challenge';
import QuizUI from '../../../components/QuizUI/QuizUI';
<p class="inset">[Hook paragraph with emoji]</p>
[Intro paragraph describing quiz scope]
<QuizUI>
<Challenge
client:load
index={0}
group="Warmup"
title="Question Title"
options={[
{ text: 'Option A' },
{ text: 'Option B', isAnswer: true },
{ text: 'Option C' },
{ text: 'Option D' },
]}
>
<slot name="question">
<div className="question">
[Question text with code block]
</div>
</slot>
<slot name="explanation">
<div className="explanation">
[Detailed explanation with code examples]
</div>
</slot>
</Challenge>
</QuizUI>
[Closing section with personality]
| Field | Type | Description | Example |
|---|---|---|---|
title | string | Must start with "Quiz: " | "Quiz: JavaScript Error Mastery" |
subTitle | string | Catchy tagline, often wordplay or question | "Are your exceptions truly exceptional?" |
label | string | Short label for UI badges | "Errors", "RegEx", "CSS Fundamentals" |
category | string | Always "Quiz" | Quiz |
subCategory | string | Topic area | JavaScript, CSS, Rust, PostgreSQL, Bash, Cloud |
date | string | Post date (YYYY-MM-DD) | 2025-11-03 |
tags | array | Include quiz + topic + difficulty levels | [quiz, javascript, error-handling, intermediate, advanced] |
| Field | Type | Description |
|---|---|---|
modified | string | Last modified date |
unlisted | boolean | Hide from lists but accessible via URL |
draft | boolean | Hide from build entirely |
redirects | array | Old URLs to redirect here |
social_image | string | Path to social sharing image |
related | array | Related post slugs |
popularity | number | 0-1 score for sorting |
At least one cover image is needed. Most quizzes use three variants:
cover_full_width: [filename]-wide.webp
cover_mobile: [filename]-square-200.webp
cover_icon: [filename]-square-200.webp
Some older quizzes also include a cover field (square format).
Naming conventions:
photographer-name-XXXX-unsplash-wide.webp, photographer-name-XXXX-unsplash-square.webppsychedelic-shell-wide.webp, elephant-synthwave-gym-square-200.webpdesktop-social.webp, mobile.webp (some quizzes use these in social_image)Cover credit (optional, for Unsplash photos):
cover_credit: Photo by <a href="https://unsplash.com/@photographer">Name</a> on <a href="https://unsplash.com/photos/...">Unsplash</a>
<Challenge
client:load // Required: Astro React hydration directive
index={0} // Required: Zero-based question number
group="Warmup" // Required: Category grouping for this question
title="Question Title" // Required: Short descriptive title
options={[ // Required: Array of Option objects
{ text: 'Option A' },
{ text: 'Option B', isAnswer: true },
{ text: 'Option C', hint: "Optional hint text" },
]}
difficulty={2} // Optional: 1-5 numeric scale (used in Rust & AWS quizzes)
objectives={[ // Optional: Learning objectives (used in Rust & AWS quizzes)
"Understand concept X",
"Identify pattern Y",
]}
>
Note on client:load: The vast majority of quizzes use client:load. Only the oldest quiz (JavaScript Promises, 2019) uses client:only="react" on some Challenges. Always use client:load for new quizzes.
The Option type (from src/components/QuizUI/types.ts):
type Option = { text: string; isAnswer: boolean; hint?: string };
text (required): The displayed option textisAnswer (required): Exactly one option must have isAnswer: truehint (optional): Per-option hint shown when user selects that wrong answerEvery Challenge has two required slots and one optional slot:
<slot name="question">
<div className="question">
What does `JSON.stringify(error)` return?
```js
const error = new Error('Oops');
console.log(JSON.stringify(error));
```
<slot name="explanation">
<div className="explanation">
Error objects have non-enumerable properties (`message`, `name`, `stack`), so
`JSON.stringify()` returns `{}`. Use `JSON.stringify(error, Object.getOwnPropertyNames(error))`
or create a plain object instead.
</div>
</slot>
There are two hint styles used across quizzes. Pick one per question, don't mix both.
Style A: Per-option hints (used in Rust & AWS quizzes). Hints are attached to individual wrong-answer options:
options={[
{ text: 'Wrong A', hint: "Think about what happens after a move" },
{ text: 'Wrong B', hint: "Once moved, can we still use it?" },
{ text: 'Correct answer', isAnswer: true },
{ text: 'Wrong C', hint: "Rust catches these at compile time" },
]}
Style B: Hints slot (used in older JS quizzes, 2024 era). An empty or content-filled <slot name="hints"> block:
<slot name='hints'>
<div className="hint">
Think about enumerable properties on Error objects.
</div>
</slot>
Or an empty hints slot (just the tags with no content):
<slot name='hints'>
</slot>
Prefer Style A (per-option hints) for new quizzes. Style A is more engaging because hints are specific to the wrong answer the user selected, not generic. Style B with an empty slot just means "no hint for this question."
Good (PostgreSQL quiz — playful insider tone):
Did this make you frustrated, even angry? You're not alone! To quote an unnamed "core" database contributor, "what the hell, Dan?! I crashed on the type questions! Thats violent sir!" 😈 You're welcome.
Good (Bash quiz — irreverent but educational):
I know. It's wild how quickly escaping makes strings tough to parse. Imagine escaping other languages in Bash strings — with all those quotes, apostrophes and
$symbols to f*ck you up. 🫠
Good (Short subtitle wordplay):
"Are your exceptions truly exceptional?" "(Borrow) check yo self before you wreck yo self! 🦀" "Can you navigate the cloud labyrinth?"
Use emojis sparingly but effectively. Prefer 1-3 per section, not per question:
| Emoji | Usage |
|---|---|
| 🐘 | PostgreSQL |
| 🦀 | Rust |
| 💥 | Errors / explosions |
| 🚨 | Errors / warnings |
| 🤖 | Bots / automation / "these aren't your typical questions" |
| ✨ | Features / "no signup required" |
| 🍀 | Luck / "good luck" |
| 🏆 | Achievements / scoring |
| 🤔 | Thinking / questioning |
| 🤯 | Mind-blowing |
| 🕵️♂️ | Detective / "identify the invalid one" |
| 😈 | Tricky / diabolical questions |
| 🫠 | Frustration / melting |
| 💪 | Strength / challenges |
| 🔥 | Hot takes |
| ⬇️ | "Jump in below" |
backticks for code references inlineShow code, ask what it produces:
<slot name="question">
<div className="question">
What does `JSON.stringify(error)` return?
```js
const error = new Error('Oops');
console.log(JSON.stringify(error));
```
Options: Actual output values, common misconceptions, error messages.
List several items, one is fake/invalid. Often uses :
<slot name="question">
<div className="question">
Which of these is <em class="highlight">NOT</em> ❌ a valid PostgreSQL type?
(Seriously, these are (mostly) real types.)
</div>
</slot>
Options: 5-7 real items + 1 plausible-sounding fake. These questions typically have more options (5-8).
Show variations of syntax, ask which works:
<slot name="question">
<div className="question">
How are variables defined in Bash?
</div>
</slot>
Options: Correct syntax + common mistakes (spaces, wrong operators, etc.)
Describe a scenario, ask about runtime/compile behavior:
<slot name="question">
<div className="question">
What happens with multiple mutable references?
```rust
fn main() {
let mut wisdom = String::from("He who laughs at");
let ref1 = &mut wisdom;
let ref2 = &mut wisdom;
ref1.push_str(" himself never runs");
ref2.push_str(" out of things to laugh at.");
}
Think about Rust's rules for mutable references.
```Ask about concepts, best practices, or when to use something:
<slot name="question">
<div className="question">
When should you use Rc (Reference Counting) in Rust?
</div>
</slot>
// Simple — most quizzes
{ text: 'Option text' }
// Correct answer
{ text: 'Option text', isAnswer: true }
// With per-option hint (Rust/AWS style)
{ text: 'Wrong answer', hint: "Think about X..." }
// Multiple correct (RARE, only when intentional)
{ text: 'TypeScript error', isAnswer: true }
{ text: 'null', isAnswer: true }
Wrong answers should be:
name = Dan with spaces in Bash)Examples of good wrong answers:
JSON.stringify(new Error('Oops')): '{"message":"Oops","name":"Error"}' — what you'd expect but isn't true"$name=Dan" — common mistake of using $ prefixc {} — looks valid but <c> isn't an HTML elementipv4 — so intuitive it must exist, but doesn't; inet covers both IPv4 and IPv6isAnswer: true per question (unless intentionally multi-answer — see below)Only use when there are genuinely two valid answers. Explain why in the explanation:
options={[
{ text: 'TypeScript error', isAnswer: true },
{ text: "'null'", isAnswer: true },
{ text: 'undefined' },
]}
This was used in the Destructuring quiz for a TypeScript question where ignoring type errors gives different runtime behavior. Use sparingly — most questions should have exactly one correct answer.
Attached to wrong-answer options. Shown as tooltips when user clicks that wrong answer after the first wrong attempt (IGNORE_HINTS = 1).
options={[
{ text: 'Wrong A', hint: "Think about what happens to 'philosopher' after it's moved" },
{ text: 'Compilation Error', isAnswer: true },
{ text: 'Runtime Error', hint: "Rust catches these issues at compile time" },
{ text: 'null', hint: "Rust doesn't have null values" },
]}
Hint writing principles:
{ text: "DynamoDB credits for Green Vendors", hint: "Really?" })Used in older JavaScript quizzes (2024 era). Can be empty or contain a single hint div:
<!-- Empty hints slot (no hint for this question) -->
<slot name='hints'>
</slot>
<!-- With hint content -->
<slot name='hints'>
<div className="hint">
Think about enumerable properties on Error objects.
</div>
</slot>
Short (2-4 sentences, for straightforward questions):
<slot name="explanation">
<div className="explanation">
The `age` property does not exist on `person`, so `age` will be `undefined`.
Definitely not `Infinity` 😅
This results in:
```plaintext
Name: Dan Levy, Age: undefined
```
Medium (1-2 paragraphs, for intermediate questions):
<slot name="explanation">
<div className="explanation">
Error objects have non-enumerable properties (`message`, `name`, `stack`), so
`JSON.stringify()` returns `{}`. This is a common gotcha when sending errors
in API responses. Use `JSON.stringify(error, Object.getOwnPropertyNames(error))`
or create a plain object instead.
</div>
</slot>
Long (multiple paragraphs + code examples, for advanced/Rust topics):
<slot name="explanation">
<div className="explanation">
This code fails to compile because of Rust's ownership rules. When we assign
`philosopher` to `greeting`, the ownership of the String is moved to `greeting`.
After this move, `philosopher` is no longer valid to use.
Here are three ways to fix this:
1. Clone the string (creates a new copy):
```rust
let greeting = philosopher.clone();
let greeting = &philosopher;
let greeting = &philosopher[..];
Each solution has different use cases and performance implications.
```js`, sql, ````rust, bash`, html, ````plaintext)[Learn more about RegExp flags](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#advanced_searching_with_flags)
Common link targets:
Groups organize questions into thematic sections displayed in the quiz UI.
"Warmup" → "Basic [Topic]" → "[Topic]" → "Advanced [Topic]" → "[Topic] Gotchas"
JavaScript Error Quiz — descriptive/thematic names:
PostgreSQL Quiz — topic + prefix pattern:
Regex Quiz — skill-level progression with humor:
Bash Quiz — concise topic names:
Rust Quiz — conceptual groupings:
Used with the difficulty prop on a 1-5 scale:
| Level | Meaning | Example |
|---|---|---|
| 1 | Warmup/Trivia | "What does S3 stand for?" |
| 2 | Basic | "Basic variable declaration in Bash" |
| 3 | Intermediate | "Mutable borrowing rules" |
| 4 | Advanced | "Lifetime annotations on structs" |
| 5 | Expert | "Zero-cost abstractions / memory layout" |
Used in Rust and AWS quizzes for pedagogical structure:
<Challenge
client:load
index={0}
group="Ownership"
title="Basic Move Semantics"
difficulty={2}
objectives={[
"Explain Rust's ownership rules and move semantics",
"Identify compilation errors related to moved values",
"Apply solutions to fix move-related compilation errors"
]}
>
When to use difficulty + objectives: Add them when the quiz covers a structured learning progression (Rust, AWS, databases). Skip for casual knowledge quizzes (regex, CSS, destructuring).
Always specify the language:
```js // JavaScript
```ts // TypeScript
```sql // SQL / PostgreSQL
```rust // Rust
```bash // Shell / Bash
```html // HTML
```css // CSS
```json // JSON
```plaintext // Plain output / no syntax
Use backticks for:
err.nameJSON.stringify()??, ?., ||=undefined, null, truefont-size, align-contentVARCHAR(100), timestamptz<p class="inset">Ready to test your [topic] skills? [emoji]</p>
This quiz covers [scope description]: from [basic concept] to [advanced concept].
Good luck! 🍀
### Think you know [topic] inside and out?
* **Test your expertise!** 💥
* No login or signup required. ✨
* Multiple choice. 🤖 ... _These ain't your typical questions!_
<p class="inset">Or is it your <em>Symphony of Destruction?</em></p>
This quiz will test your knowledge of [topic]: from "basic" [concept] to [advanced concept].
Jump right in to the warmup — prove your skills! 👇
> **Part 1 of 2.** [Go to Part 2](/quiz-postgres-sql-mastery-pt2/)
<p class="inset">PostgreSQL 🐘 Is easily my favorite Database!</p>
This quiz covers a mix of familiar and lesser-known features...
<p class="inset">Ready to test your Rust memory management skills? 🦀</p>
This quiz will challenge your understanding of Rust's ownership system, borrowing rules, lifetimes, and smart pointers.
**Note:** The questions are formatted in ~50-column width to ensure readability across all devices.
Whether you're a seasoned Rustacean or just getting started, this quiz will help reinforce your knowledge. **Let's dive in!** 🦀
Use markdown headers or styled paragraphs to break up long quizzes:
# Dizzying Types
I'm sure you've used _so many_ types in PostgreSQL, right?
The next few questions are about Postgres' v17 native types. 🤯
For each question, identify the **one invalid type**. 🕵️♂️
<p class="inset">Onward!</p>
# TypeScript Ahead
Section breaks serve as transitions — add context about what's coming next.
## Master the Art of Error Handling
From serialization gotchas to cross-context instanceof failures, these advanced concepts separate junior developers from ~seasoned~ damaged professionals.
Ready for more challenges? Check out our [complete quiz collection](/challenges/) for additional brain teasers on JavaScript, algorithms, and more!
<p className="inset">Did my Bash Quiz leave you in shambles?</p>
Let me know in the comments below!
### Further Reading
Brush up on your skills:
- [Bash Guide](https://www.gnu.org/software/bash/manual/bash.html)
- [BashFAQ](http://mywiki.wooledge.org/BashFAQ)
- [ShellCheck](https://www.shellcheck.net/)
Well done! You went deep on several areas of PostgreSQL! 🐘
I hope you learned something new, or at least got a score to gloat about! 🏆
<p class="inset">Check out [Part 2](/quiz-postgres-sql-mastery-pt2/) for more Postgres fun! 🚀</p>
Want more thrills in life? Check out my [Quiz Collection](/challenges/) for endless* fun!
Thanks for taking the quiz! If you enjoyed testing your Rust knowledge, check out my other [programming challenges](/challenges/)! 🧠
**Want to level up your Rust skills?** Here are some recommended resources:
- [Rust Book - Chapter 4: Ownership](https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html)
- [Rust By Example - Memory Management](https://doc.rust-lang.org/rust-by-example/scope.html)
All closings should include a link to /challenges/ (the quiz collection page).
After writing a quiz, verify:
title starts with "Quiz: "category is exactly QuizsubCategory matches the topictags includes quiz + topic keywords + difficulty levelsclient:load directive (NOT client:only)index values are sequential starting from 0isAnswer: true option (unless intentionally multi-answer)question and explanation slotsgroup and title props are present on every Challenge<slot name="..."> syntaxclassName (not class) is used in JSX/MDX# Type check
bun run check
# Validate quiz structure (checks question numbering)
bun run fix-quizzes
# Build to verify no errors
bun run build
# Generate quiz question screenshots for social images
bun run screenshots
bun run screenshots
getCollection("posts") directly — use PostCollections from @/shared/postsCachepublic/_redirects — use frontmatter redirects arrayisAnswer: true in one question (unless intentional and explained)client:load directive on Challengesclass in JSX — use className insteadclient:only="react" (legacy, use client:load)bun run fix-quizzes before committingclassName not class in JSX/MDX/challenges/ in closing sectionssrc/content/posts/YYYY-MM-DD--quiz-[topic-slug]/
├── index.mdx # Quiz content
├── [cover]-wide.webp # Full width cover image
├── [cover]-square-200.webp # Mobile cover (200px)
└── [cover]-square-300px.webp # Icon cover (300px, optional)
Some quizzes also include:
desktop-social.webp — social sharing imagemobile.webp — mobile social sharing imageannotated-code/ — subdirectory with annotated code imagesUse the pattern: YYYY-MM-DD--quiz-[descriptive-slug]
Examples:
2025-11-04--quiz-advanced-js-error-mastery2024-11-27--quiz-postgres-sql-mastery-pt12024-11-15--quiz-regex-or-wreckage2024-12-28--quiz-is-your-memory-rusty2024-11-20--quiz-bash-in-the-shellThe import paths are relative to the post's location:
import Challenge from '../../../components/QuizUI/Challenge';
import QuizUI from '../../../components/QuizUI/QuizUI';
These paths assume posts are in src/content/posts/YYYY-MM-DD--slug/ (3 levels deep from src).
Hints attached to individual wrong answers, shown after the first incorrect attempt:
options={[
{ text: 'Wrong A', hint: "Think about what happens after a move" },
{ text: 'Compilation Error', isAnswer: true },
{ text: 'Runtime Error', hint: "Rust catches these at compile time" },
]}
Hint behavior: After 1 wrong attempt (IGNORE_HINTS = 1), subsequent wrong selections that have hints will show the hint as a tooltip. This means the first wrong answer never shows its hint — only the second+ wrong answers do.
For structured learning quizzes, add difficulty and objectives:
<Challenge
client:load
index={0}
group="Ownership"
title="Basic Move Semantics"
difficulty={2}
objectives={[
"Explain Rust's ownership rules and move semantics",
"Identify compilation errors related to moved values",
"Apply solutions to fix move-related compilation errors"
]}
>
When to use: Add these for quizzes that teach a structured curriculum (Rust, AWS, databases). Skip for casual knowledge quizzes (regex, CSS, destructuring).
Some questions intentionally have multiple correct answers:
options={[
{ text: 'TypeScript error', isAnswer: true },
{ text: 'null', isAnswer: true }, // Runtime behavior differs from TS expectation
{ text: 'undefined' },
]}
When to use: Only when there are genuinely two valid answers (e.g., TypeScript says one thing, runtime says another). Always explain in the explanation why there are two correct answers.
For multi-part quizzes, link between parts:
> **Part 1 of 2.** [Go to Part 2](/quiz-postgres-sql-mastery-pt2/)
Always include these tag categories:
quizjavascript, rust, css, postgresql, bash, regex, aws, clouderror-handling, memory-management, destructuring, s3, dynamodbintro, beginner, intermediate, advanced, expertExamples:
tags: [quiz, javascript, error-handling, intermediate, advanced]
tags: [quiz, javascript, intro, esnext, features, intermediate]
tags: [quiz, rust, memory-management, ownership, borrowing, lifetimes, intermediate, advanced]
tags: [quiz, aws, cloud, storage, databases, s3, dynamodb, rds, elasticache]
tags: [quiz, bash, scripting, shell, linux, beginner, intermediate, advanced]
The frontmatter is validated against this Zod schema (from src/content.config.ts):
z.object({
title: z.string(),
subTitle: z.string().optional().default(""),
label: z.string().optional(),
social_image: image().optional(),
commentsKeyOverride: z.string().optional(),
publish: z.boolean().optional().default(true),
draft: z.boolean().optional(),
unlisted: z.coerce.boolean().optional(),
hidden: z.coerce.boolean().optional(),
date: z.coerce.string().optional(),
modified: z.coerce.string().optional(),
minReleaseDate: z.coerce.date().optional(),
cover: image().optional(),
cover_full_width: image().optional(),
cover_mobile: image().optional(),
cover_icon: image().optional(),
category: z.string().optional(),
subCategory: z.string().optional(),
tags: z.array(z.string()).optional(),
popularity: z.number().min(0).max(1.0).optional(),
related: z.array(z.string()).optional(),
redirects: z.array(z.string()).optional(),
})
Key observations:
title is the only truly required field (everything else has defaults or is optional)title, category: Quiz, subCategory, date, tags, and cover imagessubTitle defaults to "" — set it to something catchy