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

wff-web

v0.1.1

Published

Web preview renderer for WearOS Watch Face Format (WFF) v4 XML

Readme

wff-web

Render WearOS Watch Face Format (WFF) v4 XML in the browser using HTML Canvas.

Install

npm install wff-web

Usage

import { renderWatchFace } from "wff-web";

const canvas = document.createElement("canvas");
document.body.appendChild(canvas);

const xml = `<WatchFace width="450" height="450" clipShape="CIRCLE">
  <Scene backgroundColor="#1a1a2e">
    <AnalogClock centerX="225" centerY="225">
      <HourHand resource="hour.png" x="0" y="0" width="450" height="450"
        pivotX="0.5" pivotY="0.5" />
      <MinuteHand resource="minute.png" x="0" y="0" width="450" height="450"
        pivotX="0.5" pivotY="0.5" />
    </AnalogClock>
  </Scene>
</WatchFace>`;

const { metadata } = await renderWatchFace(canvas, { xml });

With assets

Pass image assets as a Map<string, ArrayBuffer>. Keys match the resource attribute paths in the XML.

const assets = new Map();
assets.set("hour.png", await fetch("/hands/hour.png").then(r => r.arrayBuffer()));
assets.set("minute.png", await fetch("/hands/minute.png").then(r => r.arrayBuffer()));

await renderWatchFace(canvas, { xml, assets });

Setting the time

By default the renderer uses the current time. Pass a Date to render a specific moment:

await renderWatchFace(canvas, {
  xml,
  time: new Date("2024-06-15T10:10:30"),
});

Ambient mode

Render the always-on display variant:

await renderWatchFace(canvas, { xml, ambient: true });

Animation

Start a live animation loop that updates every frame:

const { stop } = await renderWatchFace(canvas, {
  xml,
  assets,
  animate: true,
});

// Later, stop the loop:
stop();

Custom dimensions

Override the dimensions declared in the XML:

await renderWatchFace(canvas, { xml, width: 300, height: 300 });

User configuration

Watch faces can declare user-customizable options (colors, lists, booleans). Override their defaults:

await renderWatchFace(canvas, {
  xml,
  configuration: {
    theme_color: "1",      // ColorConfiguration option id
    show_seconds: "TRUE",  // BooleanConfiguration
    dial_style: "2",       // ListConfiguration option id
  },
});

API

renderWatchFace(canvas, options): Promise<RenderResult>

Renders a WFF XML watch face onto the provided HTMLCanvasElement.

RenderOptions

| Option | Type | Default | Description | |---|---|---|---| | xml | string | required | WFF v4 XML document | | assets | Map<string, ArrayBuffer> | new Map() | Image assets keyed by resource path | | width | number | from XML | Canvas width in pixels | | height | number | from XML | Canvas height in pixels | | time | Date | new Date() | Time to render | | ambient | boolean | false | Render in ambient (always-on) mode | | configuration | Record<string, string \| number \| boolean> | {} | User configuration overrides | | animate | boolean | false | Start a requestAnimationFrame loop |

RenderResult

| Field | Type | Description | |---|---|---| | metadata | Map<string, string> | Metadata from the XML (e.g. CLOCK_TYPE, PREVIEW_TIME) | | stop | () => void \| undefined | Stops the animation loop (only present when animate: true) |

Supported elements

Shapes: Arc, Ellipse, Line, Rectangle, RoundRectangle Layout: Group, Part, PartDraw Text: PartText, TimeText, Font Clock: AnalogClock, HourHand, MinuteHand, SecondHand, DigitalClock Images: PartImage Conditions: Condition, Compare, Default Styling: Fill, Stroke, LinearGradient, RadialGradient, SweepGradient Animation: Transform, Gyro, Variant Masking: Mask with blend modes

License

ISC