The context
This notebook collects athletics notes: season plans, sessions, warm-ups, technical drills, physical preparation, nutrition, competitions and injuries. The notes are written in Obsidian, but the notebook needed to read like a site, with search, a table of contents and a printable version.
The site is mainly a way to share sessions and season references with athletes. It turns the notes into a static site at build time, with no server and no database. Once the build finishes, only files remain.
Notes as the source
Content comes from an Astro collection that reads notes outside the repository. A set of Sätteri plugins handles Obsidian syntax: wiki links, transclusions, attachments, callouts, comments, block ids, maths, Mermaid and Excalidraw.
The sidebar follows the order declared in each note's frontmatter. The table of contents is built from headings collected during rendering. A note can keep its original structure while becoming a readable HTML page.
Unlisted notes stay out of the navigation. Wiki links and vault paths resolve to published pages, preferring the file closest to the note that references it.
A note can contain instruction callouts, tables, formulas and diagrams. The render keeps those elements instead of flattening them into text. Unlisted notes remain reachable by direct link, but they do not appear in the navigation. The notebook is a reference during the season and stays readable on a phone at the edge of the track.
Images and PDF
Note images are linked to the project at startup, then Astro generates WebP variants at 480, 960 and 1440 pixels. The PDF keeps the original path so it can embed the full-resolution image.
Every listed note has an HTML page and a PDF generated with takumi-pdf. The PDF follows the note layout with a dedicated print stylesheet. A session can be printed or sent as is.
The PDF is generated from the same HTML the reader sees, so a session does not drift between the web page and the printed version. Images are inlined at full resolution for print, while the web page keeps the smaller WebP variants.
Search lives in a static JSON file loaded on the client. There is no search service to query. The pole vault calculator is an isolated React 19 component. The rest of the site is static HTML.
Offline reading
The service worker caches:
- notes and images;
- fonts and the search index;
MermaidandExcalidrawchunks.
The total is around 21 MB. The notebook stays readable offline after the first visit. Unlisted notes and videos join the cache on demand. An install button appears when the browser offers one.
The cache version is derived from file contents. A new deployment replaces the old cache instead of leaving stale notes behind.
Deployment
Deployment runs through Vercel or through the Docker image with nginx. The build reads the notes locally, and the host only receives the generated files. The vault is never copied into the repository.
For a Docker build, the vault is mounted as a build context. The final container holds only the generated site and the nginx configuration.
The result
The notebook reads offline, a note can be found through search, and a session prints to PDF. The notes stay in Obsidian, with their links, callouts and diagrams.
The notebook does not depend on an online account. It asks for no login, no sync and no external service to display a note. That autonomy matches the intended use: reading a session at the track, where the network is not reliable.
Listed notes get a stable URL that can be bookmarked or shared. The PDF uses the same note name, so the printed version is easy to find next to the page.


