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

zenopack

v1.0.0

Published

Universal game package format for browser-based unblocking platforms. Bundle any web game into a single portable .zenopack file.

Readme

ZenoPack Specification v1.0

The universal game package format for browser-based unblockers.


Overview

ZenoPack (.zenopack) is an open, client-side game packaging format designed for browser-based unblocking platforms. A .zenopack file contains everything needed to run a web game — HTML, JavaScript, CSS, assets, and metadata — in a single portable file that requires no server, no installation, and no external dependencies.

Any platform that implements the ZenoPack spec can import and export games interchangeably, creating a universal ecosystem of shareable browser games.


Installation

Option 1 — Script Tag (recommended for most sites)

Download zenopack.js and optionally zenopack-ui.js, place them in your project, then include them in your HTML:

<!-- Core library (required) -->
<script src="zenopack.js"></script>

<!-- Optional: drop-in import UI -->
<script src="zenopack-ui.js"></script>

That's it. ZenoPack and ZenoPack_UI are now available globally.

Option 2 — CDN (via jsDelivr)

No download needed — link directly from a CDN. Replace @1.0.0 with the latest version tag:

<script src="https://cdn.jsdelivr.net/gh/xXmizzeryXx/[email protected]/zenopack.js"></script>
<script src="https://cdn.jsdelivr.net/gh/xXmizzeryXx/[email protected]/zenopack-ui.js"></script>

Option 3 — npm

npm install zenopack
const ZenoPack = require('zenopack');
// or
import ZenoPack from 'zenopack';

Option 4 — Manual Implementation

If you don't want to use the library at all, the format is simple enough to implement yourself in under 50 lines. See the Implementation Guide section below.


File Format

A .zenopack file is a UTF-8 encoded JSON document with the .zenopack extension.

Despite being JSON, it is saved with the .zenopack extension to make it clearly identifiable and prevent accidental editing. Platforms should not rely on the MIME type being set correctly by the transferring system.

Top-Level Structure

{
  "zenopack": "1.0",
  "name": "My Game",
  "icon": "data:image/png;base64,...",
  "category": "arcade",
  "description": "A short description of the game.",
  "fileCount": 3,
  "exportedAt": "2025-03-16T12:00:00.000Z",
  "files": [ ... ]
}

Top-Level Fields

| Field | Type | Required | Description | |-------|------|----------|-------------| | zenopack | string | ✅ | Spec version. Currently "1.0". | | name | string | ✅ | Display name of the game. Max 128 characters. | | files | array | ✅ | Array of file objects. Must contain at least one entry with path: "index.html". | | icon | string | ❌ | Base64 data URL of the game's icon/thumbnail. Recommended size: 256×256px. | | category | string | ❌ | Category tag. See Categories. | | description | string | ❌ | Short description of the game. Max 512 characters. | | fileCount | number | ❌ | Number of files (informational, for display). | | exportedAt | string | ❌ | ISO 8601 timestamp of when the pack was created. |


File Objects

Each entry in the files array represents one file from the game.

{
  "path": "index.html",
  "mimeType": "text/html",
  "data": [60, 33, 68, 79, 67, 84, 89, 80, 69, ...]
}

File Fields

| Field | Type | Required | Description | |-------|------|----------|-------------| | path | string | ✅ | Relative path of the file within the game folder. Must use forward slashes. | | mimeType | string | ✅ | MIME type of the file (e.g. "text/html", "application/javascript"). | | data | number[] | ✅ | Raw file contents as an array of unsigned 8-bit integers (byte array). |

Path Rules

  • Paths are relative to the game root — no leading slash, no ./ prefix.
  • Directory separators must be forward slashes (/), not backslashes.
  • Every .zenopack must contain a file with path: "index.html" — this is the game's entry point.
  • Subdirectories are supported: "assets/sprite.png", "js/game.js", etc.

Encoding File Data

File contents are stored as a plain JavaScript byte array (array of integers 0–255). This is intentionally chosen over base64 for simplicity and direct Uint8Array compatibility:

// Encoding (export)
const buffer = await file.arrayBuffer();
const data = Array.from(new Uint8Array(buffer));

// Decoding (import)
const buffer = new Uint8Array(data).buffer;
const file = new File([buffer], filename, { type: mimeType });

Validation Rules

A valid .zenopack file must satisfy all of the following:

  1. The file must be valid JSON.
  2. The top-level zenopack field must be present and a string.
  3. The name field must be present and a non-empty string.
  4. The files field must be a non-empty array.
  5. At least one file must have path equal to "index.html" (case-insensitive).
  6. Every file object must have path, mimeType, and data fields.
  7. data must be an array of integers.

Categories

The optional category field should be one of the following standard values. Platforms may display or filter by category.

| Value | Description | |-------|-------------| | arcade | Fast-paced action games | | puzzle | Logic and puzzle games | | platformer | Side-scrolling platformers | | shooter | Shoot-em-ups and FPS | | rpg | Role-playing games | | strategy | Strategy and tower defense | | sports | Sports simulations | | racing | Racing games | | horror | Horror games | | other | Anything else |


Versioning

The zenopack field contains the spec version as a string ("1.0").

  • Patch versions (e.g. 1.01.0.1) are backwards compatible. Importers should accept any 1.x pack.
  • Major versions (e.g. 1.02.0) may introduce breaking changes. Importers should warn if the major version is higher than supported.

Implementation Guide

Importing a .zenopack

// 1. Read the file as text
const text = await file.text();
const pack = JSON.parse(text);

// 2. Validate
if (!pack.zenopack || !pack.name || !pack.files?.length) {
  throw new Error('Invalid .zenopack');
}
const hasIndex = pack.files.some(f => f.path.toLowerCase() === 'index.html');
if (!hasIndex) throw new Error('Missing index.html');

// 3. Reconstruct files
const fileRecords = pack.files.map(f => {
  const buffer = new Uint8Array(f.data).buffer;
  const file = new File([buffer], f.path.split('/').pop(), { type: f.mimeType });
  return { file, path: f.path, mimeType: f.mimeType };
});

// 4. Use fileRecords however your platform loads games
// e.g. register with a Service Worker, use blob URLs, etc.

Exporting a .zenopack

// fileRecords: [{ file: File, path: string, mimeType: string }]
async function exportZenopack(name, fileRecords) {
  const files = [];
  for (const r of fileRecords) {
    const buf = await r.file.arrayBuffer();
    files.push({
      path: r.path,
      mimeType: r.mimeType,
      data: Array.from(new Uint8Array(buf)),
    });
  }

  const pack = {
    zenopack: '1.0',
    name,
    fileCount: files.length,
    exportedAt: new Date().toISOString(),
    files,
  };

  const blob = new Blob([JSON.stringify(pack)], { type: 'application/octet-stream' });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = name.replace(/[^a-z0-9_-]/gi, '_') + '.zenopack';
  a.click();
  URL.revokeObjectURL(url);
}

Using the Official Library

The fastest way to add ZenoPack support is to use the official zenopack.js library:

<script src="zenopack.js"></script>
<!-- Optional: drop-in UI -->
<script src="zenopack-ui.js"></script>

Import a game:

const fileInput = document.getElementById('my-file-input');
fileInput.addEventListener('change', async () => {
  const game = await ZenoPack.import(fileInput.files[0]);
  console.log(game.name);       // "My Game"
  console.log(game.fileRecords); // [{ file, path, mimeType }, ...]
});

Export a game:

await ZenoPack.export({
  name: 'My Game',
  icon: 'data:image/png;base64,...', // optional
  fileRecords: myFileRecords,
});
// Downloads "My_Game.zenopack" automatically

Drop-in import UI:

ZenoPack_UI.createImportUI('#my-container', {
  onImport: (game) => {
    console.log('Imported:', game.name);
    // game.fileRecords is ready to use
  },
  onError: (err) => console.error(err),
});

File Size Considerations

ZenoPack files store binary data as integer arrays, which results in approximately 3–4× larger file sizes compared to the original game assets. This is a deliberate trade-off for simplicity and universal JSON compatibility.

For large games (>50MB original), consider whether ZenoPack is the right transport. For most browser games (typically 1–20MB), the size overhead is acceptable.


Example .zenopack

{
  "zenopack": "1.0",
  "name": "Snake",
  "category": "arcade",
  "description": "Classic snake game.",
  "fileCount": 2,
  "exportedAt": "2025-03-16T12:00:00.000Z",
  "files": [
    {
      "path": "index.html",
      "mimeType": "text/html",
      "data": [60, 104, 116, 109, 108, 62, ...]
    },
    {
      "path": "game.js",
      "mimeType": "application/javascript",
      "data": [118, 97, 114, 32, 115, ...]
    }
  ]
}

License

The ZenoPack specification is released under the MIT License. Any platform may implement, extend, or build upon it freely.


Credits

ZenoPack was created by the Eclipse Suite team as part of the Zeno platform.

Originated by Mizzery — Eclipse Suite