Overview
An internal inventory management panel built at TOPS Infosolutions: stock, orders and users, with different roles seeing different slices of all three. Admin panels are unglamorous and enormously consequential — someone uses this tool for hours a day, and every bit of friction is paid for repeatedly.
What I built
- Next.js App Router with TypeScript, wired to more than ten REST endpoints owned by the backend team.
- Role-based access control, applied to both routing and individual UI affordances — a role that can’t perform an action shouldn’t be shown a button that fails.
- JWT auth with secure cookie session handling, specified jointly with the backend team rather than reverse-engineered from the endpoints.
- A reusable component library with Framer Motion transitions, verified across Chrome, Firefox and Safari, which put an end to a recurring class of cross-browser regressions.
The performance work
The production site scored 68 on Lighthouse. It now scores 92, and loads 45% faster. That came from:
- Server-side rendering for the content that was previously assembled in the browser.
- Dynamic imports for heavy, rarely-used routes.
- Lazy loading below the fold.
- Asset optimisation — correct formats, correct sizes, correct caching.
None of it was clever. All of it was measured first. The single most useful habit was refusing to change anything until I could point at the number it was supposed to move.
Things worth remembering
RBAC belongs in the data layer, not the template. The first version checked roles in components. That works until two components disagree. Deriving permissions once, close to the data, and letting the UI ask questions of it, is both safer and shorter.
Admin tools deserve real design. The temptation is to ship a table and move on. But the people using it are captive — they can’t choose a competitor — which seems to me like an argument for more care, not less.