posthog/building-canvases
> Create or edit a PostHog canvas — a sandboxed browser application (data board, document, form, small tool, graphics experiment) stored in PostHog and rendered by the desktop/web app. Use when a task asks to build, generate, update, or fix a canvas, or when a canvas id is given as the publish target. Covers resolving or creating the target canvas, choosing an implementation approach (React + Quill vs plain HTML/browser APIs), the read → edit → validate → publish → build loop, and which companion canvas skills to load for the details.
npx skills add https://github.com/PostHog/posthog --skill building-canvases
A canvas is a client-side browser application that runs in a sandboxed iframe inside PostHog.
Its source lives in PostHog — not in a repository — and you read and write it through the
canvas-* tools. Never write a canvas to a local file; publishing through the tool is what
saves it.
with canvas-list (scope with channel; resolve a bare channel name with channel-list first).
If one is clearly what the request refers to — an earlier iteration of the same board or tool —
build on it instead of creating a near-duplicate, and say so in your reply so the user knows
where the result landed.
canvas-create in the right channel, namedwith a short descriptive title drawn from the request — never "Untitled canvas".
that should look native to PostHog. Load the building-react-quill-canvases skill.
graphics, <canvas>/WebGL work where React adds no structure. Load the building-html-canvases skill.
canvas element, or a mostly static page can mount one interactive island.
This is a judgment call, not a persisted mode — ask the user only when the choice changes a
user-visible requirement you cannot infer.
canvas-source-retrieve.Remember current_version_id — your publish must be guarded on it.
querying-canvas-dataskill (saved insights loaded via the ph SDK — never fetch or your own PostHog client), and
declare every ph call in project.capabilities (insight short ids in
capabilities.posthog.insights, captured events in captureEvents, inlineQueries: true for
ad-hoc queries) — the host enforces these at runtime and validation rejects undeclared calls.
canvas-validate-create as often as needed and fix every error-severitydiagnostic.
canvas-publish-create, passing expected_current_version_id.Follow the validating-and-publishing-canvases skill for diagnostics and conflict recovery.
canvas-builds-retrieve(every few seconds, up to ~2 minutes) until your build is ready or failed. On failed,
read the build's error diagnostics, fix the project, and publish again — do not finish the
task with a failed build.
Publish once per requested change, when the canvas is ready — not after every micro-edit.
index.html as the entry shell returned by the source tool.src/canvas.tsx remains the conventional React entry component, but it may import additionalrelative TypeScript, TSX, JavaScript, JSON, SVG, CSS, and admitted asset files from the project.
./worker.ts?worker. A worker must not importanother local module.
assets map as base64 content with an admitted content type.PNG, JPEG, GIF, WebP, AVIF, WOFF/WOFF2, WebAssembly, and generic octet-stream assets are supported.
imports are project files, while bare imports remain limited to the platform-pinned set.
Take posthog/building-canvases from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.