@blogree/nextjs-adapter
v1.0.1
Published
Official Next.js adapter for Blogree — pull posts and handle ISR revalidation
Downloads
30
Maintainers
Readme
@blogree/nextjs-adapter
The official Next.js adapter for Blogree. Blogree is an AI-powered content engine that helps you generate thousands of SEO-optimized articles and sync them directly to your website. Connect your website to your Blogree workspace in minutes. It will automatically finds the gaps in your content and generates high-quality intent driven articles to fill those gaps. Fetch your blog posts, handle automatic caching (ISR), and set up secure webhooks with almost zero configuration.
🚀 5-Minute Integration Guide
If you just want to get your blog up and running quickly, follow these steps. The code below is designed so you can simply copy and paste it into your project.
Step 1: Install the package
Installation
npm install @blogree/nextjs-adapterOr with yarn:
yarn add @blogree/nextjs-adapterOr with pnpm:
pnpm add @blogree/nextjs-adapterStep 2: Add your Environment Variables
- Log in to your Blogree Dashboard
- Navigate to Sites, and add your website there
- Copy:
- Pull API Key (for fetching posts)
- Webhook Secret (for signature verification)
- Add them to your
.env.localfile:
BLOGREE_API_KEY=your_pull_api_key
BLOGREE_WEBHOOK_SECRET=your_webhook_secretStep 3: Fetch and Display Posts
We provide a simple helper function getBlogreePosts to fetch your content. Here is a perfect boilerplate for your core blog page using the modern Next.js App Router:
// app/blog/page.tsx
import { getBlogreePosts } from '@blogree/nextjs-adapter';
import Link from 'next/link';
export default async function BlogPage() {
// 1. Fetch your posts from Blogree
const posts = await getBlogreePosts({
apiKey: process.env.BLOGREE_API_KEY!,
});
// 2. Render them to the screen
return (
<div style={{ maxWidth: '800px', margin: '0 auto', padding: '2rem' }}>
<h1>My Blog</h1>
{posts.map((post) => (
<article key={post.id} style={{ marginBottom: '2rem' }}>
<h2>{post.title}</h2>
<p>{post.excerpt}</p>
<Link href={`/blog/${post.slug}`}>
<span style={{ color: 'blue', textDecoration: 'underline' }}>Read more</span>
</Link>
</article>
))}
</div>
);
}Step 4: Show a Single Post
When a user clicks "Read more", they need to go to a dedicated page that displays the content of your post. We use the helper function getBlogreePost for this.
// app/blog/[slug]/page.tsx
import { getBlogreePost } from '@blogree/nextjs-adapter';
import { notFound } from 'next/navigation';
export default async function BlogPostPage({ params }: { params: { slug: string } }) {
// 1. Fetch a single post based on the URL parameter (slug)
const post = await getBlogreePost(params.slug, {
apiKey: process.env.BLOGREE_API_KEY!,
});
// 2. Show a graceful 404 error if someone types a bad URL structure
if (!post) {
notFound();
}
// 3. Render the post HTML
return (
<article style={{ maxWidth: '800px', margin: '0 auto', padding: '2rem' }}>
<h1>{post.title}</h1>
<time>{new Date(post.published_at).toLocaleDateString()}</time>
<div
style={{ marginTop: '2rem' }}
dangerouslySetInnerHTML={{ __html: post.body.html }}
/>
</article>
);
}Step 5: Setup Auto-Updating (Zero-Config Webhooks)
By default, Next.js caches your pages so they load blazingly fast. But when you write a new post in the Blogree dashboard, Next.js needs to know about it.
We provide a zero-config webhook handler that securely validates the request and automatically clears the proper cache tags for you when you hit "Publish".
First, create an API Route in Next.js:
// app/api/blogree/route.ts
import { createWebhookHandler } from '@blogree/nextjs-adapter';
// It really is this simple!
export const POST = createWebhookHandler({
apiKey: process.env.BLOGREE_API_KEY!,
webhookSecret: process.env.BLOGREE_WEBHOOK_SECRET!,
});Next, connect it to your Blogree account:
Go to your Blogree Dashboard > Settings > Webhooks and add your live URL (e.g., https://yourwebsite.com/api/blogree). Select all post events.
🎉 That's it! You've successfully integrated a fully-featured, auto-updating, SEO-friendly blog.
Types
If you are strictly typing your components, import our standard types:
import type { BlogreePost, WebhookPayload, BlogreeConfig } from '@blogree/nextjs-adapter';
// Excerpt of a post payload...
interface BlogreePost {
id: string;
slug: string;
title: string;
excerpt: string | null;
body: {
html: string;
markdown: string;
};
meta: {
title: string | null;
description: string | null;
og_image: string | null;
};
tags: string[];
published_at: string;
status: string;
}Advanced Client Class
Instead of the helper functions from Step 3, if your app is more advanced, you can instantiate our BlogreeClient class once and reuse it across files. Notice that apiUrl is completely optional for local development overrides!
import { BlogreeClient } from '@blogree/nextjs-adapter';
const client = new BlogreeClient({
apiKey: process.env.BLOGREE_API_KEY!,
// apiUrl: 'http://localhost:3000' // Override for local testing only
});
// Use it anywhere:
const posts = await client.getPosts({ limit: 10, page: 1, tag: 'technology' });
const post = await client.getPost('my-post-slug');If you are using the older Next.js pages/ directory instead of the app/ router, use our dedicated pages router handler. Manual revalidation requires providing paths.
Webhook Handler for Pages Router:
// pages/api/blogree/webhooks.ts
import { createPagesWebhookHandler } from '@blogree/nextjs-adapter';
export default createPagesWebhookHandler(
{
apiKey: process.env.BLOGREE_API_KEY!,
webhookSecret: process.env.BLOGREE_WEBHOOK_SECRET!,
},
async (payload, res) => {
// Manual ISR revalidation
await res.revalidate('/blog');
await res.revalidate(`/blog/${payload.post.slug}`);
}
);- "Posts aren't appearing on my live production site."
Make sure you have set the environment variables in your hosting provider's dashboard (like Vercel or Netlify), not just locally in
.env.local. - "Webhooks are failing or returning Unauthorized error 401."
Double check that your
BLOGREE_WEBHOOK_SECRETmatches exactly what is running in your Blogree dashboard. The adapter strictly verifies the HMAC-SHA256 signature to protect your site. - "TypeScript errors with next/cache"
Ensure your
tsconfig.jsonincludes the correct libs:"lib": ["ES2020", "DOM", "DOM.Iterable"]
Still stuck? View Documentation • Report an Issue
