Inspiration
Managing payslips manually is error-prone, and often not accesible to small businesses that can't afford expensive HR software. I wantd to build something that feels modern and professional, a tool that any employer or HR manager could pick up and use immediately, without a steep learning curve. NexaPay was born from the simple idea that payroll management should be clean, fast, and secure.
What it does
NexaPay is a modern payslip management web application that helps employers and HR managers create, manage, and distribute payslips with ease.
How we built it
NexaPay is a full-stack web application built with a modern frontend-first stack:
- Frontend: React 18 + TypeScript
- Styling: Tailwind CSS + shadcn/ui
- Backend: Firebase Authentication + Firestore
- PDF: jsPDF
- Forms: React Hook Form + Zod
- Routing: React Router v7
- Build Tool: Vite
The database uses three Firestore collections — payslips, employees, and settings — all scoped per authenticated user. Salary calculations follow a straightforward model:
\( \text{Gross Pay} = \text{Basic Salary} + \text{Total Allowances} \)
$$ \text{Net Salary} = \text{Gross Pay} - \text{Total Deductions} $$
These are computed automatically as the user fills in the payslip form — no manual arithmetic needed.
Authentication supports both Email/Password and Google Sign-In, making onboarding frictionless. Once logged in, users set their company name in Settings and can immediately start generating payslips.
Challenges we ran into
- Time pressure — Every hour counted. Balancing building, debugging, and polishing a full-stack app within a tight hackathon deadline meant making fast decisions and constantly re-prioritising what mattered most.
- Credits expiring — Running out of Firebase and API credits mid-build was a stressful reality check. We had to quickly rethink usage, optimise calls, and work around limitations just to keep the app alive and functional.
- Debugging a prompt-based app — Debugging AI-assisted and prompt-driven logic is a different beast entirely. Errors aren't always obvious — sometimes the output looks right but behaves wrong, and tracing the source of the problem takes far longer than traditional debugging.
- Firestore security rules — Writing airtight per-user data isolation rules required careful iteration and testing. One wrong rule could expose sensitive payroll data.
- Responsive tables — Payslip data is naturally wide and table-heavy. Making it readable on small screens without losing clarity took significant layout work with Tailwind CSS.
Accomplishments that we're proud of
- Built a fully functional payroll system end-to-end — from authentication to PDF download — in a single hackathon sprint
- Achieved complete data isolation between users using Firestore security rules, with no shared data leakage
- Delivered a clean, professional UI that feels production-ready, not like a hackathon prototype
- Implemented automatic salary calculations that update in real time as the user fills in the form
- Made the app fully responsive — usable on a phone just as comfortably as on a desktop
What we learned
- How to structure Firestore security rules for strict per-user data isolation in a multi-tenant app
- How to combine React Hook Form + Zod for robust, type-safe form validation at scale
- How to generate formatted PDF documents client-side using jsPDF without any server involvement
- How to build and ship a complete, polished product under time pressure
What's next for nexapay
- [ ] Dark / Light mode toggle — Let users choose their preferred theme
- [ ] Bulk payslip creation — Generate payslips for an entire team in one action
- [ ] Export to CSV — Download payslip data for use in spreadsheets or accounting tools
- [ ] Email notifications — Automatically email payslips to employees on generation
- [ ] Mobile app — A native mobile experience built with Capacitor
Built With
- firebase-authentication
- firebase-storage
- firestore
- jspdf
- node.js
- react
- react-hook-form
- react-router-v7
- shadcn/ui
- tailwind-css
- typescript
- vite
- zod
Log in or sign up for Devpost to join the conversation.