From acdf3edb3de207ed9d72242ba2d017531d1bd5cc Mon Sep 17 00:00:00 2001 From: Mischa Date: Sat, 20 Jun 2026 21:08:08 +0200 Subject: [PATCH] docs: add demo data redesign implementation plan Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01Vgmzx8VTTTmCskSpQtsLTr --- .../plans/2026-06-20-demo-data-redesign.md | 969 ++++++++++++++++++ 1 file changed, 969 insertions(+) create mode 100644 docs/superpowers/plans/2026-06-20-demo-data-redesign.md diff --git a/docs/superpowers/plans/2026-06-20-demo-data-redesign.md b/docs/superpowers/plans/2026-06-20-demo-data-redesign.md new file mode 100644 index 0000000..e47d1d5 --- /dev/null +++ b/docs/superpowers/plans/2026-06-20-demo-data-redesign.md @@ -0,0 +1,969 @@ +# Demo Data Redesign Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Replace patchwork demo content with a single high-quality `italy-2026-demo` trip following the real 8-day Tuscan cycling loop, with 12 journal entries (with photos) and 4 stories exercising all shortcode types. + +**Architecture:** All demo source files live in `user/docs/demo/trips/italy-2026-demo/`. `make demo-load` copies them into `user/pages/01.trips/italy-2026-demo/` inside Docker. Images are downloaded once and committed to the demo source so the Makefile stays simple (cp -r copies everything). Tests in `tests/ui/stories.spec.js` reference story slugs that must match the new folder names. + +**Tech Stack:** Grav CMS page files (YAML frontmatter + Markdown), story-blocks shortcodes (`snap-gallery`, `scrolly-section`, `chapter-break`, `pull-quote`), picsum.photos placeholder images, Playwright tests, Make. + +## Global Constraints + +- All content paths are relative to project root: `/home/mischa/Nextcloud/Projects/travel-blog-intotheeast/` +- `user/` is a **separate git repo** — commit content changes there with `git -C user commit` +- Never read `.env`; never ssh directly to production +- Demo trip slug: `italy-2026-demo`; fictional dates: 2026-09-01 to 2026-09-08 +- `hero_image: ''` in all entry frontmatter — template auto-selects `01.jpg` as hero +- Story images: 1600×1000 from `https://picsum.photos/seed//1600/1000` +- Entry images: 1200×800 from `https://picsum.photos/seed//1200/800` +- Dev server: `http://localhost:8081` + +--- + +### Task 1: Cleanup, GPX rename, trip.md, dailies.md + +**Files:** +- Delete: `user/docs/demo/trips/japan-korea-2026/` (entire folder) +- Delete: `user/docs/demo/trips/italy-2025/dailies/` (entries only) +- Delete: `user/docs/demo/trips/italy-2025/04.stories/` (stories only) +- Delete: `user/docs/demo/trips/italy-2026-demo/dailies/` (replace with new entries in later tasks) +- Delete: `user/docs/demo/trips/italy-2026-demo/04.stories/` (replace with new stories in later tasks) +- Rename: 4 GPX files in `user/docs/demo/trips/italy-2026-demo/` +- Modify: `user/docs/demo/trips/italy-2026-demo/trip.md` +- Create: `user/docs/demo/trips/italy-2026-demo/dailies/dailies.md` +- Modify: `CLAUDE.md` (update demo-load description) + +- [ ] **Step 1: Remove old demo data** + +```bash +rm -rf user/docs/demo/trips/japan-korea-2026 +rm -rf user/docs/demo/trips/italy-2025/dailies +rm -rf user/docs/demo/trips/italy-2025/04.stories +rm -rf user/docs/demo/trips/italy-2026-demo/dailies +rm -rf user/docs/demo/trips/italy-2026-demo/04.stories +``` + +- [ ] **Step 2: Rename the 4 new GPX files** + +```bash +cd user/docs/demo/trips/italy-2026-demo + +mv "2025-10-11_2627663255_TGE Tuscany 2025 Final Route - 8 days - Day 1 - from Venturina Terme to Sugherella.gpx" \ + day-1-campiglia-to-sugherella.gpx + +mv "2025-10-12_2630489431_TGE Tuscany 2025 Final Route - 8 days - Day 2.gpx" \ + day-2-sugherella-to-orbetello.gpx + +mv "2025-10-13_2632495944_TGE Tuscany 2025 Final Route - 8 days - Day 3.gpx" \ + day-3-orbetello-to-sorano.gpx + +mv "2025-10-14_2634086364_TGE Tuscany 2025 Final Route - 8 days - Day 4.gpx" \ + day-4-sorano-to-val-dorcia.gpx + +cd ../../../.. +``` + +- [ ] **Step 3: Verify 7 GPX files exist with correct names** + +```bash +ls user/docs/demo/trips/italy-2026-demo/*.gpx +``` + +Expected output (7 files): +``` +day-1-campiglia-to-sugherella.gpx +day-2-sugherella-to-orbetello.gpx +day-3-orbetello-to-sorano.gpx +day-4-sorano-to-val-dorcia.gpx +day-5-val-dorcia-to-siena.gpx +day-6-siena-to-florence.gpx +day-8-coast-to-piombino.gpx +``` + +- [ ] **Step 4: Update trip.md** + +Write `user/docs/demo/trips/italy-2026-demo/trip.md`: + +```markdown +--- +title: 'Tuscany 2026' +template: trip +date: '2026-09-01' +date_start: '2026-09-01' +date_end: '2026-09-08' +cover_image: '' +--- +``` + +- [ ] **Step 5: Create dailies index page** + +Create `user/docs/demo/trips/italy-2026-demo/dailies/dailies.md`: + +```markdown +--- +title: Journal +template: dailies +--- +``` + +- [ ] **Step 6: Recreate empty story and entry directories** + +```bash +mkdir -p user/docs/demo/trips/italy-2026-demo/dailies +mkdir -p user/docs/demo/trips/italy-2026-demo/04.stories +``` + +- [ ] **Step 7: Update CLAUDE.md demo-load description** + +In `CLAUDE.md`, find the line: +``` +- `make demo-load` — load demo entries for both trips (Japan/Korea 2026 + Italy 2025 with real GPX) +``` + +Replace with: +``` +- `make demo-load` — load demo content into `italy-2026-demo` trip (journal entries + stories + GPX) +``` + +- [ ] **Step 8: Commit** + +```bash +git -C user add -A +git -C user commit -m "chore(demo): cleanup old demo data, rename GPX files, update trip.md" + +git add CLAUDE.md +git commit -m "docs: update demo-load description in CLAUDE.md" +``` + +--- + +### Task 2: Update stories.spec.js for new story slugs + +**Files:** +- Modify: `tests/ui/stories.spec.js` + +The existing tests point to old story slugs (`val-dorcia-dawn`, `long-climb-montalcino`). New slugs are `val-dorcia-at-dawn` and `sorano-rock-and-time`. The shortcode assertions stay identical — the new stories are designed to match them. + +- [ ] **Step 1: Update slug constants and comments in stories.spec.js** + +Replace the top of `tests/ui/stories.spec.js` (lines up to the first test): + +```javascript +// @ts-check +// Tests: S1–S7 — story mode rendering and navigation +// Requires demo data: run `make demo-load` before this suite. +const { test, expect } = require('@playwright/test'); + +const STORIES_URL = '/trips/italy-2026-demo/stories'; +const STORY_GALLERY = '/trips/italy-2026-demo/stories/val-dorcia-at-dawn'; // gallery-led: snap-gallery × 2, chapter-break, text-only pull-quote +const STORY_SCROLLY = '/trips/italy-2026-demo/stories/sorano-rock-and-time'; // scrolly-led: scrolly-section × 2, chapter-break, pull-quote with image +const DEMO_STORY = '/trips/italy-2026-demo/stories/val-dorcia-at-dawn'; // used for cross-trip hero sanity check +``` + +- [ ] **Step 2: Update the two hardcoded URLs in S7** + +In `tests/ui/stories.spec.js`, find and replace the hardcoded URL in S7: + +Old: +```javascript +test('S7: story body back link has back-pill class', async ({ page }) => { + await page.goto('/trips/italy-2026-demo/stories/val-dorcia-dawn'); +``` + +New: +```javascript +test('S7: story body back link has back-pill class', async ({ page }) => { + await page.goto('/trips/italy-2026-demo/stories/val-dorcia-at-dawn'); +``` + +- [ ] **Step 3: Verify tests reference correct slugs** + +```bash +grep -n "val-dorcia\|montalcino\|sorano\|florence-without" tests/ui/stories.spec.js +``` + +Expected: no references to `val-dorcia-dawn` or `long-climb-montalcino`; `val-dorcia-at-dawn` and `sorano-rock-and-time` appear. + +- [ ] **Step 4: Commit** + +```bash +git add tests/ui/stories.spec.js +git commit -m "test(stories): update story slugs to match new demo content" +``` + +--- + +### Task 3: Write Story 1 — Sorano: Rock and Time + +**Target:** `user/docs/demo/trips/italy-2026-demo/04.stories/01.sorano-rock-and-time/` +**Test coverage:** `STORY_SCROLLY` — needs scrolly-section × 2, chapter-break, pull-quote with image + +**Files:** +- Create: `user/docs/demo/trips/italy-2026-demo/04.stories/01.sorano-rock-and-time/story.md` +- Create: `user/docs/demo/trips/italy-2026-demo/04.stories/01.sorano-rock-and-time/hero.jpg` +- Create: `user/docs/demo/trips/italy-2026-demo/04.stories/01.sorano-rock-and-time/photo-1.jpg` +- Create: `user/docs/demo/trips/italy-2026-demo/04.stories/01.sorano-rock-and-time/photo-2.jpg` + +- [ ] **Step 1: Create story directory and download images** + +```bash +mkdir -p user/docs/demo/trips/italy-2026-demo/04.stories/01.sorano-rock-and-time +SDIR=user/docs/demo/trips/italy-2026-demo/04.stories/01.sorano-rock-and-time +curl -sL "https://picsum.photos/seed/demo-s1-hero/1600/1000" -o "$SDIR/hero.jpg" +curl -sL "https://picsum.photos/seed/demo-s1-1/1600/1000" -o "$SDIR/photo-1.jpg" +curl -sL "https://picsum.photos/seed/demo-s1-2/1600/1000" -o "$SDIR/photo-2.jpg" +``` + +- [ ] **Step 2: Write story.md** + +Write `user/docs/demo/trips/italy-2026-demo/04.stories/01.sorano-rock-and-time/story.md`: + +```markdown +--- +title: 'Sorano: Rock and Time' +date: '2026-09-03' +location_name: Sorano +location_country: Italy +lat: 42.683 +lng: 11.715 +hero_image: hero.jpg +hero_alt: Medieval town of Sorano clinging to pale tufa cliffs at dusk +published: true +--- + +The road from Orbetello climbs inland through scrubland and heat. For most of the afternoon there is nothing on the horizon except sky and the occasional electricity pylon. Then, at the top of a ridge, Sorano appears — and the word "appears" does not quite cover it. The town has been carved from a cliff of tufa, a pale volcanic rock so soft you can score it with a fingernail. The buildings are the cliff and the cliff is the buildings. + +[scrolly-section image="hero.jpg" alt="Medieval town of Sorano seen from the approach road, perched on pale tufa cliffs" caption="Sorano — tufa cliff town, Grosseto province"] +The approach by bike gives you an unusually long time to study it. The descent into the valley and the climb back up take perhaps forty minutes, and the town is visible for most of that time, doing nothing, requiring nothing. + +--- + +Close up the rock is extraordinary. Hundreds of tomb niches cut into the cliff face — Etruscan graves, most of them open to the sky now, their contents long removed. The people who built this town chose to live surrounded by the evidence of their own mortality. This seems either very brave or very sensible. + +--- + +The gate into the old town is fifteenth century and narrow enough that loaded bikes don't fit without turning sideways. Inside, the air is noticeably cooler and the alleys are steep, paved with the same pale tufa, worn smooth by centuries of feet. +[/scrolly-section] + +We found a wall to lean the bikes against and sat looking south over the valley we had come from. The light was going amber. Below us, the road we had ridden was already in shadow. + +[chapter-break image="photo-1.jpg" title="After Dark" number="II" alt="Narrow medieval alley in Sorano at dusk, pale stone walls glowing warm" /] + +[pull-quote image="photo-1.jpg" alt="Stone alley in Sorano lit by a single lantern at night"] +A town built on rock, carved from rock, returning slowly to rock. Two thousand years of human effort and the cliff remains indifferent. +[/pull-quote] + +[scrolly-section image="photo-2.jpg" alt="View south from the tufa cliff walls of Sorano at dusk" caption="Val di Fiora, from the old walls"] +One restaurant was open. The menu was four items. We had the pasta with wild boar and the pasta with truffles and a carafe of local wine that cost six euros and was excellent. + +--- + +The owner sat at the next table watching a football match on his phone without headphones. Nobody minded. The town outside was completely quiet. +[/scrolly-section] + +We were in bed before nine. Sorano at night is absolutely silent. It has been this quiet, in approximately this configuration, for a very long time. +``` + +- [ ] **Step 3: Verify shortcode counts match test S3 expectations** + +```bash +grep -c "scrolly-section" user/docs/demo/trips/italy-2026-demo/04.stories/01.sorano-rock-and-time/story.md +grep -c "chapter-break" user/docs/demo/trips/italy-2026-demo/04.stories/01.sorano-rock-and-time/story.md +grep -c "pull-quote image=" user/docs/demo/trips/italy-2026-demo/04.stories/01.sorano-rock-and-time/story.md +``` + +Expected: `2` scrolly-section tags (opening tags only), `1` chapter-break, `1` pull-quote with image. + +- [ ] **Step 4: Commit** + +```bash +git -C user add -A +git -C user commit -m "feat(demo): add story 1 — Sorano: Rock and Time" +``` + +--- + +### Task 4: Write Story 2 — Val d'Orcia at Dawn + +**Target:** `user/docs/demo/trips/italy-2026-demo/04.stories/02.val-dorcia-at-dawn/` +**Test coverage:** `STORY_GALLERY` — needs snap-gallery × 2, chapter-break, text-only pull-quote + +**Files:** +- Create: `user/docs/demo/trips/italy-2026-demo/04.stories/02.val-dorcia-at-dawn/story.md` +- Create: `hero.jpg`, `photo-1.jpg`, `photo-2.jpg` (same directory) + +- [ ] **Step 1: Create story directory and download images** + +```bash +mkdir -p user/docs/demo/trips/italy-2026-demo/04.stories/02.val-dorcia-at-dawn +SDIR=user/docs/demo/trips/italy-2026-demo/04.stories/02.val-dorcia-at-dawn +curl -sL "https://picsum.photos/seed/demo-s2-hero/1600/1000" -o "$SDIR/hero.jpg" +curl -sL "https://picsum.photos/seed/demo-s2-1/1600/1000" -o "$SDIR/photo-1.jpg" +curl -sL "https://picsum.photos/seed/demo-s2-2/1600/1000" -o "$SDIR/photo-2.jpg" +``` + +- [ ] **Step 2: Write story.md** + +Write `user/docs/demo/trips/italy-2026-demo/04.stories/02.val-dorcia-at-dawn/story.md`: + +```markdown +--- +title: "Val d'Orcia at Dawn" +date: '2026-09-05' +location_name: Val d'Orcia +location_country: Italy +lat: 43.078 +lng: 11.676 +hero_image: hero.jpg +hero_alt: Wide Tuscan valley at dawn, long cypress shadows across pale gravel road +published: true +--- + +We left before the heat arrived. The alarm was five-thirty and the sky outside the tent was still more grey than blue. The valley was invisible in the dark except as an absence — a vast silence below us where the shapes of hills ought to be. By six the light had changed. The Val d'Orcia is one of those landscapes that photographers wait years to shoot at this hour, and you can see why: the light arrives at an angle that makes everything look like something from a different century. + +[snap-gallery images="hero.jpg,photo-1.jpg,photo-2.jpg" captions="Six in the morning: the valley belongs entirely to the light,The Cypress Road — every photograph of Tuscany was taken here or somewhere like it,A farmhouse that has been sitting on this hill for four hundred years" alts="Wide misty Tuscan valley at dawn with long shadows,Straight road lined by tall cypress trees in morning light,Stone farmhouse on a hilltop with rolling landscape behind" /] + +The roads down here are white gravel — strade bianche — and the tyres make a particular sound on them that you don't get anywhere else. We rode for two hours without seeing a car. The only other people were two elderly men walking a dog in the opposite direction. They waved. + +[chapter-break image="photo-1.jpg" title="The Hour Before Heat" alt="Cypress road vanishing into a hazy summer morning" /] + +By nine the temperature had already shifted. The quality of the light changed — softer, more diffuse, the sky turning white at the edges. The windows of the farmhouses began to open. Dogs that had been invisible in the dark became visible on walls and in doorways, watching us with professional detachment. + +[snap-gallery images="photo-2.jpg,hero.jpg" captions="The road changes from asphalt to gravel to packed earth and back again without warning,The valley floor at nine: the shadows have shortened, the colours have flattened" alts="Farmhouse detail with terracotta roof and single cypress tree,Tuscan valley road in mid-morning haze" /] + +[pull-quote] +The best hours of a cycling day are the ones nobody else sees. Before the heat arrives, before the cafes open, before the traffic comes. Everything belongs to you then. +[/pull-quote] + +We reached Pienza at eleven-thirty. The ice-cream queue was eight deep and entirely justified. +``` + +- [ ] **Step 3: Verify shortcode counts match test S2 expectations** + +```bash +grep -c "snap-gallery" user/docs/demo/trips/italy-2026-demo/04.stories/02.val-dorcia-at-dawn/story.md +grep -c "chapter-break" user/docs/demo/trips/italy-2026-demo/04.stories/02.val-dorcia-at-dawn/story.md +grep -c "pull-quote__inner--no-image\|^\[pull-quote\]" user/docs/demo/trips/italy-2026-demo/04.stories/02.val-dorcia-at-dawn/story.md +``` + +Simpler check — verify exactly 2 `[snap-gallery` tags and 1 `[pull-quote]` (no `image=`): + +```bash +grep -c "\[snap-gallery" user/docs/demo/trips/italy-2026-demo/04.stories/02.val-dorcia-at-dawn/story.md +grep "\[pull-quote" user/docs/demo/trips/italy-2026-demo/04.stories/02.val-dorcia-at-dawn/story.md +``` + +Expected: `2` snap-gallery, and the pull-quote line has no `image=` attribute. + +- [ ] **Step 4: Commit** + +```bash +git -C user add -A +git -C user commit -m "feat(demo): add story 2 — Val d'Orcia at Dawn" +``` + +--- + +### Task 5: Write Story 3 — One Evening in Siena + +**Target:** `user/docs/demo/trips/italy-2026-demo/04.stories/03.one-evening-siena/` +**Primary shortcode:** `pull-quote` with background image; also uses `chapter-break` and `scrolly-section` + +**Files:** +- Create: `user/docs/demo/trips/italy-2026-demo/04.stories/03.one-evening-siena/story.md` +- Create: `hero.jpg`, `photo-1.jpg` (same directory) + +- [ ] **Step 1: Create story directory and download images** + +```bash +mkdir -p user/docs/demo/trips/italy-2026-demo/04.stories/03.one-evening-siena +SDIR=user/docs/demo/trips/italy-2026-demo/04.stories/03.one-evening-siena +curl -sL "https://picsum.photos/seed/demo-s3-hero/1600/1000" -o "$SDIR/hero.jpg" +curl -sL "https://picsum.photos/seed/demo-s3-1/1600/1000" -o "$SDIR/photo-1.jpg" +``` + +- [ ] **Step 2: Write story.md** + +Write `user/docs/demo/trips/italy-2026-demo/04.stories/03.one-evening-siena/story.md`: + +```markdown +--- +title: 'One Evening in Siena' +date: '2026-09-05' +location_name: Siena +location_country: Italy +lat: 43.318 +lng: 11.330 +hero_image: hero.jpg +hero_alt: Piazza del Campo at dusk, terracotta paving fading from gold to shadow +published: true +--- + +[pull-quote image="hero.jpg" alt="Piazza del Campo seen from the upper rim at golden hour"] +Siena is not a city that tries to impress you. It has been here for a thousand years and intends to be here for a thousand more. You fit around it, not the other way. +[/pull-quote] + +We rolled in at half past six, legs finished, panniers heavier than they started. The Campo appeared without warning at the end of a narrow street and we both stopped pedalling at exactly the same moment. That particular square does something to people. It is partly the shape — a shallow bowl, a scallop shell, the way it holds you — and partly the light at that hour, which turns the terracotta pavement the colour of old copper. + +[chapter-break image="photo-1.jpg" title="The Campo" number="I" alt="Detail of Siena's herringbone brick pavement catching the last light" /] + +[scrolly-section image="hero.jpg" alt="Piazza del Campo filling with people as evening comes" caption="Campo, 19:00 — the square fills from the edges inward"] +The locals arrive first. They know which spot faces west and which benches stay in the shade longest. Then the tourists, then the pigeons, then the long shadows. + +--- + +A busker with an accordion near the Fonte Gaia. A group of students lying on the slope reading. Three children running in a circle for reasons nobody questioned. + +--- + +We sat on the pavement with our backs against the warm brickwork of the Palazzo Pubblico and did not move for forty minutes. The relief of sitting still after eight hours on a bike is a specific physical sensation. It travels upward from your legs and settles somewhere just behind the sternum. +[/scrolly-section] + +We found a place for dinner three streets away, down a flight of steps with no sign outside. The pasta was handmade, the wine was local, the bill was reasonable. We were in bed by ten. Tomorrow: Florence. +``` + +- [ ] **Step 3: Commit** + +```bash +git -C user add -A +git -C user commit -m "feat(demo): add story 3 — One Evening in Siena" +``` + +--- + +### Task 6: Write Story 4 — Florence Without a Map + +**Target:** `user/docs/demo/trips/italy-2026-demo/04.stories/04.florence-without-a-map/` +**Primary shortcode:** `chapter-break` as structural divider; also uses `snap-gallery`, `pull-quote` (text-only), `scrolly-section` + +**Files:** +- Create: `user/docs/demo/trips/italy-2026-demo/04.stories/04.florence-without-a-map/story.md` +- Create: `hero.jpg`, `photo-1.jpg` (same directory) + +- [ ] **Step 1: Create story directory and download images** + +```bash +mkdir -p user/docs/demo/trips/italy-2026-demo/04.stories/04.florence-without-a-map +SDIR=user/docs/demo/trips/italy-2026-demo/04.stories/04.florence-without-a-map +curl -sL "https://picsum.photos/seed/demo-s4-hero/1600/1000" -o "$SDIR/hero.jpg" +curl -sL "https://picsum.photos/seed/demo-s4-1/1600/1000" -o "$SDIR/photo-1.jpg" +``` + +- [ ] **Step 2: Write story.md** + +Write `user/docs/demo/trips/italy-2026-demo/04.stories/04.florence-without-a-map/story.md`: + +```markdown +--- +title: 'Florence Without a Map' +date: '2026-09-07' +location_name: Florence +location_country: Italy +lat: 43.769 +lng: 11.255 +hero_image: hero.jpg +hero_alt: Arno river at midday with Ponte Vecchio, ochre buildings reflected in still water +published: true +--- + +No route today. No GPS, no distance target, no reason to be anywhere by any particular time. After six days of forward motion this felt almost wrong — the instinct to check the elevation profile arriving at nothing. We put the bikes in the hotel basement and walked out into Florence on foot. + +[chapter-break image="hero.jpg" title="Day Seven" number="VII" alt="Arno river and Ponte Vecchio from Ponte Santa Trinita at midday" /] + +[snap-gallery images="hero.jpg,photo-1.jpg" captions="The Arno at noon — greener than expected, the bridges older than you remember,Via dei Servi: washing lines, shutters, a cat on a warm stone ledge that had been warm since morning" alts="Arno river with Ponte Vecchio reflected in still water at midday,Narrow Florence street with laundry strung between buildings" /] + +[pull-quote] +Cycling makes you earn every city you arrive at. Florence, we got for free. It felt like a gift and a debt simultaneously. +[/pull-quote] + +[scrolly-section image="photo-1.jpg" alt="Narrow Oltrarno street in afternoon light" caption="Oltrarno, 14:00"] +The Uffizi had a queue that stretched around two corners and disappeared into a side street. We looked at it for a moment and went to find coffee instead. This felt correct. + +--- + +A covered market in the Oltrarno that nobody had told us about. A man selling leather goods from a table he clearly reassembled each morning from identical components. A small dog sleeping under a fruit stall in a precisely calculated patch of shade. + +--- + +We crossed the Ponte Vecchio at two in the afternoon, which is exactly the wrong time to cross the Ponte Vecchio, and it was still worth it. The light off the Arno at that hour is genuinely extraordinary and all the photographs in the world do not prepare you for it. +[/scrolly-section] + +Dinner near the apartment, early. Feet sore in a different way from legs sore — a smaller, more concentrated complaint. Tomorrow: the last day. The coast road home. +``` + +- [ ] **Step 3: Commit** + +```bash +git -C user add -A +git -C user commit -m "feat(demo): add story 4 — Florence Without a Map" +``` + +--- + +### Task 7: Write Journal Entries — Days 1–4 (entries 1–6) + +**Target:** `user/docs/demo/trips/italy-2026-demo/dailies/` + +Each entry directory name: `.entry/` +Each entry contains: `entry.md` + numbered images `01.jpg`, `02.jpg`, … + +- [ ] **Step 1: Entry 1 — Setting Off from Campiglia (2 photos)** + +```bash +EDIR=user/docs/demo/trips/italy-2026-demo/dailies/2026-09-01-0700-setting-off-from-campiglia.entry +mkdir -p "$EDIR" +curl -sL "https://picsum.photos/seed/demo-d1-1/1200/800" -o "$EDIR/01.jpg" +curl -sL "https://picsum.photos/seed/demo-d1-2/1200/800" -o "$EDIR/02.jpg" +``` + +Write `$EDIR/entry.md`: + +```markdown +--- +title: 'Setting Off from Campiglia' +date: '2026-09-01 07:00' +template: entry +published: true +hero_image: '' +lat: 43.024 +lng: 10.603 +location_city: Campiglia Marittima +location_country: Italy +weather_temp_c: 27 +weather_desc: Sunny +--- + +Seven in the morning and the coast road is still cool. We loaded the bikes in the car park below the old town, the panniers heavier than they should be and the weather forecast saying nine consecutive days of sun. The route heads south first — down into the Maremma, then east, then a long loop back. Eight days. Nobody goes this way in September except cyclists and people who have got lost. +``` + +- [ ] **Step 2: Entry 2 — Maremma in Full Sun (3 photos)** + +```bash +EDIR=user/docs/demo/trips/italy-2026-demo/dailies/2026-09-02-1130-maremma-in-full-sun.entry +mkdir -p "$EDIR" +curl -sL "https://picsum.photos/seed/demo-d2a-1/1200/800" -o "$EDIR/01.jpg" +curl -sL "https://picsum.photos/seed/demo-d2a-2/1200/800" -o "$EDIR/02.jpg" +curl -sL "https://picsum.photos/seed/demo-d2a-3/1200/800" -o "$EDIR/03.jpg" +``` + +Write `$EDIR/entry.md`: + +```markdown +--- +title: 'Maremma in Full Sun' +date: '2026-09-02 11:30' +template: entry +published: true +hero_image: '' +lat: 42.612 +lng: 11.171 +location_city: Maremma +location_country: Italy +weather_temp_c: 29 +weather_desc: Sunny +--- + +Eleven-thirty and already thirty degrees. The Maremma is agricultural land and scrubland and very little else, and in September it has the quality of a landscape that has given up trying. The road is straight, the sun is direct, the shadows are almost vertical. We stopped at a petrol station and drank two cans of something cold each. The man at the counter looked at us like people who had made a series of questionable decisions. +``` + +- [ ] **Step 3: Entry 3 — The Lagoon at Dusk (3 photos)** + +```bash +EDIR=user/docs/demo/trips/italy-2026-demo/dailies/2026-09-02-1900-the-lagoon-at-dusk.entry +mkdir -p "$EDIR" +curl -sL "https://picsum.photos/seed/demo-d2b-1/1200/800" -o "$EDIR/01.jpg" +curl -sL "https://picsum.photos/seed/demo-d2b-2/1200/800" -o "$EDIR/02.jpg" +curl -sL "https://picsum.photos/seed/demo-d2b-3/1200/800" -o "$EDIR/03.jpg" +``` + +Write `$EDIR/entry.md`: + +```markdown +--- +title: 'The Lagoon at Dusk' +date: '2026-09-02 19:00' +template: entry +published: true +hero_image: '' +lat: 42.442 +lng: 11.218 +location_city: Orbetello +location_country: Italy +weather_temp_c: 24 +weather_desc: Partly cloudy +--- + +Orbetello sits on a causeway between two lagoons and at dusk the light does something remarkable to the water. Pink flamingos — real ones, not ornamental — were standing in the shallows on the western side, perfectly still. We ate at a table outside overlooking the eastern lagoon. The sky turned orange and then purple and then a deep blue that was almost indistinguishable from the water. The wine was cold and the pasta had clams. +``` + +- [ ] **Step 4: Entry 4 — Orbetello Morning (2 photos)** + +```bash +EDIR=user/docs/demo/trips/italy-2026-demo/dailies/2026-09-03-0800-orbetello-morning.entry +mkdir -p "$EDIR" +curl -sL "https://picsum.photos/seed/demo-d3a-1/1200/800" -o "$EDIR/01.jpg" +curl -sL "https://picsum.photos/seed/demo-d3a-2/1200/800" -o "$EDIR/02.jpg" +``` + +Write `$EDIR/entry.md`: + +```markdown +--- +title: 'Orbetello Morning' +date: '2026-09-03 08:00' +template: entry +published: true +hero_image: '' +lat: 42.442 +lng: 11.217 +location_city: Orbetello +location_country: Italy +weather_temp_c: 22 +weather_desc: Sunny +--- + +The lagoon at eight in the morning is a different thing from the lagoon at eight in the evening. Flat, silver, nearly silent. A single fisherman in a small boat about two hundred metres out, not appearing to fish. We left before the town had properly woken up, heading northeast on roads that climbed immediately and steeply into a landscape of oak and limestone that felt nothing like the coast we had left behind twenty minutes before. +``` + +- [ ] **Step 5: Entry 5 — Tufa and Towers (2 photos)** + +```bash +EDIR=user/docs/demo/trips/italy-2026-demo/dailies/2026-09-03-1700-tufa-and-towers.entry +mkdir -p "$EDIR" +curl -sL "https://picsum.photos/seed/demo-d3b-1/1200/800" -o "$EDIR/01.jpg" +curl -sL "https://picsum.photos/seed/demo-d3b-2/1200/800" -o "$EDIR/02.jpg" +``` + +Write `$EDIR/entry.md`: + +```markdown +--- +title: 'Tufa and Towers' +date: '2026-09-03 17:00' +template: entry +published: true +hero_image: '' +lat: 42.683 +lng: 11.715 +location_city: Sorano +location_country: Italy +weather_temp_c: 26 +weather_desc: Sunny +--- + +Sorano appears on the horizon an hour before you reach it: a cluster of towers and walls on a pale cliff, floating above the valley. The closer you get the stranger it becomes. The town is not built on rock — the town is rock, volcanic tufa carved and inhabited over two thousand years. The Etruscans started it. Everyone since has just kept adding floors. We are staying the night and it already feels like somewhere that requires more time than we have. +``` + +- [ ] **Step 6: Entry 6 — The Long Climb North (4 photos)** + +```bash +EDIR=user/docs/demo/trips/italy-2026-demo/dailies/2026-09-04-1500-the-long-climb-north.entry +mkdir -p "$EDIR" +curl -sL "https://picsum.photos/seed/demo-d4-1/1200/800" -o "$EDIR/01.jpg" +curl -sL "https://picsum.photos/seed/demo-d4-2/1200/800" -o "$EDIR/02.jpg" +curl -sL "https://picsum.photos/seed/demo-d4-3/1200/800" -o "$EDIR/03.jpg" +curl -sL "https://picsum.photos/seed/demo-d4-4/1200/800" -o "$EDIR/04.jpg" +``` + +Write `$EDIR/entry.md`: + +```markdown +--- +title: 'The Long Climb North' +date: '2026-09-04 15:00' +template: entry +published: true +hero_image: '' +lat: 43.077 +lng: 11.678 +location_city: "Val d'Orcia" +location_country: Italy +weather_temp_c: 23 +weather_desc: Partly cloudy +--- + +Today was the hardest day. The route from Sorano to the Val d'Orcia crosses the eastern slope of Monte Amiata, which sounds manageable on a map and is not manageable at all. By noon we had climbed eleven hundred metres. By two we were somewhere above Seggiano in thin cloud, the views long gone, legs complaining in a language that had become very specific. Then the cloud lifted and the Val d'Orcia was simply there below us: pale roads, dark cypress, the whole thing exactly as advertised. Sometimes the landscapes that have been photographed to death are still worth arriving at. +``` + +- [ ] **Step 7: Commit entries 1–6** + +```bash +git -C user add -A +git -C user commit -m "feat(demo): add journal entries days 1–4 with photos" +``` + +--- + +### Task 8: Write Journal Entries — Days 5–8 (entries 7–12) + +- [ ] **Step 1: Entry 7 — Before the Heat Arrives (2 photos)** + +```bash +EDIR=user/docs/demo/trips/italy-2026-demo/dailies/2026-09-05-0830-before-the-heat-arrives.entry +mkdir -p "$EDIR" +curl -sL "https://picsum.photos/seed/demo-d5a-1/1200/800" -o "$EDIR/01.jpg" +curl -sL "https://picsum.photos/seed/demo-d5a-2/1200/800" -o "$EDIR/02.jpg" +``` + +Write `$EDIR/entry.md`: + +```markdown +--- +title: 'Before the Heat Arrives' +date: '2026-09-05 08:30' +template: entry +published: true +hero_image: '' +lat: 43.078 +lng: 11.676 +location_city: Pienza +location_country: Italy +weather_temp_c: 21 +weather_desc: Sunny +--- + +Six o'clock and the valley below Pienza is still in shadow. We left camp early on purpose — the route to Siena is long and September sun waits for no one. On the strade bianche the tyres make a sound like distant applause. No cars for the first two hours. Just the road and the light doing things to the cypress trees that would be embarrassing to describe in any other context. +``` + +- [ ] **Step 2: Entry 8 — Into Siena (3 photos)** + +```bash +EDIR=user/docs/demo/trips/italy-2026-demo/dailies/2026-09-05-1800-into-siena.entry +mkdir -p "$EDIR" +curl -sL "https://picsum.photos/seed/demo-d5b-1/1200/800" -o "$EDIR/01.jpg" +curl -sL "https://picsum.photos/seed/demo-d5b-2/1200/800" -o "$EDIR/02.jpg" +curl -sL "https://picsum.photos/seed/demo-d5b-3/1200/800" -o "$EDIR/03.jpg" +``` + +Write `$EDIR/entry.md`: + +```markdown +--- +title: 'Into Siena' +date: '2026-09-05 18:00' +template: entry +published: true +hero_image: '' +lat: 43.318 +lng: 11.335 +location_city: Siena +location_country: Italy +weather_temp_c: 25 +weather_desc: Sunny +--- + +The approach to Siena by bike is through streets that get progressively older and steeper until suddenly the Campo is there. We had both seen it in photographs and the photographs are accurate in every way except one: they do not tell you how the square smells — stone and frying onions and the particular warm stillness of a Sienese summer evening. We sat on the pavement with our backs against the Palazzo Pubblico for forty minutes and did not want to be anywhere else. +``` + +- [ ] **Step 3: Entry 9 — Florence by Nightfall (3 photos)** + +```bash +EDIR=user/docs/demo/trips/italy-2026-demo/dailies/2026-09-06-2000-florence-by-nightfall.entry +mkdir -p "$EDIR" +curl -sL "https://picsum.photos/seed/demo-d6-1/1200/800" -o "$EDIR/01.jpg" +curl -sL "https://picsum.photos/seed/demo-d6-2/1200/800" -o "$EDIR/02.jpg" +curl -sL "https://picsum.photos/seed/demo-d6-3/1200/800" -o "$EDIR/03.jpg" +``` + +Write `$EDIR/entry.md`: + +```markdown +--- +title: 'Florence by Nightfall' +date: '2026-09-06 20:00' +template: entry +published: true +hero_image: '' +lat: 43.767 +lng: 11.253 +location_city: Florence +location_country: Italy +weather_temp_c: 21 +weather_desc: Cloudy +--- + +A long day. Siena to Florence is ninety kilometres and involves two significant climbs before you reach the Chianti hills, after which it becomes more manageable but you have already used the legs you needed. We came in from the south as the light was going, the city materialising from a distance as a density of rooftops and towers. The Arno appeared between buildings and we crossed it and then we were in, which is always a slightly surprising moment after a long day. +``` + +- [ ] **Step 4: Entry 10 — One Rest Day (2 photos)** + +```bash +EDIR=user/docs/demo/trips/italy-2026-demo/dailies/2026-09-07-1400-one-rest-day.entry +mkdir -p "$EDIR" +curl -sL "https://picsum.photos/seed/demo-d7-1/1200/800" -o "$EDIR/01.jpg" +curl -sL "https://picsum.photos/seed/demo-d7-2/1200/800" -o "$EDIR/02.jpg" +``` + +Write `$EDIR/entry.md`: + +```markdown +--- +title: 'One Rest Day' +date: '2026-09-07 14:00' +template: entry +published: true +hero_image: '' +lat: 43.769 +lng: 11.255 +location_city: Florence +location_country: Italy +weather_temp_c: 22 +weather_desc: Partly cloudy +--- + +The bikes stayed in the basement. We walked instead, which after six days of cycling felt simultaneously easier and harder — easier on the legs, harder on the feet, which are used to being passive. Florence does not require a plan. Every street contains something. We crossed the Arno four times from different bridges, each one giving a slightly different version of the same view, all of them good. +``` + +- [ ] **Step 5: Entry 11 — Dawn on the Cecina Coast (1 photo)** + +```bash +EDIR=user/docs/demo/trips/italy-2026-demo/dailies/2026-09-08-0730-dawn-on-the-cecina-coast.entry +mkdir -p "$EDIR" +curl -sL "https://picsum.photos/seed/demo-d8a-1/1200/800" -o "$EDIR/01.jpg" +``` + +Write `$EDIR/entry.md`: + +```markdown +--- +title: 'Dawn on the Cecina Coast' +date: '2026-09-08 07:30' +template: entry +published: true +hero_image: '' +lat: 43.553 +lng: 10.313 +location_city: Cecina +location_country: Italy +weather_temp_c: 20 +weather_desc: Sunny +--- + +The last day starts on the coast road south of Cecina, the sea visible between the pine trees. We have been inland for most of the week and the smell of salt water is a surprise. The road is flat, which after eight days of Tuscan hills feels almost suspicious. We rode in silence for the first hour. There was nothing that needed saying. +``` + +- [ ] **Step 6: Entry 12 — Home (2 photos)** + +```bash +EDIR=user/docs/demo/trips/italy-2026-demo/dailies/2026-09-08-1630-home.entry +mkdir -p "$EDIR" +curl -sL "https://picsum.photos/seed/demo-d8b-1/1200/800" -o "$EDIR/01.jpg" +curl -sL "https://picsum.photos/seed/demo-d8b-2/1200/800" -o "$EDIR/02.jpg" +``` + +Write `$EDIR/entry.md`: + +```markdown +--- +title: 'Home' +date: '2026-09-08 16:30' +template: entry +published: true +hero_image: '' +lat: 43.017 +lng: 10.587 +location_city: Campiglia Marittima +location_country: Italy +weather_temp_c: 26 +weather_desc: Sunny +--- + +The old town of Campiglia was visible on its hill for the last twenty kilometres, appearing and disappearing between the trees the way it had appeared on the horizon eight days ago when we left. The loop is complete: same car park, same view across the coast, different legs. The bikes went back in the car and we sat on a wall and counted the countries and the kilometres and the pasta dishes. Eight days, one loop, Tuscany in September. It was exactly what it was supposed to be. +``` + +- [ ] **Step 7: Verify 12 entry directories exist** + +```bash +ls user/docs/demo/trips/italy-2026-demo/dailies/ | grep -c "\.entry$" +``` + +Expected: `12` + +- [ ] **Step 8: Commit entries 7–12** + +```bash +git -C user add -A +git -C user commit -m "feat(demo): add journal entries days 5–8 with photos" +``` + +--- + +### Task 9: Verify with demo-load and run tests + +**Prerequisite:** Docker dev server running at `http://localhost:8081` + +- [ ] **Step 1: Reset any existing demo content** + +```bash +make demo-reset +``` + +- [ ] **Step 2: Load demo content** + +```bash +make demo-load +``` + +Expected: no errors; ends with `Cache cleared`. + +- [ ] **Step 3: Smoke check in browser** + +Open `http://localhost:8081/trips/italy-2026-demo` — verify: +- Trip page shows "Tuscany 2026" +- Filter bar shows All / Journal / Stories +- Journal entries visible (should show most recent first) +- Stories tab shows 4 story cards + +Open one entry (e.g. Entry 6 with 4 photos) and verify: +- Hero image renders (01.jpg) +- Gallery grid shows all 4 photos +- Lightbox opens on click + +Open `http://localhost:8081/trips/italy-2026-demo/stories/sorano-rock-and-time` and verify: +- `scrolly` sections render +- `chapter-break` renders +- `pull-quote` with background image renders + +Open `http://localhost:8081/trips/italy-2026-demo/map` and verify: +- All 7 GPX routes render on the map +- Entry markers appear at the correct coordinates + +- [ ] **Step 4: Run the full test suite** + +```bash +npm run test:ui +``` + +Expected: all tests pass. Key tests to watch: +- `S1`: stories listing shows ≥ 3 cards → passes (4 stories) +- `S2`: gallery story has 2 snap-galleries, chapter-break, text-only pull-quote +- `S3`: scrolly story has 2 scrolly-sections, chapter-break, pull-quote with image +- `S4`: no JS errors on scrolly story +- `S5`: back button navigates to stories listing +- `S6/S7`: demo story hero renders, back-pill present + +If a test fails, diagnose before moving on — do not proceed to final commit with failing tests. + +- [ ] **Step 5: Final commit** + +```bash +git -C user add -A +git -C user commit -m "chore(demo): verify demo content complete — all tests passing" +``` + +--- + +## Self-Review Checklist + +- [x] Spec § 1 Cleanup → Task 1 +- [x] Spec § 2 GPX rename (4 files) → Task 1, Step 2–3 +- [x] Spec § 3 Journal entries (12) → Tasks 7–8 +- [x] Spec § 4 Stories (4) → Tasks 3–6; shortcode counts designed to match S2/S3 test assertions +- [x] Spec § 5 Makefile — existing `cp -r` commands already handle images; no Makefile changes needed +- [x] Spec § 6 trip.md update → Task 1, Step 4 +- [x] Spec § 7 What is NOT changing — italy-2025 pages untouched, japan-korea-2026 pages untouched ✓ +- [x] stories.spec.js slug update → Task 2 (covers both constants and the hardcoded S7 URL) +- [x] `dailies.md` index page → Task 1, Step 5 (needed for Grav to render the dailies listing after demo-reset) +- [x] No placeholder text in any step +- [x] All 4 shortcode types appear across 4 stories, with STORY_GALLERY and STORY_SCROLLY matching test assertion counts