Ullrich Schäfer
70319e702f
Bump i18next from 26.0.1 to 26.0.3 and react-i18next from 17.0.1 to 17.0.2
...
Previous attempt left duplicate i18next versions in the lockfile
(26.0.1 for @trails-cool/i18n peer dep, 26.0.3 for root). This caused
two different i18next instances at runtime, breaking i18n initialization
and leaving pages blank in E2E tests.
Fix: update specifiers and run pnpm dedupe to ensure a single version.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 23:29:26 +02:00
Ullrich Schäfer
279b043faf
Merge pull request #186 from trails-cool/deps/react-router
...
Bump react-router packages from 7.13.2 to 7.14.0
2026-04-06 22:21:41 +01:00
Ullrich Schäfer
03e945eb7b
Merge branch 'main' into deps/misc
2026-04-06 22:13:54 +01:00
Ullrich Schäfer
3b0436fe33
Bump react-router packages from 7.13.2 to 7.14.0
...
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 23:13:04 +02:00
Ullrich Schäfer
2a59fc0538
Bump postgres from 3.4.8 to 3.4.9 and isbot from 5.1.36 to 5.1.37
...
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 23:10:16 +02:00
Ullrich Schäfer
0af67bef0e
Bump eslint, typescript-eslint, and turbo
...
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 23:09:49 +02:00
Ullrich Schäfer
b6711d23d6
Add Wahoo activity sync with provider-agnostic framework
...
Provider-agnostic sync framework + Wahoo as first implementation:
Framework (apps/journal/app/lib/sync/):
- SyncProvider interface for OAuth2, webhooks, import, conversion
- Provider registry for settings UI iteration
- Generic sync_connections + sync_imports tables
- Token storage with auto-refresh
Wahoo provider:
- OAuth2 with workouts_read, user_read, offline_data scopes
- Webhook-based auto-import (workout_summary events)
- Manual import page with pagination
- FIT→GPX conversion via fit-file-parser
- Webhook token verification
Routes:
- /api/sync/connect/:provider — OAuth redirect
- /api/sync/callback/:provider — OAuth callback
- /api/sync/disconnect/:provider — remove connection
- /api/sync/webhook/:provider — webhook receiver
- /sync/import/:provider — manual import page
Settings: Connected Services section with per-provider connect/disconnect
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 11:22:02 +01:00
Ullrich Schäfer
79f000fcc5
Upgrade i18next v26 + react-i18next v17 with SSR-safe init
...
Split initI18n() into separate server/client initialization paths
inspired by remix-i18next's architecture:
- initI18nServer(lng): no LanguageDetector, per-request language from
Accept-Language header
- initI18nClient(): LanguageDetector reads <html lang> first to match
server, then localStorage and navigator
- detectLanguage(request): parses Accept-Language for best match
Fixes rehydration errors caused by v26 removing initImmediate option
(replaced with initAsync) and LanguageDetector running on the server
where browser APIs don't exist.
Also makes <html lang> dynamic instead of hardcoded "en".
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 11:38:36 +02:00
dependabot[bot]
aa4d491950
Bump the production group with 10 updates
...
Bumps the production group with 10 updates:
| Package | From | To |
| --- | --- | --- |
| [@react-router/dev](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dev ) | `7.13.1` | `7.13.2` |
| [@react-router/node](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-node ) | `7.13.1` | `7.13.2` |
| [@react-router/serve](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-serve ) | `7.13.1` | `7.13.2` |
| [drizzle-orm](https://github.com/drizzle-team/drizzle-orm ) | `0.45.1` | `0.45.2` |
| [react-router](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router ) | `7.13.1` | `7.13.2` |
| [turbo](https://github.com/vercel/turborepo ) | `2.8.20` | `2.8.21` |
| [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint ) | `8.57.1` | `8.57.2` |
| [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest ) | `4.1.0` | `4.1.2` |
| [@sentry/node](https://github.com/getsentry/sentry-javascript ) | `10.45.0` | `10.46.0` |
| [@sentry/react](https://github.com/getsentry/sentry-javascript ) | `10.45.0` | `10.46.0` |
Updates `@react-router/dev` from 7.13.1 to 7.13.2
- [Release notes](https://github.com/remix-run/react-router/releases )
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-dev/CHANGELOG.md )
- [Commits](https://github.com/remix-run/react-router/commits/@react-router/dev@7.13.2/packages/react-router-dev )
Updates `@react-router/node` from 7.13.1 to 7.13.2
- [Release notes](https://github.com/remix-run/react-router/releases )
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-node/CHANGELOG.md )
- [Commits](https://github.com/remix-run/react-router/commits/@react-router/node@7.13.2/packages/react-router-node )
Updates `@react-router/serve` from 7.13.1 to 7.13.2
- [Release notes](https://github.com/remix-run/react-router/releases )
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-serve/CHANGELOG.md )
- [Commits](https://github.com/remix-run/react-router/commits/@react-router/serve@7.13.2/packages/react-router-serve )
Updates `drizzle-orm` from 0.45.1 to 0.45.2
- [Release notes](https://github.com/drizzle-team/drizzle-orm/releases )
- [Commits](https://github.com/drizzle-team/drizzle-orm/compare/0.45.1...0.45.2 )
Updates `react-router` from 7.13.1 to 7.13.2
- [Release notes](https://github.com/remix-run/react-router/releases )
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router/CHANGELOG.md )
- [Commits](https://github.com/remix-run/react-router/commits/react-router@7.13.2/packages/react-router )
Updates `turbo` from 2.8.20 to 2.8.21
- [Release notes](https://github.com/vercel/turborepo/releases )
- [Changelog](https://github.com/vercel/turborepo/blob/main/RELEASE.md )
- [Commits](https://github.com/vercel/turborepo/compare/v2.8.20...v2.8.21 )
Updates `typescript-eslint` from 8.57.1 to 8.57.2
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases )
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md )
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.57.2/packages/typescript-eslint )
Updates `vitest` from 4.1.0 to 4.1.2
- [Release notes](https://github.com/vitest-dev/vitest/releases )
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.2/packages/vitest )
Updates `@sentry/node` from 10.45.0 to 10.46.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases )
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md )
- [Commits](https://github.com/getsentry/sentry-javascript/compare/10.45.0...10.46.0 )
Updates `@sentry/react` from 10.45.0 to 10.46.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases )
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md )
- [Commits](https://github.com/getsentry/sentry-javascript/compare/10.45.0...10.46.0 )
---
updated-dependencies:
- dependency-name: "@react-router/dev"
dependency-version: 7.13.2
dependency-type: direct:production
update-type: version-update:semver-patch
dependency-group: production
- dependency-name: "@react-router/node"
dependency-version: 7.13.2
dependency-type: direct:production
update-type: version-update:semver-patch
dependency-group: production
- dependency-name: "@react-router/serve"
dependency-version: 7.13.2
dependency-type: direct:production
update-type: version-update:semver-patch
dependency-group: production
- dependency-name: drizzle-orm
dependency-version: 0.45.2
dependency-type: direct:production
update-type: version-update:semver-patch
dependency-group: production
- dependency-name: react-router
dependency-version: 7.13.2
dependency-type: direct:production
update-type: version-update:semver-patch
dependency-group: production
- dependency-name: turbo
dependency-version: 2.8.21
dependency-type: direct:development
update-type: version-update:semver-patch
dependency-group: production
- dependency-name: typescript-eslint
dependency-version: 8.57.2
dependency-type: direct:development
update-type: version-update:semver-patch
dependency-group: production
- dependency-name: vitest
dependency-version: 4.1.2
dependency-type: direct:development
update-type: version-update:semver-patch
dependency-group: production
- dependency-name: "@sentry/node"
dependency-version: 10.46.0
dependency-type: direct:production
update-type: version-update:semver-minor
dependency-group: production
- dependency-name: "@sentry/react"
dependency-version: 10.46.0
dependency-type: direct:production
update-type: version-update:semver-minor
dependency-group: production
...
Signed-off-by: dependabot[bot] <support@github.com>
2026-03-29 08:26:40 +00:00
Ullrich Schäfer
55afc4cbf3
Fix Dependabot alerts: brace-expansion and path-to-regexp
...
- Override brace-expansion >=4.0.0 <5.0.5 → 5.0.5 (process hang via zero-step sequences)
- Override path-to-regexp <0.1.13 → 0.1.13 (ReDoS via Express transitive dep)
- Dismissed esbuild alert #1 (already on 0.25.12+, alert for <=0.24.2)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 07:49:37 +01:00
Ullrich Schäfer
6b147d04ec
Use pnpm.onlyBuiltDependencies for @sentry/cli and esbuild
...
pnpm approve-builds in Dockerfile ran after install, so the approval
wasn't picked up. Use onlyBuiltDependencies in package.json instead —
this is read during install and allows build scripts to run.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 18:07:25 +01:00
Ullrich Schäfer
b6908fb288
Fix picomatch audit vulnerability and complete security hardening verification
...
Override picomatch to 4.0.4 to resolve high-severity ReDoS (GHSA-c2c7-rcm5-vvqj),
verify all security hardening tasks (gitleaks, pnpm audit, Docker non-root,
Caddy headers, scanner blocking), sync specs, and archive the change.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 00:31:27 +01:00
Ullrich Schäfer
3f7499ff06
Fix i18n: move init to root.tsx and downgrade to stable versions
...
Move initI18n() from entry.client.tsx to root.tsx in both Planner and
Journal so i18n is initialized before any component renders. Downgrade
react-i18next to 16.6.1 and i18next to 25.10.4 to avoid hydration
mismatch issues introduced in newer versions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 23:18:15 +00:00
dependabot[bot]
dfba9b8170
Bump the production group with 8 updates
...
Bumps the production group with 8 updates:
| Package | From | To |
| --- | --- | --- |
| [@react-router/dev](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dev ) | `7.13.1` | `7.13.2` |
| [@react-router/node](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-node ) | `7.13.1` | `7.13.2` |
| [@react-router/serve](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-serve ) | `7.13.1` | `7.13.2` |
| [i18next](https://github.com/i18next/i18next ) | `25.10.4` | `25.10.9` |
| [react-i18next](https://github.com/i18next/react-i18next ) | `16.6.1` | `16.6.6` |
| [react-router](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router ) | `7.13.1` | `7.13.2` |
| [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint ) | `8.57.1` | `8.57.2` |
| [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest ) | `4.1.0` | `4.1.1` |
Updates `@react-router/dev` from 7.13.1 to 7.13.2
- [Release notes](https://github.com/remix-run/react-router/releases )
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-dev/CHANGELOG.md )
- [Commits](https://github.com/remix-run/react-router/commits/@react-router/dev@7.13.2/packages/react-router-dev )
Updates `@react-router/node` from 7.13.1 to 7.13.2
- [Release notes](https://github.com/remix-run/react-router/releases )
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-node/CHANGELOG.md )
- [Commits](https://github.com/remix-run/react-router/commits/@react-router/node@7.13.2/packages/react-router-node )
Updates `@react-router/serve` from 7.13.1 to 7.13.2
- [Release notes](https://github.com/remix-run/react-router/releases )
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-serve/CHANGELOG.md )
- [Commits](https://github.com/remix-run/react-router/commits/@react-router/serve@7.13.2/packages/react-router-serve )
Updates `i18next` from 25.10.4 to 25.10.9
- [Release notes](https://github.com/i18next/i18next/releases )
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md )
- [Commits](https://github.com/i18next/i18next/compare/v25.10.4...v25.10.9 )
Updates `react-i18next` from 16.6.1 to 16.6.6
- [Changelog](https://github.com/i18next/react-i18next/blob/master/CHANGELOG.md )
- [Commits](https://github.com/i18next/react-i18next/compare/v16.6.1...v16.6.6 )
Updates `react-router` from 7.13.1 to 7.13.2
- [Release notes](https://github.com/remix-run/react-router/releases )
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router/CHANGELOG.md )
- [Commits](https://github.com/remix-run/react-router/commits/react-router@7.13.2/packages/react-router )
Updates `typescript-eslint` from 8.57.1 to 8.57.2
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases )
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md )
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.57.2/packages/typescript-eslint )
Updates `vitest` from 4.1.0 to 4.1.1
- [Release notes](https://github.com/vitest-dev/vitest/releases )
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.1/packages/vitest )
---
updated-dependencies:
- dependency-name: "@react-router/dev"
dependency-version: 7.13.2
dependency-type: direct:production
update-type: version-update:semver-patch
dependency-group: production
- dependency-name: "@react-router/node"
dependency-version: 7.13.2
dependency-type: direct:production
update-type: version-update:semver-patch
dependency-group: production
- dependency-name: "@react-router/serve"
dependency-version: 7.13.2
dependency-type: direct:production
update-type: version-update:semver-patch
dependency-group: production
- dependency-name: i18next
dependency-version: 25.10.9
dependency-type: direct:development
update-type: version-update:semver-patch
dependency-group: production
- dependency-name: react-i18next
dependency-version: 16.6.6
dependency-type: direct:development
update-type: version-update:semver-patch
dependency-group: production
- dependency-name: react-router
dependency-version: 7.13.2
dependency-type: direct:production
update-type: version-update:semver-patch
dependency-group: production
- dependency-name: typescript-eslint
dependency-version: 8.57.2
dependency-type: direct:development
update-type: version-update:semver-patch
dependency-group: production
- dependency-name: vitest
dependency-version: 4.1.1
dependency-type: direct:development
update-type: version-update:semver-patch
dependency-group: production
...
Signed-off-by: dependabot[bot] <support@github.com>
2026-03-25 12:32:37 +01:00
Ullrich Schäfer
091fc0a4bd
Add Sentry source maps and release tracking
...
- @sentry/vite-plugin uploads source maps during Docker build
- Release tagged with git SHA (SENTRY_RELEASE) on both client and server
- Environment set to production/development for filtering
- CD passes SENTRY_AUTH_TOKEN + SENTRY_RELEASE as Docker build args
- docker-compose passes SENTRY_RELEASE to runtime containers
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 02:43:28 +01:00
Ullrich Schäfer
14b179bb0c
Fix waypoint loading in Edit in Planner flow
...
Three issues fixed:
1. GPX parser used browser DOMParser which doesn't exist in Node/Vite SSR.
Added async parseGpxAsync() using linkedom for server-side parsing.
2. Server-side session initialization stored waypoints in a Yjs doc
instance separate from the Vite WebSocket plugin's doc store.
Moved waypoint initialization to client-side: API returns parsed
waypoints, client adds them to Yjs after sync.
3. GPX was encoded in URL params causing HTTP 431. Now the Journal
creates a Planner session via API (POST body), and only passes
compact waypoint coordinates in URL params.
Verified: Journal route → Edit in Planner → 4 waypoints loaded,
route computed (79.3km), elevation profile, Save to Journal ready.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 20:22:58 +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
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
9deda5f125
Add Drizzle ORM with shared db package ( #10 )
2026-03-22 22:35:50 +00: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
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
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
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
5b4d072741
Initial monorepo setup with architecture plan
...
- Monorepo structure: apps/ (planner, journal) + packages/ (ui, types, map, gpx, i18n)
- Tooling: pnpm workspaces + Turborepo
- Architecture plan documenting all resolved decisions from design review
- Shared types package with Route, Activity, and Waypoint interfaces
- MIT license
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 11:29:33 +01:00