The ESRA website — esra.bot.
Built in the open, like everything else here. If you want to change what the site says, you almost certainly want BLOGGING.md or CONTRIBUTING.md rather than this file.
A statically generated Astro site. Every page is prerendered to HTML at build time and served from a CDN — there is no server rendering, no database, and no client-side data fetching.
External data (repository statistics, video listings) is fetched during the build and baked into the HTML. A scheduled job rebuilds the site so that data stays current without anyone running a build by hand.
push to main ─┐
cron, 6h ─┼─→ GitHub Action ─→ astro build ─→ Vercel
org repo push ─┘ │
├─ GitHub API (repos, stars, commits)
├─ YouTube feeds (per-org channels)
└─ src/content/ (markdown, YAML)
Publishing a post does not wait for the cron: committing markdown to
main triggers a deploy immediately.
pnpm install
pnpm dev # http://localhost:4321| Command | What it does |
|---|---|
pnpm dev |
Development server |
pnpm build |
Production build into dist/ |
pnpm preview |
Serve the built site locally |
pnpm validate:content |
Check content files, in plain English |
pnpm validate:links |
Check every internal link resolves (needs a build first) |
pnpm check:contrast |
Verify colour contrast meets WCAG AA |
pnpm typecheck |
Type and template checking |
pnpm optimize:assets |
Re-compress images in src/assets/ |
src/
content/ ← the site's actual content
blog/ posts (.md / .mdx)
members/ one file per person
projects/ curated project pages
docs/ field guides
boms/ bills of materials
gallery.yaml photo and video index
partners.yaml affiliated clubs
data/
orgs.ts every social/org URL, defined once
site.ts site constants and navigation
components/
ui/ design-system primitives
blog/ the markdown authoring vocabulary
lib/
github.ts repo data, cached, degrades gracefully
youtube.ts channel feeds
feed.ts RSS with media enclosures
styles/
tokens.css every colour, size, and spacing value
pages/ ← routes
scripts/ ← validation and asset tooling
Content lives in src/content/, never in a component. If you find
yourself typing a person's name or a repo's star count into a .astro
file, it belongs in content or comes from an API instead.
Design values live in src/styles/tokens.css, never inline. There
should be no raw hex codes or pixel spacing anywhere else. The token file
documents the measured contrast ratio of every text colour, and
pnpm check:contrast fails the build if a change drops below WCAG AA.
The visual language comes from a set of design mockups: a 24px baseline grid, a document "sheet" over a grey field, monospace labelling, and hairline rules. Influences are U.S. Graphics Company, NASA documentation, Dieter Rams, and Bell Labs-era terminal interfaces.
Two deliberate departures from the mockups are documented in tokens.css:
-
Typography. The mockups specify Berkeley Mono and Houston Mono, both commercial licences. The site ships self-hosted IBM Plex Mono (OFL). To swap in a licensed face, add the
woff2and change two custom properties — no other file names a typeface. -
Surfaces. The mockups' muted labels measured 2.42:1, below even the 3:1 large-text floor. Note that lifting the background alone cannot fix this, because the muted tones are translucent ink composited over it and rise with it — at the limit, the mockup's
.45alpha on pure white still only reaches 4.05:1. Surfaces were lifted and text darkened, to 4.80:1.
Hosted on Vercel via the Git integration — every push builds, and every pull request gets a preview URL.
Configuration lives in vercel.json. Secrets needed:
| Secret | Where | Why |
|---|---|---|
VERCEL_DEPLOY_HOOK |
GitHub repo secret | Lets the scheduled job trigger a rebuild |
GITHUB_TOKEN |
provided by Actions | Authenticated API rate limit during build |
PUBLIC_GISCUS_REPO_ID |
Vercel env | Enables blog comments |
PUBLIC_GISCUS_CATEGORY_ID |
Vercel env | Enables blog comments |
The site degrades rather than fails when these are absent: no deploy hook means no scheduled refresh, no giscus IDs means the comments section explains that it isn't enabled yet.
Site code MIT. Written content and photographs belong to their authors, credited in each file.