Ported from margin's pipeline, with the platform list this app actually
claims. Release is manual: it bumps tauri.conf.json, package.json and
Cargo.toml together, tags, and then builds the tag rather than whatever main
has drifted to by the time the runners pick it up.
Nothing publishes until every platform lands. The last job downloads
latest.json and refuses to take the release out of draft unless
darwin-aarch64, darwin-x86_64 and linux-x86_64 are all present, because a
half-populated manifest is worse than no release at all: the updater would
offer an update to the platforms that made it and error on the ones that did
not.
Linux builds on Ubuntu 22.04 rather than latest. The bundle will not run on
anything older than the glibc it was linked against, and 22.04 is the
baseline docs/setup.md commits to. Windows is not built, matching the bundle
targets and the README; adding it is a matrix entry, msi and nsis in the
targets, and windows-x86_64 in the publish gate.
The updater had a plugin, a capability and a menu item but no keypair and no
endpoint, so releases would have produced artifacts nothing could verify.
The public half is now in tauri.release.conf.json and the private half is a
repository secret, alongside the Google OAuth client that build.rs embeds.
Without that secret the build falls back to the example credentials and warns
rather than failing, which yields an app that runs and then says Google
Calendar is not set up.
CI enforces the gate setup.md already names, the two test suites, and nothing
more. cargo fmt --check and cargo clippy -D warnings both fail on the tree as
it stands, and adopting either is a cleanup pass to decide on rather than
something to bolt onto a new pipeline.
justfile is the local equivalent of all this. `just install` builds for the
machine it is run on and installs it, and is the same command whether or not
the app is already there, so it doubles as the update. On macOS it asks a
running copy to quit first, because replacing a bundle under a live process
leaves it half old and half new.
Tauri 2, React 19 and zustand on the front, Rust behind. Rust owns auth,
all HTTP to Google, the SQLite store, the sync loop, recurrence expansion
and timezone maths. TypeScript owns rendering and never talks to Google,
which keeps the content security policy locked to ipc:.
Week, day and agenda views, and no month view: it would be a second layout
engine, and the fit and fold logic that makes a day fit the window without
scrolling is the whole point of the app.
Runs on macOS, Linux, Android and iOS. Desktop catches Google's OAuth
redirect on a loopback port. A phone cannot, and Google rejects loopback
for mobile client types anyway, so it redirects to a custom URI scheme and
needs its own public OAuth clients, which docs/mobile.md covers. Refresh
tokens are sealed with XChaCha20-Poly1305 in the app data directory on
every platform, with no OS credential store in the picture.
On a phone the chrome becomes a top bar and a bottom tab bar, overlays
become sheets, hover affordances become taps, and dragging out an event
waits for a long press. Navigation moves one day at a time everywhere,
a swipe included.