pseo-ai
v1.4.0
Published
Programmatic SEO CLI — Generate SEO pages with AI and serve via local API for any CMS
Maintainers
Readme
PSEO
Programmatic SEO CLI — Generate SEO pages with AI and serve them via a local REST API for any CMS.
Built by metehan.ai
██████╗ ███████╗███████╗ ██████╗
██╔══██╗██╔════╝██╔════╝██╔═══██╗
██████╔╝███████╗█████╗ ██║ ██║
██╔═══╝ ╚════██║██╔══╝ ██║ ██║
██║ ███████║███████╗╚██████╔╝
╚═╝ ╚══════╝╚══════╝ ╚═════╝What is PSEO?
PSEO is a CLI tool that generates programmatic SEO pages using AI and serves them through a local REST API. This makes it universally compatible with any website platform — WordPress, Webflow, Framer, or your own custom CMS.
How it works:
- Provide seed data (keywords) as CSV or JSON
- PSEO generates full pages (title, meta description, HTML body) using your chosen AI
- Start the local API server
- Connect your CMS to the API endpoints to pull content
Supported AI Providers
| Provider | Model | API | |----------|-------|-----| | OpenAI | gpt-5.2 | Responses API | | Google Gemini | gemini-3-flash-preview / gemini-3-pro-preview | Generative AI | | Anthropic | claude-opus-4-6 | Messages API | | X.ai | grok-3 | OpenAI-compatible | | Qwen | qwen-max | OpenAI-compatible | | Ollama | any local model | Local |
Installation
npm install -g programmatic-seo
# or
npm install -g pseo-aiQuick Start
# Generate a page — just pass a keyword
pseo generate "best running shoes 2024"
# Generate multiple pages at once
pseo generate "best running shoes" "marathon training guide" "running injuries"
# Start the API server to access your pages
pseo serveYour pages are now available at http://localhost:3099/api/pages. Open http://localhost:3099 for the live dashboard.
Optional setup
# Interactive config wizard (set provider, API key, linking, etc.)
pseo init
# Bulk generate from a seed file
pseo generate -i seeds.csvCLI Commands
pseo init
Optional interactive setup wizard that creates pseo.config.json:
pseo initConfigures: AI provider, API key, language, tone, word count, internal linking, and server port. Not required — you can skip this and pass everything via flags or env vars.
pseo generate
Generate SEO pages — pass keywords directly or use a seed file:
# Simplest usage — just a keyword
pseo generate "best coffee makers"
# Multiple keywords
pseo generate "best coffee makers" "espresso vs drip coffee" "coffee grinder guide"
# With provider override
pseo generate "best coffee makers" -p gemini
# Interactive — prompts you for keywords
pseo generate
# Bulk from seed file (optional)
pseo generate -i seeds.csv
pseo generate -i seeds.json --provider anthropicOptions:
| Flag | Description |
|------|-------------|
| [keywords...] | One or more keywords as arguments |
| -i, --input <file> | Seed data file — CSV or JSON (optional) |
| -p, --provider <name> | AI provider override |
| -m, --model <name> | Model override |
| -k, --api-key <key> | API key override |
| -l, --language <lang> | Content language (default: en) |
pseo serve
Start the local API server with built-in dashboard:
pseo serve
pseo serve --port 8080Opens a dashboard at http://localhost:3099 with live page listing and an API documentation page at http://localhost:3099/docs.
Seed Data Format
CSV
keyword,category,slug
best running shoes 2024,shoes,best-running-shoes-2024
marathon training guide,training,
how to prevent running injuries,health,Required column: keyword. Optional: category, slug, custom_prompt.
JSON
[
{ "keyword": "best running shoes 2024", "category": "shoes" },
{ "keyword": "marathon training guide", "category": "training" }
]Or:
{
"keywords": ["best running shoes 2024", "marathon training guide"]
}REST API
Once pseo serve is running, these endpoints are available:
GET /api/health
{ "status": "ok", "timestamp": "2024-03-18T09:00:00Z" }GET /api/pages?page=1&limit=20
{
"data": [
{
"slug": "best-running-shoes-2024",
"keyword": "best running shoes 2024",
"title": "Best Running Shoes in 2024 — Complete Guide",
"meta_description": "Discover the top running shoes...",
"body": "<h2>Introduction</h2><p>...</p>",
"internal_links": [],
"published_date": "2024-03-18T00:00:00Z",
"created_at": "2024-03-18T09:00:00Z"
}
],
"total": 1,
"page": 1,
"limit": 20,
"totalPages": 1
}GET /api/pages/:slug
Returns a single page by slug.
POST /api/generate
Generate pages via API:
curl -X POST http://localhost:3099/api/generate \
-H "Content-Type: application/json" \
-d '{
"provider": "openai",
"seed_data": [
{ "keyword": "best coffee makers 2024" }
]
}'DELETE /api/pages/:slug
Delete a page by slug.
Internal Linking
PSEO can automatically add internal links to generated content:
From sitemap.xml:
{
"internalLinking": {
"enabled": true,
"source": "sitemap",
"sitemapUrl": "https://example.com/sitemap.xml"
}
}From manual URL list:
{
"internalLinking": {
"enabled": true,
"source": "manual",
"urls": [
"https://example.com/guide-1",
"https://example.com/guide-2"
]
}
}Both sources:
{
"internalLinking": {
"enabled": true,
"source": "both",
"sitemapUrl": "https://example.com/sitemap.xml",
"urls": ["https://example.com/extra-page"]
}
}CMS Integration Examples
WordPress (via WP REST API or custom plugin)
Fetch from PSEO API and create posts:
const response = await fetch("http://localhost:3099/api/pages");
const { data } = await response.json();
for (const page of data) {
await fetch("https://your-site.com/wp-json/wp/v2/posts", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Basic " + btoa("user:password"),
},
body: JSON.stringify({
title: page.title,
content: page.body,
status: "publish",
meta: { _yoast_wpseo_metadesc: page.meta_description },
}),
});
}Webflow (via CMS API)
const response = await fetch("http://localhost:3099/api/pages");
const { data } = await response.json();
for (const page of data) {
await fetch(`https://api.webflow.com/v2/collections/{id}/items`, {
method: "POST",
headers: {
Authorization: "Bearer YOUR_TOKEN",
"Content-Type": "application/json",
},
body: JSON.stringify({
fieldData: {
name: page.title,
slug: page.slug,
"meta-description": page.meta_description,
"post-body": page.body,
},
}),
});
}Config Reference
pseo.config.json:
{
"provider": "openai",
"model": "gpt-5.2",
"apiKey": "sk-...",
"language": "en",
"tone": "informative",
"wordCount": 1500,
"internalLinking": {
"enabled": false,
"source": "manual",
"urls": []
},
"server": {
"port": 3099,
"host": "localhost"
}
}Environment Variables
Instead of storing keys in the config file, use environment variables:
| Variable | Provider |
|----------|----------|
| OPENAI_API_KEY | OpenAI |
| GEMINI_API_KEY | Google Gemini |
| ANTHROPIC_API_KEY | Anthropic |
| XAI_API_KEY | X.ai (Grok) |
| QWEN_API_KEY | Qwen |
| OLLAMA_HOST | Ollama (default: http://localhost:11434) |
License
MIT — built by metehan.ai
