App settings
architect::settings — a typed Store<T> of facet JSON in the app's config dir (atomic, skip-if-equal, optional 0600), and FileKv.
architect::settings (the settings feature) keeps an app’s settings on
the device: one typed value per [Store<T>], stored as facet JSON.
use architect::facet::Facet;
use architect::settings::Store;
#[derive(Facet, Default, PartialEq)]
struct Prefs { theme: String, zoom: u32 }
let prefs: Store<Prefs> = Store::open("my-app", "prefs")?;
let mut p = prefs.load()?; // Prefs::default() when nothing is stored
p.zoom = 120;
prefs.save(&p)?; // Ok(false) when the stored body is already this
let token: Store<Token> = Store::open("my-app", "token")?.private(); // 0600
Where it lives#
The key is "{name}.json" on every target.
| target | location |
|---|---|
| native | <app dir>/<name>.json |
| wasm | localStorage["<app>/<name>.json"] |
The app dir is settings::app_dir(app): $<APP>_CONFIG_DIR when set
(my-app → MY_APP_CONFIG_DIR; use it for tests, CI and portable
installs), otherwise the platform config dir plus the app name
(~/Library/Application Support/my-app, $XDG_CONFIG_HOME/my-app,
%APPDATA%\my-app). Store::in_dir takes an explicit directory.
Write semantics#
- Atomic. The body goes to a temp file in the same directory, is
fsynced, renamed over the target, and the directory is synced. A crash leaves the old file or the new one, never a torn one. Stale temp files from a dead writer (.<name>.tmp-<pid>-<n>) are never read. - Skip if equal. When the file already holds the exact body, nothing is
written: no rename, no mtime change, no file-watcher event.
savereturns whether it wrote. - Private.
.private()creates the file0600(unix) and tightens an existing one on the next save. - Bad bodies are errors. A file that doesn’t decode is
SettingsError::Decode. It is never silently reset to the default.
FileKv#
FileKv is the directory-of-files key/value store under Store (native
only): key k is the file <dir>/<k>, any byte outside
[A-Za-z0-9._-] %XX-escaped. It has the same atomic, skip-if-equal
writes. With atom-persist also on, it implements architect-atom’s Kv,
so KvRows::new(FileKv::new(dir), "app/") is a durable native
LocalRows. It holds the same keys LocalStorageRows writes in the
browser, without a database (see optimistic).
Linked from
- SettingsDeclare settings once as a typed struct; architect stores each in its scope (this device, the person's, the project's) under an org's defaults and locks, and draws the settings page with search to the row.
- SettingsSettings declared once (a struct, or data an extension registers), held by scope over an org's defaults and locks, stored on the device, the project or the person's synced document, and drawn as one settings page.
- The workspace: docking, tabs and screensetsOne layout system for every app: tab groups in splits, docks on each side, stacked tabs, pop-out windows, per-tab history, and screensets — as flexible as Obsidian, REAPER and Premiere, so no app builds docking again.
- Feature flagsEvery architect cargo feature, what it implies, and which profile to reach for.
- Settings: declared once, a page for freeAn app declares its settings as typed structs; architect stores them (per device or synced to the person), and builds the Settings page — T3 Code's design — with search, reset and restore.