Documentation Index
Fetch the complete documentation index at: https://mintlify.com/eersnington/sideffect/llms.txt
Use this file to discover all available pages before exploring further.
After Sideffect finishes discovering your workflow layers, it writes a file called sideffect-env.d.ts in your project root (or next to your Wrangler config if you pass configPath). This file uses TypeScript’s global interface augmentation to add each discovered workflow binding to both the Env and Cloudflare.Env interfaces, giving every Worker handler fully typed access to its workflow bindings without any manual type declarations.
What the generated file looks like
For a project with a single add-numbers workflow whose layer is exported as addNumbersLayer from src/workflows/add-numbers.ts, Sideffect generates:
// Generated by Sideffect. Do not edit.
import type { WorkflowLayer } from "sideffect";
import type { addNumbersLayer as __SideffectWorkflow0 } from "./src/workflows/add-numbers";
type __SideffectCloudflareWorkflow<Payload> = Workflow<Payload>;
type __SideffectWorkflowPayload<T> = T extends WorkflowLayer<infer Payload, any> ? Payload : never;
declare global {
interface Env {
ADD_NUMBERS: __SideffectCloudflareWorkflow<__SideffectWorkflowPayload<typeof __SideffectWorkflow0>>;
}
namespace Cloudflare {
interface Env {
ADD_NUMBERS: __SideffectCloudflareWorkflow<__SideffectWorkflowPayload<typeof __SideffectWorkflow0>>;
}
}
}
export {};
Each discovered workflow contributes one line to both Env blocks. The helper types __SideffectCloudflareWorkflow and __SideffectWorkflowPayload extract the payload type directly from your WorkflowLayer export so the binding’s generic parameter stays in sync with your schema without any duplication.
For projects with many workflows the file scales to list all of them:
// Generated by Sideffect. Do not edit.
import type { WorkflowLayer } from "sideffect";
import type { addNumbersLayer as __SideffectWorkflow0 } from "./src/workflows/add-numbers";
import type { billingInvoiceLayer as __SideffectWorkflow1 } from "./src/workflows/billing-invoice";
import type __SideffectWorkflow2 from "./src/workflows/image-processing";
type __SideffectCloudflareWorkflow<Payload> = Workflow<Payload>;
type __SideffectWorkflowPayload<T> = T extends WorkflowLayer<infer Payload, any> ? Payload : never;
declare global {
interface Env {
ADD_NUMBERS: __SideffectCloudflareWorkflow<__SideffectWorkflowPayload<typeof __SideffectWorkflow0>>;
BILLING_INVOICE: __SideffectCloudflareWorkflow<__SideffectWorkflowPayload<typeof __SideffectWorkflow1>>;
IMAGE_PROCESSING: __SideffectCloudflareWorkflow<__SideffectWorkflowPayload<typeof __SideffectWorkflow2>>;
}
namespace Cloudflare {
interface Env {
ADD_NUMBERS: __SideffectCloudflareWorkflow<__SideffectWorkflowPayload<typeof __SideffectWorkflow0>>;
BILLING_INVOICE: __SideffectCloudflareWorkflow<__SideffectWorkflowPayload<typeof __SideffectWorkflow1>>;
IMAGE_PROCESSING: __SideffectCloudflareWorkflow<__SideffectWorkflowPayload<typeof __SideffectWorkflow2>>;
}
}
}
export {};
Default-exported workflow layers use a default import (import type __SideffectWorkflow2 from "...") rather than a named import.
When the file is written
sideffect-env.d.ts is regenerated every time the Vite plugin runs its config hook — that is, on every vite dev start and every vite build. Do not edit the file manually; your changes will be overwritten on the next build.
If sideffect-env.d.ts is missing or stale (for example after a fresh clone or after adding a new workflow), simply start the Vite dev server (vite dev or wrangler dev) and Sideffect will regenerate it before the first compilation finishes.
Including the file in TypeScript
TypeScript must be able to see sideffect-env.d.ts for the augmented interfaces to take effect. There are two common ways to do this.
Via tsconfig.json include (recommended):
{
"include": ["src", "sideffect-env.d.ts"]
}
Via a triple-slash reference in an existing declaration file such as src/env.d.ts:
/// <reference path="../sideffect-env.d.ts" />
Either approach is equivalent; the include entry is simpler for most projects.
Using the typed binding in a Worker
Once sideffect-env.d.ts is on the TypeScript path, the env object in your Worker handlers carries the correct type for every discovered workflow. The params argument to .create() is inferred from your workflow’s payload schema:
export default {
async fetch(_req: Request, env: Env): Promise<Response> {
// env.ADD_NUMBERS is typed as Workflow<{ left: number; right: number }>
const instance = await env.ADD_NUMBERS.create({
params: { left: 2, right: 3 },
});
return Response.json({ id: instance.id });
},
};
Passing the wrong shape — for example { left: "two", right: 3 } — produces a TypeScript error at the call site without any additional type annotations needed in your Worker.
Committing or gitignoring the file
Because sideffect-env.d.ts is fully generated from your workflow source files, teams commonly add it to .gitignore and regenerate it in CI as part of the build step:
# .gitignore
sideffect-env.d.ts
In a CI pipeline the file is produced automatically the first time Vite runs, so no extra step is needed beyond your normal vite build or wrangler deploy command.
If you prefer to commit the file — for example to make pull-request diffs show the binding changes alongside workflow changes — that is equally valid. The file is deterministic given the same workflow sources, so it will not cause spurious conflicts as long as the dev server or build runs before you commit.