HackNU/26 — 9th Annual Student Hackathon site and registration app
- Registration: Sign in via email OTP or Google OAuth → complete onboarding → access dashboard.
- Teams: Create a team or join via invite link—up to 4 members per team. Teams are considered eligible with at least 2 members. Captain can kick members or dissolve the team; non-captains can leave.
- AI team name generation: AI-powered suggestions for team names in the dashboard.
- Admin: Participants and teams report at
/admin. Check-in for eligible teams at/checkin. Both require your account email to be listed inADMIN_EMAILS(see Setup).
TanStack Start (React) on Cloudflare Workers. D1 + Drizzle for storage. better-auth (email OTP, Google OAuth). Tailwind CSS, shadcn/ui (baseui), i18next (en/kk/ru).
-
Install Bun.
-
Clone the repo and
cdinto it. -
Create
.envand.dev.varsin the project root:cp .env.example .env cp .dev.vars.example .dev.vars
Fill in the values in both files.
.env— Used on your PC for Drizzle Kit andbun run auth:generate(see.env.example)..dev.vars— Loaded by Wrangler forbun run dev; mirrors production secrets (see.dev.vars.example).
Note:
.dev.varsis only for local development. On production, set the same variable names withwrangler secret put <NAME>(or the dashboard). The.envfile is not deployed to Workers—it stays on your machine for CLI tools. -
Install dependencies:
bun install
-
Generate Cloudflare Worker types:
bun run types
-
Apply migrations locally:
bun run db:migrate:local
Email OTP delivery and CV upload use a Google Apps Script. See HackNU26 GAS for the script and setup instructions.
The GAS handles: send-otp, upload-cv / delete-cv, and sync-report. Deploy as Web App → Execute as: Me → Who has access: Anyone. Set Script Properties: GAS_SECRET, CV_FOLDER_ID, WORKER_URL, SHEET_ID.
Note: This setup is feasible because we use the ACM@NU Google Workspace account (Gmail, Drive, Sheets).
Without GAS: If you don't want to spam your mail during testing, you can view the OTP in the verification table (e.g. bun run db:studio:local).
To enable "Sign in with Google":
- Go to Google Cloud Console → APIs & Services → Credentials.
- Create an OAuth 2.0 Client ID (Web application).
- Add authorized redirect URI:
https://your-domain.com/api/auth/callback/google(e.g.https://hacknu.nuacm.kz/api/auth/callback/googlefor production) andhttp://localhost:3000/api/auth/callback/googlefor local. - Set
GOOGLE_CLIENT_IDandGOOGLE_CLIENT_SECRETin.dev.vars(local) or viawrangler secret put(production).
bun run devStarts the Vite dev server on port 3000 with Cloudflare Workers bindings via the @cloudflare/vite-plugin.
When you change auth config, run bun run auth:generate && bun run db:generate.
When you change db schema, run bun run db:generate.
Run formatting and lint checks:
bun run format
bun run lint- Inspect local DB:
bun run db:studio:local - Inspect remote DB:
bun run db:studio:remote
Note: You can also inspect local DB by viewing .wrangler/state/v3/d1 with a SQLite viewer extension in VS Code.
bun run deployThis installs dependencies, builds the app, and deploys to Cloudflare Workers. Wrangler will prompt you to log in if needed.
First-time deploy: Run bun run db:migrate:remote before deploying so the remote D1 database has the schema.
If you do not have Cloudflare access yet, ask for access and provide your email address.
By default, the Worker is available at https://<name>.<subdomain>.workers.dev. For production, use a custom domain:
- Register a domain at Dashboard → Domains → Onboard a domain
- Dashboard → Workers & Pages → your Worker → Triggers → Add Custom Domain
bun run dev— start dev server on port 3000bun run build— build for productionbun run deploy— build and deploy to Cloudflare Workersbun run types— regenerate Cloudflare Worker typesbun run db:generate— generate migrations from schemabun run db:migrate:local— apply migrations to local D1bun run db:migrate:remote— apply migrations to remote D1bun run db:studio:local— open Drizzle Studio for local DBbun run db:studio:remote— open Drizzle Studio for remote DBbun run auth:generate— regenerate auth schema from better-auth configbun run lint/bun run lint:fix— ESLintbun run format/bun run format:check— Prettier