Radical
How-to guides

Switch to bundled mode

Package the UI while keeping server functions on your API origin.

See the delivery flow and authentication constraints.

Configure delivery

Pass this config to both tanstackStart(tanstackStartOptions(config)) and radical(config) from @akshatowo/radical/tanstack-start:

const config = {
  appId: "dev.example.app",
  mode: "bundled",
  origin: "https://api.example.com",
} satisfies RadicalConfig;

Configure Start

Set src/start.ts:

import { createStart } from "@tanstack/react-start";
import { createRadicalFetch } from "@akshatowo/radical/client";
import { createRadicalRequestMiddleware } from "@akshatowo/radical/tanstack-start-server";
import { config } from "virtual:radical/config";

export const startInstance = createStart(() => ({
  defaultSsr: config.mode !== "bundled",
  requestMiddleware: [...createRadicalRequestMiddleware()],
  serverFns: { fetch: createRadicalFetch(config) },
}));

Wrap the API

Keep the explicit bundled-request wrapper in src/server.ts:

import {
  createStartHandler,
  defaultStreamHandler,
} from "@tanstack/react-start/server";
import {
  offlineHandler,
  withBundledRequests,
} from "@akshatowo/radical/tanstack-start-server";

export default {
  fetch: withBundledRequests(
    createStartHandler(offlineHandler(defaultStreamHandler))
  ),
};

Configure the root

Apply the complete root setup for each mode:

// Root loader:
Effect.runPromise(localNativeContext());
// Route component:
<ClientOnly>
  <Outlet />
</ClientOnly>;
// Mount effect:
Effect.runSync(mountNativeContext());

Keep startup loaders independent of unavailable APIs.

Shared setupUse
Document stylesafeAreaStyle(nativeContext, config.mode)
Offline registrationregisterOffline({ mode: config.mode, ... })
Other API requestscreateRadicalFetch(config)
Build outputsKeep Start's dist/client, _shell.html, and Vite base /

Run the shell

Regenerate and launch.

You see the packaged UI without fetching its initial document from the API.

For a local API, build, then run from the app directory:

pnpm exec vp preview --host 0.0.0.0 --port 4173

Set origin to a device-reachable address.

Custom Vite CORS must use cors: false or an origin callback returning false for both bundled origins. Static lists can consume preflights before withBundledRequests.

On this page