# Driver.js: a 5kb overlay library for tours, popovers and focus shifting

> Driver.js is a dependency-free TypeScript library that dims the page and highlights one element at a time. It fits when you want an overlay primitive you control, and not when you want a full onboarding platform.

**nilbuild/driver.js** — A lightweight, dependency-free JavaScript library for guiding user focus across the page.

- Repository: https://github.com/nilbuild/driver.js
- Website: https://driverjs.com
- Stars: 26,853 · Forks: 1,204
- Language: TypeScript
- License: MIT
- Published: 2026-09-21 · Updated: 2026-09-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/nilbuild-driver-js

## What Driver.js actually does, and who ends up using it

The README frames Driver.js as more than a tour library, and that framing is the honest description of the project. Tours are one use case. The underlying capability is an overlay that dims the rest of the page and cuts a hole around one element, with a popover attached to it. The README lists the other cases it is meant for: highlighting a component while a user interacts with it, contextual help such as a popover over a dimmed background while a form is filled in, a focus shifter that pulls attention to one part of the page, a turn-off-the-lights effect for video players, and a plain modal.

That list tells you who the library is for. It is for front-end engineers who need this overlay behaviour inside an application they already own, and who do not want a second rendering framework in the bundle to get it. The README states the library has no external dependencies and is written in Vanilla TypeScript, so it does not assume React, Vue, Angular or Svelte underneath. The repository topics point the same way: overlay, popover, spotlight, product-tour, user-onboarding, walkthrough.

The pitch on size is explicit. The README claims roughly 5kb gzipped and contrasts that with other libraries it says are 12kb or more gzipped. Treat that as the project's own claim rather than a measured result; the README does not say which libraries were measured or how. What is verifiable is the absence of dependencies, which is the part that usually matters more than the raw number once a bundler has done its work.

## The mechanism: one highlighted element, hooks around the transitions

Driver.js does not render your application. It highlights elements that already exist in the DOM. The README says it can highlight any element on the page, and that the library gives you hooks to manipulate elements as they are highlighted, about to be highlighted, or deselected. That three-part lifecycle is the core of the API surface: you get a callback before a step becomes active, while it is active, and when it is being torn down. Anything you need to do to the page around a step, such as opening a collapsed panel or scrolling a container, has to happen in those callbacks, because the library only knows about the element you pointed it at.

The overlay itself is the visual contract. One element is in focus, everything else is dimmed. The README describes this as a focus shifter and as a spotlight, and the repository topics use the same words. The popover is optional in the sense that the library is also usable as a simple modal, but the popover attached to a highlighted element is the shape most people mean when they say product tour.

Keyboard control is called out as a feature: the README says everything is controllable by keyboard. That matters for the contextual-help and modal use cases more than for a marketing tour, because a dimmed page with no keyboard escape is a trap. The README does not document the specific key bindings, so check the documentation site for the current set before you rely on them.

The architecture in the repository is a pnpm workspace driven by Turborepo. The library itself lives under the packages directory, the playground and documentation live under apps, and the root package.json is a private monorepo manifest rather than the published package. If you are filing an issue or reading source, that layout is where to look first.

## Installing Driver.js and running a first tour

The published package is `driver.js` on npm, and the README links to its npm and jsDelivr pages. The README itself does not give an install command, so the package name is the only thing to take from it: install `driver.js` with whichever package manager your project uses.

After that, the library is imported and driven from your own code. The README points to driverjs.com for demos and documentation rather than reproducing an example inline, and it does not list option names or a CSS path. The safest first step is the documentation site, then a minimal tour of your own: import the library, create an instance, and define steps that each name an element selector and the popover content for it. When that runs, the page dims, the first matched element is cut out of the dim layer, and the popover appears next to it. Advancing moves the highlight to the next selector. The README does not describe what happens when a selector matches nothing, so verify that case before shipping a tour that depends on an element which may not be rendered yet.

If you want to work on the library itself rather than consume it, the README documents the local setup. The playground is an Astro app that imports the library straight from source, so edits hot-reload.

```bash
pnpm install
pnpm run playground:install
pnpm dev
```

Examples live one per file under `playground/src/examples/` and appear in the sidebar; adding one means dropping an entry into the relevant group file (`highlight.ts`, `popover.ts`, `tour.ts`, `api.ts`). `pnpm build` and `pnpm test` are the other scripts the README lists. Note that the root `test` script delegates to `pnpm --dir packages/driver test`, so the tests belong to the package, not the workspace root.

## Where Driver.js stops being the right tool

The library is an overlay, not an onboarding system. Everything that makes a tour survive contact with real users sits outside it. There is no persistence of which steps a user has already seen, no targeting by user segment, no analytics on completion or drop-off, and no authoring interface. If your requirement is "show this tour once per account, resume it if the user leaves halfway, and report completion rates to the growth team", you are building all of that yourself on top of the hooks. The README's own framing supports this reading: it presents the library as something you use however you want, which is a statement about flexibility, not about batteries included.

The second boundary is the DOM. Highlighting works on elements that exist and are visible. A step that points at a node inside a collapsed accordion, a virtualised list row that has been recycled, or a route that has not mounted yet has nothing to highlight. The README does not document a fallback for a missing element, so the sequencing work falls to your callbacks. That is a real cost, and it is the reason tours built with overlay libraries tend to break quietly after a redesign.

The third boundary is maintenance. The last push to the repository was on 2026-07-18, which is recent, and the repository is not archived. Releases are frequent: 1.6.0 on 2026-06-25, 1.7.0 on 2026-07-13, and 1.8.0 on 2026-07-17. That cadence is good news for fixes and less good news for stability, because three minor releases in under a month means the surface is still moving. The README does not document a deprecation policy or a migration guide between minors, so pinning a version and reading the release notes before bumping is the practical stance.

## Driver.js against Shepherd, Intro.js and React Joyride

The alternatives people search for alongside this project are Shepherd, Intro.js and React Joyride, and the meaningful difference is the same in all three cases: framework coupling and feature scope.

React Joyride is a React component. You compose the tour into your React tree, pass steps as props or as a callback, and the library participates in React's rendering and state. That is convenient if your application is React and the tour is part of the same component hierarchy. It is a poor fit if you are not on React, or if you want to trigger a tour from outside the component tree, such as from a plain JavaScript module or a support widget. Driver.js has no framework binding to fight because it has none at all; the cost is that you wire the lifecycle yourself.

Shepherd takes the opposite structural approach to Driver.js. It is built around a tour object with steps, and it exposes an event system and a set of primitives for attaching content and actions to each step, closer to a small framework for tours than to a bare overlay. If your problem is specifically "build a multi-step tour with rich step content and event handling", Shepherd gives you more of that structure out of the box. If your problem is "dim the page and cut a hole around this one element, and let me decide everything else", the extra structure is overhead.

Intro.js is the closest in spirit and the most commonly compared. It also dims the page and walks a user through highlighted elements. The difference the README draws is size and dependencies: it states Driver.js is about 5kb gzipped with no external dependencies, and contrasts that with libraries it describes as 12kb or more. Intro.js is also the one of the three with the most visible commercial framing around licensing, so check the licence terms of whichever you pick rather than assuming they match. Driver.js is MIT, which the README states plainly.

## Licence and the cost of keeping up

Driver.js is MIT licensed, credited in the README to Kamran Ahmed, and the README describes it as free for personal and commercial use. The repository contains a `license` file at the top level. MIT is permissive, so the usual obligations apply: keep the copyright notice and the licence text with any distribution. That is a description of the licence, not legal advice; if your organisation has a policy on bundled front-end dependencies, run it through that process.

The upgrade cost is the more interesting question. The project ships minors quickly and the README does not describe a deprecation window or a migration path between them. The README carries no changelog beyond the release list, and no compatibility statement. In practice that means every bump is a small review: read the release notes for the version you are moving to, check whether the option names and hook signatures you depend on are still present, and re-run your own tour definitions. The library is small enough that this is minutes of work rather than days, but it is not zero, and it is the reason to pin the version in `package.json` rather than floating on a caret range if tours are on a critical path such as a paid onboarding flow.

For contributors, the workspace is Turborepo with pnpm, and the release script in the root `package.json` runs `pnpm --dir packages/driver release` with a GitHub token from `gh auth token`. That is the maintainer path, not something a consumer needs.

## Conclusion

Adopt Driver.js if you want a small overlay primitive you drive from your own code and you are willing to write the step sequencing, state persistence and analytics yourself. Do not adopt it if you expect a hosted onboarding platform, a React component tree, or a documented migration path between minor versions. Before committing, check the driverjs.com documentation for the option and hook names that match the version you install, and read the release notes for 1.8.0 to see what changed since the version your bundler resolves by default.

## FAQ

### Is Driver.js free?

Yes. The README states the project is MIT licensed and free for personal and commercial use, and the repository contains a license file at the top level.

### How do I use Driver.js in a page?

Import the library, create an instance, and pass a steps array where each step names an element selector and the popover content for it. The README points to driverjs.com for the demos and the full option list rather than reproducing an example inline.

### What is Driver.js?

It is a dependency-free TypeScript library for guiding user focus across a page. The README describes it as an overlay for highlighting elements, with product tours as one use case among popovers, focus shifters, modal-style overlays and feature introductions.

### How does Driver.js compare with React Joyride?

React Joyride is a React component that participates in your component tree, while Driver.js is written in Vanilla TypeScript with no framework binding. If your app is not React, or you need to trigger the overlay from outside a component tree, Driver.js does not require a binding to work around.

### How does Driver.js compare with Shepherd?

Shepherd is built around a tour object with steps plus an event system and primitives for step content and actions, which is more structure than Driver.js provides. Driver.js gives you the overlay and hooks for the highlight lifecycle and leaves the rest of the tour logic to your own code.

### How does Driver.js compare with Intro.js?

Both dim the page and walk a user through highlighted elements. The README draws the difference on size and dependencies, stating Driver.js is about 5kb gzipped with no external dependencies while other libraries are 12kb or more.

## Sources

- [License: MIT](https://github.com/nilbuild/driver.js/blob/master/LICENSE)
- [nilbuild/driver.js on GitHub](https://github.com/nilbuild/driver.js)
- [Project website](https://driverjs.com)
- [README](https://github.com/nilbuild/driver.js/blob/master/README.md)
- [Releases](https://github.com/nilbuild/driver.js/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/nilbuild-driver-js
