Creating Labs
Creating Tasks
Learn how to create task directories, write assignment instructions, and configure tabs for POV Demo labs.
Task Directory Structure
Each task is a directory inside the lab root with at least two characters whose name begins with a digit. Tasks are read in directory-name order; use zero-padded prefixes such as 01- to make that order clear.
01-exploring-pods/
├── assignment.md # Task instructions with YAML frontmatter
├── setup-ubuntu-1 # Runs before learner starts the task
├── check-ubuntu-1 # Validates learner's work (exit 0 = pass)
└── solve-ubuntu-1 # Provides the solution- Recommended: use two-digit numeric prefixes such as
01-,02-, and03-. - The name after the prefix is descriptive but not shown to learners — only the title in frontmatter is displayed
- For labs with VMs, script files use
{operation}-{vm-name}(for example,check-ubuntu-1).
assignment.md Format
The assignment.md file has two parts: a YAML frontmatter block (between --- delimiters) and the task content in Markdown.
---
slug: "explore-pods"
id: "explore-pods"
type: "challenge"
title: "Explore Running Pods"
teaser: "Use kubectl to inspect pods in a running cluster."
notes:
- type: text
contents: |
Kubernetes Pods are the smallest deployable units. In this task,
you will explore pods running in your cluster.
tabs:
- title: "Terminal"
type: terminal
hostname: ubuntu-1
- title: "Kubernetes Dashboard"
type: service
id: "kubernetes-dashboard"
hostname: ubuntu-1
port: 8001
difficulty: "basic"
skip: false
---
List all pods in the default namespace:
```bash
kubectl get pods
```
You should see the pods created by the lab setup script. Note the STATUS column — all pods should show `Running`.
Describe one of the pods to see its details:
```bash
kubectl describe pod <pod-name>
```# Title) in the Markdown content. The platform can render the title field separately.Frontmatter Fields
The bundle parses these fields and requires delimited frontmatter when it builds a task. For ordinary labs, pov validate silently skips absent or unterminated frontmatter; when it can parse delimited YAML, it rejects service tabs without a valid id. Puzzle labs add their own constraints.
| Field | Enforced by validate | Description |
|---|---|---|
slug | No | Task slug stored in the published task. |
id | No | Task ID. The bundle uses the directory name when this is omitted. |
type | No | Task type stored in the published task. |
title | No | Displayed task title. |
teaser | No | Short task description. |
notes | No | Context blocks with type and contents. |
difficulty | No | Accepted task difficulty metadata. |
enhanced_loading | No | Accepted task loading metadata. |
tabs | No | UI tab configuration. Service tabs require a URL-safe id when validated locally. |
timelimit | No | Task time value. A positive value is required only for the single task in a puzzle lab. |
skip | No | Published task metadata; local validation does not enforce skip behavior. |
Tab Types
| Type | Required Fields | Description |
|---|---|---|
terminal | hostname | Opens a terminal connected to the specified VM. |
service | id, hostname, port | Opens a web service running on the VM at the given port. Local validation requires id to be lowercase alphanumeric/hyphen and not begin or end with a hyphen; other routing fields are optional to that validator. |
code | hostname, path | Opens a file editor for the given path on the VM. |
aws_credentials | — | Shows temporary AWS credentials and opens the AWS Console for the lab session. |
gcp_credentials | — | Shows temporary GCP credentials and opens the GCP Console for the lab session. |
azure_credentials | — | Shows temporary Azure credentials and opens the Azure Portal for the lab session. |
# Terminal tab
- title: "Server Terminal"
type: terminal
hostname: ubuntu-1
# Service tab
- title: "Dashboard"
type: service
id: dashboard
hostname: ubuntu-1
port: 8080
# Code editor tab
- title: "Config File"
type: code
hostname: ubuntu-1
path: /etc/myapp/config.yaml
# AWS credentials tab
- title: "AWS Console"
type: aws_credentials
# GCP credentials tab
- title: "GCP Console"
type: gcp_credentials
# Azure credentials tab
- title: "Azure Portal"
type: azure_credentialsKeep Tasks Focused
Aim for a small, coherent set of steps. Split a task when learners need to hold too much context at once; this is authoring guidance, not a validator rule.
Avoid
One task with 8 steps: “Complete Kubernetes Setup”
- Install kubectl
- Configure kubeconfig
- Create a namespace
- Deploy an application
- Expose a service
- Verify the deployment
- Scale the deployment
- Check logs
Correct
Split into three focused tasks:
Task 1 (3 steps)
- Install kubectl
- Configure kubeconfig
- Verify connectivity
Task 2 (3 steps)
- Create a namespace
- Deploy an application
- Verify the deployment
Task 3 (3 steps)
- Expose a service
- Scale the deployment
- Check logs
