@ic-reactor/vite-plugin
@ic-reactor/vite-plugin runs the shared
@ic-reactor/codegen pipeline inside Vite. It
generates declarations and typed reactor entrypoints, with optional React
hooks, from .did files, watches for changes, and can inject the ic_env
cookie used by
ClientManager.
Installation
Section titled “Installation”pnpm add -D @ic-reactor/vite-pluginpnpm add @ic-reactor/react @tanstack/react-query @icp-sdk/coreFor non-React output, set target: "core" and install the matching runtime
package instead of @ic-reactor/react.
import { defineConfig } from "vite"import react from "@vitejs/plugin-react"import { icReactor } from "@ic-reactor/vite-plugin"
export default defineConfig({ plugins: [ react(), icReactor({ canisters: [{ name: "backend", didFile: "./backend/backend.did" }], }), ],})By default, generated files go to src/declarations/<canister>/, and the
plugin imports clientManager from ../../clients.
Relative outDir and didFile paths resolve against Vite’s resolved
config.root, not the directory you ran vite from. If you set
root: "frontend" or pass the root positionally (vite build apps/web), paths
are relative to that directory. Note that --config on its own only selects the
config file — it does not change the root.
For each canister, generation produces:
declarations/<did-basename>.js,.d.ts, and a.didcopyindex.generated.ts: managed implementation regenerated on every runindex.ts: stable entry wrapper that re-exports fromindex.generated.ts
With the default target: "react", index.generated.ts exports the reactor
plus hooks named after the canister — for a canister named backend:
useBackendQuery, useBackendSuspenseQuery, useBackendInfiniteQuery,
useBackendSuspenseInfiniteQuery, useBackendMutation, and
useBackendMethod.
Plugin Options
Section titled “Plugin Options”| Option | Type | Default | Description |
|---|---|---|---|
canisters |
CanisterConfig[] |
— | Canister configurations (required). |
outDir |
string |
"src/declarations" |
Base output directory for generated files. |
clientManagerPath |
string |
"../../clients" |
Default client manager import path (relative from generated files). |
target |
"react" | "core" |
"react" |
Default generated runtime target. |
injectEnvironment |
boolean |
true |
Inject ic_env cookie and proxy during vite dev. |
failOnError |
boolean |
true on vite build, false on vite dev |
Abort the Vite run when a canister fails to generate. |
Per-canister options
Section titled “Per-canister options”| Option | Type | Description |
|---|---|---|
name |
string |
Canister name (required). |
didFile |
string |
Path to the .did file (required). |
mode |
string |
Reactor class: Reactor, DisplayReactor (default), CandidReactor, CandidDisplayReactor, MetadataDisplayReactor. |
outDir |
string |
Override output directory for this canister. |
clientManagerPath |
string |
Override client manager path for this canister. |
target |
string |
Override runtime target for this canister. |
canisterId |
string |
Fixed canister ID (overrides auto-detected value during local dev). |
Reactor Mode
Section titled “Reactor Mode”Set mode per canister to choose the generated reactor class:
icReactor({ canisters: [ { name: "backend", didFile: "./backend/backend.did" }, { name: "workflow_engine", didFile: "./workflow/workflow_engine.did", mode: "Reactor", }, ],})Supported modes:
ReactorDisplayReactorCandidReactorCandidDisplayReactorMetadataDisplayReactor
Set target to control whether generated files include React hooks:
react(default): generates the reactor plus bound React hookscore: generates only the typed reactor exports with no React dependency
Local Development
Section titled “Local Development”When injectEnvironment is enabled during vite dev, the plugin tries to read
local network details from the icp CLI, then:
- resolves canister IDs (including
internet_identity, which is added automatically if not already in your canister list) - sets the
ic_envcookie - proxies
/apito the local replica
If icp CLI environment detection is unavailable, the plugin still falls back
to proxying /api to http://127.0.0.1:4943, but it skips cookie injection.
If you provide canisterId in the plugin config, that fixed ID overrides the
auto-detected development value for that canister.
Set the ICP_ENVIRONMENT environment variable to target a non-default network
(defaults to "local").
.did File Changes
Section titled “.did File Changes”When a watched .did file changes, the plugin:
- regenerates declarations
- regenerates
index.generated.ts - preserves custom
index.tsfiles, while updating the default wrapper or migrating older generated entrypoints to the wrapper model - triggers a full browser reload
A generation failure aborts vite build by default — a build that silently
ships the bindings from the last successful run is worse than no build. Under
vite dev the default is the opposite, because the dev server has to survive
the broken intermediate states of a .did being edited; there the failure is
reported to the terminal and to the browser error overlay instead. Set
failOnError explicitly to override either default.