- Journal: Impressum (§5 TMG), Terms of Service, GDPR privacy page
- Registration flow: required ToS checkbox, termsAcceptedAt persisted
- Alpha banner on Journal (always visible); alpha badge on Planner hero
- Footer with legal links + GitHub on both apps
- Reduce PII: sendDefaultPii=false, Sentry init only after login (Journal)
- Drop Sentry from Planner (no login, no consent possible)
- Drop localStorage caching from i18n client detection
- Sync SSR i18n resources each request so locale edits HMR without restart
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- RouteMap.tsx referenced undefined MapLibreRN namespace, causing
typecheck to fail on main and in every downstream PR
- metro.config.js is CommonJS, exclude from ESLint flat config
Changes that were pushed directly to main earlier bypassed CI and
broke both typecheck and lint.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Proposal, design, specs, and tasks for German legal compliance (Impressum,
Datenschutzerklärung, ToS) and alpha-stage disclaimers at signup.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Magic links open in the device browser, not the OAuth in-app browser,
so the session doesn't carry over. A login code lets mobile users
type a 6-digit code from their email into the login page instead.
- Generate 6-digit numeric code alongside magic link token
- Store code in magic_tokens table
- Add verify-code step to login API endpoint
- Show code input UI after magic link is sent
- Include code in email template
- i18n keys for code UI (en + de)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Metro couldn't resolve hoisted packages (@maplibre, @gorhom, etc.)
because it only looked in apps/mobile/node_modules. Configure
watchFolders and nodeModulesPaths to include the monorepo root.
Also revert MapLibre fallback — direct import is correct, the issue
was Metro resolution, not a missing native module.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use try/catch require() for MapLibre so the app works without it
(shows fallback UI). Needed when running on builds that don't include
MapLibre native module (old EAS builds, Expo Go).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The route editor called fetch() directly for /api/v1/routes/compute
without the bearer token. Now uses the API client which injects auth
headers and handles 401 auto-refresh.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The "Waypoints (3)" assertion timed out at 5s in CI. The waypoints
load from URL params but the sidebar needs BRouter mock response +
Yjs sync before updating. Increase to 15s to match other assertions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Android 9+ blocks cleartext HTTP by default. Enable usesCleartextTraffic
so the emulator can reach the Journal dev server at http://10.0.2.2:3000.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Android emulator has its own network stack — localhost refers to the
emulator, not the host. Use 10.0.2.2 (host loopback alias) on Android.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- prebuild: generate native ios/ and android/ projects
- prebuild:clean: regenerate from scratch
- run:ios / run:android: build and run locally with Xcode/Gradle
- Add ios/ and android/ to .gitignore (CNG-generated)
Allows building locally without EAS credits:
pnpm --filter @trails-cool/mobile prebuild
pnpm --filter @trails-cool/mobile run:ios
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace custom View-based bottom sheet with @gorhom/bottom-sheet:
- Native gesture-driven drag, snap points, pan-down-to-close
- Proper safe area handling built in
- Wrap app with GestureHandlerRootView
- Add react-native-reanimated plugin to Expo config
Adds react-native-reanimated and react-native-gesture-handler as
native dependencies (requires new EAS build).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Close button was overlapping the home indicator. Now uses
useSafeAreaInsets() for dynamic bottom padding.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The route polyline wasn't visible because segments were initialized
empty. Now extractSegmentsFromGpx() parses trkpt coordinates from
the GPX string via regex on init, so the route shows immediately
in both view and edit modes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The check now also verifies that source paths referenced by
COPY --from=build lines actually exist in the repo. This would have
caught the premature app/jobs COPY that broke the journal build.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The journal doesn't have an app/jobs directory yet — that will arrive
with the Komoot import PR. The COPY line was added prematurely and
breaks the Docker build.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a script that verifies every packages/*/package.json is listed in
all app Dockerfiles. Catches the recurring issue where adding a new
workspace package breaks production because the Dockerfile deps stage
doesn't know about it.
Also fixes two pre-existing missing packages in the planner Dockerfile
(api, map-core) caught by the new check.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Both Dockerfiles were missing packages/jobs/package.json in the deps stage,
causing pnpm install to skip pg-boss. Also copy app/jobs directories into
the runtime stage so job handlers are available at runtime.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
pg-boss v10 requires explicit queue creation via `createQueue()` before
`schedule()` or `work()` can reference a queue. Without this, the planner
crashes on startup in fresh databases (like CI) with "Queue not found".
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Proposal, design, specs, and tasks for persistent staging instance and
ephemeral PR preview environments on the existing Hetzner server.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add @trails-cool/jobs package wrapping pg-boss for durable background job
execution using the existing PostgreSQL database. Wire up planner session
expiry as the first scheduled job (hourly, 7-day TTL) — this was previously
dead code that never ran. Add placeholder worker to journal for future
Komoot import and federation jobs.
Infrastructure: grant grafana_reader access to pgboss schema, add job queue
health panels to Service Health dashboard, add failed job alert.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The smoke test failed in CI with version mismatch between react
(19.2.5 from catalog) and react-test-renderer (19.2.0 transitive).
Adding it explicitly ensures they stay in sync.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The journal now depends on @trails-cool/api which depends on zod.
The Dockerfile was missing these package.json files, causing pnpm
install to skip them and the build to fail.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The journal now depends on @trails-cool/api (added in PR #217) which
depends on zod. The Dockerfile was missing the package.json for api
and map-core, causing pnpm install to skip them and the build to fail
with "Failed to resolve import zod".
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove SENTRY_DISABLE_AUTO_UPLOAD from all build profiles
- Add @sentry/cli as explicit dependency to fix pnpm module
resolution in EAS cloud builds
- SENTRY_AUTH_TOKEN configured as EAS environment secret
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Initialize @sentry/react-native with dedicated mobile project DSN
- Wrap root layout with Sentry.wrap() for unhandled error capture
- Configure Sentry plugin with org (trails-qq) and project (mobile)
for source map uploads during EAS builds
- Disabled in dev, full tracing in production
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add eas.json with development, preview, and production profiles
- Link project to EAS (projectId: 93c75cae-fecf-4ce5-8cd8-c823760b12e2)
- Add expo-dev-client, expo-constants, expo-linking dependencies
- Remove eas-cli from project deps (use globally)
- Add ITSAppUsesNonExemptEncryption to iOS infoPlist
- Use catalog react with expo.install.exclude to skip version check
- Fix slug to match EAS project registration
- Run pnpm dedupe to resolve duplicate react across workspaces
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Route detail at /routes/:id shows:
- Header with back navigation and route name
- Map placeholder (MapLibre requires EAS dev build)
- Stats row: distance, elevation gain/loss, day count
- Description text
- Version count
- "Edit in Planner" opens Journal web UI
- "Download Offline" button (handler pending Phase 5)
Safe area insets applied to header and scroll content.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>