Light the way.
Leave the door open.

The spotlight you can click through. A product tour that cuts a hole in the overlay, so your users work the real thing underneath.

npm install @annetaan/leko

Scroll, and follow the light

01 · Why another tour

Every other tour puts glass over the button.

A highlight is usually a transparent layer. It looks like the button is right there, but the click lands on the layer. So a tour can only point and say “click here”, and the user watches.

Save

A layer the click hits the glass

A hole the click hits the button

02 · Signals

A step ends when something really happened.

Steps never advance on clicks. Your app says what finished, and the step waiting for it moves on. A step that waits has no next button, because that would be a way past the work it asks for.

The story

const checkout = {
id: 'checkout',
steps: [
{ id: 'cart', target: '#cart', message: 'Your cart.' },
{
id: 'pay',
target: { elements: '#pay', interactive: true },
message: 'Pay for real. The tour waits.',
awaits: 'order-saved',
},
],
} satisfies LekoStory

Your app, where the order really saved

await api.saveOrder(cart)
leko.reached('order-saved')

03 · Typed signals

Typos are caught before anyone runs the tour.

@annetaan/leko-codegen collects every signal your app reports with reached() and turns them into a type. A step can only wait for one of them, so a misspelt signal is a compile error, not a tour that waits forever.

{ id: 'pay', awaits: 'ordr-saved' }

TS2322Type "ordr-saved" is not assignable to type "order-saved" | "profile-filled".

04 · Yours to shape

Styled with CSS. Shipped with nothing else.

Every colour, radius and shadow is a CSS custom property, so the tour looks like your app. And Leko has no runtime dependencies at all.

Your stylesheet

:root {
--leko-scrim-color: #000a;
--leko-halo-outline: 2px solid gold;
--leko-message-radius: 12px;
}

0

runtime dependencies

One more thing

The light you followed down this page is Leko, too.

Leko Scroll is a spotlight for a long page. No story, no steps, nothing to click: the light moves as the reader scrolls, and the page underneath stays fully usable. It ships in the same package.

Get started with Leko Scroll

This page, more or less

import { createScroll } from '@annetaan/leko/scroll'
createScroll({
targets: [
{ target: '#why-copy' },
{ target: '#why', message: { title: 'A layer, or a hole' } },
{ target: '#signals-copy' },
{ target: '#signals', message: { title: 'No click listener' } },
],
})

Now try it for real.

The playground runs a Leko tour over a real page. Type, click, and watch it wait for you.