Build an AI-powered blog for your NextJS app

Learn how to Build an AI-powered blog for your NextJS app. Generate SEO optimized blogs daily fully automatically. Grow to rank #1 on search engines.Jul 6, 2025Build an AI-powered blog for your NextJS app

TL;DR

Want to add a blog to your Next.js app, but don’t want to write every post by hand? Here’s how I plugged in NextBlog to automate content, keep things SEO-friendly, and let the robots do the heavy lifting—so I can focus on shipping features, not writing articles.

Why I Automated My Blog

I love building products, but writing blog posts? Not so much. I wanted my app to have a blog (for SEO, for users, for the “we’re alive!” signal), but I didn’t want to spend hours writing or wrangling guest posts.
That’s when I found NextBlog. It’s a tool that uses AI to generate blog content, and it has a dead-simple API. I figured: why not let it handle the writing, and just wire it up to my Next.js app?
Here’s how I did it.

Step 1: Set Up NextJS and dependencies

Create your NextJs project if you haven't already.
npx create-next-app@latest
Install react-markdown. We’ll use this to render the markdown content from NextBlog
npm install react-markdown

Step 2: Set Up NextBlog

Nextblog is sick. You can use it for free to manage your blog and create unlimited posts.
You also have the option to automatically generate and publish blogs daily as well with AI.
  • - Sign up at nextblog.ai (free trial, no credit card needed).
  • - Create a project, fill in what your app does, who it’s for, and what kind of content you want.
  • - Grab your API key from the dashboard. (Don’t share this key—treat it like a secret.)
  • Step 3: Add Your API Key to Next.js

    In your Next.js project, add these to .env.local:
    NEXTBLOG_API_KEY=your_api_key_here NEXTBLOG_PROJECT_ID=your_project_id_here
    Restart your dev server so Next.js picks up the new env vars.

    Step 4: Fetch and Render Blog Posts

    // Blog List Page (/app/blog/page.js) import Link from 'next/link'; export const metadata = { title: 'My Website Blog', description: 'Latest posts and updates.', }; // Fetch all your blog posts async function getBlogPosts() { const apiKey = process.env.NEXTBLOG_API_KEY; const projectId = process.env.NEXTBLOG_PROJECT_ID; try { const response = await fetch(`https://nextblog.ai/api/blog/${projectId}`, { headers: { 'Authorization': `Bearer ${apiKey}` }, next: { revalidate: 3600 } }); if (!response.ok) throw new Error('Failed to fetch blog posts'); const data = await response.json(); return data.blogs; } catch (err) { console.error('Error fetching blog posts:', err); return []; } } // Render the blog posts export default async function BlogList() { const blogs = await getBlogPosts(); return ( <div> <h1>Blog</h1> {blogs.map(blog => ( <article key={blog.id}> <h2>{blog.title}</h2> <p>{blog.description}</p> {blog.cover_image_url && <img src={blog.cover_image_url} alt={blog.title} />} <Link href={`/blog/${blog.slug}`}>Read more</Link> </article> ))} </div> ); }

    Step 5: Page for Single Blog Post

    // Single Blog Post Page (app/blog/[slug]/page.js) import { notFound } from 'next/navigation'; import ReactMarkdown from 'react-markdown'; // Fetch the blog post based on the pathname (slug) async function getBlogPost(slug) { const apiKey = process.env.NEXTBLOG_API_KEY; const projectId = process.env.NEXTBLOG_PROJECT_ID; try { const response = await fetch(`https://nextblog.ai/api/blog/${projectId}/${slug}`, { headers: { 'Authorization': `Bearer ${apiKey}` }, next: { revalidate: 3600 } }); if (!response.ok) throw new Error('Failed to fetch blog post'); const data = await response.json(); return data.blog; } catch (err) { console.error('Error fetching blog post:', err); return null; } } // Generate SEO optimized metadata export async function generateMetadata({ params }) { const blog = await getBlogPost(params.slug); return { title: blog?.title || 'Blog Post', description: blog?.description || '', openGraph: { title: blog?.title, description: blog?.description, images: blog?.cover_image_url, }, }; } // Render the blog post export default async function BlogPost({ params }) { const blog = await getBlogPost(params.slug); if (!blog) notFound(); return ( <article> <h1>{blog.title}</h1> <div> <time>{new Date(blog.created_at).toLocaleDateString()}</time> </div> <ReactMarkdown>{blog.markdown}</ReactMarkdown> </article> ); }

    Step 6: That’s It—Let the Robots Write

    Now, whenever NextBlog generates a new post for your project, it’ll show up in your app automatically. No rebuilds, no copy-pasting, no “I’ll write that post tomorrow” guilt.

    FAQ

    Q: Is this good for SEO?
    A: Yep. NextBlog’s posts are optimized for search engines, and you can tweak the project description to steer the AI.
    Q: Can I edit posts?
    A: You can sync with Notion and edit there, or just use the API to fetch whatever you want.
    Q: Is it free?
    A: There’s a free trial. After that, it’s paid—but honestly, it’s cheaper than hiring a writer.

    Final Thoughts

    I built this because I wanted to focus on shipping features, not writing blog posts. If you’re an indie hacker or solo dev, and you want a blog that updates itself, give NextBlog a try. It’s one less thing to worry about.
    If you have questions or want to see more advanced stuff (like caching, custom templates, or analytics), let me know in the comments!
    Happy shipping 🚀

    Grow your website traffic FAST with NextBlog

    Stop wasting your time and start growing with the best SEO automation tool.NextBlog The Ultimate SEO Automation Tool