The CoNSTruct hackathon experience now runs on a React + Vite front-end with an Express/Firebase API. Expect a neon-charged landing experience, a reactive registration flow, and an admin console that mirrors Firestore submissions in realtime.
.
├── client/ # Vite + React + Tailwind front-end
│ ├── index.html
│ ├── src/
│ │ ├── components/
│ │ ├── pages/
│ │ ├── hooks/
│ │ └── data/
│ └── public/ # Static assets consumed by Vite
├── server/ # Express API + Firebase Admin bootstrap
│ ├── index.js
│ ├── routes/
│ ├── services/
│ └── middleware/
├── api/submit.js # Serverless handler that reuses server/services
├── data/local-registrations.json
└── package.json # Root scripts for API + client orchestration
- The React app lives in
client/(Vite, React 18, Tailwind, Framer Motion, React Router). - When
client/distexists (afternpm run client:build), Express serves it as the SPA shell. Otherwise it falls back to the legacypublic/folder. /api/registrationsand/api/submitare identical POST endpoints accepting team payloads./api/registrations(GET) stays Basic Auth–protected for admins.
- Node.js 18+
- npm 9+
- Firebase project with Cloud Firestore
- Service account JSON with read/write access (see
.env.example)
Copy .env.example → .env (server/API) and client/.env.example → client/.env (Vite) before running locally or configuring hosting.
| Variable | Description |
|---|---|
FIREBASE_SERVICE_ACCOUNT |
Optional. Inline JSON (or base64) for the service account. |
FIREBASE_SERVICE_ACCOUNT_PATH |
Optional. Path to service-account JSON (defaults to bundled sample). |
PORT |
Express port (default 3001). |
CORS_ORIGIN |
Comma-separated list of allowed origins. |
API_RATE_LIMIT_MAX |
Requests per minute for the /api limiter (default 60). |
ADMIN_USERNAME |
Basic Auth username for the admin console (default admin). |
ADMIN_PASSWORD |
Basic Auth password (required in production). |
VITE_ADMIN_USERNAME |
Vite build-time variable that surfaces the preset username on the admin login UI. |
Install dependencies once for the server:
npm installIn one terminal:
npm run client:dev- Vite boots at
http://localhost:5173with Hot Module Reload. - Proxies are not configured; API calls still point to
http://localhost:3001.
In another terminal:
npm run dev
# or
npm startThe API listens on http://localhost:3001. When you build the React client (npm run client:build), the Express server will start serving client/dist automatically.
npm run client:build
npm startclient/dist becomes the SPA entry point, served by Express alongside the /api routes. Use npm run client:preview for a static preview powered by Vite.
- Animated hero with countdown timer, neon backdrop, and orbiting particles.
- Dark/light theme toggle with persisted preference.
- Section navigation powered by React Router + smooth hash scrolling.
- Tailwind-powered cards for timeline, guidelines, awards, and partners.
- Registration form with dynamic member slots, validation helpers, and live API submission.
- Admin console that authenticates with Basic Auth and renders curated registration cards.
- Analytics beacons emit
page_viewevents to/api/_analyticsusingnavigator.sendBeacon.
- Registration form posts JSON to
POST /api/registrations. - Payload validated via
server/services/teamRegistrations.js. - Valid submissions persist to Firestore (or
data/local-registrations.jsonfallback when Firestore is absent). - Admin console hits
GET /api/registrationswith Basic Auth headers.
| Issue | Fix |
|---|---|
Admin access is not configured |
Supply ADMIN_PASSWORD in .env or your hosting platform. |
Failed to save submission |
Confirm Firebase credentials and Firestore permissions. |
| CORS errors | Set CORS_ORIGIN to the front-end origin list. |
| Express serves old static HTML | Run npm run client:build so client/dist/index.html exists. |
- Full-stack hosts (Render, Railway, Fly.io, VPS): build the client during deploy (
npm run client:build) and launch withnpm start. - Static hosting + serverless: deploy
client/distto your static host of choice and reuseapi/submit.jsas a serverless endpoint. - Vercel hybrid: deploy
client/as the front-end, mountapi/submit.js, and keep the Express server for environments where SSR is unnecessary.
Bring your own brand edits, motion tweaks, and data sources — the React structure is modular, so you can slot in live leaderboards, mentor rosters, or hackathon telemetry next.