|
|
9 uur geleden | |
|---|---|---|
| .. | ||
| public | 23 uur geleden | |
| src | 9 uur geleden | |
| src-tauri | 9 uur geleden | |
| .gitignore | 1 dag geleden | |
| README.md | 9 uur geleden | |
| nuxt.config.ts | 20 uur geleden | |
| package.json | 9 uur geleden | |
| vitest.config.ts | 20 uur geleden | |
A warm, literary journal app. Built with Tauri, Nuxt UI, and the @enesis/editor block markdown engine.
Daily notes are flat markdown files (journals/YYYY-MM-DD.md) — readable anywhere, no lock-in. A SQLite index provides full-text search and backlinks.
The visual identity (Hearthside theme) leans into warmth: Lora serif, clay primary, stone neutrals, earthy semantics.
pnpm install
pnpm generate # static build
pnpm tauri dev # or: pnpm tauri build
| Layer | Technology |
|---|---|
| Desktop shell | Tauri v2 (Rust) |
| Frontend | Nuxt 3 + Vue 3 + TypeScript |
| UI framework | Nuxt UI v4 |
| Editor engine | @enesis/editor (Lezer-based block markdown) |
| Index | SQLite via tauri-plugin-sql, FTS5 |
| File watching | notify crate |
Warm, earthy, literary. Lora serif throughout, clay primary, orange secondary, stone neutral base, rose/emerald/amber/sky for semantics. Configured in app.config.ts and assets/main.css.
pnpm dev # Vite dev server
pnpm tauri dev # Tauri desktop dev
pnpm generate # Static pre-render (for Tauri)
pnpm test:e2e # Playwright E2E (in packages/editor)
src/
assets/main.css # Tailwind + theme tokens + font
app.config.ts # Nuxt UI color mappings
components/
JournalDay.vue # One Editor per day
JournalView.vue # Reverse-chronological feed
TimelineRail.vue # Density dot timeline
AppRightSidebar.vue # References + search
layouts/default.vue # Sidebars + editor shell
composables/ # useFileSystem, useDates, etc.
stores/ # Pinia: workspace, ui
lib/ # Indexer, schema, parse helpers
src-tauri/
src/lib.rs # Rust commands + plugins
icons/ # App icons (clay block logo)
public/
favicon.svg # Clay block stacking logo
Content is saved to disk 500ms after you stop typing. Pending saves are flushed immediately when navigating away, so you won't lose edits from quick page switches.
No file is created until you type. Clicking a [[link]] navigates to the page's path and shows an empty editor. The file is written to disk only when you add content. If you navigate away without typing, nothing is saved. This keeps your workspace clean of empty placeholder files.
The conventional location for new pages is the pages/ directory (e.g. pages/My Note.md). You can change this in Settings.
The title at the top of a page is an editable <input> styled as a heading. Changing it renames the underlying file on disk. Press Enter to confirm, Escape to cancel. Note: existing [[links]] in other pages are not updated — that's a planned enhancement.
Clicking a #tag opens a virtual aggregation page showing all blocks that reference it, regardless of which file they're in. This is a read-only view — no file on disk until you type content here (future feature).
At the bottom of every page, a collapsible "Linked references" section shows which other pages link to this one. Each result includes the source page name and a contextual excerpt with the [[link]] highlighted. Clicking a backlink navigates to the source page.
Full-text search across the SQLite index is planned but not yet wired to the sidebar. The FTS5 index is built, the query logic is ready, but the UI is not connected.
The SQLite index is rebuilt on two paths with different trade-offs:
syncIndex)Runs every time the app launches. Avoids unnecessary work:
.md files from the filesystempages.content_hash)splitMarkdownIntoBlocks, no SQL writes)indexFile (block-level diff, only writes changed blocks)Files whose content hasn't changed cost one hash computation and a SELECT query. No block parsing, no link extraction, no write amplification.
fullReindex)Triggered via File → Reindex Library (Cmd+Shift+R). Wipes the entire index (DELETE FROM pages — FK cascade handles blocks, links, FTS) and re-indexes every .md file from scratch. Use when you suspect corruption or want a guaranteed clean state.
Between these two flows, the notify-based file watcher handles individual file changes:
indexFile on the single fileremoveFile (cascade)The watcher starts before sync completes. If a file changes mid-sync, the watcher re-indexes it independently — worst case a stale entry that corrects on the next change.
For implementation details, data flow diagrams, and edge case documentation, see AGENTS.md in the repository root. Key sections:
[...slug].vue classifies paths (page vs tag)EditorBlock click → usePageNavigation → router pushcomputePageTitle() ensures every page has a non-empty title@remarks on each component and function list deferred workpnpm test # vitest run in apps/tauri
biome check src/ # run from apps/tauri