Marketing site for Milo — an open source business operating system for product-led B2B companies, built by Datum.
Live site: https://www.milo-os.com
This repository contains the public marketing website for Milo. It is built as a static-first Astro site with MDX content, reusable UI components, and a lightweight server layer for runtime features such as health checks and dynamic data endpoints.
- Astro 6 with MDX content
- Tailwind CSS 4
- Alpine.js for client-side interactivity
- Bun for development and production runtime
The site is pre-rendered to static HTML and served by a custom Bun server in server.mjs, which handles static assets, compressed responses, and middleware for dynamic routes.
- Bun 1.3+
- A local environment file copied from .env.example
bun install
cp .env.example .env
bun run devThe development server will be available at http://localhost:4321.
# Development environment with hot reload
docker compose up dev
# Production build
docker compose up prod| Command | Purpose |
|---|---|
bun run dev |
Start the Astro dev server with type checking |
bun run build |
Type-check and build the site to ./dist/ |
bun run start |
Start the production server from server.mjs |
bun run preview |
Preview the built site locally |
bun run typecheck |
Run Astro type checks |
bun run lint |
Lint JavaScript, TypeScript, Astro, and MD/MDX files |
bun run lint:md |
Lint MDX content |
bun run format |
Format supported source files |
The app reads configuration from .env.example. The most important values are:
| Variable | Required | Description |
|---|---|---|
SITE_URL |
No | Public site URL (default: http://www.milo-os.com) |
PORT |
No | Server port (default: 4321) |
APP_ID |
Yes* | GitHub App ID for roadmap and changelog data |
APP_INSTALLATION_ID |
Yes* | GitHub App installation ID |
APP_PRIVATE_KEY |
Yes* | GitHub App private key (PEM) |
CACHE_CLEAR_SECRET |
Yes* | Secret for authenticating the cache-clear endpoint |
- Required for full functionality. The site can still render without these values, but dynamic features such as roadmap data and changelog data will not work.
/
├── config/ # Kubernetes and Gateway API deployment manifests
├── docs/ # Internal documentation, including release notes
├── public/ # Static assets such as fonts and images
├── src/
│ ├── components/ # Astro components
│ ├── content/ # MDX pages and legal content
│ ├── data/ # Shared site config and navigation data
│ ├── layouts/ # Shared page layouts
│ ├── libs/ # GitHub, cache, and utility modules
│ ├── pages/ # Routes for the site
│ ├── types/ # TypeScript types
│ ├── utils/ # Shared helpers
│ └── v1/ # Legacy styles, scripts, and assets
├── astro.config.mjs
├── docker-compose.yml
├── Dockerfile
└── server.mjs # Production HTTP server
Before opening a pull request, run the relevant checks locally:
bun run typecheck
bun run lint
bun run formatThe site runs on Kubernetes behind the Gateway API, with Datum Cloud edge proxying public traffic. See docs/release.md for deployment details.
# Deploy to cluster
kubectl apply -k config/base
# Update Datum Cloud gateway config
kubectl apply -k config/gateway --kubeconfig datumcfg -n milo-os-comHealth check endpoints are available at /healthz, /livez, and /readyz.