Lab Anatomy
A lab lives in a directory under the course’slabs/ folder:
lab.yaml
The lab manifest. Every field maps to a behavior in the lab runtime.INSTRUCTIONS.md
What the learner sees in the instructions panel. Markdown format.scaffold/
The starting code. Everything inside this directory is copied to the learner’s workspace when the lab starts. This is what they’ll edit.Designing Labs
What to Give vs. What to Leave Blank
The scaffold should be a working skeleton with holes. The learner fills the holes.Give them
Give them
- Project structure (package.json, directory layout)
- Boilerplate they shouldn’t waste time on (imports, config, server setup)
- Utility functions not related to the teaching point
- Database schemas or seed scripts
- Test files (they don’t write tests — they pass them)
- Comments or TODO markers where they need to write code
Leave blank
Leave blank
- The core implementation (the thing the lesson just taught)
- Logic that requires understanding the concept
- Integration between components (if composition is the lesson)
The 80/20 Scaffold Rule
The scaffold should be 80% complete. The learner writes the 20% that matters — the part that demonstrates understanding.- If the scaffold is 50% complete, the learner is fighting boilerplate
- If it’s 95% complete, the lab is too easy and they learn nothing
Progressive Labs
When labs build on each other, useworkspace: continue:
workspace: fresh. The scaffold is a clean start.
Scaffolding Patterns
The TODO pattern
The TODO pattern
The stub pattern
The stub pattern
The partial pattern
The partial pattern
Service Configuration
Presets
The lab system has built-in presets for common services. Just use the name:postgres:16-alpine on port 5432 with default credentials.
Available presets:
| Preset | Image | Port | Default Credentials |
|---|---|---|---|
postgres | postgres:16-alpine | 5432 | user: postgres, pass: postgres |
redis | redis:7-alpine | 6379 | (none) |
mysql | mysql:8-oracle | 3306 | root: root, db: lab |
mongo | mongo:7 | 27017 | (none) |
rabbitmq | rabbitmq:3-management-alpine | 5672 | guest / guest |
kafka | confluentinc/cp-kafka:7.6.0 | 9092 | (requires zookeeper) |
zookeeper | confluentinc/cp-zookeeper:7.6.0 | 2181 | (none) |
localstack | localstack/localstack:latest | 4566 | s3, sqs, sns, dynamodb, lambda |
minio | minio/minio:latest | 9000 | minioadmin / minioadmin |
Custom Services
Override preset defaults or define entirely custom services:When to Use Services
Database labs
postgres, mysql, mongo
Caching labs
redis
Message queue labs
rabbitmq, kafka + zookeeper
AWS-like labs
localstack (S3, SQS, DynamoDB, etc.)
File storage labs
minio
If the lab doesn’t need external services (pure frontend, algorithm exercises), omit the
services field entirely. No containers, faster startup.Setup Commands
Setup commands run sequentially after the scaffold is copied and services are healthy:Order Matters
Commands run in order. Later commands can depend on earlier ones:Idempotency
Setup commands should be idempotent — running them twice shouldn’t break things. This matters forworkspace: continue labs where setup runs again but the database might already have data.
Good: CREATE TABLE IF NOT EXISTS
Open Files
Opening Strategy
Instructions Design
Structure
Task Writing
Tasks should be:- Concrete: “Implement the POST /users endpoint” not “Add user creation”
- Ordered: Task 2 builds on Task 1
- Testable: Each task maps to one or more test assertions
- Verb-first: “Create,” “Implement,” “Connect,” “Add,” “Fix”
Hint Writing
Hints help without solving. They point to files, mention useful APIs, or clarify requirements:Difficulty Calibration
A lab should take 5-15 minutes.- More than 15 minutes means too many tasks or tasks that are too complex
- Less than 5 minutes means the lab is trivial
Lab Lifecycle
Understanding the lifecycle helps you design labs that work reliably.
Key implications:
- Services must be healthy BEFORE setup runs (setup may need the database)
- Setup commands run AFTER scaffold is copied (npm install needs package.json)
- Test command runs in the workspace directory (paths are relative to scaffold root)
- Workspace persists between test runs (the learner’s edits are preserved)
Example Lab: Database CRUD
Complete Lab Example
Complete Lab Example
Course Architecture
Design lesson-lab rhythm and arcs
Writing Lessons
Master triggers and narration