The bar above is every app's only header
It wears the current app's name, icon and accent, carries that app's navigation, and adds the switcher into the other apps plus the shared account menu. One tag:
<script src="https://bar.cashabarba.com/appbar.js" data-app="train" defer></script>
Navigation comes from apps.json, so it renders before the app's own
JavaScript does. data-app only matters when the hostname is not in that registry.
Driving it from the app
cbAppbar.configure({
title: household.name, // overrides the app name
nav: [{ label: 'Home', key: 'home' }], // key = in-page section, href = link
active: 'home',
actions: [{ label: 'Reset week', onClick: resetWeek }],
onNavigate: (key) => showSection(key), // also fires cb-appbar:navigate
});
cbAppbar.setStatus('Saved', 'ok'); // small pill beside the nav
cbAppbar.profile().then((p) => p.displayName); // shared profile, no extra request
A second row
Sub-navigation and banners stay with the app, hung below the bar:
.subnav { position: sticky; top: var(--cb-appbar-h, 0px); }
The account
One profile for every app, at /account — display name, avatar, units,
sex, birth year. It is stored as Supabase user_metadata, so it arrives with the
identity check each app already makes.