Forge30
Applications, status lookup, an admin area and verifiable student ID cards for a 30-day, 60-hour developer programme.
- Role
- Product, full-stack build, security, deployment
- Testing
- Unit, API and security, six-viewport browser and full-journey tests
- Source
- Public
- Stack
- Next.js 15 App Router · TypeScript · PostgreSQL (pg) · Zod · Plain CSS · Vercel
Problem
Running a cohort needs more than a form: applicants need to check their status, organisers need control, and confirmed students need an identity that others can verify without exposing their data.
What I built
- A multi-step application and a status lookup that signs a student in with a reference code and email, remembering the device for 30 days.
- A dashboard showing status, announcements, cohort info, group, class time and seat.
- On confirmation, an automatically issued student ID and a non-guessable serial. Students upload a passport photo that is re-encoded server-side with EXIF stripped, then download a CR80 card at 300 dpi.
- A QR code that opens a verify page showing only name, ID and active or inactive.
- An admin area for applications, cohort settings and exports, with an audit log of admin actions.
Architecture
Application routes, from src/app
src/app/
apply/ status/ dashboard/ applicant journey
v/ verify/ scan/ card verification
admin/ cohort + applications
api/ validated endpoints
opengraph-image.tsx sitemap.ts robots.ts
tests/ unit · e2e · browser (6 viewports) · journey · card Engineering decisions
Security as a checklist in the codebase
Zod validation on every endpoint, parameterised SQL only, Origin checks on state-changing routes, SameSite=Strict admin cookie, database-backed rate limits, constant-time password comparison, CSV formula-injection neutralisation, and noindex plus no-store on admin.
Verification reveals the minimum
The public verify page shows name, ID and status only. Setting a student away from Confirmed deactivates the card, and admin notes are never returned by any public route.
No animation or UI libraries
Plain CSS keeps the bundle small and the behaviour predictable on low-end phones.
Current state and limits
- Public beta: the programme and its numbers are still being established.
- I could not load the deployed beta from my research environment, so its availability is stated from the repository.