Case study · Workforce systems

Retail Shift Scheduler: a week's roster in minutes, offline

Weekly retail rosters, leave tracking and payroll export that used to eat a manager's afternoon — done in minutes, offline in a browser, on one of the strongest test suites in my portfolio.

Vanilla JS · Canvas · IndexedDB · Playwright Status: working, actively maintained · data model v5

01The problem

Rostering a retail store is deceptively hard. Every week a manager has to cover opening and closing under staffing rules, respect who's on leave, spread duties fairly across departments, and land on hours that reconcile to payroll — usually in a sprawling spreadsheet that no one else can safely touch. It's slow, it's error-prone, and a single mistake shows up in someone's pay. The task is repetitive enough to automate but detailed enough that generic scheduling apps never quite fit how a real store operates.

02Constraints

03Approach

The heart of the app is a DOM-free scheduling core: pure JavaScript that takes staff, rules, leave and duties and produces a roster, with no dependency on the browser or a network. Around it, persistence is layered — IndexedDB and localStorage for working state, the File System Access API for exporting, and HTML5 Canvas to render printable PDF sheets. Leave (AL/MC/NG), per-department duties on a timetable, month sheets and an audit trail are all built in, with desktop and mobile builds. Because the data outlives any one version, the saved format is explicitly versioned and the app migrates older files forward on load. All of it is defended by roughly 135 automated tests — around 42 unit tests plus a Playwright end-to-end suite.

04Architecture

05One hard decision & the trade-off

The decision

Build the scheduling logic as a DOM-free, network-free core and invest heavily in a versioned data model with migrations and ~135 tests — before adding features.

It would have been faster to wire logic straight into the UI and skip the migration machinery. But this software feeds payroll and lives on real users' machines, so a bug or a broken upgrade isn't a cosmetic issue — it's someone's pay and a month of lost data. Separating the core made it exhaustively testable, and versioning the schema meant every future change could ship without stranding existing rosters. The cost is upfront engineering that a throwaway tool wouldn't justify; the payoff is that I can keep improving it in production without fear, which for business software is the whole game.

06Outcome

~135automated tests (unit + E2E)
v5data model with migrations
0servers · fully offline

The scheduler is in real, ongoing store use. A weekly roster that used to be an afternoon of spreadsheet wrangling is now minutes of guided work, with leave and coverage handled automatically, payroll exported directly, and an audit trail behind every change. It's the piece I point to when the question is whether "offline, single-file, vanilla JS" can also mean rigorous — a versioned data model and one of my deepest test suites say it can.

Tech

07FAQ

How does a scheduling app work fully offline?

The core scheduling logic is plain JavaScript with no DOM or network dependency, and state persists locally through IndexedDB, localStorage and the File System Access API. There's no server in the loop, so a store manager can build next week's roster on a laptop with no internet and export it straight to payroll.

What stops an update from corrupting existing rosters?

The saved data carries a schema version — currently v5 — and the app runs forward migrations on load, so older files are upgraded in place rather than breaking. That versioned data model, plus around 135 automated tests including a Playwright end-to-end suite, is what makes it safe to keep shipping changes to software people rely on for payroll.

How much time does it actually save?

Building a weekly retail roster by hand — balancing coverage rules, leave, duties and payroll hours across managers, full-timers and part-timers — is hours of spreadsheet work. The app applies the coverage rules automatically and exports payroll directly, turning that into minutes, with an audit trail so changes are traceable.

Need an internal tool that runs without IT approval?

Let's talk. Rostering, inventory, inspections — if it's an operations headache, it can usually become a tool your team just opens and uses.

Get in touch