Template System Implementation Plan
November 13, 2025 · View on GitHub
Goal: Modernize template system to support AI-powered workflows and multi-note scaffolding
Phase 1: AI-Powered Template Creation (2-3 days) ⭐ START HERE
Commands to Implement
-
noted.createTemplateWithAI- User describes template purpose (natural language input)
- AI generates template structure using existing Copilot integration
- Show preview webview with edit capability
- Save to
.noted-templates/with metadata
-
noted.enhanceTemplate- Select existing custom template
- AI analyzes and suggests improvements
- Preview changes before applying
Technical Implementation
// src/templates/TemplateGenerator.ts
export class TemplateGenerator {
async generateFromDescription(description: string): Promise<Template> {
// Use VS Code LLM API (like TagGenerator does)
const model = await this.selectCopilotModel();
const prompt = this.buildTemplateGenerationPrompt(description);
const response = await model.sendRequest([
vscode.LanguageModelChatMessage.User(prompt)
]);
// Parse AI response into template structure
return this.parseTemplateResponse(response);
}
}
Prompt Template for AI
You are a template generation assistant for a note-taking extension.
User wants: "{description}"
Generate a structured note template with:
1. Appropriate YAML frontmatter (tags, status, etc.)
2. Logical sections with headers
3. Placeholders for content (using {variable} syntax)
4. Helpful prompts and examples
5. Related note suggestions
Output format:
{
"name": "template-name",
"description": "brief description",
"category": "category",
"tags": ["tag1", "tag2"],
"variables": [
{"name": "var1", "type": "string", "required": true, "prompt": "Enter..."}
],
"content": "full template content with {variables}"
}
Configuration
// package.json contributions
"noted.templates.useAI": {
"type": "boolean",
"default": true,
"description": "Use AI to enhance template creation"
}
Phase 2: Multi-Note Workflow Bundles (3-4 days) ⭐⭐
Data Structure
// src/templates/TemplateMetadata.ts
export interface TemplateBundle {
id: string;
name: string;
description: string;
version: string;
author?: string;
variables: TemplateVariable[];
notes: BundleNote[];
post_create?: {
open_notes?: string[]; // Note names to open after creation
message?: string; // Success message to show
};
}
export interface BundleNote {
name: string; // Can include {variables}
template: string; // Template ID to use
folder: string; // Target folder (can include {variables})
description?: string;
links?: string[]; // Other note names to link to
}
export interface TemplateVariable {
name: string;
type: 'string' | 'number' | 'enum' | 'date' | 'boolean';
required?: boolean;
default?: any;
prompt?: string;
values?: string[]; // For enum type
}
Commands to Implement
-
noted.createBundle- Show picker with available bundles
- Collect variable values from user (multi-step input)
- Create all notes in bundle
- Establish wiki-links between notes
- Open specified notes
-
noted.createBundleFromTemplates- Select multiple existing templates
- Define relationships between them
- Save as new bundle
Implementation
// src/templates/BundleService.ts
export class BundleService {
async createFromBundle(bundleId: string): Promise<string[]> {
const bundle = await this.loadBundle(bundleId);
const variables = await this.collectVariables(bundle.variables);
const createdPaths: string[] = [];
// Create each note
for (const note of bundle.notes) {
const noteName = this.replaceVariables(note.name, variables);
const folder = this.replaceVariables(note.folder, variables);
const content = await this.generateNoteContent(note.template, variables);
// Add links to other notes in bundle
const linkedContent = this.addBundleLinks(content, note.links, variables);
const filePath = await this.createNote(folder, noteName, linkedContent);
createdPaths.push(filePath);
}
// Post-creation actions
if (bundle.post_create?.open_notes) {
await this.openNotes(bundle.post_create.open_notes, variables, createdPaths);
}
return createdPaths;
}
}
Example Bundle: Video Tutorial Workflow
// .noted-templates/bundles/video-tutorial.bundle.json
{
"id": "video-tutorial-complete",
"name": "Video Tutorial Workflow",
"description": "Script + text guide + resources for tutorial videos",
"version": "1.0.0",
"variables": [
{
"name": "topic",
"type": "string",
"required": true,
"prompt": "Tutorial topic (e.g., 'VS Code Debugging')"
},
{
"name": "duration",
"type": "number",
"default": 10,
"prompt": "Estimated duration in minutes"
},
{
"name": "level",
"type": "enum",
"values": ["beginner", "intermediate", "advanced"],
"default": "beginner",
"prompt": "Target audience level"
}
],
"notes": [
{
"name": "{topic}-script",
"template": "video-script",
"folder": "Tutorials/Scripts",
"description": "Video script and outline"
},
{
"name": "{topic}-guide",
"template": "text-guide",
"folder": "Tutorials/Guides",
"description": "Written companion guide",
"links": ["{topic}-script"]
},
{
"name": "{topic}-resources",
"template": "resources",
"folder": "Tutorials/Resources",
"description": "Assets and resource tracking",
"links": ["{topic}-script", "{topic}-guide"]
}
],
"post_create": {
"open_notes": ["{topic}-script"],
"message": "Tutorial workflow created! Start with the script."
}
}
Phase 3: Enhanced Template Metadata (2-3 days) ⭐⭐
Migrate from Plain Text to JSON
Current: .noted-templates/my-template.md (plain text)
New: .noted-templates/my-template.json (structured metadata)
// src/templates/TemplateMetadata.ts
export interface Template {
id: string;
name: string;
description: string;
category: string;
tags: string[];
version: string;
author?: string;
variables: TemplateVariable[];
ai_generation?: {
enabled: boolean;
sections?: string[]; // Which sections to generate
hints?: string[]; // Hints for AI
};
content: string; // Actual template content
// Metadata
created?: string;
modified?: string;
usage_count?: number;
}
Backward Compatibility
// src/services/templateService.ts
export async function loadTemplate(templateId: string): Promise<Template> {
const templatesPath = getTemplatesPath();
// Try JSON first
const jsonPath = path.join(templatesPath, `${templateId}.json`);
if (await pathExists(jsonPath)) {
const content = await readFile(jsonPath);
return JSON.parse(content) as Template;
}
// Fall back to .md/.txt for backward compatibility
const fileFormat = getFileFormat();
const textPath = path.join(templatesPath, `${templateId}.${fileFormat}`);
if (await pathExists(textPath)) {
const content = await readFile(textPath);
// Convert plain text template to Template object
return {
id: templateId,
name: templateId,
description: 'Legacy template',
category: 'Custom',
tags: [],
version: '1.0.0',
variables: extractVariablesFromContent(content),
content: content
};
}
throw new Error(`Template not found: ${templateId}`);
}
Migration Command
// noted.migrateTemplates
export async function handleMigrateTemplates() {
const legacyTemplates = await findLegacyTemplates();
if (legacyTemplates.length === 0) {
vscode.window.showInformationMessage('No legacy templates to migrate');
return;
}
const answer = await vscode.window.showInformationMessage(
`Migrate ${legacyTemplates.length} template(s) to new JSON format?`,
'Migrate', 'Cancel'
);
if (answer !== 'Migrate') return;
for (const template of legacyTemplates) {
await migrateTemplate(template);
}
vscode.window.showInformationMessage(
`Migrated ${legacyTemplates.length} templates successfully`
);
}
Phase 4: Template Browser UI (4-5 days) ⭐⭐⭐
Webview Implementation
Similar to existing graph view (src/graph/graphView.ts) and calendar view (src/calendar/calendarView.ts)
// src/templates/templateBrowserView.ts
export class TemplateBrowserView {
private panel: vscode.WebviewPanel | undefined;
async show() {
if (this.panel) {
this.panel.reveal();
return;
}
this.panel = vscode.window.createWebviewPanel(
'notedTemplateBrowser',
'Template Browser',
vscode.ViewColumn.One,
{ enableScripts: true }
);
this.panel.webview.html = this.getHtmlContent();
// Handle messages from webview
this.panel.webview.onDidReceiveMessage(async (message) => {
switch (message.command) {
case 'createFromTemplate':
await this.createFromTemplate(message.templateId);
break;
case 'editTemplate':
await this.editTemplate(message.templateId);
break;
case 'deleteTemplate':
await this.deleteTemplate(message.templateId);
break;
}
});
}
private getHtmlContent(): string {
// Return HTML with embedded Vue/React component
// Show template cards with preview, description, metadata
// Filter by category, tags, search
// Show usage statistics
}
}
UI Features
- Grid/List View: Template cards with icons, descriptions
- Filter Bar: By category, tags, author
- Search: Fuzzy search by name, description, content
- Preview: Hover or click to see template content
- Quick Actions:
- Create note from template
- Edit template
- Duplicate template
- Delete template
- Export template
- Statistics: Usage count, last used date, rating
- Sorting: By name, usage, date created, date modified
Command
// noted.showTemplateBrowser
export async function handleShowTemplateBrowser() {
const browser = new TemplateBrowserView(context);
await browser.show();
}
Configuration Settings
Add to package.json
{
"contributes": {
"configuration": {
"title": "Noted Templates",
"properties": {
"noted.templates.useAI": {
"type": "boolean",
"default": true,
"description": "Use AI to enhance template creation and suggestions"
},
"noted.templates.defaultCategory": {
"type": "string",
"default": "General",
"description": "Default category for new custom templates"
},
"noted.templates.enableBundles": {
"type": "boolean",
"default": true,
"description": "Enable multi-note workflow bundles"
},
"noted.templates.showBrowser": {
"type": "boolean",
"default": false,
"description": "Show template browser instead of quick pick (requires restart)"
},
"noted.templates.aiModel": {
"type": "string",
"default": "gpt-4o",
"enum": ["gpt-4o", "gpt-3.5-turbo"],
"description": "AI model to use for template generation"
}
}
}
}
}
Commands to Register
Add to extension.ts
// Template commands (Phase 1)
context.subscriptions.push(
vscode.commands.registerCommand('noted.createTemplateWithAI',
() => handleCreateTemplateWithAI()),
vscode.commands.registerCommand('noted.enhanceTemplate',
() => handleEnhanceTemplate())
);
// Template commands (Phase 2)
context.subscriptions.push(
vscode.commands.registerCommand('noted.createBundle',
() => handleCreateBundle()),
vscode.commands.registerCommand('noted.createBundleFromTemplates',
() => handleCreateBundleFromTemplates())
);
// Template commands (Phase 3-4)
context.subscriptions.push(
vscode.commands.registerCommand('noted.showTemplateBrowser',
() => handleShowTemplateBrowser()),
vscode.commands.registerCommand('noted.migrateTemplates',
() => handleMigrateTemplates())
);
Add to package.json commands
{
"contributes": {
"commands": [
{
"command": "noted.createTemplateWithAI",
"title": "Create Template with AI",
"category": "Noted"
},
{
"command": "noted.enhanceTemplate",
"title": "Enhance Template with AI",
"category": "Noted"
},
{
"command": "noted.createBundle",
"title": "Create Notes from Bundle",
"category": "Noted"
},
{
"command": "noted.createBundleFromTemplates",
"title": "Create Bundle from Templates",
"category": "Noted"
},
{
"command": "noted.showTemplateBrowser",
"title": "Show Template Browser",
"category": "Noted"
},
{
"command": "noted.migrateTemplates",
"title": "Migrate Templates to JSON Format",
"category": "Noted"
}
]
}
}
Testing Plan
Unit Tests
TemplateGenerator.test.ts- AI generation, prompt buildingBundleService.test.ts- Variable replacement, note creation, linkingTemplateParser.test.ts- JSON parsing, validationTemplateMetadata.test.ts- Type conversions, validation
Integration Tests
- Create template with AI → save → load → verify
- Create bundle → verify all notes created → verify links
- Migrate legacy template → verify structure → verify content
Manual Testing
- Create template with description "video tutorial script"
- Verify AI generates appropriate structure
- Edit and save template
- Create bundle from multiple templates
- Execute bundle → verify all notes created
- Check wiki-links between notes
- Open template browser → filter, search, preview
- Migrate existing template → verify backward compatibility
Rollout Strategy
Version 1.41.0: AI Template Creation
- New command:
noted.createTemplateWithAI - New command:
noted.enhanceTemplate - Documentation: How to use AI template creation
- Release notes: "AI-powered template creation - describe what you need and let Copilot generate the structure"
Version 1.42.0: Multi-Note Bundles
- New command:
noted.createBundle - Bundle format specification
- Example bundles (video tutorial, project, sprint)
- Migration path for existing workflows
- Release notes: "Multi-note workflow bundles - create related notes with automatic linking"
Version 1.43.0: Enhanced Metadata
- JSON template format
- Variable type system
- Migration command
- Backward compatibility with existing templates
- Release notes: "Enhanced template system with rich metadata and variable types"
Version 1.44.0: Template Browser
- Template browser webview
- Filter, search, preview capabilities
- Usage statistics
- Template sharing (export/import)
- Release notes: "Visual template browser with search, filtering, and statistics"
Documentation Updates
Update Files
- CLAUDE.md - Document new template architecture
- README.md - Add template features to feature list
- docs/templates.md - Comprehensive template guide
- Basic templates
- AI-powered templates
- Multi-note bundles
- Variable reference
- Bundle format specification
- Best practices
New Documentation
- docs/bundles.md - Bundle format specification and examples
- docs/ai-templates.md - AI template generation guide
- TEMPLATE_MIGRATION.md - Migration guide for v1.43.0
Questions & Decisions Needed
1. Template Format
- JSON (structured, strongly typed, validatable) ← Recommended
- YAML (more readable, less verbose)
- Hybrid (metadata in JSON, content in markdown)
2. Storage Structure
- Current:
.noted-templates/*.{md,txt} - Option A:
.noted-templates/templates/*.json+.noted-templates/bundles/*.json - Option B: Keep flat structure, differentiate by file extension ← Recommended
3. AI Behavior
- Always suggest AI generation for new templates
- Opt-in per template via checkbox
- Global setting (on/off) ← Recommended (default: on)
4. Bundle Execution
- Create all notes immediately
- Create notes progressively (one at a time with preview)
- Hybrid (create structure, user fills in) ← Recommended
5. Variable Collection UI
- Quick pick for each variable (current approach)
- Single form with all variables ← Recommended (better UX)
- Webview with rich input controls (future enhancement)
Success Metrics
Adoption
- % of users who create at least one custom template
- % of users who use AI template creation
- % of users who create bundles
- Average templates per user
Usage
- Template usage frequency (uses per week)
- Most popular templates (built-in vs custom)
- Bundle usage vs single templates
- AI enhancement acceptance rate
Quality
- Template rating (if we add rating feature)
- Template duplication rate (indicates reuse)
- Templates shared (if we add sharing)
Timeline Estimate
Total: 11-15 days (2.5-3 weeks)
- Phase 1: 2-3 days (AI template creation)
- Phase 2: 3-4 days (Multi-note bundles)
- Phase 3: 2-3 days (Enhanced metadata)
- Phase 4: 4-5 days (Template browser)
Recommendation: Start with Phase 1 to validate AI integration, then proceed to Phase 2 for your video tutorial use case. Phases 3 & 4 can be done in parallel or deferred.
Next Steps
- ✅ Review implementation plan
- 🎯 Approve Phase 1 approach
- 🎯 Create
src/templates/directory structure - 🎯 Implement
TemplateGenerator.ts(copy pattern fromTagGenerator.ts) - 🎯 Create AI prompt for template generation
- 🎯 Build template creation command
- 🎯 Test with video tutorial template example
- 🎯 Document and release v1.41.0