Files
deardiary/todo/ai_style.md
lotherk 0bdd71a4ed feat: v0.1.0 - geolocation capture, calendar, search, Starlight docs site
- 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
2026-03-27 02:27:55 +00:00

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

  1. Style Presets: Pre-defined writing styles (formal, casual, poetic, etc.)
  2. Custom Styles: User-defined styles with full control over prompt components
  3. Per-Diary Override: Ability to use a different style for specific dates
  4. Style Preview: Generate a sample diary to preview style before use
  5. 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:

  1. Style Directive: How to write (tone, voice)
  2. Content Requirements: What to include
  3. Structure Guidance: How to organize
  4. 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:

  1. Check journal.stylePresetId for per-diary override
  2. Fall back to settings.defaultStyleId
  3. Fall back to legacy settings.journalPrompt (for backwards compatibility)
  4. 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

This feature adds significant user value with moderate implementation effort.

Justification:

  1. High Impact: Users frequently want personalized output
  2. Low Risk: Feature is additive, doesn't break existing flows
  3. Builds on Existing: Leverages already-implemented journal generation
  4. Differentiated: Few journaling apps offer this level of customization

Implementation Order

  1. First: Add StylePreset model + seed default styles
  2. Second: Update journal generation to use style
  3. Third: Basic style selector in Settings
  4. Fourth: Style editor for custom styles
  5. Fifth: Preview feature (optional, can ship later)

Considerations

  • Migration: Existing users with custom journalPrompt should 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

  1. Style Transfer: Copy another user's shared style (community feature)
  2. Learning from Edits: After user edits generated diary, update style
  3. Multi-language Styles: Different writing styles per language
  4. Style Analytics: Show which styles user uses most
  5. 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.