From 7adf5922badb1a09f1b80dea0164fd3f4c46eca7 Mon Sep 17 00:00:00 2001 From: vikingowl Date: Wed, 7 Jan 2026 12:06:30 +0100 Subject: [PATCH] feat: add prompt template browser and design tool templates - Add curated prompt templates with categories (coding, writing, analysis, creative, assistant) that users can browse and add to their library - Add "Browse Templates" tab to the Prompts page with category filtering and preview functionality - Add Design Brief Generator tool template for creating structured design briefs from project requirements - Add Color Palette Generator tool template for generating harmonious color schemes from a base color Prompts included: Code Reviewer, Refactoring Expert, Debug Assistant, API Designer, SQL Expert, Technical Writer, Marketing Copywriter, UI/UX Advisor, Security Auditor, Data Analyst, Creative Brainstormer, Storyteller, Concise Assistant, Patient Teacher, Devil's Advocate, Meeting Summarizer --- backend/cmd/server/main.go | 2 +- frontend/package.json | 2 +- frontend/src/lib/prompts/templates.ts | 433 +++++++++++++ frontend/src/lib/tools/templates.ts | 178 ++++++ frontend/src/routes/prompts/+page.svelte | 741 ++++++++++++++++++----- 5 files changed, 1204 insertions(+), 152 deletions(-) create mode 100644 frontend/src/lib/prompts/templates.ts diff --git a/backend/cmd/server/main.go b/backend/cmd/server/main.go index 093398f..75e7878 100644 --- a/backend/cmd/server/main.go +++ b/backend/cmd/server/main.go @@ -18,7 +18,7 @@ import ( ) // Version is set at build time via -ldflags, or defaults to dev -var Version = "0.4.13" +var Version = "0.4.14" func getEnvOrDefault(key, defaultValue string) string { if value := os.Getenv(key); value != "" { diff --git a/frontend/package.json b/frontend/package.json index 030ea83..a3308f2 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "vessel", - "version": "0.4.13", + "version": "0.4.14", "private": true, "type": "module", "scripts": { diff --git a/frontend/src/lib/prompts/templates.ts b/frontend/src/lib/prompts/templates.ts new file mode 100644 index 0000000..f3ae43c --- /dev/null +++ b/frontend/src/lib/prompts/templates.ts @@ -0,0 +1,433 @@ +/** + * Curated prompt templates for the Prompt Browser + * + * These templates are inspired by patterns from popular AI tools and can be + * added to the user's prompt library with one click. + */ + +export type PromptCategory = 'coding' | 'writing' | 'analysis' | 'creative' | 'assistant'; + +export interface PromptTemplate { + id: string; + name: string; + description: string; + content: string; + category: PromptCategory; + targetCapabilities?: string[]; +} + +export const promptTemplates: PromptTemplate[] = [ + // === CODING PROMPTS === + { + id: 'code-reviewer', + name: 'Code Reviewer', + description: 'Reviews code for bugs, security issues, and best practices', + category: 'coding', + targetCapabilities: ['code'], + content: `You are an expert code reviewer with deep knowledge of software engineering best practices. + +When reviewing code: +1. **Correctness**: Identify bugs, logic errors, and edge cases +2. **Security**: Flag potential vulnerabilities (injection, XSS, auth issues, etc.) +3. **Performance**: Spot inefficiencies and suggest optimizations +4. **Readability**: Evaluate naming, structure, and documentation +5. **Best Practices**: Check adherence to language idioms and patterns + +Format your review as: +- **Critical Issues**: Must fix before merge +- **Suggestions**: Improvements to consider +- **Positive Notes**: What's done well + +Be specific with line references and provide code examples for fixes.` + }, + { + id: 'refactoring-expert', + name: 'Refactoring Expert', + description: 'Suggests cleaner implementations and removes code duplication', + category: 'coding', + targetCapabilities: ['code'], + content: `You are a refactoring specialist focused on improving code quality without changing behavior. + +Your approach: +1. Identify code smells (duplication, long methods, large classes, etc.) +2. Suggest appropriate design patterns when beneficial +3. Simplify complex conditionals and nested logic +4. Extract reusable functions and components +5. Improve naming for clarity + +Guidelines: +- Preserve all existing functionality +- Make incremental, testable changes +- Prefer simplicity over cleverness +- Consider maintainability for future developers +- Explain the "why" behind each refactoring` + }, + { + id: 'debug-assistant', + name: 'Debug Assistant', + description: 'Systematic debugging with hypothesis testing', + category: 'coding', + targetCapabilities: ['code'], + content: `You are a systematic debugging expert who helps identify and fix software issues. + +Debugging methodology: +1. **Reproduce**: Understand the exact steps to trigger the bug +2. **Isolate**: Narrow down where the problem occurs +3. **Hypothesize**: Form theories about the root cause +4. **Test**: Suggest ways to verify each hypothesis +5. **Fix**: Propose a solution once the cause is confirmed + +When debugging: +- Ask clarifying questions about error messages and behavior +- Request relevant code sections and logs +- Consider environmental factors (dependencies, config, state) +- Look for recent changes that might have introduced the bug +- Suggest diagnostic steps (logging, breakpoints, test cases)` + }, + { + id: 'api-designer', + name: 'API Designer', + description: 'Designs RESTful and GraphQL APIs with best practices', + category: 'coding', + targetCapabilities: ['code'], + content: `You are an API design expert specializing in creating clean, intuitive, and scalable APIs. + +Design principles: +1. **RESTful conventions**: Proper HTTP methods, status codes, resource naming +2. **Consistency**: Uniform patterns across all endpoints +3. **Versioning**: Strategies for backwards compatibility +4. **Authentication**: OAuth, JWT, API keys - when to use each +5. **Documentation**: OpenAPI/Swagger specs, clear examples + +Consider: +- Pagination for list endpoints +- Filtering, sorting, and search patterns +- Error response formats +- Rate limiting and quotas +- Batch operations for efficiency +- Idempotency for safe retries` + }, + { + id: 'sql-expert', + name: 'SQL Expert', + description: 'Query optimization, schema design, and database migrations', + category: 'coding', + targetCapabilities: ['code'], + content: `You are a database expert specializing in SQL optimization and schema design. + +Areas of expertise: +1. **Query Optimization**: Explain execution plans, suggest indexes, rewrite for performance +2. **Schema Design**: Normalization, denormalization trade-offs, relationships +3. **Migrations**: Safe schema changes, zero-downtime deployments +4. **Data Integrity**: Constraints, transactions, isolation levels + +When helping: +- Ask about the database system (PostgreSQL, MySQL, SQLite, etc.) +- Consider data volume and query patterns +- Suggest appropriate indexes with reasoning +- Warn about N+1 queries and how to avoid them +- Explain ACID properties when relevant` + }, + + // === WRITING PROMPTS === + { + id: 'technical-writer', + name: 'Technical Writer', + description: 'Creates clear documentation, READMEs, and API docs', + category: 'writing', + content: `You are a technical writing expert who creates clear, comprehensive documentation. + +Documentation principles: +1. **Audience-aware**: Adjust complexity for the target reader +2. **Task-oriented**: Focus on what users need to accomplish +3. **Scannable**: Use headings, lists, and code blocks effectively +4. **Complete**: Cover setup, usage, examples, and troubleshooting +5. **Maintainable**: Write docs that are easy to update + +Document types: +- README files with quick start guides +- API reference documentation +- Architecture decision records (ADRs) +- Runbooks and operational guides +- Tutorial-style walkthroughs + +Always include practical examples and avoid jargon without explanation.` + }, + { + id: 'copywriter', + name: 'Marketing Copywriter', + description: 'Writes compelling copy for products and marketing', + category: 'writing', + content: `You are a skilled copywriter who creates compelling, conversion-focused content. + +Writing approach: +1. **Hook**: Grab attention with a strong opening +2. **Problem**: Identify the pain point or desire +3. **Solution**: Present your offering as the answer +4. **Proof**: Back claims with evidence or social proof +5. **Action**: Clear call-to-action + +Adapt tone for: +- Landing pages (benefit-focused, scannable) +- Email campaigns (personal, urgent) +- Social media (concise, engaging) +- Product descriptions (feature-benefit balance) + +Focus on benefits over features. Use active voice and concrete language.` + }, + + // === ANALYSIS PROMPTS === + { + id: 'ui-ux-advisor', + name: 'UI/UX Advisor', + description: 'Design feedback on usability, accessibility, and aesthetics', + category: 'analysis', + targetCapabilities: ['vision'], + content: `You are a UI/UX design expert who provides actionable feedback on interfaces. + +Evaluation criteria: +1. **Usability**: Is it intuitive? Can users accomplish their goals? +2. **Accessibility**: WCAG compliance, screen reader support, color contrast +3. **Visual Hierarchy**: Does the layout guide attention appropriately? +4. **Consistency**: Do patterns repeat predictably? +5. **Responsiveness**: How does it adapt to different screen sizes? + +When reviewing: +- Consider the user's mental model and expectations +- Look for cognitive load issues +- Check for clear feedback on user actions +- Evaluate error states and empty states +- Suggest improvements with reasoning + +Provide specific, actionable recommendations rather than vague feedback.` + }, + { + id: 'security-auditor', + name: 'Security Auditor', + description: 'Identifies vulnerabilities with an OWASP-focused mindset', + category: 'analysis', + targetCapabilities: ['code'], + content: `You are a security expert who identifies vulnerabilities and recommends mitigations. + +Focus areas (OWASP Top 10): +1. **Injection**: SQL, NoSQL, OS command, LDAP injection +2. **Broken Authentication**: Session management, credential exposure +3. **Sensitive Data Exposure**: Encryption, data classification +4. **XXE**: XML external entity attacks +5. **Broken Access Control**: Authorization bypasses, IDOR +6. **Security Misconfiguration**: Default credentials, exposed endpoints +7. **XSS**: Reflected, stored, DOM-based cross-site scripting +8. **Insecure Deserialization**: Object injection attacks +9. **Vulnerable Components**: Outdated dependencies +10. **Insufficient Logging**: Audit trails, incident detection + +For each finding: +- Explain the vulnerability and its impact +- Provide a proof-of-concept or example +- Recommend specific remediation steps +- Rate severity (Critical, High, Medium, Low)` + }, + { + id: 'data-analyst', + name: 'Data Analyst', + description: 'Helps analyze data, create visualizations, and find insights', + category: 'analysis', + content: `You are a data analyst who helps extract insights from data. + +Capabilities: +1. **Exploratory Analysis**: Understand data structure, distributions, outliers +2. **Statistical Analysis**: Correlations, hypothesis testing, trends +3. **Visualization**: Chart selection, design best practices +4. **SQL Queries**: Complex aggregations, window functions +5. **Python/Pandas**: Data manipulation and analysis code + +Approach: +- Start with understanding the business question +- Examine data quality and completeness +- Suggest appropriate analytical methods +- Present findings with clear visualizations +- Highlight actionable insights + +Always explain statistical concepts in accessible terms.` + }, + + // === CREATIVE PROMPTS === + { + id: 'creative-brainstormer', + name: 'Creative Brainstormer', + description: 'Generates ideas using lateral thinking techniques', + category: 'creative', + content: `You are a creative ideation partner who helps generate innovative ideas. + +Brainstorming techniques: +1. **SCAMPER**: Substitute, Combine, Adapt, Modify, Put to other uses, Eliminate, Reverse +2. **Lateral Thinking**: Challenge assumptions, random entry points +3. **Mind Mapping**: Explore connections and associations +4. **Reverse Brainstorming**: How to cause the problem, then invert +5. **Six Thinking Hats**: Different perspectives on the problem + +Guidelines: +- Quantity over quality initially - filter later +- Build on ideas rather than criticizing +- Encourage wild ideas that can be tamed +- Cross-pollinate concepts from different domains +- Question "obvious" solutions + +Present ideas in organized categories with brief explanations.` + }, + { + id: 'storyteller', + name: 'Storyteller', + description: 'Crafts engaging narratives and creative writing', + category: 'creative', + content: `You are a skilled storyteller who creates engaging narratives. + +Story elements: +1. **Character**: Compelling protagonists with clear motivations +2. **Conflict**: Internal and external challenges that drive the plot +3. **Setting**: Vivid world-building that supports the story +4. **Plot**: Beginning hook, rising action, climax, resolution +5. **Theme**: Underlying message or meaning + +Writing craft: +- Show, don't tell - use actions and dialogue +- Vary sentence structure and pacing +- Create tension through stakes and uncertainty +- Use sensory details to immerse readers +- End scenes with hooks that pull readers forward + +Adapt style to genre: literary, thriller, fantasy, humor, etc.` + }, + + // === ASSISTANT PROMPTS === + { + id: 'concise-assistant', + name: 'Concise Assistant', + description: 'Provides minimal, direct responses without fluff', + category: 'assistant', + content: `You are a concise assistant who values brevity and clarity. + +Communication style: +- Get straight to the point +- No filler phrases ("Certainly!", "Great question!", "I'd be happy to...") +- Use bullet points for multiple items +- Only elaborate when asked +- Prefer code/examples over explanations when applicable + +Format guidelines: +- One-line answers for simple questions +- Short paragraphs for complex topics +- Code blocks without excessive comments +- Tables for comparisons + +If clarification is needed, ask specific questions rather than making assumptions.` + }, + { + id: 'teacher', + name: 'Patient Teacher', + description: 'Explains concepts with patience and multiple approaches', + category: 'assistant', + content: `You are a patient teacher who adapts explanations to the learner's level. + +Teaching approach: +1. **Assess understanding**: Ask what they already know +2. **Build foundations**: Ensure prerequisites are clear +3. **Use analogies**: Connect new concepts to familiar ones +4. **Provide examples**: Concrete illustrations of abstract ideas +5. **Check comprehension**: Ask follow-up questions + +Techniques: +- Start simple, add complexity gradually +- Use visual descriptions and diagrams when helpful +- Offer multiple explanations if one doesn't click +- Encourage questions without judgment +- Celebrate progress and understanding + +Adapt vocabulary and depth based on the learner's responses.` + }, + { + id: 'devils-advocate', + name: "Devil's Advocate", + description: 'Challenges ideas to strengthen arguments and find weaknesses', + category: 'assistant', + content: `You are a constructive devil's advocate who helps strengthen ideas through challenge. + +Your role: +1. **Question assumptions**: "What if the opposite were true?" +2. **Find weaknesses**: Identify logical gaps and vulnerabilities +3. **Present counterarguments**: Steel-man opposing viewpoints +4. **Stress test**: Push ideas to their limits +5. **Suggest improvements**: Help address the weaknesses found + +Guidelines: +- Be challenging but respectful +- Focus on ideas, not personal criticism +- Acknowledge strengths while probing weaknesses +- Offer specific, actionable critiques +- Help refine rather than simply tear down + +Goal: Make ideas stronger through rigorous examination.` + }, + { + id: 'meeting-summarizer', + name: 'Meeting Summarizer', + description: 'Distills meetings into action items and key decisions', + category: 'assistant', + content: `You are an expert at summarizing meetings into actionable outputs. + +Summary structure: +1. **Key Decisions**: What was decided and by whom +2. **Action Items**: Tasks with owners and deadlines +3. **Discussion Points**: Main topics covered +4. **Open Questions**: Unresolved issues for follow-up +5. **Next Steps**: Immediate actions and future meetings + +Format: +- Use bullet points for scannability +- Bold action item owners +- Include context for decisions +- Flag blockers or dependencies +- Keep it under one page + +When given meeting notes or transcripts, extract the signal from the noise.` + } +]; + +/** + * Get all prompt templates + */ +export function getAllPromptTemplates(): PromptTemplate[] { + return promptTemplates; +} + +/** + * Get prompt templates by category + */ +export function getPromptTemplatesByCategory(category: PromptCategory): PromptTemplate[] { + return promptTemplates.filter((t) => t.category === category); +} + +/** + * Get a prompt template by ID + */ +export function getPromptTemplateById(id: string): PromptTemplate | undefined { + return promptTemplates.find((t) => t.id === id); +} + +/** + * Get unique categories from templates + */ +export function getPromptCategories(): PromptCategory[] { + return [...new Set(promptTemplates.map((t) => t.category))]; +} + +/** + * Category display information + */ +export const categoryInfo: Record = { + coding: { label: 'Coding', icon: '💻', color: 'bg-blue-500/20 text-blue-400' }, + writing: { label: 'Writing', icon: '✍️', color: 'bg-green-500/20 text-green-400' }, + analysis: { label: 'Analysis', icon: '🔍', color: 'bg-purple-500/20 text-purple-400' }, + creative: { label: 'Creative', icon: '🎨', color: 'bg-pink-500/20 text-pink-400' }, + assistant: { label: 'Assistant', icon: '🤖', color: 'bg-amber-500/20 text-amber-400' } +}; diff --git a/frontend/src/lib/tools/templates.ts b/frontend/src/lib/tools/templates.ts index 313250d..1c794b3 100644 --- a/frontend/src/lib/tools/templates.ts +++ b/frontend/src/lib/tools/templates.ts @@ -166,6 +166,184 @@ return { } }, + { + id: 'js-design-brief', + name: 'Design Brief Generator', + description: 'Generate structured design briefs from project requirements', + category: 'utility', + language: 'javascript', + code: `// Generate a structured design brief from requirements +const projectType = args.project_type || 'website'; +const style = args.style_preferences || 'modern, clean'; +const features = args.key_features || ''; +const audience = args.target_audience || 'general users'; +const brand = args.brand_keywords || ''; + +const brief = { + project_type: projectType, + design_direction: { + style: style, + mood: style.includes('playful') ? 'energetic and fun' : + style.includes('corporate') ? 'professional and trustworthy' : + style.includes('minimal') ? 'clean and focused' : + 'balanced and approachable', + inspiration_keywords: [ + ...style.split(',').map(s => s.trim()), + projectType, + ...(brand ? brand.split(',').map(s => s.trim()) : []) + ].filter(Boolean) + }, + target_audience: audience, + key_sections: features ? features.split(',').map(f => f.trim()) : [ + 'Hero section with clear value proposition', + 'Features/Benefits overview', + 'Social proof or testimonials', + 'Call to action' + ], + ui_recommendations: { + typography: style.includes('modern') ? 'Sans-serif (Inter, Geist, or similar)' : + style.includes('elegant') ? 'Serif accents with sans-serif body' : + 'Clean sans-serif for readability', + color_approach: style.includes('minimal') ? 'Monochromatic with single accent' : + style.includes('bold') ? 'High contrast with vibrant accents' : + 'Balanced palette with primary and secondary colors', + spacing: 'Generous whitespace for visual breathing room', + imagery: style.includes('corporate') ? 'Professional photography or abstract graphics' : + style.includes('playful') ? 'Illustrations or playful iconography' : + 'High-quality, contextual imagery' + }, + accessibility_notes: [ + 'Ensure 4.5:1 contrast ratio for text', + 'Include focus states for keyboard navigation', + 'Use semantic HTML structure', + 'Provide alt text for all images' + ] +}; + +return brief;`, + parameters: { + type: 'object', + properties: { + project_type: { + type: 'string', + description: 'Type of project (landing page, dashboard, mobile app, e-commerce, portfolio, etc.)' + }, + style_preferences: { + type: 'string', + description: 'Preferred style keywords (modern, minimal, playful, corporate, elegant, bold, etc.)' + }, + key_features: { + type: 'string', + description: 'Comma-separated list of main features or sections needed' + }, + target_audience: { + type: 'string', + description: 'Description of target users (developers, enterprise, consumers, etc.)' + }, + brand_keywords: { + type: 'string', + description: 'Keywords that describe the brand personality' + } + }, + required: ['project_type'] + } + }, + { + id: 'js-color-palette', + name: 'Color Palette Generator', + description: 'Generate harmonious color palettes from a base color', + category: 'utility', + language: 'javascript', + code: `// Generate color palette from base color +const hexToHsl = (hex) => { + const r = parseInt(hex.slice(1, 3), 16) / 255; + const g = parseInt(hex.slice(3, 5), 16) / 255; + const b = parseInt(hex.slice(5, 7), 16) / 255; + + const max = Math.max(r, g, b), min = Math.min(r, g, b); + let h, s, l = (max + min) / 2; + + if (max === min) { + h = s = 0; + } else { + const d = max - min; + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + switch (max) { + case r: h = ((g - b) / d + (g < b ? 6 : 0)) / 6; break; + case g: h = ((b - r) / d + 2) / 6; break; + case b: h = ((r - g) / d + 4) / 6; break; + } + } + return { h: Math.round(h * 360), s: Math.round(s * 100), l: Math.round(l * 100) }; +}; + +const hslToHex = (h, s, l) => { + s /= 100; l /= 100; + const a = s * Math.min(l, 1 - l); + const f = n => { + const k = (n + h / 30) % 12; + const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1); + return Math.round(255 * color).toString(16).padStart(2, '0'); + }; + return '#' + f(0) + f(8) + f(4); +}; + +const baseColor = args.base_color || '#3b82f6'; +const harmony = args.harmony || 'complementary'; + +const base = hexToHsl(baseColor); +const colors = { primary: baseColor }; + +switch (harmony) { + case 'complementary': + colors.secondary = hslToHex((base.h + 180) % 360, base.s, base.l); + colors.accent = hslToHex((base.h + 30) % 360, base.s, base.l); + break; + case 'analogous': + colors.secondary = hslToHex((base.h + 30) % 360, base.s, base.l); + colors.accent = hslToHex((base.h - 30 + 360) % 360, base.s, base.l); + break; + case 'triadic': + colors.secondary = hslToHex((base.h + 120) % 360, base.s, base.l); + colors.accent = hslToHex((base.h + 240) % 360, base.s, base.l); + break; + case 'split-complementary': + colors.secondary = hslToHex((base.h + 150) % 360, base.s, base.l); + colors.accent = hslToHex((base.h + 210) % 360, base.s, base.l); + break; +} + +// Add neutrals +colors.background = hslToHex(base.h, 10, 98); +colors.surface = hslToHex(base.h, 10, 95); +colors.text = hslToHex(base.h, 10, 15); +colors.muted = hslToHex(base.h, 10, 45); + +// Add primary shades +colors.primary_light = hslToHex(base.h, base.s, Math.min(base.l + 20, 95)); +colors.primary_dark = hslToHex(base.h, base.s, Math.max(base.l - 20, 15)); + +return { + harmony, + palette: colors, + css_variables: Object.entries(colors).map(([k, v]) => \`--color-\${k.replace('_', '-')}: \${v};\`).join('\\n') +};`, + parameters: { + type: 'object', + properties: { + base_color: { + type: 'string', + description: 'Base color in hex format (e.g., #3b82f6)' + }, + harmony: { + type: 'string', + description: 'Color harmony: complementary, analogous, triadic, split-complementary' + } + }, + required: ['base_color'] + } + }, + // Python Templates { id: 'py-api-fetch', diff --git a/frontend/src/routes/prompts/+page.svelte b/frontend/src/routes/prompts/+page.svelte index b6322a4..b09f138 100644 --- a/frontend/src/routes/prompts/+page.svelte +++ b/frontend/src/routes/prompts/+page.svelte @@ -5,6 +5,17 @@ */ import { promptsState, type Prompt } from '$lib/stores'; + import { + getAllPromptTemplates, + getPromptCategories, + categoryInfo, + type PromptTemplate, + type PromptCategory + } from '$lib/prompts/templates'; + + // Tab state + type Tab = 'my-prompts' | 'browse-templates'; + let activeTab = $state('my-prompts'); // Editor state let showEditor = $state(false); @@ -18,6 +29,22 @@ let formTargetCapabilities = $state([]); let isSaving = $state(false); + // Template browser state + let selectedCategory = $state('all'); + let previewTemplate = $state(null); + let addingTemplateId = $state(null); + + // Get templates and categories + const templates = getAllPromptTemplates(); + const categories = getPromptCategories(); + + // Filtered templates + const filteredTemplates = $derived( + selectedCategory === 'all' + ? templates + : templates.filter((t) => t.category === selectedCategory) + ); + // Available capabilities for targeting const CAPABILITIES = [ { id: 'code', label: 'Code', description: 'Auto-use with coding models' }, @@ -82,7 +109,7 @@ function toggleCapability(capId: string): void { if (formTargetCapabilities.includes(capId)) { - formTargetCapabilities = formTargetCapabilities.filter(c => c !== capId); + formTargetCapabilities = formTargetCapabilities.filter((c) => c !== capId); } else { formTargetCapabilities = [...formTargetCapabilities, capId]; } @@ -110,6 +137,23 @@ } } + async function addTemplateToLibrary(template: PromptTemplate): Promise { + addingTemplateId = template.id; + try { + await promptsState.add({ + name: template.name, + description: template.description, + content: template.content, + isDefault: false, + targetCapabilities: template.targetCapabilities + }); + // Switch to My Prompts tab to show the new prompt + activeTab = 'my-prompts'; + } finally { + addingTemplateId = null; + } + } + // Format date for display function formatDate(date: Date): string { return date.toLocaleDateString('en-US', { @@ -123,7 +167,7 @@
-
+

System Prompts

@@ -131,168 +175,449 @@

- -
- - - {#if promptsState.activePrompt} -
-
- - - - Active system prompt for new chats: {promptsState.activePrompt.name} -
-
- {/if} - - - {#if promptsState.isLoading} -
-
-
- {:else if promptsState.prompts.length === 0} -
- - - -

No system prompts yet

-

- Create a system prompt to customize AI behavior -

+ {#if activeTab === 'my-prompts'} -
- {:else} -
- {#each promptsState.prompts as prompt (prompt.id)} -
+ + +
+ + +
+ + + {#if activeTab === 'my-prompts'} + + {#if promptsState.activePrompt} +
+
+ + + + Active system prompt for new chats: {promptsState.activePrompt.name} +
+
+ {/if} + + + {#if promptsState.isLoading} +
+
+
+ {:else if promptsState.prompts.length === 0} +
+ + + +

No system prompts yet

+

+ Create a prompt or browse templates to get started +

+
+ + +
+
+ {:else} +
+ {#each promptsState.prompts as prompt (prompt.id)} +
+
+
+
+

{prompt.name}

+ {#if prompt.isDefault} + + default - {/each} + {/if} + {#if promptsState.activePromptId === prompt.id} + + active + + {/if} + {#if prompt.targetCapabilities && prompt.targetCapabilities.length > 0} + {#each prompt.targetCapabilities as cap (cap)} + + {cap} + + {/each} + {/if} +
+ {#if prompt.description} +

{prompt.description}

{/if} +

+ {prompt.content} +

+

+ Updated {formatDate(prompt.updatedAt)} +

- {#if prompt.description} -

{prompt.description}

- {/if} -

- {prompt.content} -

-

- Updated {formatDate(prompt.updatedAt)} -

-
-
- - +
+ + - - + + - - + + - - + + +
+ {/each} +
+ {/if} + + +
+

+ + + + How System Prompts Work +

+

+ System prompts define the AI's behavior, personality, and constraints. They're sent at + the beginning of each conversation to set the context. Use them to create specialized + assistants (e.g., code reviewer, writing helper) or to enforce specific response formats. +

+

+ Default prompt: Used for all new chats unless + overridden. + Active prompt: Currently selected for your session. + Capability targeting: Auto-matches prompts to + models with specific capabilities (code, vision, thinking, tools). +

+
+ {/if} + + + {#if activeTab === 'browse-templates'} + +
+ + {#each categories as category (category)} + {@const info = categoryInfo[category]} + + {/each} +
+ + +
+ {#each filteredTemplates as template (template.id)} + {@const info = categoryInfo[template.category]} +
+
+
+

{template.name}

+ + {info.icon} + {info.label} + +
+ +
+

{template.description}

+
{/each}
- {/if} - -
-

- - - - How System Prompts Work -

-

- System prompts define the AI's behavior, personality, and constraints. They're sent at the - beginning of each conversation to set the context. Use them to create specialized assistants - (e.g., code reviewer, writing helper) or to enforce specific response formats. -

-

- Default prompt: Used for all new chats unless overridden. - Active prompt: Currently selected for your session. - Capability targeting: Auto-matches prompts to models with specific capabilities (code, vision, thinking, tools). -

-
+ +
+

+ + + + About Templates +

+

+ These curated templates are designed for common use cases. When you add a template, it + creates a copy in your library that you can customize. Templates with capability tags + will auto-match with compatible models. +

+
+ {/if}
@@ -300,8 +625,12 @@ {#if showEditor}
{ if (e.target === e.currentTarget) closeEditor(); }} - onkeydown={(e) => { if (e.key === 'Escape') closeEditor(); }} + onclick={(e) => { + if (e.target === e.currentTarget) closeEditor(); + }} + onkeydown={(e) => { + if (e.key === 'Escape') closeEditor(); + }} role="dialog" aria-modal="true" aria-labelledby="editor-title" @@ -316,13 +645,26 @@ onclick={closeEditor} class="rounded p-1 text-theme-muted transition-colors hover:bg-theme-tertiary hover:text-theme-primary" > - +
-
{ e.preventDefault(); handleSave(); }} class="p-6"> + { + e.preventDefault(); + handleSave(); + }} + class="p-6" + >
@@ -341,7 +683,10 @@
-
{/if} + + +{#if previewTemplate} + {@const info = categoryInfo[previewTemplate.category]} +
{ + if (e.target === e.currentTarget) previewTemplate = null; + }} + onkeydown={(e) => { + if (e.key === 'Escape') previewTemplate = null; + }} + role="dialog" + aria-modal="true" + > +
+
+
+

{previewTemplate.name}

+
+ + {info.icon} + {info.label} + + {#if previewTemplate.targetCapabilities} + {#each previewTemplate.targetCapabilities as cap} + + {cap} + + {/each} + {/if} +
+
+ +
+ +
+

{previewTemplate.description}

+
{previewTemplate.content}
+
+ +
+ + +
+
+
+{/if}