Skip to main content

max / balanced_breakfast

git clone https://makenot.work/git/max/balanced_breakfast.git git clone git@ssh.makenot.work:max/balanced_breakfast.git
Name Size
/ crates/
/ dist/
/ docs/
/ migrations/
/ plugins/
/ scripts/
/ src-tauri/
· .env.example 177 B
· .gitignore 1.7 KB
· app-icon.png 51.4 KB
· BalancedBreakfast-Pitch.pdf 8.6 KB
· bento.toml 1.2 KB
· Cargo.lock 191.5 KB
· Cargo.toml 3.7 KB
· CHANGELOG.md 1.3 KB
· CLA.md 6.4 KB
· CONTRIBUTING.md 9.7 KB
· generate_pitch_pdf.py 16.1 KB
· LICENSE 4.3 KB
· logo.svg 1.5 KB
· README.md 7.3 KB
· rust-toolchain.toml 86 B
· synckit.toml 501 B

README

Balanced Breakfast

A desktop feed aggregator that unifies RSS, Hacker News, arXiv, and other sources into a single timeline. Built with Tauri 2, Rust, and a Rhai plugin system for extensible feed fetching.

Prerequisites

  • Rust (stable toolchain, 2021 edition)
  • Tauri 2 CLI (cargo install tauri-cli --version '^2')
  • Linux only: system dependencies for WebKitGTK
    # Debian/Ubuntu
    sudo apt install libwebkit2gtk-4.1-dev build-essential curl wget file \
        libxdo-dev libssl-dev libayatana-appindicator3-dev librsvg2-dev
    
    # Arch
    sudo pacman -S webkit2gtk-4.1 base-devel curl wget file openssl \
        appmenu-gtk-module libappindicator-gtk3 librsvg2-dev
    
  • macOS / Windows: no extra system dependencies beyond Rust and the Tauri CLI.

Build and Run

# Development (hot-reload frontend, debug backend)
cargo tauri dev

# Production build (macOS DMG, Windows installer, Linux AppImage)
cargo tauri build

# Run all workspace tests
cargo test --workspace

Workspace Architecture

The project is a Cargo workspace with four library crates and one application crate:

CratePathRole
bb-interfacecrates/bb-interface/Shared types for the plugin system: FeedItem, FetchResult, ConfigSchema, ConfigField, BusserCapabilities. Defines the contract between plugins and the host.
bb-corecrates/bb-core/Orchestrator (feed refresh scheduling, lifecycle), Rhai plugin runtime (engine setup, script loading, host function registration), config encryption, URL tracker-stripping.
bb-feedcrates/bb-feed/Feed aggregation and ordering. Merges items from all active sources and applies sort modes (newest, scored, unread-first, starred-first).
bb-dbcrates/bb-db/SQLite persistence via rusqlite. Repositories for feeds, items, tags, and busser key-value state. FTS5 full-text search.
src-taurisrc-tauri/Tauri 2 desktop shell. Tauri commands (thin wrappers over the library crates), app state, background auto-fetch, frontend (vanilla HTML/CSS/JS).

Dependency flow: bb-interface is leaf (no internal deps) -> bb-core and bb-feed depend on bb-interface -> bb-db depends on bb-interface -> src-tauri depends on all four.

Theme loading comes from makeover, published to crates.io. Shared libraries from ../../MNW/shared/: tagtree (tag validation), synckit-client (cloud sync SDK).

Features

  • Unified timeline: RSS, Atom, JSON Feed, Hacker News, arXiv, and custom sources merged into one feed
  • Plugin system: Rhai scripting for extensible feed fetching (write a plugin for any source)
  • Reader view: clean article rendering with HTML sanitization via DocEngine
  • Search: FTS5 full-text search across all items with sanitized indexing
  • Organization: tags, starred items, read/unread tracking, query feeds (saved dynamic filters)
  • Auto-fetch scheduling: configurable per-plugin fetch intervals, circuit breaker after consecutive failures
  • Feed health tracking: visual status indicators (green/yellow/red) per source
  • Cloud sync: SyncKit integration with E2E encryption (feeds, tags, read state, preferences)
  • OTA updates: background update checker with consent dialog (Tauri updater v2)
  • 17 bundled themes: dark, light, and high-contrast variants in TOML format, system auto-detection
  • Platforms: macOS, Windows, Linux (native via Tauri 2)

Plugin Authoring

Plugins (“bussers”) are .rhai script files. Drop one into the plugins directory and it loads on next launch.

  • Dev: plugins/ at the project root
  • Prod: <app_config_dir>/plugins/ (e.g. ~/Library/Application Support/com.balancedbreakfast.app/plugins/ on macOS)

Every plugin defines four functions (id, name, config_schema, fetch) plus an optional capabilities(). Full authoring guide with field types, return shapes, host functions, and examples: docs/plugin_authoring.md.

Bundled Plugins

Eleven plugins ship with the app:

PluginSource
rss.rhaiRSS, Atom, and JSON Feed
hackernews.rhaiHacker News stories
arxiv.rhaiarXiv papers
reader.rhaiWeb page reader view
github_trending.rhaiGitHub trending repositories
devto.rhaiDev.to articles
lobsters.rhaiLobsters community
xkcd.rhaiXKCD comics
nasa_apod.rhaiNASA Astronomy Picture of the Day
earthquakes.rhaiUSGS earthquake data
nws_alerts.rhaiNational Weather Service alerts

Key Paths

WhatWhere
Plugin contract typescrates/bb-interface/src/
Plugin runtime + orchestratorcrates/bb-core/src/
Feed aggregationcrates/bb-feed/src/
Database layercrates/bb-db/src/
Tauri commandssrc-tauri/src/commands/
Frontend JSsrc-tauri/frontend/js/
Stylessrc-tauri/frontend/css/ (styles, shell, components, features, mobile, responsive)
Bundled pluginsplugins/
Plugin authoring guidedocs/plugin_authoring.md
Architecturedocs/architecture.md

Verifying a release

Every Linux release artifact (.AppImage, .deb) is published with a detached minisign signature beside it, named <artifact>.minisig. Updates that arrive through the in-app updater are checked automatically against a separate key; this covers the manual download path, which nothing checks for you.

Download both files, then:

minisign -Vm balanced-breakfast_<version>_<arch>.AppImage -p makecreative.pub

The public key is dist/makecreative.pub in this repository:

untrusted comment: Make Creative, LLC release key (minisign)
RWSMMbsBuZY5GfFRHPd19bZAVcyFAI4zsUlPjC5RaS/5tL7zT45SpjD9

You can also pass it inline instead of saving the file:

minisign -Vm balanced-breakfast_<version>_<arch>.AppImage -P 'RWSMMbsBuZY5GfFRHPd19bZAVcyFAI4zsUlPjC5RaS/5tL7zT45SpjD9'

Expect Signature and comment signature verified. Any other result means the file is not what we published. Do not run it.

Contributing

This project is licensed under PolyForm Noncommercial 1.0.0. Make Creative, LLC owns the codebase and needs to hold clear title to all of it, so contributions work a little differently here than on a permissively licensed project.

Found a bug, or something small and obviously wrong? Open a bug report rather than sending a patch. A clear report of what you did, what happened, and what you expected is worth more to us than a diff, and it saves you the paperwork below.

Want to build something substantial? Write to info@makenot.work first. We are open to paying for contributions that matter, and we would rather agree on scope and terms before you spend your evenings on it than after.

Sending code directly? Any code you submit is covered by the Contributor License Agreement in CLA.md, which assigns copyright in the contribution to Make Creative, LLC. Read it before you send anything. Add these lines to your commit message to record that you accept it:

Make-Creative-CLA: 1.0.0
Signed-off-by: Your Name <your@email>

We may decline a contribution for any reason, including that it is not something we want to maintain.

License

PolyForm Noncommercial 1.0.0