Skip to content

Latest commit

 

History

299 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🌼 felicia

フェリシア — 琉璃雏菊(蓝费莉菊)

A map-based travel journal. The map is the index; the mementos are the stories.

Each journey is drawn on a world map as an orange route line. Along it sit mementos — the little things that anchor a memory (a train ticket, a temple stamp, a plush, a receipt) — each a collectible stub that animates open into an essay and a photo gallery.

Modeled on liuaaron.com · "Aaron's Waypoints."


status web backend i18n license


✨ The idea

  • 🗺️ The map is the index. One glance says everywhere I've been and which trip to revisit. You navigate spatially, not through a feed.
  • 🎫 Mementos, not tickets. Physical stubs are dying, so a memento is kind-tagged (goods · live · transit · stamp · receipt · souvenir) and rendered from data, template-first — not scanned.
  • 📍 A place is a visit. Following how Dawarich and Google Timeline model location (points → tracks → visits @ places → trips), a place is a dwell-time visit derived from your track. Several memories can stack at one place.
  • ✍️ Auto-ingest, then author. A pipeline seeds ingested fields (track, photos, stubs); you author the essay, curation, and animation. Re-import is field-scoped and never clobbers what you wrote.
  • 🌏 Japanese-first, with English and Chinese alongside.

🚪 Four front doors, one contract

The public reader renders the same { journey, visit, memento } contract four ways. The production catalog under publication/journeys/ is the publication source, and the on-screen switcher is deep-linkable.

Front door Route What it is
🗺️ Atlas / map-and-story reader: journey rail → route map → memento detail. The default.
🗄️ Cabinet #cabinet Memento-first shelf; a "greatest-hits" browse across every trip.
📓 Techo (手帳) #techo Warm paper notebook: a journal-index spread, then the trip on a real map with mementos clustered by place/visit — open a place to read its memories.
🌐 Cartography (世界地図) #cartography Full-map atlas index across every journey; mementos render as kind-designed collectible stubs (one stub design per registry kind).

The production catalog contains sanitized, published journey inputs; the same shape is served by the working backend.

🏗️ Architecture

flowchart LR
  subgraph S["Sources (self-hosted)"]
    daw["Dawarich\ntrack + visits"]
    imm["Immich\nphotos"]
  end
  daw & imm --> imp["waypoints importer\n(Go)"]
  imp --> db[("SQLite local / Postgres\njourneys · mementos")]
  imp --> r2[["R2 / S3\nEXIF-stripped photos"]]
  db --> api["HTTP API (Go, chi)\n/api/v1 · GeoJSON"]
  r2 --> api
  api --> web["Reader hosts\nCartography · Cabinet · Techo · Atlas (MapLibre)"]
Loading
  • Ingestwaypoints pulls the track + visits from Dawarich and photos from Immich, joins on timestamp, EXIF-strips + resizes to R2, and seeds stub mementos. Raw GPS never lands in a public file.
  • Serve — the API layer depends on runtime ports; SQLite is the default local provider and PostgreSQL remains available for deployments that need it.
  • Read — any number of frontends project the same contract. Adding a design is one registry entry, not a schema change.

🧱 Built with

Standing on a lot of excellent open source. 🙏

🖥️ Web Svelte 5 · TypeScript · Vite · MapLibre GL JS · Tailwind CSS · Bun · basemaps by CARTO + OpenStreetMap

⚙️ Backend Go · chi · pgx · sqlc · orb · goose · minio-go · imaging · gpxgo · tzf · koanf · go-toml · anthropic-sdk-go

🗃️ Data & storage PostgreSQL · PostGIS · Cloudflare R2 (S3-compatible; MinIO/B2 swappable)

📥 Ingestion sources (self-hosted) Dawarich (GPS track + visits) · Immich (photos)

🧰 Tooling mise · golangci-lint · Docker Compose · Cloudflare Tunnel · MkDocs Material · uv

🚀 Quick start

The public reader runs on the production catalog — no database or keys are needed for a local reader preview.

make web-dev          # Vite dev server → http://localhost:5173

Then use the switcher at the bottom (地図 / コレクション / 手帳 / 世界地図), or jump straight in: / (Atlas) · #cabinet · #techo · #cartography. Toggle language (日本語 / EN / 中文) and light/dark in each design's header.

make web-check        # svelte-check + eslint
make check            # Go workspace checks + uv feature-contract tests

The complete toolchain comes from mise (mise install). Everything routes through make <target>.

🌍 Publish your own site

Your journal is authored locally and only the compiled site is published — there is no hosted admin, and drafts, originals, and the SQLite journal never leave your machine.

make admin                              # authoring GUI on 127.0.0.1 — import, curate, write, publish
BASE_PATH=/my-travels/ make site-build  # deployable site → apps/felicia-public-site/dist

Then push that directory to the repository serving your GitHub Pages site. Full walkthrough — both the local-authoring route and the CI route, base-path table, and troubleshooting: docs/publish.md.

🧭 Data model in one breath

journal → journeys → mementos, with a derived visit/place layer and canonical media:

  • memento — one uniform table, kind-tagged, kind-specifics in a kind_data jsonb. New kinds = a new enum value, not a new table.
  • place = visit — a derived dwell-time cluster (consumed from Dawarich, or clustered from a GPX fallback); mementos anchor to the nearest visit.
  • Provenance is load-bearing — every field is INGESTED / OVERRIDABLE / AUTHORED; the importer is field-scoped and re-import is always safe.
  • Media — images, videos, audio, documents, links, and provider-approved embeds are canonical asset kinds attached to memories.
  • Locales — system-owned UI labels use static ja/en/zh catalogs; user content is rendered exactly as authored.

Full detail: docs/research/data-model.md · docs/research/backend-stack.md.

🛣️ Status & roadmap

Implementation stage (research trail continues). The backend pipeline, live API, CLI, and static compiler are built and tested; GitHub Pages publication runs the real SQLite pipeline end to end (PR #55); the admin authoring GUI MVP is complete (epic FELICIA-ADMIN-01). Auditing that flow against a real trip found four P0 data-integrity defects — a second trip overwrote the first, re-import destroyed authored fields, the artifact shipped an unrounded GPS trace, and media keys collided on basename — all now fixed and covered by provider-parity tests. Remaining gaps: deferred AI enrichment/object storage seams and the dynamic form engine.

Single source of truth for delivery status: docs/roadmap.md; target end-to-end journey: docs/roadmap/user-journey.md.

📚 Docs

Preview locally: make docs (uv-backed MkDocs Material).

🙏 Acknowledgements

📄 License

GNU AGPL-3.0 — network copyleft, matching the self-hosted sources felicia builds on (Dawarich and Immich are both AGPL-3.0). If you run a modified felicia as a network service, you must offer your users its source.

About

A map-based travel journal. The map is the index; the mementos are the stories.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages