WORK / W-05

Team Planner
Who does what, this week.

A multi-user planning web app built for the Pixel Federation cross department use: people as rows, days as columns, tasks as draggable man-day bars - with absences, holidays, milestones and a sprint ruler, shared by the whole team through a browser.

ROLE
Designer & Developer
STUDIO
Pixel Federation
STACK
TypeScript · React · Express
Drizzle · PostgreSQL / PGlite
YEAR
2026
The planner board: team members as rows, working days as columns, coloured task bars, an absence, a holiday column and milestone flags along the top
FIG.01 — A WEEK OF THE ART TEAM ON ONE BOARD (SAMPLE DATA)

An art lead's week is a puzzle: who is on which asset, who is off, what lands before the milestone. In Pixel Federation that puzzle lived in excel, Miro boards, Jira and so on. I built a planner that puts it on one board the whole company can see and edit - and kept building it as the team's needs changed.

A task is "six man-days of the locomotive", it skips the holiday and the artist's doctor's appointment, and the moment two leads open the same plan, one of them must not silently overwrite the other. The first version - a single shared JSON file on the LAN - proved the board, and its limits.

BEFORE
spreadsheet per lead →
who's off? → ask around →
re-plan by hand
WITH THE PLANNER
drag a task onto a person → everyone sees it in seconds

One small Node server hosts everything: it serves the built React app, exposes the REST API and owns the database through Drizzle ORM - a managed PostgreSQL in production, or an embedded PGlite store on disk for a zero-install instance. Accounts are real: bcrypt-hashed passwords, server-side sessions stored only as a SHA-256 hash of the token that lives in an HttpOnly cookie, and three roles - admin, editor, viewer - on top of each person's discipline.

A board is a document: members, tasks, absences, holidays, backlog and milestones. The client autosaves edits after 0.8 s of quiet and polls every 4 s, so teammates' changes simply appear; a status pill reads Saved, Saving, Offline or Conflict. Saves are lost-update-proof - the server checks the board's version inside a transaction that locks the project row, so the second of two competing saves is told the board moved on and its author chooses to reload or keep their copy. Every write is schema-validated, and the server re-derives member names and disciplines from the user table rather than trusting the client.

FIG.02 — ONE SERVER SERVES THE APP, THE API AND THE DATA
E/01
Man-days, not calendar days

A task's length is working capacity: each date is worth 1, 0.5 or 0 for a given person - holidays first, then the board's own non-working weekdays unless a date is forced working, then that person's absences, with half-day absences and afternoon starts drawn as half cells.

E/02
Lost-update-proof saves

Every save carries the version it was based on. Inside a transaction the project row is locked and the version compared; the loser gets a 409 with the current board and a choice - reload, or keep working on its own copy.

E/03
Swimlane packing

A person's overlapping tasks are packed into as few tracks as possible: sorted by start and length, each bar takes the first track where it overlaps nothing, with bars cut cleanly at the visible edges of the grid.

E/04
Sessions that survive a leak

The database stores only a SHA-256 hash of each session token; the token itself exists only in the user's HttpOnly cookie, so a leaked table row cannot be replayed as a login. Passwords are bcrypt-hashed; expired sessions are purged on start.

E/05
Jira, encrypted at rest

An admin can connect Jira Cloud and curate saved JQL bookmarks; editors import issues straight onto the board. The API token is stored AES-256-GCM encrypted and is never returned to a client.

E/06
Fail fast, never corrupt

The embedded database allows one process per data directory, so the server takes an advisory PID lock and refuses to start a second instance with a clear message instead of silently corrupting the store. Migrations are additive and run on startup.

The admin's people page: accounts with their discipline and access role
FIG.03 — PEOPLE, DISCIPLINES AND ROLES (SAMPLE DATA)
The sign-in page of the planner
FIG.04 — REAL ACCOUNTS: SIGN IN, THEN EDIT OR VIEW BY ROLE

In daily use by the teams, evolved from a single-file LAN tool into a multi-user product with accounts, teams, Jira import and a planned-versus-actual read-out per person. It deploys as one Node process behind HTTPS - point it at a Postgres, or run it with nothing installed but Node.

4 s
UNTIL A TEAMMATE'S CHANGE SHOWS UP
3
ROLES — ADMIN · EDITOR · VIEWER