- milestone specs: docs/milestone-*-spec.md → docs/working/milestones/milestone-*.md - qa files: docs/qa-*.md → docs/working/qa/*.md - research files: docs/research-*.md → docs/research/*.md - design spec: docs/design/design-spec.md → docs/reference/design-system.md - backlog, pm-analysis, summary: moved to docs/working/
16 KiB
Into the East — Design Spec
Date: 2026-06-18
Status: Approved for implementation
1. Direction
The brief: A personal travel journal, sole author, trip to East Asia. Three weeks to implement before departure. Audience is both friends/family and the occasional curious stranger.
The position: Neither Polarsteps nor FindPenguins. Both optimize for social sharing of travel data. This site optimizes for the story — and should feel like reading a well-edited travel journal, not using an app.
What we steal from each:
- Polarsteps: photography-first hierarchy, airy whitespace, map as the emotional spine of the trip
- FindPenguins: typography as brand identity, stats as trophy case, hierarchical trip → entry structure
What we do better than both:
- Web-native: fast, linkable, no install, works on any browser
- Single author = pure editorial voice, no social noise
- Full CSS control = real typographic identity, not generic app chrome
- Editorial feel: more travel magazine, less productivity dashboard
Aesthetic direction: Field notes. The kind of journal a thoughtful traveler would carry — clean, direct, lets the photography speak. Sophisticated without effort.
The one aesthetic risk: Full-bleed hero photography with a translucent date+location overlay at the bottom of each card. The photo IS the entry card — not a thumbnail beside text. This is the single element that distinguishes this design from both reference apps and from typical blog layouts.
2. Color System
Palette
| Token | Hex | Usage |
|---|---|---|
--color-ink |
#17171A |
Primary text (near-black with cool undertone, like ink) |
--color-ink-2 |
#4A4850 |
Secondary text, body paragraphs |
--color-ink-muted |
#9896A0 |
Labels, timestamps, captions, placeholder text |
--color-paper |
#F7F5F2 |
Page background (warm paper white, not blue-white) |
--color-canvas |
#FFFFFF |
Card backgrounds, modals, form surfaces |
--color-border |
#E8E6E3 |
Standard dividers, card borders |
--color-border-soft |
#F0EDEA |
Subtle section dividers |
--color-accent |
#1F6B5A |
Deep teal — brand color, links, CTAs, active states |
--color-accent-hover |
#185647 |
Darkened accent for hover/pressed states |
--color-accent-light |
#EBF5F2 |
Pale teal for highlight backgrounds |
--color-accent-on |
#FFFFFF |
Text on accent-colored surfaces |
Rationale for accent color
Deep teal #1F6B5A was chosen over:
- Blue (#0066cc current): too generic, too tech
- Orange/saffron: clichéd for "Asia" travel design
- Terracotta/cream: the most common default for lifestyle/travel blogs
Teal evokes bamboo, celadon porcelain, ancient jade, the color of temple gardens — all without being literal or kitsch. It works cleanly against both the warm paper background and white card surfaces.
3. Typography
Fonts
| Role | Family | Fallback | Source |
|---|---|---|---|
| Display / Headings | DM Serif Display | Georgia, serif | Google Fonts |
| UI / Body / Labels | DM Sans | -apple-system, BlinkMacSystemFont, sans-serif | Google Fonts |
Google Fonts URL:
https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,400;0,9..40,500;0,9..40,600;1,9..40,400&family=DM+Serif+Display:ital@0;1&display=swap
Why this pairing: DM Serif Display has a calligraphic quality — slightly editorial, authoritative but not stiff. Paired with DM Sans (its designed companion) the system is cohesive. DM Sans is neutral and highly legible at all sizes. Both are under-used relative to Inter/Lato/Playfair, so the combination has a distinctive voice without being trendy.
Type Scale
| Token | Size | Line Height | Usage |
|---|---|---|---|
--text-xs |
0.75rem (12px) | 1.5 | Badges, captions |
--text-sm |
0.875rem (14px) | 1.5 | Meta, timestamps, labels |
--text-base |
1rem (16px) | 1.65 | Body paragraphs |
--text-md |
1.125rem (18px) | 1.55 | Lead text, intro paragraphs |
--text-lg |
1.375rem (22px) | 1.35 | Subheadings, card titles (mobile) |
--text-xl |
1.75rem (28px) | 1.25 | Entry card titles |
--text-2xl |
2.25rem (36px) | 1.2 | Page headings, entry titles (desktop) |
--text-3xl |
3rem (48px) | 1.1 | Hero entry title |
Usage rules
- Entry titles:
--font-display,--text-xl(mobile) /--text-2xl(desktop) - Site title in header:
--font-display,--text-lg - All other UI text:
--font-ui - Body paragraphs:
--font-ui,--text-base,--leading-normal - Timestamps/badges:
--font-ui,--text-xs, uppercase,letter-spacing: 0.07em
4. Spacing & Layout
Spacing scale (4px base unit)
| Token | Value |
|---|---|
--space-1 |
0.25rem (4px) |
--space-2 |
0.5rem (8px) |
--space-3 |
0.75rem (12px) |
--space-4 |
1rem (16px) |
--space-5 |
1.25rem (20px) |
--space-6 |
1.5rem (24px) |
--space-8 |
2rem (32px) |
--space-10 |
2.5rem (40px) |
--space-12 |
3rem (48px) |
--space-16 |
4rem (64px) |
Layout
- Content max-width:
720px(comfortable reading at any font size) - Page horizontal padding:
1.25rem(mobile),1.5rem(desktop ≥520px) - Header height:
60px(fixed, for JS offset calculations) - Map page: full viewport, no content max-width constraint
Border radius
| Token | Value | Usage |
|---|---|---|
--radius-sm |
4px | Photo corners, small chips |
--radius-md |
8px | Cards, buttons, inputs |
--radius-lg |
12px | Large cards, modals |
--radius-full |
9999px | Pills, badges |
Shadows
| Token | Value | Usage |
|---|---|---|
--shadow-sm |
0 1px 3px rgba(0,0,0,0.08) |
Stat blocks, subtle elevation |
--shadow-md |
0 4px 12px rgba(0,0,0,0.10) |
Cards on hover, dropdowns |
--shadow-lg |
0 8px 24px rgba(0,0,0,0.14) |
Lightbox, modals |
5. Component Inventory
5.1 Site Header
[ into the east ] [ Journal Map Stats ]
← accent bar across top (3px) ───────────────────────────────
- Top border:
3px solid var(--color-accent)— thin accent bar signals the brand color without decorating - Site title: DM Serif Display,
--text-lg, no decoration - Nav links: DM Sans,
--text-sm, weight 500,--color-ink-2 - Active nav link:
--color-accent, weight 600 - Mobile: same layout, title slightly smaller, nav links compact
- Background:
--color-canvas(white), bottom border1px solid var(--color-border)
5.2 Entry Feed Card — With Photo
┌─────────────────────────────────────┐
│ │
│ [photo] │ ← full-width, 16:9, rounded corners
│ │
│ 18 JUN · 📍 Kyoto, Japan │ ← overlaid at bottom, gradient mask
└─────────────────────────────────────┘
Arrived in Tokyo ← DM Serif Display, --text-xl
After 14 hours of flying I finally ← body excerpt, --color-ink-2
set foot on Japanese soil...
Read entry → ← --color-accent, --text-sm
- Photo:
aspect-ratio: 16/9,object-fit: cover,border-radius: var(--radius-md) - Photo has a
linear-gradient(to top, rgba(0,0,0,0.55), transparent)overlay at the bottom 40% - Date + location sit on top of gradient in white text (
rgba(255,255,255,0.92)) - On hover: photo scales to 1.03 (subtle zoom, 0.4s ease)
- Title below photo: DM Serif Display, hover turns
--color-accent - Card separation:
padding-bottom: var(--space-12)+border-bottom: 1px solid var(--color-border)
5.3 Entry Feed Card — No Photo
When no photo is available, fall back to a text-only layout:
18 JUN 2026 · 📍 Kyoto, Japan ← meta row, --text-sm, --color-ink-muted
Arrived in Tokyo ← DM Serif Display, --text-xl
After 14 hours of flying...
Read entry →
- No photo container
- Meta (date + location) on one line above title, small + muted
5.4 Single Entry Page
Wednesday, 18 June 2026 ← --text-sm, --color-ink-muted, uppercase
📍 Kyoto, Japan · ⛅ Partly cloudy · 22°C
Arrived in Tokyo ← DM Serif Display, --text-2xl / --text-3xl
─────────────────────────────────────
Body text content... ← --font-ui, --text-base/md
[Photo gallery — 2 or 3 col grid]
← Back to journal
- The entry title uses
--font-displayat largest scale - A thin
--color-borderrule separates the header from the body - Body text is
--text-md(18px) for comfortable long-form reading - Full-bleed hero option: if a
hero_imageis set, it spans the full content width with a bottom margin
5.5 Post Form (Author View)
New Entry
Title * [________________________]
Date & Time [2026-06-18 14:30 ]
What happened [ ]
today? [ ]
[ ]
Photos [ + Add photos (max 4) ]
City [________________________]
Country [________________________]
[ 📍 Get Location ] [ 🌤 Get Weather ]
✓ Location captured: Kyoto, Japan ← status line
[ Post Entry ]
UX changes from current:
- Lat/lng inputs hidden from the UI (remain in the form as
display:nonefor data capture, filled by JS) - Location status shows captured city/country + coordinates in a single line (not separate status paragraphs)
- Photo upload area: larger touch target, visual indication of count
- "Post Entry" button:
--color-accentbackground, full-width on mobile,min-height: 52px - Form fields:
--radius-mdcorners,--color-borderborder, focus ring in--color-accent - Section spacing: generous vertical rhythm on mobile
5.6 Stats Page
┌────────────┐ ┌────────────┐
│ 42 │ │ 18 │
│ days on │ │ entries │
│ the road │ │ posted │
└────────────┘ └────────────┘
┌────────────┐ ┌────────────┐
│ 6 │ │ ~14,200 │
│ countries │ │ km │
│ visited │ │ traveled │
└────────────┘ └────────────┘
Countries visited
Japan · South Korea · Mongolia · Russia · Finland · Estonia
- Numbers:
--font-display,--text-3xl,--color-accent - Labels:
--font-ui,--text-xs, uppercase,--color-ink-muted - Cards: white,
--shadow-sm,--radius-md, centered
5.7 Map Page
Minimal changes — the map itself is good. Style improvements:
- Leaflet popups: match the new design (DM Sans,
--radius-md,--shadow-md) - Markers: keep current circle style, update color to
--color-accent - Feed mini-map wrapper: match
--radius-md,--border
6. UX Flows
6.1 Reader — First Visit
- Land on
/tracker(journal feed) - See mini-map above fold (if entries exist) — route tells the geographic story at a glance
- First entry card: full-bleed hero photo with date/location overlay — immediate emotional pull
- Scroll through chronological entries
- Tap/click entry → entry detail page
- Navigate back via "← Back to journal"
Key principle: The reader should understand the journey spatially (mini-map) and emotionally (hero photo) before reading a single word.
6.2 Reader — Navigation
- Journal: primary destination, the feed
- Map: geographic exploration mode
- Stats: quick numbers, satisfying progress indicator
- No account required, no social friction, no login prompt for readers
6.3 Author — Posting from Mobile
- Navigate to
/post(bookmark on home screen) - Already logged in (Grav session persists) — form loads directly
- Title: tap → type (autofocused)
- Date & Time: auto-filled to now, adjust if needed
- Content: write what happened
- Photos: tap "Add photos" → camera or gallery → select up to 4
- Location: tap "📍 Get Location" → GPS fires → status shows "Kyoto, Japan · 34.985, 135.758" in one line
- Weather: tap "🌤 Get Weather" (works only if location was captured) → status shows "Partly cloudy · 22°C"
- City/Country: auto-populated from GPS is a nice-to-have for v2; in v1 type manually if needed
- Tap "Post Entry" → success message → 2-second pause → redirect to /tracker (new entry visible at top)
Key principles:
- One-thumb operation for all critical actions on mobile
- Location/weather are conveniences, not blockers — can skip both
- Visual feedback is immediate (status line updates on GPS response)
- After submit: don't leave author on a success message page; redirect to see their new post
7. Mobile Specifics
Touch targets
- All interactive elements:
min-height: 44px,min-width: 44px(Apple HIG standard) - Form buttons:
min-height: 52pxon the post form (primary CTA) - Nav links:
padding: 0.5rem 0.75rem
Viewport concerns
- Map page:
height: calc(100vh - 60px),touch-action: noneon map container — prevents scroll trap - Photo lightbox: full viewport overlay, swipe-friendly (keyboard + click already implemented)
- Form on mobile: single-column, generous input padding
0.875rem 1rem,font-size: 1rem(prevents iOS zoom on focus)
Performance
- Google Fonts: loaded with
preconnecthints - Images:
loading="lazy"on all non-above-fold images (already in place) - Leaflet: loaded from CDN, only on pages that need it
- No new JS frameworks — vanilla JS throughout
8. Tech Stack Decision
Keep Grav CMS. With a 3-week timeline, replacing it would consume all available time on migration rather than design improvements.
| Layer | Decision | Rationale |
|---|---|---|
| Backend | Grav CMS (PHP, Twig) — unchanged | Works, flat-file, no DB |
| CSS | Vanilla CSS + custom properties (design tokens) | No build step, full control, ships as one file |
| JS | Vanilla JS — unchanged | Current JS is well-structured, scope doesn't justify a framework |
| Icons | Unicode + emoji (current) | No dependency, works everywhere |
| Fonts | Google Fonts via CDN | Two fonts, display-swap, negligible impact |
| Maps | Leaflet.js (current) | Already in use, no reason to change |
| Build | None — no build pipeline | Grav's asset pipeline handles minification if needed |
No Alpine.js, no TypeScript, no Tailwind. The site has clean vanilla JS and CSS today; a redesign is about visual quality, not framework migration. Introducing a build pipeline on a 3-week timeline is a distraction.
9. What Changes From Current Design
| Area | Current | New |
|---|---|---|
| Typography | System sans-serif only | DM Serif Display for headings + DM Sans for UI |
| Accent color | #0066cc (generic blue) |
#1F6B5A (deep teal) |
| Background | #ffffff (pure white) |
#F7F5F2 (warm paper) |
| Entry cards | Thumbnail + text below | Full-bleed 16:9 photo with overlay |
| Header | No visual identity | Accent top-border, typographic title |
| Design tokens | Hardcoded values throughout | CSS custom properties throughout |
| Post form | Lat/lng visible inputs | Lat/lng hidden, single status line |
| Font loading | None | Google Fonts DM pairing |
| Hover states | Minimal | Photo zoom, title color change |
| Stat numbers | #0066cc |
--color-accent (#1F6B5A) |