Skip to content
Data
Skill

/validating-and-publishing-canvases

Validate and publish a canvas source project safely: the source-project shape, declared capabilities, reading the current version pointer, iterating on validation diagnostics, guarded publishing with expected_current_version_id, staging a draft build and promoting it, waiting

From plugin
posthog-posthog
40k158 skills11 agents1 command3 MCP
Install
$ npx -y skills add posthog/posthog --skill validating-and-publishing-canvases --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/validating-and-publishing-canvases

Context preview

The summary Claude sees to decide when to auto-load this skill.

Validate and publish a canvas source project safely: the source-project shape, declared capabilities, reading the current version pointer, iterating on validation diagnostics, guarded publishing with expected_current_version_id, staging a draft build and promoting it, waiting

SKILL.md

validating-and-publishing-canvases.SKILL.md
name: validating-and-publishing-canvases
description: >
  Validate and publish a canvas source project safely: the source-project shape, declared
  capabilities, reading the current version pointer, iterating on validation diagnostics, guarded
  publishing with expected_current_version_id, staging a draft build and promoting it, waiting out
  the queued build, and recovering from a 409 version_conflict or a 429 capacity limit without
  overwriting concurrent work. Use whenever a canvas edit is ready to save, a draft build is wanted,
  a canvas publish or build returns diagnostics or a conflict, or a task needs to understand canvas
  version history.

Validating and publishing canvases

A canvas's source lives in PostHog, versioned per publish. Publishing is guarded: every edit is based on a specific version, and the server refuses to overwrite newer work. Every publish queues a server-side build, and the canvas renders the last successful build.

The source project

`canvas-source-retrieve` returns:

  • `project` — `schemaVersion` (1), `files` (path → content), `entryHtml` (`"index.html"`),

`dependencies` (exact platform-pinned versions), `canvasSdkVersion`, `capabilities`.

  • `current_version_id` — the version your edits are based on. Keep it; the publish needs it.

It is `null` for a canvas that has never been published — pass that `null` on the first publish.

Keep `index.html` and `dependencies` exactly as returned. You may add relative source files and admitted assets to the project. Use `?worker` for a self-contained module worker and represent binary assets as base64 entries in `assets`; new npm dependencies or dependency-version drift fail validation.

Declare capabilities

The host enforces `project.capabilities` at runtime, so an undeclared `ph` call builds fine and then dies in the rendered canvas. Declare:

  • `capabilities.posthog.insights` — every insight short id the canvas passes to `ph.loadInsight`.
  • `capabilities.posthog.captureEvents` — every event name it passes to `ph.capture`.
  • `capabilities.posthog.inlineQueries: true` — when it calls `ph.query` at all.
  • `capabilities.posthog.agentRequests: true` — when it calls `ph.agent.request`.
  • `capabilities.connectors` — one `{ "provider", "tools" }` entry per third-party provider the

canvas reads through `ph.connectors.call`, listing every tool it calls on that provider. A provider is a native id (`github`) or `mcp:<server host>` (`mcp:mcp.calendly.com`). Unknown providers, unregistered native tools, and private MCP hosts fail validation; every declared tool must have `is_read_only: true` in the catalog. An upstream hint alone does not grant access. A canvas with connectors cannot declare shared state.

  • `capabilities.network.origins` — each exact HTTPS origin used by `fetch`, `XMLHttpRequest`, or an

external stylesheet, image, font, media file, or frame. Remote scripts remain blocked. Do not include paths, credentials, queries, fragments, or wildcards. The host must be public: loopback and private IPs, single-label names like `intranet`, and the `.local`, `.localhost`, `.internal`, and `.home.arpa` suffixes are all rejected, so a local dev host such as `https://localhost:8010` fails validation with an `invalid_network_origin` error. Data sent to a declared origin leaves PostHog and appears in the capability review before promotion.

Before validation, inventory every literal external URL in every source file. Classify navigation links and `ph.openExternal()` URLs as navigation; they do not need a network origin. For every request or resource URL, declare its scheme + host + optional port only. Include every origin a request redirects to and every secondary origin a stylesheet references for fonts or images. Never infer that one CDN hostname covers another.

Validation rejects undeclared literal calls and resource URLs (`capability_missing_*` diagnostics) so you can fix them before publishing. Dynamic URLs and redirect destinations cannot be inferred, so the inventory is still required even when validation is clean.

Validate until clean

`canvas-validate-create` is side-effect free; call it as often as needed. Diagnostics carry `severity`, a stable `code`, a `message`, and (for file-specific problems) `path` and `line`:

  • `error` diagnostics block publishing — fix all of them. Common ones: `import_not_allowed`

(bare imports are limited to the dependencies returned in the source project), `forbidden_dynamic_import` / `forbidden_require` / `forbidden_inline_script`, `invalid_path`, `capability_missing_insight` / `capability_missing_capture_event` / `capability_missing_inline_queries` / `capability_missing_agent_requests` / `capability_missing_network_origin`, `dependency_not_admitted` / `dependency_version_mismatch`, `platform_token_redeclared` (a CSS variable named like a Quill token that the platform stylesheet sets on every element, so the value never applies; prefix your own variables), and path/size violations.

  • `warning` diagnostics don't block, but heed them: `network_fetch` / `network_xhr` mean the code

reaches for the network directly. Declare the exact HTTPS origin or use the `ph` bridge.

Publish guarded

Publishing goes live immediately and is the default way to save a change, for a canvas's first version and for every follow-up edit. Every version records who published it and which task did the work, so the history stays reviewable after the fact. Stage a draft instead only when the user asked for a draft, a preview, or a review step — see "Draft, then promote" below.

Two ways to publish, both guarded:

  • **Whole project** — `canvas-publish-create` with the complete `project`.
  • **Per-file edits** — `canvas-edit-create` with `operations` (each sets a

file's complete content, or deletes it with `content: null`). Prefer this for small changes to a large project; the guard is mandatory here because a diff's meaning depends on its base.

For a w

Read more
Ships withposthog-posthog

:hedgehog: PostHog is the leading platform for building self-driving products. Our developer tools – AI observability, analytics, session replay, flags, experiments, error tracking, logs, and more – capture all the context agents need to diagnose problems, uncover opportunities, and ship fixes. Steer it all from Slack, web, desktop, or the MCP.

Get the whole plugin

Other skills on posthog-posthog.