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

spice-html5-react

v0.1.1

Published

React + TypeScript SPICE protocol client component library

Downloads

172

Readme

spice-html5-react

A React + TypeScript client library for the SPICE remote desktop protocol. Connects to SPICE servers over WebSocket (via websockify) and renders the remote display in a browser.

Features

  • Drop-in <SpiceDisplay> React component with full connection lifecycle management
  • Low-level useSpice hook for custom UI and fine-grained control
  • Keyboard, mouse, and scroll input forwarding
  • Clipboard sharing between host and guest
  • File transfer via drag-and-drop
  • Audio playback (Opus codec)
  • Dynamic guest display resizing
  • SPICE ticket (RSA) authentication
  • SSR-safe (guards against document/WebSocket in server environments)
  • Ships as ESM, CJS, and TypeScript declarations

Requirements

  • React 18+
  • A running SPICE server (e.g. QEMU with -spice flag)
  • A WebSocket proxy such as websockify bridging WebSocket traffic to the SPICE server's TCP port

Installation

npm install spice-html5-react

Peer dependencies: react and react-dom (>= 18.0.0).

Quick Start

<SpiceDisplay> Component

The simplest way to embed a SPICE session:

import { useRef } from 'react';
import { SpiceDisplay } from 'spice-html5-react';
import type { SpiceDisplayHandle } from 'spice-html5-react';

function RemoteDesktop() {
    const displayRef = useRef<SpiceDisplayHandle>(null);

    return (
        <SpiceDisplay
            ref={displayRef}
            connection={{
                host: "localhost",
                port: 5959,
                password: "secret",
            }}
            display={{ fitContainer: true }}
            features={{
                enableKeyboard: true,
                enableMouse: true,
                enableClipboard: true,
                enableFileTransfer: true,
            }}
            onConnect={() => console.log("connected")}
            onDisconnect={() => console.log("disconnected")}
            onError={(e) => console.error(e)}
            onResize={(w, h) => console.log(`${w}x${h}`)}
            style={{ width: "100%", height: 600 }}
        />
    );
}

The imperative handle exposes sendCtrlAltDel(), disconnect(), reconnect(), and getConnection().

useSpice Hook

For full control over the connection lifecycle and input events:

import { useEffect, useRef } from 'react';
import { useSpice } from 'spice-html5-react';

function CustomDisplay() {
    const containerRef = useRef<HTMLDivElement>(null);
    const { status, resolution, controls } = useSpice({
        canvasRef: containerRef,
        callbacks: {
            onConnect: () => console.log("connected"),
            onError: (e) => console.error(e),
        },
    });

    useEffect(() => {
        controls.connect({ uri: "ws://localhost:5959", password: "secret" });
        return () => controls.disconnect();
    }, [controls]);

    return (
        <div>
            <p>Status: {status}</p>
            {resolution && <p>Resolution: {resolution.width}x{resolution.height}</p>}
            <div ref={containerRef} style={{ width: "100%", height: 600 }} />
            <button onClick={() => controls.sendCtrlAltDel()}>Ctrl+Alt+Del</button>
        </div>
    );
}

The hook returns reactive status, error, resolution, and surfaces state, plus a controls object with methods for input, clipboard, resolution changes, and connection management.

SPICE Server Setup

  1. Start a SPICE-enabled VM (example using QEMU):
qemu-system-x86_64 \
    -spice port=5900,disable-ticketing=on \
    -drive file=disk.qcow2,format=qcow2
  1. Start websockify to proxy WebSocket connections to the SPICE TCP port:
websockify 5959 localhost:5900
  1. Point the client at ws://localhost:5959.

Development

# Install dependencies
npm install

# Dev server
npm run dev

# Type-check (no emit)
npm run typecheck

# Build library (ESM + CJS + .d.ts)
npm run build

# Run tests
npm run test

Example App

A full working example lives in the example/ directory. It demonstrates how to integrate <SpiceDisplay> into a React application with a connection form, status indicator, error handling, and imperative controls.

What It Shows

  • Embedding <SpiceDisplay> with grouped props (connection, display, features)
  • Using a ref to access the imperative handle (sendCtrlAltDel, disconnect, reconnect)
  • Handling lifecycle callbacks (onConnect, onDisconnect, onError, onResize)
  • Conditionally mounting/unmounting the display based on user actions
  • Resilient error handling that keeps the component mounted on transient errors

Running the Example

The example links to the parent library via "file:..", so you need to build the library first:

# From the repository root
npm install
npm run build

# Then start the example
cd example
npm install
npm run dev

The Vite dev server starts at http://localhost:3000. Enter the host and port matching your websockify proxy (defaults to localhost:5959), optionally a password, and click Connect.

Example Structure

example/
  index.html          # HTML entry point
  package.json        # Dependencies (links to parent library via file:..)
  tsconfig.json       # TypeScript config
  vite.config.ts      # Vite dev server config
  src/
    main.tsx          # React root mount
    App.tsx           # Main app — connection form, SpiceDisplay, controls

App.tsx is the main file to look at. It wires up connection form state, mounts <SpiceDisplay> on connect, and exposes Disconnect, Reconnect, and Ctrl+Alt+Del buttons through the imperative ref.

API Reference

<SpiceDisplay> Props

| Prop | Type | Description | |------|------|-------------| | connection | SpiceConnectionProps | Host, port, password, scheme, path | | display | SpiceDisplayOptions | scale, resize, fitContainer | | features | SpiceFeatureToggles | Toggle keyboard, mouse, clipboard, file transfer, audio | | audio | SpiceAudioProps | volume (0-1), muted | | onConnect | () => void | Fired when the SPICE connection is established | | onDisconnect | () => void | Fired when the connection is closed | | onError | (error: Error) => void | Fired on connection errors | | onResize | (width, height) => void | Fired when the display resolution changes | | onClipboard | (text: string) => void | Fired when clipboard text is received from the guest | | onFileTransferProgress | (taskId, bytes, total, filename) => void | File transfer progress | | onFileTransferComplete | (taskId, filename, error?) => void | File transfer completion | | className | string | CSS class for the outer container | | style | CSSProperties | Inline styles for the outer container |

SpiceDisplayHandle (imperative ref)

| Method | Description | |--------|-------------| | sendCtrlAltDel() | Send Ctrl+Alt+Delete to the guest | | disconnect() | Close the SPICE connection | | reconnect() | Reconnect using current props | | getConnection() | Get the underlying SpiceMainConn instance |

useSpice Return Value

| Field | Type | Description | |-------|------|-------------| | status | "disconnected" \| "connecting" \| "connected" \| "error" | Current connection status | | error | Error \| null | Last connection error | | resolution | { width, height } \| null | Current display resolution | | surfaces | number | Number of active display surfaces | | controls | SpiceControls | Methods: connect, disconnect, sendKeyDown, sendKeyUp, sendMouseMove, sendMouseButton, sendClipboard, setResolution, sendCtrlAltDel, getConnection |

Project Structure

src/
  index.ts                 # Package entry point / barrel export
  components/
    SpiceDisplay.tsx        # Drop-in React component
  hooks/
    useSpice.ts             # Low-level React hook
  protocol/                 # SPICE protocol implementation
    spiceconn.ts            # Base WebSocket connection
    main.ts                 # Main channel, agent, clipboard
    display.ts              # Display rendering (canvas 2D)
    inputs.ts               # Keyboard and mouse input
    cursor.ts               # Cursor rendering
    playback.ts             # Audio playback (Opus/WebM)
    port.ts                 # Port channel
    enums.ts                # Protocol constants
    spicemsg.ts             # Message serialization
    spicetype.ts            # SPICE data types
    wire.ts                 # Binary framing / wire reader
    ticket.ts               # RSA ticket authentication
    quic.ts, lz.ts          # Image decompression
    bitmap.ts, png.ts       # Image format conversion
    webm.ts                 # WebM container for VP8
    resize.ts               # Guest screen resizing
    filexfer.ts             # File transfer (drag-and-drop)
    simulatecursor.ts       # Software cursor
  utils/
    debug.ts                # Debug flags and utilities
    atKeynames.ts           # AT keyboard scancode names
    codeToScancode.ts       # KeyboardEvent.code to scancode map