Skip to content

Repository files navigation

machzero-web

The MachZero site (PESOS X Silicon hackathon, 31 Oct – 1 Nov 2026) built on eventKit. Its / page is the MachZero hero page, and behind it the app does everything the hosted eventKit front end does, scoped to this one event:

Path What
/ Hero page with the Mach meter, schedule and "Register your team"
/join The event's participant link: start a team (or log in / sign up first)
/i/:token Any other invite link (volunteer, judge, admin)
/app The dashboard: team and registration for participants, scanner, admin section

It talks only to the public eventKit API, with this event's own API key. It is an installable web app (PWA); the volunteer scanner lives here too.

Setup in eventKit

The event is created and run in eventKit; this site needs three values from it:

  1. Event ID: the MachZero event's id.
  2. API key: an admin creates one for the event (POST /v1/events/{eventId}/api-keys, see eventkit-api's docs/usage.md). The full key is shown once. It only says which event's app is calling; permissions still come from each user's role.
  3. Participant link token: from the event's participant invite link (Admin → Links), the part after /i/.

Add this site's origin to the API's CORS_ORIGINS (or serve it under the same domain as the API, with the API at /api).

Run locally

Start the API first (see eventkit-api's README), then:

cp .env.example .env   # fill in VITE_EVENT_ID, VITE_API_KEY, VITE_PARTICIPANT_TOKEN
npm install
npm run dev            # http://localhost:5174 (proxies /api to localhost:4000)

API types

Types come from the API's OpenAPI spec, never written by hand:

npm run gen:api        # reads ../eventkit-api/openapi.json by default
OPENAPI_SPEC=/path/to/openapi.json npm run gen:api

src/api/client.ts wraps openapi-fetch: every call is typed from the spec and carries the Bearer token and X-Api-Key.

Scripts

Script What it does
npm run dev Dev server
npm test / npm run test:coverage Vitest + Testing Library + MSW (90% gate)
npm run lint / npm run typecheck oxlint, tsc
npm run build Production build into dist/

Docker

The image serves dist/ with Caddy. Configuration is read when the container starts (written to /config.js), so one image works anywhere:

Variable Default Meaning
API_URL /api Where the API is
API_KEY The MachZero event's API key
EVENT_ID The MachZero event's id
PARTICIPANT_TOKEN Token of the event's participant link

Without PARTICIPANT_TOKEN, /join shows "Page not found".

Design

  • Hand-written CSS in src/theme.css, taken from the MachZero page: Bricolage Grotesque, ink on pale blue-grey, one hot orange accent, light and dark modes (prefers-color-scheme, or data-theme on <html>). No UI kit.
  • Components use semantic classes (.card, .btn, .badge--ok, …); cx() in src/lib/utils.ts joins them.
  • The Mach meter (src/features/landing/mach.ts) is the page's canvas script as a module: it starts when the hero mounts and stops when it unmounts.

Notes

  • Times are stored in UTC and always shown in IST (src/lib/datetime.ts).
  • The service worker caches only the app shell. API responses are never cached, because scanning is online-only.
  • Creating events is left to eventKit; this site serves one event.

Releases

Packages

Contributors

Languages