Every content marketing strategy needs a blog. Most teams overcomplicate it with a CMS. Here's the simpler path: file-based content in your Next.js repo, with full SEO, in under an hour.
The architecture
Each post is a file — either .mdx (Markdown + JSX) or .tsx (pure React). Metadata lives in frontmatter or an exported object. A registry file indexes all posts for the hub page and sitemap.
Step by step
- Create
src/content/posts/— one file per post with metadata (title, slug, date, description, category, tags) and a body component. - Create a registry at
src/content/posts.ts— imports all posts, exportsgetAllPosts()andgetPostBySlug(). - Build the hub page at
app/blog/page.tsx— callsgetAllPosts(), renders a grid with featured post + cards. - Build the detail page at
app/blog/[slug]/page.tsx— callsgetPostBySlug(), renders the body + FAQ + related posts. - Add SEO —
generateMetadatawith canonical, BlogPosting JSON-LD, BreadcrumbList, FAQPage on posts with questions. - Add to sitemap — map
getAllPosts()to sitemap entries withdateModified. - Add RSS — route handler at
app/feed.xml/route.tsmapping posts to RSS items.
SEO checklist for blog posts
- Unique title (55–60 chars) with target keyword
- Description (150–160 chars) that reads like a scroll-stopper
- Canonical URL pointing to itself
- BlogPosting schema with datePublished, dateModified, author
- BreadcrumbList (Home → Blog → Post Title)
- FAQPage schema if the post has a FAQ section
- OG image (dynamic per-post is ideal)
- Reading time displayed
- Related posts section (same-category cross-links)
Why skip the CMS (for now)
A headless CMS adds complexity: API layer, caching strategy, webhook revalidation, content modeling, and a monthly bill. For a blog with under 50 posts published by a technical team, file-based content is faster to build, faster to load, and easier to maintain. Add a CMS when the editorial workflow demands it — not before.