npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ai-blog-gen

v3.3.0

Published

AI-powered SEO blog generator using Pi SDK — any OpenAI/Anthropic compatible provider, competitive research, E-E-A-T, charts, illustrations, validation

Downloads

2,723

Readme

ai-blog-gen

AI-powered SEO blog generator using Pi SDK. Supports any OpenAI or Anthropic compatible provider. A single agent handles competitive research, outline creation, draft writing, E-E-A-T enhancement, and final polish — all in one multi-turn session with web search and file writing tools.

Install

npm install ai-blog-gen

Quick Start

import { createBlogGenerator } from 'ai-blog-gen'

const blog = createBlogGenerator({
  llm: {
    provider: 'anthropic',
    model: 'claude-sonnet-4-5-20250929',
    apiKey: process.env.ANTHROPIC_API_KEY!,
  },
})

const result = await blog.generate({
  lang: 'en',
  topic: 'Complete guide to sustainable energy solutions',
})

console.log(result.title)       // SEO-optimized title
console.log(result.slug)        // URL-friendly slug
console.log(result.content)     // Full markdown article
console.log(result.validation)  // { wordCount, hasTLDR, hasFAQ, hasTable, bannedWordsFound }

Supported Providers

// Anthropic Claude
const blog = createBlogGenerator({
  llm: {
    provider: 'anthropic',
    model: 'claude-sonnet-4-5-20250929',
    apiKey: 'sk-ant-...',
  },
})

// OpenAI
const blog = createBlogGenerator({
  llm: {
    provider: 'openai',
    model: 'gpt-4o',
    apiKey: 'sk-...',
  },
})

// Any OpenAI-compatible endpoint (Ollama, vLLM, LiteLLM, etc.)
const blog = createBlogGenerator({
  llm: {
    provider: 'my-local',
    model: 'llama3',
    apiKey: 'not-needed',
    baseUrl: 'http://localhost:11434/v1',
  },
})

// OpenRouter
const blog = createBlogGenerator({
  llm: {
    provider: 'openrouter',
    model: 'anthropic/claude-sonnet-4',
    apiKey: 'sk-or-...',
  },
})

How It Works

The library creates a multi-turn agent session via Pi SDK in a temporary directory. The agent follows a 5-phase workflow:

  1. Competitive Research — searches the web, analyzes top results, identifies content gaps
  2. Outline — creates structured outline with information gain per section
  3. Draft — writes full article in the target language
  4. E-E-A-T Enhancement — adds author expertise, trusted sources, internal links
  5. Final Polish — adds H1 title, TL;DR, FAQ section

After the agent finishes, the library post-processes the output: renders charts, generates illustrations, validates content, and extracts metadata.

Full Configuration

import { createBlogGenerator, createStorageProvider } from 'ai-blog-gen'

const blog = createBlogGenerator({
  // Required: LLM provider configuration
  llm: {
    provider: 'anthropic',
    model: 'claude-sonnet-4-5-20250929',
    apiKey: process.env.ANTHROPIC_API_KEY!,
  },

  // Optional: Storage provider for uploading charts/images
  storage: createStorageProvider(async (buffer, key, contentType) => {
    // Upload to S3, B2, GCS, etc.
    return { url: `https://cdn.example.com/${key}` }
  }),

  // Optional: SEO configuration
  bannedWords: ['delve', 'vibrant', 'unlock', 'leverage'],
  competitorDomains: ['competitor1.com', 'competitor2.com'],
  trustedDomainPatterns: ['\\.gov$', 'reuters\\.com', 'bloomberg\\.com'],
  internalLinks: [
    { url: '/listings', anchor: 'Browse Listings', type: 'search' },
    { url: '/about', anchor: 'About Us', type: 'home' },
  ],

  // Optional: Author profiles for E-E-A-T
  authors: [
    {
      id: 'john',
      name: 'John Smith',
      role: 'Senior Analyst',
      bio: '10+ years experience in market analysis...',
      credentials: ['PhD Economics', 'Published Author'],
    },
  ],

  // Optional: Workspace settings
  outputDir: '/tmp/blog-workspace',  // custom output dir
  keepWorkspace: true,               // don't auto-cleanup tmp dir

  // Optional: Lifecycle hooks
  hooks: {
    onLog: (msg) => console.log(msg),
    afterResearch: (research) => console.log(`Found ${research.contentGaps.length} gaps`),
    afterOutline: (outline) => console.log(`${outline.sections.length} sections planned`),
    afterDraft: (content) => console.log(`Draft: ${content.length} chars`),
    afterPolish: (content) => console.log('Final polish done'),
  },
})

Generate Options

const result = await blog.generate({
  lang: 'en',                          // language code
  topic: 'Your topic here',            // article topic
  targetKeyword: 'focus keyword',      // optional, defaults to topic
  wordCountTarget: 2000,               // optional, defaults to 2000
  author: myAuthor,                    // optional, overrides random selection
  hooks: { onLog: (msg) => {...} },    // optional, per-call hooks override config hooks
})

Result

interface GenerateResult {
  filePath: string              // path to final markdown file
  title: string                 // SEO-optimized title
  slug: string                  // URL-friendly slug
  metaDesc: string              // meta description (150-160 chars)
  content: string               // full markdown article
  author: Author                // author profile used
  charts: string[]              // CDN URLs of generated charts
  illustration?: string         // CDN URL of illustration
  seo: SeoMeta                  // OpenGraph, Twitter, focus keyword
  internalLinks: InternalLink[] // links found in content
  sources: Source[]             // external sources (government/news/research)
  validation: ValidationResults // wordCount, hasTLDR, hasFAQ, etc.
  research?: CompetitiveResearch // intermediate: competitor analysis
  outline?: ArticleOutline       // intermediate: structured outline
  costUsd?: number              // API cost in USD (if available)
}

Charts (standalone)

import { generateBarChart, generateLineChart, renderMermaidChart } from 'ai-blog-gen'

// Bar chart
const bar = await generateBarChart(
  { labels: ['A', 'B', 'C'], datasets: [{ label: 'Value %', data: [5.2, 4.8, 5.5], color: '#3b82f6' }] },
  'Comparison Chart',
  { storage: myStorage },
)

// Line chart
const line = await generateLineChart(
  [2020, 2021, 2022, 2023],
  [100, 120, 135, 150],
  'Price Trends',
  { storage: myStorage },
)

// Mermaid diagram
const mermaid = await renderMermaidChart('graph TD\n A-->B', { storage: myStorage })

Architecture

User config + topic
       |
Pi SDK Agent Session (multi-turn, cwd=tmpdir)
  +-- Phase 1: web search -> research.json
  +-- Phase 2: outline -> outline.json
  +-- Phase 3: draft -> blog.md
  +-- Phase 4: E-E-A-T + sources -> blog.md
  +-- Phase 5: title, TL;DR, FAQ -> blog.md + metadata.json
  +-- Optional: Mermaid diagrams -> chart-*.mmd
       |
Post-processing (Node.js)
  +-- Read files from tmpdir
  +-- Render charts (SVG -> WebP via Sharp)
  +-- Generate illustration (OpenRouter Flux)
  +-- Validate content
  +-- Extract links, sources, metadata
  +-- Upload via storage provider
       |
GenerateResult

License

MIT