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

@secundus-studio/stift-core

v0.4.32

Published

Headless stift core: reactive store, locale/dialect model, detector pipeline, formatter engine interface, pack manager.

Readme

@secundus-studio/stift-core

Headless Stift runtime: reactive store, locale/dialect model, detector pipeline, ICU MessageFormat engine, pack manager. No React, no DOM � works in Node, browsers, workers, anywhere TypeScript runs. (React apps: install @secundus-studio/stift-react instead � it re-exports all of this.)

pnpm add @secundus-studio/stift-core

1. Create the instance

import { createStift } from '@secundus-studio/stift-core'
import { createStiftRuntime } from 'virtual:stift/runtime' // emitted by @secundus-studio/stift-vite-plugin

const Stift = createStift({
  ...createStiftRuntime(), // locales, detection, state backend, CompiledArtifactSource, catalog
  persister, // offline pack storage: OPFS / IndexedDB / Cache API (optional but recommended)
  hooks: { onError: (e) => console.error(e) }, // pack failures, missing keys
})

createStift is synchronous and side-effect-free. Persisted user state (the locale preference plus setParam/setUnit overrides) is configured in stift.config.ts (state: { prefix: '__stift_', storage: 'webStorage' }) and read synchronously at construction — no flash. persister is where downloaded pack bytes live. Without a persister, packs are memory-only (re-fetched each boot) — Stift.pack.durability reports 'durable' | 'memory' | 'none' so UI can gate install affordances honestly.

2. Boot (offline-first)

const locale = await Stift.detectLocale() // explicit ? persisted ? navigator ? fallback
await Stift.initialize({ locale })        // strategy decides what loads when

initialize fast-paths returning visitors: installed packs verify + activate from the persister with zero network, and the reactive packInstalls status is rehydrated from disk so it reads installed from the first notification. Loading strategies (loadingStrategy): 'lazy-per-namespace' (default, load on first t()), 'critical-then-full-background' (load critical, swap, persist the rest in the background), 'boot-all' (everything pinned before first paint).

3. Translate

Stift.t('checkout', 'title')                          // unscoped: namespace + key
Stift.scope('checkout')('title')                      // scoped: bare keys
Stift.scope(['common', 'checkout'])('login')          // multi: first namespace with the key wins
Stift.t('checkout', 'title', { count: 3 }, 'ar')      // render for a locale without switching

Keys, param shapes, and locales are literal types once the generator emits stift.gen.d.ts � typos and wrong params are compile errors. A cache miss returns the raw key, records it in store.missingKeys, reports hooks.onError({ code: 'missing-key' }), and kicks a background load so the next read resolves. ICU select/plural/offset work through the default engine; swap it via createStift({ formatter }).

Stift.subscribe((state) => �) fires on any store mutation (locale, cache, packInstalls, missingKeys�); read Stift.state / Stift.getLocale() / Stift.getDirection() synchronously anytime.

4. Offline packs

await Stift.installLocale('ar')          // download + verify + activate (boolean)
await Stift.activateLocale('ar')         // verify + activate from disk, no network
await Stift.isLocaleInstalled('ar')
await Stift.getPackSize('ar')            // byte budget vs download-needed
await Stift.pack.checkAllForUpdates()    // ONE catalog fetch, diff every installed locale
await Stift.pack.refreshStale('ar')      // re-download only stale namespaces
await Stift.pack.wipeLocale('ar')        // delete one locale (honest error status on partial failure)

Update checks compare per-namespace content hashes against a freshly fetched catalog.json � one ping detects every change. Statuses that lie are bugs: install/refreshStale write __meta per namespace (a failed write never corrupts the previous good pack), wipes report error instead of fake idle, and byte-true bytesReceived/bytesTotal come from the catalog.

Optional persisterTtlMs: packs older than the budget report reason: 'ttl-expired' (still fully usable offline) and refresh in the background on activate. Content hashes stay the real invalidation signal.

5. SSR hydration (no SSR boot mode)

The server renders t() results directly (@secundus-studio/stift-core/server: resolveLocale + FsJsonSource), then serializes what it rendered:

// server, after rendering
const state = serializeStiftState(Stift) // { locale, namespaces }
// ? inject into HTML as window.__STIFT_STATE__, set <html lang>
// client � adopt it: no re-detection, no fallback flash, no re-fetch
const Stift = createStift({ ...runtime, hydrate: window.__STIFT_STATE__ })
await Stift.initialize({ locale: state.locale })

There is deliberately no 'ssr' boot strategy � hydration is the SSR story.

6. Persisters

One package, three backends, plus a best-effort chain:

import { createBestEffortPersister } from '@secundus-studio/stift-persisters'
// OPFS → IndexedDB → Cache Storage → memory: first supported wins
const Stift = createStift({ ...runtime, persister: await createBestEffortPersister() })

| Import | Backend | Notes | |---|---|---| | @secundus-studio/stift-persisters/opfs | Origin Private FS | Fastest; needs secure context | | @secundus-studio/stift-persisters/idb-keyval | IndexedDB | Broad fallback | | @secundus-studio/stift-persisters/cache-api | Cache Storage | Shares the browser cache quota |

All implement PersisterAdapter = { get, set, del, keys } over Uint8Array — custom backends implement the same interface directly, no registration needed.