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¶
- Keep old versions in the same file (don't delete)
- Add new version as separate constant with incremented version number
- Update pointer to point to new version
- 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 withfillHandlebarsTemplate - 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¶
- Keep prompts focused: One file per feature/domain
- Document changes: Add comments when creating new versions
- Type everything: Always define interfaces for template variables
- Use semantic names: Names should describe the prompt's purpose
- Don't delete old versions: Keep them for rollback capability
- Test after changes: Verify prompt behavior after updating
- Review regularly: Periodically audit and clean up very old versions