0.2.0

What is Borda?

Borda is an embeddable onboarding widget that guides users through your interface step by step. It renders a spotlight overlay around target elements, paired with a tooltip that displays a title, description, image, and navigation buttons — all configurable per step.

Borda works on any type of site — SaaS dashboards, landing pages, e-commerce stores, documentation portals — without requiring a specific framework. The widget mounts into any container or directly into document.body as a floating overlay.

Built with Svelte 5, Borda compiles down to vanilla JavaScript with no framework runtime. The output integrates into React, Vue, Angular, or plain HTML without dependency conflicts. Distribution formats include ES Module, UMD, and CommonJS.

Borda is a fully open-source, non-commercial project. It's built and maintained by a small team in their free time with the goal of helping developers build better projects. If you encounter bugs or rough edges — we'd appreciate your patience and a GitHub issue over frustration.

See it in action

The only required field is steps — an array of step definitions. Each step specifies a target element, a title, a description, and a placement for the tooltip. This tour runs on the page you're reading right now: every target below is a real heading or feature card further down, and each step uses a different placement to show the tooltip positioning itself around its target.

import { useBorda, ComponentPlacement } from '@retoo/borda';

import '@retoo/borda/styles';

const borda = useBorda();

const instance = await borda.mount({
  steps: [
    {
      target: '#page-header',
      title: 'Page header',
      description: 'Every page has a header with a title and description — Borda spotlights it as the starting point of the tour.',
      placement: ComponentPlacement.BOTTOM_CENTER,
    },
    {
      target: '#what-is-borda',
      title: 'What is Borda?',
      description: 'The first section heading on the page. Borda can target any element with a CSS selector.',
      placement: ComponentPlacement.BOTTOM_START,
    },
    {
      target: '#what-is-borda-description',
      title: 'Description',
      description: 'A paragraph of text right below the heading. The spotlight wraps around just this block.',
      placement: ComponentPlacement.BOTTOM_START,
    },
    {
      target: '#features',
      title: 'Features',
      description: 'The entire Features section wrapped in a single spotlight. One step can cover a large area.',
      placement: ComponentPlacement.MIDDLE_START,
    },
    {
      target: '#bundle-size',
      title: 'Bundle size',
      description: '~42 KB gzipped. Zero runtime dependencies.',
      placement: ComponentPlacement.TOP_START,
    },
    {
      target: '#bundle-callout',
      title: 'Full breakdown',
      description: 'Callouts, links, and inline elements are valid targets too.',
      placement: ComponentPlacement.TOP_CENTER,
    },
  ],
});
See the Basic Setup example for a complete onboarding flow with multiple steps.

Features

Guided tours
multi-step, lifecycle hooks
Define an ordered list of steps with per-step target elements, tooltips, images, and async preparation hooks.
Spotlight overlay
configurable cutout
Full-screen backdrop with a cutout around the target element. Configurable padding, border radius, and animation.
Tooltips
auto-placement, arrow, image
Positioned tooltips with title, description, image, and arrow. Auto-flips to stay in viewport.
Navigation
buttons + keyboard + swipe
Built-in prev/next/finish/skip buttons, keyboard navigation with ArrowRight, ArrowLeft, and Escape, and touch swipe gestures on the tooltip.
Skip feature
localStorage
"Don't show again" checkbox with persistent storage — the onboarding won't replay for returning users.
Highlight
single element spotlight
Spotlight a single element without a full tour using the highlight() shortcut.
Responsive
breakpoint overrides
Apply different component configs at different viewport widths via matchMedia breakpoints.
Runtime updates
mergeConfig / setConfig
Patch or replace the entire config without unmounting.

Bundle size

The production bundle weighs ~42 KB gzipped (JS + CSS combined). Zero runtime dependencies — nothing is loaded beyond the assets you provide.

Full breakdown by format in the Bundle Size reference.