Skip to the cat guide
oneko
Browse the cat guide

ONEKO / DOCUMENTATION

A little guide
for little paws

A pixel cat, at home in your React app. Install it, pick a coat, and make its little habits your own.

Oneko is a shadcn registry component for React. The installer copies the component, hooks, animation engine, 12 bundled skins, and skin credits into your project. You own the code. Start from a React project with shadcn configured and a working import alias.

Install Oneko
npx shadcn@latest add https://oneko.dhrv.pw/r/oneko.json

Mount one cat near the root of your app. It attaches its sprite and bubble to document.body; it does not take up layout space. For a browser-only React app, import Oneko and render it directly.

Browser-only React
import Oneko from "@/components/oneko";

export default function CatLayer() {
  return <Oneko meow={false} />;
}

In Next.js App Router, put the no-SSR dynamic import inside a client component. Render this wrapper from your layout. This also ensures the default starting position is computed in the browser.

components/cat-layer.tsx
"use client";

import dynamic from "next/dynamic";

const Oneko = dynamic(() => import("@/components/oneko"), { ssr: false });

export default function CatLayer() {
  return <Oneko meow={false} />;
}
Inside your existing app/layout.tsx
import CatLayer from "@/components/cat-layer";

// Keep your existing layout, providers, and metadata.
// Add this once inside <body>, alongside your app content:
<CatLayer />

All props are optional. These are component defaults; the playground starts with sound off and its own cat thought. The engine runs at 10fps, so 10 active frames is about one second. Hidden tabs and paused cats do not advance those timers.

Most props update live. initialPos is mount-only; changing persistPosition, storageKey, zIndex, or the liveStateRef object restarts the animation DOM. Suggested playground ranges are guidance, not automatic clamps unless explicitly stated below.

Coat & appearance

skin
OnekoSkinDefault "classic"

One of the 12 bundled pixel-art coats. Changing coats keeps the current animation running.

scale
numberDefault 1

Scale of the cat and its bubble. Use a positive value; the playground offers 0.5–3.

opacity
numberDefault 1

Sprite opacity, from 0 to 1. Does not change bubble opacity.

hueRotate
numberDefault 0

Coat hue rotation in degrees. The playground offers 0–360.

rotationAmount
numberDefault 15

Maximum movement tilt in degrees. Set 0 for upright paws.

Paws & play

paused
booleanDefault false

Freeze movement, activity, and bubble timers without unmounting. Existing sounds may finish. Resume from the same state.

followCursor
booleanDefault true

Follow the cursor or touch destination and visit favorites. False stops chasing and zoomies while allowing grooming, bubbles, and naps.

sleepEnabled
booleanDefault true

Allow sleepy idle animations and naps. False wakes an existing or restored nap on the next active tick.

speed
numberDefault 10

Movement speed per animation tick, with easing. Use a positive value; the playground offers 1–30.

followDistance
numberDefault 20

Distance in CSS pixels at which the cat stops chasing. Use a positive value; the playground offers 10–200.

idleThreshold
numberDefault 1000

Rest time in milliseconds before idle activities become eligible. The cat chooses an activity rather than napping immediately.

animationSpeed
numberDefault 1

Idle animation pace multiplier. Use a positive value; the playground offers 0.5–2. Does not change the 10fps engine tick.

freerunChance
numberDefault 0.06

Probability, from 0 to 1, of starting zoomies on an eligible chasing tick. Set 0 to disable spontaneous zoomies.

freerunDuration
numberDefault 40

Zoomies duration in active frames. At 10fps, 40 frames is about 4 seconds.

laserPointer
booleanDefault false

Replace the system cursor with a pixel laser toy. Hidden while paused or when followCursor is false. The toy takes priority over favorites.

Bubbles

bubbleEnabled
booleanDefault true

Enable the cat’s speech bubbles.

bubblePlacement
"auto" | "above" | "below"Default "auto"

Preferred side for thoughts. Auto prefers above and flips below near the top. Placement is constrained to the viewport when the bubble fits.

bubbleScale
numberDefault 1

Extra bubble size multiplier on top of scale. Clamped to 0.5–2; non-finite values fall back to 1.

bubbleText
stringDefault ""

Custom text for awake idle activities. Sleeping always uses sleepy cat thoughts. The playground limits this to 120 characters.

bubbleChance
numberDefault 0.5

Chattiness factor, from 0 to 1. Idle and moving states use different trigger rates; this is not a direct per-frame probability.

bubbleDisplayFrames
numberDefault 180

Regular bubble display duration in active frames: about 18 seconds by default. Zoomies use their own duration.

bubbleCooldown
numberDefault 120

Quiet frames between regular bubbles: about 12 seconds by default.

Sounds

meow
booleanDefault true

Allow optional cat audio. Set false if you have not added sound files. The hosted playground starts with sound off.

volume
numberDefault 0.5

Volume for newly played sounds, from 0 to 1.

soundBasePath
stringDefault "/cat-sounds"

Local or absolute directory URL for the optional .ogg files. Trailing slashes are removed. Keep the original filenames.

Home & integration

persistPosition
booleanDefault true

Restore saved position/activity on mount and save before page unload. False disables both storage reads and writes.

storageKey
stringDefault "oneko"

localStorage key for saved position. Use a distinct key for independent saved positions. Changing it remounts the animation DOM and reads the new key.

initialPos
{ x: number; y: number }Default viewport center

Initial cat center in viewport CSS pixels. Mount-only; an existing saved position takes precedence. Disable persistence for a deterministic starting spot.

zIndex
numberDefault 2147483646

Layer for the cat and its overlays. Set a lower value to place site UI above it. Changing this remounts the animation DOM.

zones
readonly OnekoZone[]Default []

Keep-out areas and favorite spots, using CSS selectors or viewport rectangles. HTML data-oneko-zone attributes work alongside these definitions.

zoneAttractionChance
numberDefault 0.3

Chance to visit a favorite at each five-second check. Clamped to 0–1. Set 0 to skip visits; non-finite values use 0.3.

zoneAttractionDuration
numberDefault 4000

Visit duration in milliseconds, including travel. Rounded to 100ms ticks and clamped to 100–60000. Non-finite values use 4000.

onStateChange
(state: CatActivityState) => voidDefault undefined

Called when activity changes. Use it for React UI that displays the cat’s current activity.

liveStateRef
{ current: CatLiveState }Default undefined

An initialized mutable ref updated each active frame. Ref writes do not trigger React renders. Keep the ref identity stable to avoid remounting.

Choose classic, black, gray, calico, tora, catppuccin, ghost, silver, spirit, valentine, maia, or vaporwave. All skins ship with the registry; there is no separate image download. They use the original pixel art without smoothing.

A calico companion
<Oneko skin="calico" scale={1.5} rotationAmount={0} meow={false} />

The installer includes docs/oneko-skins.md with artwork provenance. Code is MIT; preserve the artwork credits and review the skin-specific notes when redistributing.

Meet the cat artists
A quiet companion
<Oneko
  followCursor={false}
  sleepEnabled
  freerunChance={0}
  meow={false}
  persistPosition={false}
  initialPos={{ x: 80, y: 120 }}
/>
  • paused freezes the current activity; it does not make the cat sleep. Use paused={isDialogOpen} with your existing dialog state to pause while a dialog is open.
  • followCursor={false} keeps the cat resting in one spot, with grooming, bubbles, and optional naps. Keep-out zones can still relocate it to safety. Re-enabling follows the latest pointer position.
  • sleepEnabled={false} wakes a sleeping cat on the next active tick. If paused, it wakes after resuming.
  • The laser toy is hidden while paused or when cursor-follow is disabled. While active, it takes priority over favorite spots.
  • On touch screens, a tap on non-interactive space gives the cat a destination. Taps on buttons, links, and form controls are ignored.
Bubble comforts
<Oneko
  meow={false}
  bubbleText="Dreaming of treats…"
  bubblePlacement="above"
  bubbleScale={1.2}
  bubbleDisplayFrames={60}
  bubbleCooldown={100}
/>

bubbleScale multiplies the bubble’s inherited scale without changing the cat. Auto placement prefers above and flips below near the top. Bubbles are kept inside the viewport when they fit; an oversized bubble is centered horizontally. Keep-out zones constrain the cat, not its bubble.

Custom text is used for awake idle activities. Sleeping always uses sleepy thoughts. Keep your copy cat-themed. bubbleChance controls regular chatter; zoomies have their own thoughts and timing.

Bubble styling reads --background, --foreground, and --border from your theme. It uses --font-geist-pixel-square when available, otherwise monospace. Geist Pixel is optional; the component does not require this site’s fonts.

Mark real page elements as keep-out areas or favorite spots. These attributes work without a zones prop and follow visible elements as the page moves.

Element zones
<section data-oneko-zone="avoid">
  {/* Your checkout or other UI that needs room. */}
</section>
<div data-oneko-zone="attract">A cozy cat bed</div>
<Oneko meow={false} />
Typed zones
import Oneko, { type OnekoZone } from "@/components/oneko";

const zones: OnekoZone[] = [
  { id: "checkout", type: "avoid", selector: "#checkout", padding: 12 },
  { id: "bed", type: "attract", selector: ".cat-bed" },
  {
    id: "corner", type: "avoid",
    rect: { left: 0, top: 0, right: 160, bottom: 100 },
  },
];

export function CatLayer() {
  return (
    <Oneko zones={zones} zoneAttractionChance={0.3}
      zoneAttractionDuration={4000} meow={false} />
  );
}
  • OnekoZone has id, type (avoid or attract), and either selector or rect. A selector takes precedence and includes all matching visible elements. Use distinct IDs for separate definitions.
  • Rectangles use viewport CSS pixels with left, top, right, and bottom. Optional padding adds extra space around avoid zones. Invalid selectors and empty rectangles are ignored.
  • Avoid zones protect the entire scaled, tilting cat, even during zoomies. A new zone around the cat moves it to the nearest safe spot. If no room remains, the cat hides until space returns.
  • Favorites are checked every five seconds. A visit includes travel time, followed by an eight-second break after it ends. Offscreen favorites and favorites inside keep-out areas are skipped.
  • Zones are sampled at the 10fps tick. Keep-out boundaries take priority; paused cats do not reconcile moving zones until resumed.

The registry does not include audio files. Keep meow={false} for a silent install, or copy public/cat-sounds/ from the source repository into your app’s public assets, preserving the .ogg filenames. Browsers may require user interaction before audio can play.

Your cat’s sound directory
<Oneko meow volume={0.3} soundBasePath="/assets/cat-sounds" />

soundBasePath also accepts an absolute directory URL. Mute and volume apply to future playback; sounds already playing can finish. Sleeping audio uses the purr pool.

Find the cat sound files
A saved spot for this site
<Oneko storageKey="my-site:cat" persistPosition meow={false} />

Position and idle activity are restored from localStorage on mount and saved before page unload. Storage failures are ignored. A saved spot takes precedence over initialPos. Use persistPosition={false} for a predictable starting position or when saving is unwanted.

The component does not save its configuration props. The hosted playground separately remembers its controls under oneko:playground:v1. Copy your cat in the instantly available install panel exports your selected configuration. Open customization and install panels keep the cat outside; zone sample spots sit below the controls.

Activity in React
"use client";

import { useState } from "react";
import Oneko, { type CatActivityState } from "@/components/oneko";

export function CatActivity() {
  const [activity, setActivity] = useState<CatActivityState>("idle");
  return (
    <>
      <Oneko meow={false} onStateChange={setActivity} />
      <p>Cat activity: {activity}</p>
    </>
  );
}

Activity values are idle, moving, sleeping, scratchSelf, tired, alert, scratchWallN, scratchWallS, scratchWallE, scratchWallW, and freerun. In a Next.js app, use the no-SSR wrapper pattern from installation for the Oneko import.

Optional live telemetry
import { useRef } from "react";
import type { CatLiveState } from "@/components/oneko";

// Inside your client component:
const liveStateRef = useRef<CatLiveState>({
  state: "idle", posX: 0, posY: 0, velMag: 0,
  idleTime: 0, distToMouse: 0, frameCount: 0,
  freerunActive: false, freerunTimer: 0, bubbleVisible: false,
  pathLength: 0, obstacleCount: 0,
});

// Pass liveStateRef={liveStateRef} to Oneko.
// Read liveStateRef.current when needed; writes do not rerender React.

CatLiveState exposes activity, position, speed, idle ticks, cursor distance, total ticks, zoomies status/time, bubble visibility, and nearby movement information. Public types OnekoProps, OnekoSkin, OnekoZone, CatActivityState, and CatLiveState are exported from @/components/oneko.

Copy this prompt into your coding agent with your project open. It points to the same documentation in Markdown, gives the exact install command, and asks the agent to adapt to your existing app.

Prompt for your coding agent
Add the Oneko pixel cat to this project using its shadcn registry component.

Read https://oneko.dhrv.pw/llms.txt, then https://oneko.dhrv.pw/docs.md for the full API and integration recipes. Fetch https://oneko.dhrv.pw/r/oneko.json if you need the exact installable source.

1. Inspect the framework, package manager, existing shadcn setup, import aliases, theme tokens, and client/server boundaries. Preserve unrelated changes.
2. Install with: npx shadcn@latest add https://oneko.dhrv.pw/r/oneko.json
3. Mount one Oneko instance in an appropriate client component. For Next.js App Router, use the documented dynamic import with ssr: false inside a client wrapper, then render that wrapper from the layout.
4. Start with meow={false} unless the sound assets are installed. Keep the built-in reduced-motion behavior, pixel art, and theme-token bubble styling. Keep cat thoughts cat-themed, and sleeping thoughts sleepy.
5. Use documented props to match this site. Put data-oneko-zone="avoid" on sensitive UI that needs space. Use initialPos with persistPosition={false} when a fixed starting spot is required. Do not add new settings unless needed.
6. Check desktop and touch behavior, light and dark themes, keyboard controls, and reduced motion. Run the project’s relevant lint, type, test, and build checks. Report the files changed, chosen props, and any missing sound assets.

Implement the integration in this project. Do not deploy or publish it.

Agents can read /llms.txt for discovery, /docs.md or /llms-full.txt for the complete guide, and /r/oneko.json for the installable source. These resources are public and need no login. The HTML guide is rendered on the server, so it is readable without JavaScript.

  • No cat? Check that it is mounted in the browser. Reduced motion is checked when the animation mounts; a matching preference skips the cat. Keep-out zones covering the whole viewport can also hide it.
  • Cat stays still? Check paused, followCursor, followDistance, and whether the tab is hidden. A resting cat may need the cursor moved farther away before it chases.
  • Starting spot ignored? A saved position overrides initialPos. Disable persistence or use a new storage key, then remount the component.
  • No purrs? Check meow, volume, the sound directory and filenames, and whether the page has received a user interaction. Sound files are not part of the registry download.
  • Cat covers a dialog? Lower zIndex or use paused with your dialog state. The cat is mounted on document.body, so a parent’s stacking context does not contain it.
  • Bubble font differs? Load Geist Pixel and expose --font-geist-pixel-square, or keep the monospace fallback. Define theme variables in both light and dark modes.