next-blog-ai
v0.3.12
Published
AI-powered blog generation and content delivery for Next.js and other frameworks
Maintainers
Readme
Next-Blog-AI
AI-powered blog generation and content delivery built exclusively for Next.js applications. Designed from the ground up to work seamlessly with Next.js App Router and Pages Router, providing optimized solutions for React Server Components, static site generation, and incremental static regeneration.
Important: Service Setup Required
Before using this package: You need to sign up and set up your blog content service at next-blog-ai.com.
This package is the client library that connects to the Next-Blog-AI service where you'll:
- Manage your account and subscription
- Configure content generation settings
- Monitor analytics and performance
- Get your API key for connecting via this package
Sign up at next-blog-ai.com to get started.
Features
- Optimized for Next.js App Router architecture
- Blog post listing and detail views
- Supports both HTML and JSON response formats
- Built-in caching mechanism with Next.js-specific optimizations and configurable TTL
- Response normalization (snake_case to camelCase)
- Automatic retries with exponential backoff
- Concurrent request deduplication
- HTML content styling with customizable CSS
- TypeScript support with comprehensive type definitions
Key Next.js Integration Points
- App Router Optimization: Built specifically for Next.js 13+ App Router architecture
- Server Components: First-class support for React Server Components
- ISR Support: Deep integration with Incremental Static Regeneration
- Metadata API: Optimized for Next.js Metadata API
- Edge Runtime: Compatible with Next.js Edge Runtime
- Static Exports: Support for
generateStaticParamsand static generation
Installation
You have two options to install Next-Blog-AI in your Next.js project:
Option 1: Automated Installation (Recommended)
Use our automated setup tool which handles everything for you:
npx create-next-blog-ai@latestThis command will:
- Install the Next-Blog-AI package automatically
- Set up the client in your project
- Configure the necessary files for blog functionality
Option 2: Manual Installation
If you prefer a manual approach, first install the package:
npm install next-blog-ai
# or
yarn add next-blog-ai
# or
pnpm add next-blog-aiThen you'll need to configure the client yourself (see the Advanced Manual Setup section below).
Advanced Manual Setup
If you prefer to set up the client manually or need more customization, follow the steps below:
For the best experience in Next.js projects, we provide a specialized Next.js client creator that simplifies integration:
// lib/next-blog-ai.ts
import { createNextBlogAIForNextJs } from 'next-blog-ai';
// Create a Next.js-optimized client with all methods ready to use with Next.js caching
export const {
client, // The base client instance
getBlogPosts, // List posts
getBlogPost, // Get single post
getBlogPostSEO, // Get post SEO
getBlogListSEO, // Get list SEO
getAllBlogSlugs, // Get all slugs
} = createNextBlogAIForNextJs(process.env.NEXT_BLOG_AI_API_KEY!);Then import and use these functions throughout your Next.js application:
// app/blog/page.tsx
import { getBlogPosts } from '@/lib/next-blog-ai';
export default async function BlogPage() {
// Using the Next.js-optimized function with default caching
const { data, error } = await getBlogPosts();
// Or override the default cache settings
const { data: freshData } = await getBlogPosts({
next: {
revalidate: 0, // Dynamic rendering for this request only
},
});
// Rest of your component...
}This approach gives you:
- Proper typing for all Next.js-specific options
- Simplified imports across your Next.js application
- Consistent caching defaults that can be overridden when needed
- Full compatibility with both App Router and Pages Router
Documentation
For comprehensive documentation, guides, and examples, please visit our official documentation site:
Our documentation includes detailed information about installation, API reference, advanced usage examples, and best practices for Next.js integration.
Fetching blog posts
// Get a list of blog posts in a Next.js Server Component
const { data, error } = await nextBlogAI.getBlogPosts({
page: 1,
perPage: 10,
format: 'json', // 'html' or 'json'
display: 'list', // 'grid' or 'list' (only applies to HTML format)
// Next.js-specific caching options
next: {
revalidate: 3600, // ISR with 1-hour revalidation
},
});
if (error) {
console.error('Error fetching blog posts:', error);
} else {
console.log('Blog posts:', data);
}Fetching a single blog post
// Get a single blog post by slug in a Next.js Server Component
const { data, error } = await nextBlogAI.getBlogPost('hello-world', {
format: 'html',
// Next.js-specific caching options
next: {
revalidate: 3600, // ISR with 1-hour revalidation
},
});
if (error) {
console.error('Error fetching blog post:', error);
} else {
console.log('Blog post:', data);
}Submitting a comment
// Submit a comment on a blog post (works great with Next.js Server Actions)
const { data, error } = await nextBlogAI.submitComment({
postId: '123',
authorName: 'John Doe',
authorEmail: '[email protected]', // Optional
content: 'Great article! Thanks for sharing.',
});
if (error) {
console.error('Error submitting comment:', error);
} else {
console.log('Comment submitted:', data);
}Next.js Server Components (App Router)
// In a Next.js Server Component (app/blog/page.tsx)
import { nextBlogAI } from '@/lib/next-blog-ai';
export default async function BlogPage() {
const { data, error } = await nextBlogAI.getBlogPosts({
next: {
revalidate: 3600, // Enable ISR and revalidate every hour
},
});
if (error) {
return <div>Error loading blog posts: {error.message}</div>;
}
if (data.format === 'html') {
return <div dangerouslySetInnerHTML={{ __html: data.content }} />;
} else {
return (
<div>
{data.posts.map((post) => (
<article key={post.id}>
<h2>{post.title}</h2>
<p>{post.excerpt}</p>
</article>
))}
</div>
);
}
}Dynamic Route for Blog Post
// In app/blog/[slug]/page.tsx
import { nextBlogAI } from '@/lib/next-blog-ai';
export default async function BlogPostPage({
params,
}: {
params: Promise<{ slug: string }>;
}) {
// Important: await the params, following Next.js App Router patterns
const { slug } = await params;
const { data, error } = await nextBlogAI.getBlogPost(slug, {
next: {
revalidate: 3600, // Enable ISR and revalidate every hour
},
});
if (error) {
return <div>Error loading blog post: {error.message}</div>;
}
return (
<>
{data.format === 'html' ? (
<>
<div dangerouslySetInnerHTML={{ __html: data.content }} />
<div dangerouslySetInnerHTML={{ __html: data.comments }} />
<div dangerouslySetInnerHTML={{ __html: data.commentForm }} />
</>
) : (
<>
<h1>{data.post.title}</h1>
<div>{data.post.content}</div>
<h2>Comments</h2>
{data.comments.map((comment) => (
<div key={comment.id}>
<strong>{comment.authorName}</strong>
<p>{comment.content}</p>
</div>
))}
{/* Your custom comment form */}
</>
)}
</>
);
}Customizing Styles
You can customize the styles for both blog content and blog listings:
import { createNextBlogAI, DEFAULT_BLOG_STYLES } from 'next-blog-ai';
// Create client with custom styles
const nextBlogAI = createNextBlogAI({
apiKey: 'your-api-key',
styles: {
blogContent: `
${DEFAULT_BLOG_STYLES}
/* Your custom overrides */
.next-blog-ai-content h1 {
color: #0070f3;
font-size: 2.5rem;
}
`,
blogList: '/* Your custom CSS for blog listings */',
},
});
// Or set styles later
nextBlogAI.setStyles({
blogContent: '/* Your custom CSS for blog posts */',
blogList: '/* Your custom CSS for blog listings */',
});Advanced Usage
Manual Cache Control
// Clear the entire cache
nextBlogAI.clearCache();
// Clear a specific item from the cache
nextBlogAI.clearCacheItem('list', { page: 1, per_page: 10 });Error Handling
const { data, error } = await nextBlogAI.getBlogPosts();
if (error) {
if (error.status === 401) {
console.error('Authentication error. Check your API key.');
} else if (error.status === 429) {
console.error('Rate limit exceeded. Please try again later.');
} else if (error.status >= 500) {
console.error('Server error. Please try again later.');
} else {
console.error(`Error: ${error.message}`);
}
}API Reference
Next.js Integration Functions
createNextBlogAIForNextJs(apiKey, defaultCacheOptions)- Create a Next.js-optimized clientgetBlogPosts(options)- Get a list of blog posts with Next.js cachinggetBlogPost(slug, options)- Get a single blog post with Next.js cachinggetBlogPostSEO(slug, options)- Fetch only SEO metadata for a post with Next.js cachinggetBlogListSEO(options)- Fetch only SEO metadata for blog list with Next.js cachinggetAllBlogSlugs(options)- Get all blog post slugs with Next.js caching (for static site generation)submitComment(data)- Submit a comment on a blog post
Next.js-Specific Options
| Option | Type | Description |
| ------------ | --------- | ------------------------------------------ |
| revalidate | number | Next.js revalidation time in seconds (ISR) |
| dynamic | boolean | Force dynamic rendering without caching |
Configuration Options
| Option | Type | Default | Description |
| ------------------------ | --------------------------------------------- | -------------- | --------------------------------------------- |
| apiKey | string | Required | API key for authentication |
| defaultFormat | 'html' \| 'json' | 'html' | Default format for content responses |
| defaultBlogListDisplay | 'grid' \| 'list' | 'grid' | Default display format for blog lists |
| defaultCacheTTL | number | 0 | Default cache TTL in seconds (0 = no caching) |
| retry | RetryOptions | See below | Configuration for request retries |
| styles | { blogContent?: string, blogList?: string } | Default styles | Custom CSS styles for HTML content |
RetryOptions
| Option | Type | Default | Description |
| --------------- | --------- | ------- | -------------------------------------------------- |
| maxRetries | number | 3 | Maximum number of retry attempts |
| initialDelay | number | 300 | Initial delay before first retry (ms) |
| backoffFactor | number | 2 | Factor by which to increase delay after each retry |
| maxDelay | number | 10000 | Maximum delay between retries (ms) |
| jitter | boolean | true | Whether to add jitter to retry delays |
License
MIT
SEO Metadata
Next-Blog-AI automatically generates SEO metadata for all blog posts at the time they are created. This metadata includes:
- SEO Title: An optimized title for search engines
- Meta Description: A compelling description that includes relevant keywords
- Keywords: Primary and related keywords relevant to the content
- Featured Image: Image data for social media sharing (Open Graph, Twitter cards)
- Structured Data: JSON-LD markup for Schema.org that helps search engines understand the content
This SEO metadata is stored in the database and returned with each blog post request, so there's no delay in generating it on-demand. The API returns this SEO metadata in both formats (HTML and JSON) as part of the response.
Using SEO Metadata
// When using the HTML format
const { data } = await getBlogPost('my-post-slug', { format: 'html' });
// Set document metadata (example with Next.js)
export const metadata: Metadata = {
title: data.seo.title,
description: data.seo.description,
keywords: data.seo.keywords.join(', '),
// Add Open Graph and Twitter metadata if a featured image is available
...(data.seo.featuredImage
? {
openGraph: {
images: [
{
url: data.seo.featuredImage.url,
width: 1200,
height: 630,
alt: data.seo.featuredImage.alt,
},
],
},
twitter: {
card: 'summary_large_image',
images: [data.seo.featuredImage.url],
},
}
: {}),
};
// Add Schema.org structured data to your page
<script
type='application/ld+json'
dangerouslySetInnerHTML={{ __html: JSON.stringify(data.seo.structuredData) }}
/>;Performance Optimizations
SEO-Only Fetching
For pages that only need SEO metadata (like in Next.js generateMetadata functions), you can use our optimized SEO-only functions:
// For blog post detail pages
export async function generateMetadata({ params }): Promise<Metadata> {
const { slug } = await params;
const { data, error } = await nextBlogAI.getBlogPostSEO(slug, {
cache: { ttl: 3600 }, // Cache for 1 hour
});
if (error || !data) {
return { title: 'Blog Post', description: 'Default description' };
}
return {
title: data.seo.title,
description: data.seo.description,
keywords: data.seo.keywords.join(', '),
};
}
// For blog list pages
export async function generateMetadata(): Promise<Metadata> {
const { data, error } = await nextBlogAI.getBlogListSEO({
cache: { ttl: 3600 }, // Cache for 1 hour
});
if (error || !data) {
return { title: 'Blog', description: 'Default description' };
}
return {
title: data.seo.title,
description: data.seo.description,
keywords: data.seo.keywords.join(', '),
};
}These optimized functions only fetch the SEO metadata without retrieving the full content, significantly improving performance and reducing bandwidth usage for metadata-only operations.
Static Site Generation (SSG)
For static site generation in Next.js, you can use the getAllBlogSlugs function to get a list of all blog post slugs:
// pages/blog/[slug].tsx (Next.js Pages Router)
import { createNextBlogAI } from 'next-blog-ai';
const nextBlogAI = createNextBlogAI({
apiKey: process.env.NEXT_BLOG_AI_API_KEY!,
});
// Get all available blog post slugs for static paths
export async function getStaticPaths() {
const { data, error } = await nextBlogAI.getAllBlogSlugs();
if (error || !data) {
// Handle error or provide fallback
return { paths: [], fallback: 'blocking' };
}
// Generate static paths from the slugs
return {
paths: data.slugs.map((slug) => ({ params: { slug } })),
fallback: 'blocking', // or false if you only want to pre-render known paths
};
}
// Get the content for each blog post
export async function getStaticProps({ params }) {
const { data, error } = await nextBlogAI.getBlogPost(params.slug);
if (error || !data) {
return { notFound: true };
}
return {
props: {
post: data,
},
// Optionally revalidate the page after a certain time
revalidate: 3600, // 1 hour
};
}
// Your component to render the blog post
function BlogPost({ post }) {
// Render the post content
}
export default BlogPost;Next.js App Router with Static Exports
For the App Router in Next.js with static exports, use the generateStaticParams function:
// app/blog/[slug]/page.tsx
import { createNextBlogAIForNextJs } from 'next-blog-ai';
const { getAllBlogSlugs, getBlogPost } = createNextBlogAIForNextJs(
process.env.NEXT_BLOG_AI_API_KEY!
);
// Generate static paths at build time
export async function generateStaticParams() {
const { data, error } = await getAllBlogSlugs();
if (error || !data) {
return [];
}
return data.slugs.map((slug) => ({ slug }));
}
// Server Component to render the blog post
export default async function BlogPostPage({
params,
}: {
params: { slug: string };
}) {
const { slug } = params;
const { data, error } = await getBlogPost(slug);
if (error || !data) {
return <div>Blog post not found</div>;
}
return (
<>
{/* Render blog post content */}
{data.format === 'html' ? (
<div dangerouslySetInnerHTML={{ __html: data.content }} />
) : (
<>
<h1>{data.post.title}</h1>
<div>{data.post.content}</div>
</>
)}
</>
);
}This approach allows you to pre-render all your blog posts at build time, improving performance and SEO.
Blog List Display Formats
Next-Blog-AI supports two display formats for blog listings when using the HTML format:
Grid View (Default)
The grid view displays blog posts in a responsive grid layout, which is ideal for blog homepages or archive pages where you want to showcase multiple posts in a compact, visually appealing format.
const { data } = await nextBlogAI.getBlogPosts({
display: 'grid', // This is the default value
});List View
The list view displays blog posts in a vertical list, with a horizontal layout for each post card. This view is ideal for readers who prefer a more traditional blog layout or when you want to emphasize the content hierarchy.
const { data } = await nextBlogAI.getBlogPosts({
display: 'list',
});You can also set the default display format when initializing the client:
const nextBlogAI = createNextBlogAI({
apiKey: 'your-api-key',
defaultBlogListDisplay: 'list', // Sets the default to list view
});Note: The display format option only applies when using the HTML format. When using the JSON format, you'll need to implement your own display logic using the returned data.
Caching Behavior
By default, Next-Blog-AI has caching disabled to ensure you always get fresh content during development. This behavior can be customized:
Enabling Caching
You can enable caching by:
// For individual requests
const { data } = await getBlogPosts({
next: {
revalidate: 3600, // Cache for 1 hour
},
});
// Or set a default when creating the client
const { getBlogPosts } = createNextBlogAIForNextJs(
process.env.NEXT_BLOG_AI_API_KEY!,
{ revalidate: 3600 } // Default to caching for 1 hour
);Disabling Caching
Caching is disabled by default, but you can explicitly disable it:
const { data } = await getBlogPosts({
next: {
revalidate: 0, // Disable cache for this request
// or
dynamic: true, // Also disables cache
},
});Using fetchOptions directly with Next.js App Router
If you're using Next.js App Router with the standard createNextBlogAI function (not the Next.js wrapper), you can directly specify fetch options to control caching:
// Force dynamic rendering (no caching)
const { data } = await nextBlogAI.getBlogPosts({
cache: {
fetchOptions: {
cache: 'no-store', // Force dynamic rendering
},
},
});
// Or use incremental static regeneration
const { data } = await nextBlogAI.getBlogPosts({
cache: {
fetchOptions: {
next: {
revalidate: 3600, // Revalidate every hour
},
},
},
});Setting Default Fetch Options for Next.js App Router
By default, when using createNextBlogAI() with Next.js App Router, the client will use dynamic rendering with cache: 'no-store' for all requests to ensure you always get fresh content.
You can customize these defaults when creating the client:
// Override the default fetch options (which is 'no-store')
const nextBlogAI = createNextBlogAI({
apiKey: 'your-api-key',
defaultFetchOptions: {
cache: 'force-cache',
next: {
revalidate: 3600, // Use ISR with 1 hour revalidation instead
},
},
});
// All requests will now use these custom fetch options
const { data } = await nextBlogAI.getBlogPosts();Individual request options will override the defaults:
// This specific request will use these options instead of the defaults
const { data } = await nextBlogAI.getBlogPosts({
cache: {
fetchOptions: {
cache: 'no-store', // Override back to dynamic rendering
},
},
});Next.js Best Practices
Project Structure
When integrating Next-Blog-AI into your Next.js project, consider the following structure:
src/
lib/
next-blog-ai.ts // Client initialization
app/
blog/
page.tsx // Blog listing
[slug]/
page.tsx // Blog post detail
opengraph-image.tsx // OG image generation
api/
blog/
comment/
route.ts // Server action for commentsEnvironment Variables
Set up your environment variables in a .env.local file:
NEXT_BLOG_AI_API_KEY=your_api_key_here