Spec schema
spec.yaml is the single source of truth for a GenLabZ project. It defines what the student builds, how it is evaluated, and how it is cleaned up. Every field is validated by the SDK on load.
Project (top-level)
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
id | str | ✓ | — | Unique kebab-case identifier |
title | str | ✓ | — | Project title |
summary | str | ✓ | — | One-liner for catalog cards (~150 chars, plain text) |
purpose | str | ✓ | — | Author-facing pedagogical intent (not student-facing) |
overview | str | ✓ | — | Student-facing introduction; supports markdown. Overridden by content/overview.md if present |
outcomes | list[str] | ✓ | — | Learning outcomes (min 1) |
objectives | list[Objective] | ✓ | — | Goal-oriented groupings of steps (min 1) |
schema_version | str | — | "1.0" | Schema format version |
version | str | — | "1.0" | Project content version |
status | str | — | — | draft / published / archived |
difficulty | str | — | — | beginner / intermediate / advanced |
duration | int | — | — | Estimated minutes to complete |
tags | list[str] | — | — | Searchable tags |
prerequisites | list[str] | — | — | What students need before starting |
thumbnail | str | — | — | Path to thumbnail image in images/ |
recap | str | — | — | Completion summary; supports markdown. Overridden by content/recap.md if present |
next_steps | list[NextStep] | — | — | Suggested follow-on projects and resources |
references | list[Reference] | — | — | Source material links |
platform | Platform | — | — | Platform-specific configuration |
Objective
A goal-oriented grouping of steps.
| Field | Type | Required | Description |
|---|---|---|---|
id | str | ✓ | Two-digit zero-padded identifier, e.g. "01" |
title | str | ✓ | Objective title |
description | str | ✓ | What this objective achieves; supports markdown. Overridden by content/{objective_id}.md if present |
steps | list[Step] | ✓ | Steps to achieve this objective (min 1) |
references | list[Reference] | — | Relevant documentation links |
Step
A discrete, testable action within an objective.
| Field | Type | Required | Description |
|---|---|---|---|
id | str | ✓ | Two-digit zero-padded identifier within the objective, e.g. "01" |
title | str | ✓ | Step title |
instructions | list[str] | ✓ | Student-facing guidance — what to do, not how (min 1) |
inputs | list[str] | — | Handle names from prior steps this step depends on |
outputs | list[Output] | — | Resource handles produced by this step |
Output
A resource handle declared as an output of a step.
| Field | Type | Required | Description |
|---|---|---|---|
name | str | ✓ | Handle name — must follow {OO}_{SS}_{resource_name} format |
type | str | ✓ | CloudFormation resource type (e.g. AWS::S3::Bucket) or "string" |
description | str | — | Human-readable description of the resource |
See Handle wiring for naming rules and how handles flow through the test runner.
Reference
An external link attached to a project, objective, or step.
| Field | Type | Required | Description |
|---|---|---|---|
title | str | ✓ | Human-readable link title |
url | str | ✓ | Valid HTTP/HTTPS URL |
type | str | — | source / documentation / tutorial |
NextStep
A suggested follow-on after completing the project.
| Field | Type | Required | Description |
|---|---|---|---|
title | str | ✓ | What to do next |
type | str | — | project / tutorial / documentation |
ref | str | — | Internal project ID (for GenLabZ projects) |
url | str | — | External URL (for non-GenLabZ resources) |
description | str | — | Why this is a good next step; supports markdown |
Platform
Platform-specific configuration. Currently only AWS is defined.
platform: aws: services: [s3, lambda] regions: [us-east-1] iam_policy: - effect: Allow actions: [s3:CreateBucket] resources: ["arn:aws:s3:::*"]| Field | Type | Description |
|---|---|---|
aws.services | list[str] | AWS service identifiers used by the project |
aws.regions | list[str] | AWS regions the project targets |
aws.iam_policy | list[IAMStatement] | IAM policy statements required for the sandbox role |
IAMStatement
| Field | Type | Required | Description |
|---|---|---|---|
effect | str | ✓ | "Allow" or "Deny" |
actions | list[str] | ✓ | IAM actions (min 1), e.g. s3:CreateBucket |
resources | list[str] | ✓ | Resource ARNs (min 1) |
Enumerated values
status
| Value | Meaning |
|---|---|
draft | Work in progress — not visible to students |
published | Live and available to students |
archived | No longer active — hidden from catalog |
difficulty
| Value | Meaning |
|---|---|
beginner | Minimal prior AWS experience required |
intermediate | Comfortable with core AWS services |
advanced | Deep AWS knowledge expected |
Reference type
| Value | Meaning |
|---|---|
source | Primary source material |
documentation | Official service documentation |
tutorial | Step-by-step guide |
Markdown fields
These fields support markdown formatting and are rendered to students:
overview— project introductionrecap— completion summaryobjective.description— objective narrativenext_steps[].description— why a follow-on is worth doing
Keep summary plain text — it appears on catalog cards where markdown is not rendered.
Content files
Content files in content/ override the corresponding spec field when present. Both are rendered as Markdown. A minimal project works fine with just spec fields; content files add richness when you want more control over formatting, length, or images.
| Spec field | Content file path | Overrides when present |
|---|---|---|
overview | content/overview.md | Yes — file wins over spec field |
recap | content/recap.md | Yes — file wins over spec field |
objective.description | content/{objective_id}.md | Yes — file wins over spec field |
step.instructions | content/{objective_id}_{step_id}.md | Yes — file wins over spec field |
The resolution rule is consistent: when a content file exists for a scope, it takes precedence over the corresponding inline spec field. When neither exists, the field is treated as empty. See Content files for the full authoring guide.
Complete example
schema_version: "1.0"id: s3-static-websiteversion: "1.0"title: "Host a Static Website on S3"summary: "Create an S3 bucket and configure it to serve a static website"purpose: "Learn how to use S3 for static web hosting with public access"overview: | Deploy a static website using **Amazon S3** for hosting. This project covers:
- Creating and configuring an S3 bucket - Enabling static website hosting with an index document - Writing a bucket policy for public read access
By the end, you'll have a live website served directly from S3.outcomes: - "Create and configure an S3 bucket for static website hosting" - "Write and apply an S3 bucket policy for public access"
status: draftdifficulty: beginnerduration: 30tags: ["s3", "static-website", "beginner"]prerequisites: []
platform: aws: services: ["s3"] regions: ["us-east-1"] iam_policy: - effect: Allow actions: [s3:CreateBucket, s3:PutBucketWebsite, s3:PutObject, s3:PutBucketPolicy] resources: ["arn:aws:s3:::*"]
references: - title: "S3 Static Website Hosting" url: "https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteHosting.html" type: documentation
objectives: - id: "01" title: "Create and configure the S3 bucket" description: | Set up an S3 bucket with static website hosting enabled. This objective covers bucket creation with a unique name and configuring the **index document** for website hosting. steps: - id: "01" title: "Create the S3 bucket" instructions: - "Create a new S3 bucket with a unique name" - "The bucket name must be globally unique — use a random suffix" outputs: - name: "01_01_bucket" type: "AWS::S3::Bucket" description: "The S3 bucket for hosting" - id: "02" title: "Enable static website hosting" instructions: - "Configure the bucket for static website hosting" - "Set index.html as the index document" inputs: - "01_01_bucket" outputs: - name: "01_02_website_url" type: "string" description: "The website endpoint URL"
- id: "02" title: "Configure public access" description: | Add a bucket policy to allow public read access to the website. You'll write an IAM policy document that grants `s3:GetObject` to all principals on the bucket's objects. steps: - id: "01" title: "Apply a public read bucket policy" instructions: - "Create a bucket policy that allows s3:GetObject for all principals" - "Apply the policy to the bucket created in objective 01" inputs: - "01_01_bucket" outputs: - name: "02_01_policy" type: "AWS::S3::BucketPolicy" description: "Public read policy on the bucket" references: - title: "S3 Bucket Policy Examples" url: "https://docs.aws.amazon.com/AmazonS3/latest/userguide/example-bucket-policies.html" type: documentation
next_steps: - title: "Add CloudFront distribution" type: project description: "Serve your S3 website through CloudFront for HTTPS and global edge caching."