Configure or debug LLM blog post generation using Vercel AI SDK and Google Gemini...
Blog generation package: packages/ai/
packages/ai/
โโโ src/
โ โโโ generate-post.ts # 2-step generation (analysis โ structured output)
โ โโโ config.ts # System instructions
โ โโโ schemas.ts # Zod schemas (postSchema, highlightSchema)
โ โโโ tags.ts # Tag constants (CARS_TAGS, COE_TAGS)
โ โโโ hero-images.ts # Hero image URLs
โ โโโ save-post.ts # Post persistence with idempotency
generateText() + Code Execution Tool + Extended Thinking โ Accurate calculationsgenerateObject() + Zod schema โ Type-safe structured output// Generate and persist (returns saved-post metadata, not the raw Zod object)
import { generateBlogContent } from "@motormetrics/ai";
const post = await generateBlogContent({
data: tokenisedData, // Pipe-delimited data
month: "October 2024",
dataType: "cars", // "cars" or "coe"
});
// post.postId, post.title, post.slug, post.excerpt
// postSchema
z.object({
title: z.string().max(100), // SEO title, max 60 chars preferred
excerpt: z.string().max(500), // Meta description, under 300 chars
content: z.string(), // Markdown (no H1)
tags: z.array(z.string()).min(1).max(10), // 3-5 tags, first is dataType
highlights: z.array(highlightSchema), // 3-6 key statistics
});
// highlightSchema
z.object({
value: z.string(), // "52.60%", "$125,000"
label: z.string(), // "Electric Vehicles Lead"
detail: z.string(), // "2,081 units registered"
});
export const CARS_TAGS = ["Cars", "Registrations", "Fuel Types", "Market Trends", ...] as const;
export const COE_TAGS = ["COE", "Quota Premium", "1st Bidding Round", "PQP", ...] as const;
Edit packages/ai/src/config.ts:
ANALYSIS_INSTRUCTIONS: For calculation logicGENERATION_INSTRUCTIONS: For output formatLow Quality Output: Check Step 1 analysis logs, verify Code Execution Tool runs Python
Schema Validation Errors: Check Zod constraints (max lengths, array bounds)
API Errors: Verify AI_GATEWAY_API_KEY, check Gateway quota/billing
AI_GATEWAY_API_KEY=... # Required (Vercel AI Gateway)
DATABASE_URL=... # Required for generate-and-save (Neon/Postgres)
BLOB_READ_WRITE_TOKEN=... # Required for local hero-image upload
packages/ai/AGENTS.md for full package documentation