Skip to content

Commit e6c14e4

Browse files
LizzieeptonLizzie Eptonsmallbrownbike
authored
Add WarehouseWizardHint to data source pages (#18819)
* feat: add WarehouseWizardHint to data source pages Port the product app's WarehouseWizardHint (the "let AI connect your sources for you" nudge that promotes `npx @posthog/wizard warehouse`) to posthog.com and render it below the heading on the data-source pages: - /data-stack/sources (added directly in the page) - /docs/data-warehouse/sources and every child page — injected once in ReaderView, gated on the pathname, for MDX source docs; added directly in the DataWarehouseSource template (which hides the ReaderView title and renders its own heading) with a !hideTitle guard to avoid double-rendering. The card reuses the shared WizardCommand for the copyable command and is dismissible (persisted to localStorage), matching the product app. Generated-By: PostHog Code Task-Id: 0718dea4-1ae6-4e51-87cf-cc1c19609923 * fixes --------- Co-authored-by: Lizzie Epton <lizzieepton@Lizzies-Air.powerhub> Co-authored-by: Eli Kinsey <eli@ekinsey.dev>
1 parent f18cdff commit e6c14e4

7 files changed

Lines changed: 109 additions & 0 deletions

File tree

src/components/ReaderView/index.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ interface ReaderViewProps {
9898
title?: string
9999
header?: React.ReactNode
100100
hideTitle?: boolean
101+
belowTitle?: React.ReactNode
101102
tableOfContents?: any
102103
hideMobileTableOfContents?: boolean
103104
mdxComponents?: any
@@ -424,6 +425,7 @@ export default function ReaderView({
424425
title,
425426
header,
426427
hideTitle = false,
428+
belowTitle,
427429
tableOfContents,
428430
hideMobileTableOfContents = false,
429431
mdxComponents,
@@ -459,6 +461,7 @@ export default function ReaderView({
459461
title={title}
460462
header={header}
461463
hideTitle={hideTitle}
464+
belowTitle={belowTitle}
462465
tableOfContents={tableOfContents}
463466
hideMobileTableOfContents={hideMobileTableOfContents}
464467
mdxComponents={mdxComponents}
@@ -1346,6 +1349,7 @@ function ReaderViewContent({
13461349
title,
13471350
header,
13481351
hideTitle = false,
1352+
belowTitle,
13491353
tableOfContents,
13501354
hideMobileTableOfContents = false,
13511355
mdxComponents,
@@ -1594,6 +1598,19 @@ function ReaderViewContent({
15941598
{title}
15951599
</h1>
15961600
)}
1601+
{belowTitle && (
1602+
<div
1603+
className={`my-4 transition-all ${
1604+
fullWidthContent || body?.type !== 'mdx'
1605+
? 'max-w-full'
1606+
: contentMaxWidthClass
1607+
? contentMaxWidthClass
1608+
: 'mx-auto max-w-2xl'
1609+
}`}
1610+
>
1611+
{belowTitle}
1612+
</div>
1613+
)}
15971614
{(body?.date || body?.contributors || body?.tags) && (
15981615
<div
15991616
className={`flex items-center space-x-2 mb-4 flex-wrap transition-all ${
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import React from 'react'
2+
import { IconX } from '@posthog/icons'
3+
import CloudinaryImage from 'components/CloudinaryImage'
4+
import WizardCommand from 'components/WizardCommand'
5+
6+
// Persist dismissal so the hint doesn't nag a user who has already seen it. Mirrors the
7+
// product app's WarehouseWizardHint, which uses the same localStorage key.
8+
// theme-init.js sets `warehouse-wizard-hint-dismissed` on <html> before paint when this
9+
// key is set; global.css hides `.warehouse-wizard-hint` when that class is present.
10+
const DISMISSED_KEY = 'warehouse-wizard-hint-dismissed'
11+
const DISMISSED_CLASS = 'warehouse-wizard-hint-dismissed'
12+
13+
/**
14+
* Agent-flavored nudge that pushes the `npx @posthog/wizard warehouse` CLI, which auto-detects
15+
* and connects a user's databases/APIs straight from their codebase instead of setting up a
16+
* source by hand. Visual design matches [`WizardCTA`](../WizardCTA).
17+
*/
18+
export default function WarehouseWizardHint({ className = '' }: { className?: string }): JSX.Element {
19+
const handleDismiss = () => {
20+
localStorage.setItem(DISMISSED_KEY, '1')
21+
document.documentElement.classList.add(DISMISSED_CLASS)
22+
}
23+
24+
return (
25+
<div className={`warehouse-wizard-hint relative ${className}`}>
26+
<button
27+
type="button"
28+
onClick={handleDismiss}
29+
aria-label="Dismiss"
30+
className="absolute cursor-pointer rounded-full bg-white dark:bg-secondary p-1 top-1 right-1 translate-x-1/2 -translate-y-1/2 z-10 text-secondary hover:text-primary border border-secondary"
31+
>
32+
<IconX className="size-4" />
33+
</button>
34+
<div className="relative overflow-hidden rounded not-prose border border-secondary">
35+
<CloudinaryImage
36+
src="https://res.cloudinary.com/dmukukwp6/image/upload/texture_tan_9608fcca70.png"
37+
className="dark:hidden absolute inset-0 -bottom-12"
38+
imgClassName="h-full w-full object-cover"
39+
/>
40+
<CloudinaryImage
41+
src="https://res.cloudinary.com/dmukukwp6/image/upload/texture_tan_dark_a92b0e022d.png"
42+
className="hidden dark:block absolute inset-0 -bottom-12"
43+
imgClassName="h-full w-full object-cover"
44+
/>
45+
<div className="relative flex flex-col-reverse @lg:flex-row items-center justify-between pl-5 @lg:pl-8 pr-8 py-4 @lg:py-3 gap-4">
46+
<div className="flex-1 text-center @lg:text-left max-w-lg">
47+
<p className="text-lg font-bold !mb-0">Let AI connect your sources for you</p>
48+
<p className="!mt-1 !mb-3 text-sm opacity-75">
49+
Skip the manual setup — run this in your project and the wizard auto-detects your databases
50+
and APIs and connects them to PostHog.
51+
</p>
52+
<WizardCommand command="warehouse" />
53+
</div>
54+
<div className="shrink-0">
55+
<img
56+
src="https://res.cloudinary.com/dmukukwp6/image/upload/wizard_3f8bb7a240.png"
57+
alt="PostHog Wizard hedgehog"
58+
className="w-36 @lg:w-32 @xl:w-40 @2xl:w-48"
59+
/>
60+
</div>
61+
</div>
62+
</div>
63+
</div>
64+
)
65+
}

src/pages/data-stack/sources.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { customerDataInfrastructureNav } from '../../hooks/useCustomerDataInfras
44
import { TreeMenu } from 'components/TreeMenu'
55
import SEO from 'components/seo'
66
import Link from 'components/Link'
7+
import WarehouseWizardHint from 'components/WarehouseWizardHint'
78
import DWInstallationPlatforms from './dw-installation-platforms'
89

910
const LeftSidebarContent = () => {
@@ -19,6 +20,7 @@ export default function Sources(): JSX.Element {
1920
image="images/og/cdp.jpg"
2021
/>
2122
<ReaderView leftSidebar={<LeftSidebarContent />} title="Data sources & import (ELT)">
23+
<WarehouseWizardHint className="my-4" />
2224
<p>
2325
Connect your external databases, SaaS tools, ad platforms, and more to sync data in bulk into your
2426
PostHog warehouse for analysis and modeling. All events and user data captured via PostHog SDKs are

src/styles/global.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3053,3 +3053,8 @@ div[data-radix-popper-content-wrapper] {
30533053
transform: translate(calc(-50% + 1.5px), calc(-50% + 1px));
30543054
}
30553055
}
3056+
3057+
/* Set on <html> by theme-init.js before paint when the hint was previously dismissed. */
3058+
html.warehouse-wizard-hint-dismissed .warehouse-wizard-hint {
3059+
display: none;
3060+
}

src/templates/DataWarehouseSource.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import SEO from 'components/seo'
44
import ReactMarkdown from 'react-markdown'
55
import ReaderView from 'components/ReaderView'
66
import SourceConfiguration from 'components/Product/Sources/Configuration'
7+
import WarehouseWizardHint from 'components/WarehouseWizardHint'
78
import { getProseClasses } from '../constants'
89

910
interface SourceField {
@@ -43,6 +44,7 @@ export default function DataWarehouseSource({
4344
<span className="text-xs font-semibold px-2 py-0.5 rounded bg-blue/10 text-blue">Beta</span>
4445
)}
4546
</div>
47+
<WarehouseWizardHint className="my-4" />
4648
<div className={getProseClasses('base')}>
4749
<p>
4850
Connect {name} to PostHog to sync your data into the PostHog data warehouse for analysis and

src/templates/Handbook.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from 'react'
22
import ReaderView from 'components/ReaderView'
33
import { graphql } from 'gatsby'
4+
import { useLocation } from '@reach/router'
45
import { Blockquote } from 'components/BlockQuote'
56
import { MdxCodeBlock } from 'components/CodeBlock'
67
import { Heading } from 'components/Heading'
@@ -28,6 +29,7 @@ import { IconWarning, IconCheck, IconX } from '@posthog/icons'
2829
import IsEU from 'components/IsEU'
2930
import IsUS from 'components/IsUS'
3031
import { CallToAction } from 'components/CallToAction'
32+
import WarehouseWizardHint from 'components/WarehouseWizardHint'
3133
import Tooltip from 'components/Tooltip'
3234
import NewsletterForm from 'components/NewsletterForm'
3335
import { MDXRenderer } from 'gatsby-plugin-mdx'
@@ -353,6 +355,14 @@ export default function Handbook({ data: { post, postHogSource }, pageContext: {
353355
const sourceFields = postHogSource?.sourceFields ?? null
354356
const sourceTables = postHogSource?.tables ?? null
355357
const posthog = usePostHog()
358+
const { pathname } = useLocation()
359+
// Hand-written source docs use this template (not DataWarehouseSource). Show the
360+
// warehouse wizard nudge on data-warehouse source URLs and on CDP source pages
361+
// linked to a postHogSource.
362+
const showWarehouseWizardHint =
363+
!!postHogSource ||
364+
pathname === '/docs/data-warehouse/sources' ||
365+
pathname.startsWith('/docs/data-warehouse/sources/')
356366

357367
// Track product interest for cross-subdomain cookie
358368
useProductInterestFromPathname(slug)
@@ -437,6 +447,7 @@ export default function Handbook({ data: { post, postHogSource }, pageContext: {
437447
: null),
438448
}}
439449
title={title}
450+
belowTitle={showWarehouseWizardHint && <WarehouseWizardHint />}
440451
tableOfContents={frontmatterTableOfContents || tableOfContents}
441452
mdxComponents={components}
442453
commits={commits}

static/scripts/theme-init.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,11 @@
3838
siteSettings.reduceTransparency ? 'true' : 'false'
3939
)
4040
} catch (err) {}
41+
42+
// Hide dismissed WarehouseWizardHint before first paint
43+
try {
44+
if (localStorage.getItem('warehouse-wizard-hint-dismissed') === '1') {
45+
document.documentElement.classList.add('warehouse-wizard-hint-dismissed')
46+
}
47+
} catch (err) {}
4148
})()

0 commit comments

Comments
 (0)