Model or dataset
nilbuild/page-mascot avatar
nilbuild/page-mascot

page-mascot: An Animated Cursor-Tracking React Character for Web Pages

A mascot that watches the cursor and blinks when you poke it

825 stars81 forksPythonMIT

At a glance

What is it?
page-mascot is a React npm package that places an interactive sprite-sheet character on a page, having its gaze follow the cursor and displaying a reaction when clicked, with a companion AI agent skill for drawing new characters.
Who is it for?
page-mascot is appropriate for portfolio sites, game-adjacent web projects, and developer tools pages where a personality element is a deliberate design choice. The 52 pre-built characters on the demo page cover a range of styles.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 15 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What page-mascot Does and Who It Is For

page-mascot is a React component that renders an interactive sprite-based character on a page. The character tracks the user's mouse cursor and turns its head toward it in real time. When the user clicks on the character, it shows a reaction expression for half a second before returning to its tracking state.

The README describes the package homepage as koboyo.com/page-mascot, where 52 existing characters are available for preview and download. The component is designed for web pages that benefit from a personality element: portfolio sites, landing pages for developer tools, game-adjacent applications, or any context where an interactive character makes sense.

The package is built in TypeScript with Vite and published as an ES module. The peer dependency is React 18 or higher. It is not a general-purpose animation library; its only function is the mascot interaction pattern.

How the Two-Sheet Sprite Architecture Works

Each character in page-mascot is represented as two 3 by 3 sprite sheets: one sheet for head directions (nine cells) and one sheet for facial expressions and reactions (nine cells). The two sheets are the complete data model for a character.

At runtime, the component calculates the angle between the character's position and the current cursor position. That angle selects a cell from the directions sheet, showing the corresponding head orientation. A dead zone around the character's position prevents the head from jittering when the cursor is very close; the head settles and stops tracking at short distances.

A click triggers a cell from the reactions sheet, displayed for half a second. The reaction is a brief visual response, analogous to a blink or startled expression, after which the component returns to direction tracking.

Both sheets are standard images served by the page's static file server. The component references them via the `directions` and `reactions` props, which accept any URL or import path the app can serve. This means the images can live in the public/ folder, as imported assets processed by a bundler, or on a CDN.

The fixed 3 by 3 grid is a deliberate constraint. Nine direction cells cover the eight cardinal and intercardinal directions plus a forward-facing default. The uniformity of the grid is what allows the drawing skill to verify alignment automatically: if any cell in the directions sheet is misaligned with its neighbor, the character appears to jump position between frames, which the skill detects and rejects.

Installing and Using a Pre-Built Mascot

The package installs via npm:

bash
npm i page-mascot

To use a pre-built character, download its two sprite sheets from the demo page and place them in the app's public/mascots directory, then reference them in the component:

tsx
import { Mascot } from 'page-mascot'

<Mascot
  directions="/mascots/fox-directions.webp"
  reactions="/mascots/fox-reactions.webp"
/>

The full prop set is documented in the README. The `size` prop sets the display size in pixels, defaulting to 140. The `label` prop sets the accessible name for screen readers, defaulting to 'mascot'. The `className` prop passes through to the container for CSS customization.

The component's default positioning and display behavior are intentionally minimal; layout and placement relative to the rest of the page are left to the consuming application's CSS.

Drawing Custom Mascots with the Agent Skill

For characters not in the existing set of 52, page-mascot includes a Claude Code skill that generates new sprite sheets from a text description. Installing the skill:

bash
npx skills add nilbuild/page-mascot --skill page-mascot --global --yes

After installation, the agent handles the full pipeline from description to finished component. Examples from the README:

code
/page-mascot a chibi otter with chocolate-brown fur
/page-mascot make one that looks like me
/page-mascot a chibi fox, in the riso style

The skill draws all nine head directions and all nine expressions, assembles them into two aligned sheets, checks that the character does not jump visually between frames due to misalignment, and places the Mascot component on the page.

The README states that drawing requires an image generation tool. Codex has its own image generation capability built in. Claude Code uses the OpenAI Images API and requires the OPENAI_API_KEY environment variable:

bash
export OPENAI_API_KEY=sk-...

For users who do not want to use either agent environment, the README provides a link to the prompt files used for each drawing step, allowing manual generation in any chat UI that accepts image prompts.

Six drawing styles are documented: colour, ink, sketch, riso, paper, and pixel. The README notes that because the styles only change the rendering pass and not the underlying character geometry, the alignment between sheets holds across style variants of the same character.

Accessibility and Motion Considerations

The README documents two accessibility-relevant behaviors. First, cursor tracking switches off automatically when no fine pointer is present. This means the component does not track finger position on touchscreens, where the cursor is not persistent between gestures. The character simply sits in its default facing direction on touch devices.

Second, the click squash animation that provides the visual feedback on interaction respects the `prefers-reduced-motion` media query. On systems where the user has enabled reduced motion in their operating system settings, the squash animation is suppressed. The README does not specify exactly what the fallback behavior is; it only states that the animation honors the preference.

The `label` prop allows the character's accessible name to be set to something meaningful for screen reader users, which is a straightforward but important detail for any site that aims for accessibility compliance.

Limitations, Scope, and Comparison

The package is narrowly scoped to the specific mascot interaction pattern. It does not support animated idle cycles, movement across the page, collision with page elements, or any interactivity beyond the cursor-tracking direction change and the click reaction. Projects that need a character with more complex behaviors would need to build on top of the component or use a different approach entirely.

The component has no built-in dialog system, speech bubble, or tooltip. Any conversational or guiding behavior around the character must be implemented by the consuming application. The mascot is a visual element only.

The closest alternative for embedding animated interactive characters on a web page is Lottie, which plays JSON-encoded animations exported from tools like Adobe After Effects. Lottie supports full keyframe animation and is widely used for UI microanimations. The trade-off is that Lottie animations are static sequences: a Lottie character does not track the cursor or react to clicks as a programmatic state machine the way page-mascot does.

The package is at version 0.1.0, so the API should be treated as potentially unstable. The last push was on 2026-09-15, indicating the project is under current development. There are no GitHub releases listed, and the npm package version reflects the early-stage state of the project. Anyone building production integrations should pin the package version explicitly and test after upgrades, since the prop interface or sprite sheet format could change before a 1.0 release.

Editorial conclusion

page-mascot is appropriate for portfolio sites, game-adjacent web projects, and developer tools pages where a personality element is a deliberate design choice. The 52 pre-built characters on the demo page cover a range of styles. Projects that need a character not in that set require an OpenAI API key and either Claude Code or a Codex session to run the drawing skill; there is no manual sprite sheet creation tool bundled. React 18 is a hard prerequisite. The MIT licence under Kamran Ahmed's name is permissive, with no commercial restrictions beyond what the licence itself states.

Frequently asked questions

Does page-mascot work on mobile or touchscreen devices?

The README states that cursor tracking switches off without a fine pointer, so the character does not track touch input on mobile devices. On touchscreens it remains static in its default facing direction.

Can I create a custom page-mascot character without an AI agent?

Yes. The README provides a link to the prompt files used by the drawing skill, allowing manual generation in any image-generation chat UI. The two resulting sprite sheets can then be passed to the Mascot component via the directions and reactions props.

What React version does page-mascot require?

The package.json lists React 18 or higher as a peer dependency.

Official sources

  1. Issues
  2. License: MIT
  3. nilbuild/page-mascot on GitHub
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/nilbuild-page-mascot.svg)](https://hysenlabs.com/projects/nilbuild-page-mascot)