A locked display, two separate homes, and the things we can’t do — by design.
Written for two readers at once: the analyst forwarding it, and the reviewer receiving it.
The shape of it
Your dashboard is displayed from a different domain than the app. The app (accounts, settings, billing) lives on larssoni.com. The dashboard itself is served from larssonipages.com — a domain that never carries a login cookie. Free public dashboards are served from a third, separate home (larssoni.co) so business dashboards never share a reputation with anonymous content.
The display is locked. A dashboard can render your numbers, but the display it runs in cannot make calls to other services, cannot submit forms, and cannot open windows. Scripts are limited to a short allowlist of common library CDNs (jsDelivr, cdnjs, unpkg) so pasted dashboards render — never arbitrary third-party code. That’s not a policy we enforce with reviews — it’s a browser-level rule set in HTTP headers on every single page we serve, and you can check it with curl -I.
Auto-updates read as little as possible. By default, setup reads your spreadsheet’s column names only — the structure, not the values. Your real numbers flow at update time, get checked against what the dashboard expects, and go live only if they look right. If they don’t, viewers see your last good version, clearly dated.
What goes where
| Data | Where it lives | How long |
|---|---|---|
| Your dashboard file | Encrypted storage on Cloudflare (EU jurisdiction options) | Every version kept until you delete it |
| Your spreadsheet values | Read live at update time and never stored — we keep only a one-way fingerprint to tell whether anything changed | Fingerprint 30 days; values not retained |
| A file you upload as a source | Stored so we can re-read it on refresh | Until you delete the dashboard or your account |
| Spreadsheet structure (column names) | Setup recipe | While auto-update is on |
| Viewer email (locked links) | Used once to check access and send a code, then kept only as a one-way hash so we can count distinct openers. Never shown to the dashboard owner — they see counts, never identities | Hash erased when the dashboard is deleted; 7-day access pass, revocable any time |
| Your sign-in | Email link or Google — no passwords stored, ever | Session only |
Sub-processors
Cloudflare (hosting, EU options) · Stripe (payments — card details never touch us) · Postmark (email) · Anthropic (setup only — your page’s markup once, never your data values). Google isn’t a sub-processor: when someone signs in with Google or connects a Sheet, Google discloses data to us at that person’s instruction, as an independent controller. Full list with locations and change notifications in the data processing terms.
The paperwork
A binding Article 28 data processing agreement — not a summary, and it self-executes with our terms, so there is nothing to chase. Coordinated disclosure policy + security.txt · 48-hour breach notification to you · sub-processor changes with 30 days’ notice and a right to object. Need it countersigned on your paper? Email support@larssoni.com.
How we prove it
The locked-display rules and the two-domain split aren’t promises on a page — they’re checked by an automated security battery on every release, and the display headers are verified against the live edge. If we can’t deliver a control, we don’t claim it here.