SayKit
Integrations

Vite (unplugin)

Use SayKit with Vite, Rollup, Rolldown, Webpack, Rspack, esbuild, Farm, or Bun

unplugin-saykit is the universal SayKit build-tool plugin. Powered by unplugin, it ships ready-made entry points for almost every JS bundler.

This page focuses on Vite, but the configuration is the same shape for any bundler, only the import path changes.

Install

pnpm add -D unplugin-saykit

And the supporting packages SayKit needs:

pnpm add -D @saykit/config @saykit/format-po @saykit/transform-js @saykit/transform-jsx

Use

vite.config.ts
import saykit from 'unplugin-saykit/vite';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [saykit()],
});
rollup.config.js
import saykit from 'unplugin-saykit/rollup';

export default {
  plugins: [saykit()],
};
tsdown.config.ts
import { defineConfig } from 'tsdown';
import saykit from 'unplugin-saykit/rolldown';

export default defineConfig({
  entry: ['src/entry.ts'],
  plugins: [saykit()],
});
webpack.config.js
const saykit = require('unplugin-saykit/webpack').default;

module.exports = {
plugins: [saykit()],
};
rspack.config.js
const saykit = require('unplugin-saykit/rspack').default;

module.exports = {
  plugins: [saykit()],
};
import saykit from 'unplugin-saykit/esbuild';
import { build } from 'esbuild';

await build({
plugins: [saykit()],
});
farm.config.ts
import saykit from 'unplugin-saykit/farm';

export default {
  plugins: [saykit()],
};
import saykit from 'unplugin-saykit/bun';

await Bun.build({
plugins: [saykit()],
});

The plugin takes no options, everything it needs lives in your saykit.config.ts.

What it does

For every file in your bucket's include globs, the plugin asks the configured transformers to rewrite the source. Macros like say`Hello, ${name}!` become small say.call({ id: '...', name }) runtime invocations.

For every import that matches a bucket's output template, e.g. import en from './locales/en.po', the plugin parses the file with the bucket's formatter and emits a JS module exporting the compiled catalogue. There is no .po file at runtime; just plain JS objects.

Plugin ordering

The plugin uses enforce: 'pre' so it runs before most other transforms. That matters because macros need to be visible, if a previous transform mangles or wraps them, extraction may miss messages.

If you have a custom plugin that lowers tagged templates (e.g. to function calls), make sure SayKit's plugin runs first.

Bundler-specific notes

Vite

saykit() plugs in cleanly alongside @vitejs/plugin-react and other Vite plugins, including TanStack Start. Drop it into the plugins array and you're done.

Rolldown / tsdown

Used by the Carbon example to bundle for Cloudflare Workers. See the Carbon integration.

Webpack / Rspack

Should work out of the box, though watch mode varies by bundler. For Next.js, prefer babel-plugin-saykit instead.

esbuild

Sufficient for libraries but limited: esbuild's plugin API can't always produce the same dev-server experience as Vite. Combine with Vite/Rolldown when possible.

Next

On this page