# Homepage Redesign Spec **Date:** 2026-06-21 **Goal:** Make the homepage context-aware: a persistent two-column map+feed layout that switches its right column between an active-trip feed and a curated highlights grid depending on whether Mischa is currently travelling. --- ## 1. Mode switch A `travelling` toggle in `user/config/site.yaml` controls which mode the homepage renders. It is exposed in Admin2's Site Configuration panel via a new site config blueprint. | `travelling` | Homepage mode | |---|---| | `true` | Active trip — map + live feed | | `false` | Between trips — map + highlights grid | The `active_trip` value changes format: it now stores the full page route (`/trips/italy-2026-demo`) instead of the bare slug (`italy-2026-demo`), because it will be managed via a `type: pages` dropdown in Admin2 rather than a free-text field. --- ## 2. Data model changes ### 2a. New file: `user/blueprints/config/site.yaml` Exposes site config fields in Admin2: ```yaml active_trip: type: pages label: Active Trip start_route: '/trips' show_root: false show_slug: true travelling: type: toggle label: Currently Travelling highlight: 1 default: false ``` ### 2b. `user/config/site.yaml` — value format update ```yaml # Before active_trip: italy-2026-demo # After active_trip: /trips/italy-2026-demo travelling: false ``` ### 2c. Trip page blueprint (`user/themes/intotheeast/blueprints/trip.yaml`) Add one field: ```yaml tagline: type: text label: Tagline help: Short description shown on homepage highlight cards (e.g. "6 weeks from Venice to Sicily by train") ``` ### 2d. Entry blueprint (`user/themes/intotheeast/blueprints/entry.yaml`) Add one field: ```yaml featured: type: toggle label: Featured highlight help: Show this entry as a homepage highlight when not travelling default: false ``` ### 2e. Story blueprint (`user/themes/intotheeast/blueprints/story.yaml`) Add the same `featured` toggle (identical definition). Stories are not auto-included — they opt in the same way as journal entries. --- ## 3. Layout The two-column structure is always present regardless of mode. ``` ┌────────────────────────┬────────────────────────────────┐ │ │ │ │ MapLibre map │ Right column │ │ (sticky, │ (switches by mode) │ │ always visible) │ │ │ │ │ └────────────────────────┴────────────────────────────────┘ ``` - Map: left column, ~45% width, `position: sticky; top: 0; height: 100vh` - Right column: ~55% width, scrollable - Mobile: map stacks on top at `40vh`, right column scrolls below --- ## 4. Active trip mode (`travelling: true`) ### Right column Chronological feed, newest first. Merges journal entries and story cards from the active trip's `/dailies` and `/stories` sub-pages. This is the existing feed behaviour — no changes to card markup or order logic. Trip title and entry counts shown above the feed. ### Map - Marker per journal entry with `lat`/`lng` in frontmatter - Journey line connecting markers in order - GPX route files loaded from the active trip page media (same pattern as `map.html.twig`, including the smart connector-suppression logic from the GPX connector spec) - Clicking a marker scrolls to that entry card in the feed ### Template change (`home.html.twig`) The slug-based path construction is replaced with direct route usage: ```twig {# Before #} {% set slug = config.site.active_trip %} {% set trip = grav.pages.find('/trips/' ~ slug) %} {% set dailies_page = grav.pages.find('/trips/' ~ slug ~ '/dailies') %} {% set stories_page = grav.pages.find('/trips/' ~ slug ~ '/stories') %} {# After #} {% set trip_route = config.site.active_trip %} {% set trip = grav.pages.find(trip_route) %} {% set dailies_page = grav.pages.find(trip_route ~ '/dailies') %} {% set stories_page = grav.pages.find(trip_route ~ '/stories') %} ``` --- ## 5. Between-trips mode (`travelling: false`) ### Highlight selection logic 1. Collect all published trip pages from `/trips` 2. For each trip, collect all published children from `/dailies` and `/stories` where `featured: true` 3. From each trip's candidates, pick one at random (`random()`) 4. Gather the per-trip picks into a pool; if more than 6 trips have candidates, randomly discard down to 6 5. Shuffle the final pool so cards appear in random order (not grouped by trip) ### Right column A grid of highlight cards. Below the grid, a "Explore all past trips →" CTA linking to `/trips`. **Grid layout:** 3 columns on desktop, 2 on tablet, 1 on mobile. ### Highlight card anatomy ``` ┌──────────────────────────┐ │ [hero image] │ ├──────────────────────────┤ │ ✦ Story / ◎ Journal │ ← type badge │ Entry title │ ← links to entry page │ Italy 2025 │ ← trip title │ "tagline from trip" │ ← trip tagline │ → View trip │ ← links to trip page └──────────────────────────┘ ``` - Hero image: `entry.media.images|first` if no `hero_image` frontmatter field; cropped to 16:9 - Type badge: `✦ Story` (accent colour) or `◎ Journal` (muted) - Entry title: full clickable link to the entry URL - Trip title + tagline: small secondary text; trip title links to the trip page - "→ View trip": explicit CTA link to the trip page Cards with no hero image still render but without an image block. ### Map - Marker per highlighted entry that has `lat`/`lng` in frontmatter - No journey line between markers (entries are from different trips) - No GPX data loaded - Map fits bounds across all markers; falls back to a world-level zoom if no entries have coordinates - Clicking a marker scrolls to that highlight card --- ## 6. Files changed | File | Change | |---|---| | `user/blueprints/config/site.yaml` | **Create** — exposes `active_trip` (pages) + `travelling` (toggle) in Admin2 | | `user/config/site.yaml` | **Update** — `active_trip` value to full route; add `travelling: false` | | `user/themes/intotheeast/blueprints/trip.yaml` | **Update** — add `tagline` text field | | `user/themes/intotheeast/blueprints/entry.yaml` | **Update** — add `featured` toggle | | `user/themes/intotheeast/blueprints/story.yaml` | **Update** — add `featured` toggle | | `user/themes/intotheeast/templates/home.html.twig` | **Update** — mode branch, route-based lookup, highlights logic, GPX loading | | `user/themes/intotheeast/css/style.css` | **Update** — highlight card styles, grid layout | No new plugins. No build pipeline. All changes in `user/`. --- ## 7. Constraints - `post-form.md` (`pageconfig.parent`) remains manually synced with `active_trip` — this is unchanged behaviour documented in CLAUDE.md - The `type: pages` field in Admin2 is confirmed present in the bundle but untested in a user site config blueprint; if it does not render, fall back to `type: select` with static trip slug options (one-minute fix, no other code changes needed) - Random selection uses Twig's `random()` — order varies per page load; this is intentional