Before writing a line of code, I read 500+ Marketplace reviews across the Jira Gantt category. I expected the 1-star reviews to be about missing features. They almost never were.
They were about trust. Dates reset on install, without consent. The "Updated" field touched on thousands of issues before first use. Removing a project from a view — and discovering the underlying issues were deleted, with no recycle bin. Hours of replanning gone because there was no autosave and the official advice for errors was "reload the page".
In this category, people don't leave because a feature is missing. They leave because the app changed something they didn't ask it to change. So I built SteadyGantt around one rule: Jira stays untouched until you confirm a diff. Everything else followed from that.
1. No delete path exists. The app cannot delete an issue — not as a feature, not as a bug. The only write it can ever perform is updating the date fields you explicitly confirm.
2. Read-only by default. Opening the chart, zooming, exploring — none of it writes. Every drag creates a draft, rendered next to a dashed ghost of the original so you always see both states.
3. Field-level diff before any write. Syncing opens a panel listing every change as field: old → new, each with its own checkbox. Only checked fields are written. The payload is built from the diff itself, so "never touch unconfirmed fields" is enforced by construction, not by discipline.
4. Undo is a first-class payload. Every sync stores its inverse — the from values, including null when a field was empty. One click restores the exact previous state, "no date" included. This turned out to be the feature reviewers were really asking for when they wrote "I had to reset every timeline manually."
5. Autosave everything, promise nothing else. Drafts and view state (zoom, scroll, collapsed groups, column widths) persist automatically — localStorage for instant restore, Forge KVS for cross-device. There is no save button to forget.
A few things that might save other Forge developers some time:
Runs on Atlassian is a feature, not a badge. Building with zero external egress means no trackers, no cookies, no vendor servers — not as a policy, but because the architecture can't phone home. For a data-safety product this alignment is worth the constraints.
Progressive loading beats waiting. Page 1 of issues goes out before custom-field discovery resolves; later pages include the start-date field, and page 1 gets patched in the background. First paint lands in about a second even behind slow networks, and a local snapshot makes reopening instant.
Canvas, with a performance budget in CI. The chart is a single canvas — 1,000 tasks draw in ~7ms, drag response is sub-millisecond at p95. The budget is enforced by the build script, so a slow commit fails before it ships.
Be honest about date precision. Jira's built-in date fields are day-precision. SteadyGantt offers hour-level zoom for planning, but the diff panel shows exactly the day-rounded values that will be written. Showing users precisely what lands in Jira matters more than pretending precision exists.
Mock the bridge, ship a demo. The best trick I found: esbuild's --alias swaps @Forge/bridge for an in-memory mock at build time. The exact same code that runs in the Forge iframe runs as a public demo page against sample data — drag, diff, sync, undo, all real, no install. If you build Forge apps, you can probably do this too.
I also turned those 500+ reviews into a tool-agnostic data-safety checklist — 10 tests to run in the first hour of any Gantt trial, whichever app you choose. Each test recreates a real incident from public reviews.
SteadyGantt is on the Marketplace here: https://marketplace.atlassian.com/apps/55985132 — free for teams of 10 or fewer. The live demo runs the full app in your browser with sample data.
Happy to answer anything about the Forge setup, the canvas renderer, or the diff/undo design in the comments.