# Authoring a walking adventure — agent guide (API v1)

You are creating an actual outdoor walking game, not a list of quiz questions.
Use this guide with `/api/v1/openapi.json` and `/api/v1/trail.schema.json`.
Discover these URLs at `/.well-known/agent.json`. Content is plain Dutch by
convention, but all narrative strings belong to the trail rather than the app.

## Start here: a short request is enough

A request such as “Maak een tocht met een [thema] voor [gebied] met behulp van
Speurtocht; zie deze handleiding” is a complete instruction to carry
out the workflow below. Research, create the content and map, save a draft,
validate, repair and publish the finished adventure. Agents **may publish**;
do not ask for a separate publication approval when the request is to create a
playable trail. Do not stop after describing a plan or producing a JSON file.

### An API key is required

Before using the management API, obtain the API key for this deployment. If you
already have it in your environment or secret configuration, use it. **If the key
is not known, ask the user to provide it securely.** Send it as
`Authorization: Bearer <API_KEY>` with every trail-management or asset-upload
request. Never include the key in a URL, trail content or your final report.
You can read this guide and research the adventure while waiting for the key.

### This deployment and its entry points

Use the deployment serving this guide:

- Platform origin: https://sprookjestocht.nl
- Management API base: https://sprookjestocht.nl/api/v1
- API reference: [OpenAPI](https://sprookjestocht.nl/api/v1/openapi.json)
- Complete content contract: [JSON Schema](https://sprookjestocht.nl/api/v1/trail.schema.json)
- Difficulty levels: [Trail-owned level contract](https://sprookjestocht.nl/api/v1/levels)
- Available themes, drawing styles and figure libraries: [Theme catalog](https://sprookjestocht.nl/api/v1/themes)
- Theme style and image examples: follow the selected theme’s `style_url` and actually view its `reference_images`.
- POI icons and matching figure references: follow that theme’s `icons_url`.
- Existing trails: https://sprookjestocht.nl/api/v1/trails
- Management overview: https://sprookjestocht.nl/admin

Resolve all API and asset paths against this origin. A platform name or domain
mentioned in a brief is not an instruction to switch deployments: when this guide
is read on localhost, create the trail on that local deployment. Use another
origin only when the user explicitly selects it as the API target. Never switch
to production automatically if a local request fails. A localhost URL can only be
used by an agent that can reach the same machine; report an access failure rather
than pretending to have created a trail.

### Fill in ordinary choices yourself

Use explicit user requirements first. Otherwise use these starting defaults:

- Language: Dutch. Design for the intended audience. Choose the number of
  difficulty levels and write a short, helpful title and description for each.
  Three levels often suit families; use the brief and `/api/v1/levels` contract.
- Route: choose the distance and number of destinations for the terrain, story
  and a pleasant walking pace. There is no fixed destination quota. Use a separate
  story-only entrance and a satisfying final destination.
- Questions: one fixed question per destination per configured level: N × L
  questions for N destinations and L levels, without reserves or random pools.
  Deliberately balance puzzles, theme knowledge and interesting local facts.
  Research the place yourself; ask the user about the desired balance if unclear.
- Theme: fetch the catalog, its `style_url` and `icons_url`, view the reference images before creating any artwork; choose `fairy_tale` for a fairy-tale brief, `sports`
  for sport, or `rescue` for a rescue-team adventure. The narrative is original
  content; do not create a new application UI theme.
- Collection: use nouns matching that style (fireflies/jar, footballs/trophy,
  stars/badge); start at 0, award 1 for a first-try correct answer and lose up to
  1 for a wrong answer. Use up to 20 optional moving collectibles along the route
  when suitable; `[]` is supported when wild collecting does not fit the brief.
- GPS rules: arrival radius 20 m, maximum accuracy 30 m, location lifetime 30 s.
- Duration: provide `estimated_duration_minutes`, an integer estimate of the
  **whole adventure**, not just walking time. Include time for the intended age
  group to walk the verified route, read the story, discuss and answer questions,
  collect optional finds, and take short breaks. As a starting point for families,
  use about 3 km/h plus 1–2 minutes per question destination and 10–15 minutes for
  the story and exploring; adjust for hills, terrain, crossings and the brief.
  Round to a sensible 5- or 15-minute estimate. Do not present it as field-tested
  or derive it from the straight-line distance between destinations. The app
  shows this separately from distance in the directory and before starting.
- Map: a richly illustrated adventure map in the selected theme’s drawing style, grounded in the verified OSM
  geometry, optimized for mobile. The requested narrative theme must be visible
  throughout the map itself, through characters and story scenes. A clean park
  diagram with themed colors, repeated tree symbols and a decorative border is
  not a finished themed map. Follow the art-direction workflow below; include a
  smaller matching preview and preserve GPS registration.
- Supporting art: a wide `artwork.hero`, a portrait `artwork.story` and a separate
  transparent title logo in `artwork.logo`. Follow the artwork contract below;
  map crops do not count as supporting art.

Do not interview the user about each of these optional choices. State the choices
in the final handover. Ask a concise preference question if the intended audience
or balance of question types remains unclear. Also ask when an essential ambiguity
cannot be resolved from reliable sources, such as two places with the same name.
A location or named theme alone is not a reason to pause.

### Write an invitation into the adventure

Write for the family imagining their day out. Let `summary` be a short,
story-led invitation: evoke the place, introduce the mystery or characters, and
give the family a reason to join in. A few vivid, natural sentences should make
this particular adventure feel worth discovering.

Carry that voice through the opening, story and ending. Let characters, events
and the family's mission bring the adventure to life. Practical planning details
belong in the dedicated configuration fields and directions/access notes; the
app presents those facts and explains how to play. Read the visitor-facing copy
aloud before publishing: it should sound like a storyteller welcoming the family,
rather than an author describing how the trail was assembled.

### Your deliverable and stopping conditions

Create a new trail unless the user explicitly asks to update an existing one.
Choose a descriptive unique slug; list existing trails first and do not overwrite
an unrelated trail with a matching name. For an explicit update, create a new
version of that trail, preserving existing published versions and group progress.

Supply every required field in the JSON Schema: title/area/summary,
`estimated_duration_minutes`, the chosen `levels`, theme choice
and story nouns, collection rules, GPS rules,
start point, registered map and preview, both supporting illustrations and their
alt text, opening/ending/share/photo-frame copy,
access sources, ordered destinations with walking geometry and one nested question per configured level each.
Use `schema_version: 2`; older content formats are not accepted.
`flights` is optional. Obtain local image-generation, mapping or file tools as
needed; the content API stores the finished assets and does not generate artwork
or research a walking route for you. Do not reuse artwork or coordinates from a different real-world area. Never fabricate an asset URL or claim an upload,
source check, validation or publication that did not succeed.

Before publication, check the complete walking route against access sources,
check several known map points against the artwork, perform the visual acceptance
review below, proofread the questions and explanations, then validate through the API. Fix errors and repeat validation;
use the current ETag when replacing or publishing a draft. Once valid and
source-checked, publish and verify the public directory, returned trail URL and
its `/trail-config`. Do not claim the route has been walked or field-tested.

If essential tools, map registration or public access cannot be verified, save the
available content as an **unpublished draft** and report the specific missing work.
Do not mark `access.reviewed` true or publish merely to get past validation.
If the API is unreachable, report that blocker without claiming a saved draft.

Finish in the user's language with: title, area, chosen theme and the configured levels, route
length and destination/question counts, source links and access restrictions,
trail slug/version, actual validation/publication status, and the playable URL
(or draft reference and remaining blockers). All operating instructions belong in
this guide; the human should not have to repeat the API workflow in their prompt.

## The experience to design

A family reads an introduction at home, travels to the start and chooses a group
name and one of the trail’s levels, with no preselected level. The chosen level is
fixed for that group throughout the adventure. GPS unlocks the opening story at a **separate
start point without a question**. Start the timer after the family accepts the
story. Reveal only the next destination and the walking path to it. Within the
configured arrival radius its question appears. Only a correct answer reveals
the following destination. The destination, selected level and published trail version determine exactly
one fixed question. No questions are randomly selected. Answers and explanations are never sent before
they are needed. Celebrations wait for the family to press Continue.

Each first-try correct answer can award collectibles. Wrong answers remove the
configured number, floored at zero; there is no waiting penalty. Optional moving
collectibles fly near the route, with smooth client-side movement. A fresh,
accurate GPS fix is required to collect. Flight proximity is client-authoritative
by design, so scores are a casual family game, not a fraud-proof competition.

The ending, story, theme, POI nouns, collectibles, map, frame text,
scoreboard and share invitation are specific to the trail. The public photo link
invites another family to start on that trail's own subdomain. Existing groups
and photographs remain bound to their original published version when a new
version is published. Records are scoped to that same trail version AND chosen level.

## Resolve the brief before authoring

Use the request, source research and the defaults above; this is not a questionnaire.
Establish: real area and entrance; audience (including mixed families); theme;
walking distance and available time; destination count; finish point; accessibility
needs; collection object/container; narrative goal; land manager and access rules.
For example: a fairy-tale adventure collecting fireflies in a jar, or a rescue
adventure collecting stars for a badge, adapted to the requested area.
These are briefs, not pre-verified walking routes.

## Build a coherent and reachable route

1. Consult OpenStreetMap **and authoritative land-manager access information**.
   Respect private roads, water, barriers, opening hours, permits, protected areas
   and temporary closures. Never guess a shortcut across a road or through water.
2. Choose a distinct start and ordered, publicly reachable POIs. The final POI is
   a satisfying finish and need not return to the entrance. Keep groups off roads
   and away from hazards while reading questions. Prefer adequate GPS reception.
3. Avoid unnecessary backtracking and repeated paths. Reorder, move or replace
   destinations when that produces a coherent route over verified accessible
   connections. A necessary shared entrance path may remain. Check consecutive
   legs for reverse traversal of the same segments. Recompute actual walking
   distance and estimated duration whenever the geometry changes.
4. Supply `approach` as real walking-path geometry for **every** leg: from start
   to POI 1, then from the preceding POI to each next POI. Coordinates are WGS84
   `[latitude, longitude]`, never GeoJSON's reversed coordinate order. The server
   computes length; do not invent a straight segment and call it a footpath.
5. Explain access limitations in `access.notes`, cite an HTTPS source URL and
   supply proper OSM attribution. Set `access.reviewed: true` only after actually
   checking those sources. Do not claim a field survey unless one happened.
   Structural validation cannot establish real-world access; an on-site walk is
   still needed before recommending the trail to visitors.

## Write the story and fixed questions

Use `story.intro_title` and `intro` for the at-home introduction; `title` and
`paragraphs` for the GPS-unlocked opening. Explain the goal, characters, collection
mechanic and finish. Write `completion_title` and `completion` as a payoff to that
same story. `directions` describes the entrance and practical access.
`share_title` invites a new family; `share_text` describes the achievement.
`frame_title` and the two short `frame_lines` appear over the group's photograph.
All copy is **plain text**. No HTML, scripts, CSS, instructions for the application,
external analytics or credentials belong in content.

For each POI you may include a short `description` (shown with its question) and
a practical `navigation_hint` (shown while walking there). Use plain text and
keep the story consistent. After choosing `theme.id`, call
`GET https://sprookjestocht.nl/api/v1/themes/{theme_id}/icons` (replace `{theme_id}` with
the chosen ID). The response contains `icons` and a `default_icon`; each entry has an `id`,
`name`, `description`, small drawn `icon_url`, matching `figure_reference_url`
and fallback `symbol`. Resolve image paths against this guide’s origin and
actually view the figure references. Choose a returned ID for `stops[].icon`,
or omit it for the theme default. Only IDs from the selected theme are accepted;
unknown names, glyphs or another theme’s IDs prevent publication.

Use that same figure type in the illustrated map scene at the corresponding real
POI. Preserve its recognizable appearance; poses, names and story roles may vary.
Paint figures into the landscape with coherent scale, light and surroundings,
rather than pasting icons onto a diagram. Do not invent extra destination figure
types. The small question/navigation/reveal icon comes from the app’s library,
so you do not upload a separate icon or figure field with the trail.

### Levels and questions belong to the trail

Supply root-level `levels`: 1–10 objects with `level`, `name` (max 80 characters)
and `description` (max 500). Number them consecutively from 1, easiest first.
Choose the count and write titles and descriptions that explain the audience and
challenge of this adventure. `/api/v1/levels` explains the contract; it does not
prescribe titles or difficulty. Keep each selected level consistent along the walk.

Each stop has exactly one fixed question for every configured level. N stops and
L levels require **N × L** questions; the story-only start has none. No reserves,
random pools or root-level questions. Give every question `level`, `prompt`, four
distinct plausible `choices`, zero-based `answer_index` and a clear `explanation`.
Check that only one answer is correct; avoid hints from answer length or wording.
Raise difficulty through age-appropriate knowledge, richer connections and more
careful reasoning, rather than obscure facts or longer text alone.

Think about the question mix before writing. Combine engaging puzzles, knowledge
related to the theme, and surprising facts about the actual place. Follow the
user's requested proportions; otherwise choose a suitable balance, and ask the
user when the intended emphasis is unclear. Round proportions sensibly for the
number of questions, considering the experience at each playable level.
Research local history, nature and landmarks yourself using trustworthy sources,
preferably the land manager, museum or local heritage organisation. Do not invent
facts or present fictional scenery as local history. Keep each question connected
to its surroundings or story, and distinguish what players can observe from what
they need to know. The explanation should teach the interesting fact, not merely
repeat the answer. Do not rely on a seasonal sighting or access inside a building.

Record optional `category` (`riddle`, `theme`, `location`) to review the mix. For
`location` questions also supply `source_url`: the HTTPS page supporting the fact.
Sources are stored in the version's authoring content, not exposed as answers
before a group reaches the destination.

Example fragment (complete every stop for both configured levels):

```json
{"schema_version":2,"levels":[
  {"level":1,"name":"Ontdekkers","description":"Korte weetvragen en eenvoudige verbanden."},
  {"level":2,"name":"Kenners","description":"Verdieping en uitdagender redeneren."}
],"stops":[{"position":1,"questions":[
  {"level":1,"prompt":"…","choices":["…","…","…","…"],"answer_index":0,"explanation":"…"},
  {"level":2,"prompt":"…","choices":["…","…","…","…"],"answer_index":1,"explanation":"…"}
]}]}
```

This illustrates nesting only; all other configuration fields are still required.

## Supporting illustrations and a separate title logo

Create **two original narrative illustrations and one transparent title logo in
addition to the navigation map**.
They introduce the adventure before the family starts walking. The app uses:

| Field | Composition | Where it appears | Suggested export |
| --- | --- | --- | --- |
| `artwork.hero` | Wide scene, about 2:1 | Trail catalog and the opening screen, including visitors still at home | 1600×800 or 2000×1000 WebP |
| `artwork.story` | Portrait scene, about 3:4 | “Het verhaal”, the opening story and the public invitation page | 1200×1600 WebP |
| `artwork.logo` | Wide transparent lettering with the exact trail title | Separate layer on the theme’s map scroll (or the upper safe margin for an unframed theme) | About 1800×600 PNG or WebP with alpha |

Use one coherent art direction across both scenes and the map: the same cast,
clothing, palette, lighting, illustrated landscape and motifs from this story.
Design different compositions for their roles. The hero invites the family into
the setting; the portrait shows the protagonist, central mystery or quest object
in a story scene. Show an adventure that families can imagine themselves joining.
Adapt this to the chosen narrative and UI theme; sport and rescue adventures need
their own scenes, not fairy-tale imagery by default. Do not reuse another trail's
illustrations or introduce unrelated characters merely to decorate the page.

The two narrative scenes are **not maps, screenshots, enlarged map crops, photo frames or collages**.
Do not paint a parchment scroll, UI buttons, title text, labels, waypoint numbers
or a border into them. The app places the title and copy separately. The scenes
can be full-bleed and do not need GPS registration. Fictional scenery illustrates
the story; do not imply that an invented castle or bridge physically exists there.

### Title logo

Draw the exact `title` legibly in the selected theme’s visual language. The logo
is lettering with restrained matching decoration, on genuine transparency; no
paper, banner, scroll, panel or background. Keep the complete mark inside the
canvas with a little breathing room. Check the spelling and readability on a
phone, and inspect alpha on both light and dark backgrounds. The app positions
this separate asset on the scroll; never bake it into the navigation map or add
a blank title strip to that map. For an unframed theme the logo occupies the
upper 8% safe margin, so keep essential map content clear there.

Use ratio 1.8–5.5, at least 900×200 pixels, at most 2 MB. A roughly 3:1 mark is a
good default. PNG and extended WebP with an alpha channel are accepted. The API
checks dimensions, separate asset references and alpha metadata; it does not
read the lettering or prove that the background pixels are actually transparent.

### Safe composition for responsive layouts

Design both illustrations to survive resizing and center cropping. The source
image's outer edge is **not a safe place for essential content**. Use the following
safe areas in every adventure, regardless of location, characters or theme.
Coordinates are percentages of the full source image, measured from its top-left:

| Illustration | Horizontal safe area | Vertical safe area | What belongs outside it |
| --- | --- | --- | --- |
| Hero, about 2:1 | x = 25–75% (middle 50% of width) | y = 30–70% (middle 40% of height) | Expendable scenery, atmosphere and supporting decoration |
| Story, about 3:4 | x = 15–85% | y = 10–90% | Background and secondary details that are not needed to understand the scene |

Keep the **entire visible extent** of important faces, heads (including helmets,
hair and horns), quest objects and story-critical gestures inside the relevant
safe area. Putting only an object's center inside it is insufficient. A hand
holding the quest object must remain readable together with that object. Feet,
foliage or a decorative wing tip can extend farther when losing them would not
change the scene's meaning. Avoid placing important elements against the safe
area boundary; leave a little additional breathing room.

For example, in a 2000×1000 hero, essential content belongs between x = 500–1500
and y = 300–700 pixels. In a 1200×1600 portrait, use x = 180–1020 and y = 160–1440.
These are composition guides, not boxes to draw into the illustration. Continue
natural scenery to every edge: no blank bars, artificial padding, borders or
painted safe-area guides. Group the essential subjects around one central focal
scene rather than spreading them across the full width or height.

The hero may appear as a 2:1 card or a wider banner. For the usual 2:1 source,
a centered 4:1 crop removes the top and bottom quarters. Plan for that loss before
generating the image. The portrait is normally shown at its native 3:4 ratio;
its margins also protect against rounded corners and small future layout changes.
These margins improve resilience, but no composition can survive every possible
crop. Inspect the actual delivered images rather than trusting the prompt alone.

Include the aspect ratio, safe-area percentages, focal subjects and forbidden
edge placements explicitly in each image-generation prompt. Do not fix a bad
composition by distorting the image, adding white space or stretching it to fit.
Recompose/regenerate it when necessary. Create two separate compositions rather
than supplying the same image twice or cropping the hero into a portrait.

Before uploading/publishing:

1. Review the hero at its full ratio and as centered 3:1, 3.4:1 and 4:1 crops.
   Check that whole heads, essential objects and gestures remain visible. Treat
   4:1 as a conservative stress check, not a promise about the current app layout.
2. View the hero at about 360 pixels wide and the portrait at 300–360 pixels wide.
   The main characters, quest object and visual action must still be recognizable
   without zooming. Use clear silhouettes and contrast; tiny decorative details
   must not carry essential story information.
3. Inspect the actual catalog, opening screen and story view on a phone and a
   small tablet. Check for awkward cuts, unexpected subject placement, stretching
   and an image that only works at desktop size. A simulated crop alone does not
   replace checking the app.
4. Confirm that both images share the map's cast, palette and illustration style,
   contain no generated lettering/UI, and have alt text describing the actual
   scene. If any check fails, repair the image before publication.

The API checks dimensions and asset references; it cannot certify safe placement,
readability, composition or artistic quality. Do not report those visual checks
as passed unless you actually inspected the pixels and views.

Upload all three assets using the existing authenticated `POST /api/v1/assets` endpoint and
use its returned URLs. Supply short, descriptive Dutch alt text for each scene:

```json
"artwork": {
  "hero": { "image": "<hero upload URL>", "alt": "Een beschrijving van de brede avonturenscène." },
  "story": { "image": "<portrait upload URL>", "alt": "Een beschrijving van de held en het raadsel." },
  "logo": { "image": "<transparent logo upload URL>", "alt": "De volledige naam van de tocht." }
}
```

The placeholders above are not literal asset URLs. Publication requires all three
assets and alt texts (1–240 characters), three different uploaded assets,
and assets distinct from `map.image`/`map.preview`. Hero: ratio 1.8–2.2 and at least
1200×600 pixels. Story: ratio 0.70–0.80 and at least 900×1200 pixels. Each supporting
illustration must be at most 2 MB; prefer WebP and aim for 500 KB or less for fast
mobile loading. No extra preview uploads are needed for these two illustrations.

Inspect the generated pixels and the actual catalog, opening screen and story
view before publishing. Check visual consistency, recognizable characters, the
hero crop and whether each alt text describes the actual image. Structural
validation does not judge artistic quality. If you cannot create these assets,
save an unpublished draft and name the missing work; do not publish placeholders.
Older published trails without this field keep running with an app-owned neutral
theme visual. When updating one, supply both illustrations and the title logo in the new draft;
do not copy that placeholder or a derived map URL into `artwork`.

## Map registration and artwork

### Art direction: make the map part of the adventure

The theme owns the drawing style, figure library, UI and map frame. After choosing
it, fetch `GET https://sprookjestocht.nl/api/v1/themes/{theme_id}/style` (or follow
`style_url`) and the theme’s `icons_url`. Read the style description and map
instructions, then **load and view the reference images and chosen figures**.
Pass these images to your illustration tool with their roles clearly identified:
style examples supply visual language, figure examples supply character identity,
and the verified map of the requested location supplies the geography.

Use the selected theme’s visual language consistently for the map, hero and story
illustration and title logo. Do not copy an example trail’s location, composition, geography,
plot, names or decorative frame. Choose a coherent cast from the figure library,
give them original story roles, and integrate their scenes into the real terrain.
Woodland, dunes, water or urban buildings must retain the actual area’s character.
Fictional characters and structures are story motifs beside verified real places,
not claims that those features exist there or create additional walking access.

For `map_frame: "parchment"`, the app adds the shared curled paper and softly
feathers your artwork along an irregular edge. Upload the illustrated landscape
alone with parchment-compatible colors. Do not bake in another border, scroll,
curled ends, blank inner margin, title strip or frame. The title belongs only in
`artwork.logo`. For `none`, the app displays your canvas without that frame.
The theme does not generate the trail’s illustrations: you must create them using
its style and figure references. A recolored map diagram with separate character
stickers is not a finished themed illustration.

Every adventure begins at a **theme-matched illustrated gate** at the real,
verified start access: for example an enchanted gate, sporting start arch or
rescue gateway, following the selected theme's style instructions. This is the
story-only start, not a question. It must be clearly recognizable on the map and
must not imply a new entrance, water crossing or access through a closed area.

**Every question location must have its own recognizable painted figure or motif
from the selected theme library**, matching that stop's `icon` ID. A handful of
generic decorative scenes is insufficient. Reusing a type at two stops means
painting it at both places; it is not satisfied by one distant example. Integrate
the figures into the landscape close enough to their actual question locations
that the correspondence is clear, while leaving paths and crossings readable.
Several figures may share a larger scene, but each location must still be
identifiable. Check the complete stop list against the actual painted map before
publishing; also verify the matching question/navigation/reveal icon in the app.

Plan the gate and all figures **before** finalizing the visit points. If a scene
cannot fit, first recompose it or use a suitable scale. Where needed, move a visit
point onto a verified accessible part of the route, reorder points, or choose a
better real place. Recheck GPS coordinates, connected approaches, story/question
relevance, logical walking order, distance and duration after any change. Never
move real roads, buildings or water, or place a GPS target somewhere inaccessible,
just to accommodate the painting. Keep the gate separate from the first question.

The illustrations must remain recognizable at normal phone zoom; tiny decorations
only visible in the full-resolution file do not count as the required figures. Keep paths and junctions
clear, with fewer and more subtle strokes than the live route overlay. Use labels
sparingly. Do not bake waypoint numbers, the active route, questions, GPS dots,
score controls or UI buttons into the artwork; the application supplies those.

### Paint over the real map

1. **Build the geographic master first.** Verify the OSM path network, accessible
   bridges, buildings, land cover, water, entrance and visit points. Render a
   clean north-up reference at the final bounds, aspect ratio and projection,
   without pins, labels or UI. Include at least **150 metres of real landscape
   beyond the whole walking route on every side** and keep essential navigation
   and story scenes inside the central **84%** of the canvas. Measure the margin
   in ground metres, accounting for latitude. Record control points at junctions,
   bridge ends, building footprints and bends in the shore, spread across the map.
   Plan a theme-matched gate at the story start and a matching library figure for
   **every** question point; check space and access together.
2. **Edit that actual image; paint over it.** Supply the registered master as the
   edit target, alongside separately identified theme-style and figure references.
   Ask for one continuous painting: sandy tracks belong to the terrain, trees
   follow the real woods and meadows, real buildings become illustrated buildings
   anchored to their actual footprints. Add friendly theme scenes beside the
   real places. Preserve every path centreline, junction, bridge, shoreline and
   building position. Keep the canvas, geographic crop, scale and projection fixed;
   volume in trees and roofs must not shift their ground position. First establish
   a coherent landscape with painted paths, water and architecture; then add the
   gate and figures in small registered regions. Use the actual terrain of the
   new area: the style reference does not turn dunes or city blocks into a forest.
   The old style map supplies appearance only, never a new area's geography.
3. **Compare the painted pixels to the master.** Make a registered transparent
   overlay and inspect the whole route, every junction and crossing it uses, the
   start/finish and distributed control points; also check the surrounding network
   for invented paths or water connections. Inspect buildings and land cover too.
   Check detailed crops and phone readability. A correct GPS transform or unchanged
   bounds alone does not establish that the painting is accurate. Record the
   discrepancies rather than declaring success from the prompt.
4. **Repair locally in the same painting.** Supply a cropped reference and edit
   target for each faulty area, with enough overlap to retain registration and
   context. A numbered copy can specify scene positions, but those guides must
   disappear from the result. Check each figure's ground/contact point, not just
   its visual centre. Preserve already-correct pixels; reject a beautiful regional
   redraw if it shifts a road or bank. Locally blend only its useful painted scene
   into the accepted painting when that preserves geography. Keep blend edges
   narrow and interiors opaque so no pale panels or doubled features appear.
   Review each repair and its seams against the master again. Do not move
   coordinates to fit a distorted painting. Do not use a
   generic painted woodland with technical roads, flat water polygons or building
   blocks laid over it as the finished map: those features must share the painting's
   texture, lighting and linework. Exact vector layers are useful as construction
   guides and QA overlays, not as a substitute for integrated illustrated geography.
5. **Export the landscape, frame and logo separately.** Upload only the painted
   terrain as `map.image`, with a smaller preview of identical composition. It
   reaches every edge: no extra border, title, blank padding or internal paper.
   For `parchment`, use compatible warm colors and let the app add the scroll and
   organic edge fade within the expendable outer 8%. For `none`, the canvas is
   shown without automatic paper/fade. Supply `artwork.logo` separately; the app
   reserves a separate area on the flat paper below the top curl for it, above
   the landscape. Check the composed result,
   while keeping the uploaded map free of a reserved title band or second border.
   Never stretch or change bounds to conceal drift or
   manufacture missing landscape coverage. Resizing/compression are appropriate
   finishing steps, without another generative redraw.

Use an image-generation/illustration tool that accepts the reference as an edit
input, not a text-only reconstruction of the location. Such a tool may still
change geometry; the overlay review and local repairs are mandatory. If suitable
artwork or reliable registration cannot be achieved, save an unpublished draft
and explain what remains rather than publish an inaccurate or plain diagram.
The upload API stores assets; it does not generate or visually certify them.

### Visual acceptance before publishing

Actually open and inspect the finished map and preview, not just the drawing
script, image dimensions or a successful upload. Review the whole composition,
several detailed crops and a phone-sized view with a sample walking leg and pin.
Ask yourself:

- Is the themed start gate clearly visible at the actual entrance, separate from
  the first question? Does **every stop**, checked one by one against `stops[]`,
  have its own matching figure close to its GPS location?
  Keep a short completeness checklist mapping each stop's position, icon ID and
  GPS anchor to a checked crop of the finished painting, including repeated types.
  Check that live navigation pins do not hide the scene's identifying features.
- Without reading the title or seeing the app chrome, is the requested theme
  unmistakable in the map's interior? Can I point to several substantial story
  scenes and explain how they belong to this adventure?
- Does this look like an illustrated adventure rather than a clean cartographic
  diagram with decorative trim? Are the characters and scenic landmarks large
  enough to recognize on a phone, with visual variety across the route?
- Do **all junctions and crossings used by the walk**, the verified entrance,
  distributed control points, clearings, real buildings and the finish still align with the known coordinates? Can a family read the walking route
  clearly without mistaking a decorative feature for a real path?
- Does the entire route have at least 150 metres of illustrated landscape beyond
  it on every side? Are route lines, pins, navigation junctions and important story
  scenes outside the outer 8%, with no essential content lost in the irregular
  fade? Check the framed overview and the route's outermost points on a phone.
- Are there no clipped scenes, unreadable generated text, accidental UI elements,
  stray white edges or differences between map and preview? For a parchment
  theme, inspect the app's framed result as well as the uploaded illustration:
  does it blend naturally onto the paper without a second border or visible seam?

If the map is too neutral, revise the art direction and regenerate or enrich the
illustration before publication. If registration fails, repair that too. Passing
`/validate` checks structure and geometry constraints; it does **not** certify
illustration quality, theme fidelity or actual alignment of the painted pixels.
In the handover, briefly name the main illustrated scenes and describe the visual
and registration checks actually performed. Do not claim a visual inspection that
you did not perform.

### Upload and registration contract

Upload a **PNG or extended WebP (VP8X)** using `POST /api/v1/assets` with a JSON
`data_base64` string. Images must be complete, static files (no APNG/animated WebP). Maximum decoded
size is 8 MB and 16 million pixels; both
image dimensions must be 100–8192 pixels. Use the returned same-origin `url` in
`map.image` or `map.preview`. No server-side URL fetching, SVG, remote scripts,
credentials or arbitrary local filesystem paths are supported.

For the parchment theme, upload the finished **illustration only**, without the
theme's paper or border. An opaque PNG/WebP is fine: the app applies the edge fade.
Use `paper_width = width` and `paper_height = height` for new parchment maps.
`map.bounds` is `[[south,west],[north,east]]` of the **registered inner map**,
not a lat/lon bounding box guessed from the artwork. The projection is Mercator in
latitude and linear in longitude. Preserve OSM geography when illustrating:
landmarks and paths must not move. The painted image is decoration; the overlaid
walking geometry is the navigation source.

`width` and `height` are the logical registered inner canvas. `paper_width` and
`paper_height` describe the full image canvas, with the inner canvas centered.
These describe your uploaded canvas, **excluding the app-owned frame**. Use equal
dimensions for new parchment maps; unequal dimensions are supported for historical
assets that already have centered padding. `image_pixel_ratio` relates logical
coordinates to exported pixels (usually 2). Example: registered canvas 1200×1400,
`paper_width: 1200`, `paper_height: 1400`, full upload 2400×2800 pixels.
The app expands the displayed paper dimensions and supplies framed image URLs in
`/trail-config`. Its `artwork_offset_y` locates the registered canvas below the
reserved logo area; the client projection accounts for this asymmetric margin.
Never copy these derived values back into an authoring document.
The preview is a smaller export of exactly the same composition and aspect ratio.
Use WebP for a reasonable mobile download. Do not request a new AI redraw when
only deterministic compositing or compression is needed.

Set reasonable `max_zoom`, `route_max_zoom` and `start_max_zoom` (zoom levels are
powers of two relative to the logical canvas). The map overview fits the full
border. Trackpad/pinch is continuous. Do not alter registration to change zoom.

Optional `flights` have consecutive IDs starting at 1 and 2+ path points each,
inside bounds and preferably near walking paths, away from the outer map edge.
They are not extra mandatory POIs. `[]` disables moving collectibles.
Choose `theme.id` from the public `GET /api/v1/themes` catalog:
- `fairy_tale`: forest green/gold, sparkles in a glass jar, botanical photo frame.
- `sports`: blue/yellow, football tokens in a trophy, striped photo frame.
- `rescue`: teal/orange, stars in a rescue badge, shield photo frame.

These are application-owned themes, including illustration styles and figure libraries,
tested independently of individual trails. Fetch their current style and figures
from the API; this guide does not maintain a second style brief or icon list.
Do not submit colors, CSS, hero symbols, collection symbols, `visual` or
`container_style`; publication rejects these fields. New styles require app
code and theme tests, never a content API request. Use the closest existing style.
A narrative may feature knights, football or a rescue team without adding a style.
`theme.name`, `stop_singular`, `stop_plural`, collectible nouns and container name
are content. Match these nouns to the selected visual (e.g. balls/trophy for sport,
stars/badge for rescue). Map geography, scenes and stories remain trail-specific; drawing style and figure
types come from the selected application theme.

Example: `"theme": {"id":"sports", "name":"Het kampioensteam",
"stop_singular":"coach", "stop_plural":"coaches"}` and
`"collection": {"singular":"bal", "plural":"ballen", "container":"beker",
"initial":0, "first_try_bonus":1, "wrong_answer_loss":1}`.

Historical published exports may use the former color-based format. For updates
to the **same trail**, clone with `source_version_id` to adapt to the current theme
contract. That parameter cannot clone across trails. For a new trail, submit a new
configuration object, using the reference only to understand its structure.

## API workflow

Base URL for this deployment: `https://sprookjestocht.nl/api/v1`.
All trail-management and asset-upload requests require the owner's fixed API key:
`Authorization: Bearer <API_KEY>`. This includes reading trail/version exports,
creating drafts, uploading assets, validation and publication. Obtain the key from
the operator through the agent's environment or secret configuration, for example
`TRAILS_API_TOKEN`; never invent a key, print it, put it in a URL, save it in trail
content or include it in the final report. Do not try the owner's admin passkey or
browser session as API authentication. Ask the user to supply the key securely
if it is unavailable; independent research may continue, but do not claim an API
write succeeded. A 401 means the key is missing or invalid; a 503 can mean the API
key has not been configured on the server.

The guide, OpenAPI, JSON Schema, theme and icon catalogs, discovery and visitor
gameplay remain public. The admin UI uses the owner's passkey and has no public signup.
Authentication does not change publication validation, immutable versions or
`If-Match` requirements. Agents with the key may publish without a separate human
approval. Public game config still excludes the question bank.

1. `POST /trails` with `{ "slug": "voorbeeld-avontuur", "title": "Een nieuw avontuur" }`.
   These names are examples; choose a slug and title for the requested adventure.
   Slugs are lowercase DNS labels, immutable, unique, at most 50 characters. A
   reserved or existing slug returns an error; inspect it before creating another.
2. `POST /assets` for the full map, matching map preview, wide hero illustration,
   portrait story illustration and transparent title logo (five uploads). Save the returned URLs in
   `map.image`, `map.preview`, `artwork.hero.image`, `artwork.story.image` and `artwork.logo.image`.
3. `POST /trails/voorbeeld-avontuur/versions` with `{ "configuration": { ... } }`.
   An incomplete document may be saved as a draft. For updates to an existing
   trail, use `{ "source_version_id": 123 }` to copy its content to a **new draft**.
4. `GET /trails/voorbeeld-avontuur/versions/124` to read the complete editable document and
   its `ETag` / numeric `revision`. `PUT` to that URL replaces the whole document;
   send `{ "configuration": { ... } }` and `If-Match: "0"` (use the actual ETag).
   A stale revision returns 412; missing If-Match returns 428. Re-read and reconcile
   concurrent edits rather than overwriting them. Drafts are invisible to visitors.
5. `POST /trails/voorbeeld-avontuur/versions/124/validate`. 200 means valid; 422 gives
   `errors` with configuration paths. Resolve all errors. Use the JSON Schema for
   preflight checks and this endpoint for geometric/question-bank checks.
6. `POST /trails/voorbeeld-avontuur/versions/124/publish` with the current `If-Match`.
   Agents **may publish** with the API key. Publication validates
   again and atomically creates the playable POIs/questions, freezes this version
   and switches the trail's current version. Failed validation leaves the current
   public version unchanged. A published version cannot be overwritten; edit a
   new draft. Repeating publication of the same version is harmless with its current
   ETag. There is deliberately no destructive delete endpoint.
7. Verify the directory on this deployment and the trail URL returned by the API.
   Unknown or unpublished subdomains return 404. On a local deployment, use the
   returned `http://<slug>.localhost:<port>/` URL. On a hosted deployment, use its
   returned public subdomain URL. Do not construct URLs for another deployment.
   Wildcard DNS, TLS and proxy routing must be configured by the operator first.

`GET /trails` lists IDs, titles, publication and URLs. `GET /trails/:slug` lists
versions. Management version exports include the answer bank; keep these out of
the public game interface.
An existing published trail may serve as a **structural reference** through these
endpoints. It is not a content template: create the requested area’s own route,
artwork, coordinates, story and questions. Never reuse another area’s map
registration or assume that the reference trail’s characters fit the new brief.

Errors are JSON with `error` and usually `details` (validation endpoint: `errors`).
Typical statuses: 401 invalid/missing API key, 404 unknown resource, 409 immutable version, 412 stale
revision, 413 oversized body, 422 invalid content, 428 missing revision, 503 API not configured or database busy.
