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 viewer, on a demo company. You work by talking to Claude or Codex; the viewer is for looking.
+6100 Software & Subscriptions Dr 59.38 + 2100 Business Credit Card Cr 59.38Balanced, receipt attached. Software is now $1,324.69 for the year. Post it?



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.