diff --git a/crates/ledger-gui/src/app.rs b/crates/ledger-gui/src/app.rs index 86323b5..6d2ede6 100644 --- a/crates/ledger-gui/src/app.rs +++ b/crates/ledger-gui/src/app.rs @@ -47,6 +47,7 @@ pub struct App { state: PageState, palette: crate::palette::Palette, updated_at: f64, + live_label: bool, } impl App { @@ -84,6 +85,7 @@ impl App { state: PageState::default(), palette: Default::default(), updated_at: -1e9, + live_label: false, } } @@ -98,6 +100,12 @@ impl App { } /// Page state (tests). + /// Label a fixed-books app "Live", as it reads when following a + /// journal (screenshots of what a running app looks like). + pub fn show_live_label(&mut self) { + self.live_label = true; + } + pub fn state_mut(&mut self) -> &mut PageState { &mut self.state } @@ -250,7 +258,7 @@ impl App { ui, b, ui.input(|i| i.time) - self.updated_at, - self.loader.is_some(), + self.loader.is_some() || self.live_label, ); } }); diff --git a/crates/ledger-gui/tests/screens.rs b/crates/ledger-gui/tests/screens.rs index 394614f..eb9fd14 100644 --- a/crates/ledger-gui/tests/screens.rs +++ b/crates/ledger-gui/tests/screens.rs @@ -87,6 +87,9 @@ fn screenshots() { .unwrap_or(920.0), )) .build_eframe(|cc| App::with_books(&cc.egui_ctx, books, dark, route.clone())); + if std::env::var("SHOT_LIVE").is_ok() { + harness.state_mut().show_live_label(); + } harness.run_steps(4); let ctx = harness.ctx.clone(); harness.state_mut().settle(&ctx); diff --git a/justfile b/justfile index 57ce8de..7d95ca9 100644 --- a/justfile +++ b/justfile @@ -27,15 +27,16 @@ install: demo: cargo run --release -p ledger-gui -- --demo -# Regenerate the website's screenshots from the demo company +# Regenerate the website's screenshots (dark) from the demo company site-shots: #!/usr/bin/env bash set -euo pipefail tmp=$(mktemp -d) - SHOT_DIR="$tmp/light" SHOT_ONLY=overview,entry,pnl SHOT_ENTRY=249 cargo test -p ledger-gui --test screens - SHOT_DIR="$tmp/dark" SHOT_DARK=1 SHOT_ONLY=overview cargo test -p ledger-gui --test screens - for f in overview entry pnl; do cp "$tmp/light/$f.png" site/assets/; done - cp "$tmp/dark/overview.png" site/assets/overview-dark.png + SHOT_DIR="$tmp" SHOT_DARK=1 SHOT_LIVE=1 SHOT_ONLY=overview,pnl cargo test -p ledger-gui --test screens + # The hero's viewer pane: taller, to sit beside the session. + SHOT_DIR="$tmp" SHOT_DARK=1 SHOT_LIVE=1 SHOT_ONLY=entry SHOT_ENTRY=245 SHOT_HEIGHT=1150 cargo test -p ledger-gui --test screens + for f in overview entry pnl; do cp "$tmp/$f.png" site/assets/; done + rm -f site/assets/overview-dark.png rm -rf "$tmp" # Assemble the website in site/dist (index.html, install.sh, assets) diff --git a/site/assets/entry.png b/site/assets/entry.png index a093a61..fcaa57c 100644 Binary files a/site/assets/entry.png and b/site/assets/entry.png differ diff --git a/site/assets/overview-dark.png b/site/assets/overview-dark.png deleted file mode 100644 index 2663179..0000000 Binary files a/site/assets/overview-dark.png and /dev/null differ diff --git a/site/assets/overview.png b/site/assets/overview.png index 85b65e4..44969ed 100644 Binary files a/site/assets/overview.png and b/site/assets/overview.png differ diff --git a/site/assets/pnl.png b/site/assets/pnl.png index f29fc5a..d5ea6e2 100644 Binary files a/site/assets/pnl.png and b/site/assets/pnl.png differ diff --git a/site/index.html b/site/index.html index e575fa1..97d6006 100644 --- a/site/index.html +++ b/site/index.html @@ -62,8 +62,24 @@ h1 { font-size: clamp(38px, 6vw, 62px); line-height: 1.04; letter-spacing: -0.03 @media (max-width: 760px) { .equation { grid-template-columns: 1fr; } .equation .op { justify-self: center; line-height: 1; } } .shot { margin: 40px 0 8px; border-radius: 14px; border: 1px solid var(--border); overflow: hidden; box-shadow: 0 24px 60px -24px rgba(0,0,0,.25); background: var(--surface); } .shot img { display: block; width: 100%; height: auto; } -.shot.dark { display: none; } -@media (prefers-color-scheme: dark) { .shot.light { display: none; } .shot.dark { display: block; } } +.duo { margin: 44px 0 8px; display: grid; grid-template-columns: 5fr 8fr; gap: 16px; align-items: stretch; } +.duo figcaption { grid-column: 1 / -1; color: var(--faint); font-size: 14px; text-align: center; margin-top: 2px; } +.duo .shot { margin: 0; align-self: start; } +.term-pane { background: #0b0b0d; border: 1px solid #2a2b30; border-radius: 14px; overflow: hidden; box-shadow: 0 24px 60px -24px rgba(0,0,0,.35); display: flex; flex-direction: column; color: #d6d6dc; } +.term-bar { display: flex; align-items: center; gap: 7px; padding: 11px 14px; border-bottom: 1px solid #222328; font: 500 12px Inter, sans-serif; color: #8a8a94; } +.term-bar span { width: 10px; height: 10px; border-radius: 50%; background: #34353b; } +.term-bar b { font-weight: 500; margin-left: 8px; } +.term-body { padding: 14px 16px 16px; font: 400 12px/1.5 ui-monospace, "SF Mono", Menlo, Consolas, monospace; display: flex; flex-direction: column; gap: 8px; } +.term-body .you { color: #ececee; background: #17181c; border: 1px solid #2a2b30; border-radius: 8px; padding: 7px 10px; } +.term-body .ai, .term-body .tool { padding-left: 18px; position: relative; } +.term-body i { position: absolute; left: 0; font-style: normal; color: #ececee; font-size: 10px; line-height: 18px; } +.term-body .tool i { color: #4ade80; } +.term-body .tool { color: #a3a3ac; } +.term-body .tool b { color: #ececee; font-weight: 600; } +.term-body .tool span { color: #6e6e78; } +.term-body .ai b { color: #fff; } +.term-body pre { margin: 6px 0; font: inherit; color: #ececee; white-space: pre; overflow-x: auto; } +@media (max-width: 860px) { .duo { grid-template-columns: 1fr; } } .caption { color: var(--faint); font-size: 14px; text-align: center; margin: 10px 0 0; } section { padding: 72px 0 8px; } h2 { font-size: clamp(27px, 3.6vw, 38px); letter-spacing: -0.02em; line-height: 1.12; margin: 0 0 14px; } @@ -143,9 +159,27 @@ footer { padding: 72px 0 48px; color: var(--faint); font-size: 14px; display: fl

One line installs everything, makes your books, and starts your bookkeeper in Claude Code. Using Codex? Add --codex to the end. Linux and macOS; Windows via WSL2.

-
The wanderbooks overview: cash, what you owe, spending, revenue, runway, a cash chart, and what needs attention
-
The wanderbooks overview in dark mode
-

The viewer, on a demo company. You work by talking to Claude or Codex; the viewer is for looking.

+
+ +
The wanderbooks viewer showing entry #245, Adobe Creative Cloud, with its lines and the rendered receipt
+
An example session: you talk to Claude Code (or Codex) on the left; the viewer on the right follows along live, receipt and all. Demo company.
+

Just ask.

@@ -219,7 +253,7 @@ footer { padding: 72px 0 48px; color: var(--faint); font-size: 14px; display: fl
-
A transaction with its lines, its rendered receipt, and its history
+
The viewer's overview: cash, what you owe, spending, revenue, runway, a cash chart, and what needs attention

Talk to change. Look in the viewer.

Everything that changes your books happens in conversation with Claude or Codex. The viewer is the other half: a live, read-only window on the books for browsing, searching, and reports. Whatever your bookkeeper posts shows up there in a fraction of a second, and every number goes all the way down: click an amount on a statement for the transactions behind it, then a transaction for its lines, the receipt itself, and its history.