A small, content-driven public website that communicates what Datum is in a format equally legible to AI agents and humans. See agents-datum.md for the full project brief.
- React Router v7 (SSR)
- Hono via
react-router-hono-server(Node runtime) - Node runtime + npm
- Vite
- Tailwind CSS v4
@datum-cloud/datum-ui— Datum's design system (built on shadcn/ui + Radix)- TypeScript strict
Light + dark via the user's OS prefers-color-scheme. Default is light; dark only activates when the OS explicitly prefers dark. No toggle UI in v1.
Implemented via @datum-cloud/datum-ui's ThemeProvider in system mode (attribute="class", defaultTheme="system", enableSystem). An inline <ThemeScript /> in <head> resolves the theme before hydration so there's no flash of incorrect theme. See §5.6 of the brief, app/root.tsx, and app/styles/globals.css.
- Node
26.12.1(see.tool-versions)
npm install
cp .env.example .envnpm run dev
# http://localhost:3000To verify theme switching: open the page, then change your OS appearance (macOS: System Settings → Appearance → Dark). The page should flip colors live with no reload.
npm run build
npm run startnpm run lint
npm run typecheck
npm run format:check # check only (CI)
npm run format # auto-fixThe GitHub Actions pipeline (.github/workflows/ci.yml) runs on every PR and push to main:
- Install —
npm ci(cached bypackage-lock.jsonhash) - Lint & Format —
npm run lint && npm run format:check(parallel with Typecheck) - Type Check —
npm run typecheck(parallel with Lint) - Build —
npm run build(only after Lint + Typecheck both pass) - Skill Index —
npm run skills:check: every URL in the skill index returns 200 and matches its digest - Status Gate — final aggregated pass/fail
public/.well-known/agent-skills/index.json is generated from the Datum Claude Code plugin marketplace. Don't edit it by hand. Each URL is pinned to a commit, so it keeps working when a skill moves.
npm run skills:generate # rewrite the index from the marketplace
npm run skills:drift # fail if the index is behind the marketplaceThe Skill Index workflow runs the drift check every week. When it fails, run npm run skills:generate and open a PR. Set GITHUB_TOKEN to raise the GitHub API rate limit.
The Kubernetes publish jobs moved out of ci.yml into a manual-only workflow (publish-kubernetes.yml). Releases go through release-please: merging its release PR tags the version and deploys the container image to Datum Compute (general-purpose runtime). See docs/datum-compute.md.
Build and run the production image locally (simplest):
docker compose up --build
# http://localhost:3000Or build and run directly:
docker build -t agents-datum-net:local .
docker run --rm -p 3000:3000 agents-datum-net:localTo tag a specific version (e.g. for CI):
docker build --build-arg VERSION=$(git rev-parse --short HEAD) -t agents-datum-net:local .The image uses Node on Alpine, runs as a non-root datum user (UID 1001), and includes a HEALTHCHECK against GET /. Dev dependencies are pruned during the build stage so the final image contains only production deps.
app/
├── root.tsx HTML shell + ThemeProvider + global meta
├── routes/
│ └── _index.tsx Homepage placeholder
├── lib/ env, utils (cn re-exported from datum-ui)
└── styles/globals.css Tailwind v4 + datum-ui tokens
Hono server: virtual default from `react-router-hono-server`. Materialize
with `npx react-router-hono-server reveal file` when custom routes
(`/llms.txt`, `/manifest.json`, etc.) are needed in Phase 4.