Skip to content

PATTERN Cited by 1 source

Two-phase framework integration pattern

Two-phase framework integration pattern is the reusable template for onboarding a cross-framework SDK (durable workflow, auth, telemetry, feature flags, etc.) to N JavaScript frameworks without writing N independent integrations.

The pattern separates the integration into two temporal phases with framework-specific adapters at the bridge points:

  1. Build-time phase — compile user source code into deployable handler files. Handle bundling, determine output location, apply framework-specific patches, configure hot-module replacement.
  2. Runtime phase — expose the build-time handler files as HTTP endpoints reachable by the framework's app server. Apply SDK-client transforms so user code that calls a workflow/handler gets rewritten into HTTP-client calls.

Canonical statement from Vercel's 2026-04-21 WDK post: "On the surface, integrating WDK with Next.js looks nothing like integrating it with Express or SvelteKit. They all have different bundlers, routing systems, and developer experiences. But at its core, every framework integration follows the same two-phase pattern." And closing verbatim: "The core pattern remains the same across different frameworks. Generate workflow handlers at build-time. Register those handlers as HTTP endpoints at runtime. Only the implementation details change with a few framework-level specifics."

Ingredients

  • A compiler plugin (WDK: SWC plugin) that does the build-time transform. Ideally parameterised by mode so one plugin emits multiple outputs (patterns/swc-plugin-three-mode-transform).
  • A core integration for the dominant meta-framework (WDK: Vite-based integration). Amortises per-framework cost across the ecosystem.
  • Per-framework adapter that provides the two bridges:
  • Build-time output location (for file-based-routing frameworks) OR virtual-handler injection substrate (for bare-HTTP frameworks via Nitro).
  • Runtime request-object converter (patterns/injected-request-object-converter).
  • HMR hook per-framework (patterns/vite-hotupdate-directive-triggered-rebuild for Vite-based frameworks).

Why it works

The pattern scales because:

  1. Build-time is the same transform across all frameworks — compile the same source + the same directives into the same handler artefacts. No framework-specific AST rewriting.
  2. Runtime is two bridges + a small adapter, not a fat cross-framework abstraction layer — each framework's adapter is ~a few hundred LOC, not a reimplementation of the framework's request/response surface.
  3. Framework taxonomy (concepts/file-based-routing-vs-bare-http-framework-taxonomy) bifurcates the runtime bridge into two well-defined strategies (file output, virtual-handler-injection via Nitro) rather than N unique strategies.

When to use

  • Building a cross-framework SDK that ships as user code (not a service): workflow/sveltekit, @company/auth, @platform/telemetry — anything where the SDK artefact is npm-installed.
  • When users should not have to wire endpoints manually — the SDK's handlers must just appear in the app.
  • When the SDK needs compile-time behaviour (code transform, dead-code elim, type generation) as well as runtime behaviour.

When NOT to use

  • When the SDK is purely runtime (a plain library with no compile-time behaviour and no HTTP endpoints) — the pattern's build-time phase is unused overhead.
  • When a single framework is strategic target (first release / narrow product) — premature abstraction. Integrate the target framework natively first, extract the two-phase template when the second framework arrives.
  • When the framework family is non-JS / non-Vite-adjacent — the core-Vite-integration amortisation doesn't apply.

Canonical instance

Vercel Workflow DevKit (WDK) ships this pattern for 8 frameworks as of 2026-04-21: Next.js, Nitro, SvelteKit, Astro, Express, Hono + 2 others (TanStack Start + React Router in development). Verbatim adoption datum: "Since launch, the Workflow DevKit has gained over 1,300 GitHub stars, with developers building workflows across all these frameworks. Building six additional framework integrations demonstrated how good abstractions reveal patterns. What looks like six different problems is really one problem solved six different ways."

Anti-pattern

  • Per-framework from-scratch integration — each new framework is a 10,000-LOC bespoke codebase. Works once, doesn't transfer, loses improvements. WDK's engineering insight is that this was the naive failure mode it avoided.
  • Fat cross-framework abstraction layer at runtime — trying to build a single "request shape" that abstracts over SvelteKit, Express, Next.js, etc. More code, less flexibility, slower. WDK's injected converter approach sidesteps this deliberately.

Seen in

Last updated · 476 distilled / 1,218 read