sin558 downloadsPlan and record trips as structured data with map views, days grouping, and routes.
English | 简体中文
Life as Code - Roadmap is a travel planning and journaling plugin for Obsidian. Trips are stored as TOML inside Markdown — no database, no proprietary format, fully readable and editable on their own. Render them as a journal-style timeline with maps, day grouping, route segments, and a heatmap.
DAY n / 11·01 / count tab strip; multi-select tabs filter the timeline+ transit chip between places opens an editor for travel mode (walk / bicycle / motorcycle / drive / transit), distance, duration, and tolls — with an "auto-calculate" button that calls Google Directions or AMap routingtype = "root", renders = ["roadmap"]), so a trip can contain nested tripsmap_provider overrides the global default — same vault can mix both seamlesslyAll data is TOML at the top of regular Markdown files, with [[Wikilink]] references for relationships. The plugin only rewrites the keys it owns and preserves leading comments.
Roadmap collection root (roadmap.md):
type = "root"
renders = ["roadmapset"]
[[Tokyo Trip]]
[[Kyoto Adventure]]
Roadmap file (Tokyo Trip.md):
name = "Tokyo Trip"
[detail]
description = "Akihabara + Asakusa"
start_time = "2025-11-01"
end_time = "2025-11-02"
map_provider = "google"
[[Akihabara]]
travelMode = "transit"
distance = 4800
duration = 1080
tolls = 240
[[Senso-ji Temple]]
The lines between two [[wikilink]] rows describe a route segment between those two places. The travelMode decides the polyline style (walk / bicycle render dashed; the rest solid) and colour.
Place file (Akihabara.md):
name = "Akihabara"
[detail]
start_time = "2025-11-01 10:00"
end_time = "2025-11-01 12:30"
description = "Electronics, anime, retro games"
[detail.address]
name = "Akihabara Station"
address = "1 Chome Sotokanda, Chiyoda City, Tokyo"
longitude = 139.7741
latitude = 35.6985
coordinate_system = "WGS84"
When a place is referenced by multiple trips, its own start_time / end_time are dropped and per-trip times live as override lines next to the wikilink in the roadmap file:
[[Akihabara]]
start_time = "2025-11-01 10:00"
end_time = "2025-11-01 12:30"
Sub-roadmap as a place (Day 2 in Kyoto.md):
type = "root"
renders = ["roadmap"]
name = "Day 2 in Kyoto"
[detail]
description = "Fushimi Inari + Gion"
[[Fushimi Inari Shrine]]
[[Gion District]]
The parent trip references this file as a regular [[Day 2 in Kyoto]] place; clicking the card navigates into it as a nested timeline.
LaC/Roadmap/
├── roadmap.md # collection root: lists every trip
├── Tokyo Trip.md # trip 1
├── Akihabara.md # place referenced by Tokyo Trip
├── Senso-ji Temple.md
├── Kyoto Adventure.md # trip 2
├── Day 2 in Kyoto.md # sub-roadmap, also referenced as a place
├── Fushimi Inari Shrine.md
└── ...
LaC/Roadmap/roadmap.md).start_time / end_time as override lines on the roadmap file instead of into the place file. Default true — keeps place files reusable across trips.None / Google Maps / AMap (高德). None disables map widgets and falls back to plain text address fields.This plugin does not go through the Obsidian Community Plugin review.
alvinfunborn/lac-roadmap.main.js, manifest.json, and styles.css into <vault>/.obsidian/plugins/lac-roadmap/ (create the folder if missing).Run "Open LaC.Roadmap" from the command palette. If the configured entry file is missing, the plugin scaffolds LaC/Roadmap/roadmap.md plus sample places so you can see the UI immediately.
On the trip list page:
+ NEW TRIP button. A modal asks for name / description / dates / map provider.← to return).On a trip detail page:
+ ADD PLACE. Pick name, time range, address. Address picker uses your configured map provider.+ ADD TRIP creates a sub-roadmap that the parent references as a place.walk · 4.8 km · 18 min) to edit travel mode / distance / duration / tolls. The auto-calculate button uses your map provider's routing API.+ transit between two consecutive places have no segment yet — click to create one.DAY 1 / 11·01 / 3 — DAY ordinal, calendar date, place count.+ DAY adds a session-only placeholder day (not persisted; for previewing how a future day's places would group).wishlist collects places without a date.The map at the top of trip / trip-list pages is a preview. Click it to open a full read-only map viewer where you can pan / zoom / inspect markers. The hero is intentionally a preview because the warm-ink visual treatment doesn't pass through pointer events under Chromium — see docs/PROGRESS.md for the trade-off.
[[wikilinks]] inside the body.IMapProvider + GoogleMapProvider / AmapProvider) so all map widgets work identically against either provider.styles/_variables.scss; falls back to system serif / sans / mono fonts so no font assets are bundled and no network requests are made.Main components:
RoadmapPlugin — plugin entry, view registration, settings tab.RoadmapView — Obsidian ItemView host; dispatches to RoadmapSetPage (collection root) or RoadmapPage (single trip) based on the file's renders field.RoadmapSetPage — trip list with hero aggregate map, status counts, drag-reorder for wishlist trips.RoadmapPage — trip detail with header / day tabs / timeline / actions.RoadmapHeader — back button + serif title + stats + hero map.DayTabsStrip — three-tier mono day tabs with long-press reorder.Timeline — spine + numbered bullets + place cards + route chips.RoadmapActions — + add place / + add trip row.RoadmapRepository — TOML parsing, place CRUD, sub-roadmap detection, route segment writes.RouteCalculationService — Google Directions / AMap routing wrapper.MapSelector — full-screen map modal (interactive picker + read-only viewer).AggregatedMap — hero map widget with warm-ink filter and overlay chrome.MIT License
Maps are optional. With provider None, no map service is requested. Enabling Google Maps or AMap loads that provider's remote JavaScript SDK and map tiles, and sends place search queries and coordinates to the selected provider for search, geocoding and route calculation. These features require your own provider account and API key and may incur provider charges. Notes stay in your vault; map queries are processed by the provider. API keys are saved in local plugin settings (data.json); do not commit or share that file. The plugin does not collect analytics.