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

tile-live-layer

v0.2.0

Published

Remote feature-flag / config SDK for Tile (Expo / React Native) apps. Fetches a per-(app,env) JSON layer from the CDN, caches it, and resolves typed flags with a 4-layer fallback.

Readme

tile-live-layer

Remote config SDK for Tile (Expo / React Native) apps.

Fetches a per-(app, environment) nested JSON config from the CDN, sliced by a generic category, caches it, and reads values on-device with a 4-layer fallback so a read never fails and the app never blocks on the network:

live (network)  →  cached (AsyncStorage)  →  bootstrap (baked at build)  →  code default

Config is arbitrary nested JSON — read any path with useLiveLayer(['home', 'cta', 'label']). It is fully decoupled from OTA bundles.

Install

npm install tile-live-layer
# AsyncStorage enables cross-launch persistence (optional but recommended):
npx expo install @react-native-async-storage/async-storage

Usage

import { LiveLayerProvider, useLiveLayer } from 'tile-live-layer';
import bootstrap from './assets/tile-live-layer.json'; // baked at build time

export default function App() {
  return (
    <LiveLayerProvider
      options={{
        appId: 'YOUR_APP_ID',
        env: 'prod',                 // 'dev' | 'staging' | 'prod' | 'preview'
        baseUrl: 'https://storage.googleapis.com/tile-livelayer-configs',
        // The category this user/session belongs to, computed from on-device
        // signals at boot. The SDK fetches the longest existing prefix of this
        // key (falling back to the base layer []).
        context: ['in', 'mumbai'],
        bootstrap,
        refreshOnForeground: true,
      }}
    >
      <Screen />
    </LiveLayerProvider>
  );
}

function Screen() {
  const label = useLiveLayer<string>(['home', 'cta', 'label'], 'Shop now');
  const timeout = useLiveLayer<number>(['checkout', 'timeoutMs'], 8000);
  // ...
}

Categories

A category is an ordered array of arbitrary strings (['in', 'mumbai']) — region, tier, A/B bucket, anything. The app declares which category it belongs to via the provider's context; the SDK fetches the longest existing prefix of it from the manifest, falling back through the chain to the base layer:

['in','mumbai','pro']  →  in/mumbai/pro → in/mumbai → in → (base)

Each category is one already-resolved flat document — the SDK fetches exactly one file and does no merging on-device.

Hooks

  • useLiveLayer(path, fallback?) — read one nested value, e.g. useLiveLayer(['home','cta','label'], 'Shop now').
  • useLiveLayerAll() — the whole active config document.
  • useLiveLayerStatus(){ config, category, version, status, source, error, refresh }.

Debug panel

Render anywhere inside the provider to see live status + every resolved value:

import { LiveLayerDebugPanel } from 'tile-live-layer';
<LiveLayerDebugPanel />

Build-time snapshot & management — the tile CLI

Management and build-time snapshots are handled by the unified tile CLI (npm i -g @tile/cli).

# bake the current published base config into your assets so first launch
# (no network, no cache) still shows real values:
tile live-layer pull --app YOUR_APP_ID --env prod --out assets/tile-live-layer.json

# manage config headless (CI / agents) — auth via `tile login` or TILE_TOKEN:
tile live-layer get                                            # base config
tile live-layer get home.cta.label --category in/mumbai        # one nested path
tile live-layer set home.cta.label="₹500 off" --category in/mumbai
tile live-layer publish --file config.json --category in/mumbai # replace whole category
tile live-layer layers                                         # list categories
tile live-layer versions --category in/mumbai
tile live-layer rollback --to 3 --category in/mumbai
tile live-layer rm-layer in/mumbai                             # delete a category

Writes are atomic per category (optimistic-locked, auto-retry once on a 409).

How serving works

The backend publishes a no-cache manifest plus one immutable blob per category:

live-layer/{appId}/{env}/manifest.json              no-cache  (which categories exist + current blob)
live-layer/{appId}/{env}/v/{N}.json                 immutable (base layer)
live-layer/{appId}/{env}/{category}/v/{N}.json      immutable (e.g. in/mumbai/v/3.json)

The SDK reads the manifest each launch (cheap, non-blocking via stale-while-revalidate), picks the longest matching category, and fetches that one immutable blob at most once per version per device. Point baseUrl at a CDN domain later with no code change.