next-blog-ai
Version:
AI-powered blog generation and content delivery for Next.js and other frameworks
794 lines (788 loc) • 26.2 kB
text/typescript
/**
* Configuration options for NextBlogAI client
*/
interface NextBlogAIConfig {
/**
* API key for authentication with Next-Blog-AI service
*/
apiKey: string;
/**
* Default format for content responses
* @default 'html'
*/
defaultFormat?: ContentFormat;
/**
* Default display format for blog lists
* @default 'grid'
*/
defaultBlogListDisplay?: BlogListDisplayFormat;
/**
* Default TTL for cache in seconds
* @default 3600 (1 hour)
*/
defaultCacheTTL?: number;
/**
* Retry options for failed requests
*/
retry?: RetryOptions;
/**
* Custom CSS styles for HTML content
*/
styles?: {
/**
* Custom CSS for blog post detail content
*/
blogContent?: string;
/**
* Custom CSS for blog listing pages
*/
blogList?: string;
};
/**
* Default fetch options to apply to all requests
* Useful for Next.js App Router to control caching behavior
*/
defaultFetchOptions?: {
/**
* Fetch cache mode: 'default', 'no-store', 'reload', 'force-cache', etc.
* Must be one of the valid RequestCache types from the Fetch API
*/
cache?: RequestCache;
/**
* Next.js specific options for fetch
*/
next?: {
/**
* Revalidation time in seconds
*/
revalidate?: number;
};
/**
* Any other fetch options
*/
[key: string]: any;
};
}
/**
* Format for content responses
*/
type ContentFormat = 'html' | 'json';
/**
* Display format for blog lists
*/
type BlogListDisplayFormat = 'grid' | 'list';
/**
* Options for caching
*/
interface CacheOptions {
/**
* Time to live in seconds
*/
ttl?: number;
/**
* Whether to bypass the cache and force a fresh fetch
*/
bypassCache?: boolean;
/**
* Framework-specific fetch options to be passed directly to the fetch API
* For Next.js, use: { cache: 'no-store' } to force dynamic rendering,
* or { next: { revalidate: seconds } } for incremental static regeneration
*/
fetchOptions?: {
/**
* Fetch cache mode: 'default', 'no-store', 'reload', 'force-cache', etc.
* Must be one of the valid RequestCache types from the Fetch API
*/
cache?: RequestCache;
/**
* Next.js specific options for fetch
*/
next?: {
/**
* Revalidation time in seconds
*/
revalidate?: number;
};
/**
* Any other fetch options
*/
[key: string]: any;
};
/**
* Framework-specific caching options
*/
[key: string]: any;
}
/**
* Error response from the API
*/
interface ErrorResponse {
/**
* Error message
*/
message: string;
/**
* HTTP status code
*/
status: number;
/**
* Error code
* Common error codes:
* - 'INVALID_API_KEY': API key is invalid or missing
* - 'RATE_LIMITED': Rate limit exceeded
* - 'NETWORK_ERROR': Network connectivity issues
* - 'HTTP_404': Resource not found
* - 'HTTP_500': Server error
*/
code?: string;
}
/**
* Blog list options
*/
interface BlogListOptions {
/**
* Page number
* @default 1
*/
page?: number;
/**
* Number of posts per page
* @default 10
*/
perPage?: number;
/**
* Format for response
*/
format?: ContentFormat;
/**
* Display format for the blog list (only applies to HTML format)
* @default 'grid'
*/
display?: BlogListDisplayFormat;
/**
* Cache options
*/
cache?: CacheOptions;
}
/**
* Blog post options
*/
interface BlogPostOptions {
/**
* Format for response
*/
format?: ContentFormat;
/**
* Cache options
*/
cache?: CacheOptions;
}
/**
* Comment submission data
*/
interface CommentData {
/**
* ID of the blog post to comment on
*/
postId: string;
/**
* Name of the comment author
*/
authorName: string;
/**
* Email of the comment author (optional)
*/
authorEmail?: string;
/**
* Content of the comment
*/
content: string;
}
/**
* Base response from the API
*/
interface ApiResponse<T> {
/**
* Response data
*/
data?: T;
/**
* Error information (if any)
*/
error?: ErrorResponse;
}
/**
* Pagination information
*/
interface Pagination {
/**
* Total number of posts
*/
totalPosts: number;
/**
* Total number of pages
*/
totalPages: number;
/**
* Current page number
*/
currentPage: number;
/**
* Number of posts per page
*/
perPage: number;
}
/**
* Blog post summary (for list view)
*/
interface BlogPostSummary {
/**
* Post ID
*/
id: string;
/**
* Post title
*/
title: string;
/**
* Post slug
*/
slug: string;
/**
* Post excerpt
*/
excerpt: string;
/**
* URL to featured image
*/
featuredImageUrl?: string;
/**
* Published date
*/
publishedAt: string;
/**
* Estimated reading time in minutes
*/
readingTime: number;
/**
* Comment count
*/
commentCount: number;
/**
* Language code (ISO 639-1)
*/
language: string;
/**
* Publisher name
*/
publisherName?: string;
}
/**
* SEO metadata
*/
interface SEOMetadata {
/**
* Page title
*/
title: string;
/**
* Page description
*/
description: string;
/**
* Keywords
*/
keywords: string[];
/**
* JSON-LD structured data for Schema.org
*/
structuredData: string | object;
/**
* Featured image for social sharing (Open Graph, Twitter cards)
*/
featuredImage?: {
/**
* URL of the featured image
*/
url: string;
/**
* Alt text for the featured image
*/
alt: string;
};
}
/**
* Blog list response in HTML format
*/
interface BlogListHtmlResponse {
/**
* Response format
*/
format: 'html';
/**
* HTML content with inline styles
*/
content: string;
/**
* SEO metadata
*/
seo: SEOMetadata;
/**
* Pagination information
*/
pagination: Pagination;
}
/**
* Blog list response in JSON format
*/
interface BlogListJsonResponse {
/**
* Response format
*/
format: 'json';
/**
* List of blog posts
*/
posts: BlogPostSummary[];
/**
* SEO metadata
*/
seo: SEOMetadata;
/**
* Pagination information
*/
pagination: Pagination;
}
/**
* Combined blog list response type
*/
type BlogListResponse = BlogListHtmlResponse | BlogListJsonResponse;
/**
* Full blog post
*/
interface BlogPost {
/**
* Post ID
*/
id: string;
/**
* Post title
*/
title: string;
/**
* Post slug
*/
slug: string;
/**
* Full post content
*/
content: string;
/**
* Post excerpt
*/
excerpt: string;
/**
* URL to featured image
*/
featuredImageUrl?: string;
/**
* Published date
*/
publishedAt: string;
/**
* Estimated reading time in minutes
*/
readingTime: number;
/**
* Language code (ISO 639-1)
*/
language: string;
}
/**
* Comment on a blog post
*/
interface Comment {
/**
* Comment ID
*/
id: string;
/**
* Name of the comment author
*/
authorName: string;
/**
* Content of the comment
*/
content: string;
/**
* Created date
*/
createdAt: string;
}
/**
* Blog post response in HTML format
*/
interface BlogPostHtmlResponse {
/**
* Response format
*/
format: 'html';
/**
* HTML content with inline styles
*/
content: string;
/**
* HTML for comment form
*/
commentForm: string;
/**
* HTML for comments
*/
comments: string;
/**
* SEO metadata
*/
seo: SEOMetadata;
}
/**
* Blog post response in JSON format
*/
interface BlogPostJsonResponse {
/**
* Response format
*/
format: 'json';
/**
* Blog post data
*/
post: BlogPost;
/**
* Comments on the post
*/
comments: Comment[];
/**
* SEO metadata
*/
seo: SEOMetadata;
}
/**
* Combined blog post response type
*/
type BlogPostResponse = BlogPostHtmlResponse | BlogPostJsonResponse;
/**
* Comment submission response
*/
interface CommentResponse {
/**
* Success flag
*/
success: boolean;
/**
* Response message
*/
message: string;
/**
* Comment data
*/
comment?: Comment;
}
/**
* Options for controlling retry behavior
*/
interface RetryOptions {
/**
* Maximum number of retry attempts
* @default 3
*/
maxRetries?: number;
/**
* Initial delay before first retry (in milliseconds)
* @default 300
*/
initialDelay?: number;
/**
* Factor by which to increase delay after each retry
* @default 2
*/
backoffFactor?: number;
/**
* Maximum delay between retries (in milliseconds)
* @default 10000 (10 seconds)
*/
maxDelay?: number;
/**
* Whether to add jitter to retry delays to prevent thundering herd problem
* @default true
*/
jitter?: boolean;
}
/**
* Options for fetching only SEO metadata
*/
interface SEOOptions {
/**
* Cache options
*/
cache?: CacheOptions;
}
/**
* SEO metadata response
*/
interface SEOResponse {
/**
* SEO metadata
*/
seo: SEOMetadata;
}
/**
* Options for fetching only blog list SEO metadata
*/
interface BlogListSEOOptions {
/**
* Page number
* @default 1
*/
page?: number;
/**
* Number of posts per page
* @default 10
*/
perPage?: number;
/**
* Cache options
*/
cache?: CacheOptions;
}
/**
* Blog list SEO metadata response
*/
interface BlogListSEOResponse {
/**
* SEO metadata
*/
seo: SEOMetadata;
}
/**
* Options for fetching all blog slugs
*/
interface BlogSlugsOptions {
/**
* Cache options
*/
cache?: CacheOptions;
}
/**
* Response containing all blog slugs
*/
interface BlogSlugsResponse {
/**
* Array of blog post slugs
*/
slugs: string[];
}
/**
* NextBlogAI Client
* Main class for interacting with the Next-Blog-AI API
*/
declare class NextBlogAI {
private apiKey;
private apiUrl;
private defaultFormat;
private defaultBlogListDisplay;
private defaultCacheTTL;
private cache;
private retryOptions;
private pendingRequests;
private customStyles;
private defaultFetchOptions?;
/**
* Default retry options
*/
private static readonly DEFAULT_RETRY_OPTIONS;
/**
* Create a new instance of NextBlogAI client
*/
constructor(config: NextBlogAIConfig);
/**
* Generate a cache key from the request parameters
*/
private generateCacheKey;
/**
* Get data from cache if available and not expired
*/
private getFromCache;
/**
* Store data in cache
*/
private storeInCache;
/**
* Calculate retry delay with exponential backoff and optional jitter
*/
private getRetryDelay;
/**
* Sleep for specified milliseconds
*/
private sleep;
/**
* Make API request with proper error handling and retry mechanism
*/
private makeRequest;
/**
* Execute the actual API request with retries
*/
private executeRequest;
/**
* Get a list of blog posts
*/
getBlogPosts(options?: BlogListOptions): Promise<ApiResponse<BlogListResponse>>;
/**
* Get a single blog post by slug
*/
getBlogPost(slug: string, options?: BlogPostOptions): Promise<ApiResponse<BlogPostResponse>>;
/**
* Submit a comment on a blog post
*/
submitComment(data: CommentData): Promise<ApiResponse<CommentResponse>>;
/**
* Get only SEO metadata for a blog post by slug
* Optimized version that doesn't fetch the full content
*/
getBlogPostSEO(slug: string, options?: SEOOptions): Promise<ApiResponse<SEOResponse>>;
/**
* Get only SEO metadata for blog list
* Optimized version that doesn't fetch the full content
*/
getBlogListSEO(options?: BlogListSEOOptions): Promise<ApiResponse<BlogListSEOResponse>>;
/**
* Get all blog post slugs
* Useful for static site generation in frameworks like Next.js
*/
getAllBlogSlugs(options?: BlogSlugsOptions): Promise<ApiResponse<BlogSlugsResponse>>;
/**
* Clear the entire cache
*/
clearCache(): void;
/**
* Clear a specific item from the cache
*/
clearCacheItem(endpoint: string, params: Record<string, any>): void;
/**
* Set custom styles for HTML content
*/
setStyles(styles: {
blogContent?: string;
blogList?: string;
}): void;
}
/**
* Factory function to create a new NextBlogAI instance
*/
declare function createNextBlogAI(config: NextBlogAIConfig): NextBlogAI;
/**
* Next.js specific caching options
*/
interface NextCacheOptions {
/**
* Next.js revalidation time in seconds
* When set to 0, cache will be bypassed completely (equivalent to dynamic: true)
*/
revalidate?: number;
/**
* Force dynamic rendering without caching
*/
dynamic?: boolean;
}
/**
* Blog list options with Next.js specific caching
*/
interface NextBlogListOptions extends Omit<BlogListOptions, 'cache'> {
/**
* Next.js specific caching options
*/
next?: NextCacheOptions;
}
/**
* Blog post options with Next.js specific caching
*/
interface NextBlogPostOptions extends Omit<BlogPostOptions, 'cache'> {
/**
* Next.js specific caching options
*/
next?: NextCacheOptions;
}
/**
* SEO options with Next.js specific caching
*/
interface NextSEOOptions extends Omit<SEOOptions, 'cache'> {
/**
* Next.js specific caching options
*/
next?: NextCacheOptions;
}
/**
* Blog list SEO options with Next.js specific caching
*/
interface NextBlogListSEOOptions extends Omit<BlogListSEOOptions, 'cache'> {
/**
* Next.js specific caching options
*/
next?: NextCacheOptions;
}
/**
* Blog slugs options with Next.js specific caching
*/
interface NextBlogSlugsOptions extends Omit<BlogSlugsOptions, 'cache'> {
/**
* Next.js specific caching options
*/
next?: NextCacheOptions;
}
/**
* Higher-order function that wraps a NextBlogAI method with Next.js caching
*/
declare function withNextCache<T, O extends object>(fn: (client: NextBlogAI, ...args: any[]) => Promise<ApiResponse<T>>): (client: NextBlogAI, ...args: any[]) => Promise<ApiResponse<T>>;
/**
* Get blog posts with Next.js caching
*/
declare function getBlogPostsWithNextCache(client: NextBlogAI, options?: NextBlogListOptions): Promise<ApiResponse<BlogListResponse>>;
/**
* Get a blog post with Next.js caching
*/
declare function getBlogPostWithNextCache(client: NextBlogAI, slug: string, options?: NextBlogPostOptions): Promise<ApiResponse<BlogPostResponse>>;
/**
* Get blog post SEO metadata with Next.js caching
*/
declare function getBlogPostSEOWithNextCache(client: NextBlogAI, slug: string, options?: NextSEOOptions): Promise<ApiResponse<SEOResponse>>;
/**
* Get blog list SEO metadata with Next.js caching
*/
declare function getBlogListSEOWithNextCache(client: NextBlogAI, options?: NextBlogListSEOOptions): Promise<ApiResponse<BlogListSEOResponse>>;
/**
* Get all blog slugs with Next.js caching
*/
declare function getAllBlogSlugsWithNextCache(client: NextBlogAI, options?: NextBlogSlugsOptions): Promise<ApiResponse<BlogSlugsResponse>>;
declare function createNextBlogAIForNextJs(apiKey: string, defaultCacheOptions?: NextCacheOptions): {
client: NextBlogAI;
getBlogPosts: (options?: NextBlogListOptions) => Promise<ApiResponse<BlogListResponse>>;
getBlogPost: (slug: string, options?: NextBlogPostOptions) => Promise<ApiResponse<BlogPostResponse>>;
getBlogPostSEO: (slug: string, options?: NextSEOOptions) => Promise<ApiResponse<SEOResponse>>;
getBlogListSEO: (options?: NextBlogListSEOOptions) => Promise<ApiResponse<BlogListSEOResponse>>;
getAllBlogSlugs: (options?: NextBlogSlugsOptions) => Promise<ApiResponse<BlogSlugsResponse>>;
};
/**
* Default CSS styles for blog content
*/
declare const DEFAULT_BLOG_STYLES = "\n/* Base styles */\n.next-blog-ai-content {\n line-height: 1.6;\n color: inherit;\n max-width: 100%;\n margin: 0 auto;\n}\n\n/* Headings */\n.next-blog-ai-content h1,\n.next-blog-ai-content h2,\n.next-blog-ai-content h3,\n.next-blog-ai-content h4,\n.next-blog-ai-content h5,\n.next-blog-ai-content h6 {\n margin-top: 2rem;\n margin-bottom: 1rem;\n font-weight: 600;\n line-height: 1.25;\n color: inherit;\n}\n\n.next-blog-ai-content h1 {\n font-size: 2.25rem;\n}\n\n.next-blog-ai-content h2 {\n font-size: 1.75rem;\n border-bottom: 1px solid #eee;\n padding-bottom: 0.3rem;\n}\n\n.next-blog-ai-content h3 {\n font-size: 1.5rem;\n}\n\n.next-blog-ai-content h4 {\n font-size: 1.25rem;\n}\n\n.next-blog-ai-content h5, .next-blog-ai-content h6 {\n font-size: 1rem;\n}\n\n/* Paragraphs and text */\n.next-blog-ai-content p {\n margin-top: 0;\n margin-bottom: 1.5rem;\n}\n\n.next-blog-ai-content strong {\n font-weight: 600;\n}\n\n.next-blog-ai-content em {\n font-style: italic;\n}\n\n/* Lists */\n.next-blog-ai-content ul,\n.next-blog-ai-content ol {\n margin-top: 0;\n margin-bottom: 1.5rem;\n padding-left: 2rem;\n}\n\n.next-blog-ai-content li {\n margin-bottom: 0.5rem;\n}\n\n.next-blog-ai-content li > ul,\n.next-blog-ai-content li > ol {\n margin-top: 0.5rem;\n margin-bottom: 0.5rem;\n}\n\n/* Links */\n.next-blog-ai-content a {\n color: #0070f3;\n text-decoration: none;\n}\n\n.next-blog-ai-content a:hover {\n text-decoration: underline;\n}\n\n/* Blockquotes */\n.next-blog-ai-content blockquote {\n margin: 1.5rem 0;\n padding: 0.5rem 1rem;\n border-left: 4px solid #ddd;\n color: #666;\n background-color: #f9f9f9;\n}\n\n.next-blog-ai-content blockquote > :first-child {\n margin-top: 0;\n}\n\n.next-blog-ai-content blockquote > :last-child {\n margin-bottom: 0;\n}\n\n/* Code blocks */\n.next-blog-ai-content pre {\n margin: 1.5rem 0;\n padding: 1rem;\n overflow: auto;\n background-color: #f6f8fa;\n border-radius: 3px;\n font-size: 0.875rem;\n}\n\n.next-blog-ai-content code {\n font-size: 0.875rem;\n padding: 0.2em 0.4em;\n background-color: rgba(27, 31, 35, 0.05);\n border-radius: 3px;\n}\n\n.next-blog-ai-content pre code {\n padding: 0;\n background-color: transparent;\n}\n\n/* Tables */\n.next-blog-ai-content table {\n width: 100%;\n border-collapse: collapse;\n margin: 1.5rem 0;\n}\n\n.next-blog-ai-content table th,\n.next-blog-ai-content table td {\n padding: 0.5rem 1rem;\n border: 1px solid #e1e4e8;\n}\n\n.next-blog-ai-content table th {\n background-color: #f6f8fa;\n font-weight: 600;\n text-align: left;\n}\n\n.next-blog-ai-content table tr:nth-child(even) {\n background-color: #f7f7f7;\n}\n\n/* Images */\n.next-blog-ai-content img {\n max-width: 100%;\n height: auto;\n display: block;\n margin: 1.5rem auto;\n}\n\n.next-blog-ai-content figure {\n margin: 1.5rem auto;\n text-align: center;\n}\n\n.next-blog-ai-content figcaption {\n font-size: 0.875rem;\n color: #666;\n margin-top: 0.5rem;\n}\n\n/* Comments */\n.next-blog-ai-comments {\n margin-top: 3rem;\n border-top: 1px solid #eee;\n padding-top: 2rem;\n}\n\n.next-blog-ai-comment {\n margin-bottom: 2rem;\n padding: 1rem;\n background-color: #f9f9f9;\n border-radius: 4px;\n}\n\n.next-blog-ai-comment-header {\n display: flex;\n justify-content: space-between;\n margin-bottom: 0.5rem;\n}\n\n.next-blog-ai-comment-author {\n font-weight: 600;\n}\n\n.next-blog-ai-comment-date {\n color: #666;\n font-size: 0.875rem;\n}\n\n.next-blog-ai-comment-content {\n line-height: 1.5;\n}\n\n/* Comment form */\n.next-blog-ai-comment-form {\n margin-top: 2rem;\n}\n\n.next-blog-ai-comment-form label {\n display: block;\n margin-bottom: 0.5rem;\n font-weight: 600;\n}\n\n.next-blog-ai-comment-form input,\n.next-blog-ai-comment-form textarea {\n width: 100%;\n padding: 0.5rem;\n margin-bottom: 1rem;\n border: 1px solid #ddd;\n border-radius: 4px;\n}\n\n.next-blog-ai-comment-form textarea {\n min-height: 6rem;\n}\n\n.next-blog-ai-comment-form button {\n background-color: #0070f3;\n color: white;\n border: none;\n padding: 0.5rem 1rem;\n border-radius: 4px;\n cursor: pointer;\n font-weight: 500;\n}\n\n.next-blog-ai-comment-form button:hover {\n background-color: #0060df;\n}\n";
/**
* Default CSS styles for blog list
*/
declare const DEFAULT_BLOG_LIST_STYLES = "\n/* Blog post list - Grid View (Default) */\n.next-blog-ai-list {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 2rem;\n margin: 2rem 0;\n}\n\n@media (max-width: 768px) {\n .next-blog-ai-list {\n grid-template-columns: 1fr;\n }\n}\n\n/* Post content padding for grid view */\n.next-blog-ai-post-content {\n padding: 1.5rem;\n display: flex;\n flex-direction: column;\n}\n\n/* List View Styles */\n.next-blog-ai-list.list-view {\n display: block;\n}\n\n.next-blog-ai-list.list-view .next-blog-ai-post-card {\n display: flex;\n flex-direction: row;\n margin-bottom: 2rem;\n border-radius: 8px;\n overflow: hidden;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n transition: transform 0.2s, box-shadow 0.2s;\n}\n\n.next-blog-ai-list.list-view .next-blog-ai-post-card:hover {\n transform: translateY(-4px);\n box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);\n}\n\n.next-blog-ai-list.list-view .next-blog-ai-post-image {\n width: 250px;\n min-width: 250px;\n height: 180px;\n padding-bottom: 0;\n position: relative;\n background-color: #f0f0f0;\n}\n\n.next-blog-ai-list.list-view .next-blog-ai-post-image img {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n.next-blog-ai-list.list-view .next-blog-ai-post-content {\n flex: 1;\n padding: 1.5rem;\n display: flex;\n flex-direction: column;\n}\n\n/* Make sure grid view items display correctly */\n.next-blog-ai-list:not(.list-view) .next-blog-ai-post-card {\n display: flex;\n flex-direction: column;\n border-radius: 8px;\n overflow: hidden;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n transition: transform 0.2s, box-shadow 0.2s;\n}\n\n/* Responsive adjustments for list view */\n@media (max-width: 768px) {\n .next-blog-ai-list.list-view .next-blog-ai-post-card {\n flex-direction: column;\n }\n \n .next-blog-ai-list.list-view .next-blog-ai-post-image {\n width: 100%;\n height: 0;\n padding-bottom: 56.25%; /* 16:9 aspect ratio */\n }\n}\n\n.next-blog-ai-post-card {\n display: flex;\n flex-direction: column;\n border-radius: 8px;\n overflow: hidden;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n transition: transform 0.2s, box-shadow 0.2s;\n}\n\n.next-blog-ai-post-title {\n font-size: 1.25rem;\n font-weight: 600;\n margin-top: 0;\n margin-bottom: 0.5rem;\n color: #111;\n}\n\n.next-blog-ai-post-title a {\n color: inherit;\n text-decoration: none;\n}\n\n.next-blog-ai-post-title a:hover {\n color: #0070f3;\n}\n\n.next-blog-ai-post-meta {\n font-size: 0.875rem;\n color: #666;\n margin-bottom: 1rem;\n display: flex;\n align-items: center;\n gap: 1rem;\n}\n\n.next-blog-ai-post-excerpt {\n margin-bottom: 1.5rem;\n flex-grow: 1;\n}\n\n.next-blog-ai-post-footer {\n margin-top: auto;\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.next-blog-ai-read-more {\n color: #0070f3;\n text-decoration: none;\n font-weight: 500;\n font-size: 0.875rem;\n}\n\n.next-blog-ai-read-more:hover {\n text-decoration: underline;\n}\n\n.next-blog-ai-comments-count {\n font-size: 0.875rem;\n color: #666;\n}\n\n/* Pagination */\n.next-blog-ai-pagination {\n display: flex;\n justify-content: center;\n margin: 3rem 0;\n gap: 0.5rem;\n}\n\n.next-blog-ai-pagination-item {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 2.5rem;\n height: 2.5rem;\n padding: 0 0.75rem;\n border-radius: 4px;\n background-color: #f0f0f0;\n color: #333;\n text-decoration: none;\n font-weight: 500;\n}\n\n.next-blog-ai-pagination-item:hover {\n background-color: #e0e0e0;\n}\n\n.next-blog-ai-pagination-item.active {\n background-color: #0070f3;\n color: white;\n}\n\n.next-blog-ai-pagination-item.disabled {\n color: #999;\n pointer-events: none;\n}\n";
/**
* Deep transforms object keys from snake_case to camelCase
*/
declare function normalizeKeys<T>(obj: any): T;
/**
* Add HTML styles for content rendering
*/
declare function addHtmlStyles(html: string, styles: string): string;
export { ApiResponse, BlogListHtmlResponse, BlogListJsonResponse, BlogListOptions, BlogListResponse, BlogListSEOOptions, BlogListSEOResponse, BlogPost, BlogPostHtmlResponse, BlogPostJsonResponse, BlogPostOptions, BlogPostResponse, BlogPostSummary, BlogSlugsOptions, BlogSlugsResponse, CacheOptions, Comment, CommentData, CommentResponse, ContentFormat, DEFAULT_BLOG_LIST_STYLES, DEFAULT_BLOG_STYLES, ErrorResponse, NextBlogAI, NextBlogAIConfig, NextBlogListOptions, NextBlogListSEOOptions, NextBlogPostOptions, NextBlogSlugsOptions, NextSEOOptions, Pagination, RetryOptions, SEOMetadata, SEOOptions, SEOResponse, addHtmlStyles, createNextBlogAI, createNextBlogAIForNextJs, getAllBlogSlugsWithNextCache, getBlogListSEOWithNextCache, getBlogPostSEOWithNextCache, getBlogPostWithNextCache, getBlogPostsWithNextCache, normalizeKeys, withNextCache };