You also need to make sure to set the output to server in your Astro config:
// astro.config.mjsimport { defineConfig } from "astro/config";import react from "@astrojs/react";export default defineConfig({ output: "server", integrations: [react()],});
If you don't want to use React with Astro, there is also an option to serve
the bknd Admin UI statically using Astro's middleware. In case you're
interested in this, feel free to reach out in
Discord or open an issue on
GitHub.
When run with Node.js, a version of 22 (LTS) or higher is required. Please
verify your version by running node -v, and
upgrade 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.
bknd.config.ts
import type { AstroBkndConfig } from "bknd/adapter/astro";export default { connection: { url: "file:data.db", },} satisfies AstroBkndConfig;
See bknd.config.ts for more information on how to configure bknd. The AstroBkndConfig type extends the BkndConfig type with the following additional properties:
type AstroEnv = NodeJS.ProcessEnv;export type AstroBkndConfig<Env = AstroEnv> = FrameworkBkndConfig<Env>;
Create a helper file to instantiate the bknd instance and retrieve the API, importing the configurationfrom the bknd.config.ts file:
src/bknd.ts
import type { AstroGlobal } from "astro";import { getApp as getBkndApp } from "bknd/adapter/astro";import config from "../bknd.config";export { config };export async function getApp() { return await getBkndApp(config);}export async function getApi( astro: AstroGlobal, opts?: { mode: "static" } | { mode?: "dynamic"; verify?: boolean },) { const app = await getApp(); if (opts?.mode !== "static" && opts?.verify) { const api = app.getApi({ headers: astro.request.headers }); await api.verifyAuth(); return api; } return app.getApi();}
Create a new catch-all route at src/pages/api/[...api].ts.
src/pages/api/[...api].ts
import { serve } from "bknd/adapter/astro";export const prerender = false;export const ALL = serve({ connection: { // location of your local Astro DB // make sure to use a remote URL in production url: "file:.astro/content.db", },});
For more information about the connection object, refer to the Database guide. In the
special case of astro, you may also use your Astro DB credentials since it's also using LibSQL
under the hood. Refer to the Astro DB documentation for more information.
You use the API in both static and SSR pages. Just note that on static pages, authentication
might not work as expected, because Cookies are not available in the static context.
Here is an example of using the API in static context:
---import { getApi } from "bknd/adapter/astro";const api = await getApi(Astro);const { data } = await api.data.readMany("todos");---<ul> {data.map((todo) => ( <li>{todo.title}</li> ))}</ul>
On SSR pages, you can also access the authenticated user:
---import { getApi } from "bknd/adapter/astro";const api = await getApi(Astro, { mode: "dynamic" });const user = api.getUser();const { data } = await api.data.readMany("todos");export const prerender = false;---{user ? <p>Logged in as <b>{user.email}</b>.</p> : <p>Not authenticated.</p>}<ul> {data.map((todo) => ( <li>{todo.title}</li> ))}</ul>