Arranges a page in PostHog made of small widgets, such as your personal home page, reusing a widget that already exists before anyone builds a new one and fitting each into the box you drew for it.
WHEN TO USE
SCOPE
USE FOR
Lay out a home page that sums up your work in progress across several widgets.
Place an existing weather widget on your grid and set it to show Lisbon.
Copy and adapt a widget that's almost right when its settings can't do what you need.
Build a new reusable widget that teammates can find and place on their own grids.
Fix a broken widget that someone flagged in a comment on the page.
NOT FOR
Building a standalone app page — that is handled by building-canvases.
This is a saved copy of the skill's SKILL.md instructions. It may differ from the upstream file or the version you install.
Composing grid canvases
A grid canvas is a composition, not an app: a grid of placements, each rendering a component
canvas (a reusable widget with its own source, build, and placement contract). The user's home
canvas is an ordinary grid canvas in their personal channel. Layout is data — publishing or
patching one is live immediately, with no build.
Three canvas kinds share one lifecycle:
freeform — a standalone app (the building-canvases skill owns these).
component — a reusable widget. Same source/build pipeline as freeform, plus a placement
contract. Visibility rides its channel: personal channel = private, team channel = shared.
grid — a layout of placements referencing components. No file source; layout only.
The resolution ladder: configure, fork, build
When a grid placement needs content ("a weather widget here", "a kanban of my tasks"), resolve in
this order — placing an existing component beats authoring a duplicate:
Search the store: canvas-list with kind=component and search=<what the widget shows>.
A component is placeable when both component_meta and published_build_id are set. If its
configSchema can express the request ("weather for Lisbon" → existing weather component with
config: {"location": "Lisbon"}), place and configure it — write no code.
Fork when a component is close but its config cannot express the ask: read its source
(canvas-source-retrieve), create a new component (canvas-create with kind=component),
adapt, publish. Name the difference in the new component's description.
Build new when nothing fits — see "Building a component" below.
New components land in the channel you create them in. Create them in the same channel as the grid
they serve unless the user asks to share them more widely.
Building a component
A component is authored exactly like a freeform canvas — load building-react-quill-canvases (or
building-html-canvases) plus querying-canvas-data and validating-and-publishing-canvases —
with three additions. A component that shows PostHog data follows the same verifiability rule as
any canvas: an insight-backed figure links its saved insight, an ad-hoc query exposes the exact
query that ran (see "Verifiability" in querying-canvas-data).
Start from the complete, buildable project in references/component-example.md; its envelope, placement contract, capability declarations, and defensive ph.state access are the parts that break when improvised.
Create with kind=component and a description written for store search: say what the
widget shows and what its config controls. Future placements are found by this text.
Declare the placement contract in the project's top-level component key:
Size is in grid units (widths 1–12, heights 1–40); minW <= defaultW <= maxW. The range is
advisory: users may resize a placement to any size, so it informs defaults and warnings, never
rejections. The config schema
vocabulary is an allowlist — type, title, description, default, properties, required,
additionalProperties, items, enum, const, minimum, maximum, minLength, maxLength,
minItems, maxItems, format. No $ref, no pattern — validation rejects them.
Design responsively. Give the component's root min-h-screen so it fills the placement iframe's viewport and grows past it as content demands.
Adapt the layout to any size the user drags: a 2×1 placement is a glanceable tile; a 6×4 is a full app surface.
Do not use h-screen on the root: a fixed viewport height caps a flex column, so tall children shrink and clip instead of scrolling.
Do not use h-full on the root either: a published component's artifact shell gives its html, body, and #root elements no explicit height, so height: 100% collapses to the content height.
Render usefully at minW×minH, and treat config as the only per-placement input.
Publish and wait for the build like any canvas — a component with no ready build cannot go live on
a grid.
Composing a whole canvas
A whole-canvas ask ("a home canvas that summarizes my work in progress") usually means several widgets, not one.
Plan the full set first — one placement per concern — then resolve each with the ladder above.
Lay them out together: no overlaps, sizes matched to what each widget shows, the grid filled deliberately rather than tiles scattered in a corner.
Batch the layout writes (one publish for an initial layout, surgical patches after) instead of one write per widget, and finish with every placement live or failed — never generating.
Canvas comments
Users leave feedback as comment threads on the canvas.
List them with the task comment tools (tasks-comments-list, tasks-comments-retrieve) on your task before and after changing the canvas, and address the open ones — a comment naming a broken widget is your brief for fixing it.
Editing a grid
The loop is read → patch, guarded exactly as validating-and-publishing-canvases describes for
source publishes — with canvas-layout-get in place of canvas-source-retrieve, and
canvas-layout-patch (surgical ops, guard required) or canvas-layout-publish (complete
document, for an initial layout or full restructure) as the write. On a 409, re-read the layout,
re-apply your change, and patch again.
Operations:
add_placement — a new box: {id, status, x, y, w, h, ...}. Placements must not overlap or
extend past grid.columns.
update_placement — merge changes into the placement with id. Filling a drawn box is
{"op": "update_placement", "id": "p1", "changes": {"status": "live", "component": "<component canvas id>", "config": {...}}}.
remove_placement, set_grid.
The placement lifecycle
A placement's status tells the renderer what to show:
pending — the user drew a box but hasn't described it (or the prompt awaits dispatch).
generating — an agent task is filling it; generationTaskId links the task and prompt
records the ask. Set this when you start working on a placement from a task.
live — renders its component at version ("latest" by default; a pinned version id is
allowed). Requires the component to be published and visible to the acting user.
failed — generation failed; keep the prompt so the user can retry or re-describe.
When a task asks you to fill a placement, its prompt and the box's size are your brief: honor the
drawn w×h and keep the placement's prompt
intact for provenance.
Validation you will hit
Layout publishes validate atomically; every error names its placement. The common ones:
component_not_found — the id is wrong, deleted, not a component, or not visible to the acting
user (a component in someone else's personal channel is not placeable).
component_not_published — the component has never published a placement contract.
placement_config_invalid — config does not match the component's configSchema.
placement_size_out_of_contract — a warning, not an error: the box's w/h is outside the
component's suggested range. The publish still succeeds; the component must render responsively.
placements_overlap / invalid_placement — geometry; fix coordinates rather than removing the
other widget.
End your reply by linking the grid canvas with the url field the canvas tools return — never
construct a canvas URL yourself.
MCP connection required
1 FOR YOU
01
Connect the PostHog MCP server
Connect the PostHog MCP server so the assistant can call canvas-list, canvas-create, canvas-source-retrieve, canvas-layout-get, canvas-layout-patch, canvas-layout-publish and tasks-comments-list.
🔌 This skill ships inside the PostHog AI Plugin. Listed package contents include 3 slash commands, 1 agent, hooks and an MCP server. Installed components and skill versions may vary by AI tool.
Install the whole plugin
This route installs the posthog plugin package selected for your AI tool.
Claude Code
Add PostHog's marketplace, then install the plugin
Run both lines in a terminal. They install PostHog's posthog plugin: this skill, PostHog's other skills, and a connection to PostHog's hosted MCP server.
01
claude plugin marketplace add PostHog/ai-plugin
02
claude plugin install posthog@posthog
Installation and loading
The plugin installs for you in every project and loads the next time you start Claude Code, or after /reload-plugins in an open session.
To connect your PostHog account, start claude, type /mcp, select plugin:posthog:posthog and follow the browser prompts.
Good to know
The plugin includes PostHog's session-capture hook; PostHog's README says it sends sessions to LLM Analytics only when POSTHOG_LLMA_CC_ENABLED=true and POSTHOG_API_KEY are both set.
If you use the separate posthog-telemetry plugin, PostHog says to keep only one of the two, because both register the same hook.
On a self-hosted PostHog, this route's MCP connection won't reach your instance: the plugin's config is fixed to https://mcp.posthog.com/mcp, which routes to PostHog's US or EU region. POSTHOG_MCP_URL works only for the Gemini CLI extension.
Install without the plugin (incomplete)
What's missing
Installing just this skill adds only its own folder. Its instructions also call for other plugin components, such as shared scripts, reference files or other skills, which aren't included. Installing the whole plugin avoids this gap.
Run this outside your AI tool, using Node.js 22.20.0 or newer. Skills CLI 1.7.2 skips skill selection; prompts cancel installation without an interactive terminal. If choosing Project when asked about installation scope, open your project's folder before running this.
Install checklist
Check selected tools if a picker appears; Claude Code may be unchecked under Additional agents. ↑/↓ moves, Space toggles selections, Enter confirms.
Without a tool picker, check Installing to: for your intended tool. Stop if it names a different tool.
If asked, choose Symlink (Recommended) for shared files or Copy to all agents for separate copies; review the summary before confirming installation.
Install the find-skills skill? defaults to Yes, adding another skill for all projects. Choose No if you don't want that extra installation.
Skills CLI 1.7.2 sends install data to skills.sh by default, including the source, skill names, target tools and file details; GitHub sources are reported only when GitHub confirms the repository is public, while other remote sources can also be reported. Confirmed-public GitHub sources also trigger a security-audit request. Before installing, set the environment variable DO_NOT_TRACK=1 or DISABLE_TELEMETRY=1 to disable both.
After installing for Claude Code, open it in the installation project if you chose Project; Global makes the skill available across projects on this computer. Once Claude Code loads the skill, its description helps Claude decide when to use it.
If installation created a top-level skills folder that did not exist when your Claude Code session started, run /reload-skills in that session. Run it again after later changes in that folder.
Sync columns from a synced data warehouse table onto PostHog person or group properties, so warehouse data becomes usable anywhere person and group properties already work: feature flag targeting, cohorts, insight filters and breakdowns, surveys, session replay filters, workflows, and the person profile. Use when the user wants to "add a person property from my warehouse", "enrich people with Stripe/Postgres/Salesforce data", "put ARR or plan tier on my persons", "target a feature flag by a warehouse column", "sync warehouse columns onto groups or organizations", or wants to inspect, backfill, disable, or debug an existing warehouse-backed person or group property.Read full description
Analyze the most expensive users in AI observability and explain why they cost so much. Use when the user asks about top spenders, expensive users, per-user LLM cost, user-level cost drivers, or patterns behind high AI observability spend.Read full description
Analyze session replay patterns across experiment variants to understand user behavior differences. Use when the user wants to see how users interact with different experiment variants, identify usability issues, compare behavior patterns between control and test groups, or get qualitative insights to complement quantitative experiment results. Also covers pairing the observed behavior with a linked survey when the user wants qualitative feedback beyond what recordings show.Read full description
Assesses what a page's heatmap is telling you and recommends concrete changes. Pulls click / rageclick / scroll-depth data for a URL, names the hot elements by cross-referencing autocapture events on the same page, and can create a saved heatmap the user opens in PostHog, then summarizes the behavior and proposes improvements.
TRIGGER when: user asks what a heatmap shows, why people aren't clicking something, where users rage-click, how far they scroll, what to change on a page based on heatmap/click data, or to 'analyze/assess/review the heatmap' for a URL.
DO NOT TRIGGER when: the user only wants to create a saved heatmap screenshot with no analysis (use heatmaps-saved-create directly), or is asking about session replay in general (use investigating-replay).Read full description
Audit every endpoint in a PostHog project for staleness, failed materialisations, and unused materialised versions. Use when the user asks "what endpoints can I clean up?", "are any of my endpoints broken?", "which materialised versions are still being called?", or wants a one-shot cleanup pass over the Endpoints product. Produces a prioritised report grouped by issue type, with recommended actions but does not modify anything without explicit confirmation.Read full description
Audit PostHog experiments and feature flags for configuration issues, staleness, and best-practice violations. Read when the user asks to audit, health-check, or review experiments or feature flags, check flag hygiene, or verify experiment setup.Read full description