A production-ready blog template built with TanStack Start, deco.cx CMS, and Tailwind CSS v4. Supports server-side rendering, reading progress, search, categories, authors, and a magazine-style layout.
- Magazine layout — hero cover story, duo feature grid, and article feed on the home page
- Full-text search — server-side filtered search with highlighted matches
- Categories & Authors — filtered listing pages with paginated results
- Reading progress bar — visible on individual post pages
- Hero scroll header — transparent header transitions to white/blur on scroll over post cover images
- Responsive — mobile-first with a slide-out drawer menu
- CMS-powered — all content is managed via
.deco/blocks/JSON files and the deco.cx admin
- Bun (recommended) or Node.js 20+
bun install
bun run devOpen http://localhost:3000.
bun run build
bun run startsrc/
sections/Blog/ # Blog UI sections (BlogHome, BlogHeader, BlogSearch, …) — markup only
sections/Blog/Post/ # Custom post content blocks (site/sections/Blog/Post/*)
sections/Seo/ # SeoBlogAuthor (post / topic SEO use the app defaults: blog/sections/Seo/*)
sdk/blog/ # Rendering logic shared by the sections:
# blocks.tsx content block registry (default × custom) + renderer
# toc.ts table of contents / heading anchors
# jsonLd.ts schema.org builders (on top of @decocms/apps-blog)
# siteConfig.ts site identity from site.json + the blog app config
# loader.ts shared section-loader context
# format.ts, scripts.ts
components/blog/ # Shared UI pieces (AuthorAvatar)
loaders/ # Site loaders (site/loaders/BlogpostList → BlogPost[], filter by category/author)
apps/deco/blog.ts # Bridge to @decocms/apps-blog (exposes the app's props to the CMS)
setup.ts # CMS bootstrap — sections, apps, loaders
.deco/blocks/ # CMS content (posts, categories, authors, pages, app config)
.deco/*.gen.* # Generated by `bun run generate`
The blog runs on @decocms/apps-blog.
Its configuration lives in .deco/blocks/deco-blog.json: pageSlug,
categorySlug, canonicalBaseUrl (origin used for canonicals and JSON-LD),
publisher and seo.
post.sections accepts two families of blocks, distinguished by __resolveType:
| Family | __resolveType |
Rendered by |
|---|---|---|
| default | blog/sections/blocks/<Name>.tsx |
the app's component (@decocms/apps-blog) |
| custom | site/sections/Blog/Post/<Name>.tsx |
this template (src/sections/Blog/Post/) |
The mapping lives in src/sdk/blog/blocks.tsx. To add a custom block, create it in
src/sections/Blog/Post/ and register it in CUSTOM_BLOCKS.
Create a file in .deco/blocks/collections%2Fblog%2Fposts/your-post.json:
{
"name": "collections/blog/posts/your-post",
"__resolveType": "blog/loaders/Blogpost.ts",
"post": {
"title": "Your Post Title",
"slug": "your-post",
"date": "2025-01-01",
"excerpt": "Short description…",
"image": "https://images.unsplash.com/photo-…?w=1280&h=720&fit=crop&q=80",
"authors": [{ "name": "Author Name", "email": "author@example.com" }],
"categories": [{ "name": "Engineering", "slug": "engineering" }],
"sections": [
{ "__resolveType": "site/sections/Blog/Post/Heading.tsx", "level": "2", "text": "Intro" },
{ "__resolveType": "site/sections/Blog/Post/Paragraph.tsx", "html": "<p>…</p>" }
]
}
}Then run bun run generate (the dev server picks up changes automatically).
Follow the same pattern in:
.deco/blocks/collections%2Fblog%2Fcategories/.deco/blocks/collections%2Fblog%2Fauthors/
This template is pre-configured for deco.cx hosting:
git push origin mainThe production site is available at https://blog-tanstack.deco.site.