Dashboard

Settings

Configure LLM, pipeline, tracks, prompts, and system

this.saved = false, 3000); } catch(e) { this.error = e.message; } finally { this.saving = false; } }, async saveAll() { this.saving = true; this.error = ''; try { const res = await fetch('/api/settings', { method: 'PUT', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(this.settings) }); if (!res.ok) throw new Error(await res.text()); this.saved = true; setTimeout(() => this.saved = false, 3000); } catch(e) { this.error = e.message; } finally { this.saving = false; } }, async resetAll() { if (!confirm('Reset ALL settings to defaults? This cannot be undone.')) return; try { await fetch('/api/settings/reset', {method: 'POST'}); location.reload(); } catch(e) { this.error = e.message; } }, async resetPrompt(stage) { if (!confirm(`Reset ${stage} prompt to default?`)) return; try { await fetch(`/api/settings/prompts/${stage}/reset`, {method: 'POST'}); const res = await fetch(`/api/settings/prompts/${stage}`); const data = await res.json(); this.settings.prompts[stage] = data.prompt; this.saved = true; setTimeout(() => this.saved = false, 3000); } catch(e) { this.error = e.message; } }, async addTrack() { if (!this.newTrackName) return; try { const res = await fetch('/api/settings/tracks', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ name: this.newTrackName, description: 'Custom track', slug_prefix: this.newTrackName + '-', enabled: true, gates: { brief: {enabled: true, required_fields: [], min_word_count: 200, max_word_count: 0}, thesis: {enabled: true, required_fields: [], min_word_count: 300, max_word_count: 0}, outline: {enabled: true, required_fields: [], min_word_count: 100, max_word_count: 0}, script: {enabled: true, required_fields: [], min_word_count: 1000, max_word_count: 0}, fact: {enabled: true, required_fields: [], min_word_count: 0, max_word_count: 0}, publish: {enabled: true, required_fields: [], min_word_count: 0, max_word_count: 0}, }, metadata: {} }) }); if (!res.ok) throw new Error(await res.text()); const data = await res.json(); this.settings.tracks[this.newTrackName] = data.track; this.newTrackName = ''; this.saved = true; setTimeout(() => this.saved = false, 3000); } catch(e) { this.error = e.message; } }, async deleteTrack(name) { if (!confirm(`Delete track '${name}'?`)) return; try { await fetch(`/api/settings/tracks/${name}`, {method: 'DELETE'}); delete this.settings.tracks[name]; this.saved = true; setTimeout(() => this.saved = false, 3000); } catch(e) { this.error = e.message; } }, async testPaths() { try { const res = await fetch('/api/settings/paths/test', {method: 'POST'}); const data = await res.json(); this.pathTestResults = data.paths; } catch(e) { this.error = e.message; } }, pathTestResults: null, promptPreview: '', previewStage: '', previewPrompt(stage) { this.previewStage = stage; const p = this.settings.prompts[stage]; this.promptPreview = `--- SYSTEM ---\n${p.system}\n\n--- USER ---\n${p.user}`; }, addDirToList(section, field) { const input = prompt('Enter directory path:'); if (input) { this.settings[section][field].push(input); } }, removeDirFromList(section, field, index) { this.settings[section][field].splice(index, 1); } }" class="space-y-6">
✓ Settings saved successfully

LLM Configuration

Stored in memory only — never persisted to disk

(off = rule-based fallback)

Pipeline Configuration

(auto-progress through gates)
(retry failed gates automatically)

Content Tracks

Prompt Templates

Preview:

                

Directory Paths

Security — Allowed Directories

Server Configuration

Requires restart to take effect

System Information

Version 0.2.0
Python 3.12+
Stack FastAPI + HTMX + Tailwind + Alpine.js
State Store Filesystem (status.yaml)
LLM Provider
LLM Enabled
Tracks
Settings File settings.yaml

Actions