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
This commit is contained in:
lotherk
2026-03-27 02:27:55 +00:00
parent deaf496a7d
commit 0bdd71a4ed
67 changed files with 15201 additions and 355 deletions

254
docs/api.md Normal file
View File

@@ -0,0 +1,254 @@
# API Reference
Base URL: `/api/v1`
Authentication: All requests require an API key in the `Authorization` header:
```
Authorization: Bearer <api_key>
```
## Authentication
### Register User
```bash
curl -X POST http://localhost:3000/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com", "password": "password123"}'
```
### Login
```bash
curl -X POST http://localhost:3000/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com", "password": "password123"}'
```
Response:
```json
{
"data": {
"token": "jwt_token",
"userId": "user_id"
},
"error": null
}
```
### Create API Key
```bash
curl -X POST http://localhost:3000/api/v1/auth/api-key \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{"name": "my-app"}'
```
## Events
### Create Event
```bash
curl -X POST http://localhost:3000/api/v1/events \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <api_key>" \
-d '{
"date": "2026-03-27",
"type": "event",
"content": "Had a great meeting about the new project"
}'
```
Valid types: `event`, `text`, `photo`, `voice`, `health`
### Get Event
```bash
curl http://localhost:3000/api/v1/events/<event_id> \
-H "Authorization: Bearer <api_key>"
```
### Update Event
```bash
curl -X PUT http://localhost:3000/api/v1/events/<event_id> \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <api_key>" \
-d '{"content": "Updated content"}'
```
Note: Events cannot be updated if a diary page has been generated for that date.
### Delete Event
```bash
curl -X DELETE http://localhost:3000/api/v1/events/<event_id> \
-H "Authorization: Bearer <api_key>"
```
Note: Events cannot be deleted if a diary page has been generated for that date.
## Days
### List Days
```bash
curl http://localhost:3000/api/v1/days \
-H "Authorization: Bearer <api_key>"
```
Response:
```json
{
"data": [
{
"date": "2026-03-27",
"eventCount": 5,
"hasJournal": true
}
],
"error": null
}
```
### Get Day Details
```bash
curl http://localhost:3000/api/v1/days/2026-03-27 \
-H "Authorization: Bearer <api_key>"
```
Response:
```json
{
"data": {
"date": "2026-03-27",
"events": [...],
"journal": {...}
},
"error": null
}
```
### Delete Day (and journal)
```bash
curl -X DELETE http://localhost:3000/api/v1/days/2026-03-27 \
-H "Authorization: Bearer <api_key>"
```
## Journal
### Generate Diary Page
```bash
curl -X POST http://localhost:3000/api/v1/journal/generate/2026-03-27 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <api_key>" \
-d '{"instructions": "Focus more on the technical aspects"}'
```
The `instructions` field is optional. If provided, it will be appended to the prompt for regeneration.
Response:
```json
{
"data": {
"journal": {
"id": "...",
"date": "2026-03-27",
"content": "Generated diary content...",
"eventCount": 5,
"generatedAt": "2026-03-27T10:30:00Z"
},
"task": {
"id": "...",
"type": "journal_generate",
"status": "completed",
"provider": "groq",
"model": "llama-3.3-70b-versatile"
}
},
"error": null
}
```
### Get Journal
```bash
curl http://localhost:3000/api/v1/journal/2026-03-27 \
-H "Authorization: Bearer <api_key>"
```
### Delete Journal
```bash
curl -X DELETE http://localhost:3000/api/v1/journal/2026-03-27 \
-H "Authorization: Bearer <api_key>"
```
Deleting the journal unlocks events for editing.
### Get Journal Tasks
```bash
curl http://localhost:3000/api/v1/journal/2026-03-27/tasks \
-H "Authorization: Bearer <api_key>"
```
## Tasks
### Get Task
```bash
curl http://localhost:3000/api/v1/tasks/<task_id> \
-H "Authorization: Bearer <api_key>"
```
Response includes full request/response JSON for debugging.
## Settings
### Get Settings
```bash
curl http://localhost:3000/api/v1/settings \
-H "Authorization: Bearer <api_key>"
```
### Update Settings
```bash
curl -X PUT http://localhost:3000/api/v1/settings \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <api_key>" \
-d '{
"aiProvider": "groq",
"providerSettings": {
"groq": {
"apiKey": "your-api-key",
"model": "llama-3.3-70b-versatile"
}
}
}'
```
## AI Providers
### Test Connection
```bash
curl -X POST http://localhost:3000/api/v1/ai/test \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <api_key>" \
-d '{
"provider": "groq",
"apiKey": "your-api-key",
"model": "llama-3.3-70b-versatile"
}'
```
Supported providers: `groq`, `openai`, `anthropic`, `ollama`, `lmstudio`
## Error Responses
All endpoints return errors in this format:
```json
{
"data": null,
"error": {
"code": "ERROR_CODE",
"message": "Human readable message"
}
}
```
Common error codes:
- `UNAUTHORIZED` - Invalid or missing API key
- `NOT_FOUND` - Resource not found
- `NO_EVENTS` - No events for diary generation
- `NO_AI_CONFIG` - AI provider not configured
- `EVENT_IMMUTABLE` - Cannot modify event (diary exists)

62
docs/astro.config.mjs Normal file
View File

@@ -0,0 +1,62 @@
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
export default defineConfig({
integrations: [
starlight({
title: 'DearDiary',
description: 'AI-Powered Daily Journal - Self-hosted journaling app where users capture events throughout the day and AI generates diary pages.',
logo: {
light: './src/assets/logo-light.svg',
dark: './src/assets/logo-dark.svg',
replacesTitle: true,
},
social: {
github: 'https://github.com/anomalyco/totalrecall',
},
editLink: {
baseUrl: 'https://github.com/anomalyco/totalrecall/edit/main/',
},
sidebar: [
{
label: 'Getting Started',
items: [
{ label: 'Introduction', slug: 'index' },
{ label: 'Installation', slug: 'getting-started/installation' },
{ label: 'Quick Start', slug: 'getting-started/quick-start' },
{ label: 'Configuration', slug: 'getting-started/configuration' },
],
},
{
label: 'Features',
items: [
{ label: 'Events', slug: 'features/events' },
{ label: 'Diary Pages', slug: 'features/diary-pages' },
{ label: 'AI Providers', slug: 'features/ai-providers' },
{ label: 'Search', slug: 'features/search' },
{ label: 'Calendar', slug: 'features/calendar' },
{ label: 'Export & Import', slug: 'features/export-import' },
{ label: 'Media Uploads', slug: 'features/media' },
],
},
{
label: 'API Reference',
items: [
{ label: 'Authentication', slug: 'api/authentication' },
{ label: 'Events', slug: 'api/events' },
{ label: 'Journals', slug: 'api/journals' },
{ label: 'Settings', slug: 'api/settings' },
],
},
{
label: 'Deployment',
items: [
{ label: 'Docker', slug: 'deployment/docker' },
{ label: 'Environment Variables', slug: 'deployment/environment' },
],
},
],
customCss: ['./src/styles/custom.css'],
}),
],
});

7311
docs/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

16
docs/package.json Normal file
View File

@@ -0,0 +1,16 @@
{
"name": "deardiary-docs",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "astro dev",
"start": "astro dev",
"build": "astro build",
"preview": "astro preview"
},
"dependencies": {
"@astrojs/starlight": "^0.34.2",
"astro": "^5.6.1",
"sharp": "^0.33.5"
}
}

View File

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<defs>
<linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#a78bfa;stop-opacity:1" />
<stop offset="100%" style="stop-color:#818cf8;stop-opacity:1" />
</linearGradient>
</defs>
<rect width="100" height="100" rx="20" fill="url(#grad)"/>
<path d="M25 25 L75 25 L75 80 L25 80 Z" fill="none" stroke="white" stroke-width="3" stroke-linecap="round"/>
<path d="M35 40 L65 40" stroke="white" stroke-width="2" stroke-linecap="round"/>
<path d="M35 50 L65 50" stroke="white" stroke-width="2" stroke-linecap="round"/>
<path d="M35 60 L55 60" stroke="white" stroke-width="2" stroke-linecap="round"/>
<circle cx="70" cy="60" r="8" fill="white" opacity="0.3"/>
<path d="M70 55 L70 65 M65 60 L75 60" stroke="white" stroke-width="2" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 897 B

View File

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<defs>
<linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#8b5cf6;stop-opacity:1" />
<stop offset="100%" style="stop-color:#6366f1;stop-opacity:1" />
</linearGradient>
</defs>
<rect width="100" height="100" rx="20" fill="url(#grad)"/>
<path d="M25 25 L75 25 L75 80 L25 80 Z" fill="none" stroke="white" stroke-width="3" stroke-linecap="round"/>
<path d="M35 40 L65 40" stroke="white" stroke-width="2" stroke-linecap="round"/>
<path d="M35 50 L65 50" stroke="white" stroke-width="2" stroke-linecap="round"/>
<path d="M35 60 L55 60" stroke="white" stroke-width="2" stroke-linecap="round"/>
<circle cx="70" cy="60" r="8" fill="white" opacity="0.3"/>
<path d="M70 55 L70 65 M65 60 L75 60" stroke="white" stroke-width="2" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 897 B

View File

@@ -0,0 +1,47 @@
---
title: Authentication
description: API authentication methods
sidebar:
order: 1
---
## API Key Authentication
All API requests require authentication using a Bearer token:
```http
Authorization: Bearer your-api-key-here
```
## Getting an API Key
### Via Login
1. POST to `/api/v1/auth/login` with email/password
2. Receive JWT token
3. Create API key via POST to `/api/v1/auth/api-key`
### Via Registration
1. POST to `/api/v1/auth/register` with email/password
2. Receive API key directly
## Response Format
All endpoints return:
```json
{
"data": { ... } | null,
"error": { "code": "ERROR_CODE", "message": "Error description" } | null
}
```
## Error Codes
| Code | HTTP Status | Description |
|------|-------------|-------------|
| `UNAUTHORIZED` | 401 | Invalid or missing API key |
| `NOT_FOUND` | 404 | Resource not found |
| `VALIDATION_ERROR` | 400 | Invalid request data |
| `EVENT_IMMUTABLE` | 400 | Cannot modify locked events |

View File

@@ -0,0 +1,70 @@
---
title: Events API
description: Events endpoints reference
sidebar:
order: 2
---
## Create Event
```http
POST /api/v1/events
```
### Request Body
```json
{
"date": "2024-01-15",
"type": "text",
"content": "Had coffee with Sarah",
"latitude": 40.7128,
"longitude": -74.0060,
"placeName": "New York, NY"
}
```
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `date` | string | Yes | Date in YYYY-MM-DD format |
| `type` | string | Yes | One of: event, text, photo, voice, health |
| `content` | string | Yes | Event content |
| `latitude` | number | No | GPS latitude |
| `longitude` | number | No | GPS longitude |
| `placeName` | string | No | Reverse-geocoded place name |
| `metadata` | object | No | Additional metadata |
### Response
```json
{
"data": {
"id": "uuid",
"date": "2024-01-15",
"type": "text",
"content": "Had coffee with Sarah",
"latitude": 40.7128,
"longitude": -74.0060,
"placeName": "New York, NY",
"createdAt": "2024-01-15T10:30:00Z"
}
}
```
## Get Day
```http
GET /api/v1/days/:date
```
Returns all events and journal for a specific date.
## Delete Event
```http
DELETE /api/v1/events/:id
```
:::caution
Cannot delete events from days with generated journals.
:::

View File

@@ -0,0 +1,80 @@
---
title: Journals API
description: Journals endpoints reference
sidebar:
order: 3
---
## Generate Diary
```http
POST /api/v1/journal/generate/:date
```
### Request Body
```json
{
"instructions": "Make it more detailed and poetic"
}
```
### Response
```json
{
"data": {
"journal": {
"id": "uuid",
"date": "2024-01-15",
"title": "A Productive Tuesday",
"content": "Full diary content...",
"eventCount": 8,
"generatedAt": "2024-01-15T22:00:00Z"
},
"task": {
"id": "uuid",
"status": "completed",
"provider": "groq",
"model": "llama-3.3-70b-versatile"
}
}
}
```
## Get Journal
```http
GET /api/v1/journal/:date
```
Returns the diary page for a specific date.
## List Journals
```http
GET /api/v1/journals?page=1&limit=10
```
### Query Parameters
| Parameter | Default | Description |
|-----------|---------|-------------|
| `page` | 1 | Page number |
| `limit` | 10 | Items per page (10, 50, or 100) |
## Get Generation Tasks
```http
GET /api/v1/journal/:date/tasks
```
Returns all generation attempts for a journal with request/response JSON.
## Delete Journal
```http
DELETE /api/v1/journal/:date
```
Deleting a journal **unlocks** all events for that day, allowing edits and new entries.

View File

@@ -0,0 +1,80 @@
---
title: Settings API
description: Settings endpoints reference
sidebar:
order: 4
---
## Get Settings
```http
GET /api/v1/settings
```
### Response
```json
{
"data": {
"aiProvider": "groq",
"aiApiKey": null,
"aiModel": "llama-3.3-70b-versatile",
"journalPrompt": "Custom instructions...",
"language": "en",
"timezone": "UTC",
"journalContextDays": 10,
"providerSettings": {
"groq": { "apiKey": "...", "model": "..." }
}
}
}
```
## Update Settings
```http
PUT /api/v1/settings
```
### Request Body
```json
{
"aiProvider": "openai",
"aiApiKey": "sk-...",
"journalPrompt": "Write in a reflective tone"
}
```
### Fields
| Field | Type | Description |
|-------|------|-------------|
| `aiProvider` | string | groq, openai, anthropic, ollama, lmstudio |
| `aiApiKey` | string | API key for selected provider |
| `aiModel` | string | Model identifier |
| `journalPrompt` | string | Custom instructions (null to clear) |
| `journalContextDays` | number | Days of previous journals to include (0-30) |
## Change Password
```http
POST /api/v1/account/password
```
```json
{
"currentPassword": "old-password",
"newPassword": "new-secure-password"
}
```
## Delete Account
```http
DELETE /api/v1/account
```
:::danger
This permanently deletes your account and all data. This cannot be undone.
:::

View File

@@ -0,0 +1,93 @@
---
title: Docker Deployment
description: Deploy DearDiary with Docker
sidebar:
order: 1
---
## Docker Compose
The recommended way to run DearDiary:
```yaml
services:
app:
build: .
ports:
- "8080:8080"
volumes:
- ./data:/data
env_file:
- backend/.env
restart: unless-stopped
```
## Running
### Start
```bash
docker compose up -d
```
### Stop
```bash
docker compose down
```
### Rebuild
```bash
docker compose build && docker compose up -d
```
## Volumes
Data persists in `./data/`:
| Directory | Contents |
|-----------|----------|
| `data/db/` | SQLite database |
| `data/media/` | Uploaded files |
## Health Check
The app exposes a health endpoint:
```http
GET http://localhost:8080/health
```
Returns:
```json
{
"status": "ok",
"timestamp": "2024-01-15T10:30:00Z"
}
```
## Production Considerations
### Reverse Proxy
For production, use a reverse proxy (nginx, Caddy, Traefik) with:
- HTTPS/TLS termination
- Security headers
- Rate limiting
### Database
Default SQLite is fine for single-user or small deployments.
For multi-user or high traffic, consider PostgreSQL:
```env
DATABASE_URL="postgresql://user:pass@host:5432/deardiary"
```
### Backup
Regularly backup `./data/` directory.

View File

@@ -0,0 +1,66 @@
---
title: Environment Variables
description: Complete environment variable reference
sidebar:
order: 2
---
## Configuration File
Copy `.env.example` to `.env`:
```bash
cp backend/.env.example backend/.env
```
## Variables
### Application
| Variable | Default | Description |
|----------|---------|-------------|
| `APP_NAME` | DearDiary | App name displayed in UI |
| `VERSION` | 0.1.0 | App version |
| `PORT` | 3000 | Internal API port |
### Database
| Variable | Default | Description |
|----------|---------|-------------|
| `DATABASE_URL` | file:./data/deardiary.db | SQLite by default |
| `DATABASE_URL` | postgresql://... | PostgreSQL connection |
| `DATABASE_URL` | mysql://... | MySQL connection |
### Security
| Variable | Default | Description |
|----------|---------|-------------|
| `JWT_SECRET` | development-secret... | **Required in production!** |
| `CORS_ORIGIN` | * | CORS allowed origins |
### User Management
| Variable | Default | Description |
|----------|---------|-------------|
| `REGISTRATION_ENABLED` | false | Enable/disable registration |
| `DEFAULT_USER_EMAIL` | admin@localhost | Default admin email |
| `DEFAULT_USER_PASSWORD` | changeme123 | Default admin password |
### Storage
| Variable | Default | Description |
|----------|---------|-------------|
| `MEDIA_DIR` | ./data/media | Media files directory |
## Production Checklist
:::caution
Before going to production:
1. Set a strong `JWT_SECRET`
2. Set `CORS_ORIGIN` to your domain
3. Change default admin credentials
4. Set `REGISTRATION_ENABLED=false` if not needed
5. Use HTTPS/TLS
6. Set up regular backups
:::

View File

@@ -0,0 +1,62 @@
---
title: AI Providers
description: Configure AI providers for diary generation
sidebar:
order: 3
---
## Supported Providers
DearDiary supports multiple AI providers:
| Provider | Default Model | Type |
|----------|---------------|------|
| **Groq** | llama-3.3-70b-versatile | Cloud |
| OpenAI | gpt-4o | Cloud |
| Anthropic | claude-3.5-sonnet | Cloud |
| Ollama | varies | Local |
| LM Studio | varies | Local |
## Groq (Recommended)
Free tier available. Fast inference.
1. Get an API key from [console.groq.com](https://console.groq.com)
2. Enter the API key in Settings
3. Select Groq as your provider
## OpenAI
1. Get an API key from [platform.openai.com](https://platform.openai.com)
2. Optionally select a specific model:
- `gpt-4o` - Most capable
- `gpt-4o-mini` - Faster, cheaper
## Anthropic
1. Get an API key from [console.anthropic.com](https://console.anthropic.com)
2. Select Claude model:
- `claude-3-5-sonnet-latest` - Recommended
- `claude-3-opus-latest` - Most capable
## Ollama (Local)
Run models locally on your machine.
1. Install [Ollama](https://ollama.ai)
2. Pull a model: `ollama pull llama3.2`
3. Set base URL: `http://localhost:11434/v1`
4. Select model name
## LM Studio (Local)
Alternative local option with GUI.
1. Download [LM Studio](https://lmstudio.ai)
2. Download a model
3. Start local server (click "Start Server")
4. Set base URL: `http://localhost:1234/v1`
## Testing Connection
Use the **Test Connection** button in Settings to verify your AI provider is working before generating diaries.

View File

@@ -0,0 +1,44 @@
---
title: Calendar
description: Visual calendar view of your journals
sidebar:
order: 5
---
## Overview
The Calendar view provides a monthly overview of your journal activity.
Access it via the navigation menu: **Calendar**
## Calendar Indicators
Each day shows:
| Indicator | Meaning |
|-----------|---------|
| **Number** | Day of month |
| **Filled circle** | Has events |
| **Purple border** | Has generated diary page |
| **Today** | Highlighted border |
## Navigation
- **Previous/Next Month** - Arrow buttons
- **Month/Year Picker** - Click month name
- **Today Button** - Jump to current date
## Clicking a Day
Click any day to view:
- All events for that day
- Diary page if generated
- Option to add new events (if unlocked)
## Use Cases
- Quickly see activity patterns
- Identify gaps in journaling
- Navigate to specific past dates
- Plan when to catch up on entries

View File

@@ -0,0 +1,60 @@
---
title: Diary Pages
description: AI-generated diary entries
sidebar:
order: 2
---
## What is a Diary Page?
A **Diary Page** is an AI-generated narrative summary of your day's events. Unlike events, diary pages:
- Can be regenerated (rewritten)
- Include a generated title
- Are narrative, not just data points
## Generating a Diary
1. Navigate to **Today** (`/today`)
2. Ensure you have at least one event
3. Click **Generate Diary Page**
4. Wait for AI processing
## Viewing Diary Pages
Access diary pages via:
- **Dashboard** - Recent diary excerpts
- **Diary** - Paginated list of all diaries
- **Calendar** - Visual overview with indicators
- **Day View** - Click any date to see its diary
## Rewriting
Click **Rewrite** to regenerate with additional instructions:
### Default Rewrite
Regenerates with the same events and default prompt.
### Custom Instructions
Add specific guidance:
```
Make it more poetic and reflective.
Focus on the conversations I had.
```
## Title Generation
Each diary page includes an AI-generated title (max 50 characters) that summarizes the day.
## Task History
Every generation attempt is logged as a **Task**, including:
- Request/response JSON for debugging
- Provider and model used
- Success/failure status
- Processing time

View File

@@ -0,0 +1,60 @@
---
title: Events
description: Capturing and managing events
sidebar:
order: 1
---
## What is an Event?
An **Event** is a single log entry in your journal. Events can be:
- **Text** - Simple text notes
- **Photo** - Captured moments with images
- **Voice** - Voice memos
- **Health** - Health-related observations
- **Event** - General activity logs
## Creating Events
### Via Today Page
1. Navigate to **Today** (`/today`)
2. Type your event in the input field
3. Select the event type
4. Press Enter or click Add
### Via Quick Add
Press `Ctrl + J` from anywhere to open the quick add widget.
## Location
Events automatically capture:
- GPS coordinates (if browser permits)
- Reverse-geocoded place names
This helps you remember where things happened.
## Immutability
Once a **Diary Page** is generated for a day, all events for that day become **locked**:
- Cannot be deleted
- Cannot be edited
- Cannot have new events added
To unlock, you must delete the diary page.
## Media
### Photos
Upload photos directly or attach them to existing events.
### Voice Memos
Record voice memos using your browser's microphone.
Media files are stored in `./data/media/{userId}/{date}/`

View File

@@ -0,0 +1,72 @@
---
title: Export & Import
description: Backup and restore your data
sidebar:
order: 6
---
## Why Export?
Regular exports ensure you never lose your data:
- Backup to external storage
- Migrate to new server
- Keep offline archive
## Export Format
Exports are JSON files containing:
```json
{
"version": "0.0.6",
"exportedAt": "2024-01-15T10:30:00Z",
"settings": { ... },
"events": [ ... ],
"journals": [ ... ],
"tasks": [ ... ]
}
```
### Included Data
- **Settings** - AI provider, model, custom prompts
- **Events** - All event data including location
- **Journals** - All generated diary pages
- **Tasks** - Generation history for debugging
## How to Export
1. Go to **Settings**
2. Scroll to **Data Management**
3. Click **Export Data**
4. Save the JSON file
## Import
### Version Compatibility
- Minimum supported: 0.0.3
- Current version: 0.0.6
Older exports may lose some data or fail to import.
### Import Steps
1. Go to **Settings** → **Data Management**
2. Click **Import Data**
3. Select your JSON export file
4. Review the preview (imported/skipped counts)
5. Click **Confirm Import**
### Duplicate Handling
- **Events**: Skipped if identical (date + content + timestamp)
- **Journals**: Skipped by date
- **Tasks**: Linked to existing journals
## Danger Zone
:::caution
The **Reset Account** option in Danger Zone deletes ALL your data except settings. Use with extreme caution!
:::

View File

@@ -0,0 +1,66 @@
---
title: Media Uploads
description: Photos and voice memos
sidebar:
order: 7
---
## Supported Media Types
### Photos
- Upload photos to accompany events
- JPEG, PNG, GIF, WebP supported
- Displayed inline in event list
### Voice Memos
- Record voice notes
- WebM audio format
- Playback controls in event list
## How to Add Media
### Photo Type Events
1. Select **Photo** type when creating event
2. Add description in text field
3. Upload photo
### Voice Type Events
1. Select **Voice** type
2. Click microphone button
3. Start recording
4. Stop when finished
5. Add optional text note
## Storage
Media files are stored at:
```
./data/media/{userId}/{date}/
```
For example:
```
./data/media/user123abc/2024-01-15/photo.jpg
./data/media/user123abc/2024-01-15/voice.webm
```
## Serving
Media is served via nginx at `/media/` route:
```
/media/{userId}/{date}/{filename}
```
## Privacy
Media files are:
- Stored locally only
- Associated with your user account
- Not shared between users
- Deleted when you delete events

View File

@@ -0,0 +1,43 @@
---
title: Search
description: Finding events and diary pages
sidebar:
order: 4
---
## Using Search
Press `Ctrl + K` from anywhere to open the search modal.
## What You Can Search
### Diary Pages
Search across all generated diary pages:
- Titles
- Full content
- Dates
### Events
Search across all events:
- Event content
- Event type
- Date
## How It Works
DearDiary uses **SQLite FTS5** (Full-Text Search) for fast, indexed searching:
1. Automatic indexing on content creation
2. Porter stemming for better matches
3. Fallback to LIKE queries if FTS fails
## Tips
- Use specific keywords for better results
- Search works across all dates
- Results are grouped by type (diaries vs events)
- Click any result to navigate directly to that item

View File

@@ -0,0 +1,54 @@
---
title: Configuration
description: Configure DearDiary for your needs
sidebar:
order: 3
---
## Settings Page
Access settings via the navigation menu. Settings are organized into sections:
### AI Provider
Choose your AI provider for diary generation:
| Provider | Model | Notes |
|----------|-------|-------|
| **Groq** (default) | llama-3.3-70b-versatile | Fast, free tier available |
| OpenAI | gpt-4o, gpt-4o-mini | Requires API key |
| Anthropic | claude-3.5-sonnet | Requires API key |
| Ollama | Various | Local models |
| LM Studio | Various | Local models |
### Custom Instructions
Add custom instructions that are prepended to the default AI prompt:
```
Write in a poetic style.
Focus on health and wellness aspects.
```
### Journal Context
Set how many previous days of diaries the AI considers when generating new entries (0-30 days).
## Environment Variables
See [Environment Variables](/deployment/environment) for server-side configuration.
## Multi-User Setup
Enable user registration:
```env
REGISTRATION_ENABLED=true
```
Or create a default admin user:
```env
DEFAULT_USER_EMAIL=admin@example.com
DEFAULT_USER_PASSWORD=your-secure-password
```

View File

@@ -0,0 +1,56 @@
---
title: Installation
description: How to install and set up DearDiary
sidebar:
order: 1
---
## Prerequisites
- [Docker](https://docs.docker.com/get-docker/) and Docker Compose
- Git
## Quick Install
1. Clone the repository:
```bash
git clone https://github.com/anomalyco/totalrecall.git
cd totalrecall
```
2. Copy the environment file:
```bash
cp backend/.env.example backend/.env
```
3. Start with Docker:
```bash
docker compose up -d
```
4. Access the app at `http://localhost:8080`
## Default Credentials
On first start, a default user is created if configured:
- **Email**: `admin@localhost` (configurable via `DEFAULT_USER_EMAIL`)
- **Password**: `changeme123` (configurable via `DEFAULT_USER_PASSWORD`)
:::tip
Change these credentials immediately after first login!
:::
## Ports
| Service | Port | Description |
|---------|------|-------------|
| App | 8080 | Main application (nginx) |
| API | 3000 | Backend API (internal) |
## Data Storage
All data is stored in Docker volumes:
- `./data/db/` - SQLite database
- `./data/media/` - Uploaded photos and voice memos

View File

@@ -0,0 +1,58 @@
---
title: Quick Start
description: Get started with DearDiary in 5 minutes
sidebar:
order: 2
---
## First Steps
### 1. Log an Event
Navigate to **Today** and start logging events:
- Type your event and press Enter
- Use the type buttons to change event category (Event, Health, Photo, Voice)
- Events are timestamped automatically
### 2. Add Your Location
When you log an event, DearDiary automatically captures:
- **Latitude/Longitude** from your browser
- **Place Name** via reverse geocoding (OpenStreetMap)
:::note
Location access requires browser permission. Grant it when prompted for automatic geolocation.
:::
### 3. Generate Your Diary
When you're ready to lock in your day:
1. Click **Generate Diary Page**
2. AI analyzes all your events
3. Creates a narrative diary entry with title
Once generated, events become **locked** (immutable).
### 4. Rewrite if Needed
Click **Rewrite** to regenerate with additional instructions:
- Add context like "Make it more detailed"
- Include specific topics to emphasize
- Adjust the tone or style
## Keyboard Shortcuts
| Shortcut | Action |
|----------|--------|
| `Ctrl + J` | Quick add event |
| `Ctrl + K` | Search |
## Tips
- Log events throughout the day for richer diaries
- Use the calendar view to browse past days
- Export your data regularly for backup

View File

@@ -0,0 +1,34 @@
---
title: DearDiary
description: AI-Powered Daily Journal
template: splash
hero:
title: DearDiary
tagline: Your AI-powered daily journal. Capture events throughout the day and let AI transform them into beautiful diary pages.
image:
file: ../../assets/logo-light.svg
actions:
- theme: brand
text: Get Started
link: /getting-started/installation/
- theme: alt
text: View on GitHub
link: https://github.com/anomalyco/totalrecall
---
import { Card, CardGrid } from '@astrojs/starlight/components';
<CardGrid stagger>
<Card title="Capture Events">
Log events throughout your day - text, photos, voice memos, and health data.
</Card>
<Card title="AI-Generated Diary">
Let AI transform your events into beautiful, narrative diary pages.
</Card>
<Card title="Privacy First">
Self-hosted. Your data stays on your server.
</Card>
<Card title="Geolocation">
Events are automatically tagged with your location.
</Card>
</CardGrid>

View File

@@ -0,0 +1,21 @@
/* Custom DearDiary styling */
:root[data-theme='light'] {
--sl-color-accent-low: #e9e3ff;
--sl-color-accent: #7c3aed;
--sl-color-accent-high: #4c1d95;
--sl-color-white: #1e1b4b;
--sl-color-gray-1: #3730a3;
--sl-color-gray-2: #4338ca;
--sl-color-gray-3: #4f46e5;
--sl-color-gray-4: #6366f1;
--sl-color-gray-5: #818cf8;
--sl-color-gray-6: #a5b4fc;
--sl-color-gray-7: #c7d2fe;
--sl-color-black: #e0e7ff;
}
:root[data-theme='dark'] {
--sl-color-accent-low: #4c1d95;
--sl-color-accent: #a78bfa;
--sl-color-accent-high: #c4b5fd;
}