docs: reconcile documentation against the code; add a supersession ledger

Five weeks of undocumented evolution left the docs describing a site that
partly no longer exists, with nothing marking which documents were historical.
The code is treated as the source of truth throughout; every claim below was
verified against code, config or the Makefile rather than inferred.

Two mechanisms, following patterns the repo already used:

- docs/reference/superseded-decisions.md (new) — one authoritative table of all
  14 reversals: what was planned, where, what is true now, when, and why. Plus
  a short list of decisions that were NOT reversed, since their planning docs
  are old enough to look suspect.
- Inline "> **Superseded ...**" notes at each stale claim, so a claim can never
  be read un-corrected. This mirrors the existing "> History:" notes in
  architecture.md and "> **Changed 2026-07:**" in trip-switching.md.

Scope split by tense: present-tense docs (CLAUDE.md, reference/, guides/,
README.md, CONCEPTS.md) are corrected; past-tense records (plans/, specs/,
milestones/, summary.md, pm-analysis.md) are annotated only, never rewritten —
their staleness is what makes them records.

Present-tense corrections:

- CLAUDE.md asserted css-compiled/ is generated from css/style.css and
  css/tokens.css. That source relationship does not exist: css/ is hand-authored
  and served directly via assets.addCss in partials/base.html.twig, while
  css-compiled/ is esbuild output from the CSS imports inside js/src/*.js.
  Highest-severity finding — an always-loaded file inviting a hand-edit of a
  generated bundle.
- README.md documented every remote-* target without the -test/-prod suffix
  guard-env requires, so its entire server runbook was unrunnable, and listed
  7 of ~20 targets while CLAUDE.md designates it authoritative for the full
  list. Rewritten with all targets, grouped, and the suffix rule stated.
- README.md told readers to "git clone" into user/, which is a submodule.
- architecture.md: nav is Home + Trips + (authenticated) New Post, not
  "Home + Past Trips only"; template tree omitted trips.html.twig,
  post-form.html.twig and forms/, and placed base.html.twig at templates/ root
  rather than in partials/; entry-actions has three API routes, not just delete;
  added the undocumented css-compiled/maplibre-gl.css output and a section on
  the /post pin editor as the one sanctioned non-entry-map map.
- design-system.md: documented 13 colour tokens against 19 in tokens.css
  (missing --color-error, --color-draft-accent and four glass overlays); claimed
  "all 3 map templates"; and described --color-canvas as "white".
- design-system-light.md documented a light palette in present tense. No light
  mode exists — tokens.css has a single :root block, no prefers-color-scheme or
  data-theme switch, and no light hex appears in css/. Banner added.
- posting.md said photos were optional; they are required, 1-6. It documented
  hero_image, which was removed for entries (stories keep it). It had no mention
  of the frontend edit flow or photo editor, both shipped 2026-07-08. Photo
  files are photo-01..NN, zero-padded.
- working/README.md advertised summary.md as the project's "current state" while
  summary.md describes Leaflet, /tracker, /map and /stats. Most misleading line
  in the tree.
- CLAUDE.md: recorded js/src/location-map.js as the one sanctioned exception to
  the single-map-path rule, and documented that make start/setup fail on a clean
  checkout because docker-compose.yml still builds a travel-memories service
  whose source moved out in a80b0a9.

Also: 2026-07-23-post-form-location-override.md read "Not started" while merged
in user/ as dd19995; status corrected.

Findings that are not documentation problems — the compose breakage, a
repeatable drift check, the unused shortcode-gallery-plusplus, and demo fixtures
for retired views — are collected in
docs/working/2026-07-25-doc-drift-recommendations.md and deliberately not acted
on. Design and verification method: docs/working/specs/2026-07-25-docs-reconciliation-design.md

The submodule gitlink is deliberately not bumped.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-25 00:13:37 +02:00
co-authored by Claude Opus 5
parent e79275a3ab
commit 8202d2a257
18 changed files with 616 additions and 63 deletions
+73 -18
View File
@@ -1,18 +1,23 @@
# Posting a Journal Entry
Two ways to post: the **mobile form** at `/post` (quick, phone-friendly) or the **Admin panel** at `/admin` (drafts, scheduling, editing).
Two ways to post: the **mobile form** at `/post` (quick, phone-friendly) or the **Admin panel** at `/admin` (scheduling, bulk edits). The `/post` form also **edits** existing entries — see below.
---
## Quick start — mobile form
1. Open `/post` on your phone (login required)
2. Fill in **Title** and **Content** (required)
3. Tap **Get Location** → fills Lat/Lng automatically
4. Tap **Get Weather** → fills weather fields using your coordinates
5. Type **City** and **Country** (optional but nice)
6. Attach photos (optional) — first photo becomes the hero image
7. Tap **Submit** → entry appears in the feed immediately
2. **Attach 16 photos** — photos come first because they anchor what you write. **At least one is required**; the form collapses them into a summary bar once uploaded
3. Fill in **Title** and **Content** (required)
4. Tap **Get Location** → fills Lat/Lng, then reverse-geocodes City + Country for you
5. Tap **Get Weather** → fills weather fields using those coordinates
6. Optional: open **More location details** to search for a place by name, or drag the pin on the map to place it exactly
7. Optional: open **More options** for transport mode, publish state, connector and highlight toggles
8. Tap **Submit** → entry appears in the feed immediately
> **Photos are mandatory (16).** This changed during the 2026-07 post-form work — an entry with no
> photo will not submit. The first photo in the grid is the hero; reorder by dragging to change it.
> See [`../reference/superseded-decisions.md`](../reference/superseded-decisions.md) → R7, R8.
---
@@ -20,14 +25,20 @@ Two ways to post: the **mobile form** at `/post` (quick, phone-friendly) or the
| Field | Required | Notes |
|---|---|---|
| Photos | ✅ | **16 per entry.** HEIC is converted to JPEG in the browser. First photo = hero; drag to reorder |
| Title | ✅ | Entry headline |
| Content | ✅ | Markdown body |
| Date | ✅ | Defaults to now — adjust if posting later |
| Lat / Lng | — | Filled by Get Location; used for map marker |
| City | — | Shown as `📍 Kyoto, Japan` on feed cards |
| Country | — | Combined with City in location badge |
| Lat / Lng | — | Filled by Get Location, by place search, or by dragging the map pin |
| City | — | Auto-filled by reverse geocoding after Get Location; shown as `📍 Kyoto, Japan` on feed cards |
| Country | — | Combined with City in the location badge |
| Weather | — | Filled by Get Weather (Open-Meteo, free, no key) |
| Photos | — | All uploaded files appear in the gallery; first = hero |
| How I got here | — | `transport_mode`: walking · bicycle · bus · train · car · plane |
| Published | — | Advanced. Default **Yes**. Set No to keep a draft, or to unpublish on edit |
| Force connector line | — | Advanced. Default No. Forces a map connector to this entry even when suppressed |
| Featured highlight | — | Advanced. Default No. Opts the entry into the home highlights grid |
The advanced three sit behind **More options**. There is **no `hero_image` field** — see the note above.
**Weather descriptions** (must be one of these if entered manually):
`Sunny` · `Partly cloudy` · `Cloudy` · `Foggy` · `Drizzle` · `Rain` · `Snow` · `Thunderstorm`
@@ -40,8 +51,9 @@ Two ways to post: the **mobile form** at `/post` (quick, phone-friendly) or the
Browser → /post (post-form.md)
└─ Grav Form plugin validates fields
└─ cache-on-save injects parent from site.active_trip
└─ add-page-by-form plugin
├─ writes user/pages/01.trips/<active_trip>/01.dailies/<slug>/entry.md
└─ and sets overwrite_mode: edit when edit_path is filled, else false
└─ add-page-by-form plugin (patched — see deploy/patches/)
├─ writes user/pages/01.trips/<active_trip>/01.dailies/<slug>.entry/entry.md
└─ moves uploaded photos into the page folder
└─ cache-on-save plugin
└─ calls $grav['cache']->deleteAll() → entry visible immediately
@@ -55,16 +67,22 @@ Example: `2026-07-20-0930-first-day-in-kyoto.entry`
```
user/pages/01.trips/denmark-2026/01.dailies/
└─ 2026-07-20-0930-first-day-in-kyoto.entry/
├─ entry.md ← frontmatter + markdown body
├─ temple.jpg hero image (or set hero_image in frontmatter)
└─ market.jpg ← additional gallery image
├─ entry.md ← frontmatter + markdown body
├─ photo-01.jpg ← first in order, so this is the hero
└─ photo-02.jpg ← additional gallery image
```
Photos are stored as `photo-01…NN` in display order — the numbering *is* the order, so reordering in
the form renames files on disk, and `photo-01` is always the hero. Names are **zero-padded** so
lexical sort matches numeric order (otherwise `photo-1, photo-10, photo-2…`); the pad width grows for
100+ photos. `PhotoRenumberer` in `cache-on-save` is the single source of truth for this invariant and
is shared with `entry-actions`.
---
## Admin panel — drafts and scheduling
Use the Admin panel at `/admin` for drafts, scheduled posts, or editing existing entries.
Use the Admin panel at `/admin` for **scheduling** (`publish_date`) and bulk or structural edits. For ordinary edits — text, photos, location, publish state — the `/post` form is quicker; see [Editing an entry](#editing-an-entry).
1. Log in at `/admin`
2. **Pages → Add Page**
@@ -96,7 +114,36 @@ Every entry supports these frontmatter fields:
| `location_country` | string | e.g. `Japan` |
| `weather_desc` | string | One of the allowed values above |
| `weather_temp_c` | number | Celsius, displayed rounded |
| `hero_image` | string | Filename to pin as hero (e.g. `temple.jpg`); auto-selects first image if blank |
| `transport_mode` | string | `walking` · `bicycle` · `bus` · `train` · `car` · `plane` |
| `force_connect` | bool | Force a map connector line to this entry even where it would be suppressed |
| `featured` | bool | Opt into the home page highlights grid |
> **No `hero_image` on journal entries.** The hero is whichever photo sorts first
> (`entry-journal.html.twig` uses `entry.media.images|first`), which the owner controls by
> reordering photos. **Stories still use `hero_image`** — they are not posted through this form.
> See [`../reference/superseded-decisions.md`](../reference/superseded-decisions.md) → R7.
---
## Editing an entry
The `/post` form doubles as the editor — you do not need Admin for ordinary edits.
1. Open the entry (or find it in the feed) while logged in
2. Use the entry's **Edit** action → `/post` opens pre-filled, with the hidden `edit_path` set to that
entry's path
3. Existing photos load into the grid. You can **add**, **remove**, and **drag to reorder** them
4. Submit → `cache-on-save` sets `overwrite_mode: edit`, so the entry is rewritten **in place**
rather than creating a new dated folder
Photo files on disk are renumbered to `photo-1…N` to match the displayed order, so the first photo is
always the hero. Reordering is a real file rename, handled server-side by `PhotoRenumberer` in the
`entry-actions` plugin via `POST /api/v1/entry/{slug}/photos/order`.
To **unpublish** an entry, edit it and set **Published** to No under *More options*.
Deleting an entry is also an entry action (`DELETE /api/v1/entry/{slug}`), owner-only and scoped to
the active trip.
---
@@ -111,5 +158,13 @@ Every entry supports these frontmatter fields:
**Photos not showing in gallery**
→ Verify files were uploaded (check the entry folder in Admin → Media). Only jpg, jpeg, png, webp, gif are rendered.
**Submit button does nothing**
→ Check you have at least one photo attached, and that every upload has finished. The form blocks
submit while an upload is still in flight, and requires 16 photos.
**500 error after posting**
→ Run `make fix-perms` to restore container file ownership.
**Edits create a new entry instead of updating**
→ The hidden `edit_path` was empty, so `overwrite_mode` fell back to `false`. Re-enter via the entry's
Edit action rather than opening `/post` directly.