Twelve design docs (00-vision through 11-command-nexus) plus assets and the wishlist, authored ahead of implementation. Claude-Session: https://claude.ai/code/session_018BjQRYBR6jQja3jCRi5S3A
61 lines
8.0 KiB
Markdown
61 lines
8.0 KiB
Markdown
# Board Templates
|
|
|
|
> **Status: settled.** The template inventory is settled (inherit all ten from the pathfinder, more to come); the definition format and the storage story below are signed off.
|
|
|
|
## Inventory (settled)
|
|
|
|
All ten pathfinder templates carry over: Basic, Classic Kanban, Software Project, Content Pipeline, Job Hunt, Sales Pipeline, Weekly Planner, Roadmap, Event Planning, Bug Tracker — each with its existing lane titles, icons, palette icon colors, board icon, and blurb. Basic stays first and remains the plain To Do / Done scaffold. The set is expected to grow.
|
|
|
|
## Definition format (settled)
|
|
|
|
**A template is itself a board.** Each template is a schema-valid board folder bundled in the app's resources — the same fractal `folder + index.md` structure, loadable by the same `BoardLoader`, validated by the same rules:
|
|
|
|
```
|
|
<app bundle>/Templates/
|
|
├── basic.kanban/
|
|
│ ├── index.md ← title: Basic; template: {order: 100}; body = picker blurb
|
|
│ ├── 3f2a9c41-…/index.md ← lane "To Do" (order: 1024)
|
|
│ └── 8d3b1f22-…/index.md ← lane "Done" (order: 2048)
|
|
├── classic-kanban.kanban/
|
|
│ └── …
|
|
```
|
|
|
|
- The template board's `index.md` carries the picker metadata in its ordinary frontmatter: `title` = display name, `icon`/`iconColor` = the board icon shown in the picker and inherited by the new board, and the **body** = the blurb (shown in the picker *and* becoming the new board's description, as in the pathfinder).
|
|
- One picker key: `template:` — a mapping holding picker concerns; **`order` (display position in the chooser) is its only subkey** (settled — future subkeys possible). Carried onto instantiated boards, where it is ignored and preserved like any unknown key; specified in the core schema's board table (01-storage-format.md).
|
|
- The bundle folder name (`basic.kanban`) is the template's stable slug (tests, a11y ids).
|
|
- Lane folders are ordinary GUID folders with ordinary `order`/`icon`/`iconColor` frontmatter. Templates *may* contain starter cards — a capability the Swift-struct format never had (e.g. a "How this board works" card).
|
|
|
|
### Instantiation
|
|
|
|
Creating a board from a template: copy the tree — **skipping tombstoned items** (Save as Template already strips them, but hand-dropped user templates can carry them; a new board isn't born with trash) — **mint fresh GUIDs** for every lane/card folder, stamp `created`/`modified` fresh (the stated exception to 01-storage-format.md's copies-keep-`created` rule — a new board is born today, not forked from the template), seed the save panel's suggested name from the template title, and **set the new board's `title` to the user-chosen document name** (per 01-storage-format.md's board-naming rule, so display name and folder name start out matching). The `template:` key is kept — inert on an ordinary board. **`.git` is never copied** — a template is content, not history, and a hand-dropped user template that carries one must not produce boards that are silently in git mode (06-history-undo.md's no-silent-auto-init; adoption applies to boards the user opens, not boards the app materializes): every new board starts at mode `none`. Beyond the `template:` residue, the result is indistinguishable from a hand-built board.
|
|
|
|
### Why this format
|
|
|
|
- **Dogfood**: the template format *is* the board format — no second schema, no parallel Swift model to keep in sync. The picker's mini per-lane preview renders from a real `BoardModel` via the normal loader. **One bad template never fails the chooser** (the user store is hand-editable, so a malformed board there is one edit away): a user template the loader rejects is still listed — by folder name, marked unloadable, carrying the loader's fail-fast specifics — but can't be instantiated or previewed; fix the files and it comes back. The same honest-surfacing posture as 02-architecture.md's welcome recents, which don't pre-detect broken boards either.
|
|
- **Authorable**: adding a template = adding a folder (a human, or an agent, can author one without touching Swift); a template diff in review shows real frontmatter, not struct literals.
|
|
- **Testable for free**: template validity is enforced by the loader's own fail-fast rules at test time (walk `Templates/`, load each).
|
|
- **Opens the door** to user-defined templates — see Save as Template below.
|
|
|
|
## Save as Template
|
|
|
|
A "Save as Template" function copies the current board into the user templates store; the chooser lists user templates after the bundled ones. **The copy is preceded by the close flush** (02-architecture.md ▸ Windows: editor saves, then the pending auto-commit — with the pull-style mechanical exception committing an open Edit session's on-disk saves as-is, sessions staying open), so the template never misses the last keystrokes; the same rule covers File ▸ Duplicate (03-board-ui.md), where the flush also keeps the copied `.git`'s history from lagging its tree. Because a template *is* a board, the copy is nearly literal: **`.git` is not copied** (a template is content, not history — copying it would embed the board's full repo, every attachment version included, in the template store; see 06-history-undo.md's repo-growth note), tombstoned items are dropped, a `template:` key is added — or, when the board already carries one (e.g. it was itself instantiated from a template), its stale `order` is overwritten — with an order appended after existing user templates; GUIDs are left as-is (instantiation mints fresh ones anyway), and timestamps are kept per 01-storage-format.md's copies-keep-`created` rule (equally inert — instantiation restamps them).
|
|
|
|
Two edges, settled:
|
|
|
|
- **Store collisions auto-rename, Finder-style** (`Board.kanban` → `Board 2.kanban`) — the 01 import precedent: saving never overwrites an existing template and never refuses.
|
|
- **Strays copy through.** The copy is literal apart from the stated exclusions (`.git`, tombstoned items) — `CLAUDE.user.md`, a seeded `.gitignore`, and other non-schema files carry through Save as Template *and* instantiation alike. Deliberate: a template is the folder, and `CLAUDE.user.md` carrying a board's custom agent instructions into boards born from it is a feature. The app-owned `CLAUDE.md` copies inertly and self-heals to the current guide version when the new board is opened (08-agent-integration.md).
|
|
|
|
**Storage (settled): Application Support** (`…/Lanework/Templates/`, inside the app container) as the canonical store — friction-free sandbox writes, no location ceremony — kept honest by a **Reveal in Finder** affordance in the template chooser: revealed, it's plain board folders, hand-editable and agent-writable, and a board folder dropped in becomes a template — **no `template:` key required**. Chooser order: bundled templates by `template.order`, then keyed user templates by `template.order`, then keyless user boards last, sorted by display name (`title` ?? folder name — 01-storage-format.md's board naming). The app never stamps a key into store files it didn't write itself — a hand-dropped board is never touched, and adding a key by hand is how its user picks a position; the one writer of keyed files is Save as Template, whose own copies arrive keyed (above). A user-visible or user-configurable location was considered and set aside as ceremony disproportionate to a secondary feature; revisit if template sharing becomes a real workflow.
|
|
|
|
## Rejected alternative
|
|
|
|
Keeping the Swift-struct catalog (pathfinder approach). Simpler to ship, but it's a second definition of "a board" that must track schema changes by hand, can't hold starter cards naturally, and forecloses non-programmer template authoring.
|
|
|
|
## Settled
|
|
|
|
- **No dialect, one schema**: bundled (and user) templates use GUID folder names like any board — no relaxed template-only format.
|
|
|
|
## Open questions
|
|
|
|
None currently — the storage location is settled (Application Support as the canonical store, kept honest by Reveal in Finder; a user-visible or configurable location was set aside as ceremony, revisit if template sharing becomes a real workflow).
|