feat(vision): add scanner templates picker#60547
Conversation
Adds a templates page at /replay-vision/templates with curated starter scanners (dead ends, session summary, user intent, session outcome, frustration score) plus a blank "create from scratch" card. The "+ New scanner" CTA on the Vision homepage and welcome card now route here. Clicking a template lands the user on the Triggers tab of a new scanner pre-filled with the template's name, description, scanner type, and prompt. Pattern follows the LLM analytics evaluations templates page. Template key is read from the ?template= search param inside replayScannerLogic rather than passed through props, so all child components share the same logic instance. Generated-By: PostHog Code Task-Id: 3f1a3362-ad42-407a-9a30-f36776fc6bfa
|
Size Change: +9.15 kB (+0.01%) Total Size: 80.7 MB 📦 View Changed
ℹ️ View Unchanged
|
There was a problem hiding this comment.
Purely additive frontend feature — new templates picker scene with pre-fill logic via URL params. Route ordering is correct (templates before :id wildcard), param handling is safe (filtered against hardcoded list), no backend or API changes, and a test covers the new pre-fill behavior.
Prompt To Fix All With AIFix the following 2 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 2
products/replay_vision/frontend/replay_scanners/replayScannerSceneLogic.ts:42-47
**`templateKey` state is never consumed**
`setTemplateKey` and `templateKey` are wired up in `urlToAction`, but nothing downstream reads `values.templateKey`. `replayScannerLogic` reads the template key directly from `router.values.searchParams` via `currentTemplateKey()`, bypassing this stored value entirely. The tracked state is superfluous — removing it would simplify the logic without any behavioural change.
### Issue 2 of 2
products/replay_vision/frontend/replay_scanners/ScannerTemplatesScene.tsx:110-116
**`learnMoreUrl` prop is declared but never passed**
`TemplateGrid` declares and handles `learnMoreUrl` in JSX, but `ScannerTemplatesScene` — the only caller — never supplies it. The conditional branch (including the `<Link>`) is dead code right now. Either pass it or remove the prop to keep the interface lean.
```suggestion
interface TemplateGridProps {
title: string
description: string
showBackButton?: boolean
minHeight?: '60vh' | '80vh'
}
```
Reviews (1): Last reviewed commit: "feat(vision): add scanner templates pick..." | Re-trigger Greptile |
| templateKey: [ | ||
| null as string | null, | ||
| { | ||
| setTemplateKey: (_, { templateKey }) => templateKey, | ||
| }, | ||
| ], |
There was a problem hiding this comment.
templateKey state is never consumed
setTemplateKey and templateKey are wired up in urlToAction, but nothing downstream reads values.templateKey. replayScannerLogic reads the template key directly from router.values.searchParams via currentTemplateKey(), bypassing this stored value entirely. The tracked state is superfluous — removing it would simplify the logic without any behavioural change.
Prompt To Fix With AI
This is a comment left during a code review.
Path: products/replay_vision/frontend/replay_scanners/replayScannerSceneLogic.ts
Line: 42-47
Comment:
**`templateKey` state is never consumed**
`setTemplateKey` and `templateKey` are wired up in `urlToAction`, but nothing downstream reads `values.templateKey`. `replayScannerLogic` reads the template key directly from `router.values.searchParams` via `currentTemplateKey()`, bypassing this stored value entirely. The tracked state is superfluous — removing it would simplify the logic without any behavioural change.
How can I resolve this? If you propose a fix, please make it concise.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| interface TemplateGridProps { | ||
| title: string | ||
| description: string | ||
| showBackButton?: boolean | ||
| learnMoreUrl?: string | ||
| minHeight?: '60vh' | '80vh' | ||
| } |
There was a problem hiding this comment.
learnMoreUrl prop is declared but never passed
TemplateGrid declares and handles learnMoreUrl in JSX, but ScannerTemplatesScene — the only caller — never supplies it. The conditional branch (including the <Link>) is dead code right now. Either pass it or remove the prop to keep the interface lean.
| interface TemplateGridProps { | |
| title: string | |
| description: string | |
| showBackButton?: boolean | |
| learnMoreUrl?: string | |
| minHeight?: '60vh' | '80vh' | |
| } | |
| interface TemplateGridProps { | |
| title: string | |
| description: string | |
| showBackButton?: boolean | |
| minHeight?: '60vh' | '80vh' | |
| } |
Prompt To Fix With AI
This is a comment left during a code review.
Path: products/replay_vision/frontend/replay_scanners/ScannerTemplatesScene.tsx
Line: 110-116
Comment:
**`learnMoreUrl` prop is declared but never passed**
`TemplateGrid` declares and handles `learnMoreUrl` in JSX, but `ScannerTemplatesScene` — the only caller — never supplies it. The conditional branch (including the `<Link>`) is dead code right now. Either pass it or remove the prop to keep the interface lean.
```suggestion
interface TemplateGridProps {
title: string
description: string
showBackButton?: boolean
minHeight?: '60vh' | '80vh'
}
```
How can I resolve this? If you propose a fix, please make it concise.|
🎭 Playwright report · View test results →
These issues are not necessarily caused by your changes. |
<!-- Authoring rules (agents: read).
Title: <type>(<scope>): <description> — type=feat|fix|chore, scope required, lowercase, no period, <72 chars.
✅ feat(insights): add retention graph export
❌ feat: Added retention export. (capitalized, period, no scope)
Description: high-level rationale, not a step-by-step replay.
Public OSS repo: no internal customers, incidents, or operational metrics.
-->
## Problem
- this is a new product and we want to make it as easy as possible for people to onboard -- borrow some inspo from flags / llm evals and make some common templates
<!-- Who are we building for, what are their needs, why is this important? -->
<!-- Does this fix an issue? Uncomment the line below with the issue ID to automatically close it when merged -->
<!-- Closes #ISSUE_ID -->
## Changes
- New page at `/replay-vision/templates` (`ScannerTemplatesScene`) — centered grid of cards: one "Create from scratch" blank card plus five curated templates (Dead ends, Session summary, User intent, Session outcome, Frustration score) spanning monitor, summarizer, classifier, and scorer types. Pattern mirrors the LLM analytics evaluations templates page.
- Template definitions in scannerTemplates.ts as a typed discriminated union keyed by `scanner_type`.
- The "+ New scanner" CTA on the homepage and the welcome-card CTA both route to the templates page; the blank card preserves the "scratch" path.
<!-- If there are frontend changes, please include screenshots. -->
<!-- If a reference design was involved, include a link to the relevant Figma frame! -->
## How did you test this code?
click around!

<!-- Describe steps to reproduce and verify the changes, and what the expected behavior is. -->
<!-- Include automated tests if possible, otherwise describe the manual testing routine. -->
<!-- Agents: do NOT claim manual testing you haven't done. State that you're an agent and list only the automated tests you actually ran. -->
👉 _Stay up-to-date with_ [_PostHog coding conventions_](https://posthog.com/docs/contribute/coding-conventions) _for a smoother review._
## Automatic notifications
- [ ] Publish to changelog?
- [ ] Alert Sales and Marketing teams?
## Docs update
<!-- Add the `skip-inkeep-docs` label if this PR should not trigger an automatic docs update from the Inkeep agent. -->
<!-- Add the `skip-migration-service-check` label if every migration here is DB-noop (e.g. `SeparateDatabaseAndState` with empty `database_operations`, or pure `RunPython`) and it's safe to ship alongside service code. -->
## 🤖 Agent context
<!-- Fill this section if an agent co-authored or authored this PR. Remove it for fully human-authored PRs. -->
<!-- Include:
- tools/agent used and link to session. List the agent and tool names used, but do not include tool call results.
- decisions made along the way (what was tried, rejected, chosen, and why)
- anything else that helps reviewers
Write reviewer-facing prose. Do not paste user prompts verbatim — paraphrase the intent in your own words.
DO NOT INCLUDE sensitive data that may have been shared in an agent session.
-->
<!-- Rules for agent-authored PRs:
- All PRs must be attributable to a human author, even if agent-assisted.
- Do not add a human Co-authored-by just for the sake of attribution — if no human was involved in the changes, own it as agent-authored.
- Agent-authored PRs always require human review — do not self-merge or auto-approve.
- Do NOT claim manual testing you haven't done.
- GitHub PR descriptions render markdown, not fixed-width text. Do not hard-wrap prose at a column width or use space-aligned tables — use real markdown tables, headings, and fenced code blocks, and let GitHub flow the text.
-->

Problem
Changes
/replay-vision/templates(ScannerTemplatesScene) — centered grid of cards: one "Create from scratch" blank card plus five curated templates (Dead ends, Session summary, User intent, Session outcome, Frustration score) spanning monitor, summarizer, classifier, and scorer types. Pattern mirrors the LLM analytics evaluations templates page.scanner_type.How did you test this code?
click around!

👉 Stay up-to-date with PostHog coding conventions for a smoother review.
Automatic notifications
Docs update
🤖 Agent context