Skip to content

Commit 33f3e67

Browse files
joaoh82claude
andauthored
SQLR-41 — Tauri 2 + Svelte 5 local-first journaling example app (#145)
* feat(examples): SQLR-41 add Tauri 2 + Svelte 5 journaling desktop app New `examples/desktop-journal/` showcases SQLRite as a serious choice for a local-first desktop product. Tauri 2 backend owns one Arc<Mutex<Connection>> in tauri::State; every #[tauri::command] grabs the mutex and runs against the modern `Connection` API. Phase 8 BM25 full-text search drives the search bar with token-boundary-aware <mark> highlighting in Rust. An "ask my journal" panel calls Connection::ask, validates the returned SQL is SELECT/WITH-only, and shows the user both the SQL and the rows. In-app Settings dialog persists the Anthropic key to a separate settings.json next to the journal file — the key never crosses into the webview (DTO returns has_api_key: bool, not the value) and falls back to SQLRITE_LLM_API_KEY when nothing's saved. Capabilities are locked down to core window/event + dialog — no fs/shell/http, so the IPC boundary is the only path to the engine. Wiring: workspace gains `examples/desktop-journal/src-tauri` as a member; CI's existing rust-build/test/clippy/doc commands pick up an `--exclude sqlrite-journal` (same shape as the existing sqlrite-desktop exclude). A new `journal-build` CI job mirrors `desktop-build` for the frontend bundle + cargo build, including a no-default-features pass to prove the off-`ask` build still works. A separate `journal-release.yml` (manual / journal-v* tag trigger) builds .dmg / .deb / .AppImage / .msi via tauri-action and attaches them to a draft release. 14 unit tests cover migrations, CRUD, tag filtering, FTS+highlight, stats, the ask-readonly SQL classifier, settings save/load round-trip, empty-string-key normalisation, three-valued update semantics, the no-leak-to-DTO contract, and settings-over-env precedence. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(examples): SQLR-41 add Remotion demo + screenshots + website card poster Follow-up to be35e4c. Captures the journal app in seven UI states (empty, new entry, markdown preview, list+tags, FTS highlight, Settings, Ask panel), then composes them into a 21s demo video via a Remotion project under `examples/desktop-journal/demo/`. The composition gives each screen a Ken Burns slow zoom with a fade-in caption strip; consecutive screens cross-fade for 8 frames. Renders to `docs/demo.mp4` (1080p H.264, ~8.5 MB) and `docs/demo.gif` (960×540, 15fps, first 5 screens, ~8.8 MB). The GIF fits comfortably in the README and on GitHub's inline image viewer; the MP4 is what the website Examples card points at. Replacing a screenshot is `cd demo && npm run render` — `prep` copies the latest PNGs from `../docs/screenshots/` into `public/` (.gitignore'd so the canonical source stays in `docs/`). Side change: pin `@tauri-apps/{api,cli}` to ~2.10 and `plugin-dialog` to ~2.7 in the journal app's `package.json`. `tauri build` rejects mismatched JS↔Rust major/minor versions; the mismatch shows up the moment you bundle for installer shipping (SQLR-41's release workflow) even though dev mode tolerates it. Website Examples card gains an `Example.demoAsset` field carrying the GIF + MP4 paths. The journal card renders the GIF inline from raw.githubusercontent.com so the homepage tracks the repo on next deploy instead of needing the asset copied into `web/public/`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 83eae48 commit 33f3e67

58 files changed

Lines changed: 9182 additions & 10 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
# - go-sdk {ubuntu, macos} cgo against libsqlrite_c + go test
1111
# - wasm-build ubuntu wasm-pack build + size report
1212
# - desktop-build ubuntu npm ci + cargo build -p sqlrite-desktop
13+
# - journal-build ubuntu npm ci + cargo build -p sqlrite-journal (SQLR-41 example)
1314
#
1415
# All jobs use caching so a warm PR run takes 2–3 minutes on ubuntu.
1516
# Go CI skips Windows for Phase 6b — Go's cgo on Windows needs a mingw
@@ -102,6 +103,7 @@ jobs:
102103
run: |
103104
cargo build --workspace \
104105
--exclude sqlrite-desktop \
106+
--exclude sqlrite-journal \
105107
--exclude sqlrite-python \
106108
--exclude sqlrite-nodejs \
107109
--exclude sqlrite-benchmarks \
@@ -111,6 +113,7 @@ jobs:
111113
run: |
112114
cargo test --workspace \
113115
--exclude sqlrite-desktop \
116+
--exclude sqlrite-journal \
114117
--exclude sqlrite-python \
115118
--exclude sqlrite-nodejs \
116119
--exclude sqlrite-benchmarks
@@ -147,6 +150,7 @@ jobs:
147150
run: |
148151
cargo clippy --workspace \
149152
--exclude sqlrite-desktop \
153+
--exclude sqlrite-journal \
150154
--exclude sqlrite-python \
151155
--exclude sqlrite-nodejs \
152156
--exclude sqlrite-benchmarks \
@@ -158,6 +162,7 @@ jobs:
158162
run: |
159163
cargo doc --workspace \
160164
--exclude sqlrite-desktop \
165+
--exclude sqlrite-journal \
161166
--exclude sqlrite-python \
162167
--exclude sqlrite-nodejs \
163168
--exclude sqlrite-benchmarks \
@@ -400,3 +405,58 @@ jobs:
400405

401406
- name: Build Rust side
402407
run: cargo build -p sqlrite-desktop
408+
409+
# ---------------------------------------------------------------------------
410+
# Journal example (SQLR-41): Tauri 2 + Svelte 5 daily-notes app under
411+
# `examples/desktop-journal/`. Same shape as `desktop-build` — frontend
412+
# first, then `cargo build -p sqlrite-journal`. Excluded from the
413+
# default workspace commands for the same reasons (Svelte build is a
414+
# prerequisite that the main rust-build-and-test job can't satisfy).
415+
journal-build:
416+
name: journal-build
417+
runs-on: ubuntu-latest
418+
steps:
419+
- uses: actions/checkout@v4
420+
421+
- uses: actions/setup-node@v4
422+
with:
423+
node-version: '20'
424+
cache: 'npm'
425+
cache-dependency-path: examples/desktop-journal/package-lock.json
426+
427+
- uses: dtolnay/rust-toolchain@stable
428+
429+
- name: Install Tauri Linux deps
430+
run: |
431+
sudo apt-get update
432+
sudo apt-get install -y \
433+
libwebkit2gtk-4.1-dev \
434+
libayatana-appindicator3-dev \
435+
librsvg2-dev \
436+
patchelf
437+
438+
- uses: Swatinem/rust-cache@v2
439+
with:
440+
shared-key: journal-build
441+
442+
- name: npm install
443+
working-directory: examples/desktop-journal
444+
# `npm ci` would be ideal, but the example doesn't ship a
445+
# lockfile in version control (it's listed in .gitignore so
446+
# downstream forkers don't have to fight a node-version-pinned
447+
# lockfile). `npm install` is acceptable for an example app;
448+
# the engine API surface is what we're really exercising.
449+
run: npm install
450+
451+
- name: Build frontend
452+
working-directory: examples/desktop-journal
453+
run: npm run build
454+
455+
- name: Build Rust side (with ask)
456+
run: cargo build -p sqlrite-journal --all-targets
457+
458+
- name: Build Rust side (no ask)
459+
run: cargo build -p sqlrite-journal --no-default-features --all-targets
460+
461+
- name: Run journal unit tests
462+
run: cargo test -p sqlrite-journal
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# SQLRite Journal — installer build workflow (SQLR-41).
2+
#
3+
# Produces packaged installers for the example desktop journal app:
4+
# - macOS: .dmg + .app bundle
5+
# - Linux: .deb + .AppImage
6+
# - Windows: .msi (best-effort; flag in README if it lights up red)
7+
#
8+
# Manual trigger by default — installers are heavy (~30–40 min total
9+
# wall clock across the matrix), and the example app changes much less
10+
# often than the engine. Tagged pushes matching `journal-v*` also fire.
11+
# Artifacts are attached to a draft GitHub release rather than the
12+
# engine's own release stream so engine releases don't accidentally
13+
# ship a journal binary baseline that's lagging behind.
14+
15+
name: Journal example — installers
16+
17+
on:
18+
workflow_dispatch:
19+
push:
20+
tags:
21+
- 'journal-v*'
22+
23+
permissions:
24+
contents: write # tauri-action needs this to upload to the draft release
25+
26+
jobs:
27+
build:
28+
strategy:
29+
fail-fast: false
30+
matrix:
31+
include:
32+
- os: macos-latest
33+
label: macos-arm64
34+
target: aarch64-apple-darwin
35+
- os: macos-13
36+
label: macos-x86_64
37+
target: x86_64-apple-darwin
38+
- os: ubuntu-latest
39+
label: linux-x86_64
40+
target: x86_64-unknown-linux-gnu
41+
- os: windows-latest
42+
label: windows-x86_64
43+
target: x86_64-pc-windows-msvc
44+
45+
name: build (${{ matrix.label }})
46+
runs-on: ${{ matrix.os }}
47+
48+
steps:
49+
- uses: actions/checkout@v4
50+
51+
- uses: actions/setup-node@v4
52+
with:
53+
node-version: '20'
54+
55+
- uses: dtolnay/rust-toolchain@stable
56+
with:
57+
targets: ${{ matrix.target }}
58+
59+
- name: Install Tauri Linux deps
60+
if: matrix.os == 'ubuntu-latest'
61+
run: |
62+
sudo apt-get update
63+
sudo apt-get install -y \
64+
libwebkit2gtk-4.1-dev \
65+
libayatana-appindicator3-dev \
66+
librsvg2-dev \
67+
patchelf \
68+
libsoup-3.0-dev \
69+
libjavascriptcoregtk-4.1-dev
70+
71+
- uses: Swatinem/rust-cache@v2
72+
with:
73+
workspaces: ./examples/desktop-journal/src-tauri
74+
shared-key: journal-release-${{ matrix.label }}
75+
76+
- name: npm install
77+
working-directory: examples/desktop-journal
78+
run: npm install
79+
80+
# tauri-action does the magic: builds frontend, runs `cargo tauri
81+
# build`, and uploads the resulting installers to a draft release
82+
# tagged with `tagName`. We deliberately don't auto-publish — a
83+
# human reviews the draft and clicks publish.
84+
- uses: tauri-apps/tauri-action@v0
85+
env:
86+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
87+
with:
88+
projectPath: examples/desktop-journal
89+
tagName: ${{ startsWith(github.ref, 'refs/tags/journal-v') && github.ref_name || format('journal-v{0}', github.run_number) }}
90+
releaseName: 'SQLRite Journal ${{ startsWith(github.ref, ''refs/tags/journal-v'') && github.ref_name || format(''build-{0}'', github.run_number) }}'
91+
releaseBody: |
92+
Installer artifacts for the SQLRite Journal example app
93+
(SQLR-41). Built against the engine version pinned in
94+
`examples/desktop-journal/src-tauri/Cargo.toml`.
95+
96+
* macOS: `.dmg` (Apple Silicon + Intel)
97+
* Linux: `.deb` + `.AppImage`
98+
* Windows: `.msi`
99+
100+
Source: <https://github.com/joaoh82/rust_sqlite/tree/main/examples/desktop-journal>
101+
releaseDraft: true
102+
prerelease: false
103+
args: --target ${{ matrix.target }}

AGENTS.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@ SQLRite is a from-scratch SQLite-style embedded database written in Rust. It's p
88

99
## Workspace layout
1010

11-
`Cargo.toml` is a workspace whose members are: `.` (the engine, package `sqlrite-engine`, lib `sqlrite`), `desktop/src-tauri`, `sqlrite-ffi`, `sqlrite-ask`, `sqlrite-mcp`, `sdk/python`, `sdk/nodejs`, `benchmarks`. `sdk/wasm` and `sdk/go` are deliberately **not** workspace members (wasm32 target / cgo separation).
11+
`Cargo.toml` is a workspace whose members are: `.` (the engine, package `sqlrite-engine`, lib `sqlrite`), `desktop/src-tauri`, `examples/desktop-journal/src-tauri`, `sqlrite-ffi`, `sqlrite-ask`, `sqlrite-mcp`, `sdk/python`, `sdk/nodejs`, `benchmarks`. `sdk/wasm` and `sdk/go` are deliberately **not** workspace members (wasm32 target / cgo separation).
1212

1313
- `src/` — engine. Public API is `Connection`/`Statement`/`Rows`/`Row`/`Value` from [src/connection.rs](src/connection.rs), re-exported via [src/lib.rs](src/lib.rs). Any new SDK should bind only to this surface.
1414
- `sqlrite-ask/` — pure-Rust LLM adapter (Anthropic/OpenAI/Ollama) for natural-language → SQL. The engine's `ask` feature provides the thin `ConnectionAskExt::ask` glue.
1515
- `sqlrite-mcp/` — MCP stdio server. Seven tools: `list_tables`, `describe_table`, `query`, `execute`, `schema_dump`, `vector_search`, `ask`. `--read-only` opens with a shared lock and hides `execute`.
1616
- `sqlrite-ffi/` — C ABI cdylib + generated `sqlrite.h` header. Backs the Go SDK and any C consumer.
17-
- `desktop/` — Tauri 2 + Svelte 5 GUI. Embeds the engine directly (no FFI hop).
17+
- `desktop/` — Tauri 2 + Svelte 5 generic SQL playground GUI. Embeds the engine directly (no FFI hop).
18+
- `examples/desktop-journal/` — Tauri 2 + Svelte 5 local-first journaling app (SQLR-41). Showcase for Phase 8 BM25 + `ask` in a non-AI-native product. Mirrors `desktop/`'s engine-as-Cargo-dep pattern but uses the modern `Connection` API.
1819
- `benchmarks/` — SQLR-4 / SQLR-16 bench harness. `Driver` trait + SQLRite + SQLite (rusqlite-bundled) drivers + criterion-driven workloads. Excluded from the default CI build/test/clippy/doc commands; run locally with `make bench` (or `make bench-duckdb`). See [docs/benchmarks-plan.md](docs/benchmarks-plan.md).
1920
- `web/` — marketing + docs site (Next.js 15 + Tailwind v4). Independent of the Cargo workspace; lives in-repo for now but is structured to lift into its own repository later. See [web/README.md](web/README.md).
2021

@@ -30,16 +31,16 @@ CI is the source of truth — the workspace excludes that follow are required be
3031

3132
```sh
3233
# Build / test the Rust workspace (matches CI)
33-
cargo build --workspace --exclude sqlrite-desktop --exclude sqlrite-python --exclude sqlrite-nodejs --exclude sqlrite-benchmarks --all-targets
34-
cargo test --workspace --exclude sqlrite-desktop --exclude sqlrite-python --exclude sqlrite-nodejs --exclude sqlrite-benchmarks
34+
cargo build --workspace --exclude sqlrite-desktop --exclude sqlrite-journal --exclude sqlrite-python --exclude sqlrite-nodejs --exclude sqlrite-benchmarks --all-targets
35+
cargo test --workspace --exclude sqlrite-desktop --exclude sqlrite-journal --exclude sqlrite-python --exclude sqlrite-nodejs --exclude sqlrite-benchmarks
3536

3637
# Single test (exact name; --nocapture to see println!)
3738
cargo test <test_name> -- --nocapture
3839

3940
# Lint (CI runs all three)
4041
cargo fmt --all -- --check
41-
cargo clippy --workspace --exclude sqlrite-desktop --exclude sqlrite-python --exclude sqlrite-nodejs --exclude sqlrite-benchmarks --all-targets
42-
cargo doc --workspace --exclude sqlrite-desktop --exclude sqlrite-python --exclude sqlrite-nodejs --exclude sqlrite-benchmarks --no-deps
42+
cargo clippy --workspace --exclude sqlrite-desktop --exclude sqlrite-journal --exclude sqlrite-python --exclude sqlrite-nodejs --exclude sqlrite-benchmarks --all-targets
43+
cargo doc --workspace --exclude sqlrite-desktop --exclude sqlrite-journal --exclude sqlrite-python --exclude sqlrite-nodejs --exclude sqlrite-benchmarks --no-deps
4344

4445
# Run the REPL (default features include cli + ask + file-locks)
4546
cargo run # in-memory
@@ -50,6 +51,7 @@ cargo run -- --readonly path/to/db.sqlrite # shared-lock open
5051
cargo build --release -p sqlrite-ffi # C cdylib + sqlrite.h
5152
cd desktop && npm install && npm run tauri dev # desktop app dev mode
5253
cargo run -p sqlrite-mcp -- /path/to.sqlrite # MCP server (stdio)
54+
cd examples/desktop-journal && npm install && npm run tauri dev # journal example app
5355

5456
# Benchmarks (SQLR-4 / SQLR-16) — local-only, never CI
5557
make bench # SQLRite + SQLite (lean)

Cargo.lock

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
# wasm32-unknown-unknown. `cargo build --workspace` on a native host
1010
# would fail on a wasm-only crate; wasm-pack drives that build
1111
# separately.
12-
members = [".", "desktop/src-tauri", "sqlrite-ffi", "sqlrite-ask", "sqlrite-mcp", "sdk/python", "sdk/nodejs", "benchmarks"]
12+
members = [".", "desktop/src-tauri", "examples/desktop-journal/src-tauri", "sqlrite-ffi", "sqlrite-ask", "sqlrite-mcp", "sdk/python", "sdk/nodejs", "benchmarks"]
1313
resolver = "3"
1414

1515
[package]

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ Beyond the per-language quickstarts in [`examples/`](examples/), the SQLR-38 umb
116116
|---|---|---|
117117
| [Python LLM agent with persistent memory](examples/python-agent/) | Python | Vector + lexical recall, fact extraction, summaries — all in one `.sqlrite` file |
118118
| [Chat-with-your-notes via Claude Desktop MCP](examples/nodejs-notes/) | Node.js | Markdown → hybrid HNSW + BM25 index → `sqlrite-mcp --read-only` → Claude Desktop |
119+
| [Local-first journaling desktop app](examples/desktop-journal/) | Tauri 2 + Svelte 5 | Markdown daily-notes, BM25 full-text search with hit highlighting, "ask my journal" panel — entire data layer is one `.sqlrite` file |
119120

120121
### Developer guide
121122

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Tauri / Vite / Node
2+
dist/
3+
node_modules/
4+
src-tauri/target/
5+
src-tauri/gen/
6+
*.log
7+
8+
# Tauri builds runtime caches into the bundle dir
9+
src-tauri/Cargo.lock

0 commit comments

Comments
 (0)