Working with these docs
What belongs here
Section titled “What belongs here”This repo describes behaviour: what the product does, the domain rules, data and sync
formats, APIs, and decisions that bind more than one platform. How a platform implements
that behaviour stays in its own repo (vulture-ios/Docs, vulture-android/docs,
vulture-web/docs).
| Put it in | When it is |
|---|---|
docs/features/<area>/<id>.md | a user-facing feature (one page each, with the feature: status block) |
docs/domain/ | a calculation both apps must get identical |
docs/data/ | stored or synced data, file formats, links |
docs/api/ | an endpoint, ours or a third party’s |
docs/accounts/ | subscriptions, entitlements, sign-in |
docs/decisions/ | a settled decision, with its date and scope |
docs/analyses/<yyyy-mm>-<slug>/ | the analysis of a feature before it is built |
Analysing a feature
Section titled “Analysing a feature”- Copy
docs/analyses/_template.mdtodocs/analyses/<yyyy-mm>-<slug>/index.md. In Claude Code, from this repo: “Analyse <feature> for iOS and Android.”CLAUDE.mddescribes the steps. - The analysis reads both codebases, writes the behaviour spec, and moves shared rules
into
domain/,data/orapi/. - The owner answers the open questions, and the
statusbecomesagreed. - In each platform repo: “Implement
../vulture-docs/docs/analyses/<slug>.” - When it ships: update the feature page’s status block (with
since), and set the analysis toshipped.
Frontmatter
Section titled “Frontmatter”Every page needs a title; don’t add an H1. The other fields are optional:
description: One sentence.scope: shared | ios | android | web # for decisions and platform notesstatus: draft | agreed | building | shipped | superseded # analysesorigin: vulture-android/docs/x.md # set when a page was moved herefeature: # feature pages only area: Flight map paid: true ios: { status: done, since: "4.1.0", paths: [Packages/Flights], notes: optional } android: { status: partial, since: unreleased, paths: [feature/flightmap] } web: { status: n/a }since is the marketing version a feature first shipped in, one of the versions in
src/data/releases.json. While a feature is usable on main but in no build yet, it is unreleased; a
feature that is built but switched off has no since until it is switched on. A TestFlight or
Google Play testing build counts as shipped. The iOS releases and
Android releases pages are built from it.
The platform sessions set unreleased as part of the work (their CLAUDE.md says so). The
deploy lanes of vulture-ios and vulture-android then stamp it after every upload:
node ../vulture-docs/scripts/release.mjs <ios|android> <version> --build <n> # or: pnpm release …It turns that platform’s since: unreleased into the version, adds the build (and a new version) to
src/data/releases.json, and commits only those files in vulture-docs, without pushing. Options:
--date yyyy-mm-dd (default today, UTC) and --no-commit.
Link pages with relative .md paths (../data/sync-schema.md#4-deterministic-ids), which
work both on disk and on the site.
Screenshots
Section titled “Screenshots”A feature page shows its screenshots under the status table, one tab per platform: iPhone, iPad,
Mac, Watch and Android, light only. src/data/screenshots.json names, per feature (its path under
docs/features/, without .md) and platform, the source image in the app repos next to this one.
pnpm screenshots copies them, scaled down as WebP, into src/assets/screenshots/ and removes the
ones the file no longer names. Run it after the apps regenerate their images, then build.
The sources today are the App Store captures in vulture-ios/fastlane/source-screenshots/ (the
paywall crops there are Mac views) and the Roborazzi test images in
vulture-android/**/src/test/screenshots/, which show screens without the map.
Running the site
Section titled “Running the site”pnpm installpnpm dev # http://localhost:4321pnpm build # fails on invalid frontmatter