npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

inochi-avatar

v1.0.1

Published

Simple, drop-in library for animating Inochi2D models in the browser

Readme

Inochi2D Fox Girl Demo

A complete WebAssembly-based Inochi2D runtime for the browser, featuring random animation and interactive controls.

Inochi2D Logo

Features

  • ✨ Full Inochi2D .inp model support in the browser
  • 🎭 Random animation with realistic head movement and blinking
  • 🖱️ Mouse-tracking in idle mode
  • 🎨 WebGL2 rendering with stencil masking support
  • 🎯 Interactive controls (zoom, pan, animation modes)
  • 📊 Real-time FPS counter
  • 🦊 Optimized WASM binary (~500KB)

Prerequisites

  1. Rust toolchain (stable)

    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
  2. WASM target

    rustup target add wasm32-unknown-unknown
  3. Trunk (WASM bundler)

    cargo install trunk

Setup

1. Get an Inochi2D Model

You need a fox girl model in .inp format. Here's how to get one:

Option A: Download Pre-made Models

  1. Visit Inochi Session Demo Models
  2. Download a model pack (they come as .inx files)
  3. Download Inochi Creator
  4. Open the .inx file in Inochi Creator
  5. Export as .inp puppet: File → Export → Puppet (.inp)

Option B: Use the Official Test Model

# Clone the Inox2D repo to get test assets
git clone --depth 1 https://github.com/Inochi2D/inox2d.git temp-inox2d
cp temp-inox2d/examples/render-webgl/assets/puppet.inp model/fox_girl.inp
rm -rf temp-inox2d

Option C: Create Your Own

2. Place the Model

Copy your .inp file to:

inochi-fox-demo/model/fox_girl.inp

The file MUST be named fox_girl.inp or update the fetch path in index.html line 207.

Building & Running

Development Mode (with hot reload)

trunk serve --open

This will:

  • Compile Rust to WASM
  • Bundle all assets
  • Start a dev server at http://127.0.0.1:8080
  • Open your browser automatically
  • Watch for file changes and hot-reload

Production Build

trunk build --release

Output goes to dist/ folder. Deploy this to any static hosting:

# Example: Python HTTP server
cd dist
python3 -m http.server 8080

# Example: Deploy to GitHub Pages, Netlify, Vercel, etc.
# Just upload the dist/ folder

Usage

Controls

  • Random Animation - Randomized head movement and blinking
  • Idle Pose - Subtle breathing, mouse-tracking head movement
  • Zoom In/Out - Adjust camera scale
  • Reset Camera - Return to default view

Mouse Interaction (Idle Mode)

In idle mode, move your mouse over the canvas to make the character follow your cursor!

Customizing Animation

Edit the animation parameters in index.html:

// In updateRandomAnimation() function
targetYaw = (Math.random() - 0.5) * 1.2;  // Horizontal head range
targetPitch = (Math.random() - 0.5) * 0.8; // Vertical head range
blinkTimer = 2 + Math.random() * 4;        // Blink frequency

Available Parameter Names

The exact parameter names depend on your model's rigging. Common ones:

  • Head:: Yaw-Pitch - 2D head rotation
  • Eye::Blink - Eye closure
  • Body:: Yaw - Body rotation
  • Eye:: Look - Eye direction

Check the browser console on load to see all available parameters for your specific model.

Architecture

┌─────────────────────────────────────┐
│   JavaScript (index.html)           │
│   - Animation logic                 │
│   - User interaction                │
│   - requestAnimationFrame loop      │
└──────────────┬──────────────────────┘
               │ wasm-bindgen FFI
┌──────────────▼──────────────────────┐
│   Rust WASM (lib.rs)                │
│   - InoxModel wrapper               │
│   - Parameter API                   │
│   - Frame lifecycle management      │
└──────────────┬──────────────────────┘
               │
┌──────────────▼──────────────────────┐
│   Inox2D Core (inox2d crate)        │
│   - INP parsing                     │
│   - Parameter system                │
│   - Physics simulation              │
│   - Mesh deformation                │
└──────────────┬──────────────────────┘
               │
┌──────────────▼──────────────────────┐
│   Inox2D OpenGL (inox2d-opengl)     │
│   - Renderer via glow               │
│   - WebGL2 context                  │
│   - Shader management               │
└─────────────────────────────────────┘

File Structure

inochi-fox-demo/
├── Cargo.toml              # Rust dependencies
├── .cargo/
│   └── config.toml         # WASM target config
├── src/
│   └── lib.rs              # Rust WASM bindings
├── index.html              # HTML + embedded JavaScript
├── model/
│   └── fox_girl.inp        # Your Inochi2D model (YOU PROVIDE THIS)
├── dist/                   # Build output (generated)
│   ├── index.html
│   ├── inochi-fox-demo.js
│   └── inochi-fox-demo_bg.wasm
└── README.md               # This file

Troubleshooting

"Failed to load model: 404"

  • Make sure model/fox_girl.inp exists
  • Check the browser console for the exact path being fetched
  • If using a different filename, update index.html line 207

"Failed to get WebGL2 context"

  • Your browser doesn't support WebGL2
  • Try Chrome, Firefox, or Safari (recent versions)
  • Check WebGL2 support

Black canvas / No rendering

  • Check browser console for errors
  • The model might not have the expected parameter names
  • Try a different model

Parameters don't work

  • Different models have different parameter names
  • Check the "Available Parameters" section in the UI
  • Update the animation code to match your model's parameters

Build fails

  • Run cargo clean then try again
  • Make sure you have the WASM target: rustup target add wasm32-unknown-unknown
  • Update Rust: rustup update

Performance

Typical performance on a modern browser:

  • Load time: 1-2 seconds (including model parsing)
  • WASM size: ~500KB (release build)
  • FPS: 60fps on most devices
  • Frame time: 5-10ms (depends on model complexity)

API Reference

Rust (InoxModel)

// Constructor
InoxModel::new(bytes: &[u8], canvas_id: &str) -> Result<InoxModel, JsValue>

// Parameters
set_parameter(name: &str, value: f32) -> Result<(), JsValue>
set_parameter_2d(name: &str, x: f32, y: f32) -> Result<(), JsValue>
get_parameter_names() -> Vec<JsValue>

// Frame lifecycle
begin_frame()
end_frame(delta_time: f32)
draw()

// Camera
set_camera_scale(scale: f32)
set_camera_position(x: f32, y: f32)
resize(width: u32, height: u32)

// Metadata
get_name() -> String
get_author() -> String

JavaScript

import init, { InoxModel } from './inochi-fox-demo.js';

await init(); // Initialize WASM

const bytes = new Uint8Array(await (await fetch('model.inp')).arrayBuffer());
const model = new InoxModel(bytes, 'canvas-id');

// Animation loop
function animate() {
    model.begin_frame();
    model.set_parameter_2d('Head:: Yaw-Pitch', x, y);
    model.end_frame(deltaTime);
    model.draw();
    requestAnimationFrame(animate);
}

License

This demo code is provided as-is for educational purposes.

The Inox2D library is licensed under BSD-2-Clause.

Resources

Credits

  • Inox2D: Rust implementation by the Inochi2D team
  • Inochi2D: Original D implementation by Luna the Foxgirl
  • Built with ❤️ using Rust and WebAssembly