Part of the Runlog project — see the project home for the overview.
Repo: runlog-org/runlog-website — public, MIT
Stack: Astro (hybrid output) + Tailwind v4 — SSG today, ready for SSR routes (account, API key management) without a refactor
Deploy target: edge runtime (static assets + Worker entrypoint) serving runlog.org and runlog.org/register
About this project: Runlog is a hobby side project by Volker Otto — not a commercial product today. A paid model is not ruled out for a later stage. See About this project for the canonical framing.
Marketing and registration surface for Runlog. Extracted into its own public repo at first release because the static site has a different deploy path (edge runtime, static assets) and release cadence than the MCP server — a CSS tweak to the landing page should never require a server deploy, and vice versa.
src/
├── content.config.ts # Astro Content Collection schema (blog)
├── content/blog/*.md # blog posts (Markdown w/ raw HTML)
├── layouts/Base.astro # shared <head>, JSON-LD, nav, footer slot
├── components/Nav.astro # primary nav + register CTA
├── components/Footer.astro # footer with build-time copyright year
├── lib/schema.ts # JSON-LD building blocks (Org, WebSite, Breadcrumb, …)
├── styles/global.css # Tailwind v4 + theme tokens + component classes
└── pages/ # file-routed pages — see Astro docs for [slug] dynamics
public/
├── assets/{fonts,img,js}/ # served as-is (fonts, vendor logos, badges, register-app.js, stats.js)
├── _headers # Cloudflare Pages security headers (CSP, HSTS, …)
├── _redirects # Cloudflare Pages 301s (/register → /register/)
├── stats.json # daily snapshot powering /stats/ + homepage callout
└── .well-known/security.txt
npm install
npm run dev # Astro dev server, ~localhost:4321
npm run build # produces dist/ (static HTML + dist/_worker.js for Cloudflare)
npm run preview # local preview of the built workerThe build target is the Cloudflare Workers adapter (hybrid mode): static pages prerender to dist/<route>/index.html, server-rendered routes (none today, but the account section will live here) compile into dist/_worker.js/. wrangler.jsonc points at dist/.
Local dev against the staging API:
/register/and/register/verifyboth loadpublic/assets/js/register-app.js, which reads the API base fromdata-api-baseon the host element.- For local API testing, edit
data-api-base="http://localhost:8000"(port allowed byregister-app.js's allowlist) on<form id="register-form">insrc/pages/register/index.astroand on the wrapper div insrc/pages/register/verify.astro.
Drop a Markdown file into src/content/blog/<slug>.md:
---
title: "Post title"
description: "One-line description for OG + meta + listing summary."
pubDate: 2026-05-10
readTime: "~6 min read"
---
<section aria-labelledby="hero-title" class="prose">
<h1 id="hero-title">Post title</h1>
<p class="meta"><time datetime="2026-05-10">2026-05-10</time> · ~6 min read</p>
<p class="lede">Lede paragraph.</p>
<p>Body…</p>
</section>
<section aria-labelledby="next-title" class="prose">
<h2 id="next-title">Next section</h2>
…
</section>The blog index (/blog/) and the /blog/<slug>/ pages pick up the new post automatically. Markdown bodies can use the design-system component classes (.prose, .callout, .pull, .drench, .compare, .verdict) — they're defined in src/styles/global.css.
runlog-org/runlog(private) —POST /registerandGET /register/verifyendpoints at runtime (no build-time dep)
MIT — see LICENSE.