Better Blog

Core concepts

How Better Blog is structured and key APIs

Package structure

  • better-blog: shared utilities, schemas, types and queries
  • better-blog/client: client components (BlogRouterPage, BetterBlogContextProvider, hooks)
  • better-blog/server: server adapters (e.g. createServerAdapter for SSR/SSG)
  • better-blog/server/api: API router utilities (e.g. createBlogApiRouter)

Data provider

You inject a BlogDataProvider implementation (CMS, files, API, DB):

export interface BlogDataProvider {
  getAllPosts: (filter?: {
        slug?: string
        tag?: string
        offset?: number
        limit?: number
        query?: string
        published?: boolean
        locale?: string
    }) => Promise<Post[]>
    getPostBySlug?: (slug: string, options?: { locale?: string }) => Promise<Post | null>
    createPost?: (input: PostCreateExtendedInput) => Promise<Post>
    updatePost?: (slug: string, input: PostUpdateExtendedInput) => Promise<Post>
    deletePost?: (slug: string) => Promise<void>
}

API surface (most used)

  • Utilities, Schemas, Types and Queries (better-blog)
    • shared routing utilities,
    • zod schemas
    • types
    • low level tanstack query functions
  • Server adapter (better-blog/server)
    • createServerAdapter(serverConfig: BlogDataProvider, queryClient: QueryClient){ generateStaticParams, generateMetadata, Entry }
    • createBlogApiRouter(serverConfig: BlogDataProvider, queryClient: QueryClient){ router }
  • Client (better-blog/client)
    • BetterBlogContextProvider
    • Hooks: usePosts, useCreatePost, etc...
    • Client components: BlogRouterPage etc...

Architecture (high-level)

  • Schema-driven routes and data; minimal state in components
  • Strict client/server separation via dedicated entry points

TanStack Query

Why we use it:

  • Caching + de/rehydration: Server prefetch + client hydration for SEO and zero-flash data
  • Great DX: Automatic refetching, pagination support, and easy overrides