next-blog-ai
TypeScript icon, indicating that this package has built-in type declarations

0.3.12 • Public • Published

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 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:

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:

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:

// 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:

  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

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: '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)

// 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 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

// 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 comments

Environment Variables

Set up your environment variables in a .env.local file:

NEXT_BLOG_AI_API_KEY=your_api_key_here

/next-blog-ai/

    Package Sidebar

    Install

    npm i next-blog-ai

    Weekly Downloads

    136

    Version

    0.3.12

    License

    MIT

    Unpacked Size

    225 kB

    Total Files

    10

    Last publish

    Collaborators

    • ammar.rayess