← KnockCONTENT HISTORY

Update to Knock

Snapshot Sep 30, 2026 · 22:59 UTC · version 1.1.0

Collection source: not recorded for this historical snapshot.

WHAT CHANGED · RULE-BASED ANALYSIS

First saved snapshot

No earlier snapshot is available to establish a change.

Compare saved observations

Download comparison JSON
Full technical diff · 0 changed fields
Full snapshot data
{
  "name": "knock-in-app-ui",
  "description": "Guidance for implementing Knock in-app UI in a web app, with a focus on setting up, rendering, and debugging Knock guides in React.",
  "included_files": [
    {
      "relative_path": "rules/debugging-guides.md",
      "size_in_bytes": 5729
    },
    {
      "relative_path": "rules/feeds-vs-guides.md",
      "size_in_bytes": 3384
    },
    {
      "relative_path": "rules/rendering-guides-react.md",
      "size_in_bytes": 12631
    },
    {
      "relative_path": "rules/setup-guide-providers-react.md",
      "size_in_bytes": 13443
    }
  ],
  "skill_md_contents": "---\nname: knock-in-app-ui\ndescription: Guidance for implementing Knock in-app UI in a web app, with a focus on setting up, rendering, and debugging Knock guides in React.\n---\n\n# Knock in-app UI skill\n\nThis skill helps you build in-app UI with Knock. It covers the two in-app products — **feeds** and **guides** — at a high level, then goes deep on guides: provider setup, rendering with hooks, and debugging.\n\nReference: https://docs.knock.app/in-app-ui/overview\n\n## Overview\n\nThe skill is organized into four focused rule files. Client-framework guidance is scoped per framework via a `-<framework>` suffix (currently only React). Cross-framework concepts live in unsuffixed files.\n\n1. **Feeds vs. guides** (framework-agnostic) — which product to pick for a given surface and why\n2. **Setting up the guide providers in React** — `KnockProvider` and `KnockGuideProvider` props, where each value comes from, and how to sequence them\n3. **Rendering guides in React** — building a guide component with `useGuide` / `useGuides`, typed content, and engagement tracking\n4. **Debugging guides** (framework-agnostic) — the guides toolbar, the triage checklist, and testing workflow\n\n> **Framework scope:** right now this skill only covers React (`@knocklabs/react`). If the user is building with Vue, Svelte, plain JS, React Native, iOS, or Android, stop and ask how they'd like to proceed — do not adapt the React rules to another client SDK on your own.\n\n## How to use this skill\n\n### When deciding what to build\n\nStart with `rules/feeds-vs-guides.md`:\n\n- Confirm the surface you're building is actually a guide, not a feed\n- Check the decision table before picking a direction\n- If the answer is \"both,\" wrap the app in `KnockProvider` once and render each product's provider where it's needed\n\n### When adding guides to a React app for the first time\n\n1. Read `rules/setup-guide-providers-react.md`\n2. **Before running any CLI commands, confirm the CLI is authenticated and which Knock environment this setup is for.** First run `knock whoami` — if it errors with something like \"not authenticated\" or \"no user session,\" run `knock login` and ask the user to complete the browser flow before continuing (the CLI persists the session so this is a one-time step per machine). Only after `knock whoami` succeeds, run `knock environment list` and ask the user to pick (the CLI defaults to `development`, but most real integrations target `production`). Remember that slug as `<env-slug>` and pass `--environment <env-slug>` on every subsequent environment-scoped `knock` command.\n3. **Before asking the user anything about the channel, discover `channelId` via the Knock CLI:** run `knock channel list --json | jq -r '.[] | select(.key == \"knock-guide\") | .id'`. Channels are account-scoped, so this command does **not** take `--environment`. If it prints a UUID, use it — do not ask the user to confirm or re-paste. Only ask the user if the CLI returns nothing or errors. See the rule file's \"Where to get `channelId`\" procedure for the full fallback order.\n4. Ask the user only for values that can't be auto-discovered — primarily the public `apiKey` for the chosen environment (and confirm `user.id` is coming from the app's auth context). Do not bundle the `apiKey` ask with `channelId`.\n5. Wire `KnockProvider` + `KnockGuideProvider` at the top of the tree.\n6. Gate `readyToTarget` on any async data your targeting depends on.\n7. **Get a real guide rendering before stopping.** Run `knock guide list --environment <env-slug> --json`, show the user the options (`key`, `name`, each step's `schema_key`), and build the first component against a real guide's actual values. Do not scaffold with placeholder strings like `\"changelog-card\"`. Fetch the message type schema with `knock message-type get <schema_key> --environment <env-slug> --json` so the content is typed. **If the environment has no guides, offer to scaffold a test one via the Knock CLI** (`knock guide new` → edit the JSON → `knock guide push --environment <env-slug>`) using a built-in message type (`card`, `banner`, or `modal`) with obvious-placeholder content — don't stall waiting for manual dashboard setup. See `rules/rendering-guides-react.md` → \"First guide: discover real guides via CLI before writing code\" for the full procedure including the empty-environment branch.\n8. Flag anything that still needs the user (paste `pk_` key, flip the guide to active in the dashboard, restart dev server) explicitly — don't leave them to discover it by absence.\n\n### When building a new guide component in React\n\n1. Follow the workflow in `rules/rendering-guides-react.md`\n2. **Discover the target guide (or message type) via the Knock CLI before picking values.** `knock guide list --environment <env-slug> --json` for the guide's `key` / step `schema_key`; `knock message-type get <schema_key> --environment <env-slug> --json` for the content schema. Avoid placeholder strings.\n3. Pick `useGuide` for single-guide surfaces, `useGuides` for lists\n4. Define a TypeScript type that mirrors the message type schema you just pulled\n5. Wire `markAsSeen`, `markAsInteracted`, and `markAsArchived` — custom components must do this themselves\n\n### When a guide isn't rendering\n\n1. Open `rules/debugging-guides.md` and work the triage checklist top to bottom\n2. Turn on the guides toolbar (`?knock_guide_toolbar=true`) first — it answers most questions in seconds\n3. Distinguish server-side (targeting/eligibility) from client-side (provider/component) failures before digging deeper\n\n## Rule files reference\n\n- `rules/feeds-vs-guides.md` — product selection between feeds and guides (framework-agnostic)\n- `rules/setup-guide-providers-react.md` — configuring `KnockProvider` and `KnockGuideProvider` for guides (React)\n- `rules/rendering-guides-react.md` — `useGuide`, `useGuides`, typed content, engagement tracking (React)\n- `rules/debugging-guides.md` — toolbar, triage checklist, testing workflow (framework-agnostic)\n\n## Quick reference\n\nThe examples below are React. For any other client SDK, see the note at the top of **Overview** before proceeding.\n\n### Providers (minimum viable setup — React)\n\n```tsx\n<KnockProvider\n  apiKey={process.env.NEXT_PUBLIC_KNOCK_API_KEY}\n  user={{ id: currentUser.id }}\n>\n  <KnockGuideProvider\n    channelId={process.env.NEXT_PUBLIC_KNOCK_GUIDE_CHANNEL_ID}\n    readyToTarget\n    listenForUpdates\n  >\n    {children}\n  </KnockGuideProvider>\n</KnockProvider>\n```\n\n### Where to source each value\n\n- **Auth first, then environment** — Knock is environment-scoped. Before any CLI command, verify the CLI is authenticated with `knock whoami`; if it errors, run `knock login` and wait for the user to complete the browser flow. Then run `knock environment list` and confirm the target slug (`production`, `development`, …) with the user. Pass `--environment <env-slug>` on every subsequent environment-scoped `knock` command. Don't rely on the CLI's `development` default.\n- `apiKey` — Knock dashboard → **Platform → API keys** → public `pk_...` key **from the tab for the chosen environment** (switch envs via the dashboard's environment selector first; remind the user to copy the key for the right env)\n- `user.id` — your auth context; must match the id used when identifying the user from your backend\n- `channelId` — the **UUID** of the guide channel, not its key. Channels are account-scoped, so `knock channel list` does **not** take `--environment`. **Always attempt CLI discovery before asking the user:**\n\n  ```bash\n  knock channel list --json | jq -r '.[] | select(.key == \"knock-guide\") | .id'\n  ```\n\n  If this prints a UUID, use it directly — don't prompt for confirmation. The default guide channel key is `knock-guide` (type `in_app_guide`). Fall back to the dashboard (**Settings → Integrations → Channels**) only if the CLI returns nothing or errors. See `rules/setup-guide-providers-react.md` for the full procedure.\n\n### Hooks at a glance\n\n- `useGuide({ type })` — one guide by message type\n- `useGuide({ key })` — one specific guide by key\n- `useGuides({ type })` — array of guides by message type\n- `useGuideContext()` — low-level client access\n\n### Engagement methods\n\n- `step.markAsSeen()` — impression (call from `useEffect` keyed on `step`)\n- `step.markAsInteracted()` — primary action\n- `step.markAsArchived()` — dismissal; removes the guide for this user going forward\n\n### First stop when something's wrong\n\nAppend `?knock_guide_toolbar=true` to any URL. The toolbar shows all guides, which are active, which this user is eligible for, and why the rest were filtered out.\n\n## Best practices summary\n\n1. **Pick the right product.** Feeds for chronological lists, guides for targeted UI.\n2. **Mount providers once, high in the tree.** Inside your auth boundary, above any route that renders guides.\n3. **Never pass a placeholder user.** Wait for auth to resolve before mounting `KnockProvider`.\n4. **Gate `readyToTarget` on async data** your targeting rules depend on.\n5. **Type your content.** `useGuide<T>` should mirror the Knock message type schema.\n6. **Always handle engagement.** Custom components must call `markAsSeen`, `markAsInteracted`, and `markAsArchived` themselves.\n7. **Use the toolbar first.** Most \"the guide isn't showing\" questions are answered in seconds.\n"
}

SHA-256: a5d4f011dae360940c07c891069779340544f5b4c0d785a00d21c29ec28899f1