App state: data apps that remember

    Every data app on Rig now has a place to keep small things: a review flag, an annotation, a saved view. Whatever you ask for in your AI tools or the Rig chat, the app remembers.

    The problem it solves

    A data app is a dashboard or app your team vibe-codes on company data, hosted and governed by Rig. Until now, those apps had nowhere to put anything of their own. Marking a row as reviewed, saving an annotation, keeping a filter between visits: each of those meant registering a typed table through the VDM write-back rail, with columns and SQL types declared up front.

    That ceremony is right for a real table and pure overhead for a flag. So small state tended to go unsaved, and apps that should have remembered things reset on every visit. App state closes the gap with a schema-less store.

    How app state works

    Every data app gets its own key value store. A value is any piece of JSON, saved under a key the app picks. Values are versioned, so two people editing at once cannot silently overwrite each other, and every value records who last wrote it, and when.

    State comes in two scopes. Shared is the default: one value every viewer of the app sees, so when one person marks a row reviewed, it is reviewed for everyone. User state is private to each person, the right home for saved views and personal settings.

    The Inspector's new State tab lists every key an app has saved, in both scopes, with its version and author. You can filter across keys and values, edit any value as JSON, or delete it.

    The app itself
    Saves and reads its own state with RigDataApp.state, already injected into every dashboard
    Claude & Rig Chat
    Agents read and write the same keys over MCP, so a conversation and an app can share state
    Inspector, State tab
    View, edit and delete any key by hand, with versions and who wrote what
    App state
    Versioned JSON values under keys the app chooses, like classification:orders or saved-view:emea
    shared scope
    One value every viewer of the app sees, the collaborative default
    user scope
    Private to each person, for saved views and personal settings
    Diagram: three surfaces write to one per-app store. The data app itself uses the injected RigDataApp.state SDK, agents in Claude and Rig Chat use MCP, and the Inspector's State tab edits keys by hand. The store holds versioned JSON values in a shared scope every viewer sees and a user scope private to each person.

    You don't have to engineer it

    There is nothing to install and nothing to wire up. When you build or change a data app in Claude or Rig Chat, describe the behaviour you want: let me mark each order as reviewed, remember the filters I had open, keep a note on every account. The model picks the right storage on its own, because the rule for choosing is part of the context every Rig agent carries: app state when an app is remembering its own small things, a VDM write-back when the app should own a real, queryable table.

    The plumbing is equally hands-off. The client SDK is injected into every dashboard Rig renders, keys need no registering, and the first write creates the store. Say what the app should do, not which rail to use. You never have to name the feature to get it.

    App state or a VDM?

    Both are write-back rails, and neither needs a deploy. The difference is a declaration versus nothing. A VDM write-back gives the app a typed table your whole team can query, and charges for it up front: you name the columns and their SQL types when you register it. App state asks for nothing up front, and in exchange it is not a table: values come back by key, not by SQL.

    App stateVDM write-back
    SetupNone. The store exists the moment an app first writes to it.Declare the columns and their SQL types up front, in one registration call.
    ShapeJSON values under keys the app chooses.Typed rows in a real table.
    Reading it backBy key or key prefix, from the app, an agent, or the Inspector.Query it like any other table: SQL, dashboards, chat.
    Who can writeAny viewer for their own private state; shared state takes an editor.Editors and up, always.
    Best forFlags, annotations, saved views, app settings.Scorecards, roll-ups, enriched tables your team queries.

    The rule of thumb: if the app is saving its own state, use app state. If the app owns data other people will query, give it a VDM. And because the choice is made by the model when you describe the feature, the rule of thumb is mostly for reading along, not for deciding.

    For technical audiences and workspace editors

    For technical audiences and workspace editors

    Every dashboard Rig renders runs in an opaque-origin sandboxed iframe that never holds a session token or an API endpoint. SDK calls travel over a postMessage relay to the host page, which attaches auth and injects the app's id itself; an app id supplied by the iframe is discarded. That is what makes the namespace trustworthy: no app can reach into another app's state.

    Storage is one derived.app_state table, JSONB values keyed by app, scope, user and key, behind the same per-tenant boundary as the VDM rail. Reads are open to any viewer of the app; writing shared state takes the editor role, writing your own private state does not. Agents reach the same store over MCP

    Was this guide helpful?