--- 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: ## Serve the API Create a helper file to instantiate the bknd instance and retrieve the API: ```ts app/bknd.ts import { type ReactRouterBkndConfig, getApp as getBkndApp } from "bknd/adapter/react-router"; const config = { connection: { url: "file:data.db" } } as const satisfies ReactRouterBkndConfig; export async function getApp(args?: { request: Request }) { return await getBkndApp(config, args); } 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(args); 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)}
); } ```