live demo — it's walking on this page right now

A 3D avatar that walks and talks over your website

Drop an animated character onto any site. It idles in the corner, follows the cursor, and greets your visitors — click it and it detaches into a full-page playground where your real DOM becomes the level. Powered by Three.js. Free and open source.

Install in 60 seconds ★ Star on GitHub
click the corner avatar → playground WASD/←→↑↓ move M stroll ⇄ platformer Esc exit

Try it right now

This page runs the real published package — @three-ws/walk straight off npm, avatars and animation clips streamed from the three.ws CDN. No build step, no screenshots, no video: the product is the demo.

Find your companionIt's idling in the corner of this page, watching your cursor.
Click itIt detaches into a full-page playground you steer with the keyboard or the on-screen d-pad.
Press MGravity on — these headings and cards become solid platforms. Land on a link to dive through it.
🕹 Launch playground (?walk=play)

Two ways to roam

One key (M) switches the movement model live, and the choice is remembered across pages.

Stroll

A gentle aerial wander

Top-down view, no gravity, nothing to fall off. Walk anywhere across the page; step onto a link and it opens like a doorway into the next page.

Platformer

Your DOM is the level

Headings, cards, buttons, and images become solid ground. Gravity, jumping, falling — land on a link to dive in. Every page you ship is a new level.

Install

From npm with a bundler, or straight into any static page with an import map — exactly how this page does it.

npm install @three-ws/walk three
import { createWalkCompanion } from "@three-ws/walk";

createWalkCompanion({
  // or host the GLBs + clip manifest yourself
  assetBase: "https://three.ws",
  manifestUrl: "https://three.ws/animations/manifest.json",
}).bootstrap();
<!-- no bundler? an import map is all you need -->
<script type="importmap">
{
  "imports": {
    "three": "https://cdn.jsdelivr.net/npm/three@0.184.0/build/three.module.js",
    "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.184.0/examples/jsm/",
    "@three-ws/walk": "https://cdn.jsdelivr.net/npm/@three-ws/walk@0.1.2/dist/index.mjs"
  }
}
</script>

Built like a product, not a gimmick

This is the engine behind the walking companion on three.ws — extracted, documented, and published for any site.

Never a T-pose

Humanoids with no animations get the shared clip library retargeted onto their skeleton — Mixamo, Ready Player Me, VRM, custom rigs. A rig that can't be driven falls back gracefully. Nothing ever freezes.

Built-in roster & picker

A dozen avatars out of the box — robots, humanoids, photoreal people, a fox. Add your own GLB with one roster entry. Visitors' choices persist across pages.

Lean & lazy

Side-effect free on import. Nothing mounts, renders, or fetches until you call enable(); the playground only initializes on first use. One shared WebGL context budget coordinates with other viewers on your page.

Accessible by default

Respects prefers-reduced-motion, fully keyboard-steerable, visible focus rings, ARIA-labelled controls.

URL controls

?walk=play deep-links straight into the playground; ?avatar=fox picks the guest. Great for sharing and QA.

Apache-2.0

Open source, no accounts, no keys. Host the assets yourself or point at the three.ws CDN (CORS is open).

Bring your own mascot

One roster entry turns any GLB into a walking brand character — the retargeting engine handles the animation.

import { createWalkCompanion, WALK_AVATARS } from "@three-ws/walk";

createWalkCompanion({
  avatars: [
    ...WALK_AVATARS,
    {
      id: "mascot",
      name: "Our Mascot",
      category: "Brand",
      asset: "/brand/mascot.glb",
      source: "static",
      rig: "shared", // retarget the shared clips onto it
      accent: "#ff0066",
    },
  ],
  defaultAvatarId: "mascot",
}).bootstrap();