API Reference
Complete API documentation for BlogFlow SDK
import { BlogFlow } from '@blogflow/sdk';
const client = new BlogFlow({
apiKey: 'your_api_key',
baseUrl: 'https://blogflow-api-server.vercel.app/api/v2', // optional
defaultLanguage: 'en' // optional, defaults to 'en' if not specified
});// Get posts with language and limit
const posts = await client.getPosts({
lang: 'zh',
limit: 20,
offset: 0
});
// Search posts
const searchResults = await client.getPosts({
search: 'react',
searchFields: ['title', 'excerpt']
});
// Sort posts
const sortedPosts = await client.getPosts({
sort: 'created_at',
order: 'desc',
limit: 10
});
// Next.js ISR cache (revalidate every 60 seconds)
const cachedPosts = await client.getPosts({
next: { revalidate: 60 }
});
// Next.js on-demand revalidation with tags
const taggedPosts = await client.getPosts({
next: { tags: ['posts'] }
});Parameters:
lang?- Language code: 'en' | 'zh' | 'es' | 'fr' | 'de' | 'ja' | 'ko'limit?- Number of posts (default: 20, max: 100)offset?- Pagination offset (default: 0)sort?- Sort field: 'id' | 'created_at' | 'updated_at'order?- Sort order: 'asc' | 'desc'search?- Search keywordsearchFields?- Fields to search: ['title', 'excerpt', 'category', 'slug']next?- Next.js cache options: { revalidate?: number, tags?: string[] }cache?- Standard fetch cache option
Returns: Promise<V2PostListItem[]>
// Get a post by slug
const post = await client.getPost('my-article-slug', {
lang: 'zh'
});
// With Next.js ISR cache (revalidate every hour)
const cachedPost = await client.getPost('my-article-slug', {
lang: 'zh',
next: { revalidate: 3600 }
});
// With cache tags for on-demand revalidation
const taggedPost = await client.getPost('my-article-slug', {
next: { tags: ['posts', 'my-article-slug'] }
});Parameters:
slug- Post slug (required)options.lang?- Language codeoptions.next?- Next.js cache optionsoptions.cache?- Standard fetch cache option
Returns: Promise<V2Post>
// Get paginated posts
const result = await client.getPaginatedPosts({
page: 1,
pageSize: 12,
lang: 'zh'
});
// Access pagination metadata
console.log(result.items); // Array of posts
console.log(result.page); // Current page number
console.log(result.pageSize); // Posts per page
console.log(result.totalCount); // Total number of posts
console.log(result.totalPages); // Total number of pages
console.log(result.hasNextPage); // Boolean
console.log(result.hasPreviousPage); // Boolean
// With search
const searchResult = await client.getPaginatedPosts({
page: 1,
pageSize: 20,
search: 'javascript',
lang: 'en'
});Parameters:
page?- 1-based page number (default: 1)pageSize?- Posts per page (default: 12, max: 100)- All parameters from
getPosts()are also supported
Returns: Promise<V2PaginatedPostsResponse>
Response includes: items, page, pageSize, totalCount, totalPages, hasNextPage, hasPreviousPage
Type Definitions
Complete TypeScript type definitions for all API methods and responses.
interface BlogFlowConfig {
apiKey: string; // Required: Your API key
baseUrl?: string; // Optional: API server URL
defaultLanguage?: SupportedLanguage; // Optional: Default language
}interface V2PostListItem {
id: number;
title: string;
slug: string;
category?: string | null;
featured_image_url?: string | null;
created_at: string; // ISO 8601 format
excerpt?: string | null;
}interface V2Post {
id: number;
title: string;
slug: string;
content: string; // Full HTML content
excerpt?: string | null;
category?: string | null;
featured_image_url?: string | null;
featured_image_alt?: string | null;
seo_title?: string | null;
seo_description?: string | null;
created_at: string; // ISO 8601 format
}interface V2PaginatedPostsResponse {
items: V2PostListItem[];
page: number;
pageSize: number;
totalCount: number;
totalPages: number;
hasNextPage: boolean;
hasPreviousPage: boolean;
}type SupportedLanguage = | 'en' // English | 'zh' // Chinese | 'es' // Spanish | 'fr' // French | 'de' // German | 'ja' // Japanese | 'ko'; // Korean
Error Handling
Learn how to handle errors gracefully in your application.
// Base error class
class BlogFlowError extends Error {
statusCode?: number;
details?: string;
}
// Authentication error (401)
class BlogFlowAuthError extends BlogFlowError
// Not found error (404)
class BlogFlowNotFoundError extends BlogFlowError
// Server error (500)
class BlogFlowServerError extends BlogFlowErrorimport {
BlogFlow,
BlogFlowError,
BlogFlowAuthError,
BlogFlowNotFoundError,
BlogFlowServerError
} from '@blogflow/sdk';
try {
const post = await client.getPost('my-slug');
} catch (error) {
if (error instanceof BlogFlowAuthError) {
// Handle authentication error (401)
console.error('Invalid API key:', error.message);
} else if (error instanceof BlogFlowNotFoundError) {
// Handle not found error (404)
console.error('Post not found:', error.message);
} else if (error instanceof BlogFlowServerError) {
// Handle server error (500)
console.error('Server error:', error.message, error.details);
} else if (error instanceof BlogFlowError) {
// Handle other errors
console.error('Error:', error.message, error.statusCode);
} else {
// Handle unexpected errors
console.error('Unexpected error:', error);
}
}Return Types
Detailed structure of all return types and response objects.
// Returns: Promise<V2PostListItem[]>
[
{
id: 1,
title: "Getting Started with Next.js",
slug: "getting-started-with-nextjs",
category: "Tutorial",
featured_image_url: "https://example.com/image.jpg",
created_at: "2024-01-15T10:30:00Z",
excerpt: "Learn how to build modern web apps..."
},
// ... more posts
]// Returns: Promise<V2Post>
{
id: 1,
title: "Getting Started with Next.js",
slug: "getting-started-with-nextjs",
content: "<h1>Getting Started</h1><p>Full HTML content...</p>",
excerpt: "Learn how to build modern web apps...",
category: "Tutorial",
featured_image_url: "https://example.com/image.jpg",
featured_image_alt: "Next.js logo",
seo_title: "Next.js Tutorial - Complete Guide",
seo_description: "Learn Next.js from scratch...",
created_at: "2024-01-15T10:30:00Z"
}// Returns: Promise<V2PaginatedPostsResponse>
{
items: [
{ id: 1, title: "Post 1", slug: "post-1", ... },
{ id: 2, title: "Post 2", slug: "post-2", ... },
// ... 12 posts
],
page: 1,
pageSize: 12,
totalCount: 150,
totalPages: 13,
hasNextPage: true,
hasPreviousPage: false
}Use Cases & Examples
Real-world examples and best practices for common scenarios.
// app/blog/page.tsx
import { BlogFlow } from '@blogflow/sdk';
const client = new BlogFlow({
apiKey: process.env.BLOGFLOW_API_KEY!,
});
export default async function BlogPage() {
// ISR: Revalidate every 60 seconds
const posts = await client.getPosts({
lang: 'en',
limit: 20,
next: { revalidate: 60 }
});
return (
<div>
{posts.map(post => (
<article key={post.id}>
<h2>{post.title}</h2>
<p>{post.excerpt}</p>
</article>
))}
</div>
);
}// app/blog/[slug]/page.tsx
import { BlogFlow } from '@blogflow/sdk';
const client = new BlogFlow({
apiKey: process.env.BLOGFLOW_API_KEY!,
});
export async function generateStaticParams() {
const posts = await client.getPosts({ limit: 100 });
return posts.map(post => ({ slug: post.slug }));
}
export default async function BlogPost({ params }: { params: { slug: string } }) {
const post = await client.getPost(params.slug, {
lang: 'en',
next: { revalidate: 3600 } // Cache for 1 hour
});
return (
<article>
<h1>{post.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.content }} />
</article>
);
}// app/search/page.tsx
import { BlogFlow } from '@blogflow/sdk';
const client = new BlogFlow({
apiKey: process.env.BLOGFLOW_API_KEY!,
});
export default async function SearchPage({
searchParams
}: {
searchParams: { q?: string }
}) {
const query = searchParams.q || '';
const results = await client.getPosts({
search: query,
searchFields: ['title', 'excerpt', 'category'],
limit: 20
});
return (
<div>
<h1>Search Results for "{query}"</h1>
{results.map(post => (
<div key={post.id}>
<h2>{post.title}</h2>
<p>{post.excerpt}</p>
</div>
))}
</div>
);
}// app/blog/page.tsx
import { BlogFlow } from '@blogflow/sdk';
const client = new BlogFlow({
apiKey: process.env.BLOGFLOW_API_KEY!,
});
export default async function BlogPage({
searchParams
}: {
searchParams: { page?: string }
}) {
const currentPage = parseInt(searchParams.page || '1');
const result = await client.getPaginatedPosts({
page: currentPage,
pageSize: 12,
lang: 'en'
});
return (
<div>
<div>
{result.items.map(post => (
<article key={post.id}>{post.title}</article>
))}
</div>
<div>
<p>Page {result.page} of {result.totalPages}</p>
{result.hasPreviousPage && (
<a href={"?page=" + (currentPage - 1)}>Previous</a>
)}
{result.hasNextPage && (
<a href={"?page=" + (currentPage + 1)}>Next</a>
)}
</div>
</div>
);
}Frequently Asked Questions
Common questions and solutions for using BlogFlow SDK.
Contact your administrator or visit your BlogFlow dashboard to obtain an API key. Keep your API key secure as it's used for authentication.
The SDK supports 7 languages: English (en), Chinese (zh), Spanish (es), French (fr), German (de), Japanese (ja), and Korean (ko).
Use the next parameter to configure ISR (Incremental Static Regeneration) caching. For example: next: { revalidate: 60 } will revalidate the cache every 60 seconds. Use tags for on-demand revalidation.
The SDK provides specific error classes: BlogFlowAuthError (401), BlogFlowNotFoundError (404), BlogFlowServerError (500). Use try-catch blocks to catch and handle these errors appropriately.
getPosts() returns a simple array of posts, suitable for list displays. getPaginatedPosts() returns a response object with pagination metadata (total pages, has next page, etc.), suitable for scenarios requiring pagination controls.
Use the search parameter to search the entire database on the server side, not just loaded posts. This is 10-100x faster than client-side search. You can specify searchFields to limit the search scope.