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 setup | Use |
|---|---|
| Document style | safeAreaStyle(nativeContext, config.mode) |
| Offline registration | registerOffline({ mode: config.mode, ... }) |
| Other API requests | createRadicalFetch(config) |
| Build outputs | Keep Start's dist/client, _shell.html, and Vite base / |
Run the shell
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 4173Set 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.