Skip to content
Back to all work
Full-Stack / Workflow Engineering2026

LeaveDesk

A working demonstration of a leave and approval portal — an escalation ladder derived from policy, a permission matrix the server actually enforces, and impersonation that names the human at the keyboard.

Role
Architect & sole engineer
Next.js 16React 19TypeScriptPrismaSQLite

The application

Screens, captured from the running app

Booted against its seeded database and walked route by route — these are the real pages, not mockups.

LeaveDesk dashboard with request counts, open approval rungs, days approved and escalations, plus a breakdown by leave type.
Escalations get their own number, because how often a policy threshold fires is a question about the policy, not the people.
Approvals queue separating rungs ready to decide from rungs still waiting on an earlier approver.
Ready-to-decide is separated from waiting-on-someone-else. A queue that lists work you can't yet do trains people to stop reading the queue.
All requests with each approval rung, its approver, its state, and the policy reason the rung exists.
Every rung carries the reason it exists — “12 days exceeds the 10-day manager limit”. Escalation is never a surprise to the person waiting.
Team view by department showing entitlement, days taken and carry-over per person alongside the reporting line.
Carry-over is shown separately from entitlement, because it expires on a different date.
Permission matrix across staff, manager, director, HR admin and super-admin, with the escalation thresholds beside it.
The page renders the same rules the server enforces, so the UI and the authorisation logic cannot drift apart.
Append-only audit trail with impersonated actions tinted violet and labelled “acting for” the affected employee.
Impersonated actions are tinted and name both parties. The trail never shows someone doing something they did not do.

A demo, built to show the architecture behind a confidential internal HR system without exposing it. The firm and its people are invented. The approval ladder, access rules and audit behaviour are the real thing.

Why it exists

Leave portals look trivial from outside — a form, a calendar, an approve button. The parts that decide whether one gets used are all invisible in a screenshot, so here they are running: twelve employees across five departments, thirty-three requests, and a full audit trail.

The ladder is derived, never chosen

A requester never picks their approvers. The ladder falls out of the policy:

  • Level 1 is always the line manager.
  • Level 2 — a director — is added when the request exceeds 10 days, when reimbursable costs exceed €500, or when the leave is unpaid at any length.

Each rung stores why it exists as text, and that text is shown to everyone: "12 days exceeds the 10-day manager limit". Escalation is never a surprise to the person waiting, and nobody has to go and read the handbook to find out why their week off needs a director.

The queue distinguishes "yours" from "not yet yours"

The approvals screen splits pending rungs into two lists: those where every earlier rung is already approved, and those still waiting on someone else.

This sounds fussy and it is the difference between a queue people check and a queue people ignore. If a director's list is padded with second-rung reviews their managers haven't reached yet, the list stops meaning anything within a fortnight.

The permission matrix is one source of truth

Five roles — staff, manager, director, HR admin, super-admin — over a matrix of actions. The server consults it before touching the database, and the roles page renders the same matrix.

Hiding a control the server would refuse anyway is a courtesy to the user, not a security boundary. Deriving both from one declaration means the UI can't quietly drift out of step with what is actually enforced.

Impersonation that can't hide

A super-admin can act on someone's behalf — that capability exists for the phone call where a return date is wrong and the person is already on a plane. Support work genuinely needs it.

What it must not do is let the trail show the impersonated person taking an action they never took. So every event stores two fields: actor is the real human, onBehalfOf is the account. In the trail those rows are tinted and labelled "acting for —", and the seed contains nine of them.

An impersonation feature without that distinction is worse than no impersonation feature, because it manufactures false evidence about a colleague.

Also on screen

Entitlement and balances by department, with carry-over shown separately from the annual allowance because it expires on a different date. Working days are computed excluding weekends rather than taken as a raw date span.

Stack

Next.js 16 App Router with React Server Components, Prisma over SQLite, six routes, deterministic seed. In production this shape pairs with Azure AD SSO through MSAL and notifications over SendGrid and Teams; the demo leaves the integrations out, since they are configuration rather than architecture.

You have a process thatshould be a system.

Tell me what arrives, who has to act on it, and where it currently falls over. That conversation is usually enough to scope the build.