Skip to content
mascot-integrator logo

Mascot Integrator

mascot-integrator

You are an expert in integrating the emotive-mascot engine into various applications, frameworks, and use cases.

SKILL.md

Full skill instructions

Mascot Integrator

You are an expert in integrating the emotive-mascot engine into various applications, frameworks, and use cases.

When to Use This Skill

  • Adding mascot to a new use case or page
  • Setting up mascot in different frameworks (React, Vue, Svelte, vanilla JS)
  • Creating custom interaction patterns
  • Configuring mascot for specific contexts
  • Implementing LLM-driven emotion responses
  • Troubleshooting integration issues

Quick Start Patterns

Vanilla JavaScript

<!DOCTYPE html>
<html>
    <head>
        <script src="https://unpkg.com/​@joshtol/​emotive-engine@latest"></​script>
    </​head>
    <body>
        <canvas id="mascot-canvas"></​canvas>

        <script>
            const mascot = new EmotiveMascot({
              containerId: 'mascot-canvas',
              width: 400,
              height: 400,
              initialEmotion: 'calm'
            })

            await mascot.initialize()
            await mascot.transitionTo('joy')
        </​script>
    </​body>
</​html>

React (Next.js App Router)

'use client';

import { useEffect, useRef, useState } from 'react';

export default function MascotDemo() {
    const canvasRef = useRef<HTMLCanvasElement>(null);
    const mascotRef = useRef<any>(null);
    const [isClient, setIsClient] = useState(false);

    useEffect(() => {
        setIsClient(true);
    }, []);

    useEffect(() => {
        if (!isClient || !canvasRef.current) return;

        const initMascot = async () => {
            const { EmotiveMascot } = await import('@joshtol/​emotive-engine');

            mascotRef.current = new EmotiveMascot({
                canvas: canvasRef.current,
                width: 400,
                height: 400,
                initialEmotion: 'calm',
                enableGazeTracking: true,
            });

            await mascotRef.current.initialize();
        };

        initMascot();

        return () => {
            mascotRef.current?.destroy();
        };
    }, [isClient]);

    const handleEmotionChange = async (emotion: string) => {
        await mascotRef.current?.transitionTo(emotion, { duration: 1000 });
    };

    if (!isClient) return null;

    return (
        <div>
            <canvas ref={canvasRef} />
            <button onClick={() => handleEmotionChange('joy')}>Joy</​button>
            <button onClick={() => handleEmotionChange('excitement')}>
                Excitement
            </​button>
        </​div>
    );
}

Vue 3

<template>
    <div>
        <canvas ref="mascotCanvas"></​canvas>
        <button @click="changeEmotion('joy')">Joy</​button>
    </​div>
</​template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue';

const mascotCanvas = ref(null);
let mascot = null;

onMounted(async () => {
    const { EmotiveMascot } = await import('@joshtol/​emotive-engine');

    mascot = new EmotiveMascot({
        canvas: mascotCanvas.value,
        width: 400,
        height: 400,
        initialEmotion: 'calm',
    });

    await mascot.initialize();
});

onUnmounted(() => {
    mascot?.destroy();
});

const changeEmotion = async emotion => {
    await mascot?.transitionTo(emotion);
};
</​script>

Use Case Patterns

1. Retail Checkout Assistant

Context: Shopping cart, payment processing, item scanning Emotions: calm → anticipation (scanning) → joy (success) → concern (error)

const mascot = new EmotiveMascot({
    containerId: 'checkout-mascot',
    initialEmotion: 'calm',
    enableGazeTracking: true,
    scrollReactive: false, // Fixed position at checkout
});

// Item scanned successfully
async function onItemScanned() {
    await mascot.playPerformance('itemScanned', {
        steps: [
            { emotion: 'anticipation', duration: 300 },
            { emotion: 'joy', duration: 800, gesture: 'bounce' },
        ],
    });
}

// Payment processing
async function onPaymentProcessing() {
    await mascot.transitionTo('anticipation', { duration: 500 });
    // Show loading state
}

// Payment success
async function onPaymentSuccess() {
    await mascot.playPerformance('celebration');
}

// Error occurred
async function onError(errorType) {
    await mascot.transitionTo('concern', { duration: 800 });
}

2. Smart Home Dashboard

Context: Device control, status monitoring, voice commands Emotions: calm → focus (listening) → joy (command success)

const mascot = new EmotiveMascot({
    containerId: 'smarthome-mascot',
    initialEmotion: 'calm',
    enableGazeTracking: true,
    scrollReactive: true,
    audioEnabled: true, // Enable audio feedback
});

// Voice command started
async function onVoiceStart() {
    await mascot.transitionTo('focus', { duration: 400 });
}

// Command recognized
async function onCommandRecognized(command) {
    await mascot.transitionTo('anticipation', { duration: 300 });
}

// Device controlled successfully
async function onDeviceControlled(device) {
    await mascot.playPerformance('success', {
        steps: [
            { emotion: 'joy', duration: 600, gesture: 'pulse' },
            { emotion: 'calm', duration: 800 },
        ],
    });
}

3. Healthcare Patient Intake

Context: Form filling, health questions, appointment scheduling Emotions: calm → empathy → reassurance

const mascot = new EmotiveMascot({
    containerId: 'patient-mascot',
    initialEmotion: 'calm',
    enableGazeTracking: true,
    scrollReactive: false,
});

// Sensitive question
async function onSensitiveQuestion() {
    await mascot.transitionTo('empathy', { duration: 1000 });
}

// Form validation error
async function onValidationError() {
    await mascot.transitionTo('concern', { duration: 600 });
}

// Form submitted
async function onFormSubmitted() {
    await mascot.playPerformance('reassurance', {
        steps: [
            { emotion: 'gratitude', duration: 800 },
            { emotion: 'calm', duration: 600 },
        ],
    });
}

4. Education / Learning Platform

Context: Quiz, lessons, progress tracking Emotions: calm → encouragement → celebration (correct) → empathy (incorrect)

const mascot = new EmotiveMascot({
    containerId: 'learning-mascot',
    initialEmotion: 'calm',
    enableGazeTracking: true,
});

// Correct answer
async function onCorrectAnswer() {
    await mascot.playPerformance('celebration', {
        steps: [
            { emotion: 'joy', duration: 600, gesture: 'bounce' },
            { emotion: 'pride', duration: 800, gesture: 'shimmer' },
        ],
    });
}

// Incorrect answer
async function onIncorrectAnswer() {
    await mascot.playPerformance('encouragement', {
        steps: [
            { emotion: 'empathy', duration: 600 },
            { emotion: 'encouragement', duration: 800 },
        ],
    });
}

// Lesson completed
async function onLessonComplete() {
    await mascot.playPerformance('achievement');
}

LLM Integration Pattern

Connect mascot to Claude, GPT, or other LLMs for sentiment-driven emotions:

import { LLMEmotionPlugin } from '@joshtol/​emotive-engine';

const mascot = new EmotiveMascot({
    containerId: 'ai-mascot',
    initialEmotion: 'calm',
    plugins: [
        new LLMEmotionPlugin({
            provider: 'anthropic', // or 'openai'
            apiKey: process.env.ANTHROPIC_API_KEY,
            autoDetect: true, // Automatically detect sentiment
        }),
    ],
});

// Handle LLM response
async function onLLMResponse(message) {
    // Plugin automatically detects sentiment and transitions emotion
    await mascot.handleLLMMessage(message);
}

// Manual sentiment override
async function onUserMessage(message) {
    if (message.includes('error') || message.includes('problem')) {
        await mascot.transitionTo('concern', { duration: 800 });
    } else if (message.includes('thank') || message.includes('great')) {
        await mascot.transitionTo('gratitude', { duration: 600 });
    }
}

Configuration Options

Essential Options

{
  // Container (choose one)
  containerId: 'my-canvas',     // ID of canvas element
  canvas: canvasElement,        // Direct canvas reference

  // Dimensions
  width: 400,                   // Canvas width
  height: 400,                  // Canvas height

  // Initial state
  initialEmotion: 'calm',       // Starting emotion

  // Interactivity
  enableGazeTracking: true,     // Follow mouse/​touch
  scrollReactive: true,         // React to page scroll
  clickReactive: true,          // React to clicks

  // Performance
  targetFPS: 60,                // Target frame rate
  pixelRatio: window.devicePixelRatio,  // Display quality

  // Features
  audioEnabled: false,          // Audio synthesis
  plugins: []                   // Additional plugins
}

Advanced Options

{
  // Accessibility
  ariaLabel: 'Interactive mascot',
  reducedMotion: false,         // Respect prefers-reduced-motion

  // Debug
  debug: false,                 // Show FPS and debug info

  // Custom behaviors
  onEmotionChange: (emotion) => {
    console.log('Emotion changed to:', emotion)
  },

  onGestureComplete: (gesture) => {
    console.log('Gesture completed:', gesture)
  },

  onPerformanceComplete: (performance) => {
    console.log('Performance completed:', performance)
  }
}

Common Integration Patterns

Fixed Position Mascot

#mascot-canvas {
    position: fixed;
    bottom: 20px;
    right: 20px;
    z-index: 1000;
    border-radius: 50%;
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);
}

Scroll-Reactive Hero Section

const mascot = new EmotiveMascot({
    containerId: 'hero-mascot',
    scrollReactive: true,
    scrollConfig: {
        minScroll: 0,
        maxScroll: 1000,
        emotionSequence: [
            { scrollY: 0, emotion: 'calm' },
            { scrollY: 300, emotion: 'curiosity' },
            { scrollY: 600, emotion: 'excitement' },
            { scrollY: 1000, emotion: 'joy' },
        ],
    },
});

Mobile Responsive

const isMobile = window.innerWidth < 768;

const mascot = new EmotiveMascot({
    containerId: 'mascot',
    width: isMobile ? 300 : 500,
    height: isMobile ? 300 : 500,
    targetFPS: isMobile ? 30 : 60, // Lower FPS on mobile
    enableGazeTracking: !isMobile, // Disable on mobile for performance
});

Troubleshooting

Mascot not rendering

  • Verify canvas element exists in DOM
  • Check canvas has width/​height (not 0x0)
  • Ensure initialize() is called after construction
  • Check browser console for errors

Performance issues

  • Reduce particle count in emotion configs
  • Lower targetFPS to 30
  • Disable gaze tracking on mobile
  • Check for other animation conflicts

Emotions not changing

  • Verify emotion name exists in emotion config
  • Check transition is awaited (async)
  • Ensure previous transition completed
  • Check for JavaScript errors blocking execution

Framework-specific issues

React: Canvas disappears on re-render

  • Use useRef for canvas element
  • Don't recreate mascot on every render
  • Clean up with destroy() in cleanup function

Vue: Mascot not initializing

  • Use onMounted hook
  • Check canvas ref is properly bound
  • Use nextTick() if needed

Next.js: SSR errors

  • Use 'use client' directive
  • Check for window before initializing
  • Use dynamic imports for mascot library

Key Files

  • Core Engine: src/​core/​EmotiveMascot.js
  • LLM Plugin: src/​plugins/​LLMEmotionPlugin.js
  • Gaze Tracking: src/​core/​GazeTrackingEngine.js
  • Scroll Reactive: src/​core/​ScrollReactiveEngine.js
  • Example Use Cases: site/​src/​app/​use-cases/

Testing Integration

// Test basic initialization
const mascot = new EmotiveMascot({ containerId: 'test-canvas' });
await mascot.initialize();
console.assert(mascot.isInitialized, 'Mascot should be initialized');

// Test emotion transition
await mascot.transitionTo('joy');
console.assert(mascot.currentEmotion === 'joy', 'Should transition to joy');

// Test gesture
await mascot.playGesture('wave');
console.assert(mascot.isGesturePlaying, 'Gesture should be playing');

// Clean up
mascot.destroy();

Resources

More skills from majiayu000

xiaohongshu logo
majiayu000/claude-arsenal

xiaohongshu

xiaohongshu

286 148
View
agent-task-conductor logo
majiayu000/claude-skill-registry

agent-task-conductor

Conduct multi-agent task orchestration and workflow coordination.

663 1
View
conductor-setup logo
majiayu000/claude-skill-registry

conductor-setup

Initialize project with Conductor artifacts (product definition,

663 1
View
animation-designer logo
majiayu000/claude-skill-registry

animation-designer

Expert in web animations, transitions, and motion design using Framer Motion and CSS

663 1
View
diagramming logo
majiayu000/claude-skill-registry

diagramming

Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...

663 1
View
h3-pg logo
majiayu000/claude-skill-registry-data

h3-pg

PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.

23 1
View
conductor-development logo
majiayu000/claude-skill-registry

conductor-development

Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...

663 1
View
conductor-status logo
majiayu000/claude-skill-registry

conductor-status

Display project status, active tracks, and next actions

663 1
View
dockerization logo
majiayu000/claude-skill-registry

dockerization

Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.

663 1
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View