Core concepts
How Better Blog is structured and key APIs
Package structure
better-blog
: types, schemas, utilities, and memory DB helpersbetter-blog/queries
: query helpers (getOrCreateQueryClient
, query keys)better-blog/hooks
: React hooks (client)better-blog/client
:BlogPageRouter
and page components (client-only)better-blog/context
:BlogProvider
, context and UI typesbetter-blog/router
: pluggable routes powered by @olliethedev/yarbetter-blog/server/pages
: SSR/SSG adapter (createBlogServerAdapter
)better-blog/api
: API router (createBlogApiRouter
)better-blog/sitemap
: sitemap generation (createBlogSitemap
)better-blog/providers/sql
: SQL provider exportsbetter-blog/providers/prisma
: Prisma provider exportsbetter-blog/providers/drizzle
: Drizzle provider exportsbetter-blog/providers/memory
: In-memory demo provider
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>
}
Router
Better Blog uses @olliethedev/yar for its routing layer.
Better Blog ships with pre-configured routes:
/
- Home (list of posts)/new
- Create new post/drafts
- Draft posts/:slug
- View post by slug/:slug/edit
- Edit post/tag/:tag
- Posts by tag
Architecture
- Pluggable, composable routes powered by yar
- Schema-driven data with 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