Getting Started
AI Setup Prompt
Copy everything below the line into an agent to set Stift up in a fresh repo.
It distills the getting-started and config skills into one paste.
You are setting up Stift by Secundus, typed build-time-compiled i18n for
TypeScript. Packages live under the @secundus-studio scope and are
pre-release: install exactly version 0.4.0, never latest.
pnpm add @secundus-studio/stift-react@0.4.0 @secundus-studio/stift-vite-plugin@0.4.0
If the registry needs auth, add the @secundus-studio scope line to .npmrc
and run with NPM_TOKEN set.
Wire the Vite plugin in vite.config.ts:
import { stiftPlugin } from '@secundus-studio/stift-vite-plugin'
export default defineConfig({
plugins: [stiftPlugin()],
})
Write stift.config.ts:
import { defineConfig } from '@secundus-studio/stift-generator'
export default defineConfig({
locales: { default: 'en', supported: ['en'] },
namespaces: { dir: 'locales', discovery: 'convention', default: ['common'] },
messageFormat: 'icu-mf1',
detection: { order: ['explicit', 'persisted', 'navigator'], fallback: 'en' },
loadingStrategy: 'critical-then-full-background',
})
Start with one locale and one namespace. Add params.context, units, and
security.tier only when the feature calls for them. The default locale is
the schema — it owns every namespace's key set, and new keys propagate to
every other locale automatically.
Create locales/en/common.json with one key:
{ "greeting": "Hello, {name}!" }
Create the runtime in src/stift.ts — everything declarative arrives via the
generated virtual:stift/runtime module; this file supplies only what can't
be serialized:
import { createStiftApp } from '@secundus-studio/stift-react'
import { createStiftRuntime } from 'virtual:stift/runtime'
import { createBestEffortPersister } from '@secundus-studio/stift-persisters'
export const { stift, boot } = await createStiftApp({
...createStiftRuntime(),
persister: createBestEffortPersister,
})
Boot before rendering in src/main.tsx:
import { stift, boot } from './stift'
await boot()
render(
<StiftProvider stift={stift}>
<Suspense fallback={<FullPageLoader />}><App /></Suspense>
</StiftProvider>,
)
Use it in a component:
const { t } = useTranslation('common')
t('greeting', { name: user.name })
Verify: pnpm dev, the greeting renders from locales/en/common.json.
When you need more than this page, load the skill that owns the topic
(pnpm exec intent load <package>#<skill>): stift-vite-plugin#build for
plugin options, stift-core#core for boot and detection,
stift-generator#config for the config schema,
stift-generator#authoring-translations for writing keys,
stift-react#react and stift-react#values for hooks and formatting.
The full routing layer is at https://stift.secundus.studio/llms.txt.
The canonical reference app is examples/tanstack-spa in the Stift repo.