AI Blog Generation
The CMS includes an AI-powered batch blog generation system using the Anthropic Claude API. This allows content editors to generate multiple blog posts in a single batch, significantly speeding up content creation.
Architecture
Editor submits topics → CMS API → Claude Batch API → Processing → Draft postsHow It Works
1. Submit Topics
Editors go to /admin/generate and provide:
- Topics — Up to 10 topics for batch generation
- Focus — Optional writing focus or angle (e.g., "budget travel", "luxury")
- Each topic becomes one blog post
2. Batch Submission
The CMS submits all topics as a single batch to the Claude Messages Batch API:
POST /api/generate
Body: { topics: string[], focus?: string }
Response: { batch: { id, batchId, status: "processing" } }3. Background Processing
The batch is processed asynchronously:
- CMS creates
GenerationBatchrecord with statuspending - Submits batch to Claude API, gets
batchIdback - Polls Claude for batch completion
- When complete, parses each result into structured post data
- Creates draft posts in the database
4. Results
Once processed, editors can view results at /admin/generate/{id}:
- See which posts were generated successfully
- Review generated content, titles, meta descriptions
- Edit and publish as needed
- Retry failed generations
Claude Prompt
The generation uses a detailed system prompt tailored for Nepalese travel content:
- First-person editorial "we" voice — Consistent brand voice
- Permit accuracy — Mentions required permits (e.g., TIMS, national park fees)
- EEAT compliance — Experience, Expertise, Authoritativeness, Trustworthiness
- Formatting rules — Proper heading hierarchy, paragraph structure, lists
- SEO metadata — Generates meta titles, meta descriptions, focus keyphrases
- JSON output — Structured result with title, excerpt, content, metadata
Example Generation Output
{
"title": "Best Time to Visit Everest Base Camp",
"excerpt": "Discover the optimal seasons for trekking to Everest Base Camp...",
"content": "<h2>Spring Season (March-May)</h2><p>Spring offers the most stable weather...</p>",
"focusKeyphrase": "best time to visit everest base camp",
"metaTitle": "Best Time to Visit Everest Base Camp | Complete Guide 2026",
"metaDescription": "Planning your Everest Base Camp trek? Our comprehensive guide covers the best seasons, weather patterns, and insider tips for an unforgettable Himalayan adventure."
}GenerationBatch Model
model GenerationBatch {
id String @id @default(cuid())
batchId String @unique // Claude batch API ID
topics String[] // Submitted topics
focus String? // Writing focus
status String @default("pending") // pending | processing | completed | failed
error String? // Error message if failed
}API Endpoints
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| POST | /api/generate | Admin | Submit topics for batch generation |
| GET | /api/generate | Admin | List all generation batches |
| GET | /api/generate/{id} | Admin | Get batch status and results |
| POST | /api/generate/{id}/process | Admin | Process a completed batch into draft posts |
Comparison: API vs CMS Generation
The original Express API also had blog generation features (blogGeneration.controller/, claude.service.ts). The CMS version is:
| Aspect | API (legacy) | CMS (current) |
|---|---|---|
| Generation | Single and batch | Batch only (but faster) |
| Import management | CSV import, row tracking | Topics submitted directly |
| Job control | Pause, resume, cancel, retry per row | Simple batch lifecycle |
| Daily limits | Configurable per job | None |
| Link management | Business link sync | Removed |
| Cron | Processing cron | Polling on demand |
| System prompt | Less detailed | More detailed (EEAT, permits) |
The CMS version is simpler and more focused — it generates posts directly without the complexity of imports, row-level tracking, and link management that the API version had.