Tiny hedgehogs. Living on your website. Walking around, jumping off your buttons, occasionally wearing top hats.
A playful PixiJS-powered hedgehog game you can drop into any React app. Your DOM elements become the platforms — buttons, cards, headings, whatever you point a CSS selector at — and the hedgehogs do the rest. PostHog uses it as the in-product mascot. Now it can live on your site too.
▶ Try the playground · 🐛 Report a bug
pnpm add @posthog/hedgehog-mode
# or: npm install @posthog/hedgehog-mode
# or: yarn add @posthog/hedgehog-modeThe package ships sprite sheets in assets/. They need to be served from a public path your app can reach:
cp -R node_modules/@posthog/hedgehog-mode/assets public/assetsPop that into a postinstall or build script so it stays in sync. (See playground/package.json for an example — look for copy-assets.)
"use client";
import { HedgehogModeRenderer, HedgeHogMode } from "@posthog/hedgehog-mode";
import { useState } from "react";
export default function Page() {
const [game, setGame] = useState<HedgeHogMode | null>(null);
return (
<>
<main>{/* your actual website */}</main>
<HedgehogModeRenderer
config={{
assetsUrl: "/assets",
platforms: {
selector: ".border", // anything visible — buttons, cards, h1s
viewportPadding: { top: 50 },
},
}}
onGameReady={setGame}
/>
</>
);
}That's it. Refresh, and watch a hedgehog wander across your homepage.
💡 Tip: the
selectoris the secret. Point it at the elements you want hedgehogs to walk on.button, .card, h1is a fun starting point.
Five skins, ten colours, and a wardrobe of accessories ship out of the box.
| Skins | default · spiderhog · robohog · hogzilla · ghost |
| Colours | green · red · blue · purple · dark · light · greyscale · sepia · invert · rainbow |
| Accessories | top hats, glasses, capes, party gear — HedgehogActorAccessoryOptions has the full list |
A pre-built picker is included if you want users to dress their own hedgehog:
import { HedgehogCustomization } from "@posthog/hedgehog-mode";
<HedgehogCustomization game={game} config={config} setConfig={setConfig} />;For avatars, lists, or anywhere you don't need a full game loop, use StaticHedgehog:
import { StaticHedgehog } from "@posthog/hedgehog-mode";
<StaticHedgehog
options={{ id: "me", skin: "spiderhog", accessories: ["top-hat"] }}
size={64}
assetsUrl="/assets"
/>;Same skins, colours, and accessories — no physics, no animation, no fuss.
- React 18 or 19 (peer dependency)
- Next.js 14, 15, 16 — App Router or Pages
- The renderer is client-only, but importing from a server component is safe (it lazy-loads
react-shadow)
Next 16 ships its own vendored React canary. With Turbopack, that vendored react can get paired with your installed react-dom, and React 19 will throw Incompatible React versions. Two ways out:
-
Run with
--webpack(next dev --webpack,next build --webpack). -
Pin
react/react-domto the canary version Next ships, e.g. viapnpm.overrides:"pnpm": { "overrides": { "react": "19.3.0-canary-3f0b9e61-20260317", "react-dom": "19.3.0-canary-3f0b9e61-20260317" } }
Bump these whenever you upgrade Next. Check the version with
cat node_modules/next/dist/compiled/react/package.json | jq -r .version.
Want to add a skin, fix a bug, or just poke around?
pnpm install
pnpm dev # builds the lib in watch mode + runs the playground at http://localhost:8002
pnpm build # builds lib then playgroundRepo layout:
hedgehog-mode/— the published libraryplayground/— Next.js demo app (the easiest way to try changes)texturepacker/— sprite-sheet generation tooling
PRs welcome. Bonus points for new accessories.
MIT — go forth and hedgehog.