Scheduling product · Jalali calendar
GanttChart
A Persian project scheduling experience where dates, RTL rendering, and timeline geometry must agree. A production bug cluster revealed that independently calculating headers, task bars, and drag positions caused visible alignment drift.
Origin and motivation
GanttChart began with a practical local need: create project schedules using Persian and Jalali dates as a native planning experience, rather than treating the calendar as a formatting layer over a Gregorian-only timeline. The product has expanded into a broader web experience with project organization, tools, templates, and subscription/payment infrastructure; individual features and entitlement boundaries continue to evolve.
The engineering problem
In an RTL chart, a task bar, a month header, a dependency connector, and a drag operation must agree about the same date-to-coordinate mapping. Fixed assumed month widths (for example, 30 days) and separate origin calculations create cumulative offsets. Dragging and resizing become especially fragile when the pointer’s pixel delta is converted to dates using a different scale than the one used to render the grid.
Canonical timeline geometry
The refactor introduced a shared geometry module in frontend/src/components/gantt/timelineGeometry.js. It defines one timeline origin at the first period boundary and one uniform pixel-per-calendar-day scale for each zoom. Columns use the actual inclusive duration of each Jalali period; Jalali months may contain 29, 30, or 31 days, and quarter groups are aligned to Jalali months.
All render and interaction consumers use the same mapping: dateToPosition and positionToDate are inverse operations; task bounds, columns, grid alignment, drag, and resize share that origin and scale. In RTL, the origin is measured from the right edge, so later dates progress left. This replaces multiple locally plausible but globally inconsistent coordinate calculations.
Validation and evidence
The timeline repair report records 18 geometry unit tests and browser checks in Chromium and Firefox across day, week, month, and quarter zooms. The later release report records 18/18 browser assertions per browser and 21/21 full-stack API assertions for selected workflows, including task persistence, dependency types, critical path, baseline comparison, and premium enforcement. The release report also records a frontend-only production deployment and smoke checks.
Coverage boundaries matter: the earlier report notes that its first browser pass did not pixel-assert the dependency SVG path or drag-selection; the later release report says those assertions were added and passed. The production payment callback was checked for reachability, not a real transaction. Public-facing test-account screenshots are intentionally excluded.
Product decisions and learning
Supporting a calendar deeply affects the model, not just labels. Date conversion boundaries, period lengths, RTL origin, scrolling, hit-testing, drag/resize inversion, and zoom behavior need a single coordinate contract. The product site and codebase also show free public tools, templates, import/export paths, and paid capabilities; SEO or market claims are not presented as verified growth metrics here.
Current limitations
- This audit did not independently verify today’s live production assets or current analytics.
- Release reports document selected smoke checks; they do not certify every browser/device combination or all scheduling cases.
- Some interactions can be proven at DOM geometry level without proving pixel-perfect rendering across all font and device conditions.
- Commercial conversion, revenue, and adoption are not claimed.
Role and contribution
I guided product direction and engineering priorities around making Persian scheduling a first-class product behavior. The timeline repair is a strong example of reducing a UI defect family to one mathematical model, then applying that model consistently across rendering and interaction code.
Discuss calendar-aware scheduling