Runtimes
The runtime in a manifest tells Budvo how to run an add-on. There are two today: theme@1 for colors and app@1 for small web apps. connector@1 is reserved for connectors.
theme@1
A theme is design tokens: colors for light mode, dark mode or both. The manifest's entry points at a JSON file with a light and/or dark object. Set only the tokens you want to change; everything else keeps Budvo's value.
{ "light": { "accent": "oklch(0.55 0.15 265)", "accent-soft": "oklch(0.55 0.15 265 / 0.1)", "accent-fg": "#ffffff" }, "dark": { "bg": "#070a14", "surface": "#0d1220", "accent": "oklch(0.75 0.13 265)", "accent-fg": "#050814" }}Tokens
| Token | Used for | Light default | Dark default |
|---|---|---|---|
bg | Page background | #f7f7f5 | #0a0b0d |
surface | Cards, panels and the sidebar | #ffffff | #111316 |
surface-2 | Inputs, hovered rows and areas inside cards | #f1f1ee | #16191d |
surface-3 | Stronger fills: selected items, pressed states, tracks | #e9e9e5 | #1d2126 |
line | Hairline borders and dividers | rgb(15 17 20 / 0.08) | rgb(255 255 255 / 0.07) |
line-strong | Borders that need to be seen, like inputs | rgb(15 17 20 / 0.14) | rgb(255 255 255 / 0.13) |
fg | Main text and numbers | #0e0f11 | #eceef0 |
fg-2 | Secondary text | #3b3f45 | #c3c7cd |
muted | Labels and captions | #6b7079 | #8a9099 |
faint | Placeholders, disabled text and hints | #9a9fa7 | #5c626b |
accent | Buttons, links, focus rings and highlights | oklch(0.6 0.105 184) | oklch(0.8 0.11 182) |
accent-soft | Tinted backgrounds behind accent content (translucent) | oklch(0.6 0.105 184 / 0.1) | oklch(0.8 0.11 182 / 0.12) |
accent-fg | Text and icons on the accent color | #ffffff | #06201d |
positive | Money in, on track, paid | oklch(0.58 0.13 155) | oklch(0.78 0.14 155) |
negative | Overdue, over budget, debt | oklch(0.58 0.17 25) | oklch(0.72 0.16 25) |
warning | Due soon, needs a look | oklch(0.72 0.14 75) | oklch(0.83 0.13 80) |
glow | Soft light behind highlights (translucent) | oklch(0.8 0.09 184 / 0.35) | oklch(0.55 0.1 184 / 0.28) |
Value rules
- Only the tokens above, and only colors:
#rgb,#rrggbb,#rrggbbaa,rgb(...)oroklch(...). - No
url(),var(), color names,hsl()or anything else. A theme can't load files or reach other variables. accent-soft,lineandglowlook best translucent:oklch(0.55 0.15 265 / 0.1)orrgb(15 17 20 / 0.08).- Debt mode's red theme still wins while debt mode is on.
- No permissions, pledges, network or pages: a theme is colors and nothing else.
Try it
Pick one of the first-party themes and a mode, or try your own accent. The JSON underneath is the theme file for what you see.
Safe to spend until Friday
$423.50
After bills, savings and your debt plan.
Budvo's own colors need no theme file. Pick a theme or try an accent to see one.
The themes guide walks through making your own, with tips for contrast in dark mode.
app@1
An app@1 add-on is a small web app: an HTML page with its CSS, JavaScript and images. Budvo shows it inside the dashboard in a sandboxed iframe, on its own page in the Add-ons menu when the manifest has ui.nav. The iOS app shows it in a web view with the same rules.
The sandbox
The frame has sandbox="allow-scripts" and no allow-same-origin, so the add-on runs with an opaque origin:
- It can't read Budvo's cookies or storage, call Budvo's API or reach into the page around it.
- It can't open new windows or tabs, show
alert,confirmorprompt, submit forms or navigate the page. localStorage,sessionStorage, IndexedDB and cookies aren't available. Usepc.storageinstead.
Content security policy
The add-on's files are served with a policy that allows only its own files, inline styles and scripts, data: and blob: images, and no network:
default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; connect-src 'none'In practice:
| Works | Doesn't |
|---|---|
| Scripts, styles, images, fonts and sounds from your own folder | Anything from another site: CDNs, web fonts, analytics |
Inline <script> and <style>, style="..." attributes | fetch, XMLHttpRequest, WebSocket and EventSource, even to your own files |
<canvas>, CSS animation, data: and blob: images | window.open and links that open new tabs |
| Talking to Budvo through the bridge | Reading Budvo's cookies or calling its API |
The bridge
Everything else goes through the bridge: messages posted between your page and Budvo with window.parent.postMessage. The iOS app provides the same window.parent.postMessage, so one add-on works in both. Use the SDK rather than raw messages:
const pc = await Budvo.connect();pc.syncTheme();Size and files
- Keep packages small: 5 MB at most, counting every file. Pixel art, plain HTML, CSS and JavaScript work best.
- No external scripts or fonts. Copy what you need into the folder, including
budvo-sdk.js. - Dotfiles,
node_modulesand iCloud'sname 2.extduplicates are left out of packages.
Sizing
In the dashboard the page fills its frame. On iOS, and when an add-on is shown inline as a card, call pc.ui.resize(height) or let pc.ui.autoResize() keep the frame as tall as your content.
Look like Budvo
pc.syncTheme() sets Budvo's tokens as CSS variables with the same names as the table above, and keeps them current when the owner switches mode or theme:
body { background: var(--bg); color: var(--fg); }.card { background: var(--surface); border: 1px solid var(--line); }.button { background: var(--accent); color: var(--accent-fg); }.muted { color: var(--muted); }It also sets color-scheme and a dark class on the root element in dark mode.
connector@1
Reserved for connectors: WebAssembly modules the server runs to sync accounts, balances and transactions with the owner's own provider credentials. They're listed in the catalog, and servers without the runtime show them as needing a newer server.