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

@iqai/prompt-weaver

v1.1.1

Published

A powerful template engine for building and rendering prompts with an extensible transformer system

Readme

Prompt Weaver

Craft Powerful, Type-Safe LLM Prompts with Ease

A powerful, extensible template engine built for the AI era. Prompt Weaver combines the flexibility of Handlebars with the safety of TypeScript and Zod/Standard Schema.

FeaturesQuick StartThe Two ApproachesTemplating SyntaxTransformersType Safety


📖 Introduction

Writing prompts for LLMs often involves messy string concatenation, zero type safety, and repetitive code. Prompt Weaver solves this by treating prompts like software artifacts.

It allows you to build dynamic prompts using templates, validate input data with schemas (Zod, Valibot, etc.), and transform data (dates, currency, arrays) directly within the prompt.

✨ Features

  • 🎨 Powerful Templating: Logic-rich templates with loops ({{#each}}), conditionals ({{#if}}), and switch/case logic.

  • ✅ Type Safety & Validation: First-class support for Standard Schema (Zod, ArkType, Valibot). Get automatic TypeScript type inference.

  • 🔧 Rich Toolset: Built-in transformers for Dates, Strings, JSON, Currencies, and Arrays.

  • 🏗️ Fluent Builder API: Construct prompts programmatically using a chainable JavaScript/TypeScript API with support for JSON, links, images, and checkboxes.

  • 🧩 Reusable Partials: Don't repeat yourself—compose prompts from reusable fragments (headers, footers, rules). Partials are pre-compiled for optimal performance.

  • ⚡ Performance Optimized: Template compilation caching and pre-compiled partials for faster rendering.

  • 🎯 Extensible: Create custom transformers and helpers to suit your specific domain.


📦 Installation

npm install @iqai/prompt-weaver

# or

pnpm add @iqai/prompt-weaver

# or

yarn add @iqai/prompt-weaver

🚀 Quick Start

1. The "Hello World"

Start simple. Define a template, inject data, and get a string.

import { PromptWeaver } from "@iqai/prompt-weaver";

// 1. Define a template with variables and a transformer
const template = "Hello {{name}}, your balance is {{currency balance}}.";

// 2. Initialize Weaver
const weaver = new PromptWeaver(template);

// 3. Render
const result = weaver.format({
  name: "Alice",
  balance: 1234.56
});

console.log(result);
// Output: "Hello Alice, your balance is $1,234.56."

2. The Feature Showcase

Here is a more complex example showing loops, conditionals, and formatting.

const template = `
You are helping {{userName}}.

## Task Details

- **Deadline**: {{relativeTime deadline}} ({{formatDate deadline "MMM DD"}})
- **Status**: {{#if isPremium}}⭐ Premium{{else}}Standard{{/if}}

## Requirements

{{#each requirements}}
{{increment @index}}. {{this}}
{{/each}}
`;

const weaver = new PromptWeaver(template);

const output = weaver.format({
  userName: "Alice",
  isPremium: true,
  deadline: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 days from now
  requirements: ["Plan project", "Review code"]
});

Output:

You are helping Alice.

## Task Details

- **Deadline**: in 7 days (Dec 12)
- **Status**: ⭐ Premium

## Requirements

1. Plan project
2. Review code

⚖️ The Two Approaches: Builder vs. Weaver

Prompt Weaver offers two ways to create prompts. You can use them separately or together.

| Feature | PromptWeaver | PromptBuilder | | :--- | :--- | :--- | | Best For... | Static templates, recurring tasks, separating content from code. | Dynamic logic, building prompts on the fly based on runtime conditions. | | Input | String template (Handlebars syntax). | Method chaining (Fluent API). | | Example | new PromptWeaver("Hello {{name}}") | new PromptBuilder().text("Hello").text(name) |

Using the Builder (Fluent API)

Perfect for when you need to construct a prompt logically in your code.

import { PromptBuilder } from "@iqai/prompt-weaver";

const builder = new PromptBuilder()
  .heading(1, "User Profile")
  .section("Info", "Name: {{name}}")
  .list(["Rule 1", "Rule 2"])
  .conditional(true, "✅ Verified", "❌ Unverified")
  .json({ version: "1.0", status: "active" }) // Format JSON
  .link("Documentation", "https://example.com") // Add markdown link
  .checkboxes([
    { text: "Task 1", checked: true },
    { text: "Task 2", checked: false }
  ]); // Add task list

// Convert to Weaver to render data
const weaver = builder.toPromptWeaver();
const output = weaver.format({ name: "Alice" });

Output:

# User Profile

## Info

Name: Alice

- Rule 1
- Rule 2

✅ Verified

```json
{
  "version": "1.0",
  "status": "active"
}
```

[Documentation](https://example.com)

- [x] Task 1
- [ ] Task 2

When to Use Each Approach

| Scenario | Use Builder | Use Weaver | Use Both | |----------|-------------|------------|----------| | Static template strings | ❌ | ✅ | ❌ | | Dynamic prompt construction | ✅ | ❌ | ✅ | | Template rendering with data | ❌ | ✅ | ✅ | | Reusable templates | ❌ | ✅ | ✅ | | Complex programmatic logic | ✅ | ❌ | ✅ |

Workflow: Build → Convert → Render

import { PromptBuilder } from "@iqai/prompt-weaver";

// Step 1: Build programmatically
const builder = new PromptBuilder()
  .heading(1, "User Dashboard")
  .section("Welcome", "Hello {{userName}}!")
  .section("Account Info", "Your balance is {{currency balance}}")
  .conditional(isPremium, "⭐ Premium Member", "Upgrade to Premium");

// Step 2: Convert to PromptWeaver for rendering
const weaver = builder.toPromptWeaver();

// Step 3: Render with data (can be called multiple times)
const output1 = weaver.format({ userName: "Alice", balance: 1000, isPremium: true });
const output2 = weaver.format({ userName: "Bob", balance: 500, isPremium: false });

// Output 1:
// # User Dashboard
//
// ## Welcome
//
// Hello Alice!
//
// ## Account Info
//
// Your balance is $1,000.00
//
// ⭐ Premium Member

// Output 2:
// # User Dashboard
//
// ## Welcome
//
// Hello Bob!
//
// ## Account Info
//
// Your balance is $500.00
//
// Upgrade to Premium

// Step 4: Optional - Validate with schema (TypeScript infers types automatically)
import { z } from 'zod';
const schema = z.object({
  userName: z.string(),
  balance: z.number(),
  isPremium: z.boolean(),
});

// TypeScript automatically infers types from the schema
const weaverWithSchema = builder.toPromptWeaver({ schema });

// format() automatically validates when schema is provided - TypeScript knows the exact shape
const validatedOutput = weaverWithSchema.format({ 
  userName: "Alice", 
  balance: 1000, 
  isPremium: true 
});

🎨 Templating Syntax

Prompt Weaver utilizes Handlebars syntax for control flow and data formatting.

Variable Interpolation & Transformers

Variables are interpolated using {{variableName}}. Format variables using transformers (Handlebars helpers): {{transformer variableName}} or {{transformer variableName arg1 arg2}}.

Basic examples:

Hello {{name}}!                        <!-- Simple variable -->
Hello {{capitalize name}}!             <!-- With transformer -->
Your balance is {{currency balance}}   <!-- Format as currency -->
Due {{relativeTime deadline}}         <!-- Relative time -->

Transformers allow you to format data directly within your templates without preprocessing. See the Built-in Transformers section below for available options.

Transformers with arguments:

{{ellipsis text 50}}                  <!-- Truncate to 50 chars -->
{{formatDate date "YYYY-MM-DD"}}      <!-- Format date with pattern -->
{{formatDate date "MMMM DD, YYYY"}}  <!-- Full month name: December 25, 2023 -->
{{formatDate date "DDDD, MMM DD"}}    <!-- Day name: Monday, Dec 25 -->
{{replace text "old" "new"}}          <!-- Replace text -->
{{filter users "status" "active"}}    <!-- Filter by property equals value -->
{{reduce numbers 0 "sum"}}            <!-- Reduce with operation -->

Chaining transformers in expressions:

{{#each (sort (filter users "active") "name")}}
  {{increment @index}}. {{capitalize name}} - {{currency balance}}
{{/each}}

Loops

{{#each items}}
  {{increment @index}}. {{this}}
{{else}}
  No items found.
{{/each}}

Conditionals

{{#if isPremium}}
  Premium Content
{{else}}
  Standard Content
{{/if}}

Switch/Case

{{#switch role}}
  {{#case "admin"}} You are an Admin {{/case}}
  {{#case "user"}} You are a User {{/case}}
{{/switch}}

Context Switching

{{#with user}}
  Name: {{name}}
  Email: {{email}}
{{/with}}

Special Variables

  • @index - Current index in {{#each}} loops (0-based)
  • @key - Current key in {{#each}} loops over objects
  • @first - true on first iteration
  • @last - true on last iteration
  • @root - Access root context from nested contexts
  • this - Current context value in loops

Partials (Reusable Fragments)

Define reusable template fragments that can be included anywhere using {{> partialName}}. Perfect for headers, footers, user cards, or any repeated sections.

Basic usage:

const template = "{{> header}}\n{{content}}\n{{> footer}}";
const weaver = new PromptWeaver(template, {
  partials: {
    header: "# {{title}}\n---",
    footer: "---\nPlease respond in JSON format."
  }
});

// Or register programmatically:
weaver.setPartial("header", "# {{title}}\n---");

Partials inherit the parent context and can include other partials. They can be reused across multiple PromptWeaver instances, enabling DRY principles.

Context Access & Nesting:

Partials inherit the parent context and can include other partials:

const template = "{{> pageLayout}}";
const weaver = new PromptWeaver(template, {
  partials: {
    pageLayout: `
{{> header}}
{{content}}
{{> footer}}
`,
    header: "# {{title}}\n---",
    footer: `---
Generated on {{formatDate date "YYYY-MM-DD"}}`
  }
});

const output = weaver.format({
  title: "My Page",
  content: "Main content here",
  date: new Date()
});

Real-World Example:

Compose complex prompts from reusable components:

const promptTemplate = `
{{> systemHeader}}
{{> taskSection}}
{{> outputFormat}}
`;

const weaver = new PromptWeaver(promptTemplate, {
  partials: {
    systemHeader: `You are {{role}}, an expert in {{domain}}.{{#if companyName}} Working for {{companyName}}.{{/if}}`,
    taskSection: `
## Task
{{taskDescription}}
{{#if requirements}}
## Requirements
{{#each requirements}}
- {{this}}
{{/each}}
{{/if}}
`,
    outputFormat: `{{#if jsonOutput}}Please respond in valid JSON format.{{else}}{{outputFormat}}{{/if}}`
  }
});

Reusability Example:

Partials can be reused across multiple PromptWeaver instances. Define a partial once and use it in different templates:

// Define a reusable partial template
const userCardPartial = `
## User Profile
- **Name**: {{name}}
- **Email**: {{email}}
- **Role**: {{role}}
{{#if isPremium}}⭐ Premium Member{{/if}}
---`;

// Use the same partial in multiple PromptWeaver instances
const emailTemplate = `{{> userCard}}\n\nYour account summary:\n{{summary}}`;
const reportTemplate = `{{> userCard}}\n\n## Activity Report\n{{report}}`;

const emailWeaver = new PromptWeaver(emailTemplate, {
  partials: { userCard: userCardPartial }
});

const reportWeaver = new PromptWeaver(reportTemplate, {
  partials: { userCard: userCardPartial }
});

// Both instances can use the same partial with different data
const emailOutput = emailWeaver.format({
  name: "Alice",
  email: "[email protected]",
  role: "Developer",
  isPremium: true,
  summary: "You have 5 unread messages."
});

const reportOutput = reportWeaver.format({
  name: "Alice",
  email: "[email protected]",
  role: "Developer",
  isPremium: true,
  report: "Last login: 2 hours ago"
});

Output:

## User Profile
- **Name**: Alice
- **Email**: [email protected]
- **Role**: Developer
⭐ Premium Member
---

Your account summary:
You have 5 unread messages.

The same userCard partial is reused in both templates, demonstrating how partials enable DRY (Don't Repeat Yourself) principles across your prompt templates.


🛠️ Built-in Transformers

Prompt Weaver comes with a massive library of transformers to format data directly inside your prompt.

📝 String & Content

| Transformer | Example | Result | | :--- | :--- | :--- | | upper | {{upper text}} | HELLO | | lower | {{lower text}} | hello | | capitalize | {{capitalize text}} | Hello | | ellipsis | {{ellipsis text 10}} | Hello w... | | json | {{json data}} | {"a":1} | | pluralize | {{pluralize word}} | apples |

Also available: replace, replaceAll, regexReplace, trim, trimStart, trimEnd, slugify, kebabCase, camelCase, snakeCase, split, join, truncate, slice, substring, padStart, padEnd, singularize

📖 View all String Transformers →

📅 Date & Time

| Transformer | Example | Result | | :--- | :--- | :--- | | formatDate | {{formatDate date "YYYY-MM-DD"}} | 2023-12-25 | | formatDate | {{formatDate date "MMMM DD, YYYY"}} | December 25, 2023 | | formatDate | {{formatDate date "DDDD, MMM DD"}} | Monday, Dec 25 | | relativeTime | {{relativeTime date}} | 2 hours ago | | isToday | {{isToday date}} | true/false |

Date format patterns: YYYY (4-digit year), YY (2-digit year), MMMM (full month), MMM (abbreviated month), MM (2-digit month), M (single digit month), DDDD (full day), DDD (abbreviated day), DD (2-digit day), D (single digit day), HH (hours), mm (minutes), ss (seconds)

Also available: formatTime, formatDateTime, isPast, isFuture, addDays, subtractDays, addHours, subtractHours, addMinutes, subtractMinutes, timestamp, unixTimestamp

📖 View all Date Transformers →

🔢 Math & Numbers

| Transformer | Example | Result | | :--- | :--- | :--- | | currency | {{currency price}} | $1,234.56 | | percent | {{percent val}} | 12.34% | | compact | {{compact views}} | 1.2M | | add | {{add 5 2}} | 7 |

Also available: subtract, multiply, divide, increment, price, signedPercent, signedCurrency, integer, number

📖 View all Number Transformers →

📊 Collections (Arrays/Objects)

| Transformer | Example | Description | | :--- | :--- | :--- | | filter | {{filter users "active"}} | Filter array by property truthiness | | filter | {{filter users "status" "active"}} | Filter array by property equals value | | map | {{map users "name"}} | Extract property from objects | | sort | {{sort items "price"}} | Sort array | | reduce | {{reduce numbers 0 "sum"}} | Reduce array with operation (sum, multiply, max, min, concat) | | first / last | {{first items}} | Get first/last item | | pick | {{pick user "name" "id"}} | Pick specific object keys |

Also available: find, findIndex, includes, reverse, nth, unique, groupBy, partition, chunk, flatten, arraySlice, length, reduce, get, has, keys, values, omit, merge, defaults, deepGet, isEmpty, isNotEmpty

📖 View all Collection Transformers →

🔀 Logic & Comparison

{{#if (eq status "active")}} ... {{/if}}
{{#if (gt age 18)}} ... {{/if}}
{{coalesce value "fallback"}}
{{ifElse isPremium "Rich" "Poor"}}

Also available: ne (not equal), gte, lt, lte, and, or, default, exists, isDefined

📖 View all Logic & Comparison Transformers →

📚 Complete Reference: See TRANSFORMERS.md for the full list of all available transformers with detailed examples and usage.


✅ Validation & Type Safety

This is where Prompt Weaver shines. By integrating Standard Schema (Zod, Valibot, ArkType), you get runtime validation AND build-time TypeScript inference automatically.

The "Magic" of Inference

You don't need to manually define interfaces. Just pass a schema, and format() automatically validates and enforces type safety.

import { z } from 'zod';
import { PromptWeaver } from "@iqai/prompt-weaver";

// 1. Define Schema
const schema = z.object({
  username: z.string(),
  age: z.number().positive(),
  email: z.string().email().optional()
});

// 2. Pass schema to Weaver
const weaver = new PromptWeaver(template, { schema });

// 3. Type-Safe Formatting with Automatic Validation
// TypeScript will now ERROR if you miss 'username' or if 'age' is a string!
// format() automatically validates the data against the schema at runtime
const output = weaver.format({
  username: "Alice", 
  age: 30,
  // email is optional, so we can omit it safely
});

// ❌ This will give a TypeScript error AND throw at runtime
// weaver.format({}); // Missing required fields

Validation Methods

  • weaver.format(data): Automatically validates when a schema is provided, renders, and throws error if invalid. Type-safe!
  • weaver.formatAsync(data): Automatically validates asynchronously when a schema is provided (use for schemas with async refinements/transforms). Returns a Promise.
  • weaver.validateSchema(data): Just runs validation, returning a success/failure object (doesn't render).

Example:

import { SchemaValidationError } from "@iqai/prompt-weaver";

// format() automatically validates when schema is provided
try {
  const output = weaver.format({ username: "Alice", age: 30 });
  console.log("Rendered:", output);
} catch (error) {
  if (error instanceof SchemaValidationError) {
    console.error("Validation errors:", error.issues);
  }
}

// formatAsync() for schemas with async validation
const schema = z.object({
  email: z.string().email().refine(async (email) => {
    return await checkEmailExists(email);
  }),
  name: z.string(),
});

const weaver = new PromptWeaver(template, { schema });
const output = await weaver.formatAsync({ email: "[email protected]", name: "Alice" });

// Or validate separately without rendering
const result = weaver.validateSchema({ username: "Alice", age: 30 });
if (result.success) {
  console.log("Valid data:", result.data); // ✅ TypeScript infers the output type
} else {
  console.error("Validation errors:", result.issues);
}

Async validation:

const result = await weaver.validateSchemaAsync({ username: "Alice", age: 30 });

[!NOTE] Prompt Weaver supports any Standard Schema-compatible validation library, including:

  • Zod (3.24+)
  • Valibot (1.0+)
  • ArkType (2.0+)
  • And other libraries that implement the Standard Schema specification

Template Validation

import { validateTemplate } from "@iqai/prompt-weaver";

const result = validateTemplate(templateSource);
if (!result.valid) {
  console.error("Template errors:", result.errors);
}

🧩 Advanced Usage

Composition

Merge multiple templates into one context. The compose method merges templates in the order they appear in the array, separated by two newlines (\n\n) by default.

const headerTemplate = "# {{title}}";
const bodyTemplate = "{{content}}";
const footerTemplate = "---\nGenerated on {{formatDate date}}";

// Templates are merged in order: header → body → footer
const composed = PromptWeaver.compose([headerTemplate, bodyTemplate, footerTemplate]);
const weaver = new PromptWeaver(composed);

const output = weaver.format({
  title: "My Document",
  content: "Main content here",
  date: new Date()
});

Output:

# My Document

Main content here

---
Generated on Dec 12, 2024

Custom Separator:

You can specify a custom separator between templates:

// Use a single newline instead of double newline
const composed = PromptWeaver.compose([headerTemplate, bodyTemplate], "\n");

// Use a custom separator
const composed = PromptWeaver.compose([headerTemplate, bodyTemplate], "\n---\n");

Direct Creation:

Or create a PromptWeaver instance directly from composed templates:

import { z } from 'zod';

const schema = z.object({
  title: z.string(),
  content: z.string(),
});

const weaver = PromptWeaver.composeAndCreate(
  [headerTemplate, bodyTemplate, footerTemplate],
  { schema }
);

Custom Transformers

Register your own logic globally or scoped to an instance.

Global Registration (Simple):

import { registerTransformer } from "@iqai/prompt-weaver";

// Simple transformer (no options)
registerTransformer("reverse", (str) => str.split("").reverse().join(""));
// Use: {{reverse text}}

// Transformer with options
registerTransformer("truncate", (value, maxLength) => {
  const str = String(value);
  const length = Number(maxLength) || 50;
  return str.length > length ? `${str.slice(0, length - 3)}...` : str;
});
// Use: {{truncate longText 100}}

Scoped Registry (Isolation):

import { TransformerRegistry } from "@iqai/prompt-weaver";

// Create isolated registry
const registry = TransformerRegistry.createScoped();
registry.registerTransformer("customHelper", (value, option1, option2) => {
  return `Custom: ${value} (${option1}, ${option2})`;
}, {
  description: "A custom helper with two options",
  version: "1.0.0"
});

// Only this instance uses this registry
const weaver = new PromptWeaver(template, { registry });

When to use which:

  • Global registration (registerTransformer()) - Use for shared transformers across your app
  • Scoped registry (TransformerRegistry.createScoped()) - Use for isolation, testing, or per-instance transformer sets

Core API Methods

PromptWeaver Class:

// Constructor
new PromptWeaver(templateSource, options?)

// Options
interface PromptWeaverOptions {
  registry?: TransformerRegistry; // Custom transformer registry (defaults to global)
  partials?: Record<string, string>; // Partial templates
  schema?: StandardSchemaV1; // Standard Schema validator (Zod, Valibot, ArkType, etc.)
  enableCache?: boolean; // Enable template compilation caching (default: true)
}

// Methods
weaver.format(data)                    // Render the template with data (automatically validates if schema provided)
weaver.formatAsync(data)               // Render asynchronously (use for schemas with async validation)
weaver.validateSchema(data)            // Validate data against schema (requires schema option)
weaver.extractVariables()              // Get required variables from template
weaver.setPartial(name, templateSource) // Register a partial template
weaver.getMetadata()                   // Get template metadata
PromptWeaver.compose(templateSources, separator?) // Compose multiple templates (static)

PromptBuilder Methods:

All methods return this for method chaining.

Content Methods:

  • .section(title?, content?) - Add a section (content can be string or function)
  • .text(text) - Add raw text content
  • .code(code, language?) - Add code block with optional language
  • .list(items, ordered?) - Add list (ordered or unordered)
  • .table(headers, rows) - Add markdown table
  • .heading(level, text) - Add heading (level 1-6)
  • .quote(text) - Add blockquote
  • .separator(char?) - Add separator line (default: "---")
  • .horizontalRule(char?) - Alias for separator
  • .json(data, indent?) - Format JSON data with indentation (default: 2 spaces)
  • .link(text, url) - Create markdown link
  • .image(alt, url, title?) - Create markdown image
  • .checkbox(text, checked?) - Add checkbox/task list item
  • .checkboxes(items) - Add multiple checkboxes (items can be strings or {text, checked} objects)

Control Flow Methods:

  • .conditional(condition, ifTrue, ifFalse?) - Add conditional content based on boolean
  • .loop(items, callback) - Add content by iterating over items

Utility Methods:

  • .build() - Build final prompt string
  • .toPromptWeaver(options?) - Convert to PromptWeaver instance for rendering
  • .clear() - Clear all content and start fresh

💡 Real-World Examples

Generates a structured prompt for reviewing PRs, handling code blocks and arrays of criteria.

const codeFence = "```";
const codeReviewTemplate = `
You are an expert code reviewer specializing in {{language}}.

## Code to Review

${codeFence}{{language}}
{{code}}
${codeFence}

## Review Criteria

{{#each criteria}}
- {{this}}
{{/each}}

## Context

- Repository: {{repoName}}
- Pull Request: #{{prNumber}}
- Author: {{authorName}}
- Files Changed: {{filesChanged}}

Please provide a thorough code review focusing on:
1. Code quality and best practices
2. Potential bugs or security issues
3. Performance optimizations
4. Test coverage recommendations

{{#if includeExamples}}
## Example Review Format

Please structure your review as:
- **Critical Issues**: List any blocking issues
- **Suggestions**: Improvement recommendations
- **Questions**: Clarifications needed
{{/if}}
`;

const weaver = new PromptWeaver(codeReviewTemplate);
const reviewPrompt = weaver.format({
  language: "TypeScript",
  code: "function calculateTotal(items: Item[]) { return items.reduce((sum, item) => sum + item.price, 0); }",
  criteria: [
    "Type safety and error handling",
    "Performance and scalability",
    "Code readability and maintainability"
  ],
  repoName: "my-app",
  prNumber: 42,
  authorName: "John Doe",
  filesChanged: 3,
  includeExamples: true
});

Takes raw data numbers and dates, formats them readable, and adds warnings if outliers are detected.

const analysisTemplate = `
You are a data analyst with expertise in {{domain}}.

## Dataset Overview

- **Total Records**: {{integer totalRecords}}
- **Date Range**: {{formatDate startDate "YYYY-MM-DD"}} to {{formatDate endDate "YYYY-MM-DD"}}
- **Key Metrics**: {{#each metrics}}{{this}}{{#unless @last}}, {{/unless}}{{/each}}

## Data Summary

{{#if hasOutliers}}
⚠️ **Note**: This dataset contains {{outlierCount}} outliers that may need special handling.
{{/if}}

## Analysis Request

{{request}}

{{#if includeVisualizations}}
## Visualization Requirements

Please suggest appropriate visualizations for:
{{#each visualizationTypes}}
- {{this}}
{{/each}}
{{/if}}

## Expected Output Format

1. **Executive Summary**: High-level insights (2-3 sentences)
2. **Key Findings**: {{findingsCount}} main observations
3. **Recommendations**: Actionable next steps
4. **Data Quality Notes**: Any concerns or limitations
`;

const analysisWeaver = new PromptWeaver(analysisTemplate);
const analysisPrompt = analysisWeaver.format({
  domain: "e-commerce",
  totalRecords: 125000,
  startDate: new Date("2024-01-01"),
  endDate: new Date("2024-03-31"),
  metrics: ["Revenue", "Conversion Rate", "Customer Lifetime Value"],
  hasOutliers: true,
  outlierCount: 47,
  request: "Analyze sales trends and identify factors contributing to revenue growth in Q1 2024.",
  includeVisualizations: true,
  visualizationTypes: ["Time series", "Cohort analysis", "Funnel visualization"],
  findingsCount: 5
});

Formats a customer ticket with history, deciding tone based on "Premium" status variables.

const supportTemplate = `
You are a customer support specialist for {{companyName}}.

## Customer Information

- **Name**: {{customerName}}
- **Account Type**: {{accountType}}
- **Member Since**: {{formatDate memberSince "MMMM YYYY"}}
{{#if isPremium}}
- ⭐ **Premium Member**
{{/if}}

## Issue Details

**Ticket ID**: {{ticketId}}
**Category**: {{category}}
**Priority**: {{upper priority}}
**Reported**: {{relativeTime reportedAt}}

**Description**:
{{issueDescription}}

{{#if previousTickets}}
## Previous Interactions

This customer has {{previousTickets.length}} previous {{pluralize "ticket" previousTickets.length}}:
{{#each previousTickets}}
- Ticket #{{ticketNumber}}: {{summary}} ({{status}})
{{/each}}
{{/if}}

{{#if orderHistory}}
## Recent Order History

{{#each orderHistory}}
- Order #{{orderNumber}}: {{productName}} - {{formatDate orderDate "MMM DD, YYYY"}} - {{capitalize status}}
{{/each}}
{{/if}}

## Response Guidelines

1. Acknowledge the customer's concern with empathy
2. Provide a clear, step-by-step solution
3. {{#if isPremium}}Offer priority escalation if needed{{else}}Suggest self-service options where appropriate{{/if}}
4. Set clear expectations for resolution timeline
5. End with a warm, helpful closing

Please draft a professional, helpful response that resolves their issue.
`;

const supportWeaver = new PromptWeaver(supportTemplate);
const supportPrompt = supportWeaver.format({
  companyName: "TechCorp",
  customerName: "Sarah Johnson",
  accountType: "Business",
  memberSince: new Date("2023-06-15"),
  isPremium: true,
  ticketId: "TC-2024-0847",
  category: "Billing",
  priority: "high",
  reportedAt: new Date(Date.now() - 2 * 60 * 60 * 1000), // 2 hours ago
  issueDescription: "I was charged twice for my subscription renewal. The charge appeared on both my credit card and PayPal account.",
  previousTickets: [
    { ticketNumber: "TC-2024-0721", summary: "Feature request", status: "resolved" }
  ],
  orderHistory: [
    { orderNumber: "ORD-1234", productName: "Pro Plan", orderDate: new Date("2024-03-01"), status: "completed" }
  ]
});

Build prompts dynamically based on runtime conditions:

import { PromptBuilder } from "@iqai/prompt-weaver";

const builder = new PromptBuilder()
  .heading(1, "AI Code Assistant")
  .section("Role", "You are an expert software engineer specializing in {{language}}.")
  .section("Task", "{{taskDescription}}");

// Conditionally add context section
if (includeContext) {
  builder
    .heading(2, "Context")
    .text("Current codebase:")
    .code(existingCode, "typescript")
    .text(`\nRelated files: ${relatedFiles.join(", ")}`);
}

// Build requirements section
builder.section("Requirements", () => {
  const reqBuilder = new PromptBuilder().list(requirements);
  if (hasConstraints) {
    reqBuilder.heading(3, "Constraints").list(constraints);
  }
  return reqBuilder.build();
});

builder.section("Output Format", "Please provide:\n1. Complete code solution\n2. Brief explanation\n3. Testing recommendations");

// Convert to PromptWeaver and render with data
const weaver = builder.toPromptWeaver();
const output = weaver.format({
  language: "TypeScript",
  taskDescription: "Create a function to calculate Fibonacci numbers",
  // ... other data
});

Key Benefits:

  • Build prompts programmatically with full control flow
  • Use conditionals, loops, and dynamic content
  • Convert to PromptWeaver for template rendering with variables
  • Validate data against the built template

⚠️ Error Handling

Prompt Weaver provides specific error classes for debugging with enhanced error messages.

  • SchemaValidationError: Thrown when data doesn't match your Zod/Valibot schema. Includes detailed validation issues.
  • TemplateCompilationError: Thrown when your Handlebars syntax is broken (e.g., unclosed tags). Includes surrounding code context, line numbers, and helpful suggestions.

Example:

import { SchemaValidationError, TemplateCompilationError } from "@iqai/prompt-weaver";
import { z } from 'zod';

const schema = z.object({
  name: z.string(),
  age: z.number(),
});

try {
  const weaver = new PromptWeaver(template, { schema });
  // format() automatically validates when schema is provided
  const output = weaver.format({ name: "Alice", age: 30 });
} catch (error) {
  if (error instanceof SchemaValidationError) {
    console.error("Validation failed:", error.issues);
    console.error(error.getFormattedMessage());
    // Detailed validation error messages from your schema library
  } else if (error instanceof TemplateCompilationError) {
    console.error(error.getFormattedMessage());
    // Enhanced error message includes:
    // - Line and column numbers
    // - Surrounding code context
    // - Helpful suggestions for fixing common errors
  }
}

Built with 💙 by IQ AI Team