Commit graph

54 commits

Author SHA1 Message Date
Ullrich Schäfer
55806fc84a
Fix waypoint drag, host election, segment routing, debug panel
Waypoint drag:
- Use observeDeep instead of observe to detect Y.Map property changes

Host election:
- Extracted to host-election.ts with 8 unit tests
- Simple rule: lowest real client ID is always host, deterministic
- Always sets role (host or participant), no missing roles
- Filters server docs (empty awareness state) from election

BRouter routing:
- Route segment-by-segment like bikerouter.de (one request per
  waypoint pair), guarantees route passes through every waypoint
- Merge GeoJSON segments with accumulated stats
- 8 unit tests for segment merging and waypoint splitting

Awareness cleanup:
- Track client IDs per WebSocket connection
- Immediately remove awareness on WebSocket close

Debug panel:
- Visibility + expanded state persisted in localStorage
- Hotkey (Shift+Cmd+Option+T) toggles visibility
- Labels server docs as (server)
- All logic self-contained in YjsDebugPanel.tsx

User identity:
- Color and name persisted in localStorage across reloads

Tests: 32 total (16 existing + 8 host election + 8 routing)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 08:52:52 +01:00
Ullrich Schäfer
2e5c31d117
Add animated progress bar during route computation
Blue sliding progress bar appears at the top of the map while
BRouter is computing a route. Overlays on top of Leaflet map
with z-index 1000.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 08:34:34 +01:00
Ullrich Schäfer
6ee07f0570
Fix waypoint icons and add elevation chart scrubbing
Waypoint icons:
- Replace broken Leaflet default icons with numbered blue circles
- Numbers match sidebar order (1, 2, 3...)

Elevation chart:
- Mouse hover shows crosshair, elevation, and distance at cursor
- Red dot appears on the map at the corresponding route position
- Dot disappears when mouse leaves the chart

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 07:04:04 +01:00
github-actions[bot]
ce0cd84562
Merge pull request #22 from trails-cool/fix-automerge-triggers 2026-03-23 00:20:28 +00:00
Ullrich Schäfer
1e8e01f8e3
Add all recommended triggers to automerge action
Use the full set of triggers from pascalgn/automerge-action docs:
pull_request (labeled, synchronize, opened, etc), pull_request_review,
check_suite, and status events.

Replaces workflow_run trigger which wasn't firing reliably after
the label was added before CI completed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 01:18:54 +01:00
Ullrich Schäfer
526f721547
Merge pull request #21 from trails-cool/finish-planner-ui
Complete Planner UI: profile selector, elevation chart, GPX export
2026-03-23 01:18:16 +01:00
Ullrich Schäfer
f795406e77
Revert "Add all recommended triggers to automerge action"
This reverts commit 5f353f6320.
2026-03-23 01:18:04 +01:00
Ullrich Schäfer
5f353f6320
Add all recommended triggers to automerge action
Use the full set of triggers from pascalgn/automerge-action docs:
pull_request (labeled, synchronize, opened, etc), pull_request_review,
check_suite, and status events.

Removes workflow_run trigger which wasn't firing reliably.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 01:17:05 +01:00
Ullrich Schäfer
230094b956
Fix Yjs WebSocket in dev mode
- Add Vite plugin implementing y-protocols sync server for dev mode
- Fix useYjs hook: move provider creation into useEffect to survive
  React StrictMode remounts
- Fix WebSocket URL: use /sync as base (y-websocket appends room name)
- Verified in browser: Connected status, Host badge, awareness working

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 01:12:13 +01:00
Ullrich Schäfer
49e9d589b1
Fix: recompute route on profile change
Added Y.Map observer on routeData that triggers route recomputation
when the 'profile' key changes. Previously profile changes synced
via Yjs but didn't trigger a new BRouter request.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 00:58:31 +01:00
Ullrich Schäfer
54b6232c5d
Complete Planner UI: profile selector, elevation chart, GPX export
- ProfileSelector: dropdown synced via Y.Map, triggers route recompute
  (Hiking, Cycling fast/safe, Shortest, Car profiles)
- ElevationChart: canvas-based elevation profile extracted from BRouter
  GeoJSON, shows min/max elevation and distance
- ExportButton: generates GPX from current waypoints + route track,
  downloads as route.gpx

All Groups 5 + 6 tasks complete.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 00:57:39 +01:00
github-actions[bot]
b83384ab17
Merge pull request #20 from trails-cool/fix-automerge-ready-state 2026-03-22 23:51:37 +00:00
Ullrich Schäfer
e40b7dc199
Fix SSR and automerge timing
SSR fix:
- ClientOnly wrapper prevents Leaflet/Yjs from running during SSR
- SessionView lazy-loaded to avoid browser API usage on server

Automerge fix:
- Set MERGE_READY_STATE to 'clean' only (was including 'unstable')
- Prevents merging before all CI checks complete

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 00:49:54 +01:00
github-actions[bot]
e0cce17b8d
Merge pull request #19 from trails-cool/planner-map-ui 2026-03-22 23:33:17 +00:00
Ullrich Schäfer
af70c822ee
Implement Planner map UI with collaborative editing (Groups 5+6)
Core Planner experience:
- Full-screen Leaflet map with OSM/OpenTopoMap/CyclOSM layers
- Click to add waypoints, drag to move, right-click to delete
- Waypoint sidebar with reorder, delete, route stats
- Real-time Yjs sync between participants
- Live cursors showing other users' mouse positions on the map

Routing:
- Host election via Yjs awareness (lowest client ID)
- Auto-failover when host disconnects
- Debounced BRouter route computation (500ms)
- Route polyline display from BRouter GeoJSON
- Route stats (distance, elevation gain/loss)

Client-side architecture:
- useYjs hook: WebSocket connection, awareness, document management
- useRouting hook: host election, route computation, stats parsing
- PlannerMap component: Leaflet + Yjs integration
- WaypointSidebar component: list with reorder/delete
- Lazy-loaded components for code splitting

Remaining: elevation chart, profile selector, GPX export (tasks 6.7-6.9)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 00:32:51 +01:00
github-actions[bot]
9eee93b27b
Merge pull request #18 from trails-cool/fix-automerge-timing 2026-03-22 23:27:02 +00:00
Ullrich Schäfer
33edeb17fb
Fix automerge: wait for full CI workflow, not individual checks
Changed trigger from check_suite to workflow_run on CI workflow.
This ensures all jobs (typecheck, lint, test, build, e2e) pass
before auto-merging, not just the first check to complete.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 00:26:48 +01:00
github-actions[bot]
49202899a8
Merge pull request #17 from trails-cool/fix-esbuild-vuln 2026-03-22 23:25:24 +00:00
Ullrich Schäfer
2fe8c93edb
Fix esbuild security vulnerability (Dependabot #1)
Override esbuild >=0.25.0 to fix CVE in dev server that allows
cross-origin requests. The vulnerable 0.18.20 was pulled in
transitively via drizzle-kit → @esbuild-kit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 00:25:09 +01:00
github-actions[bot]
d1f1bef2eb
Merge pull request #16 from trails-cool/fix-automerge-node24 2026-03-22 23:22:33 +00:00
Ullrich Schäfer
18d8870745
Force automerge action to run on Node.js 24
pascalgn/automerge-action@v0.16.4 hasn't released a Node 24 build yet.
Use FORCE_JAVASCRIPT_ACTIONS_TO_NODE24 env var to suppress the warning.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 00:22:18 +01:00
github-actions[bot]
d868e78247
Merge pull request #15 from trails-cool/disable-squash-merge 2026-03-22 23:20:10 +00:00
Ullrich Schäfer
643dfc8c05
Switch from squash merges to regular merge commits
Squash merges caused orphaned commits when pushing after auto-merge.
Regular merges preserve full commit history and avoid this issue.

- Disabled squash and rebase merge on repo settings
- Updated automerge action: MERGE_METHOD squash → merge
- Updated CLAUDE.md workflow docs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 00:19:57 +01:00
Ullrich Schäfer
75c9f6901b
Add reverse DNS (PTR) records to Terraform config (#14) 2026-03-22 23:17:33 +00:00
Ullrich Schäfer
2f3bc9bd21
Warn against pushing to auto-merged branches in CLAUDE.md (#13) 2026-03-22 23:15:14 +00:00
Ullrich Schäfer
52b2baaf58
Add local dev setup, fix BRouter Dockerfile, archive change (#12) 2026-03-22 23:11:43 +00:00
Ullrich Schäfer
2d02ae3f9e
Add BRouter proxy, rate limiting, and spec updates (tasks 5.1-5.2) (#11) 2026-03-22 22:43:47 +00:00
Ullrich Schäfer
9deda5f125
Add Drizzle ORM with shared db package (#10) 2026-03-22 22:35:50 +00:00
Ullrich Schäfer
6a3e566438
Complete Planner session management (tasks 4.2, 4.6, 4.7) (#9) 2026-03-22 22:18:36 +00:00
Ullrich Schäfer
a9a6b27af4
Add IPv6 (AAAA) DNS records and www redirect (#8) 2026-03-22 22:06:49 +00:00
Ullrich Schäfer
4d1461c58d
Simplify automerge docs: use --label flag on gh pr create (#7) 2026-03-22 21:57:14 +00:00
Ullrich Schäfer
df731d9d90
Document automerge label workflow in CLAUDE.md (#6) 2026-03-22 21:55:31 +00:00
Ullrich Schäfer
9160301ab3
Add DNS records via Terraform, bump hcloud to v1.60 (#4)
- trails.cool and planner.trails.cool A records pointing to server
- Using hcloud_zone_rrset (native hcloud provider, no separate DNS provider)
- Bumped hcloud provider ~> 1.45 to ~> 1.60
- Server type updated to cx23

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 22:54:07 +01:00
Ullrich Schäfer
cd18436187
Add automerge GitHub Action (#5)
PRs labeled 'automerge' will squash-merge when all checks pass.
Uses pascalgn/automerge-action. No branch protection needed.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 22:53:08 +01:00
Ullrich Schäfer
f955fb9d6e
Fix BRouter Dockerfile: correct version and download URL (#3)
- Version 1.7.7 → 1.7.8 (latest release)
- Download URL needs v prefix on tag: v1.7.8

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 13:37:18 +01:00
Ullrich Schäfer
7908a518b1
Add infrastructure: Terraform, Docker Compose, BRouter, CD pipeline (#2)
Terraform:
- Hetzner CX22 server with Docker, firewall (80/443/22)
- SSH key and output for server IP

Docker Compose:
- Caddy reverse proxy (auto HTTPS)
- Journal and Planner app containers
- BRouter routing engine container
- PostgreSQL + PostGIS
- Garage S3 storage

BRouter:
- Dockerfile based on eclipse-temurin:11-jre
- Segment download script for Germany (4 tiles, ~750MB)

CD Pipeline:
- Build & push Docker images to ghcr.io on main push
- Deploy step commented out (enable when server provisioned)

Scripts:
- PostgreSQL daily backup with 14-day retention
- Dockerfiles for both apps (multi-stage builds)

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 13:32:01 +01:00
Ullrich Schäfer
464ba0f64d
Add Planner session management with Yjs WebSocket (#1)
- Yjs WebSocket server at /sync/:sessionId for real-time collaboration
- Session creation API (POST /api/sessions) with optional GPX initialization
- Session join page with Planner layout (header, map area, sidebar)
- In-memory session store (PostgreSQL persistence deferred to infra setup)
- Custom production server entry with WebSocket upgrade handling
- Vite path aliases (~/) for clean imports
- Fix tsconfig for apps: noEmit, exclude build dir

Tasks completed: 4.1, 4.3, 4.4, 4.5
Deferred: 4.2 (PostgreSQL), 4.6-4.8 (need client-side Yjs from Group 6)

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 13:26:03 +01:00
Ullrich Schäfer
6f90c59db9
Add PR-based git workflow to CLAUDE.md
All changes go through PRs from now on. Documents:
- Pre-PR checklist (typecheck, lint, test, e2e)
- Auto-merge with squash
- PR stacking for fast local iteration
- Emergency override for admins

This is the last direct push to main.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 13:18:58 +01:00
Ullrich Schäfer
2cfa5e54e7
Implement shared packages (tasks 2.1-2.6)
- @trails-cool/types: Route, Activity, Waypoint, RouteVersion, RouteMetadata
- @trails-cool/gpx: GPX parser (XML→waypoints/tracks/elevation) and generator
  with round-trip test, haversine distance, elevation gain/loss computation
- @trails-cool/map: MapView (Leaflet + OSM/OpenTopoMap/CyclOSM layer switcher),
  RouteLayer (GeoJSON polyline rendering)
- @trails-cool/ui: Button (primary/secondary/ghost), Input (with label/error),
  Card components with Tailwind styling
- @trails-cool/i18n: react-i18next config with English + German translations,
  browser language detection, fallback to English

All 13 unit tests pass. Both apps build successfully.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 13:09:35 +01:00
Ullrich Schäfer
325a4466d5
Bump CI actions to latest versions (Node 24 native)
- actions/checkout v4 → v6
- actions/setup-node v4 → v6
- actions/upload-artifact v4 → v7

Removes FORCE_JAVASCRIPT_ACTIONS_TO_NODE24 workaround — v6 actions
natively run on Node 24.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 12:59:47 +01:00
Ullrich Schäfer
5c525d8c40
Bump CI to Node.js 24, silence deprecation warning
Actions runtime and project node-version both set to 24.
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24 opts in early.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 12:57:52 +01:00
Ullrich Schäfer
f58fe99cde
Add GitHub Actions CI, wire ESLint, lock in Caddy
CI pipeline with parallel jobs for fast feedback:
- typecheck, lint, unit tests, build run in parallel
- e2e tests run after build
- Playwright artifacts uploaded on failure

ESLint wired into both apps with sensible defaults:
- underscore-prefixed unused vars allowed
- root package.json marked as type: module

Architecture updated: Caddy as reverse proxy with auto HTTPS.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 12:55:12 +01:00
Ullrich Schäfer
9ad2f5785e
Use pnpm instead of bare turbo in dev commands
turbo is a local devDependency, not globally installed. Using pnpm
as the entry point resolves the local binary correctly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 12:41:13 +01:00
Ullrich Schäfer
f2f0bd31ae
Add testing expectations to CLAUDE.md
Explicit instruction for coding agents: write tests alongside code,
run test suites before committing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 12:39:10 +01:00
Ullrich Schäfer
40b9c425a0
Add testing strategy: Vitest for unit tests, Playwright for E2E
- Vitest: unit tests for packages, components, and app logic (jsdom env,
  @testing-library/react, co-located test files)
- Playwright: E2E browser tests per app (journal.test.ts, planner.test.ts),
  auto-starts dev servers, scoped via testMatch
- Sample unit test for types package
- Smoke E2E tests for both apps
- Updated CLAUDE.md with test commands and strategy

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 12:36:09 +01:00
Ullrich Schäfer
4fac18c165
Add crit command and skill for inline code review
Sourced from https://github.com/tomasz-tomczyk/crit/tree/main/integrations/claude-code

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 12:31:08 +01:00
Ullrich Schäfer
b4c0ee954d
Add cmux skills (browser, debug-windows, markdown, core)
Skills for cmux terminal integration: browser automation for visual
verification, debug windows, markdown viewer, and core topology control.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 12:25:54 +01:00
Ullrich Schäfer
30d40de7cf
Complete monorepo toolchain setup (tasks 1.1-1.7)
- Turborepo + pnpm workspaces with catalog for shared dependency versions
- TypeScript strict config (base + per-package extends)
- Tailwind CSS v4 via @tailwindcss/vite plugin
- ESLint + Prettier shared config
- Planner app scaffolded with React Router 7 (port 3001)
- Journal app scaffolded with React Router 7 (port 3000)
- Both apps build and start successfully via turbo

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 12:12:57 +01:00
Ullrich Schäfer
48547fdc82
Add CLAUDE.md, README, and development tooling docs
- CLAUDE.md: project context for Claude Code sessions
- README.md: human-facing project intro, structure, getting started
- docs/tooling.md: cmux, Claude Code, Crit, and OpenSpec workflow

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 12:06:51 +01:00
Ullrich Schäfer
4214564fd8
Move conversation log into docs/conversations/
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 12:00:45 +01:00