
Description
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.
SKILL.md
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.
Resolve the target canvas
- If the task names a canvas id (canvas-initiated tasks do), that is the target. Do not create another.
- Otherwise — channel-composer tasks give the channel, not a canvas — list the channel's canvases
with
canvas-list(scope withchannel; resolve a bare channel name withchannel-listfirst). 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. - Only when nothing existing fits, create one with
canvas-createin the right channel, named with a short descriptive title drawn from the request — never "Untitled canvas".
Choose the least complex implementation that meets the request
- React + Quill — PostHog data products, dashboards, forms, application-like state, and anything
that should look native to PostHog. Load the
building-react-quill-canvasesskill. - Semantic HTML, CSS, and direct browser APIs — static documents, focused experiments, generative
graphics,
<canvas>/WebGL work where React adds no structure. Load thebuilding-html-canvasesskill. - Mix them when appropriate: React can own the application chrome while Three-style code owns a 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.
The iteration loop
- Read the current source and version pointer with
canvas-source-retrieve. Remembercurrent_version_id— your publish must be guarded on it. - Edit the project files. For any PostHog data the canvas shows, follow the
querying-canvas-dataskill (saved insights loaded via thephSDK — never fetch or your own PostHog client), and declare everyphcall inproject.capabilities(insight short ids incapabilities.posthog.insights, captured events incaptureEvents,inlineQueries: truefor ad-hoc queries) — the host enforces these at runtime and validation rejects undeclared calls. - Validate with
canvas-validate-createas often as needed and fix every error-severity diagnostic. - Publish the complete project with
canvas-publish-create, passingexpected_current_version_id. Follow thevalidating-and-publishing-canvasesskill for diagnostics and conflict recovery. - Wait for the build. A publish queues a server-side build; poll
canvas-builds-retrieve(every few seconds, up to ~2 minutes) until your build isreadyorfailed. Onfailed, 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.
Source-project shape
- Keep
index.htmlas the entry shell returned by the source tool. src/canvas.tsxremains the conventional React entry component, but it may import additional relative TypeScript, TSX, JavaScript, JSON, SVG, CSS, and admitted asset files from the project.- Self-contained module workers may be imported with
./worker.ts?worker. A worker must not import another local module. - Binary assets belong in the project's
assetsmap as base64 content with an admitted content type. PNG, JPEG, GIF, WebP, AVIF, WOFF/WOFF2, WebAssembly, and generic octet-stream assets are supported. - Keep the platform dependency map exactly as returned. Do not add npm packages; local relative imports are project files, while bare imports remain limited to the platform-pinned set.
More skills from the posthog repository
View all 74 skillsanalyzing-expensive-users
analyze expensive users in AI observability
Jul 28AnalyticsCost OptimizationObservabilityPostHogauditing-endpoints
audit PostHog project endpoints
Jun 8AnalyticsAuditPostHogauditing-warehouse-source-health
audit PostHog data warehouse source health
Jun 18AuditData WarehouseObservabilityPostHogauditing-warehouse-view-health
audit PostHog materialized view health
Jun 18AuditData WarehousePerformancePostHogauthoring-error-tracking-alerts
author PostHog error tracking alerts
Jun 18AlertingDebuggingObservabilityPostHogauthoring-log-alerts
author log alerts in PostHog
Jul 18AnalyticsMonitoringObservabilityOperations +1
More from PostHog
View publisherbuilding-html-canvases
author HTML and CSS PostHog canvases
posthog
Aug 6CSSDesignGraphicsHTML +1building-react-quill-canvases
build React and Quill canvases
posthog
Aug 6DesignFrontendReactUI Componentsbuilding-workflows
build and edit PostHog workflows
posthog
Aug 6AutomationMCPPostHogWorkflow Automationcheck-posthog-loading
inspect PostHog SDK loading across URLs
posthog
May 7AnalyticsDebuggingFrontendObservability +1consuming-endpoints-from-client-code
integrate PostHog endpoints into client applications
posthog
Jun 8API DevelopmentFrontendPostHogSDK