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

@series-inc/run-game-helpers

v0.1.0

Published

Template library of reusable TypeScript game systems for RUN SDK games. Install to fetch the templates, then copy the systems you need into your game.

Readme

RUN Game Helpers

Reusable game systems for RUN games, packaged as copy-in templates with AI-first integration guides.

Each system is a small set of framework-free TypeScript ES modules plus a README.md written for an AI coding agent: the agent copies the code into the host game, adapts the marked extension points, and wires it up — deriving every game-specific answer from the host game's own code instead of asking the developer questions. This is a copy-in library, not a runtime dependency — you install or clone it to get the templates, then copy the ones you need; you never import from it at runtime.

How to use this repo (for humans)

In your game's repo, tell your AI agent something like:

"I need a save system for my game. Use the templates from https://github.com/series-ai/run-game-helpers (clone it, or point at a local checkout)."

Or install the templates from npm so the agent can copy them out of node_modules without cloning:

npm i @series-inc/run-game-helpers
# templates land in node_modules/@series-inc/run-game-helpers/{systems,shared,starter,docs}

That's it. The agent reads this file, follows the routing table below to the right system folder, and integrates it. You should not need to answer questions.

Starting from nothing? Point the agent here and say "make me a new RUN game" — starter/ is a complete app shell (Vite + Pixi.js + React + Tailwind + RUN SDK boot/loading/deploy) that scaffolds a runnable game the systems below plug into.

Routing table (for AI agents)

Match the request to a system. Requests often use different words than our folder names — route by intent.

| The user asks for... | System | Folder | |---|---|---| | save system, saving/loading, persistence, progress, cloud save, save slots, "keep progress between sessions", settings that persist | Save | systems/save/ | | shop, IAP, in-app purchases, monetization, premium currency, RunBucks, bundles, gem packs, starter pack, special offers, no-ads subscription | IAP Shop | systems/iap-shop/ | | stats, statistics screen, lifetime stats, counters, "track how many X", records screen | Stats | systems/stats/ | | daily rewards, login bonus, daily login, streak rewards, reward calendar, "come back every day" | Daily Rewards | systems/daily-rewards/ | | tutorial, onboarding, FTUE, "explain the game to new players", highlight a button, spotlight, guided tour, tooltips sequence | Tutorial | systems/tutorial/ | | daily quests, quests, missions, daily challenges, objectives, "give players goals each day" | Daily Quests | systems/daily-quests/ | | ads, rewarded ads, "watch an ad for a reward", ad rewards ladder, ad boosts, interstitials | Ads | systems/ads/ | | notifications, reminders, local/push notifications, re-engagement, "remind players to come back" | Notifications | systems/notifications/ | | analytics, events, tracking, funnels, telemetry, "measure where players drop off" | Analytics | systems/analytics/ | | localization, translations, i18n, l10n, languages, "support Spanish/Japanese/...", multi-language text | Localization | systems/localization/ | | trusted time, server time, day rollover, daily reset, countdown to midnight, anti clock-cheating | Server Time (shared) | shared/serverTime.ts | | a new game, starter project, boilerplate, scaffold, app template, "set up a RUN game with Pixi/React/Tailwind", project skeleton, loading screen | Starter (app shell) | starter/ |

If a request spans multiple systems ("set up monetization and daily rewards"), integrate them one at a time in dependency order (see below).

Integration protocol (for AI agents)

Follow this protocol for every system you integrate. The goal: zero questions to the user, working code in their game.

  1. Read the system's README.md top to bottom before writing any code. It contains the integration steps, the config reference, and a "Derive from the host game" section listing every decision you must make — with instructions for answering each from the host game's code.
  2. Read docs/run-sdk-notes.md (distilled RUN SDK facts: init, lifecycles, storage limits, error handling). If the host game has a local copy of the official SDK docs in rundot/docs/ (legacy installs: .rundot/docs/), prefer those for anything this repo's notes don't cover — and trust them over your training data.
  3. Inventory the host game. Before copying anything, establish:
    • Rendering/UI approach: plain DOM? canvas-only? React/framework? (Reference UIs here are vanilla DOM; the README's "UI adaptation" section covers the rest.)
    • Boot sequence: where is RundotGameAPI.initializeAsync() awaited? If nowhere, add it at boot before any SDK call.
    • Game loop: is there a per-frame update(dt)? (Needed for debounced save flushing.)
    • Existing systems: does the game already have a save mechanism, currencies, a screen/navigation pattern? Integrate with what exists rather than duplicating it.
  4. Copy the template files into the host game (suggested home: src/helpers/<system>/), including any shared/ modules the system lists as dependencies. Keep file names. Templates are TypeScript: a TS host consumes them as-is; if the host game is plain JavaScript, strip the type annotations while copying (interfaces/type aliases disappear, : Type annotations and as casts come off — the runtime code is identical). Never skip a system because the host is JS.
  5. Adapt. Every game-specific decision point in template code is marked with an ADAPT: comment. The config object passed to the system's create...() factory carries all game-specific content (schemas, catalogs, reward tables, copy). Machinery code below the config should rarely need edits.
  6. Wire and verify. Follow the README's numbered wiring steps (boot, loop, UI), then run its verification checklist. Actually exercise the flows (save/reload, purchase in mock mode, day rollover with the test flag) — don't just confirm it compiles.

Global rules (apply to all systems)

  • Every RundotGameAPI call can reject, and an unhandled rejection crashes the game. Wrap all SDK calls in try/catch (template code already does; keep the posture in code you add).
  • Await RundotGameAPI.initializeAsync() once at boot before any other SDK call.
  • Use the local mock contract. Outside the RUN host, SDK 5.23+ provides deterministic mocks for several surfaces (including ads, IAP, stats, and environment); other calls may still return empty/null values. Follow docs/run-sdk-notes.md and each system's checklist instead of assuming every call returns nothing. Systems must still treat unexpected null/failure as "unknown", never as a player-facing error.
  • Persist aggressively on lifecycles.onSleep; never rely on onQuit firing. And never fire fresh SDK RPCs (e.g. scheduling notifications) from onSleep/onQuit handlers — a hard close tears down the runtime before the RPC lands. Do that work while the app is alive.
  • Use shared/serverTime.ts for anything time-gated (daily resets, limited offers). Never trust the device clock for reward gating.
  • RUN games build with base: './' (Vite) and deploy the dist/ folder; don't break that.

System dependency order

save  ──────────────  foundational: stats, daily-rewards, daily-quests,
                       tutorial, iap-shop, ads all persist their state
                       inside the save blob
shared/serverTime ──  required by daily-rewards, daily-quests, ads (daily
                       caps); recommended for iap-shop limited-time offers
stats ─────────────   daily-quests measures goal progress against stat
                       counters — integrate stats before (or with) quests
iap-shop ──────────   ads uses its subscription status + RunBucks fallback
                       via injected functions (optional — ads works alone)
analytics ─────────   standalone; every other system exposes hooks that
                       wire into it (see its README's "Wiring" section)
notifications ─────   standalone; daily-rewards schedules its own reminder
                       ids directly, which coexists fine (custom-id dedupe)
localization ──────   standalone; integrate FIRST if the game will ship
                       multi-language, so other systems' player-facing copy
                       (toasts, reminders, screen labels) goes through it
                       from the start

If the host game has no save system yet and the user asks for stats / daily rewards / tutorials / IAP, integrate systems/save/ first (it's small), then the requested system. Each system's README documents exactly which save fields it adds.

If there is no game yet at all, start from starter/ (it is the host game: boot, loading screen, Pixi + React + Tailwind shell), then integrate systems into it — its README's "Wiring the systems library" section maps each system to its plug-in point.

Repo conventions

  • Template code is strict TypeScript ES modules, importing only @series-inc/rundot-game-sdk/api and files in shared/. No frameworks, no build-tool assumptions beyond ESM + a TS-aware bundler (extensionless relative imports, moduleResolution: "bundler"). Each system exports interfaces for its config, its returned object, and the save-slice it stores. The repo root's npm run check type-checks all templates (tsconfig.json).
  • Factories over globals: each system exports create<System>(config); game-specific content lives in the config, generic machinery in the module.
  • Reference UIs (*Screen.ts + .css + .html snippets) are plain-DOM implementations you can use as-is in a DOM game or treat as a spec when re-implementing in the host's UI framework.
  • ADAPT: comments mark every line an integrator is expected to change. Everything unmarked is machinery.
  • starter/ is the one exception to "framework-free": it's a whole-app scaffold and commits to a stack (Pixi.js v8, React 19, Tailwind v4). The systems/ templates stay framework-free so they fit any host, including non-starter games.

Design guarantees

The templates use defensive SDK calls, versioned save migrations, mock-mode fallbacks, and anti-clock-tampering time handling. System READMEs document their specific guarantees and tradeoffs, including quiet USER_CANCELLED handling and optional timezone-pinned daily resets.