Introduction
What Cairn is, and the problem it solves.
The problem
Every tour tool breaks the same way. Someone renames a button, the tour keeps pointing at a selector that no longer exists, and nobody finds out until a customer sees a spotlight over empty space. The industry calls it onboarding rot.
The usual answers — AI element fingerprinting, self-healing selectors — all try to repair the damage after it ships. The best case is that a user never notices.
How Cairn differs
Tours are typed data in your repository, anchors are verified in CI, and a broken tour fails the build before it reaches anyone.
✗ cairn check failed
• 1 anchor(s) are registered but never applied to an element [anchors-applied]
- questions.save (breaks "create-questions") src/walkthrough/flows.ts:35
Spread {...anchor(...)} on the element, or remove the anchor and the step pointing at it.Three layers of defence
- TypeScript — a typo in an anchor, flow id or event name will not compile.
cairn check— an element deleted from source fails CI in about a second, naming the tour it breaks and the line to open.- Browser audit — an anchor that exists in source but never renders, because of a feature flag or an empty state, fails a Playwright run.
Each catches something the others cannot. Together they mean a tour cannot silently stop working.
Where to go next
- Installation — Packages, provider, and your first tour.
- Next.js — App Router, Pages Router, and SSR notes.
- React — Vite, react-router, TanStack, or no router at all.
- Anchors — Marking elements, and why not CSS selectors.
- Flows and steps — Tours as data, and the five advance rules.