The frame around every surface: the sidebar you navigate with, the 48px header that never changes height, the bar that replaces both on a phone. Plus the mechanism Flux built to tell you how finished the page you are standing on actually is. That mechanism is the interesting one. Most products decide what to claim in marketing; Flux decided it in a TypeScript file, and then rendered the claim above the feature.
One component, one job: read src/lib/route-truth.ts for the current pathname and, if that route is not ready to be believed, say so above it. The status decides the colour, the icon and the one-word label. The sentence next to it is the route's own honesty string, verbatim. This is a good idea implemented cheaply, and both halves of that are worth showing.
Two guards, not one. The component returns null if the route sets showBadge: false, and returns null again if the matched variant has an empty label. The live variant is the second case: it is declared with an empty string precisely so it disappears, which is why the sixth box above is empty rather than blank-looking. An unmapped path falls back to status: 'shallow' with the text "This route has not been evaluated." That fallback text is what the broken and hidden boxes above are showing, because no route supplies a sentence for those statuses: broken, hidden and the fix-before-launch disposition are declared in the type and used by exactly zero routes today. reference is a third case worth naming: four routes declare it, but all four set showBadge: false, so the slate variant never reaches a screen either. Of six variants, two render.
The honesty text has drifted, and it currently undersells the product. Route-truth calls Goals, Systems, Frictions, Choices, Insights, Environments and the Audit Log seeded, mock or static sample data. All seven read and write real rows: Goals and Frictions through src/lib/domains/goals.ts and frictions.ts, Systems and Choices through useDomainCollection, Environments across two tables, Insights via day_rollups, and the Audit Log directly from sync_log and agent_actions. The app's own changelog agrees: v0.5.0 records "no more demo data" for that group and v0.6.0 records "Audit Log is real: actual sync and agent activity, no more sample rows." The banner was written before the wiring landed and was never updated, so a user on /goals is told their real, saved goals are samples. Reproduced here as shipped. A mechanism that tells the truth is only as good as the day someone last checked it, and that is worth saying plainly rather than quietly correcting.
Everything that is on screen no matter which surface you are looking at. Between them these five decide what you can reach, how much room the content gets, and how many hours you have left today. On a phone the sidebar and header step aside for a bar of five shortcuts you chose yourself.
The user block in the footer is a mockup. It renders the string "User", the string "user@flux.com" and a placehold.co avatar, and it never calls useUser(), so it shows the same person to everyone including a signed-in Supabase account whose real email the header two rows away is perfectly capable of signing out. The rest of the card is real: 11 core items, 8 preview items at opacity-70, 5 App Mgmt items, an Admin link gated on useIsAdmin(), and a Complete Setup item that appears only while onboardingCompleted is false.
The 11 core items render flat and always; Preview is a closed Radix accordion holding 8 more. The footer stacks the user block, a second accordion of 5 documentation routes, then Help and Settings, then the sidebar's own display settings. Active state is pathname.startsWith(item.href), with a special case so that / only matches itself: without it, Now would be permanently highlighted. The App Mgmt items use exact matching instead. Two deliberate deviations from stock shadcn: collapsed width is 3.25rem (52px) rather than 3rem, and menu icons are size-5 (20px) rather than size-4, inside a 32px row with 8px of padding, which is why a collapsed item is tighter than it looks. Collapsible mode comes from sidebarDisplayMode: only "hide on close" maps to offcanvas, every other mode maps to icon.
The countdown is minutes, not hours. DailyCountdown counts down to 23:59:59.999 and prints total minutes padded to four digits, then a literal ".", then seconds padded to two: at two in the afternoon it reads 0599.06 and the four-digit pad exists because the number peaks at 1439 just after midnight. It renders on every route except /, on the theory that the Now page is already about time. Three conditionals to remember: the description row only exists when description is passed; the "Local mode only" badge needs user.source === "local-dev" and a viewport at md or wider, since it ships hidden md:inline-flex; and the sign-out button needs user.source === "supabase". On a phone in local mode, the badge that tells you nothing is being saved is the thing that hides.
Three routes are unreachable from a phone. The drawer keeps its own allMenuItems array of 17 entries, and that array has fallen behind the sidebar's: Tabatha, People and Context Inbox are in coreItems but not here, so they appear neither in the five shortcuts nor in the expanded grid. There is no "more" link past the grid, so on a phone those three pages have no route to them. MobileDrawerSettings duplicates the same stale array, which is why you cannot pin them either. The rest is straightforward: !isMobile returns null, the expanded grid is allMenuItems.filter(item => !settings.mobileDrawer.includes(item.href)), and active is an exact pathname === item.href match here rather than the sidebar's startsWith.
The block is hidden whenever the sidebar is icon-collapsed, via group-data-[collapsible=icon]:hidden, which is sensible: the control that would give you the labels back is the one the collapse takes away. All four modes are honoured, in two places. AppSidebar maps only "hide on close" to collapsible="offcanvas" and everything else to "icon"; ui/sidebar.tsx then reads the mode again to add mouse-enter and mouse-leave handlers for "open on hover" and to zero the width for "hide on close". It is defined inside sidebar.tsx rather than exported, so it has no file of its own.
No JavaScript runs to swap the icon. Both Sun and Moon are always in the DOM, stacked, each carrying transition-all plus a dark: pair of rotate and scale utilities: light rotates the moon 90 degrees to scale-0, dark does the same to the sun. The cross-fade is a class on <html> and nothing else. Sizing is the odd note: h-[1.2rem] w-[1.2rem] is 19.2px, an arbitrary value where the rest of Flux uses size-4 or size-5. Both variants above are reproduced with the same CSS technique the product uses.
Two dialogs that open by themselves, at opposite ends of a user's life with the app: one the first time they arrive, one every time the app has moved on without them. Both are gated on state rather than on a button, and both return null rather than render an empty shell.
The chrome is real and the steps do nothing. All four bodies render the same literal stub, reproduced exactly above: <p>Step {currentStep + 1} Content</p> in a bg-muted/50 box. Nothing is connected, no tool is linked, no priority is defined, and the only step that has an effect is the last one: Finish writes onboardingCompleted: true and raises a toast reading "Onboarding Complete!". That flag is doing real work elsewhere. It removes the Complete Setup item from the sidebar and adds the Re-run Onboarding block to the Profile card, so a user can finish onboarding, change nothing about their setup, and have the app agree they are set up. The footer forks twice: at step 0 the Back button is replaced by an empty <div /> to hold the layout, and at the last step Next becomes Finish.
Write things down the way you already do, and Flux picks out the people, places and tools you mentioned, so your calendar starts explaining itself.
The dialog reads flux.lastSeenVersion from localStorage and compares it against APP_VERSION in src/lib/changelog.ts, which is the app's real version number (package.json still says 0.1.0 and is stale). Every version in the gap is listed, so a user returning after three releases reads all three. Every localStorage access is wrapped in try/catch with the comment "never block the app for the dialog", and if entriesSince returns nothing the component marks the version seen and renders null without ever opening. Note that on a first run it deliberately shows only the newest entry rather than all twelve.
Renders null when an entry has no technical array, so an entry can carry one layer or two. The panel is a dashed-border block in monospace, which is the app's real font-code (plain monospace, not a nicer one). What goes in it is a judgement call worth stating: this ships to every user who clicks, so it holds implementation detail rather than secrets. Table names, routes and thresholds are fine; hostnames, credentials and vendor topology are not. The v0.2.0 note used to print the production hostname to every reader and no longer does.
Two files under src/components/ that render no markup at all. They are listed rather than dropped for the same reason the dead code elsewhere on this site is listed: a showcase that quietly omits what it cannot draw is a showcase whose count you cannot check.
The entire body is return <NextThemesProvider {...props}>{children}</NextThemesProvider>. It adds no behaviour, no defaults and no types of its own; it exists so that swapping the theming library later is one file rather than every import. Carded so the component count stays reconcilable.
An effect registers /sw.js once the document has finished loading, feature-detected on 'serviceWorker' in navigator and swallowing any failure with the comment "offline shell is a progressive enhancement". If the browser refuses, you get no offline shell and no error, which is the right call: the alternative is a toast about a feature the user never asked for. This is what the v0.6.0 note "Install Flux on your phone: Add to Home Screen now works (PWA)" is made of.