Skip to content

Prompts Convention

Overview

All LLM prompts are stored as TypeScript string constants in the src/prompts/ directory. This approach provides type safety, eliminates runtime I/O overhead, and enables version control of prompts alongside code.

Directory Structure

src/
├── prompts/
│   ├── index.ts                  # Centralized exports
│   ├── storyGrader.prompts.ts    # Story grading prompts
│   ├── llmChat.prompts.ts        # Chat/coaching prompts
│   └── [feature].prompts.ts      # Additional feature prompts
└── docs/
    └── PROMPTS_CONVENTION.md     # This file

File Organization

Flat Structure

  • All prompt files live directly in src/prompts/ (no subdirectories)
  • Naming: <feature>.prompts.ts
  • Related prompts stay together in the same file

Example Structure

// prompts/storyGrader.prompts.ts

// Version 1 (archived)
export const STORY_GRADER_SYSTEM_V1 = `
You are a story grader...
`;

// Version 2 (current)
export const STORY_GRADER_SYSTEM_V2 = `
# SYSTEM: Story Essentials Checker
You are Guru's Story Essentials Checker...
{{{CRITERIA}}}
`;

// Active version pointer
export const STORY_GRADER_SYSTEM = STORY_GRADER_SYSTEM_V2;

// Interface for Handlebars template variables
export interface StoryGraderSystemVars extends Record<string, unknown> {
  CRITERIA: string;
}

// Additional related prompts
export const STORY_GRADER_USER = `
Story Content:
{{{CONTENT}}}
Please evaluate...
`;

export interface StoryGraderUserVars extends Record<string, unknown> {
  CONTENT: string;
}

Naming Conventions

File Names

  • Pattern: <feature>.prompts.ts
  • Lowercase with dot notation
  • Examples: storyGrader.prompts.ts, llmChat.prompts.ts, characterAnalysis.prompts.ts

Constant Names

  • Pattern: <FEATURE>_<TYPE>_V<N>
  • SCREAMING_SNAKE_CASE
  • Components:
  • FEATURE: The feature/domain (e.g., STORY_GRADER, LLM_CHAT)
  • TYPE: The prompt type (e.g., SYSTEM, USER, ASSISTANT)
  • V<N>: Version number (e.g., V1, V2, V3)

Active Version Pointer

  • Pattern: <FEATURE>_<TYPE> (no version suffix)
  • Always points to the current active version
  • Example: export const STORY_GRADER_SYSTEM = STORY_GRADER_SYSTEM_V2;

Interface Names

  • Pattern: <Feature><Type>Vars
  • PascalCase
  • Example: StoryGraderSystemVars, LlmChatSystemVars

Versioning

When to Create a New Version

  • Significant prompt changes that alter behavior
  • A/B testing different prompt approaches
  • Need to rollback capability

Version Management

  1. Keep old versions in the same file (don't delete)
  2. Add new version as separate constant with incremented version number
  3. Update pointer to point to new version
  4. Document changes in code comments or commit messages
// Version 1 - Original implementation
export const STORY_GRADER_SYSTEM_V1 = `...`;

// Version 2 - Added cohesion criteria (2025-01-15)
export const STORY_GRADER_SYSTEM_V2 = `...`;

// Version 3 - Refined rating scale (2025-02-01)
export const STORY_GRADER_SYSTEM_V3 = `...`;

// Active version
export const STORY_GRADER_SYSTEM = STORY_GRADER_SYSTEM_V3;

Template Variables

Using Handlebars Syntax

  • Use triple braces for unescaped content: {{{VARIABLE}}}
  • Define TypeScript interfaces for all template variables
  • All interfaces must extend Record<string, unknown> to be compatible with fillHandlebarsTemplate
  • Provides IDE autocomplete and type checking

Example with Type Safety

export const MY_PROMPT_SYSTEM_V1 = `
You are a {{{ROLE}}} that helps with {{{TASK}}}.
`;

export interface MyPromptSystemVars extends Record<string, unknown> {
  ROLE: string;
  TASK: string;
}

// Usage in code:
import { MY_PROMPT_SYSTEM, MyPromptSystemVars } from '@/prompts';
import SharedHelpers from '@/shared/sharedHelpers';

const vars: MyPromptSystemVars = {
  ROLE: 'coach',
  TASK: 'storytelling',
};

const compiled = SharedHelpers.fillHandlebarsTemplate(MY_PROMPT_SYSTEM, vars);

Centralized Exports

The prompts/index.ts file re-exports all prompts for easy importing:

// prompts/index.ts
export * from './storyGrader.prompts';
export * from './llmChat.prompts';

Usage in Code

// Import from centralized location
import { STORY_GRADER_SYSTEM, StoryGraderSystemVars } from '@/prompts';

// Or import directly
import { STORY_GRADER_SYSTEM } from '@/prompts/storyGrader.prompts';

Benefits

✅ No Runtime I/O

  • Prompts are bundled with application code
  • No file system reads at runtime
  • Better performance and reliability

✅ Type Safety

  • TypeScript interfaces for template variables
  • Compile-time checking of variable names
  • IDE autocomplete support

✅ Version Control

  • All versions in one file for easy comparison
  • Git history tracks prompt evolution
  • Easy rollback to previous versions

✅ Tree-Shakeable

  • Unused prompt versions can be removed by bundler
  • Smaller production bundles

✅ Developer Experience

  • Easy to find prompts (flat structure)
  • Clear naming conventions
  • Related prompts grouped together

Best Practices

  1. Keep prompts focused: One file per feature/domain
  2. Document changes: Add comments when creating new versions
  3. Type everything: Always define interfaces for template variables
  4. Use semantic names: Names should describe the prompt's purpose
  5. Don't delete old versions: Keep them for rollback capability
  6. Test after changes: Verify prompt behavior after updating
  7. Review regularly: Periodically audit and clean up very old versions