
When iRacing publishes a new season, the source is comprehensive—but it is still a PDF designed for reading, not querying.
I built GridSherpa to turn that document into answers such as:
- What can I race today?
- Which sessions start at a sensible time in my timezone?
- Which purchase unlocks the most weeks for the series I actually run?
- Which team events need another driver?
The 2026 Season 4 import currently contains 155 official series and 2,002 scheduled series-weeks. Getting there required more than extracting a table.
The PDF is a document, not an API
GridSherpa’s backend is TypeScript and Express. The import pipeline uses pdf-parse, then normalizes the extracted text into series and week records.
The first pass reads the table of contents to recover category, license group, and series order. A second pass locates each series body and parses its preamble and week blocks.
That sounds straightforward until layout becomes data.
Track names can wrap across physical lines. A hyphenated car name can be split in the middle of a word. Weather and rule text wrap differently depending on length. Some series change cars by week. Offseason documents label consecutive calendar days as “Week 1” through “Week 7.”
Each of those cases needs a narrow rule. A broad cleanup regex may make one row look better while silently corrupting another.
The most important distinction: simulation time is not start time
The schedule can contain an in-session simulated date and clock. That value must not be treated as UTC and converted into the driver’s timezone.
The published race cadence—such as “every two hours at :45”—is a separate concept.
GridSherpa stores the simulated clock without a timezone and derives actual event occurrences from the cadence. Keeping those concepts separate prevents a plausible-looking but incorrect local schedule.
Normalize first, trust later
The importer produces normalized JSON, but the runtime does not trust it simply because TypeScript generated it.
The loader validates:
- real ISO dates
- positive week numbers
- non-empty series and track names
- safe artwork filenames
- valid optional time multipliers
- duplicate series and week numbers
- bounded day spans for daily offseason rows
This matters because generated data can still be truncated, hand-edited, or copied from an incompatible release.
Make season changes transactional
A new schedule affects more than one file. The normalized schedule, artwork, and generated SEO pages need to describe the same release.
The import command supports a dry run. The production workflow stages and validates generated outputs before promotion, and one exclusive lock covers the full process so concurrent imports cannot interleave releases.
Schedule data changes only after a reviewed PDF import is promoted. GridSherpa deliberately does not pretend to be a live iRacing API.
Turn the normalized data into decisions
Once the schedule is structured, the useful product work begins:
- local-time Today and This Week views
- filters for category, license, car, track, weekday, and time
- season-over-season diffs
- track-use and buying analysis
- calendar subscriptions and reminders
- team-race share cards
For Season 4, the report shows 141 cars, 251 track configurations, and 17 rookie series. The global venue ranking is interesting, but it is not a buying recommendation: disciplines reuse tracks differently, so the useful answer appears only after filtering.
Explore the current Season 4 report.
View the GridSherpa source on GitHub.
If you have built an importer for a document that was never intended to be a database, I would be interested in the edge case that caused you the most trouble.
GridSherpa is an independent fan-built tool and is not affiliated with iRacing. The Season 4 figures measure scheduled use, not participation.
Top comments (0)