render an html report
screenpipe's in-app viewer can render a standalone .html file as a live page (charts, dashboards, styled reports) — but only when you opt in and keep the file self-contained. Otherwise it shows as raw source.
the two rules
-
Opt in. The first line of the file must be the marker:
<!-- screenpipe:render=human -->(or
<meta name="screenpipe:render" content="human">inside<head>). Without it the file shows as source, not a rendered page. -
Self-contained — no network. It renders in a locked-down sandbox with zero network access. So:
- inline all CSS in a
<style>tag and all JS in a<script>tag; - embed any images as
data:URIs; - no external
<script src>/<link rel=stylesheet>/ CDN, nofetch, no forms that POST.
Anything that touches the network is silently blocked — a CDN-loaded chart library renders blank. Draw charts with inline SVG or plain HTML/CSS bars instead (see the template).
- inline all CSS in a
how the user sees it
Write the file (e.g. ./output/report.html), then link it with an absolute path from your note or notification — e.g. [open report](/Users/me/.../output/report.html). The user clicks it; the viewer offers "preview rendered"; it renders inside the sandbox. Only standalone .html / .htm files render — HTML pasted inside a markdown note does not.
The viewer matches the host light/dark theme; if you care about dark mode, style with @media (prefers-color-scheme: dark).
template (copy, then fill in with real data)
html<!-- screenpipe:render=human --> <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> body { margin: 0; padding: 24px; font-family: system-ui, -apple-system, sans-serif; } h1 { font-size: 20px; margin: 0 0 4px; } .sub { color: #666; font-size: 13px; margin: 0 0 20px; } .cards { display: flex; gap: 12px; margin-bottom: 24px; flex-wrap: wrap; } .card { flex: 1; min-width: 120px; background: #f4f4f5; border-radius: 10px; padding: 12px 14px; } .card .label { font-size: 12px; color: #666; } .card .value { font-size: 24px; font-weight: 600; } .bar { fill: #3b82f6; } .axis { fill: #999; font-size: 11px; } </style> </head> <body> <h1>daily focus report</h1> <p class="sub">where your time went today</p> <div class="cards"> <div class="card"><div class="label">tracked</div><div class="value">6.4h</div></div> <div class="card"><div class="label">top app</div><div class="value">vs code</div></div> <div class="card"><div class="label">meetings</div><div class="value">3</div></div> </div> <!-- inline SVG chart — no chart library (CDNs are blocked in the sandbox) --> <svg viewBox="0 0 400 180" width="100%" role="img" aria-label="hours per app"> <rect class="bar" x="20" y="40" width="50" height="120"></rect> <rect class="bar" x="90" y="80" width="50" height="80"></rect> <rect class="bar" x="160" y="110" width="50" height="50"></rect> <rect class="bar" x="230" y="130" width="50" height="30"></rect> <text class="axis" x="45" y="174" text-anchor="middle">code</text> <text class="axis" x="115" y="174" text-anchor="middle">chrome</text> <text class="axis" x="185" y="174" text-anchor="middle">slack</text> <text class="axis" x="255" y="174" text-anchor="middle">mail</text> </svg> </body> </html>
checklist before you save
- first line is
<!-- screenpipe:render=human --> - all CSS/JS inline; all images are
data:URIs - no CDN /
<script src>/fetch/ forms - linked from the note or notification with an absolute path

