Skip to main content
generate_blogs.py is an open source Python script that automates blog content creation end-to-end. It uses a multi-pass pipeline powered by Claude to generate high-quality, humanised blog posts and publish them to your Supabase database.
This script is open source. You can adapt it for your own content pipeline — replace the Supabase publishing step with your CMS of choice.

What it does

The pipeline runs in 6 passes, each building on the last:
PassWhat happens
0Fetch existing blog titles from Supabase (auto-runs before Pass 1)
1Identify topics — avoids duplicating existing posts
2Plan blog structure per topic (comparison / technical / case-study / how-to)
3Generate full content for each blog
4Humanise — strip AI tells, vary sentence length, add real-world examples
5Add internal links across the batch and reference relevant product pages
6Push to Supabase DB with metadata (cover image, tags, SEO keywords, platform)
Each pass caches its output to local JSON files (_topics.json, _plans.json, _registry.json) so you can resume from any pass if something fails.

Requirements

  • Python 3.9+
  • An Anthropic API key (Claude)
  • A Supabase project with a blogs table (for publishing)
Install dependencies:
pip install anthropic
No other dependencies — the script uses only stdlib (json, os, argparse, pathlib, urllib) plus the anthropic package.

Setup

Clone or install from the nometria/blog-pipeline repository:
pip install blog-pipeline
Or clone the source:
git clone https://github.com/nometria/blog-pipeline
cd blog-pipeline
pip install -e .
Also available on PyPI: blog-pipeline
Set environment variables:
export ANTHROPIC_API_KEY=sk-ant-...

# Optional — defaults to Nometria's Supabase instance if not set
export SUPABASE_URL=https://xxxxxxxxxxxx.supabase.co
export SUPABASE_SERVICE_KEY=eyJ...

Usage

# Run all 6 passes (full pipeline)
python3 generate_blogs.py

# Run specific passes
python3 generate_blogs.py --passes 1-3    # Topics + planning + generation only
python3 generate_blogs.py --passes 4-6    # Humanise + link + publish only
python3 generate_blogs.py --passes 6      # Publish only (from cached content)

# Limit how many blogs to generate in this run
python3 generate_blogs.py --count 5

# Combine options
python3 generate_blogs.py --passes 1-3 --count 10

Output

Local files (in blogs/ directory):
  • _topics.json — topic list with metadata
  • _plans.json — structure plans per topic
  • _registry.json — tracking which blogs exist locally vs in DB
  • <slug>.md — one markdown file per generated blog
Published to Supabase: Each blog is inserted into the blogs table with:
{
  "slug": "my-blog-post-title",
  "title": "My Blog Post Title",
  "content": "## Introduction\n\n...",
  "cover_image": "https://images.unsplash.com/photo-...",
  "tags": ["Tutorial", "Base44"],
  "seo_keywords": ["keyword 1", "keyword 2"],
  "platform": "base44",
  "author": "Nometria Team",
  "published": true,
  "created_at": "2025-01-01T00:00:00Z"
}

Blog types

The pipeline generates three blog formats:
TypeDescriptionExample use
comparisonA vs B — compares two tools, platforms, or approaches”Base44 vs Lovable: Which is better for…”
technical-deep-diveIn-depth tutorial or explanation”How two-way GitHub sync works under the hood”
case-studyReal-world scenario with outcomes”How we deployed 50 no-code apps to AWS in a weekend”
how-toStep-by-step guide”How to add Stripe payments to your Lovable app”
Type is determined by Claude in Pass 2 based on topic suitability.

Customising for your project

Change the niche/focus: Edit the system prompt in generate_blogs.py around the CATEGORY_MAP and topic generation sections. Replace references to Nometria and vibe coding with your own product and subject matter. Change the publishing destination: Replace the push_to_supabase() function with your own CMS integration. The function receives a dict with slug, title, content, tags, cover_image, etc. Adjust the cover image pool: The _COVER_POOL dict maps blog categories to curated Unsplash photo IDs. Add or remove photo IDs to change the visual style of generated posts.

Supabase table schema

If you want to use the built-in Supabase publishing:
create table blogs (
  id uuid primary key default gen_random_uuid(),
  slug text unique not null,
  title text not null,
  content text not null,
  cover_image text,
  tags text[],
  seo_keywords text[],
  platform text,
  author text default 'Nometria Team',
  author_title text,
  author_image text,
  published boolean default true,
  created_at timestamptz default now()
);

Example run output

Pass 0: Fetching existing blogs from Supabase...
  Found 47 existing blogs.

Pass 1: Identifying topics...
  Skipping 47 existing topics.
  Generated 8 new topics.

Pass 2: Planning blog structure...
  [1/8] "How to migrate from Firebase to Supabase" → how-to
  [2/8] "Lovable vs Bolt: which is faster for..." → comparison
  ...

Pass 3: Generating content...
  [1/8] Writing "How to migrate from Firebase to Supabase"... done (2,847 words)
  ...

Pass 4: Humanising...
  [1/8] Humanising... done

Pass 5: Adding internal links...
  Added 12 internal links across 8 blogs.

Pass 6: Publishing to Supabase...
  [1/8] Pushed "how-to-migrate-from-firebase-to-supabase" ✓
  ...
  Done. 8 blogs published.