The idea
Most trackers tell you what a board looks like now. Throughline keeps the whole path: every mutation appends an immutable event, so the board can be rewound to any point in time and restored from it. Because the restore is itself recorded, the history stays append-only and the rewind is reversible.
It runs with no external services — a SQLite file and Bun serve everything.
What's in it
- Board and issues — drag-and-drop kanban with story points, priorities, labels, assignees, subtasks and comments
- List view with grouping by status, assignee or priority, plus saved filters
- History — the event log rendered as a timeline you can scrub and play back
- Analytics — cycle time and weekly throughput
- Command palette (
⌘K) and single-key shortcuts - Assistant — triage, decomposition and summaries; uses an OpenAI-compatible LLM when configured, and a local heuristic engine otherwise
Three decisions that shape the code
The event log is the source of truth for history. Issues carry current state, but every mutation also appends an immutable event. Time travel is a fold over those events rather than a separate snapshot table — which is why restoring is just another event rather than a destructive write.
Server state is mirrored into Zustand, not re-fetched. TanStack Query hydrates the stores on load; after that a mutation's response is applied in place — a create appends, a patch patches, a delete removes. Nothing refetches a collection because one item changed. That's what makes dragging a card feel immediate: one round-trip that never blocks the UI.
Styling is a single semantic token layer. Components reference bg-surface,
text-muted and border-border, never a literal colour, so light and dark are a
token swap rather than a branch in every component.
Accessibility
WCAG 2.2 AA is treated as a build requirement rather than a polish pass: every
board operation has a keyboard path, all form controls are programmatically
labelled (React Aria warnings are treated as failures), status and priority are
never conveyed by colour alone, contrast is verified in both themes, and
prefers-reduced-motion is honoured.
Stack
Bun workspaces throughout. The API is Hono with typed RPC, Drizzle ORM, Valibot and JWT auth. The client is React 19 on Vite 8, HeroUI v3 over React Aria, Tailwind CSS 4, wouter, TanStack Query and Zustand. A shared package holds the Valibot schemas and inferred DTOs used by both ends, so client and server can't drift.


