Why Product Tours Should Live in Your Git Repo
Most product tour tools have the same problem: they charge per user, lock your content in their dashboard, and have no answer for what happens when your UI changes and the tour breaks. You find out the same way your users do.
Trailguide is a free open-source runtime where tours are JSON files that live in your repo. No per-user pricing. No vendor lock-in. You own the content forever.
This post is about what you actually get when your tours live alongside your code.
Tours are just JSON files in your repo
A Trailguide trail looks like this:
{
"id": "welcome",
"title": "Welcome Tour",
"version": "1.0.0",
"steps": [
{
"id": "step-1",
"target": "[data-trail-id='create-btn']",
"placement": "bottom",
"title": "Create your first project",
"content": "Click here to get started."
}
]
}
That file lives in your repo. It gets reviewed in PRs. It has a git history. You can roll it back, branch it, diff it. Everything your team already does with code applies to tours automatically — no new process, no new tools.
When a PM wants to update the copy on step three, the change goes through the same review flow as any other edit. When something breaks, git blame tells you when and why.
Recording a tour takes minutes, not days
The Pro Editor includes a Chrome extension recorder. Enter your app's URL, click Start Recording, and click through the flow you want to document. Every click captures three things automatically:
- The element's CSS selector, using the most stable attribute available (
data-trail-id,data-testid,aria-label, or a DOM path as a fallback) - A screenshot of the page at that moment
- The exact element rect, so the editor can highlight precisely what was targeted
Selectors are graded Stable, Moderate, or Fragile based on what they target. A data-trail-id attribute is Stable — it won't break when you restructure the DOM. A fragile path selector shows a warning and ranked suggestions to fix it in one click.
When your UI ships an update, you open the editor and see the screenshot from when the tour was recorded. The broken element is highlighted. Anyone on the team can spot what changed, update the selector, and push a fix — without filing an engineering ticket or involving a developer.
Two-way Git sync means tours live where your code lives
The Pro Editor connects to GitHub and GitLab. You can load any trail file from a repo, edit it in the dashboard, and push it back as a commit or open a PR for review. The dashboard is for editing. The repo is the source of truth.
This means your tours go through the same deploy process as everything else. A tour change that hasn't been reviewed doesn't go to production any more than a code change would.
Analytics without instrumentation
The runtime tracks completion rates, step-by-step drop-off, and time per step automatically. No events to wire up. No analytics SDK to configure. When a step is losing people, you see it in the dashboard.
Most teams discover that one step causes 60% of tour abandonment. Once you can see that, you fix it. Without data, you're guessing.
One trail, two purposes
Here's the part that feels like a bonus once you already have everything above.
Set a trail's mode to "both" and the same JSON that guides your users also runs as a Playwright test in CI. Add action and assert fields to steps where you want Playwright to verify something:
{
"id": "step-1",
"target": "[data-trail-id='create-btn']",
"placement": "bottom",
"title": "Create your first project",
"content": "Click here to get started.",
"action": "click",
"assert": { "type": "visible" }
}
Then write one test:
import { test } from '@playwright/test'
import { runTrail } from '@trailguide/playwright'
import welcomeTrail from './tours/welcome.json'
test('welcome tour', async ({ page }) => {
await page.goto(process.env.BASE_URL ?? 'http://localhost:3000')
await runTrail(page, welcomeTrail)
})
runTrail walks every step in order. If a selector is missing, an action fails, or an assertion is wrong, the test fails and the deploy is blocked. Steps without action or assert still run — Trailguide checks that the target element is present, which catches most selector regressions on its own.
You didn't write a test suite. You wrote a tour. The test is a side effect of having your onboarding in a format that CI can understand.
Most teams think of product tours and regression tests as two completely separate things — different tools, different formats, different maintenance burden. When tours are JSON files in your repo, that separation disappears. The content you wrote to teach users how to use your product is exactly what you need to verify it still works.
One file. Two jobs.
Getting started
The runtime is free and open source:
npm install @trailguide/core
The Pro Editor handles recording, Git sync (GitHub and GitLab), screenshot storage, selector quality grades, analytics, and the mode toggle — 14-day free trial, $49/month after. Every trail you create is a file in your repo that your team owns.
Visit gettrailguide.com
or
Source and full docs at github.com/hellotrailguide/trailguide.
Top comments (0)