A dashboard that adapts: grid, widgets, and visibility
Photo: Negative Space · StockSnap (CC0 1.0), via Openverse
A dashboard is a strange thing. At first glance it's supposed to show exactly what matters right now — except "what matters" is different for every person. The trainer in the studio wants to see today's bookings, the practice cares about open appointments, and whoever runs an entire organization looks at revenue and member counts. A single, fixed layout can't satisfy these demands at the same time without being a little wrong for everyone.
This week is about how we built the Xircuit dashboard so that it adapts to the person instead of the other way around — and the surprisingly tricky decisions hiding behind a seemingly simple grid of tiles.
Why a rigid layout isn't enough
The simplest path would have been to design one fixed arrangement, make it look nice, and be done with it. That's exactly what we did at the start. It worked as long as you were the only user yourself. But as soon as the first real organizations joined, it became clear: what has to sit at the top for a gym is a side note for a physical therapy practice — and vice versa.
So we didn't want a dashboard that we prescribe, but one that people assemble themselves. The guiding idea was a grid in which every tile is a self-contained widget that can be moved and resized freely. Not as a gimmick, but because the order and size of a piece of information already carries meaning on its own: what sits large and at the top gets read first.
The grid: Gridstack and 16 widgets
For the grid we rely on Gridstack, a proven library for drag-and-drop layouts. It handles what's easy to underestimate — clean snapping of tiles, moving neighboring elements out of the way, coordinating with different screen widths. We wire it into our Blazor Hybrid UI through a thin JavaScript interop layer, so the actual logic and state stay in .NET and only the gesture handling happens in the browser.
This grid currently carries 16 widgets. Each one is self-contained: it knows what data it needs, how to display it, and what size makes sense for it. You grab a tile, drag it to a new spot, grab its corner and make it wider — and the grid rearranges everything else around it. What looks at first like pure cosmetics is actually the core of the personalization: the arrangement is the configuration.
Three scopes: device, member, organization
As soon as you start saving arrangements, the question immediately arises: for whom, exactly? A layout I set up on the big monitor in the office is useless on the tablet at the front desk. And what applies to me personally doesn't have to apply to the whole organization.
That's why the arrangement is saved per device. Anyone who builds a wide, dense layout on the desktop still finds a suitable, more compact variant waiting on the tablet. Beyond that, the system knows three scopes that layer on top of each other:
- Member — the personal view that only affects me.
- Organization — a shared layout that serves as the starting point for everyone in an organization.
- Platform — an overarching default that applies before anyone has customized anything.
This layering ensures nobody sits in front of a blank screen. There's always a sensible default, and each level is free to refine it without destroying the one beneath it.
Photo: Rawpixel (CC0 1.0), via Openverse
Configuration per widget: the gear icon and its JSON
The position and size of a tile are one thing — what it shows in terms of content is another. A widget displaying a metric might need to show a different time range or a different unit, without us having to build a brand-new widget every time.
That's why every widget carries a small gear icon. Clicking it opens a dialog whose fields aren't hardwired but come from a catalog: every widget declares there which settings it even knows about. The dialog builds itself from that declaration, and whatever the user configures lands as JSON directly on the widget. That keeps the configuration extensible — when a new widget arrives with new options, I don't have to change anything in the dialog itself; it simply reads the declaration and shows the matching fields.
This catalog-based approach has proven to be one of the better decisions. It cleanly separates what a widget can do from the question of how you configure it, and keeps the UI generic instead of hand-written for every widget.
Trend widgets and the time range
One concrete example where the configuration has proven its worth is the trend widgets. They show the trend of a metric over time — and naturally the decisive question is: over what time? The last seven days tell a different story than the current quarter.
So we gave the trend widgets a configurable time range. Through the same gear-icon dialog, you choose the period, and the widget redraws its curve accordingly. What's interesting is the path there: the feature initially ran behind a flag, so we could try it out in real operation without already forcing it on everyone. Only once it was clear that it was stable and felt right did we remove the flag and lock in the time range for good. This step-by-step approach — first behind a flag, then permanent — is more the rule than the exception for us, especially for things that change what users look at every day.
The view across all organizations
Anyone who manages several organizations needs more than the sum of individual dashboards. For that there's a dedicated all-organizations dashboard that doesn't just list the metrics separately side by side but aggregates them across all organizations. Instead of jumping back and forth between views, you see the full picture in one sweep.
Because inherently more sensitive, combined figures become visible here, this dashboard carries its own access protection. Not everyone who's allowed to see a single organization is also allowed to see the aggregated overview — we draw this boundary deliberately and separately from the normal roles. Data minimization and clear permissions aren't optional extras on a platform that works with health and member data — they're mandatory.
What's next?
Next week: how we track member activity in a data-minimal, GDPR-compliant way — without monitoring anyone.
Comments
No comments yet. Be the first to share your thoughts!
Leave a Comment