Maanaim Entry
Overview
Maanaim Entrada is an internal system used by Igreja Cristã Maranata - Maanaim de Uberlândia to track, in real time, all people entering and leaving on-site events. Before this system, staff relied on manual counting and spreadsheets, which made it hard to know the exact number of attendees inside the venue at any given moment, created lines at the entrance, and increased the risk of exceeding capacity.
I built a PWA web application where gate operators use phones or tablets to scan QR badges (via camera or physical scanner). Each scan registers an entry or exit in the database in real time, validating the attendee against the event’s registration list and immediately updating a shared status dashboard. Coordinators can see current occupancy, filter by church, and rely on accurate attendance records instead of approximate counts.
I acted as the full-stack engineer responsible for the entire solution: overall architecture, Next.js front-end, Fastify API, PostgreSQL modeling with Drizzle, JWT authentication with refresh tokens, authorization with CASL, infrastructure with Docker, and CI/CD with GitHub Actions on a VPS. I also focused heavily on the UX for gate operators, especially the badge scanning flow on mobile devices.
The system is currently in production, has been used in over 70 events, and has processed tens of thousands of attendees. It effectively removed manual attendance control and significantly reduced check-in time during peak arrivals in large seminars.
Key Differentiator
The key differentiator of Maanaim Entrada is not being “yet another check-in app”, but operating reliably under the real-world constraints of large-scale religious events: unstable connection, operators with varying technical background, intense short-lived peaks of scans, and the need for instant operational feedback.
Technically, the core feature is a robust badge scanning flow on mobile browsers: camera access, support for external scanners, manual search fallback, multiple identifier formats, and explicit camera permission management with clear feedback to the operator. Combined with real-time updates via Socket.IO on a shared dashboard, this reduces the need for verbal communication and parallel spreadsheets across teams.
Another strong point is the engineering for evolution: pnpm/Turborepo monorepo, schema versioning with Drizzle, a GitHub Actions pipeline tailored for a simple VPS, and an authentication/authorization model already prepared for multiple roles (gate operators, coordinators, admins) without complicating daily operations.
Architecture
- PWA Web App (Next.js 15 + React 19): main interface used on phones, tablets and desktops; supports PWA install, basic offline capabilities and fast access during events.
- QR Scanner Module: React component responsible for accessing the camera or physical reader, managing permissions, selecting the video device, and resolving the scanned value to a valid attendee.
- Gate Control Screen: operational UI for operators to register entries/exits, see recent scans, handle scan errors and fallback to manual search by name/registration.
- Event Status Dashboard: consolidated view with current occupancy, entries and exits over time, capacity and distribution by church, updated in real time via WebSocket.
- HTTP API (Fastify 5): REST services for authentication, event management, registrations, presence records, audit logs and configuration.
- Authentication Module (JWT): access + refresh tokens, stored in HTTPOnly cookies, with transparent token refresh and revocation when needed.
- Authorization Layer (CASL): role-based permissions (gate operator, coordinator, admin) defining which actions and resources each profile can access.
- Validation Layer (Zod): validation of incoming requests and API responses, ensuring end-to-end type safety between front-end and back-end.
- ORM and Migrations (Drizzle + PostgreSQL): relational modeling of events, churches, attendees, registrations and presence logs, with safe, versioned migrations for production.
- WebSocket Layer (Socket.IO): real-time channel used to broadcast presence updates and event status to all connected clients simultaneously.
- Cache and Sessions: used for sessions, hot data caching, and coordination between multiple API instances for real-time events.
- Deployment Infrastructure: containerized services running on a VPS, process management and centralized logging.
- CI/CD Pipeline (GitHub Actions): automation to install monorepo dependencies, build, run Drizzle migrations and (re)start services on each deployment.
Technical Highlights
- Production system that has handled 74+ events and 27,000+ attendees so far.
- PWA + WebSocket architecture designed for usage spikes: hundreds of badge scans in a few minutes during event start.
- QR scanner module refined through 20+ iterations, addressing browser camera permission issues, device selection, inconsistent mobile behavior and multiple badge formats.
- Robust badge matching logic, accepting numeric registration, string registration or physical crachaId, with graceful fallback to manual search.
- Back-end built with Fastify 5 focused on performance, combined with Drizzle ORM for end-to-end type safety and versioned PostgreSQL migrations in production.
- JWT authentication with refresh tokens and HTTPOnly cookies, suitable for PWA usage across multiple devices.
- Role-based access control with CASL, clearly separating gate operators, coordinators and admins in terms of capabilities and data access.
- Monorepo setup with pnpm + Turborepo and a GitHub Actions pipeline refined over many iterations to reliably orchestrate build, migrations and PM2 restarts on a VPS.
- Deployment on a simple VPS using Docker, showing a pragmatic, maintainable production setup without heavy orchestration.
- TypeScript-heavy codebase, covering front-end, back-end, shared contracts, validation and domain logic.