- Automatic browser geolocation capture on event creation - Reverse geocoding via Nominatim API for place names - Full-text search with SQLite FTS5 - Calendar view for browsing past entries - DateNavigator component for day navigation - SearchModal with Ctrl+K shortcut - QuickAddWidget with Ctrl+J shortcut - Starlight documentation site with GitHub Pages deployment - Multiple AI provider support (Groq, OpenAI, Anthropic, Ollama, LM Studio) - Multi-user registration support BREAKING: Events now include latitude/longitude/placeName fields
17 KiB
AI Diary Style Feature Specification
Overview
This document outlines a feature allowing users to customize the writing style/voice of AI-generated diary pages. Currently, the journal generation uses a fixed system prompt stored in Settings. This feature would provide a more robust, user-friendly way to define and manage diary writing styles.
Feature Description
Users can select from predefined style presets or create custom styles that influence how the AI writes their diary pages. Each style defines tone, voice, formatting preferences, and specific writing guidelines that get injected into the generation prompt.
Core Capabilities
- Style Presets: Pre-defined writing styles (formal, casual, poetic, etc.)
- Custom Styles: User-defined styles with full control over prompt components
- Per-Diary Override: Ability to use a different style for specific dates
- Style Preview: Generate a sample diary to preview style before use
- Multiple Presets: Create and switch between multiple saved styles
Style Preset Definitions
1. Formal
Voice: Professional, polished, articulate
Use Case: Users who want their diary to read like well-crafted prose
System Prompt Component:
You write in a formal, articulate style. Use complete sentences and proper grammar.
Avoid contractions and colloquialisms. Maintain a reflective, thoughtful tone.
Structure your diary with clear paragraphs that flow logically.
Sample Output:
Today began with considerable promise. The morning meeting concluded successfully, yielding clarity on the project timeline. Subsequent hours were devoted to deep work, punctuated by brief exchanges with colleagues. The afternoon brought an unexpected interruption, though it proved fruitful in unexpected ways. Tomorrow presents new challenges that require careful preparation.
2. Casual
Voice: Relaxed, friendly, conversational
Use Case: Users who want their diary to feel like chatting with a good friend
System Prompt Component:
Write in a casual, friendly tone as if talking to a close friend. Use contractions naturally.
Keep it relaxed and easygoing. Short sentences are fine. Include natural pauses and "ums."
Make it feel like you're debriefing the day with someone who gets you.
Sample Output:
So here's how today went... The morning was pretty productive, got through most of my todo list before lunch which was nice. Had this weird interaction with a coworker around 2pm that threw me off for a bit, but I think we figured it out. The rest of the afternoon flew by. Anyway, tomorrow's another day!
3. Poetic
Voice: Literary, evocative, lyrical
Use Case: Users who appreciate beautiful, descriptive language
System Prompt Component:
Write in a poetic, literary style. Use sensory details, metaphors, and evocative language.
Let sentences breathe with varied rhythm. Paint scenes with words. Find beauty in ordinary moments.
Use occasional line breaks for emphasis. Let the writing have a lyrical quality.
Sample Output:
The light crept through the window this morning like a slow, golden tide. Meetings blurred together—a symphony of voices and shifting priorities. There was a moment, somewhere between the third cup of coffee and the afternoon's weight, when the world seemed to hold its breath. Tonight, the stars are sharp and numerous. Tomorrow, another page turns.
4. Minimalist
Voice: Concise, direct, stripped-back
Use Case: Users who prefer brevity and clarity over elaboration
System Prompt Component:
Write in a minimalist style. Keep sentences short and direct. Cut unnecessary words.
No flourishes or embellishments. Get to the point. Use bullet points if helpful.
Focus on facts and essential observations only. Less is more.
Sample Output:
- Morning: Team sync, focused work block
- Afternoon: Client call, project review
- Evening: Walk, read Notable: Finally resolved the bug that's been nagging me Tomorrow: Deadline for presentation
5. Conversational
Voice: Warm, personal, storytelling
Use Case: Users who want their diary to feel like telling a story
System Prompt Component:
Write as if telling a story to someone who cares. First person, warm and personal.
Use "I" naturally. Describe things the way you'd explain them to a friend.
Include small details that bring the day to life. Make it feel present and immediate.
Sample Output:
So I have to tell you about today—it was one of those days where everything just clicked, you know? First thing this morning I sat down and finally cracked that problem I've been working on for weeks. The feeling was amazing. Then at lunch I ran into this old friend I hadn't seen in forever and we talked for an hour. The rest of the day was chill by comparison. I'm really grateful for days like this.
6. Reflective
Voice: Introspective, thoughtful, philosophical
Use Case: Users who want to explore the meaning behind their days
System Prompt Component:
Write with an introspective, reflective lens. Explore what events meant, not just what happened.
Ask yourself questions. Examine patterns and connections. Go deeper than surface events.
Consider what you learned, what surprised you, what you'll carry forward.
Sample Output:
What strikes me most about today is how the small moments added up to something meaningful. The conversation with the new team member revealed that sometimes the most valuable insights come from unexpected places. I notice I've been carrying some anxiety about the project, yet today's progress reminded me that I've handled difficult things before. What does it mean to be building something that matters? These questions linger as the day closes.
Prompt Engineering for Each Style
Structure Comparison
All styles share this base structure:
- Style Directive: How to write (tone, voice)
- Content Requirements: What to include
- Structure Guidance: How to organize
- Example Integration: From user events
Style-Specific Additions
| Style | Sentence Length | Emotion | Formatting | Vocabulary |
|---|---|---|---|---|
| Formal | Long, complex | Moderate | Paragraphs | Sophisticated |
| Casual | Short-mixed | High | Mixed | Simple |
| Poetic | Varied | Very high | Line breaks | Rich |
| Minimalist | Very short | Low | Lists/bullets | Plain |
| Conversational | Short-medium | High | Paragraphs | Colloquial |
| Reflective | Medium-long | High | Open paragraphs | Thoughtful |
JSON Response Handling
The AI returns JSON for title + content. Style affects:
- Title style: Formal (proper nouns), Casual (lowercase ok), Poetic (evocative)
- Content style: Applied through system prompt injection
UI for Selecting/Creating Styles
Settings Page Addition
┌─────────────────────────────────────────────────────┐
│ DIARY STYLE │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Current Style: [Casual ▼] [Preview] │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ STYLE PRESETS [+ Create New] │
│ ┌─────────────────────────────────────────────────┐ │
│ │ ● Formal │ │
│ │ ○ Casual │ │
│ │ ○ Poetic │ │
│ │ ○ Minimalist │ │
│ │ ○ Custom: Morning Pages │ │
│ └─────────────────────────────────────────────────┘ │
Style Editor Modal
┌─────────────────────────────────────────────────────┐
│ CREATE / EDIT STYLE │
│ │
│ Name: [ ] │
│ │
│ Style Directive: │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Write in a... │ │
│ │ │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ Content Requirements: │
│ ┌─────────────────────────────────────────────────┐ │
│ │ • Summarize key events │ │
│ │ • Include emotions and reflections │ │
│ │ • End with forward-looking thought │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ Example Tone (optional): │
│ ┌─────────────────────────────────────────────────┐ │
│ │ "Today was a good day. I felt..." │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ [Cancel] [Save Style] │
└─────────────────────────────────────────────────────┘
Per-Diary Style Override
On the journal generation page (/journal/:date):
┌─────────────────────────────────────────────────────┐
│ GENERATE DIARY [⚙ Style: Casual]│
└─────────────────────────────────────────────────────┘
Clicking style button opens dropdown to override for this single generation.
Style Preview Feature
Generate a "test" diary using current events + selected style:
- Modal shows generated preview
- "Apply this style" button to save as default
- Useful for testing custom styles before committing
Storage of Custom Styles
Database Schema Addition
model StylePreset {
id String @id @default(uuid())
userId String
name String
isDefault Boolean @default(false)
// Style components
styleDirective String // Core tone/voice instructions
contentRequirements String? // What to include
structureGuidance String? // How to organize
exampleText String? // Sample tone (optional)
// Metadata
isBuiltIn Boolean @default(false) // True for official presets
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([userId])
}
Settings Model Update
model Settings {
// ... existing fields
defaultStyleId String? // FK to StylePreset
defaultStyleId String?
defaultStyle StylePreset? @relation(fields: [defaultStyleId], references: [id])
}
Journal Model Update (for per-diary override)
model Journal {
// ... existing fields
stylePresetId String? // Override style for this specific journal
stylePreset StylePreset? @relation(fields: [stylePresetId], references: [id])
}
API Design
New Endpoints
GET /api/v1/styles // List user's styles
POST /api/v1/styles // Create custom style
GET /api/v1/styles/:id // Get specific style
PUT /api/v1/styles/:id // Update style
DELETE /api/v1/styles/:id // Delete custom style
POST /api/v1/styles/:id/preview // Generate preview with this style
PUT /api/v1/settings/default-style // Set default style
Generation Integration
In journal.ts, modify the generation to:
- Check
journal.stylePresetIdfor per-diary override - Fall back to
settings.defaultStyleId - Fall back to legacy
settings.journalPrompt(for backwards compatibility) - Build style prompt from StylePreset or use journalPrompt directly
Prompt Building Logic
function buildStylePrompt(style: StylePreset | null, journalPrompt: string): string {
if (!style) return journalPrompt;
const parts = [
style.styleDirective,
style.contentRequirements && `\n\nRequirements:\n${style.contentRequirements}`,
style.structureGuidance && `\n\nStructure:\n${style.structureGuidance}`,
style.exampleText && `\n\nTone example: "${style.exampleText}"`,
].filter(Boolean);
return parts.join('\n\n') + '\n\n' + journalPrompt;
}
Implementation Complexity
Phase 1: Core Infrastructure (Medium)
- Database schema changes (StylePreset model)
- Settings model update
- Journal model update
- New API routes for CRUD operations
- Seed default presets on first run
Phase 2: UI Components (Medium)
- Style selector in Settings
- Style editor modal (create/edit)
- Preview modal with generation
- Per-diary override UI
Phase 3: Generation Integration (Low)
- Update journal generation to use style
- Handle migration from old journalPrompt
- Add style_id to generation task logging
Complexity Breakdown
| Component | Complexity | Notes |
|---|---|---|
| Database Schema | Low | Simple additions, Prisma handles migration |
| API Routes | Medium | Standard CRUD, ~100 lines |
| Style Editor UI | Medium | Form with preview, ~200 lines |
| Preview Feature | Medium | Requires new generation endpoint |
| Per-Diary Override | Low | Simple FK field + dropdown |
| Migration Path | Low | Handle nulls gracefully |
Estimated Time
- Backend: 2-3 hours
- Frontend: 3-4 hours
- Testing: 1 hour
Priority Recommendation
Recommended Priority: Phase 2 (Medium-High)
This feature adds significant user value with moderate implementation effort.
Justification:
- High Impact: Users frequently want personalized output
- Low Risk: Feature is additive, doesn't break existing flows
- Builds on Existing: Leverages already-implemented journal generation
- Differentiated: Few journaling apps offer this level of customization
Implementation Order
- First: Add StylePreset model + seed default styles
- Second: Update journal generation to use style
- Third: Basic style selector in Settings
- Fourth: Style editor for custom styles
- Fifth: Preview feature (optional, can ship later)
Considerations
- Migration: Existing users with custom
journalPromptshould be converted to a "Custom" style preset on first migration - Defaults: Pre-build the 6 style presets so users have immediate options
- Validation: Ensure style prompts don't exceed model context limits
- Preview: Consider rate-limiting preview generation to prevent abuse
Future Enhancements
- Style Transfer: Copy another user's shared style (community feature)
- Learning from Edits: After user edits generated diary, update style
- Multi-language Styles: Different writing styles per language
- Style Analytics: Show which styles user uses most
- Export/Import: Share style configurations
Summary
The AI Style feature transforms DearDiary from a basic AI diarist into a personalized writing assistant. By giving users control over tone, voice, and formatting, we create a more engaging journaling experience that matches individual preferences.
The implementation is straightforward given the existing architecture, and the feature delivers immediate value without requiring significant refactoring or risk.