From c3198394de10c2cb4167175648eec3cbd543d2d3 Mon Sep 17 00:00:00 2001 From: Shishant Biswas Date: Thu, 12 Feb 2026 21:03:50 +0530 Subject: [PATCH] docs: add tanstack start integration guide --- .../integration/(frameworks)/meta.json | 9 +- .../integration/(frameworks)/nextjs.mdx | 2 +- .../(frameworks)/tanstack-start.mdx | 291 ++++++++++++++++++ .../integration/introduction.mdx | 6 + docs/content/docs/(documentation)/start.mdx | 6 + .../tanstack-start/src/routes/admin.$.tsx | 2 +- 6 files changed, 313 insertions(+), 3 deletions(-) create mode 100644 docs/content/docs/(documentation)/integration/(frameworks)/tanstack-start.mdx diff --git a/docs/content/docs/(documentation)/integration/(frameworks)/meta.json b/docs/content/docs/(documentation)/integration/(frameworks)/meta.json index 6fb7bfc..5cc7900 100644 --- a/docs/content/docs/(documentation)/integration/(frameworks)/meta.json +++ b/docs/content/docs/(documentation)/integration/(frameworks)/meta.json @@ -1,3 +1,10 @@ { - "pages": ["nextjs", "react-router", "astro", "sveltekit", "vite"] + "pages": [ + "nextjs", + "react-router", + "astro", + "sveltekit", + "tanstack-start", + "vite" + ] } diff --git a/docs/content/docs/(documentation)/integration/(frameworks)/nextjs.mdx b/docs/content/docs/(documentation)/integration/(frameworks)/nextjs.mdx index b31deb9..c6b8c0b 100644 --- a/docs/content/docs/(documentation)/integration/(frameworks)/nextjs.mdx +++ b/docs/content/docs/(documentation)/integration/(frameworks)/nextjs.mdx @@ -71,7 +71,7 @@ export type NextjsBkndConfig = 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: +Create a helper file to instantiate the bknd instance and retrieve the API, importing the configuration from the `bknd.config.ts` file: ```ts title="src/bknd.ts" import { diff --git a/docs/content/docs/(documentation)/integration/(frameworks)/tanstack-start.mdx b/docs/content/docs/(documentation)/integration/(frameworks)/tanstack-start.mdx new file mode 100644 index 0000000..f34b599 --- /dev/null +++ b/docs/content/docs/(documentation)/integration/(frameworks)/tanstack-start.mdx @@ -0,0 +1,291 @@ +--- +title: "Tanstack Start" +description: "Run bknd inside Tanstack Start" +tags: ["documentation"] +--- + +## Installation + +To get started with Tanstack Start and bknd, create a new Tanstack Start project by following the [official guide](https://tanstack.com/start/latest/docs/framework/react/getting-started#start-a-new-project-from-scratch), and then install bknd as a dependency: + + + +```bash tab="npm" +npm install bknd +``` + +```bash tab="pnpm" +pnpm install bknd +``` + +```bash tab="yarn" +yarn add bknd +``` + +```bash tab="bun" +bun add bknd +``` + + + +## 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: + +```typescript title="bknd.config.ts" +import { type TanstackStartConfig } from "bknd/adapter/tanstack-start"; +import { em, entity, text, boolean } from "bknd"; + +const schema = em({ + todos: entity("todos", { + title: text(), + done: boolean(), + }), +}); + +export default { + connection: { + url: "file:data.db", + }, + config: { + data: schema.toJSON(), + auth: { + enabled: true, + jwt: { + secret: "random_gibberish_please_change_this", + // use something like `openssl rand -hex 32` for production + }, + }, + }, + options: { + // the seed option is only executed if the database was empty + seed: async (ctx) => { + // create some entries + await ctx.em.mutator("todos").insertMany([ + { title: "Learn bknd", done: true }, + { title: "Build something cool", done: false }, + ]); + + // and create a user + await ctx.app.module.auth.createUser({ + email: "test@bknd.io", + password: "12345678", + }); + }, + }, +} satisfies TanstackStartConfig; +``` + +For more information about the connection object, refer to the [Database](/usage/database) guide. + + +See [bknd.config.ts](/extending/config) for more information on how to configure bknd. The `TanstackStartConfig` type extends the base config type with the following properties: + +```typescript +export type TanstackStartConfig = FrameworkBkndConfig; +``` + +## Serve the API + +The Tanstack Start adapter uses Tanstack Start's hooks mechanism to handle API requests. Create a `/src/routes/api.$.ts` file: + +```typescript title="/src/routes/api.$.ts" +import { createFileRoute } from "@tanstack/react-router"; +import config from "../../bknd.config"; +import { serve } from "bknd/adapter/tanstack-start"; + +const handler = serve(config); + +export const Route = createFileRoute("/api/$")({ + server: { + handlers: { + ANY: async ({ request }) => await handler(request), + }, + }, +}); +``` + +Create a helper file to instantiate the bknd instance and retrieve the API, importing the configuration from the `bknd.config.ts` file: + +```ts title="src/bknd.ts" +import config from "../bknd.config"; +import { getApp } from "bknd/adapter/tanstack-start"; + +export async function getApi({ + headers, + verify, +}: { + verify?: boolean; + headers?: Headers; +}) { + const app = await getApp(config, process.env); + + if (verify) { + const api = app.getApi({ headers }); + await api.verifyAuth(); + return api; + } + + return app.getApi(); +}; +``` + + + The adapter uses `process.env` to access environment variables, this works because Tanstack Start uses Nitro underneath and it will use polyfills for `process.env` making it platform/runtime agnostic. + + +## Enabling the Admin UI + +Create a page at /src/routes/admin.$.tsx: + +```typescript title="/src/routes/admin.$.tsx" +import { createFileRoute } from "@tanstack/react-router"; +import { useAuth } from "bknd/client"; +import "bknd/dist/styles.css"; +import { Admin } from "bknd/ui"; + +export const Route = createFileRoute("/admin/$")({ + ssr: false, // [!code highlight] "data-only" works too + component: RouteComponent, +}); + +function RouteComponent() { + const { user } = useAuth(); + return ( + + ); +}; +``` + + + Admin routes are expected to run on the client not using `ssr: false` will cause errors like `✘ [ERROR] No matching export in "node_modules/json-schema-library/dist/index.mjs" for import "Draft2019"` and production build might fail because of this + + + +## Example usage of the API + +You can use the `getApp` function to access the bknd API in your app: +These are a few examples how you can validate user and handle server-side requests using `createServerFn`. + +```typescript title="src/routes/index.tsx" +import { createFileRoute } from "@tanstack/react-router"; +import { getApi } from "@/bknd"; +import { createServerFn } from "@tanstack/react-start"; + +export const getTodo = createServerFn() + .handler(async () => { + const api = await getApi({}); + const limit = 5; + const todos = await api.data.readMany("todos", { limit, sort: "-id" }); + return { todos }; + }); + +export const Route = createFileRoute("/")({ + ssr: false, + component: App, + loader: async () => { + return await getTodo(); + }, +}); + +function App() { + const { todos } = Route.useLoaderData(); + + return ( +
+

Todos

+
    + {todos.map((todo) => ( +
  • {todo.title}
  • + ))} +
+
+ ); +} +``` + + + +### Using authentication + +To use authentication in your app, pass the request headers to the API: + +```typescript title="src/routes/user.tsx" +import { getApi } from "@/bknd"; +import { createServerFn } from "@tanstack/react-start"; +import { Link } from "@tanstack/react-router"; +import { createFileRoute } from "@tanstack/react-router"; +import { getRequest } from "@tanstack/react-start/server"; + +export const getUser = createServerFn() + .handler(async () => { + const request = getRequest(); + const api = await getApi({ verify: true, headers: request.headers }); + const user = api.getUser(); + return { user }; + }); + +export const Route = createFileRoute("/user")({ + component: RouteComponent, + loader: async () => { + return { user: await getUser() }; + }, +}); + +function RouteComponent() { + const { user } = Route.useLoaderData(); + return ( +
+ {user ? ( + <> + Logged in as {user.email}.{" "} + + Logout + + + ) : ( +
+

+ Not logged in. + + Login + +

+

+ Sign in with: + + test@bknd.io + + / + + 12345678 + +

+
+ )} +
+ ) +} +``` + +Check the [Tanstack Start repository example](https://github.com/bknd-io/bknd/tree/main/examples/tanstack-start) for more implementation details. diff --git a/docs/content/docs/(documentation)/integration/introduction.mdx b/docs/content/docs/(documentation)/integration/introduction.mdx index 7119efd..6b94374 100644 --- a/docs/content/docs/(documentation)/integration/introduction.mdx +++ b/docs/content/docs/(documentation)/integration/introduction.mdx @@ -33,6 +33,12 @@ bknd seamlessly integrates with popular frameworks, allowing you to use what you href="/integration/sveltekit" /> +} + title="Tanstack Start" + href="/integration/tanstack-start" +/> + Create a new issue to request a guide for your framework. diff --git a/docs/content/docs/(documentation)/start.mdx b/docs/content/docs/(documentation)/start.mdx index 5a7a937..744588d 100644 --- a/docs/content/docs/(documentation)/start.mdx +++ b/docs/content/docs/(documentation)/start.mdx @@ -150,6 +150,12 @@ Pick your framework or runtime to get started. href="/integration/sveltekit" /> +} + title="Tanstack Start" + href="/integration/tanstack-start" +/> + } title="AWS Lambda" diff --git a/examples/tanstack-start/src/routes/admin.$.tsx b/examples/tanstack-start/src/routes/admin.$.tsx index facf57b..6e2971f 100644 --- a/examples/tanstack-start/src/routes/admin.$.tsx +++ b/examples/tanstack-start/src/routes/admin.$.tsx @@ -4,7 +4,7 @@ import "bknd/dist/styles.css"; import { Admin } from "bknd/ui"; export const Route = createFileRoute("/admin/$")({ - ssr: false, + ssr: false, // "data-only" works too component: RouteComponent, });