Skip to content
← All starter build updates

Travel starter

Meridian

A thoughtful travel planner for collecting places and organizing an itinerary.

Live on VuraUpdated

Guide context carries into the planner without silently replacing saved plans. Rich logistics, coherent fixed-slot movement and the current-state route map are verified on desktop and mobile.

Meridian: actual released desktop product view after the shared typography refinement.
Preview captured · Explore the product ↗

Build phase

  1. PlannedComplete
  2. BuildingComplete
  3. Local checks passedComplete
  4. In reviewComplete
  5. Live on VuraCurrent phase

This tracks the recorded release phase. The checks below include later findings and ongoing refinements.

Product scope and intended patterns

The following describes the intended reference. Features are not a verification claim; recorded check results below define what has actually been tested.

Build-time rendered public content with client-mounted interactive islands.

Learning journal

How to read this starter

Meridian is a static travel-planning reference with build-time guide pages and a client-mounted itinerary planner island.

Source map

Server route renderer

src/server/render.mjs

Every guide, alias, planner, build and not-found page renders with h() and renderToString().

Planner island

src/client/main.jsx

Signals store stops, timezone, export text and storage mode; computed values group stops by day.

Static build script

scripts/build.mjs

The build rewrites the Vite asset name, writes static pages, sitemap, robots and manifest.

Browser smoke

scripts/smoke.mjs

The smoke checks direct routes, reorder, timezone switch, JSON export, corrupt storage, denied storage and 404.

Guide plans and slot movement

src/content.mjs

Known guide records seed local plans; pure movement swaps activities while retaining destination day/time slots.

Responsive application stylesheet

src/styles.css

Start-aligned planner controls and larger mobile SVG text preserve the actual itinerary geometry.

Code patterns worth copying

Decode escaped script JSON before mounting

src/client/main.jsx

The server renderer escapes script content. The planner island decodes entities before JSON.parse so the static payload stays readable and safe.

const data = safeJson(decodeEntities(document.querySelector('#meridian-data')?.textContent || '')) || { sampleStops: [], guides: [] };

Group route state from one stop list

src/client/main.jsx

The exported JSON, day cards and timezone preview follow the same source signals.

const exportText = useSignal('');

Move activities without moving the schedule clock

src/content.mjs

Slots own their clock labels. The guide query selects known records; saved plans win until the visitor explicitly applies a guide.

next[index] = { ...items[target], day: items[index].day, time: items[index].time };
  next[target] = { ...items[index], day: items[target].day, time: items[target].time };

Fit planner controls to their content

src/styles.css

Start-aligned planner controls and larger mobile SVG text preserve the actual itinerary geometry.

.controls { display: grid; gap: 16px; align-self: start; align-content: start; }

Real issues and fixes

Grid children stretch unless controls opt out

Problem
The trip controls lived beside tall itinerary cards, so the grid stretched the controls panel into a heavy block.
Fix
The controls panel opts out with align-self and align-content start while the itinerary can keep its taller rhythm.
Proof
The smoke captures the production page after timezone switching and route export from the generated static artifact.
Takeaway
A small CSS alignment rule can make an island feel intentional instead of stretched by its sibling content.

SSG JSON is HTML-escaped by the renderer

Problem
The static route embeds guide data in a script tag, and server rendering escapes that text before the client reads it.
Fix
Decode HTML entities and tolerate missing or malformed JSON before mounting the planner island.
Proof
The smoke test exports a route plan after a production build, proving the planner received sample stops.
Takeaway
Static script JSON needs the same rendering-boundary care as visible HTML.

Before

const data = JSON.parse(document.querySelector('#meridian-data').textContent);

After

const data = safeJson(decodeEntities(document.querySelector('#meridian-data')?.textContent || ''));

Reordering activities could reverse the clock

Problem
Moving an activity retained its old timestamp while hard-coding day reassignment, allowing a later time to appear before an earlier one.
Fix
Swap activities into destination day/time slots. Resolve known guide context, preserve existing saved plans, and project current stops in the mounted SVG. Label timezone output as a fixed reference instant, not conversion of undated stops.
Proof
Pure tests cover guide plans and slot stability; browser tests cover contextual plans, exported guide ids, reorder and storage failure.
Takeaway
Distinguish activity identity, schedule slots and real timestamps before implementing itinerary movement.

Measure SVG labels after responsive scaling

Problem
An SVG can fit the viewport while its text becomes too small as the viewBox scales.
Fix
Retain the 400-by-120 route coordinates and increase mobile route-map text to 18px.
Proof
The local style-browser suite visits home, guide, planner and build at multiple widths and measures rendered map-label height.
Takeaway
Verify rendered text dimensions as well as logical SVG geometry.

What went smoothly

  • Guide aliases and sitemap rows come from the same route list, which keeps direct static paths and metadata aligned.
  • Move buttons made itinerary reordering keyboard and touch friendly without needing drag/drop code.
  • Native move buttons reused pure plan operations; guide context and the reactive route projection did not require drag/drop or a map service.
  • Route maps retain their 400-by-120 SVG coordinates; larger mobile labels compensate for scaling while content-fit planner controls keep itinerary actions together.

Boundaries to preserve

  • Trip data is fictional and local-only.
  • The planner is client-mounted over static fallback HTML; it is not SSR-preserving hydration.

Verification record

Build journal

  1. · Live on Vura

    Shared typography release captured from production

    Published shared typography and responsive control refinements are tied to the exact live deployment and source revision. Actual released captures replace the previous gallery preview; existing product behavior and source-grounded lessons are retained.

  2. · Live on Vura

    Product-depth iteration released and exercised

    Guide context carries into the planner without silently replacing saved plans. Rich logistics, coherent fixed-slot movement and the current-state route map are verified on desktop and mobile.

  3. · Live on Vura

    Reviewed source ready for release verification

    Unique product identities and deeper workflows are implemented and independently reviewed. Existing releases remain accessible while new source is published and fresh deployments are exercised.

  4. · Live on Vura

    Product-depth iteration in progress

    Carrying selected guide context into the planner and reconciling itinerary order, days and times. The current source and deployment links still identify the previous verified release.

  5. · Live on Vura

    Live corrections verified after independent follow-up

    Planner controls stay compact, day headings and time columns are legible, and the route SVG uses actual sample stops. Reordering and reload persistence passed.

  6. · Live on Vura

    Design refinement released for live workflow review

    Planner controls stay compact, day headings and time columns are legible, and the route SVG uses actual sample stops. Reordering and reload persistence passed.

  7. · Live on Vura

    Independent live design review started

    The existing public app remains available while a new design review examines hierarchy, typography, navigation and workflow clarity. Actual findings and before/after repairs will be recorded as they are verified.

  8. · Live on Vura

    Hosted reference rechecked after documentation review

    Public source, green CI and the live app were checked together after the clean-machine documentation pass. Lessons and limitations now reflect the implemented code rather than pending pre-release work.

  9. · Live on Vura

    Final source and CI checkpoint verified

    The public source and build reference match the released learning journal, and the source workflow is green. The demo remains live at the same verified deployment; README and CI-only refinements did not change application code.

  10. · Live on Vura

    Clean-machine browser setup documented

    The README now installs the locked Chromium engine after npm ci and explains the Linux system-library prerequisite. The hosted application is unchanged; code examples, repair notes and boundaries remain source-backed.

  11. · Live on Vura

    Public template and Vura release

    The reviewed implementation is available from its independent repository and real hosted URL. Detailed code examples and actual repair notes are linked below.

  12. · In review

    Design review cleared; release verification underway

    The local implementation is complete and revised visual evidence has passed review. Source and demo links will appear only after publication and hosted verification.

  13. · In review

    Local build ready for specialist review

    The implementation owner completed the local build and workflow checks. No public source release or hosted verification is claimed yet.

  14. · Building

    Implementation started

    The standalone project files exist and the product build is active. No local verification or live release is claimed yet.

  15. · Planned

    Product scope recorded

    This is a planned starter, not a working release. Implementation, tests, public source and deployment evidence will be added as they are completed.

Implementation lessons

Known limitations

Remaining work and blockers

No release blockers are recorded for this snapshot.

Using this as an agent reference

Read the public README and BUILD.md, reproduce the recorded checks and inspect the source before adapting the starter. A live demo, where available, provides separate deployed evidence.