Better Blog

API routes

Expose CRUD endpoints and use the default API-backed provider

If you prefer not to ship a client-side BlogDataProvider, Better Blog can expose API endpoints and consume them via a default API-backed provider.

1) Mount the API router

Can be served by any web standard compatible server (like Bun, node, nextjs, sveltekit, etc...)

Create app/api/posts/[...all]/route.ts:

import { createBlogApiRouter } from "better-blog/server/api"
import { createDemoMemoryDBProvider } from "better-blog"

// simple in-memory provider for demo purposes, replace with your own provider
const provider = createDemoMemoryDBProvider()

const { handler } = createBlogApiRouter(provider, {
    openapi: {
        disabled: false,
    },
  });
  
  export const GET = handler;
  export const POST = handler;
  export const PUT = handler;
  export const DELETE = handler;

Or with TanStack Start, create src/routes/api/posts/$.ts:

import { createServerFileRoute } from "@tanstack/react-start/server"
import { createBlogApiRouter } from "better-blog/server/api"
import { createDemoMemoryDBProvider } from "better-blog"

const provider = createDemoMemoryDBProvider()

const { handler } = createBlogApiRouter(provider, {
    basePath: '/api/posts', // must match your api route path
    openapi: {
        disabled: false,
    },
  });


export const ServerRoute = createServerFileRoute("/api/posts/$").methods({
    GET: async ({ request }) => {
        return handler(request)
      },
      POST: async ({ request }) => {
        return handler(request)
      },
      PUT: async ({ request }) => {
        return handler(request)
      },
      DELETE: async ({ request }) => {
        return handler(request)
      },
  })

Endpoints exposed:

  • GET /api/posts/posts – list (supports slug, tag, offset, limit, query, published, locale)
  • GET /api/posts/posts/:slug – fetch one (supports locale via query)
  • POST /api/posts/posts – create
  • PUT /api/posts/posts/:slug – update
  • DELETE /api/posts/posts/:slug – delete

Locale support

  • The API supports a locale query param for both list and detail routes.
  • On the client, the API-backed provider is wired through BetterBlogContextProvider (not used standalone).
  • You can set a provider-wide defaultLocale and optionally override per call via the context’s clientConfig.

Usage with context:

import { BetterBlogContextProvider, useBetterBlogContext } from "better-blog/client";
import { createApiBlogProvider } from "better-blog/core/providers/api-provider";

// Provide API-backed client with a provider-wide default locale
<BetterBlogContextProvider
  clientConfig={createApiBlogProvider({ baseURL: "/api/posts", defaultLocale: "en" })}
>
  {children}
</BetterBlogContextProvider>