Live preview · Guide + Chat + AI (@ai handoff when a human guide joins)
Live co-browsing — instead of click-here tours

Stop telling them where to click.
Be on the page with them.

Register in admin, paste two lines of code. Co-browse, chat and AI on your site in minutes — no SDK, no iframe, no tour builder.

Create free account

Widget is live on this page — bottom-right corner

The thesis

From canned tooltip tours to open, live guidance

Static product tours are a guess about what each user might need. They break the moment your UI changes and can't adapt to what the visitor is actually looking at. Guidewell flips it: a real teammate joins the session, sees the same screen, and points with the cursor in real time — with an AI co-pilot that knows when to stay quiet.

The old way

Pre-recorded tooltip tours

"Click Save → then Settings → then this icon" — one fixed path, no eye-contact, no follow-up question.

Step 3 of 7
Click the Save button at the top-right to continue. Then we'll show you Settings.
  • Static, pre-recorded path
  • Breaks when the UI changes
  • One-way — you can't see them
  • Same script for everyone
With Guidewell

A real teammate (or three) — live on the same page

Shared cursors, click ripples, scroll & navigation in sync. When a human guide joins, AI goes on standby — summon it any time with @ai in chat. Solo visitors still get full AI guidance.

Anna · guide + visitor · AI standby
Anna · guide
visitor
QA · guide
AI · on @ai
  • Live, free-form pointing
  • Human + AI without talking over each other
  • @ai tag — explicit handoff in chat
  • Solo visitors: AI replies automatically
Live demo on this page

Open the widget. Invite someone. See it click.

Real install — not a mockup. The button in the corner runs co-browse, session chat, and AI with @ai handoff.

Bottom-right corner · ? for help

Join the session

Click the floating button, enter your name, pick visitor or guide. Saved locally — no form on return visits.

Guide tab Chat tab

Invite the room

Hit Copy invite link and open it in another tab, incognito, or send to teammates — everyone lands in the same session with their own cursor.

?session_id=… Multi-peer

Co-browse, chat & AI handoff

On Guide, point and scroll together. On Chat, reach your ops inbox. Solo? AI replies on its own. Human in the room? Type @ai to summon it — guides stay in control.

@ai AI standby Admin Chats
Capabilities

Everything you need for live co-browsing

Live co-browse, AI handoff, and operator chat — grouped by what your demo audience actually cares about. Every card maps to a real capability in the widget you can try on this page.

AI & chat

AI + human handoff

Solo visitors get proactive AI co-browse and automatic replies. When a guide joins, AI goes on standby — summon it with @ai in chat. No duplicate answers, no awkward overlap.

Live room

Shared cursors

Unique color per peer, 60 fps, viewport-normalized — see exactly where everyone points.

Live room

Click ripples

Tap anywhere — a wave fires for every peer. "Click this button" without a voice call.

Sync

Scroll sync

Normalized scroll ratio — different viewport sizes stay in lock-step, no echo loops.

Sync

Navigation sync

Classic loads and SPAs — we patch pushState so routes mirror instantly.

MPA SPA history API
Invite & rooms

Multi-peer rooms

N participants, no hard cap. Broadcast model — peers_snapshot on join, honest UI when someone leaves.

Invite & rooms

Frictionless invite

Name + role once, then copy the invite link — every tab auto-joins. No email, no signup wall.

?session_id=… autojoin=1 copy link
Ship

Lightweight

Vanilla JS, scoped styles, async load — won't block TTI.

Ship

WebSocket signaling

JWT-scoped per session. Peer snapshot on join — UI never lies.

Ship

Origin-aware

Sessions remember site_origin. Cross-origin filtered server-side.

Ship

Themeable

primaryColor, dark theme, custom FAB icon — brand in HTML.

Ops

Selective event log

Cursors & scroll stay in-memory. Meaningful events — clicks, navigations, custom actions — land in gw_analytics_events for admin replay.

AI & chat

Built-in chat

data-chat="session" for co-browse room chat · inbox for operator queue · both for Guide + Chat tabs. Dynamic @ai hint when a guide is present.

WebSocket chat Operator inbox @ai tag
Under the hood

Anatomy of a session

REST to bootstrap, WebSocket to stream, Postgres to remember. A pure broadcast room — N peers, no cap, no master/slave. Every signal fans out; only meaningful events hit the database.

1

REST: bootstrap & link

Bootstrap

POST /v1/sessions with X-Guidewell-Key creates a row scoped to project_id + owner_user_id — that's how admin shows only your sessions.

POST /v1/sessions → session_id, signal_token
POST …/participants → join as visitor | teacher
identity_jwt ?session_id=… autojoin=1
2

WebSocket: signal channel

Live

Each peer opens /v1/sessions/{id}/signal?token=…. Server adds them to an in-memory SignalRoom, sends peers_snapshot to the newcomer, then peer_join to everyone else.

peers_snapshot peer_join peer_leave
3

Broadcast: N peers, one room

Fan-out

Cursor, scroll, click ripples and nav sync — JSON from any peer, relayed to all others (sender excluded). No participant cap, no role hierarchy, no per-pair signaling.

cursor · scroll · click_wave · nav_change
{ v:1, pid, role, body }
60 fps cursor normalized 0…1 remote_click
4

AI standby & @ai tag

Handoff

Solo room → POST /v1/ai/respond on visitor messages + proactive nudges. Human teacher joins → AI waits until chat contains @ai. Guide messages never trigger AI unless tagged.

@ai ai_actions proactive nudge
5

Persist: only what matters

Postgres

Cursors & scroll stay in-memory — they'd drown Postgres at 60 fps. click_wave, nav_change and custom action events land in gw_analytics_events for admin replay.

gw_analytics_events gw_session_messages inbox threads
Integration

Two lines of HTML. That's the whole install.

Seven copy-ready paths — script tag, dynamic config, reverse proxy, React, Nuxt, URL invites, and a JavaScript API. Every snippet is generated per project in the admin console.

One script tag. Auto-mount.

Drop the snippet anywhere on your page. The bundle injects its own host element, scopes its styles, creates sessions on demand and tears itself down on unmount — no glue code, no virtual DOM runtime.

  • Two attributes do the work · data-api points at your backend, data-key binds the session to a project. Everything else has sensible defaults.
  • Brand it in HTML · add data-fab-icon (any inline SVG — paste from lucide.dev), data-fab-text, data-primary-color, data-theme="dark".
  • Or configure via JS · set window.GuidewellConfig = {…} before the script tag. Same options, useful when you build the config dynamically.
  • Text chat (opt-in) · add data-chat="session" for in-session messaging, data-chat="inbox" for a site-wide operator queue, or data-chat="both" for Guide + Chat tabs. Off by default.
  • AI handoff · enable with data-ai="true". Solo visitors get automatic replies; when a guide joins, type @ai in chat to summon the assistant.
  • Open it from anywhere · put data-guidewell-toggle on any button on your page, or call Guidewell.open() / .close() / .toggle() from your own JS. The two CTAs on this page use exactly that.
index.html
<!-- That's the entire install. Same-origin: no data-api needed. -->
<script src="/widget.js"></script>

<!-- Cross-origin? Point at your API host. The data-key links every session
     this widget creates to your project + owner row, so the admin console
     shows you only the sessions you actually own. -->
<script src="https://api-gw.screwglit.ch/widget.js"
        data-api="https://api-gw.screwglit.ch"
        data-key="prj_pk_…"
        data-chat="both"></script>
Default

Script tag — data attributes

One <script src="…/widget.js"> with data-api and data-key. Auto-mounts on load — the fastest path (~2 min after signup).

Dynamic

window.GuidewellConfig

Set config in JS before loading the script — same options as data attributes, useful when values come from your CMS or env at runtime.

Same-origin

Reverse proxy

Proxy /gw-api/* to the Guidewell API. Serve /gw-api/widget.js with data-api="/gw-api" — no CORS, no third-party script domain.

React

React / Next.js

Inject the script in useEffect with dataset.api and dataset.key. Call Guidewell.unmount() on cleanup for SPA route changes.

Nuxt

Nuxt 3 / 4 plugin

Client-only plugin that appends the widget script on app init — same pattern as React, fits Nuxt's plugin lifecycle out of the box.

Invites

URL parameters

Deep-link into a session: ?session_id=…&role=teacher&autojoin=1&name=Anna. Share the link — widget opens and joins automatically.

API

JavaScript API

After load: Guidewell.open(), .toggle(), .showGuideNudge(), .unmount(), .mount({…}). Bind with data-guidewell-toggle on any button — no glue code.

All snippets pre-filled with your API key in Admin → Projects → Embed Code · full reference in Widget docs

Admin console

A real control plane behind the widget

Guidewell ships with a Nuxt-based admin console for project owners and operators — manage projects, watch live sessions, run the API, handle billing & access. Production console: guidewell-admin.vercel.app.

Open admin console

Projects

Spin up a new project, get an API key, paste the embed snippet, lock to site_origin, tweak per-project widget defaults — all from the dashboard.

Sessions monitor

Every session you launched — scoped to your account via owner_user_id, filterable by project_id. Status, origin, mode, started/ended timestamps. Drill in to replay the persisted click / nav / action stream.

Billing

Per-project payments ledger with manual or provider-backed entries (Stripe/etc.), currency-aware, export-ready. Wire your own pricing on top.

Users & roles

Invite teammates, assign roles, review who has access to which projects. Admin-only view, JWT-backed, role-aware navigation in the sidebar.

Policies

RBAC primitives baked in: control which roles can manage projects, run sessions, see analytics or charge customers — Postgres rows, not config files.

API console & docs

Built-in OpenAPI playground — pick any endpoint, set path params and JSON body, fire it from the admin without touching curl. Live docs included.

Stack

Boring, batteries-included tech

No proprietary runtime, no vendor lock-in. Three deploy surfaces you already know — API on Fly, admin + landing on Vercel, Postgres via Supabase. Same repo, same migrations, same OpenAPI.

Backend & signaling

Fly.io

FastAPI

Async REST + WebSocket on one process. OpenAPI at /docs, widget at /widget.js.

Python 3.11+ Uvicorn JWT auth

WebSocket rooms

In-memory SignalRoom per session — cursor, scroll, nav, chat fan-out. peers_snapshot on join.

Broadcast Multi-peer

Docker

Single Dockerfile + compose for local dev. Prod image serves API + static widget bundle.

compose healthcheck

Data & auth

Supabase

Postgres

Sessions, participants, projects, inbox, AI runs — transactional, RLS-ready schema in supabase/migrations/.

14 migrations gw_* tables

Supabase Auth

Admin login via Supabase → POST /v1/app/auth/supabase → app JWT for /v1/app/*.

RLS-ready service role

AI guide storage

Per-project LLM config, guide programs, run logs — optional module behind GUIDEWELL_AI_ENABLED.

Ollama OpenRouter

Client surfaces

Vercel

Vanilla JS widget

IIFE embed — one <script> tag, scoped CSS, no React/Vue on customer sites.

~7 KB gzip Vite build

Nuxt 4 admin

Projects, sessions, inbox, AI guide, billing, API console — thin client to the same API.

shadcn i18n

Vite landing

This page — static HTML + GSAP, live widget embed, built with VITE_GUIDEWELL_API.

static nginx / Vercel
Production today
api-gw.screwglit.ch · Fly guidewell-admin.vercel.app guidewell.screwglit.ch Docker · Render · K8s — your call

Run it on your stack today

Spin up the backend, mount the widget, open the admin console. Everything you saw on this page is shipped in this repo — no SaaS sign-up required.