mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 17:35:10 +03:00
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Add telemetry for `PromptPanel` to help us understand how people interact with our AI prompts better. Relates to DOCS-1393 Dashboard(restricted access): [Docs: AI prompt affordances](https://eu.posthog.com/project/34344/dashboard/957235) ## What is the current behavior? The docs homepage cover renders a setup panel with "AI Prompt" and "CLI" tabs, and guides render `AiPrompt` blocks. Both are built on the shared `PromptPanel`, whose copy button called `copyToClipboard` and nothing else. Copying was therefore unmeasured, while the neighbouring affordances (`ask_ai_clicked`, `agent_setup_clicked`, `copy_as_markdown_clicked`) are already instrumented. ## What is the new behavior? `PromptPanel` takes an optional `telemetry` prop. When it is set, the panel sends a new docs-owned event after a **successful** clipboard write, so instrumentation lives in the shared component instead of a forked homepage copy button. New event in `packages/common/telemetry-constants.ts`: | | | | --- | --- | | `action` | `docs_ai_prompt_copied` | | `source` | `homepage` \| `guide` \| `agent_setup` | | `tab` | `prompt` \| `cli` (omitted for panes outside that set) | | `promptId` | prompt id, when the panel comes from an `AiPrompt` block | Wired consumers: `HomePageCover` (`homepage`), `AiPrompt` (`guide` by default, plus `promptId`), and `AgentSetup` (`agent_setup`). No prompt body text and no PII is sent. Studio's existing `ai_prompt_copied` event is deliberately left alone: it has a different owner and surface, and merging the two would blend unrelated funnels. ### Proof it works ``` $ pnpm run test:local:unwatch features/ui/PromptPanel.telemetry.test.ts RUN v5.0.0 /apps/docs Test Files 1 passed (1) Tests 4 passed (4) Duration 775ms ``` ## Additional context Test plan, run against a local docs server with a stub telemetry endpoint so the request bodies could be read directly: | Case | Observed payload | | --- | --- | | Homepage, AI Prompt tab | `{"source":"homepage","tab":"prompt"}` | | Homepage, CLI tab | `{"source":"homepage","tab":"cli"}` | | Next.js quickstart `AiPrompt` | `{"source":"guide","tab":"prompt","promptId":"nextjs"}` | | `automate-with-agents/health` `AgentSetup` | `{"source":"agent_setup","tab":"prompt","promptId":"monitoring-agent-health"}` | | Clipboard write rejected | no request sent, error toast shown, button does not flip to "copied" | The failure case was re-checked with a control click on the same page after restoring a working clipboard, which did send the event, so the negative result is not just a missed handler. Also run: `turbo typecheck --filter=docs --filter=common` (passes), Prettier check on the touched files (passes), and ESLint on the touched docs files (no new findings; the one warning on `HomePageCover` is the pre-existing default export). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Successful prompt copies are now tracked across the homepage, documentation guides, and agent setup experiences. * Copy activity records the prompt’s source, selected format, and associated prompt when available, providing more complete usage insights. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Nik Richers <nik@validmind.ai>
54 lines
1.5 KiB
TypeScript
54 lines
1.5 KiB
TypeScript
'use client'
|
|
|
|
import { aiPrompts, type AiPromptId } from '~/data/ai-prompts.data'
|
|
|
|
import {
|
|
Prompt,
|
|
PromptContent,
|
|
PromptCopy,
|
|
PromptMarkdown,
|
|
PromptPanel,
|
|
PromptTitle,
|
|
type PromptPanelTelemetry,
|
|
} from './PromptPanel'
|
|
|
|
type AiPromptProps = {
|
|
/** Looks up prompt text from `aiPrompts`. */
|
|
id: AiPromptId | string
|
|
/** Includes the prompt body in generated guide Markdown. */
|
|
includeInMarkdown?: boolean
|
|
/** Surface reported when the prompt is copied. */
|
|
telemetry: Omit<PromptPanelTelemetry, 'promptId'>
|
|
}
|
|
|
|
/**
|
|
* MDX-facing wrapper around {@link PromptPanel}. Composes the compound
|
|
* children in this client module so detection does not cross the RSC
|
|
* boundary (where child types arrive as `react.lazy` and the panel
|
|
* would otherwise render nothing).
|
|
*
|
|
* Prompt text lives in `~/data/ai-prompts.data`. Markdown export is opt-in so
|
|
* existing quickstarts do not duplicate their instructions in bulk exports.
|
|
*/
|
|
function AiPrompt({ id, telemetry }: AiPromptProps) {
|
|
const prompt = aiPrompts[id as AiPromptId]
|
|
if (!prompt) {
|
|
throw new Error(`Unknown AiPrompt id: ${id}`)
|
|
}
|
|
|
|
return (
|
|
<PromptPanel telemetry={{ ...telemetry, promptId: id }}>
|
|
<Prompt value="prompt" expandable>
|
|
<PromptTitle>Agent Prompt</PromptTitle>
|
|
<PromptCopy>{prompt}</PromptCopy>
|
|
<PromptContent>
|
|
<PromptMarkdown>{prompt}</PromptMarkdown>
|
|
</PromptContent>
|
|
</Prompt>
|
|
</PromptPanel>
|
|
)
|
|
}
|
|
|
|
export { AiPrompt }
|
|
export type { AiPromptProps }
|