github.com/ArnavChoudhary9/brca-website · status: COMPILING · updated 13d ago
Cultural events portal for the Board for Recreational and Cultural Activities, IIT Delhi — clubs, competitions, calendar, public submissions, inter-hostel trophy.
Built on Next.js 16 (App Router), Postgres, MinIO, nginx. Deployed as a single Docker compose stack.
# 1. Bring up Postgres (5434) and MinIO (api 9100, console 9101)
npm run db:up
# 2. Copy env template and adjust if needed
cp .env.example .env
# 3. Install deps, migrate the schema, seed sample data
npm install
npm run db:migrate
npm run db:seed # prints the seeded user list + default password
# 4. Run Next.js
npm run dev
Open http://localhost:3000. Sign in at /login with any seeded user (default password changeme).
| Username | Role |
|---|---|
tanvi.saxena.gsec | GSec |
vikram.hegde.dgsec | D-GSec |
aarav.mehta.dance | Dance Secy |
karan.bhatia.music | Music Secy |
(Full list printed by npm run db:seed.)
| Script | What it does |
|---|---|
npm run db:up | Start Postgres + MinIO via compose.dev.yml |
npm run db:down | Stop them (keeps data) |
npm run db:reset | Stop, wipe volumes, restart |
npm run db:logs | Follow Postgres + MinIO logs |
npm run db:generate | Generate a new Drizzle migration from the schema |
npm run db:migrate | Apply pending migrations |
npm run db:seed | Seed the DB from src/data/*.json |
npm run db:studio | Open Drizzle Studio (DB browser) |
npm run dev | Start Next.js |
npm run build | Production build (standalone output) |
npm run lint | ESLint |
MinIO console: http://localhost:9101 — login with MINIO_ROOT_USER / MINIO_ROOT_PASSWORD from .env.
All persistent state lives in Postgres. Drizzle schema: src/db/schema.ts. Files (banners, rulebooks, avatars, contest submissions) live in MinIO under bucket brca.
The site loads from the JSON files in src/data/ only at seed time (src/db/seed.ts). Once seeded, edits happen exclusively through /admin.
Sign in as a Secy and:
/admin/competitions/new. Fill in title, dates, description, weight, optional submission window. Save as draft, then upload banner / rulebook PDF, then submit for review. GSec/D-GSec approves at /admin/approvals./admin/events/new. Same workflow./admin/announcements/new. Per-club or BRCA-wide (officers only).submissionsOpenAt/submissionsCloseAt set and is approved, anyone can upload a file at /comp/<slug>/submit. Secys see entries at /admin/competitions/<id>/submissions.pending → visible to GSec/D-GSec at /admin/approvals.approved).audit_log table)./trophy shows:
winner.points × competition.weight per hostel.The single weight field on a competition applies in both club and overall rankings.
src/
app/ # Next.js App Router routes
(public) # / · /clubs · /clubs/[id] · /comp/[id]
comp/[id]/submit/ # public submission form
admin/ # role-gated admin pages
login/ · logout/ # auth pages
components/
layout/ # Navbar · Footer
cards/ # ClubCard · EventCard · CompetitionCard · TeamMemberCard
calendar/ # multi-day calendar with mobile-friendly grid
trophy/ # tabbed leaderboard
admin/ # AdminShell · forms · upload widgets
ui/ # shadcn primitives (auto-generated)
data/ # JSON seed source (clubs/events/comps/team/trophy)
db/ # schema · migrations · seed · drizzle client
lib/
actions/ # Server Actions (CRUD + uploads + approvals)
auth/ · auth.ts # bcrypt + iron-session + DB sessions
queries/trophy.ts # tabbed-trophy SQL aggregation
schemas/ # zod schemas
storage.ts # @aws-sdk/client-s3 wrapper for MinIO
data.ts · types.ts # public data layer (consumed by all public pages)
date.ts # native Intl-only date helpers
proxy.ts # Next.js 16 proxy (replaces middleware) gating /admin/*
nginx/default.conf # prod reverse proxy: /assets/ → MinIO, / → Next
Dockerfile # multi-stage: deps → build → runner (standalone) + migrator
compose.dev.yml # dev: Postgres + MinIO only; Next runs on host
compose.prod.yml # prod: postgres + minio + migrate + next + nginx
Single host, single network, single port (80).
# 1. Set production env
cp .env.example .env
# Edit .env: strong POSTGRES_PASSWORD, SESSION_SECRET, MINIO_ROOT_PASSWORD
# 2. Build + start the full stack
docker compose -f compose.prod.yml up -d --build
# 3. (Once, optional) Seed sample data
docker compose -f compose.prod.yml --profile setup run --rm seed
The site is now at http://<host>/. nginx fronts:
/_next/static/... → Next.js (long-cache)/assets/<key> → MinIO bucket brca (long-cache, immutable):3000After first up: log in as GSec (default tanvi.saxena.gsec / changeme if you seeded), immediately change the password at /admin/profile, then create real officer accounts at /admin/users and delete the seeded ones.
compose.prod.yml does not publish Postgres or MinIO ports to the host — they're only reachable inside the compose network. Submission files are publicly readable via nginx because the bucket has a download policy; if you need private submissions, gate the path in nginx and add an authenticated download route.
The migrate service runs once at up and exits. next won't start until migrations succeed.
Not handled here. Front this stack with a reverse proxy that terminates TLS (Caddy, Cloudflare, an nginx ingress) and forwards :80.
proxy.ts (not middleware.ts); cookies(), headers(), route params are all async; output: "standalone" for Docker.src/db/migrations/.base-nova style) on Tailwind v4 — Button, Card, Tabs, Input, Label, Textarea, Dialog, DropdownMenu, Sonner, Avatar, etc..env (no code change).Internal IIT Delhi project. No license declared.