mcpField
B
btst-integration

btst-integration

github.com/better-stack-aiDevelopment7844 installsUpdated today
Repository

About btst-integration

btst-integration is a skill that guides integration of the BTST stack into applications, from backend and client plugin setup to routes, providers, schemas, and migrations. It covers framework-specific entry points and adapter choices.

Key features

  1. 01Configure backend and client plugins
  2. 02Wire API and page routes
  3. 03Set up providers and CSS imports
  4. 04Generate database schemas
  5. 05Run Kysely migrations

Use cases

  1. 01Add BTST plugins to an application
  2. 02Connect plugin routes to a framework
  3. 03Generate schemas for a database adapter
  4. 04Prepare Kysely database migrations

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/better-stack-ai/better-stack --skill btst-integration

After installing, type/btst-integrationin Claude Code to confirm it loaded.

Bundled filesREFERENCE.md

Details

From the project README

BTST Library Integration

Quick start

  1. Install @btst/stack, @tanstack/react-query, and one @btst/adapter-*.
  2. Install and register each plugin's backend and client halves.
  3. Create lib/stack.ts → export { handler, dbSchema }.
  4. Mount handler with the framework API entry factory at /api/data/*.
  5. Add @import "@btst/stack/plugins/{plugin}/css" per plugin in your global CSS.
  6. Create lib/stack-client.tsx, lib/query-client.ts, and the /pages/* catch-all route with the framework page entry factory.
  7. Create the pages layout file with QueryClientProvider + StackProvider.
  8. Run @btst/cli generate (and migrate for Kysely).

See REFERENCE.md for full code shapes for every file.

Workflow

1) Install prerequisites and packages
  • Prereqs: shadcn/ui (CSS variables enabled), Sonner <Toaster />, Tailwind v4.
  • Install: @btst/stack, @tanstack/react-query, and one adapter:
    • @btst/adapter-prisma / @btst/adapter-drizzle / @btst/adapter-kysely / @btst/adapter-mongodb
    • @btst/adapter-memory — dev/testing only, not for production
  • Install each plugin package alongside @btst/stack (they ship inside the monorepo package).
2) Register plugins (backend + client)
  • Backend (lib/stack.ts): import {plugin}BackendPlugin from @btst/stack/plugins/{plugin}/api.
    • Pass hooks and config in the backend plugin options object (e.g. blogBackendPlugin({ hooks })).
    • Use camelCase keys for plugins that have compound names: aiChat, formBuilder, uiBuilder.
  • Client (lib/stack-client.tsx): import {plugin}ClientPlugin from @btst/stack/plugins/{plugin}/client.
    • Client definitions receive only plugin-specific options such as seo, hooks, or page components. Configure api, site, and queryClient once on createClientStack(); its resolver binds that runtime to every definition.
    • Pass incoming SSR request headers through the top-level createClientStack({ api: { headers } }) configuration.
    • Resolve one trusted API/site origin snapshot on the server and hydrate it into the provider. A managed backend may use a distinct BTST_API_URL; never reconstruct it from window.location after hydration.
3) Configure backend stack
  • Call createBackendStack({ basePath: "/api/data", plugins: { ... }, adapter: (db) => createXxxAdapter(..., db, {}), auth: serverAuth }) when application authorization is enabled.
  • Create serverAuth with createServerAuth({ authorization, getIdentity }). Omitting auth intentionally preserves permissive no-authorization compatibility; plugin labels such as AI Chat's access: "authorized" are not an enforcement boundary by themselves.
  • Export handler and dbSchema.
  • Memory adapter + Next.js: pin to globalThis to avoid two instances in the same process:
    function createAppStack() {
      return createBackendStack({ ... })
    }
    
    type AppStack = ReturnType<typeof createAppStack>
    const g = globalThis as typeof globalThis & { __btst__?: AppStack }
    export const myStack = g.__btst__ ??= createAppStack()
    export const { handler, dbSchema } = myStack
    
4) CSS — edit global stylesheet

Add one line per plugin before your Tailwind layers:

@import "@btst/stack/plugins/blog/css";
@import "@btst/stack/plugins/cms/css";
@import "@btst/stack/plugins/ai-chat/css";
/* …one per selected plugin */

Do not duplicate — the patcher and manual edits must both be idempotent.

5) Wire framework routes and client runtime
  • API route: use toNextRouteHandlers, toReactRouterHandlers, or toTanStackHandlers from the framework entry point.
  • Pages route: use createNextPage, createReactRouterPage, or createTanStackPageOptions. The factory owns route matching, loader ordering, hydration, metadata, and 404 handling.
  • Pages layout ("use client" in Next.js): wrap in QueryClientProvider then StackProvider:
    • Pass the resolved client stack with stack={clientStack}. Its top-level site.basePath must match your pages catch-all prefix.
    • router={nextRouter()} / reactRouter() / tanstackRouter() for framework-wide links, images, navigation, and refresh.
    • auth={createClientAuth({ authorization, getIdentity, loginPath })} when plugins need identity or permission presentation gates.
    • overrides={{ pluginKey: { uploadImage?, ...pluginSpecificValues } }} only for plugin-specific customization.
    • Let the resolved plugin map infer override keys and values; do not duplicate a manual provider map.
    • See REFERENCE.md for provider wiring and per-plugin override shapes.
  • ai-chat plugin only: wrap the root layout (above StackProvider) with PageAIContextProvider:
    import { PageAIContextProvider } from "@btst/stack/plugins/ai-chat/client/context"
    // root layout.tsx (not the pages layout)
    export default function RootLayout({ children }) {
      return <PageAIContextProvider>{children}</PageAIContextProvider>
    }
    
    Pages then call useRegisterPageAIContext(...) to register their AI context — see the btst-ai-context skill.
6) Generate schemas and run migrations
  • Install @btst/cli as a dev dependency.
  • Prisma: npx @btst/cli generate --config=lib/stack.ts --orm=prisma --output=schema.prisma
  • Drizzle: npx @btst/cli generate --config=lib/stack.ts --orm=drizzle --output=src/db/schema.ts
  • Kysely: npx @btst/cli generate --config=lib/stack.ts --orm=kysely --output=migrations/schema.sql --database-url=...
  • Kysely migrate: npx @btst/cli migrate --config=lib/stack.ts --database-url=...
  • Prisma/Drizzle: use native migration tooling after generate.

Validation checklist

  • stack.ts exports both handler and dbSchema.
  • Protected applications pass createServerAuth(...) to createBackendStack({ auth }); omitted auth is intentionally permissive.
  • Every plugin is registered on both backend and client sides.
  • API basePath and createBackendStack({ basePath }) match exactly.
  • API and page catch-all routes use the framework entry factories.
  • Pages layout is "use client" and wraps QueryClientProvider then StackProvider.
  • The resolved client stack's site.basePath matches the /pages catch-all route prefix.
  • Global CSS has one @import line per selected plugin.
  • /pages/* routes render expected plugin pages.
  • CLI commands run with required env vars in scope.

Gotchas

  • "use client" missing on pages layout — StackProvider uses hooks and must be client-side.
  • Wrong key casing — backend/client plugin map keys must match; compound names use camelCase (aiChat, not ai-chat).
  • Missing CSS import — plugin UI breaks silently even when data loads correctly.
  • Half-registered plugin — backend-only = routes don't exist; client-only = 404 on data calls.
  • Memory adapter + Next.js — always pin to globalThis to share one in-memory store across API and page bundles.
  • Path aliases in CLI — @btst/cli executes your config file directly; use relative imports in lib/stack.ts and its dependencies.
  • Kysely generate needs DB — pass DATABASE_URL or --database-url; use dotenv-cli for .env.local.
  • Provider services copied into plugin overrides — never add Link, Image, navigation, refresh, API paths, identity, or login values to built-in plugin overrides. Use top-level router, api, and auth.

Comments

Markdown supported