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

@superapp_men/content-provider

v1.4.0

Published

Offline content provider for SuperApp partner applications via iframe/Capacitor

Readme

@superapp_men/content-provider

Bridge package for Bewize / SuperApp partner applications to request offline assets from the SuperApp host via postMessage.

Partner apps run inside an iframe managed by the SuperApp. This package provides typed clients for four categories of assets:

| Client | Function | What it returns | |--------|----------|-----------------| | ContentProviderClient | getContent() | The student's grade-specific content.json | | MediaProviderClient | getMedia(path) / getMediaObjectUrl(path) | Downloaded audio / video / image files | | BackgroundProviderClient | getBackground(name) | Shared SVG background images | | RiveProviderClient | getRive(path) / getRiveBuffer(path) / getRiveUrl(path) | Rive animation files (.riv) |


Installation

npm install @superapp_men/content-provider

ContentProviderClient

Retrieves the pre-downloaded content.json for the authenticated student's grade.

import { ContentProviderClient } from "@superapp_men/content-provider";

const client = new ContentProviderClient({ partnerCode: "bewize" });

try {
  const content = await client.getContent();
  console.log(content); // parsed content.json object
} finally {
  client.destroy();
}

Config

| Option | Type | Default | Description | |--------|------|---------|-------------| | partnerCode | string | required | Your partner code (e.g. "bewize") | | timeout | number | 15000 | Request timeout in ms | | debug | boolean | false | Enable console logs |


MediaProviderClient

Retrieves downloaded media files (audio, video, images) stored in the SuperApp's data directory at partner-apps/{partnerCode}/media/.

import { MediaProviderClient } from "@superapp_men/content-provider";

const media = new MediaProviderClient({ partnerCode: "bewize" });

// Option A — get base64 data + MIME type
const { data, mimeType, encoding } = await media.getMedia("consignes/00e5b2a4-98c8-409e-9b68-d8eb397d4c78.mp3");

// Option B — get a ready-to-use object URL (recommended for <audio> / <video> / <img>)
const { url, mimeType, revoke } = await media.getMediaObjectUrl("consignes/00e5b2a4-98c8-409e-9b68-d8eb397d4c78.mp3");

const audio = new Audio(url);
audio.play();

// Release the object URL when no longer needed
audio.addEventListener("ended", revoke);

media.destroy();

mediaPath format

Pass the relative path exactly as listed in the manifest media.audio.files[] array:

"consignes/00e5b2a4-98c8-409e-9b68-d8eb397d4c78.mp3"
"questions/159903a1-803d-46ee-9f34-365010d378f3.mp3"

The same function works for future video and image files — the MIME type is auto-detected from the extension.

Supported MIME types

| Extension | MIME type | |-----------|-----------| | .mp3 | audio/mpeg | | .m4a | audio/mp4 | | .ogg | audio/ogg | | .wav | audio/wav | | .mp4 | video/mp4 | | .webm | video/webm | | .png | image/png | | .jpg / .jpeg | image/jpeg | | .gif | image/gif | | .webp | image/webp | | .svg | image/svg+xml |

Config

| Option | Type | Default | Description | |--------|------|---------|-------------| | partnerCode | string | required | Your partner code | | timeout | number | 30000 | Request timeout in ms (files can be large) | | debug | boolean | false | Enable console logs |


BackgroundProviderClient

Retrieves shared SVG background images hosted by the SuperApp. Returns a ready-to-use base64 data URL.

import { BackgroundProviderClient } from "@superapp_men/content-provider";
import type { BackgroundName } from "@superapp_men/content-provider";

const bg = new BackgroundProviderClient();

const { url } = await bg.getBackground("champs");

// Use as CSS background
element.style.backgroundImage = `url(${url})`;

// Or as <img> src
imgElement.src = url;

bg.destroy();

Available backgrounds

| Name | Preview | |------|---------| | "champs" | Green countryside fields | | "decor_souk" | Traditional souk decoration | | "douar" | Rural village scene | | "puis" | Well / water scene |

Config

| Option | Type | Default | Description | |--------|------|---------|-------------| | timeout | number | 10000 | Request timeout in ms | | debug | boolean | false | Enable console logs |


RiveProviderClient

Retrieves Rive animation files (.riv) stored in the partner app's bundle. The SuperApp reads the pre-downloaded file from partner-apps/{partnerCode}/rive/{rivPath} and returns its binary content as base64.

import { RiveProviderClient } from "@superapp_men/content-provider";
import { Rive, EventType } from "@rive-app/canvas";

const riveProvider = new RiveProviderClient({ partnerCode: "bewize" });

// Option A — ArrayBuffer (recommended, for Rive's `buffer` prop)
const buffer = await riveProvider.getRiveBuffer("animations/intro.riv");
const r = new Rive({ buffer, canvas, autoplay: true });

// Option B — temporary object URL (for Rive's `src` prop)
const { url, revoke } = await riveProvider.getRiveUrl("animations/intro.riv");
const r2 = new Rive({ src: url, canvas, autoplay: true });
r2.on(EventType.Load, revoke); // free memory after load

// Option C — raw base64 data
const { data, mimeType, encoding } = await riveProvider.getRive("animations/intro.riv");

riveProvider.destroy();

rivPath format

Pass the relative path within the partner app's rive/ directory (as stored in the downloaded bundle):

"animations/intro.riv"
"characters/hero.riv"
"ui/button.riv"

Config

| Option | Type | Default | Description | |--------|------|---------|-------------| | partnerCode | string | required | Your partner code (e.g. "bewize") | | timeout | number | 30000 | Request timeout in ms | | debug | boolean | false | Enable console logs |

SuperApp host path

The SuperApp reads the file from:

partner-apps/{partnerCode}/rive/{rivPath}

Make sure your bundle extraction puts .riv files under this path in the app's data directory.


SuperApp integration

If you are implementing the SuperApp host side, import from the /superapp subpath to get the handler types:

import {
  ContentMessageType,
  MediaMessageType,
  BackgroundMessageType,
  RiveMessageType,
} from "@superapp_men/content-provider/superapp";

import type {
  ContentRequestMessage,
  MediaRequestMessage,
  BackgroundRequestMessage,
  RiveRequestMessage,
} from "@superapp_men/content-provider/superapp";

The SuperApp's IframeCommunicationHandler handles all four message types:

| Message type | Handler | Filesystem path | |-------------|---------|-----------------| | content:request | Reads content.json | partner-apps/{code}/content/current/content.json | | media:request | Reads media file as base64 | partner-apps/{code}/media/{path} | | background:request | Fetches SVG from static assets | /shared_backgrounds/{name}.svg | | rive:request | Reads .riv file as base64 | partner-apps/{code}/rive/{path} |


Message protocol

All messages follow the same pattern:

Request (partner → SuperApp):

{
  "type": "content:request",
  "requestId": "1751234567890-abc123",
  "payload": { "partnerCode": "bewize" },
  "timestamp": 1751234567890
}

Response (SuperApp → partner):

{
  "type": "content:response",
  "requestId": "1751234567890-abc123",
  "statusCode": 200,
  "body": { "content": { ... } },
  "timestamp": 1751234567891
}

Rive request (partner → SuperApp):

{
  "type": "rive:request",
  "requestId": "1751234567890-abc123",
  "payload": { "partnerCode": "bewize", "rivPath": "animations/intro.riv" },
  "timestamp": 1751234567890
}

Rive response (SuperApp → partner):

{
  "type": "rive:response",
  "requestId": "1751234567890-abc123",
  "statusCode": 200,
  "body": { "data": "<base64>", "mimeType": "application/octet-stream", "encoding": "base64" },
  "timestamp": 1751234567891
}

Error responses use statusCode 400 / 404 / 500 and body: { "error": "...", "detail": "..." }.


License

MIT — SuperApp Team