AttendifyClassroom Attendance App
- Period
- Jan 2026 - Mar 2026
- Project type
- Collaborative Duo Project
- Role
- Full-Stack Developer (Pair)
- Team
- Two-person development team
A cross-platform attendance application for organizing classes and students, marking a daily register, and reviewing monthly and weekly summaries through a JWT-protected NestJS API.
- Tracked client repository
- 102Mobile filesTracked client repository
- Tracked backend repository
- 51API filesTracked backend repository
Overview
Attendify connects an Expo Router mobile client to a modular NestJS and PostgreSQL API. Teachers can restore an authenticated session, maintain owned classes and rosters, record one mark per student and date, and request render-ready attendance summaries without issuing a query for every visual cell.
Role & context
- Role
- Full-Stack Developer
- Team
- Two-person development team
- Type
- Collaborative Duo Project
- Period
- Jan 2026 - Mar 2026
Built as a two-person full-stack project across separate Expo mobile and NestJS API repositories. Responsibilities and outcomes are presented at team level because the repository history does not consistently separate each collaborator's contribution.
Problem
Paper registers and ad-hoc spreadsheets make daily attendance capture slow and monthly reporting error-prone. The system connects authentication, owned class rosters, one mark per student and date, and consistent summary calculations.
Approach & architecture
Expo client (RTK Query) talks to a JWT-guarded NestJS API scoped by ownerId over TypeORM/PostgreSQL; auth state is persisted on-device and the app ships as an internal EAS APK.
Practices followed
Multi-tenant ownership isolation
every class/student/attendance query is scoped by
ownerIdfrom the JWT, so one teacher can never read or mutate another's dataIdempotent writes
a composite unique index (
studentId, date) plus an upsert path means the same mark sent twice never creates duplicatesPassword hygiene
bcrypt-hashed passwords and a
sanitize()projection that strips the hash before any user object leaves the API; password reset requires the old passwordHook-per-screen separation of concerns
each screen has a sibling use<Screen>.tsx owning data/effects, leaving the screen file as pure JSX
Cache-correctness over manual refetch
RTK Query tags drive invalidation, so marking a student auto-refreshes dependent summary screens
End-to-end type safety
TypeScript strict, @/* path aliases, and Expo Router typed routes from route name to API call to Redux state
Challenges & resolutions
School reports demand boys/girls splits at four granularities (daily, weekly, monthly, yearly), and the academic 'week' is week-within-the-month (1-5), not ISO week — naive per-endpoint SQL would be four near-duplicate queries disagreeing on edge cases.
FixCentralised the maths in the attendance service: fetch the marks for the date range once, then group in-memory by a custom week-of-month function and by gender. One source of truth feeds all summary endpoints with render-ready totals.
On Android cold start, the login screen flashed before redux-persist rehydrated the saved JWT.
FixWrapped the app in PersistGate (whitelist: auth) and gated the entry route on the rehydrated accessToken before choosing login vs class-select; auth routes also suppress the bottom-tab layout.
Outcomes
The source implements the teacher workflow from authentication through class and roster setup, daily marking, and summaries
The mobile client and API are separately versioned and can be developed and deployed independently
Database and service rules address duplicate daily marks and cross-owner access
EAS profiles provide a path from development builds through internal preview to an Android app bundle
Tech stack
Concepts & skills12
- JWT bearer authentication (NestJS Passport guards)
- Role-Based Access Control (TEACHER / STUDENT / ADMIN)
- Multi-tenant data isolation via ownership scoping
- Composite unique indexes for idempotent writes / upserts
- TypeORM relations & cascading deletes
- RTK Query with tag-based cache invalidation
- redux-persist + PersistGate rehydration
- Expo Router file-based & typed routes
- NativeWind / Tailwind in React Native
- DTO validation (class-validator) + Swagger/OpenAPI
- EAS Build profiles & internal APK distribution
- React Native New Architecture + React Compiler