bknd Documentation

repository·main·Indexed 25 days ago

https://github.com/bknd-io/bknd

A lightweight, modular backend system providing database management, authentication, media handling, and workflows. Built on Web Standards for universal compatibility, bknd supports multiple deployment platforms including Cloudflare Workers (via D1), Bun, and Astro. It offers flexible configuration modes, including code-only for programmatic schema definition and hybrid mode for visual Admin UI configuration during development.

Tokens
57.4K
Snippets
157
Records
340
Agent score
87%

What's inside bknd

  1. Choose a bknd operation mode

    main

    bknd supports three distinct modes of operation depending on how you want to manage configuration and data:

    • UI-only mode: Configure your backend and manage data visually using the built-in Admin UI.
    • Code-only mode: Configure your backend programmatically using a Drizzle-like API, while still using the Admin UI for data management.
    • Hybrid mode: Configure your backend visually during development, but use a read-only configuration in production environments.
  2. Understand bknd's approach to database and environment portability

    main

    bknd is designed to avoid vendor lock-in by focusing on portability across databases and environments:

    • Database Portability: bknd treats the database (targeting SQLite as the baseline) primarily as a data store and query interface. Schema enforcement and validation logic are moved to the application layer using TypeScript. This allows the same validation logic to run on both client and server and enables compatibility with other SQL or NewSQL systems (like PlanetScale).
    • Environment Portability: bknd avoids Node-specific APIs in favor of Web APIs, ensuring it can run in any JavaScript environment (including workerd for Cloudflare Workers). It can be integrated directly into a JavaScript framework for single-deployment apps, or run standalone via CLI or Docker.
  3. Automate workflows with Flows

    main
    The Flows module in bknd allows you to design and run automated workflows. You can automate tasks using various trigger types, manage complex task sequences (including loops and parallel execution), and choose between synchronous or asynchronous execution modes. Note that the Flows UI is currently in development and may not be visible in the Admin UI during the tech preview phase.
  4. Associate media with an entity

    main

    To associate media (like a cover image or a gallery) with an entity when media is enabled, follow these three steps:

    1. Add a virtual field to your entity using medium() (for a single item) or media() (for multiple items).
    2. Add the media system entity to your schema using systemEntity("media", ...).
    3. Define the relation in the em callback using polyToOne or polyToMany, specifying the mappedBy option to link the virtual field.

    Note: Relations to the media entity are polymorphic.

  5. Serve the Admin UI via remote `assetsPath`

    main

    If you cannot use local files or raw imports, you can point bknd to a remote URL containing the static assets using the adminOptions.assetsPath property within createRuntimeApp.

    import { createRuntimeApp } from "bknd/adapter";
    
    const app = await createRuntimeApp({
       connection: {
          url: "file:data.db",
       },
       adminOptions: {
          assetsPath: "https://...",
       },
    });
    
    export default {
       fetch: app.fetch,
    };
  6. Install bknd for AWS Lambda

    main

    You can set up bknd for AWS Lambda using either a CLI starter or a manual installation.

    CLI Starter

    To create a new Bun CLI starter project pre-configured for AWS, run:

    npx bknd create -i aws

    Manual Installation

    If you already have an AWS Lambda project, install bknd as a dependency using your preferred package manager:

    npm install bknd
    # or
    pnpm install bknd
    # or
    yarn add bknd
    # or
    bun add bknd
  7. Use Authentication with the bknd API

    main

    To perform authenticated requests on the server (e.g., inside a createServerFn), retrieve the current request using getRequest from @tanstack/react-start/server and pass its headers to getApi with the verify: true option. This allows you to call api.getUser() to retrieve the authenticated user.

    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}.{" "}
              <Link
                className="font-medium underline"
                to={"/api/auth/logout" as string}
              >
                Logout
              </Link>
            </>
          ) : (
            <div className="flex flex-col gap-1">
              <p>
                Not logged in.
                <Link
                  className="font-medium underline"
                  to={"/admin/auth/login" as string}
                >
                  Login
                </Link>
              </p>
              <p className="text-xs opacity-50">
                Sign in with: 
                <b><code>test@bknd.io</code></b> / 
                <b><code>12345678</code></b>
              </p>
            </div>
          )
        }
      );
    }
  8. Serve the bknd API in SvelteKit

    main

    The SvelteKit adapter uses SvelteKit's hooks mechanism to handle API requests. Create a src/hooks.server.ts file and use the serve function from bknd/adapter/sveltekit. The adapter uses $env/dynamic/private to access environment variables, making it compatible with various deployment targets like Node.js, Bun, or Cloudflare.

    import type { Handle } from "@sveltejs/kit";
    import { serve } from "bknd/adapter/sveltekit";
    import { env } from "$env/dynamic/private";
    import config from "../bknd.config";
    
    const bkndHandler = serve(config, env);
    
    export const handle: Handle = async ({ event, resolve }) => {
      // handle bknd API requests
      const pathname = event.url.pathname;
      if (pathname.startsWith("/api/")) {
        const res = await bkndHandler(event);
        if (res.status !== 404) {
          return res;
        }
      }
    
      return resolve(event);
    };
  9. Run bknd Next.js starter commands

    main

    Use the following commands from the project root to manage your local development and production builds:

    • npm install: Installs all necessary dependencies.
    • npm run dev: Starts the local development server at http://localhost:3000.
    • npm run dev:turbo: Starts a local Turso development server.
    • npm run build: Builds the project for production.
    npm install
    npm run dev
    npm run dev:turbo
    npm run build