UNPKG

next-blog-ai

Version:

AI-powered blog generation and content delivery for Next.js and other frameworks

745 lines (584 loc) 21.9 kB
# 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](https://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](https://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 `generateStaticParams` and 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: ```bash npx create-next-blog-ai@latest ``` This command will: 1. Install the Next-Blog-AI package automatically 2. Set up the client in your project 3. Configure the necessary files for blog functionality ### Option 2: Manual Installation If you prefer a manual approach, first install the package: ```bash npm install next-blog-ai # or yarn add next-blog-ai # or pnpm add next-blog-ai ``` Then 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: ```typescript // 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: ```typescript // 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: 1. Proper typing for all Next.js-specific options 2. Simplified imports across your Next.js application 3. Consistent caching defaults that can be overridden when needed 4. Full compatibility with both App Router and Pages Router ## Documentation For comprehensive documentation, guides, and examples, please visit our official documentation site: [https://next-blog-ai.com/docs](https://next-blog-ai.com/docs) Our documentation includes detailed information about installation, API reference, advanced usage examples, and best practices for Next.js integration. ## Fetching blog posts ```typescript // 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 ```typescript // 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 ```typescript // 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: 'john@example.com', // 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) ```typescript // 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 ```typescript // 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: ```typescript 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 ```typescript // Clear the entire cache nextBlogAI.clearCache(); // Clear a specific item from the cache nextBlogAI.clearCacheItem('list', { page: 1, per_page: 10 }); ``` ### Error Handling ```typescript 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 client - `getBlogPosts(options)` - Get a list of blog posts with Next.js caching - `getBlogPost(slug, options)` - Get a single blog post with Next.js caching - `getBlogPostSEO(slug, options)` - Fetch only SEO metadata for a post with Next.js caching - `getBlogListSEO(options)` - Fetch only SEO metadata for blog list with Next.js caching - `getAllBlogSlugs(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 ```typescript // 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: ```typescript // 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: ```typescript // 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: ```typescript // 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. ```typescript 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. ```typescript const { data } = await nextBlogAI.getBlogPosts({ display: 'list', }); ``` You can also set the default display format when initializing the client: ```typescript 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: ```typescript // 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: ```typescript 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: ```typescript // 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: ```typescript // 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: ```typescript // 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 comments ``` ### Environment Variables Set up your environment variables in a `.env.local` file: ``` NEXT_BLOG_AI_API_KEY=your_api_key_here ```