OnTracksy
Draws a timeline of how every ticket moves through your workflow.
A browser extension that draws a timeline of how every ticket moves through a workflow, so stalled work is obvious. Works with Jira, or standalone without it.
The problem
A ticket board shows status, not history. “In Progress” for six days looks the same as “In Progress” since yesterday.
OnTracksy renders each ticket as a lane, one segment per state, sized by how long it stayed there — a stalled ticket is visually obvious without reading fifteen tickets one at a time.
It doesn’t solve every kind of timeline. A trip itinerary, for instance, is one sequence of things happening one after another — a single track, nothing to compare side by side. OnTracksy’s value shows up specifically when several things are moving through the same set of states at once and you need to see them together: a sprint board, a hiring pipeline, a queue of support tickets. One track alone doesn’t need this; a dozen tracks changing state in parallel do.
It works two ways: connected to Jira, or fully local, with no login and no data leaving the browser.
Approach and methodology
Standalone and Jira-connected were always meant to be one product, not two with a shared name — so the design question going in was how to support both without either mode becoming a second-class citizen of the other. The answer was pushing every tool-specific concern (auth, fetching, pagination) behind a single interface, and keeping the timeline-building logic on the other side of it completely ignorant of which mode is running. Architecture below shows the shape that produced.
Built solo over about four months, with dedicated accessibility and security review passes rather than something bolted on at the end. Development itself was agentic: the repo’s own process docs define a model-tiering scheme — a planning pass on a stronger model, an orchestrating pass on a mid-tier one, mechanical work on a faster one — plus named roles for specific jobs, like a dedicated code reviewer and a dedicated end-to-end spec author. Every change runs against the actual built and loaded extension through a Playwright/BDD suite before it counts as done, regardless of which tier wrote it.
Architecture
A Jira Cloud adapter and a local-only static adapter both implement one ToolAdapter interface,
feeding the same timeline-building pipeline — that’s the whole trick behind shipping standalone
and Jira-connected modes as one product instead of two. The shape that both sides have to
satisfy, from the real interface (libs/core/src/models/adapter.interface.ts):
export interface ToolAdapter {
getSprints(): Promise<Sprint[]>;
getSprint(sprintId: string): Promise<Sprint>;
getSprintTickets(sprintId: string): Promise<Ticket[]>;
getTicket(ticketId: string): Promise<Ticket>;
getTicketHistory(ticketId: string): Promise<Ticket>;
}Trimmed to the data-shape methods — the real interface also declares authenticate and
refreshToken, which imply an OAuth exchange. What actually ships rides the browser’s own Jira
session cookie instead (see Limitations), so those two are left out here rather than shown and
left unexplained.
| Standalone | Jira-connected | |
|---|---|---|
| Data source | Data you provide — a static, already-complete snapshot | Jira Cloud REST API, fetched live |
| Login | None | Your existing Jira session cookie — no separate account |
| Updates | None — a fixed point in time | Polling (see Limitations — no webhooks) |
| Leaves the browser | Never | Only requests to your own Jira instance |
No content script, either mode. The extension opens as a full browser tab, and Jira-connected mode requests narrow permissions at runtime rather than at install — avoiding the broad “read your browsing history” warning a content-script-based extension would trigger.
Results
The bet was that one framework-free core could serve two very different audiences — teams already living in Jira, and people who just want a private, local timeline — without becoming two separate products. That held: the standalone extension, the Jira-connected extension, and a Jira Marketplace app all run on the same core today.
None of the three has a public listing yet. The Chrome Web Store and Edge Add-ons submissions, and the Jira Marketplace listing, are release tasks still ahead — store assets, a business entity, and a few other non-code steps — not a code gap. Closed beta reflects that plainly: the extension works end to end, there just isn’t a public install link to it yet.
Limitations
- Polling only, no real-time webhooks — a deliberate scope cut, not an oversight.
- Two accepted accessibility trade-offs, both documented rather than silently shipped: the
drag/resize handles on a timeline segment are pointer-only and marked
aria-hiddenrather than half-working with a keyboard; the lane list’s row/cell markup doesn’t sit inside a proper table/grid ancestor, deferred rather than rushed. - An API-key Jira auth path exists in the code but was never wired to a UI. The only authentication that ships rides the browser’s own Jira session cookie.
- No Firefox support. Trello/Asana/GitHub adapters are anticipated by the interface, none implemented.
Work in progress
An Insights panel — flow metrics, time-in-status breakdowns — is fully built and sitting behind a feature flag, off by default.
The Jira Marketplace app is far along but hasn’t had a formal “done” pass yet.
The remaining work is mostly the non-code kind: store listings, a registered business entity, and the paperwork a Marketplace vendor account requires — the checklist Results points at, not another feature.