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

@minit-games/sdk

v1.7.0

Published

Official SDK for building Minit Games HTML5 mini-games

Readme

@minit-games/sdk

Official SDK for building Minit Games HTML5 mini-games. Provides the game lifecycle API, configuration helpers, UI components (tutorial overlays, feedback text, flying rewards, header bars), and background utilities.

Install

npm install @minit-games/sdk

Usage

Core entry point

import { initializeSDK, getConfigValue, reportResult, loadingDone } from '@minit-games/sdk';

// Bootstrap the SDK at startup. Accepts an optional config for
// background and meta-tag injection (see API overview below).
initializeSDK();

// Read URL-param config (passed by the app). Returns a string (or
// undefined if the key is missing and no default is supplied) —
// coerce with Number(...) / parseInt(...) for numeric mods.
const difficulty = getConfigValue('difficulty', 'normal');

// Signal that assets are loaded and the game is ready to be shown.
// Until this is called, the Minit app keeps a loading state on top
// of the WebView — call it as soon as the first interactive frame
// is ready.
loadingDone();

// At game end, report the result. The Minit app immediately overlays
// its own result screen on top of the WebView, so the game loses
// focus — do NOT render an in-game "result submitted" confirmation,
// and stop driving updates after this call.
reportResult(1500, { flavorText: 'Great run!' });

Game lifecycle

The host (Minit app or web player) wraps the game in a controlled lifecycle. Three SDK calls drive it:

  • initializeSDK(config?) — call once at startup to bootstrap the SDK and set up backward-compat shims. Cheap and synchronous. The optional config arg can apply a background (config.background) and inject meta tags (config.metaTags: true).
  • loadingDone() — call once when the game is interactive (assets loaded, first frame ready). Until this fires, the app keeps a loading state on top of the WebView; the player sees the loader, not your game. Calling it more than once is a no-op.
  • reportResult(result, options?) — call once when the game ends. The host immediately overlays its own result screen, takes focus away from the WebView, and prepares to tear it down. Do not render any "submitted" confirmation in-game, and stop scheduling animations / audio / network calls after the call.

The flavorText option is a short caption rendered beneath the score on the host's result screen, and is also surfaced in the activity feed where friends see this player's results. Use it for context ('Beat the expert!', '3 turns to spare') — not for confirmation copy.

UI entry point

import { showTutorial, hideTutorial, showPositiveFeedback, createHeaderBar, spawnReward } from '@minit-games/sdk/ui';

// Tutorial hint
showTutorial('Tap to jump!', 'center');
// ... on first player action:
hideTutorial();

// Feedback pop-up
showPositiveFeedback('Combo x3!');

// Header bar with score and turns panels
const header = createHeaderBar({ y: 60, padding: 40 });
const score = header.addPanel({ label: 'Score', value: 0, align: 'right', style: { valueColor: '#f7931e' } });
const turns = header.addPanel({ label: 'Turns', value: 10 });

// Animate a reward flying to the score panel
score.flyToPanel({
    start: { x: 200, y: 400 },
    visual: '⭐',
    onArrive: () => score.setValue(Number(score.getValue()) + 100, { animate: true })
});

API overview

@minit-games/sdk (core)

| Export | Description | |--------|-------------| | initializeSDK(config?) | Initialize the SDK; sets up background and backward-compat shims | | loadingDone() | Signal to the app that the game is ready to be shown | | reportResult(result, options?) | Submit the final game result | | getUserData() | Read the player's persistent userData string (see Persistent user data) | | getConfigValue(key, default?) | Read a URL-param config value injected by the app | | getConfig() | Get all URL-param config values as a plain object | | seededRandom() | Deterministic random number (seeded from ?seed= param) | | patchSeed(seed) | Override the random seed at runtime | | addBackground(options?) | Apply a styled background to the game container | | applyMetaTags() | Inject charset + viewport meta tags |

Legacy aliases

For backward compatibility with games written against earlier versions, the old Drop-prefixed names are exported as aliases: reportDropResult, getDropConfigValue, getDropConfig, initializeDropSDK, addDropBackground, applyDropMetaTags, getDropEnvironment, and the types DropBackground/DropResultOptions/DropEnvironment.

Using with AI assistants

Chat-based AI assistants (Claude, ChatGPT, Gemini, and others) can scaffold a complete Minit game project, but the output is typically source code — it needs a build step before it can be uploaded. Once your game is working in the AI's preview, give it this prompt:

The game is ready. Please run `npm run build` and give me a ZIP whose root is the contents of the `dist/` folder — `index.html` should be at the top of the ZIP, not inside a `dist/` subfolder.

That ZIP is what you upload to the Creator Console. For a full walkthrough — including a Google AI Studio callout and what to do if the upload is rejected — see docs/ai-assistants.md.

Persistent user data

Each player has a single string slot stored per creator — shared across all of your games. The host (app) owns serialisation and transport; the SDK reads window.minit.userData as a plain string | undefined and the string value is forwarded unchanged (no JSON parse, no normalization). Use it to persist save data, settings, high scores, or any other per-player state (encode multiple values into a single string if needed).

Reading

import { getUserData } from '@minit-games/sdk';

const savedState = getUserData();  // string | undefined
  • Returns undefined when no value is stored for this player or when running outside the host app.
  • Returns "" when the stored value is the empty string — distinct from undefined.

Local userData testing

During npm run dev, you can seed getUserData via a URL param — no app host required:

?userData=tutorialPlayed%3Dtrue

getUserData() will return 'tutorialPlayed=true'.

URL-param values apply only when the host has not injected window.minit.userData (i.e. the property is undefined or null). Any host-injected string (including "") wins over the URL param — URL params are a local-dev convenience only.

userData is a reserved URL-param key. It is stripped from getConfig() and getConfigValue(), so getConfigValue('userData') always returns undefined (or its default). Read userData exclusively via getUserData().

Writing

Pass a string as userData in reportResult:

import { reportResult } from '@minit-games/sdk';

// Persist a plain string
reportResult(score, { userData: 'tutorialDone' });

// Encode multiple values into one string
const state = JSON.stringify({ level: 3, highScore: 1500 });
reportResult(score, { userData: state });

Omitting userData (or not passing options) leaves the stored value unchanged. An empty string "" is a valid value and will overwrite any previously stored data.

Limits

  • 1 KB (1024 UTF-8 bytes) maximum. Writes that exceed this limit are rejected and the existing value is left unchanged.

@minit-games/sdk/ui

| Export | Description | |--------|-------------| | showTutorial(text, options?) | Display a non-blocking tutorial hint overlay | | hideTutorial() | Hide the current tutorial hint | | isTutorialVisible() | Check if a tutorial hint is showing | | showFeedback(text, variant?, duration?) | Show a temporary feedback pop-up ("positive", "neutral", "negative") | | showPositiveFeedback(text, duration?) | Convenience wrapper — green variant | | showNeutralFeedback(text, duration?) | Convenience wrapper — orange variant | | showNegativeFeedback(text, duration?) | Convenience wrapper — red variant | | preloadFeedbackFont() | Preload the feedback font to avoid flash | | spawnReward(options) | Animate a single reward icon from start → target | | spawnRewards(count, options, staggerMs?) | Animate multiple reward icons with staggered timing | | createHeaderBar(config?) | Create a header bar for displaying game stats | | getHeaderBar() | Get the current header bar instance |

Fonts and assets

Game assets must be self-contained

Minit games run sandboxed — the game WebView has no external network access at runtime. All assets (images, audio, fonts, etc.) must ship inside the game ZIP. Any <link> to fonts.googleapis.com or any other external URL will fail silently when the game plays inside the app.

If your build does reference Google Fonts links, the Minit publish pipeline will attempt to inline the font data automatically at publish time. This is a best-effort safety net — do not rely on it. The correct approach is to bundle font files (woff2) inside your project and reference them with relative-path @font-face rules:

@font-face {
    font-family: 'MyFont';
    src: url('./fonts/myfont.woff2') format('woff2');
    font-weight: 400;
}

After building, confirm that the font file appears in dist/ alongside index.html.

SDK UI fonts are built in

The SDK's own UI components (header panel, feedback text) bundle their fonts as base64-inlined woff2 — no network requests are made and they work fully offline. The bundled families are:

| Module | Font | Weight | |--------|------|--------| | @minit-games/sdk/uicreateHeaderBar | Lato | 400, 700 | | @minit-games/sdk/uishowFeedback / preloadFeedbackFont | Bowlby One SC | 400 |

Both families are latin subset. Their SIL OFL license texts ship in the licenses/ directory (included in the npm package).

Bundle-size impact

The font data is tree-shaken per module — games pay only for what they import:

| Component | Adds to bundle | |-----------|---------------| | createHeaderBar (Lato 400 + 700) | ~37 KB base64 (~27.5 KB woff2) | | showFeedback / preloadFeedbackFont (Bowlby One SC 400) | ~26 KB base64 (~19.4 KB woff2) | | Neither | 0 KB |

Games that use neither createHeaderBar nor any feedback function pay no overhead. This per-module elimination applies when the game is built with a tree-shaking bundler (Vite, Rollup, esbuild, webpack); unbundled ESM consumers load whatever modules they import.

License

MIT — see LICENSE.