--- title: 'React Router' description: 'Run bknd inside React Router' --- import InstallBknd from '/snippets/install-bknd.mdx'; ## Installation To get started with React Router and bknd you can either install the package manually, and follow the descriptions below, or use the CLI starter: Create a new React Router CLI starter project by running the following command: ```sh npx bknd create -i react-router ``` Create a new React Router project by following the [official guide](https://reactrouter.com/start/framework/installation), and then install bknd as a dependency: ## Configuration When run with Node.js, a version of 22 (LTS) or higher is required. Please verify your version by running `node -v`, and [upgrade](https://nodejs.org/en/download/) if necessary. Now create a `bknd.config.ts` file in the root of your project. If you created the project using the CLI starter, this file is already created for you. ```typescript bknd.config.ts import type { ReactRouterBkndConfig } from "bknd/adapter/react-router"; export default { connection: { url: "file:data.db" }, } satisfies ReactRouterBkndConfig; ``` See [bknd.config.ts](/extending/config) for more information on how to configure bknd. The `ReactRouterBkndConfig` type extends the `BkndConfig` type with the following additional properties: ```typescript type ReactRouterEnv = NodeJS.ProcessEnv; type ReactRouterFunctionArgs = { request: Request; }; export type ReactRouterBkndConfig = FrameworkBkndConfig; ``` ## Serve the API Create a helper file to instantiate the bknd instance and retrieve the API, importing the configurationfrom the `bknd.config.ts` file: ```ts app/bknd.ts import { type ReactRouterBkndConfig, getApp as getBkndApp } from "bknd/adapter/react-router"; import config from "../bknd.config"; export { config }; // you may adjust this function depending on your runtime environment. // e.g. when deploying to cloudflare workers, you'd want the FunctionArgs to be passed in // to resolve environment variables export async function getApp() { return await getBkndApp(config, process.env as any); } export async function getApi( args?: { request: Request }, opts?: { verify?: boolean } ) { const app = await getApp(); if (opts?.verify) { const api = app.getApi({ headers: args?.request.headers }); await api.verifyAuth(); return api; } return app.getApi(); } ``` For more information about the connection object, refer to the [Database](/usage/database) guide. Create a new api splat route file at `app/routes/api.$.ts`: ```ts app/routes/api.$.ts import { getApp } from "~/bknd"; const handler = async (args: { request: Request }) => { const app = await getApp(); return app.fetch(args.request); }; export const loader = handler; export const action = handler; ``` ## Enabling the Admin UI Create a new splat route file at `app/routes/admin.$.tsx`: ```tsx app/routes/admin.$.tsx import { lazy, Suspense, useSyncExternalStore } from "react"; import { type LoaderFunctionArgs, useLoaderData } from "react-router"; import { getApi } from "~/bknd"; const Admin = lazy(() => import("bknd/ui").then((mod) => ({ default: mod.Admin }))); import "bknd/dist/styles.css"; export const loader = async (args: LoaderFunctionArgs) => { const api = await getApi(args, { verify: true }); return { user: api.getUser(), }; }; export default function AdminPage() { const { user } = useLoaderData(); // derived from https://github.com/sergiodxa/remix-utils // @ts-ignore const hydrated = useSyncExternalStore(() => {}, () => true, () => false); if (!hydrated) return null; return ( ); } ``` ## Example usage of the API You can use the `getApi` helper function we've already set up to fetch and mutate: ```tsx app/routes/_index.tsx import { useLoaderData, type LoaderFunctionArgs } from "react-router"; import { getApi } from "~/bknd"; export const loader = async (args: LoaderFunctionArgs) => { // use authentication from request const api = await getApi(args, { verify: true }); const { data } = await api.data.readMany("todos"); return { data, user: api.getUser() }; }; export default function Index() { const { data, user } = useLoaderData(); return (

Data

{JSON.stringify(data, null, 2)}

User

{JSON.stringify(user, null, 2)}
); } ```