Back to Docs

Quick Start Guide

Get up and running with BlogFlow in 5 minutes

Step 1: Installation

npm install @blogflow/sdk

Step 2: Configuration

Create a .env.local file in your project root and set your API keys:

# .env.local
BLOGFLOW_API_KEY=your_api_key_here

NEXT_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.