Getting Started
Overview
ReactVanilla
Secundus Stift is typed, build-time-compiled internationalization for TypeScript apps — vanilla or React. You author plain JSON, get compile-time-checked keys, and ship binary packs that load lazily, work offline, and invalidate precisely.
The pitch in one line: compile-time typed translations, build-time binary packs (small, optionally obfuscated/encrypted), runtime lazy loading with bounded memory, offline-first locale storage, dev/prod byte-identical.
How it works
- Author
locales/<locale>/<namespace>.json+stift.config.ts(locales, detection order, loading strategy, security tier). See Messages & Keys and stift.config.ts. - Build validates, type-gens
src/stift.gen.d.ts(keys, param shapes, locales become literal types — typos are compile errors), and compiles each locale×namespace into a binary.datpack (msgpack/cbor + compression) plus acatalog.json. See Build: Vite Plugin & CLI. - Run: the app detects a locale, loads only the namespaces it renders, persists packs for offline use, and revalidates against the catalog on a single ping. No service worker required. See Offline & Persistence and Updates & Invalidation.
Packages
| Package | Role | Docs |
|---|---|---|
@secundus-studio/stift-core |
Headless runtime: store, detection, ICU formatter, pack manager | React setup (core concepts), Offline |
@secundus-studio/stift-react |
React adapter: provider + hooks (re-exports core) | Setup & Boot Modes, Translating |
@secundus-studio/stift-generator |
Build core: config, discovery, typegen, pack compiler | stift.config.ts |
@secundus-studio/stift-vite-plugin |
Vite integration: virtual:stift/runtime, dev/prod packs |
Build |
@secundus-studio/stift-cli |
stift bin: generate, watch, compile |
Build |
@secundus-studio/stift-tanstack-router-plugin |
TanStack Router: URL rewriting + locale runtime | Setup |
@secundus-studio/stift-tanstack-devtool-plugin |
TanStack Devtools panel: live editing, pack state | Devtools |
@secundus-studio/stift-format |
Optional tree-shakable formatters (units, ordinals…) | Units |
@secundus-studio/stift-persisters |
Offline pack storage: OPFS / IndexedDB / Cache API chain | Offline & Persistence |
Enough talk, show me some code
Vanilla TypeScript (Node, browser, anywhere):
import { createStift } from '@secundus-studio/stift-core'
import { createStiftRuntime } from 'virtual:stift/runtime' // emitted by the vite-plugin
const Stift = createStift({ ...createStiftRuntime(), persister })
await Stift.initialize({ locale: await Stift.detectLocale() })
Stift.scope('common')('greeting', { name: 'Ada' }) // typed keys + params
React:
<StiftProvider Stift={Stift} boot={() => Stift.initialize({ locale })}>
<BootFallback fallback={<Spinner />}>
<App />
</BootFallback>
</StiftProvider>
const { t } = useTranslation('common')
t('greeting', { name: 'Ada' })
What now?
- New here? Follow the Quickstart — install to first translated string in eight steps.
- Installing into an existing app? See Installation.
- Wondering how keys stay in sync across locales? Read Messages & Keys — the default locale is the schema.