* chore: fix monorepo build pipeline and migrate shared to built package
- Root package.json: add workspace scripts (dev, build, test, test:cov, test:e2e)
that delegate to actual scripts in shared/server/client workspaces
- shared: add tsup build step (CJS + ESM dual output, .d.ts); consumers now import
from the built dist instead of raw TS source via path aliases
- server: replace tsc-alias with tsconfig-paths (tsc-alias mangled node_modules
paths); fix MCP SDK path aliases to point to root node_modules (../node_modules)
- server/scripts/dev.mjs: delay node --watch until tsc -w signals first-pass done,
eliminating the spurious restart on every dev startup
- client/vite.config.js + vitest.config.ts: remove @trek/shared path alias (no longer
needed now that shared is a proper package)
- Consolidate package-lock.json at the workspace root; drop per-workspace lock files
* chore: fix test script to reflect root package.json
* chore: add missing lint and prettier script in root package.json
* fix(ci): build shared before tests; fix vitest MCP SDK alias paths
vitest.config.ts aliases pointed at ./node_modules/ (server-local) but
packages are hoisted to the root node_modules/ in the npm workspace —
changed to ../node_modules/.
CI jobs now install and build shared before running server/client tests
so that @trek/shared's dist/ exists when vitest resolves the package.
* fix(docker): update Dockerfile and CI for monorepo workspace structure
Dockerfile:
- Add shared-builder stage that produces @trek/shared dist before
client and server stages need it
- Each build stage carries root package.json + package-lock.json so npm
can resolve @trek/shared as a workspace dependency
- Production stage installs via workspace context (npm ci --workspace=server
--omit=dev) so node_modules/@trek/shared symlinks to shared/dist correctly
- Copy server/tsconfig.json into the image so tsconfig-paths/register can
find the MCP SDK path aliases at runtime
- CMD cds into /app/server before starting node so tsconfig-paths baseUrl
resolves and ../node_modules points to /app/node_modules
- Remove mkdir for /app/server (now a real dir); keep symlinks for uploads/data
docker.yml version-bump:
- Replace manual per-workspace cd+npm-version calls with single:
npm version --workspaces --include-workspace-root --no-git-tag-version
(mirrors the version:* scripts in root package.json)
- git add now references root package-lock.json; adds shared/package.json
.dockerignore: add shared/dist
package.json: fix version:prerelease preid (alpha → pre)
* fix(tests): use in-memory SQLite per worker in test mode
vitest pool:forks spawns parallel worker processes that all called
initDb() on the same data/travel.db, causing SQLite "database is locked"
and "duplicate column name" races.
When NODE_ENV=test each fork now gets an isolated :memory: DB so migrations
run independently with no file contention.
* chore(ci): add ACT guards to skip DockerHub steps in local act runs
act sets ACT=true automatically. Guards added:
- docker login: if: ${{ !env.ACT }}
- build outputs: type=docker (local load) when ACT, push-by-digest when CI
- digest export/upload: if: ${{ !env.ACT }}
- merge job: if: ${{ !env.ACT }}
- release-helm job (docker.yml): if: ${{ !env.ACT }}
- version-bump git push (docker.yml): wrapped in [ -z "$ACT" ] shell guard
Run locally with:
./bin/act -j build -W .github/workflows/docker.yml \
-P ubuntu-latest=catthehacker/ubuntu:act-latest
* fix(ci): move ACT guards to step level; add guards to security.yml
env context is invalid in job-level if conditions — moved all ACT
guards down to individual steps. Also guards docker login + scout
in security.yml so act can run the build-only part of that workflow.
* fix(ci): skip git fetch and tag logic in act (no remote access in local containers)
* Revert "fix(ci): skip git fetch and tag logic in act (no remote access in local containers)"
This reverts commit 67cf290cda.
* Revert "fix(ci): move ACT guards to step level; add guards to security.yml"
This reverts commit f92b95e054.
* Revert "chore(ci): add ACT guards to skip DockerHub steps in local act runs"
This reverts commit 797183de08.
* fix(docker): add musl optional deps so alpine builds find native rollup/sharp binaries
npm prunes libc-constrained optional deps to the host libc (glibc) when
generating the lockfile, leaving no musl entry for Alpine containers.
Declaring the x64/arm64 musl variants as explicit root optionalDependencies
forces them into the lockfile so npm ci on Alpine can install them.
Covers shared-builder (tsup/rollup) and client-builder (vite/rollup + sharp
icon generation) for both linux/amd64 and linux/arm64 CI targets.
* fix(docker): copy client dist into server/public so the server resolves static files correctly
The server runs from /app/server and serves static files relative to that
directory, so the client build output must land at /app/server/public, not /app/public.
* fix(mcp): replace relative oauth constent redirect by absolute redirect derived from APP_URL (#987)
* feat(journey): convert HEIC/HEIF uploads to JPEG for cross-platform compatibility
HEIC is an Apple-only format not recognised as an image by many browsers
and platforms. heic-to (lazy-loaded) now converts HEIC/HEIF files to JPEG
before upload in both the gallery and entry editor photo pickers.
Embedded metadata (EXIF, GPS) may be lost during conversion — documented
in the Journey Journal wiki page.
* fix(journey): skip heic-to import for non-HEIC files to avoid test env failures
* fix(notifications): prevent double-escaping HTML in password reset emails
buildPasswordResetHtml passed a pre-built HTML block to buildEmailHtml,
which then escaped it again — rendering raw tags as plain text in the email.
- Mapbox GL provider alongside Leaflet for trip and journey maps (opt-in in
settings with token, style presets incl. 3D on satellite, quality mode,
experimental badge).
- GPS "blue dot" with heading cone on mobile; three-state FAB (off / show /
follow), geodesic accuracy circle, desktop-hidden since browser IP geo is
too coarse for navigation.
- Marker drift fix: outer wrap no longer carries inline position/transform,
so mapbox's translate keeps the pin pinned at every zoom and pitch.
- Journey map popup (mapbox-gl): Apple-Maps-style tooltip on marker
highlight/click showing entry title + location / date subline.
- Journey feed reorder: up/down controls to the left of each entry reorder
sort_order within a day. Server endpoint, optimistic store update, rollback
on failure.
- Journey entry editor: desktop modal now centers over the feed column only,
backdrop still blurs the whole page (map included).
- Scroll-sync guard on journey: marker click locks the sync so smooth-scroll
can't steer the highlight to a neighbouring entry mid-animation.
- Misc: map top-padding aligned with hero, live/synced badges replaced by a
compact back-button in the hero, skeleton entries no longer pollute the
journey map, journey detail no longer shows map on mobile path when
combined view is active.
Server-side notice registry with per-user condition evaluation (firstLogin,
existingUserBeforeVersion, addonEnabled, dateWindow, role, custom).
Notices are sorted by priority then severity, filtered against dismissals
stored in a new user_notice_dismissals table, and served via
GET /api/system-notices/active + POST /api/system-notices/:id/dismiss.
Client renders notices through a host component that partitions by
display type (modal / banner / toast). The modal renderer supports
multi-page pagination with directional slide transitions, keyboard
navigation, and correct dismiss-all semantics on CTA / X / ESC.
Dismissals are optimistic with a single background retry.
Includes 3.0.0 upgrade notices (v3-photos, v3-journey, v3-features),
onboarding welcome modal, and full i18n coverage across 15 languages.
The /journey route is addon-gated on both client and server.
Also includes: unit + integration test suites, registry integrity test
that validates action CTA IDs against client source, and technical
documentation in docs/system-notices.md.
Add remark-breaks plugin so single newlines in note content render
as <br> instead of being collapsed by Markdown. Applies to both
the card preview and the expanded view.
- 5-table schema (journeys, entries, photos, trips, contributors) with migrations 87-91
- Trip-to-Journey sync engine with skeleton entries and photo sync
- Full CRUD API for journeys, entries, photos with Immich/Synology integration
- Timeline, Gallery and Map views with entry editor (markdown, mood, weather, pros/cons)
- Journey frontpage with hero card, stats and trip suggestions
- Public share links with token-based access and photo proxy
- PDF photo book export (Polarsteps-inspired)
- Dashboard redesign: mobile greeting, live trip hero, quick actions, unified card design
- BottomNav profile sheet with settings/admin/logout
- DayPlan mobile inline place picker
- TripFormModal members management
- Vacay calendar trip date indicator dots
- Fix contributor photo access (403) for journey Immich/Synology photos
- Trip deletion cleanup for journey skeleton entries
- i18n: 231 new keys across all 14 languages (native translations, no fallbacks)
vitest@4 requires vite@^6, causing two conflicting esbuild versions in
the lockfile and EBADPLATFORM errors during Docker npm ci. Pin to vitest
3.x which supports vite@5 and resolves a single esbuild@0.21.5.
Add npm overrides to force esbuild@^0.28.0, resolving the conflict
between vite@5.x (which installs 0.21.5) and vitest@4.x's internal
vite@8.x (which requires ^0.27.0 || ^0.28.0). Without this,
npm ci fails on a clean install.