v0.1.6: Add comprehensive API docs and additional documentation pages

This commit is contained in:
lotherk
2026-03-27 15:11:36 +00:00
parent a98b58be19
commit a5f1f89176
10 changed files with 651 additions and 1 deletions

View File

@@ -233,6 +233,7 @@ Version is managed via `VERSION.txt` (single source of truth). All other version
- Never commit actual version numbers in source files
## Version History
- 0.1.6: Add comprehensive API docs and additional documentation pages
- 0.1.5: Fix ENV syntax in website Dockerfile
- 0.1.4: Version links to git releases on website
- 0.1.3: Add VERSION to website build

View File

@@ -1 +1 @@
0.1.4
0.1.6

View File

@@ -30,9 +30,16 @@
<a href="installation.html">Installation</a>
<a href="quick-start.html">Quick Start</a>
</div>
<div class="sidebar-section">
<h3>Configuration</h3>
<a href="configuration.html">Environment</a>
<a href="api.html">API Reference</a>
</div>
<div class="sidebar-section">
<h3>Features</h3>
<a href="events.html">Events</a>
<a href="ai-providers.html" class="active">AI Providers</a>
<a href="export-import.html">Export & Import</a>
</div>
</aside>

218
www/docs/api.html Normal file
View File

@@ -0,0 +1,218 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>API Reference - DearDiary</title>
<link rel="stylesheet" href="../css/styles.css">
<link rel="stylesheet" href="../css/docs.css">
</head>
<body>
<nav class="navbar">
<div class="nav-container">
<a href="../" class="logo">
<svg width="32" height="32" viewBox="0 0 100 100"><defs><linearGradient id="g" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" style="stop-color:#6d28d9"/><stop offset="100%" style="stop-color:#4c1d95"/></linearGradient></defs><rect width="100" height="100" rx="20" fill="url(#g)"/><path d="M25 25 L75 25 L75 80 L25 80 Z" fill="none" stroke="white" stroke-width="3"/><path d="M35 40 L65 40 M35 50 L65 50 M35 60 L55 60" stroke="white" stroke-width="2"/></svg>
DearDiary
</a>
<div class="nav-links">
<a href="../">Home</a>
<a href="../docs/" class="active">Docs</a>
<a href="../blog/">Blog</a>
<a href="${GIT_URL}" target="_blank">Git Repository</a>
</div>
</div>
</nav>
<div class="docs-layout">
<aside class="docs-sidebar">
<div class="sidebar-section">
<h3>Getting Started</h3>
<a href="installation.html">Installation</a>
<a href="quick-start.html">Quick Start</a>
</div>
<div class="sidebar-section">
<h3>Configuration</h3>
<a href="configuration.html">Environment</a>
<a href="api.html" class="active">API Reference</a>
</div>
<div class="sidebar-section">
<h3>Features</h3>
<a href="ai-providers.html">AI Providers</a>
<a href="events.html">Events</a>
<a href="export-import.html">Export & Import</a>
</div>
</aside>
<main class="docs-content">
<h1>API Reference</h1>
<p>The DearDiary API is REST-based with JSON responses. All endpoints return a consistent format.</p>
<h2>Response Format</h2>
<p>All responses follow this structure:</p>
<pre><code>{
"data": { ... } | null,
"error": { "code": "ERROR_CODE", "message": "..." } | null
}</code></pre>
<h2>Authentication</h2>
<p>Include your API key in the Authorization header:</p>
<pre><code>Authorization: Bearer &lt;your-api-key&gt;</code></pre>
<h2>Endpoints</h2>
<h3>Events</h3>
<h4>GET /api/v1/events?date=YYYY-MM-DD</h4>
<p>List events for a specific date.</p>
<pre><code>// Response
{
"data": [
{
"id": "evt_xxx",
"date": "2026-03-27",
"type": "text",
"content": "Had coffee with Sarah",
"latitude": 40.7128,
"longitude": -74.0060,
"placeName": "New York, NY",
"createdAt": "2026-03-27T08:30:00Z"
}
]
}</code></pre>
<h4>POST /api/v1/events</h4>
<p>Create a new event.</p>
<pre><code>// Request body
{
"date": "2026-03-27",
"type": "text", // text, photo, voice, health
"content": "Event content"
}
// Response
{
"data": {
"id": "evt_xxx",
"date": "2026-03-27",
"type": "text",
"content": "Event content",
"createdAt": "2026-03-27T10:00:00Z"
}
}</code></pre>
<h4>DELETE /api/v1/events/:id</h4>
<p>Delete an event. Only works if no journal exists for that date.</p>
<h3>Journals</h3>
<h4>GET /api/v1/journal/:date</h4>
<p>Get diary page for a specific date.</p>
<pre><code>{
"data": {
"id": "jrn_xxx",
"date": "2026-03-27",
"title": "A Productive Tuesday",
"content": "Today was filled with...",
"eventCount": 8,
"generatedAt": "2026-03-27T20:00:00Z"
}
}</code></pre>
<h4>POST /api/v1/journal/generate/:date</h4>
<p>Generate a diary page from events. Starts an async task.</p>
<pre><code>// Request body (optional)
{
"instructions": "Focus on the meeting with the client"
}
// Response
{
"data": {
"taskId": "tsk_xxx",
"status": "pending"
}
}</code></pre>
<h4>PUT /api/v1/journal/:date</h4>
<p>Update journal title and content.</p>
<pre><code>// Request body
{
"title": "New Title",
"content": "Updated content..."
}</code></pre>
<h4>DELETE /api/v1/journal/:date</h4>
<p>Delete journal. This unlocks events so they can be modified.</p>
<h3>Tasks</h3>
<h4>GET /api/v1/journal/:date/tasks</h4>
<p>Get generation tasks for a journal.</p>
<pre><code>{
"data": [
{
"id": "tsk_xxx",
"type": "generate",
"status": "completed", // pending, processing, completed, failed
"title": "A Great Day",
"provider": "groq",
"model": "llama-3.3-70b-versatile",
"createdAt": "2026-03-27T20:00:00Z",
"completedAt": "2026-03-27T20:00:30Z"
}
]
}</code></pre>
<h3>Journals List</h3>
<h4>GET /api/v1/journals?page=1&amp;limit=10</h4>
<p>List all diary pages with pagination.</p>
<h4>GET /api/v1/days</h4>
<p>List days with journal info and excerpts.</p>
<h3>Settings</h3>
<h4>GET /api/v1/settings</h4>
<p>Get current user settings.</p>
<h4>PUT /api/v1/settings</h4>
<p>Update user settings.</p>
<pre><code>{
"aiProvider": "groq",
"aiApiKey": "gsk_xxx",
"aiModel": "llama-3.3-70b-versatile",
"useSystemDefault": false
}</code></pre>
<h3>Data Management</h3>
<h4>GET /api/v1/export</h4>
<p>Export all user data as JSON.</p>
<pre><code>{
"data": {
"version": "0.1.0",
"exportedAt": "2026-03-27T12:00:00Z",
"events": [...],
"journals": [...],
"tasks": [...],
"settings": {...}
}
}</code></pre>
<h4>POST /api/v1/import</h4>
<p>Import data from export file.</p>
<h4>GET /api/v1/health</h4>
<p>Health check endpoint (no auth required).</p>
<pre><code>{ "status": "ok" }</code></pre>
<div class="next-steps">
<a href="configuration.html" class="btn">← Configuration</a>
<a href="events.html" class="btn btn-primary">Next: Events →</a>
</div>
</main>
</div>
</body>
</html>

144
www/docs/configuration.html Normal file
View File

@@ -0,0 +1,144 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Configuration - DearDiary</title>
<link rel="stylesheet" href="../css/styles.css">
<link rel="stylesheet" href="../css/docs.css">
</head>
<body>
<nav class="navbar">
<div class="nav-container">
<a href="../" class="logo">
<svg width="32" height="32" viewBox="0 0 100 100"><defs><linearGradient id="g" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" style="stop-color:#6d28d9"/><stop offset="100%" style="stop-color:#4c1d95"/></linearGradient></defs><rect width="100" height="100" rx="20" fill="url(#g)"/><path d="M25 25 L75 25 L75 80 L25 80 Z" fill="none" stroke="white" stroke-width="3"/><path d="M35 40 L65 40 M35 50 L65 50 M35 60 L55 60" stroke="white" stroke-width="2"/></svg>
DearDiary
</a>
<div class="nav-links">
<a href="../">Home</a>
<a href="../docs/" class="active">Docs</a>
<a href="../blog/">Blog</a>
<a href="${GIT_URL}" target="_blank">Git Repository</a>
</div>
</div>
</nav>
<div class="docs-layout">
<aside class="docs-sidebar">
<div class="sidebar-section">
<h3>Getting Started</h3>
<a href="installation.html">Installation</a>
<a href="quick-start.html">Quick Start</a>
</div>
<div class="sidebar-section">
<h3>Configuration</h3>
<a href="configuration.html" class="active">Environment</a>
<a href="api.html">API Reference</a>
</div>
<div class="sidebar-section">
<h3>Features</h3>
<a href="ai-providers.html">AI Providers</a>
<a href="events.html">Events</a>
<a href="export-import.html">Export & Import</a>
</div>
</aside>
<main class="docs-content">
<h1>Configuration</h1>
<p>DearDiary uses environment variables for configuration. Create a <code>.env</code> file in the project root.</p>
<h2>Environment Variables</h2>
<table>
<tr>
<th>Variable</th>
<th>Default</th>
<th>Description</th>
</tr>
<tr>
<td><code>BACKEND_JWT_SECRET</code></td>
<td><em>Required</em></td>
<td>Secret key for JWT token signing. Generate a strong random string.</td>
</tr>
<tr>
<td><code>BACKEND_PORT</code></td>
<td>3001</td>
<td>Port for the backend API server</td>
</tr>
<tr>
<td><code>BACKEND_CORS_ORIGIN</code></td>
<td>*</td>
<td>CORS allowed origins (comma-separated)</td>
</tr>
<tr>
<td><code>BACKEND_REGISTRATION_ENABLED</code></td>
<td>false</td>
<td>Allow new user registration (true/false)</td>
</tr>
<tr>
<td><code>BACKEND_DATABASE_URL</code></td>
<td>file:/data/deardiary.db</td>
<td>SQLite database path</td>
</tr>
<tr>
<td><code>BACKEND_MEDIA_DIR</code></td>
<td>/data/media</td>
<td>Directory for uploaded media files</td>
</tr>
<tr>
<td><code>BACKEND_DEFAULT_USER_EMAIL</code></td>
<td>-</td>
<td>Email for default admin user (created on first start)</td>
</tr>
<tr>
<td><code>BACKEND_DEFAULT_USER_PASSWORD</code></td>
<td>-</td>
<td>Password for default admin user</td>
</tr>
<tr>
<td><code>BACKEND_DEFAULT_AI_PROVIDER</code></td>
<td>groq</td>
<td>Default AI provider (groq, openai, anthropic, ollama, lmstudio)</td>
</tr>
<tr>
<td><code>BACKEND_DEFAULT_AI_MODEL</code></td>
<td>llama-3.3-70b-versatile</td>
<td>Default AI model</td>
</tr>
<tr>
<td><code>BACKEND_DEFAULT_AI_API_KEY</code></td>
<td>-</td>
<td>Default API key for AI provider</td>
</tr>
<tr>
<td><code>BACKEND_DEFAULT_AI_BASE_URL</code></td>
<td>-</td>
<td>Custom API base URL (for local providers)</td>
</tr>
</table>
<h2>Example .env File</h2>
<pre><code>BACKEND_JWT_SECRET=your-super-secret-key-change-this
BACKEND_CORS_ORIGIN=https://your-domain.com
BACKEND_REGISTRATION_ENABLED=false
BACKEND_DEFAULT_USER_EMAIL=admin@your-domain.com
BACKEND_DEFAULT_USER_PASSWORD=change-me-after-login
BACKEND_DEFAULT_AI_PROVIDER=groq
BACKEND_DEFAULT_AI_API_KEY=your-groq-api-key</code></pre>
<h2>Using System Default AI Settings</h2>
<p>When <code>BACKEND_DEFAULT_AI_*</code> variables are set, all new users will use those settings by default. Users can override these in their personal settings.</p>
<div class="tip">
<strong>Tip:</strong> For production, always set <code>BACKEND_REGISTRATION_ENABLED=false</code> and create the admin user via <code>BACKEND_DEFAULT_USER_EMAIL</code> and <code>BACKEND_DEFAULT_USER_PASSWORD</code>.
</div>
<div class="next-steps">
<a href="installation.html" class="btn">← Installation</a>
<a href="api.html" class="btn btn-primary">Next: API Reference →</a>
</div>
</main>
</div>
</body>
</html>

125
www/docs/events.html Normal file
View File

@@ -0,0 +1,125 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Events - DearDiary</title>
<link rel="stylesheet" href="../css/styles.css">
<link rel="stylesheet" href="../css/docs.css">
</head>
<body>
<nav class="navbar">
<div class="nav-container">
<a href="../" class="logo">
<svg width="32" height="32" viewBox="0 0 100 100"><defs><linearGradient id="g" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" style="stop-color:#6d28d9"/><stop offset="100%" style="stop-color:#4c1d95"/></linearGradient></defs><rect width="100" height="100" rx="20" fill="url(#g)"/><path d="M25 25 L75 25 L75 80 L25 80 Z" fill="none" stroke="white" stroke-width="3"/><path d="M35 40 L65 40 M35 50 L65 50 M35 60 L55 60" stroke="white" stroke-width="2"/></svg>
DearDiary
</a>
<div class="nav-links">
<a href="../">Home</a>
<a href="../docs/" class="active">Docs</a>
<a href="../blog/">Blog</a>
<a href="${GIT_URL}" target="_blank">Git Repository</a>
</div>
</div>
</nav>
<div class="docs-layout">
<aside class="docs-sidebar">
<div class="sidebar-section">
<h3>Getting Started</h3>
<a href="installation.html">Installation</a>
<a href="quick-start.html">Quick Start</a>
</div>
<div class="sidebar-section">
<h3>Configuration</h3>
<a href="configuration.html">Environment</a>
<a href="api.html">API Reference</a>
</div>
<div class="sidebar-section">
<h3>Features</h3>
<a href="ai-providers.html">AI Providers</a>
<a href="events.html" class="active">Events</a>
<a href="export-import.html">Export & Import</a>
</div>
</aside>
<main class="docs-content">
<h1>Events</h1>
<p>Events are the building blocks of your diary. They're quick captures throughout the day that get transformed into thoughtful diary pages.</p>
<h2>Event Types</h2>
<table>
<tr>
<th>Type</th>
<th>Description</th>
<th>Example</th>
</tr>
<tr>
<td><strong>Text</strong></td>
<td>Plain text notes</td>
<td>"Coffee with Mike at 9am"</td>
</tr>
<tr>
<td><strong>Photo</strong></td>
<td>Image captures</td>
<td>Sunset from the office window</td>
</tr>
<tr>
<td><strong>Voice</strong></td>
<td>Voice memos</td>
<td>Ideas for the project</td>
</tr>
<tr>
<td><strong>Health</strong></td>
<td>Health-related notes</td>
<td>"Feeling tired, had 6 hours sleep"</td>
</tr>
</table>
<h2>Automatic Metadata</h2>
<p>Every event captures:</p>
<ul>
<li><strong>Timestamp</strong> - When the event was created</li>
<li><strong>Date</strong> - The calendar date (YYYY-MM-DD)</li>
<li><strong>Location</strong> - GPS coordinates (if browser allows)</li>
<li><strong>Place Name</strong> - Reverse geocoded address</li>
</ul>
<h2>Immutability</h2>
<p>Once a diary page is generated for a day, all events for that day become <strong>locked</strong>:</p>
<ul>
<li>You cannot edit or delete individual events</li>
<li>This preserves the authenticity of your record</li>
<li>Your past stays untouched by today's perspective</li>
</ul>
<div class="tip">
<strong>To unlock events:</strong> Delete the diary page for that date. Events become editable again.
</div>
<h2>Event Stream</h2>
<p>The <strong>Today</strong> page shows your event stream for the current day:</p>
<ul>
<li>Newest events appear at the top</li>
<li>Events show time, type, content, and location</li>
<li>Quick add via text input or keyboard shortcut (Ctrl+J)</li>
</ul>
<h2>Browse Past Days</h2>
<p>Use the calendar view or date navigator to view events from any day:</p>
<ul>
<li>Click any date to see that day's events</li>
<li>Days with diary pages are marked</li>
<li>Navigate with arrow keys in the date picker</li>
</ul>
<div class="next-steps">
<a href="api.html" class="btn">← API Reference</a>
<a href="export-import.html" class="btn btn-primary">Next: Export & Import →</a>
</div>
</main>
</div>
</body>
</html>

125
www/docs/export-import.html Normal file
View File

@@ -0,0 +1,125 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Export & Import - DearDiary</title>
<link rel="stylesheet" href="../css/styles.css">
<link rel="stylesheet" href="../css/docs.css">
</head>
<body>
<nav class="navbar">
<div class="nav-container">
<a href="../" class="logo">
<svg width="32" height="32" viewBox="0 0 100 100"><defs><linearGradient id="g" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" style="stop-color:#6d28d9"/><stop offset="100%" style="stop-color:#4c1d95"/></linearGradient></defs><rect width="100" height="100" rx="20" fill="url(#g)"/><path d="M25 25 L75 25 L75 80 L25 80 Z" fill="none" stroke="white" stroke-width="3"/><path d="M35 40 L65 40 M35 50 L65 50 M35 60 L55 60" stroke="white" stroke-width="2"/></svg>
DearDiary
</a>
<div class="nav-links">
<a href="../">Home</a>
<a href="../docs/" class="active">Docs</a>
<a href="../blog/">Blog</a>
<a href="${GIT_URL}" target="_blank">Git Repository</a>
</div>
</div>
</nav>
<div class="docs-layout">
<aside class="docs-sidebar">
<div class="sidebar-section">
<h3>Getting Started</h3>
<a href="installation.html">Installation</a>
<a href="quick-start.html">Quick Start</a>
</div>
<div class="sidebar-section">
<h3>Configuration</h3>
<a href="configuration.html">Environment</a>
<a href="api.html">API Reference</a>
</div>
<div class="sidebar-section">
<h3>Features</h3>
<a href="ai-providers.html">AI Providers</a>
<a href="events.html">Events</a>
<a href="export-import.html" class="active">Export & Import</a>
</div>
</aside>
<main class="docs-content">
<h1>Export & Import</h1>
<p>Your data belongs to you. Export everything anytime, import to restore or migrate.</p>
<h2>Export</h2>
<p>Go to <strong>Settings</strong> and click <strong>Export Data</strong>. This downloads a JSON file containing:</p>
<ul>
<li><strong>version</strong> - DearDiary version</li>
<li><strong>exportedAt</strong> - Timestamp</li>
<li><strong>settings</strong> - Your AI and app settings</li>
<li><strong>events</strong> - All event records with metadata</li>
<li><strong>journals</strong> - All diary pages</li>
<li><strong>tasks</strong> - Generation history</li>
</ul>
<h2>Import</h2>
<p>Go to <strong>Settings</strong> and click <strong>Import Data</strong>. Select your export file.</p>
<h3>Import Behavior</h3>
<ul>
<li><strong>Duplicates skipped</strong> - Events matched by date + content + timestamp</li>
<li><strong>Journals matched by date</strong> - Won't create duplicate diaries</li>
<li><strong>Tasks linked to journals</strong> - Generation history preserved</li>
<li><strong>Settings overwritten</strong> - Your current settings are replaced</li>
</ul>
<h3>Version Compatibility</h3>
<p>DearDiary checks export versions:</p>
<ul>
<li>Minimum supported: 0.0.3</li>
<li>Warnings shown for older/newer versions</li>
<li>May lose data with very old exports</li>
</ul>
<div class="tip">
<strong>Tip:</strong> Export regularly as a backup. Store exports in a safe place.
</div>
<h2>Why Export?</h2>
<ul>
<li><strong>Backup</strong> - Protect against data loss</li>
<li><strong>Migration</strong> - Move to a new server</li>
<li><strong>Privacy</strong> - Keep a local copy</li>
<li><strong>Analysis</strong> - Work with your data in other tools</li>
</ul>
<h2>Export Format</h2>
<pre><code>{
"version": "0.1.0",
"exportedAt": "2026-03-27T12:00:00Z",
"settings": {
"aiProvider": "groq",
"aiApiKey": "gsk_xxx",
...
},
"events": [
{
"id": "evt_xxx",
"date": "2026-03-27",
"type": "text",
"content": "Had coffee with Sarah",
"latitude": 40.7128,
"longitude": -74.0060,
"placeName": "New York, NY",
"createdAt": "2026-03-27T08:30:00Z"
}
],
"journals": [...],
"tasks": [...]
}</code></pre>
<div class="next-steps">
<a href="events.html" class="btn">← Events</a>
<a href="ai-providers.html" class="btn btn-primary">Next: AI Providers →</a>
</div>
</main>
</div>
</body>
</html>

View File

@@ -29,7 +29,17 @@
<h3>Getting Started</h3>
<a href="installation.html">Installation</a>
<a href="quick-start.html">Quick Start</a>
</div>
<div class="sidebar-section">
<h3>Configuration</h3>
<a href="configuration.html">Environment</a>
<a href="api.html">API Reference</a>
</div>
<div class="sidebar-section">
<h3>Features</h3>
<a href="events.html">Events</a>
<a href="ai-providers.html">AI Providers</a>
<a href="export-import.html">Export & Import</a>
</div>
</aside>

View File

@@ -29,7 +29,17 @@
<h3>Getting Started</h3>
<a href="installation.html" class="active">Installation</a>
<a href="quick-start.html">Quick Start</a>
</div>
<div class="sidebar-section">
<h3>Configuration</h3>
<a href="configuration.html">Environment</a>
<a href="api.html">API Reference</a>
</div>
<div class="sidebar-section">
<h3>Features</h3>
<a href="events.html">Events</a>
<a href="ai-providers.html">AI Providers</a>
<a href="export-import.html">Export & Import</a>
</div>
</aside>

View File

@@ -29,7 +29,17 @@
<h3>Getting Started</h3>
<a href="installation.html">Installation</a>
<a href="quick-start.html" class="active">Quick Start</a>
</div>
<div class="sidebar-section">
<h3>Configuration</h3>
<a href="configuration.html">Environment</a>
<a href="api.html">API Reference</a>
</div>
<div class="sidebar-section">
<h3>Features</h3>
<a href="events.html">Events</a>
<a href="ai-providers.html">AI Providers</a>
<a href="export-import.html">Export & Import</a>
</div>
</aside>