Prompt Patterns and Templates
Prompt Patterns and Templates
Once you understand prompting techniques, the next step is building a library of reusable patterns. Just like software design patterns, prompt patterns solve common problems in reliable, repeatable ways. This chapter gives you battle-tested templates you can copy, customize, and use immediately.
The Four Core Prompt Patterns
Most AI tasks fall into one of four categories:
| Pattern | What It Does | Example |
|---|---|---|
| Extraction | Pull structured data from unstructured text | Extract names, dates, and amounts from emails |
| Classification | Sort inputs into categories | Classify support tickets by type |
| Generation | Create new content from requirements | Write documentation, code, or marketing copy |
| Transformation | Convert one format to another | Rewrite code, translate languages, reformat data |
Let's build reusable templates for each.
Pattern 1: Extraction
Use extraction when you need to pull specific information out of unstructured text.
Template
Extract the following fields from the text below.
Return the result as valid JSON.
If a field is not found, use null.
Fields to extract:
- [field1]: [description and type]
- [field2]: [description and type]
- [field3]: [description and type]
Text:
"""
[paste text here]
"""
Real Example: Invoice Extraction
Extract the following fields from the invoice text below.
Return the result as valid JSON.
If a field is not found, use null.
Fields to extract:
- vendor_name: string, the company issuing the invoice
- invoice_number: string, the invoice or reference number
- date: string in YYYY-MM-DD format
- total_amount: number, the total due amount
- currency: string, 3-letter currency code
- line_items: array of { description: string, quantity: number, unit_price: number }
Text:
"""
INVOICE #INV-2024-0892
From: TechSupply Co.
Date: March 15, 2024
2x Wireless Mouse - $29.99 each
1x USB-C Hub - $49.99
5x HDMI Cable 6ft - $12.99 each
Subtotal: $174.92
Tax (8%): $13.99
Total Due: $188.91 USD
"""
In Code
async function extractInvoiceData(invoiceText: string) { const response = await openai.chat.completions.create({ model: "gpt-4o", messages: [ { role: "system", content: "You extract structured data from invoices. Always return valid JSON. Use null for missing fields." }, { role: "user", content: `Extract invoice data from this text:\n\n${invoiceText}` } ], response_format: { type: "json_object" }, // Forces valid JSON output temperature: 0, // Deterministic output for extraction }); return JSON.parse(response.choices[0].message.content); }
Pattern 2: Classification
Use classification when you need to sort inputs into predefined categories.
Template
Classify the following [input type] into exactly one of these categories:
[list of categories]
Rules:
- Choose the single best-fitting category
- If uncertain, choose the closest match
- Return only the category name, nothing else
[Input type]: "[the input to classify]"
Category:
Real Example: Support Ticket Classification
Classify the following support ticket into exactly one of these categories:
- billing
- technical-issue
- feature-request
- account-access
- general-question
Rules:
- Choose the single best-fitting category
- If the ticket spans multiple categories, choose the primary concern
- Return only the category name, nothing else
Ticket: "I was charged twice for my subscription this month. I need a refund for the duplicate charge."
Category:
In Code with Batch Processing
type TicketCategory = "billing" | "technical-issue" | "feature-request" | "account-access" | "general-question"; async function classifyTicket(ticketText: string): Promise<TicketCategory> { const response = await openai.chat.completions.create({ model: "gpt-4o-mini", // Smaller model is fine for classification messages: [ { role: "system", content: `You classify support tickets. Categories: billing, technical-issue, feature-request, account-access, general-question. Return only the category name.` }, { role: "user", content: ticketText } ], temperature: 0, max_tokens: 20, }); return response.choices[0].message.content.trim() as TicketCategory; } // Batch classify multiple tickets async function classifyTickets(tickets: string[]): Promise<TicketCategory[]> { const results = await Promise.all(tickets.map(classifyTicket)); return results; }
Pattern 3: Generation
Use generation when you need to create new content based on specifications.
Template
Generate [what] based on the following specifications:
Requirements:
- [requirement 1]
- [requirement 2]
- [requirement 3]
Tone: [professional/casual/technical/friendly]
Length: [word count or size constraint]
Audience: [who will read this]
Format: [how it should be structured]
Additional context:
[any relevant background information]
Real Example: API Documentation Generation
Generate API documentation for the following endpoint:
Endpoint: POST /api/v1/projects
Purpose: Creates a new project within an organization
Requirements:
- Requires Bearer token authentication
- Request body includes: name (required string), description (optional string),
visibility (enum: "public" | "private", default "private")
- Returns the created project object with id, createdAt, and owner fields
- Returns 400 for missing name, 401 for invalid token, 409 for duplicate name
Tone: Technical, concise
Format: Use sections: Description, Authentication, Request, Response, Errors, Example
Include: curl example and TypeScript fetch example
Pattern 4: Transformation
Use transformation when you need to convert content from one format or style to another.
Template
Transform the following [source format] into [target format].
Rules:
- [transformation rule 1]
- [transformation rule 2]
- [preservation rule — what to keep unchanged]
Source:
"""
[input content]
"""
Real Example: SQL to Firestore
Transform the following SQL query into a Firestore query using
the Firebase Admin SDK (Node.js/TypeScript).
Rules:
- Use the firebase-admin/firestore import style
- Handle the WHERE clauses with .where() chains
- Convert ORDER BY to .orderBy()
- Convert LIMIT to .limit()
- Return the equivalent TypeScript code
Source:
"""
SELECT * FROM products
WHERE category = 'electronics'
AND price < 500
AND inStock = true
ORDER BY price ASC
LIMIT 20
"""
Building a Prompt Library
Organize your prompts like you organize code — in a structured, reusable way:
// src/prompts/index.ts export const PROMPTS = { extraction: { invoice: (text: string) => ({ system: "You extract structured data from invoices. Return valid JSON.", user: `Extract from this invoice:\n\n${text}`, }), contactInfo: (text: string) => ({ system: "You extract contact information. Return valid JSON with fields: name, email, phone, company.", user: `Extract contact info:\n\n${text}`, }), }, classification: { sentiment: (text: string) => ({ system: "Classify sentiment as: positive, negative, or neutral. Return only the label.", user: text, }), supportTicket: (text: string) => ({ system: "Classify into: billing, technical-issue, feature-request, account-access. Return only the category.", user: text, }), }, generation: { commitMessage: (diff: string) => ({ system: "Write concise git commit messages in conventional commit format. One line, under 72 characters.", user: `Write a commit message for this diff:\n\n${diff}`, }), codeReview: (code: string) => ({ system: "Review code for bugs, performance, and best practices. Format: Issues, Suggestions, Score (1-10).", user: `Review this code:\n\n${code}`, }), }, transformation: { toTypeScript: (jsCode: string) => ({ system: "Convert JavaScript to TypeScript. Add proper types, interfaces, and type annotations. Do not change logic.", user: `Convert to TypeScript:\n\n${jsCode}`, }), simplify: (text: string) => ({ system: "Rewrite the text for a non-technical audience. Keep the meaning, remove jargon, use simple words.", user: `Simplify:\n\n${text}`, }), }, };
Using the Prompt Library
import { PROMPTS } from "@/prompts"; async function callAI(prompt: { system: string; user: string }) { const response = await openai.chat.completions.create({ model: "gpt-4o", messages: [ { role: "system", content: prompt.system }, { role: "user", content: prompt.user }, ], }); return response.choices[0].message.content; } // Usage const review = await callAI(PROMPTS.generation.codeReview(myCode)); const category = await callAI(PROMPTS.classification.supportTicket(ticketText)); const tsCode = await callAI(PROMPTS.transformation.toTypeScript(jsCode));
Prompt Chaining — Multi-Step Workflows
Some tasks are too complex for a single prompt. Prompt chaining breaks them into steps, where each step's output becomes the next step's input.
Example: Blog Post Pipeline
// Step 1: Generate an outline const outline = await callAI({ system: "You create blog post outlines. Return a structured outline with sections and key points.", user: "Create an outline for a blog post about 'Why TypeScript is worth learning in 2025'. Target audience: JavaScript developers.", }); // Step 2: Write each section using the outline const draft = await callAI({ system: "You write technical blog posts. Write in a conversational but authoritative tone. Use code examples.", user: `Write a complete blog post from this outline. 1500-2000 words.\n\nOutline:\n${outline}`, }); // Step 3: Edit and polish const finalPost = await callAI({ system: "You are a technical editor. Improve clarity, fix awkward phrasing, ensure code examples are correct, and add a compelling intro and conclusion.", user: `Edit and polish this blog post draft:\n\n${draft}`, }); // Step 4: Generate metadata const metadata = await callAI({ system: "Generate SEO metadata. Return JSON with: title (under 60 chars), description (under 160 chars), tags (array of 5-8 keywords).", user: `Generate metadata for this post:\n\n${finalPost}`, });
Example: Code Generation Pipeline
// Step 1: Design the data model const dataModel = await callAI({ system: "Design TypeScript interfaces for a Firestore data model.", user: "Design data models for a project management app with: projects, tasks, users, and comments.", }); // Step 2: Generate service code const serviceCode = await callAI({ system: "Generate a Firestore service file with CRUD operations.", user: `Create a service file based on these data models:\n\n${dataModel}`, }); // Step 3: Generate tests const tests = await callAI({ system: "Write unit tests using Vitest for Firestore service functions.", user: `Write tests for this service file:\n\n${serviceCode}`, });
When to Chain vs. Single Prompt
| Use Single Prompt | Use Chain |
|---|---|
| Task has one clear output | Task has multiple distinct phases |
| Output is under 500 words | Output would be 1000+ words |
| Simple transformation | Requires different "expertise" at each step |
| Classification or extraction | Generate, then refine, then validate |
Key Takeaways
- Most AI tasks fit four patterns: extraction, classification, generation, transformation
- Build a prompt library so you don't rewrite prompts from scratch
- Chain prompts for complex workflows — each step focused on one task
- Test your templates with edge cases before relying on them in production
- Iterate and improve — track which prompts produce the best results and refine them over time
Try it now: Identify three tasks you regularly do with AI. Write a reusable prompt template for each one, following the patterns in this chapter. Store them somewhere accessible so you can reuse and refine them.