This document defines the official data structure for all camp YAML files.
This contract must not change casually. Rendering logic depends on it.
source/data/camps.yaml is the central registry of all camps.
camps:
- id: string # stable identifier, never changes
name: string # display name
start_date: YYYY-MM-DD
end_date: YYYY-MM-DD
opens_for_editing: YYYY-MM-DD # first date participants can add/edit activities
registration_opens: YYYY-MM-DD # first date the homepage registration banner is shown
registration_closes: YYYY-MM-DD # last date the banner is shown (inclusive)
location: string # place name displayed on the archive page
file: string # filename in source/data/ (e.g. 2026-06-syssleback.yaml)
archived: boolean # true once the camp has ended
qa: boolean | null # optional; true marks a QA-only camp (filtered out in production)
information: string | null # optional descriptive text shown on archive page
link: string | null # optional URL (e.g. Facebook group) shown on archive page
All fields except information, link, and qa are required for each
entry. registration_opens and registration_closes are conditionally
required — see §1.7.
The opens_for_editing field defines the first date on which the add-activity and
edit-activity forms are available. The submission period closes at the end of
end_date + 1 day. Typical default: start_date − 7 days.
The registration_opens and registration_closes fields define the inclusive
date range during which the homepage displays a banner linking to the
registration section for that camp. Both fields are required for non-archived
camps and optional for archived camps (where they are ignored). The range must
satisfy registration_opens <= registration_closes < start_date.
Rules:
active field. See 03-architecture/data-layer.md §2 "Metadata Layer" for the
derivation rules. file field references a YAML file in source/data/. id is permanent and must never change after the camp is first created. Each camp file must follow this structure:
camp:
id: string
name: string
location: string
start_date: YYYY-MM-DD
end_date: YYYY-MM-DD
events:
- id: string
title: string
date: YYYY-MM-DD
start: "HH:MM"
end: "HH:MM" | null
location: string
responsible: string
description: string (markdown) | null
link: string | null
owner:
name: string
email: string
meta:
created_at: ISO-8601 | null
updated_at: ISO-8601 | null
How to read this schema:
string means a text value (e.g. "Schack")boolean means true or false (no quotes)YYYY-MM-DD means a date written as 2026-06-28"HH:MM" means a 24-hour time written as "14:00" (quoted)ISO-8601 means a full datetime string: 2026-06-28T14:00:00| null means the field can be omitted or set to nullSee §7 for a complete worked example.
camp:) idnamelocationstart_dateend_dateidtitledatestartendlocationresponsibledescription — markdown, parsed by marked (same variant as content/*.md). linkownermetaThe owner and meta fields are for internal use only and must never be displayed in any public view.
date must fall within the camp’s start_date and end_date (inclusive). start must use 24-hour format: "HH:MM". end must be "HH:MM". end must be after start. Exception: if end < start (midnight crossing),
the implied duration (24 × 60 − startMinutes) + endMinutes must not exceed
1 020 minutes (17 hours). The combination of:
(title + date + start)
must be unique within a camp file.
Duplicate events are not allowed.
slug-title-YYYY-MM-DD-HHMM
A “slug” is a URL-friendly version of the title: lowercase letters, numbers, and hyphens only (no spaces or special characters). For example, “Middag & dans” becomes middag-dans.
Example ID:
middag-2025-06-30-1630
camp:
id: 2025-08-syssleback
name: SB Sommar Augusti 2025
location: Sysslebäck
start_date: 2025-08-03
end_date: 2025-08-10
events:
- id: schack-2025-08-04-1400
title: Schack
date: 2025-08-04
start: "14:00"
end: "16:00"
location: Samlingssalen
responsible: Anna
description: >
Öppet parti för alla åldrar.
Ta med eget schackbräde om du vill.
**Nybörjare välkomna!**
link: null
owner:
name: ""
email: ""
meta:
created_at: null
updated_at: null
Breaking changes to this structure require:
Fields may be added in future versions. Fields must not be removed without a migration plan.
This contract is the foundation of the system.