Back to Docs
Quick Start Guide
Get up and running with BlogFlow in 5 minutes
Step 1: Installation
npm install @blogflow/sdkStep 2: Configuration
Create a .env.local file in your project root and set your API keys:
# .env.local
BLOGFLOW_API_KEY=your_api_key_hereNEXT_PUBLIC_BLOGFLOW_API_KEY=your_api_key_here💡 BLOGFLOW_API_KEY for server-side, NEXT_PUBLIC_BLOGFLOW_API_KEY for client-side
Step 3: Start Using
Option 1: BlogFlowUI (Recommended)
Easiest way - One line of code for a complete blog:
import { BlogFlowUI } from '@blogflow/sdk/react';
export default function BlogPage() {
return (
<BlogFlowUI
apiKey={process.env.NEXT_PUBLIC_BLOGFLOW_API_KEY}
/>
);
}✨ Includes 16 themes, 12 view modes, search, pagination, and more
Option 2: Custom Implementation
Use the core API for full customization:
3.1 Display Blog Posts List
Fetch and render a list of blog posts:
'use client'
import { useEffect, useState } from 'react';
import { BlogFlow } from '@blogflow/sdk/core';
export default function BlogPosts() {
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function fetchPosts() {
const client = new BlogFlow({
apiKey: process.env.NEXT_PUBLIC_BLOGFLOW_API_KEY,
defaultLanguage: 'en',
});
try {
const postsData = await client.getPosts({
lang: 'en',
limit: 10,
});
setPosts(postsData);
} catch (error) {
console.error('Failed to fetch posts:', error);
} finally {
setLoading(false);
}
}
fetchPosts();
}, []);
if (loading) {
return <div className="text-center py-8">Loading posts...</div>;
}
return (
<div className="max-w-4xl mx-auto p-6">
<h1 className="text-3xl font-bold mb-8">Blog Posts</h1>
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
{posts.map((post) => (
<article key={post.id} className="border border-gray-200 rounded-lg p-6 hover:shadow-lg transition-shadow">
<h2 className="text-xl font-semibold mb-2 text-blue-600">
{post.title}
</h2>
{post.excerpt && (
<p className="text-gray-600 mb-4 line-clamp-3">
{post.excerpt}
</p>
)}
<div className="text-sm text-gray-500">
{new Date(post.created_at).toLocaleDateString()}
</div>
</article>
))}
</div>
</div>
);
}💡 Fetch and render a list of posts. Customize styling and layout as needed.
3.1 Display Blog Posts List
Fetch and render a list of blog posts:
'use client'
import { useEffect, useState } from 'react';
import { BlogFlow } from '@blogflow/sdk/core';
export default function BlogPosts() {
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function fetchPosts() {
const client = new BlogFlow({
apiKey: process.env.NEXT_PUBLIC_BLOGFLOW_API_KEY,
defaultLanguage: 'en',
});
try {
const postsData = await client.getPosts({
lang: 'en',
limit: 10,
});
setPosts(postsData);
} catch (error) {
console.error('Failed to fetch posts:', error);
} finally {
setLoading(false);
}
}
fetchPosts();
}, []);
if (loading) {
return <div className="text-center py-8">Loading posts...</div>;
}
return (
<div className="max-w-4xl mx-auto p-6">
<h1 className="text-3xl font-bold mb-8">Blog Posts</h1>
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
{posts.map((post) => (
<article key={post.id} className="border border-gray-200 rounded-lg p-6 hover:shadow-lg transition-shadow">
<h2 className="text-xl font-semibold mb-2 text-blue-600">
{post.title}
</h2>
{post.excerpt && (
<p className="text-gray-600 mb-4 line-clamp-3">
{post.excerpt}
</p>
)}
<div className="text-sm text-gray-500">
{new Date(post.created_at).toLocaleDateString()}
</div>
</article>
))}
</div>
</div>
);
}💡 Fetch and render a list of posts. Customize styling and layout as needed.
3.2 Display Single Post
Fetch and display the full content of a single blog post:
'use client'
import { useEffect, useState } from 'react';
import { BlogFlow } from '@blogflow/sdk/core';
interface BlogPostPageProps {
params: { slug: string };
}
export default function BlogPostPage({ params }: BlogPostPageProps) {
const [post, setPost] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function fetchPost() {
const client = new BlogFlow({
apiKey: process.env.NEXT_PUBLIC_BLOGFLOW_API_KEY,
defaultLanguage: 'en',
});
try {
const postData = await client.getPost(params.slug, {
lang: 'en',
});
setPost(postData);
} catch (error) {
console.error('Failed to fetch post:', error);
} finally {
setLoading(false);
}
}
fetchPost();
}, [params.slug]);
if (loading) {
return <div className="text-center py-8">Loading post...</div>;
}
if (!post) {
return <div className="text-center py-8">Post not found</div>;
}
return (
<article className="max-w-4xl mx-auto p-6">
<header className="mb-8">
<h1 className="text-4xl font-bold mb-4 text-gray-900 dark:text-white">
{post.title}
</h1>
<div className="text-sm text-gray-500 dark:text-gray-400">
Published on {new Date(post.created_at).toLocaleDateString()}
{post.category && (
<span className="ml-4 px-2 py-1 bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200 rounded">
{post.category}
</span>
)}
</div>
</header>
{post.featured_image_url && (
<div className="relative w-full mb-8 rounded-lg overflow-hidden" style={{ aspectRatio: '16/9' }}>
<Image
src={post.featured_image_url}
alt={post.featured_image_alt || post.title}
fill
className="object-cover"
sizes="(max-width: 768px) 100vw, 896px"
/>
</div>
)}
<div
className="prose prose-lg max-w-none dark:prose-invert"
dangerouslySetInnerHTML={{ __html: post.content }}
/>
</article>
);
}💡 Fetch and render the full content of a single blog post, including title, date, category, and body.