The public site for FiveD Studio — a small product studio out of Saigon. Live engineering pulse. Static-fast pages. Streamed real-time updates.
- Static-first. Every page pre-renders to HTML at build time — instant first paint, hostable on any CDN.
- Live where it matters.
/liveopens a Server-Sent Events stream to the Pulse backend and ticks new events into the feed within seconds of them happening on GitHub. - One config switch from prod-grade.
NEXT_PUBLIC_PULSE_APIis the only environment variable needed; CI plumbs it through automatically. - Designed. Carbon-black canvas, Signal-Green accent, mono-on-system typography. Tokenized in
app/globals.css— no Tailwind, no CSS-in-JS.
| Layer | Choice |
|---|---|
| Framework | Next.js 15 (App Router, RSC) |
| Runtime | Bun |
| Output | next export → static out/ |
| Hosting | GitHub Pages |
| API client | Native fetch against the Pulse REST + SSE API |
bun install
bun run devOpen http://localhost:3000. By default the dev server points at a Pulse
backend at http://localhost:8787. Override with:
NEXT_PUBLIC_PULSE_API=https://your-pulse-host bun run devbun run build # → ./out/
npx serve out/ # preview the deploy artefact locallyCI deploys on every push to main. The workflow lives at
.github/workflows/deploy.yml.
One-time setup:
- Settings → Pages → Source = GitHub Actions.
- Settings → Secrets and variables → Actions → Variables → New variable
PULSE_API_URL= the deployed Pulse base URL.
That's it. Push to main, watch the run, the new build is live ~60 seconds later.
echo "fived.studio" > public/CNAMEThen point A records at GitHub Pages IPs (or a CNAME for www) and enable
HTTPS in Settings → Pages.
app/ # Next.js App Router
page.tsx # / home (hero, products, principles, team)
live/page.tsx # /live real-time activity stream
wrapped/page.tsx # /wrapped quarterly archive (placeholder)
m/[username]/page.tsx # /m/{login} per-member portfolio
components/
SiteHeader.tsx # shared nav
LiveTicker.tsx # SSE client — streams pulse.event into a feed
LiveStats.tsx # client-polled totals so static stats stay fresh
lib/
api.ts # Pulse REST + SSE client (BASE = NEXT_PUBLIC_PULSE_API)
.github/workflows/deploy.yml # CI → Pages
- Add the GitHub login + display name + role to
ROSTERinapp/m/[username]/page.tsx(Next needs it at build time forgenerateStaticParams). - Add the same row to
FALLBACK_MEMBERSinapp/page.tsx(used when the API is unreachable at build time). - Onboard them in Pulse — once they show up in
/v1/members, both pages prefer the live data.
This site consumes these read endpoints. Full contract in the Pulse repository.
| Method | Path | Used by |
|---|---|---|
GET |
/v1/members |
/, /m/[username] (resolve display name + avatar) |
GET |
/v1/members/:login |
/m/[username] (recent events) |
GET |
/v1/events?member=&limit= |
/m/[username], /live (initial fill) |
GET |
/v1/totals?days= |
/, /live (stats grid) |
GET |
/v1/stream/events (SSE) |
/live (live tick) |
lib/api.ts is the only file that consumes the API; type changes start there.
Proprietary. © FiveD Studio.