SovoHR
SovoHR is a complete HR ERP: employee management, payroll, attendance, rota scheduling, compliance and recruitment, delivered as a SaaS product. The organisation portal is a React application on Vite backed by Laravel; the marketing site and the public job portal are Next.js. Three surfaces, one domain model, and three genuinely different threat models.
- Year
- 2025
- Role
- Engineering - backend, portal and public surfaces
- Context
- SaaS product
- Category
- Platform

The organisation dashboard - the first screen an HR administrator sees.
An HR system holds the most sensitive non-financial data an organisation owns - salaries, addresses, right-to-work documents, disciplinary records. The same employee row has to be fully writable by an HR administrator, partially readable by a line manager, visible in redacted form to the employee, and completely invisible to a candidate browsing the public job board. Every one of those views is backed by one source of truth, and getting the boundary wrong once is a data breach rather than a bug.
Authorisation is modelled on the record rather than the route, so a permission answer does not depend on which endpoint happened to be called. The three surfaces are deployed independently: the authenticated portal, the public jobs board and the marketing site never share a session or a cache, which means the public surface cannot be tricked into rendering privileged data because it has no path to it. Payroll and attendance are treated as append-only histories rather than mutable rows - a corrected timesheet produces an adjustment with an author and a reason, because 'who changed this and why' is the question every payroll dispute actually asks. Multi-tenancy is scoped at the query layer so an organisation boundary is enforced in one place rather than remembered at every call site.
How the pieces fit.
Portal
portal.sovohr.com - React on Vite, the authenticated organisation surface covering every HR module.
Backend
Laravel services owning the domain model, authorisation, payroll calculation and the tenant boundary.
Marketing
sovohr.com - Next.js, the public product surface.
Jobs
jobs.sovohr.com - Next.js job portal and application intake, deployed separately from the portal and sharing no session with it.
Tenancy
Organisation scoping applied at the query layer, so the boundary is enforced once rather than re-implemented per feature.
Records
Payroll and attendance stored as append-only history with attributed adjustments, rather than rows edited in place.
- Employee management - records, education history and work experience in one profile
- Payroll processing with attributed, auditable adjustments
- Attendance tracking with an hourly weekly grid and shift coverage
- ROTA and shift scheduling, including shift-change request workflows
- Right-to-work checks, document management and sponsor compliance reporting
- Recruitment and ATS feeding a public job portal on its own domain
- Employee self-service - payslips, leave requests and personal-detail changes
- Role-scoped access control across administrator, manager and employee views
The parts that were not obvious at the start.
- 01
One record, four audiences
An administrator, a manager, the employee and an anonymous candidate all touch the same underlying data with completely different rights. Putting that logic on routes would have meant re-deriving the answer at every endpoint. Attaching it to the record means there is one place to reason about, and one place to get wrong.
- 02
Payroll has to explain itself
Nobody disputes a payslip that is correct. They dispute the one that changed. Editing rows in place makes that conversation impossible, so corrections are recorded as adjustments carrying an author, a timestamp and a reason - which also happens to be what a compliance audit asks for.
- 03
Compliance is a deadline, not a feature
Right-to-work and sponsor compliance carry statutory dates. A field that stores an expiry is not enough; the system has to surface what is about to lapse, to the person accountable, before it does. That turns a data model into a scheduling problem.
- 04
Three surfaces, one model
The marketing site, the portal and the jobs board share a domain but almost nothing else - different caching, different auth, different exposure. Deploying them separately keeps a public-surface change from ever being a portal risk.
- Live across three surfaces - sovohr.com, portal.sovohr.com and jobs.sovohr.com
- End-to-end HR workflows from recruitment through payroll and offboarding
- Multi-tenant organisation isolation enforced at the query layer
- Authorise the record, not the route. Routes multiply; the record is the thing that actually has an owner.
- Anything a person may later dispute should be append-only. Rewriting history is cheap right up until someone asks what it used to say.
- Separate surfaces are worth their deployment overhead when one of them is unauthenticated.