Skip to content

Writing a Blueprint

A blueprint is one markdown file defining one unit completely. Here’s the whole process, in the order that actually works.

  1. From _eidos/Framework.md, take three things: the Schema, the naming convention, and the target collection’s flavors.

    This matters even if you wrote the framework, because it drifts. It matters more for an agent, which must never assume a collection or section name — the standard has a skill read the framework from the root, never from a copy of its own.

  2. The collection’s default unless you have a reason. Start light: micro in the software seed, sketch in book, note in research.

    Then read that flavor’s shape file for the body. A blueprint on a lighter flavor is never faulted for sections only a fuller one carries. More →

  3. For its title, in the framework’s convention — kebab-case unless your framework says otherwise.

    Convention A blueprint file A group folder For
    kebab-case (default) resume-playback.md playback/ readable everywhere: no escaping, no %20, and the filename is the id
    TitleCase ResumePlayback.md Playback/ space-free, capitalized
    Title Case Resume Playback.md Playback/ a tree that reads like prose, at the cost of %20 in every link

    An absent naming key means kebab-case.

    Whichever you picked: _eidos/ is always lowercase, README.md keeps the name every tool already looks for, the id is always kebab-case, a grouping property’s value matches its folder exactly, and fields meant for tools are never names in the tree.

  4. From the properties that apply to that collection — not every property in the Schema. A specs-only property never lands on a frame.

    ---
    id: resume-playback # kebab-case, permanent, never renamed
    title: Resume Playback
    summary: Returns a viewer to the exact second they stopped.
    type: feature
    domain: playback # matches the sub-folder exactly
    status: Intake
    date_created: 2026-06-20
    date_modified: 2026-06-23
    depends_on:
    - "[Watch a Video](../playback/watch-a-video.md)"
    tags: [playback]
    ---

    Write summary as one plain line: what this blueprint is. It’s the source for the collection’s index.md listing, verbatim. A blueprint with none is flagged by the index, never invented for you.

  5. Not top to bottom. This order:

    1. The opening section## Intent in the software seed. Why this exists, the problem, and who has it. One or two paragraphs.
    2. The non-goals section## Out of Scope. Yes, second. Why →
    3. Open questions — what you don’t know yet. Writing these down early is most of the value of writing the blueprint early.
    4. Everything else — behaviors, dependencies, testing, decisions.

    Keep the shape’s order and names in the file; this is just the order to think in.

  6. Where a shape asks for labels, use them. In the software seed, each acceptance criterion is AC1:, AC2: — bold, and unique within the blueprint.

    ## Behaviors & Acceptance Criteria
    ### Functional
    - **AC1:** A viewer opens a video and the player loads with its title,
    channel, and controls.
    - **AC2:** The viewer can play, pause, and seek anywhere within the video.
    ### Performance
    - **AC5:** Playback starts within a couple of seconds on a normal connection.

    Keep each one short and checkable. Push rich detail into a table or a sub-section the criterion points at. A criterion you can’t verify isn’t a criterion; it’s a hope.

  7. Leave a section out rather than leaving it empty. An empty heading claims you considered something and found nothing to say; an absent one is honest about what you skipped.

One convention governs the whole root, and changing it later means renaming files — so it’s settled at init. Everything a human reads in the tree follows it: top-level docs, collection and sub-folders, blueprint files.

Five things hold regardless of which one you chose:

  • _eidos/ is always lowercase.
  • README.md keeps its name, whatever the convention — every tool already looks for it.
  • The id is always kebab-case.
  • A grouping property’s value matches its folder exactly.
  • Fields meant for tools are not names in the tree.

Reference other blueprints with links, not bare names — in prose and in properties.

The text is the human title; the path is the target’s filename in the framework’s convention. Only a Title Case root carries %20 — which is most of why kebab-case is the default. Add a #heading anchor for a section.

See [Resume Playback](resume-playback.md#intent) for the saved-position rules.

In YAML, quote them — a leading [ starts a list otherwise:

depends_on:
- "[Watch a Video](../playback/watch-a-video.md)"

This is the convention that separates a blueprint worth keeping from a folder of forms:

The sections are a scaffold for a living blueprint, not a form to pour text into. If a blueprint reads like filled-in boilerplate, reshape it until it reads like someone wrote it.

Within and beneath the shape’s sections, use whatever makes the meaning clearer: sub-headings, tables, lists, small diagrams. The shape constrains the skeleton, not the prose.

From the shipped Blueprint example — a subset of YouTube:

Blueprints/specs/playback/watch-a-video.md
---
id: watch-a-video
title: Watch a Video
summary: play a video reliably, signed in or not, adapting to the connection.
type: feature
domain: playback
status: Intake
depends_on: [video-catalog, cdn-delivery]
---
# Watch a Video
## Intent
A view is the core action of the whole product. If a video is slow to start
or stalls, the viewer leaves — so what "playing a video" means, and what a
viewer can count on, is the first thing to pin down.
### Assumptions
Assuming adaptive-bitrate delivery over the CDN is available and affordable
at launch scale — if it isn't, the whole playback approach changes.
## Open Questions
- How long should a signed playback URL stay valid before it has to refresh?
- Does a view count on play start, or only after a watch-time threshold?
## Behaviors & Acceptance Criteria
### Functional
- **AC1:** A viewer opens a video and the player loads with its title,
channel, and controls.
- **AC3:** A signed-out viewer who opens a shared link can still watch.
### Quality attributes
- **AC7:** A stalled segment recovers by dropping quality rather than
stopping playback.
## Out of Scope
- No comments, ratings, or next-up recommendations on the watch page.

Read the Assumptions line again. “If it isn’t, the whole playback approach changes.” That sentence is the blueprint earning its keep — it names the thing that would invalidate the rest, so the next person knows what to check.