Skip to content

feat(today): add to home from insight menus - #131365

Closed
puemos wants to merge 2 commits into
masterfrom
posthog/today-add-to-home
Closed

puemos wants to merge 2 commits into
masterfrom
posthog/today-add-to-home

Conversation

@puemos

@puemos puemos commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

Problem

  • People can pin an insight to their home only from the home page editor, not where they look at the insight.

Changes

  • The dashboard card menu and the insight page "⋮" menu show "Add to home" or "Remove from home".
  • With 4 numbers on the home, the item is disabled and says why.
  • The item shows only with today-rail-nav on, and only for line, bar and area trends.
  • A shared homePinsLogic in lib/components serves both menus.
  • Pin events get the source values dashboard_card and insight_menu.

pinned
full

How did you test this code?

  • homePinsLogic.test.ts catches a bad pin list or a fifth pin.
  • Storybook rendered all three card menu states.
  • Not checked: the insight page menu and its toast.

Release status

  • This change is behind a feature flag and is not available to users

Docs update

  • None.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Agent: Claude Code, claude-opus-5-5

Skills: /writing-ui-components, /writing-user-facing-copy, /writing-tests, /writing-pr-descriptions

More context for AI agents
  • Decisions: Split from feat(today): rework the home key numbers #131119, which keeps the key numbers changes.
  • Decisions: The logic mounts with the menu item, so pins load only when a menu opens.
  • Read closely: frontend/src/lib/components/AddToHome/homePinsLogic.ts

Created with PostHog Desktop from a PostHog Desktop task

🤖 Generated with Claude Code

The dashboard card menu and the insight page menu get "Add to home" or "Remove from home" for line, bar and area trends, behind today-rail-nav. The item is disabled when the home already shows 4 numbers. A shared homePinsLogic serves both menus.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Generated-By: PostHog Desktop
Task-Id: 731c158e-22b1-4b23-87e2-779c3453cb27
@puemos puemos self-assigned this Nov 7, 2026
@trunk-io

trunk-io Bot commented Nov 7, 2026

Copy link
Copy Markdown

Merging to master in this repository is managed by Trunk.

  • To merge this pull request, check the box to the left or comment /trunk merge below.

After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here

@github-actions

github-actions Bot commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

🤖 CI report

✅ Trunk lane — non-backend lane

This PR is assigned to the non-backend lane. It does not run backend Python tests and may merge in parallel with PRs in other lanes.

⚠️ Complexity (TypeScript) — 3 functions above the limit (max 123)

Cyclomatic complexity above the limit in changed typescript files (10 for production files, 15 for test files). Warn only: worth simplifying when you next touch these functions.

Function Location Complexity Limit
InsightMetaBody frontend/src/lib/components/Cards/InsightCard/InsightMeta.tsx:159 123 10
InsightMetaContent frontend/src/lib/components/Cards/InsightCard/InsightMeta.tsx:904 23 10
QuillInsightPageHeaderActions products/product_analytics/frontend/insights/insightScene/QuillInsightPageHeaderActions.tsx:35 16 10
✅ Duplication (Python) — clean

New Python code duplication introduced by this branch. Fails at 70+ tokens in app code, or 150+ tokens when both copies live in test files. Advisory while the gate proves itself: extract a shared helper instead of copying.

✅ Duplication (TypeScript) — clean

New TypeScript code duplication introduced by this branch. Fails at 70+ tokens in app code, or 150+ tokens when both copies live in test files. Advisory while the gate proves itself: extract a shared helper instead of copying.

⚠️ Bundle size — 🔺 +1.0 KiB (+0.0%)

Uncompressed size of every built .js bundle, compared against the base branch.

Total: 77.41 MiB · 🔺 +1.0 KiB (+0.0%)

No file changed by more than 1000 B.

Posted automatically by build-bundle-size-report · uncompressed bytes from dist-report

✅ Eager graph — within budget

How much code each root ships on the eager path — downloaded and parsed before the surface is interactive. Measured from the esbuild output chunks (post-tree-shake, static imports only); lazy import() / React.lazy chunks are not counted.

Root Eager (shipped) Δ vs base Budget
entry (logged-out pages, app bootstrap)
src/index.tsx
1.03 MiB · 25 files no change █████████░ 90.1% of 1.14 MiB
logged-out boot: index + App + bootApp (preloaded by every page, including /login)
src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
3.01 MiB · 625 files no change ██████████ 99.2% of 3.03 MiB
authenticated shell (every logged-in page)
src/scenes/AuthenticatedShell.tsx
3.83 MiB · 1,228 files no change ██████████ 95.6% of 4.01 MiB
dashboard scene
src/scenes/dashboard/Dashboard.tsx
7.62 MiB · 2,944 files 🔺 +4.4 KiB (+0.1%) ████████░░ 77.4% of 9.84 MiB
today home path
src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
4.70 MiB · 1,759 files 🔺 +414 B (+0.0%) ██████████ 95.4% of 4.93 MiB
AI-first home path
src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
6.00 MiB · 2,265 files 🔺 +380 B (+0.0%) ██████████ 95.7% of 6.27 MiB
events scene
src/scenes/activity/explore/EventsScene.tsx
6.69 MiB · 2,519 files no change ███████░░░ 71.1% of 9.41 MiB
web analytics scene
src/scenes/web-analytics/WebAnalyticsScene.tsx
7.71 MiB · 2,884 files no change ███████░░░ 73.5% of 10.49 MiB
replay detail scene
src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
6.91 MiB · 2,605 files no change █████████░ 85.0% of 8.13 MiB

🟢 node_modules/monaco-editor/ stays out of src/index.tsx
🟢 products/product_analytics/frontend/insights/activityDescriptions stays out of src/index.tsx
🟢 node_modules/@posthog/brand/dist/generated/hoggies/svg/ stays out of src/index.tsx
🟢 node_modules/@posthog/brand/dist/generated/hoggies/components/ stays out of src/index.tsx
🟢 node_modules/monaco-editor/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/layout/navigation-3000/navigationLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/scenes/dashboard/dashboardLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/lemon-ui/LemonMarkdown/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/components/RichContentEditor/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/components/CodeSnippet/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/taxonomy/core-filter-definitions-by-group.json stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 node_modules/zod/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/logic/billing/billingLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/components/ProductEmptyState/productSetupPreloadLogic.ts stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 node_modules/kea-test-utils/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 node_modules/monaco-editor/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 products/product_analytics/frontend/insights/activityDescriptions stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/kea-test-utils/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 products/dashboards/frontend/widgets/previews/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/session-recordings/player/sessionRecordingPlayerLogic.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/layout/panel-layout/ProjectTree/menus/SessionReplayMenuItems.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/taxonomy/core-filter-definitions-by-group.json stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/layout/navigation/projectNoticeLogic.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/layout/navigation/ImpersonationNotice/ImpersonationNotice.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/cohorts/cohortSavedToast.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 products/wizard/frontend/runs/WizardRunDetailsDrawer.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/layout/today/TodayShell.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/layout/today/TodayContextPanelFloating.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/layout/today/TodaySidePanel.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/layout/today/TodayTopBar.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/layout/today/todayRailItems.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 products/subscriptions/frontend/components/Subscriptions/exportNudge/exportNudgeLogic.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/billing/paymentEntryLogic.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 products/conversations/frontend/components/SidePanel/sidepanelTicketsLogic.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/zod/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/authentication/auth/loginLogic.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/authentication/shared/passkeyLogic.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/cohorts/CohortFilters/constants.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 products/persons/frontend/logics/personsLogic.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/surveys/constants.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/@tiptap/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/prosemirror- stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/re2js/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/react-markdown/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/lib/components/Command/Command.tsx stays out of src/scenes/AuthenticatedShell.tsx
🟢 packages/quill/packages/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 zod/v4/locales/de.js stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/@posthog/brand/dist/generated/hoggies/svg/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/@posthog/brand/dist/generated/hoggies/components/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 packages/quill/packages/quill/dist/ stays out of src/scenes/dashboard/Dashboard.tsx
🟢 node_modules/@tiptap/ stays out of src/scenes/dashboard/Dashboard.tsx
🟢 node_modules/prosemirror- stays out of src/scenes/dashboard/Dashboard.tsx
🟢 node_modules/marked/ stays out of src/scenes/dashboard/Dashboard.tsx
🟢 node_modules/frimousse/ stays out of src/scenes/dashboard/Dashboard.tsx
🟢 src/scenes/session-recordings/playlist/SessionRecordingsPlaylist.tsx stays out of src/scenes/dashboard/Dashboard.tsx
🟢 src/scenes/web-analytics/tiles/WebAnalyticsTile.tsx stays out of src/scenes/dashboard/Dashboard.tsx
🟢 src/queries/validators.js stays out of src/scenes/dashboard/Dashboard.tsx
🟢 src/queries/web-analytics-validators.js stays out of src/scenes/dashboard/Dashboard.tsx
🟢 node_modules/re2js/ stays out of src/scenes/dashboard/Dashboard.tsx
🟢 node_modules/kea-test-utils/ stays out of src/scenes/dashboard/Dashboard.tsx
🟢 src/scenes/debug/HogDebug.tsx stays out of src/scenes/dashboard/Dashboard.tsx
🟢 src/queries/QueryEditor/QueryEditor.tsx stays out of src/scenes/dashboard/Dashboard.tsx
🟢 packages/quill/packages/quill/dist/ stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
🟢 src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
🟢 src/scenes/project-homepage/today/TodayReportPage.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
🟢 src/queries/Query/Query.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
🟢 packages/quill/packages/charts/ stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
🟢 packages/quill/packages/quill/dist/ stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
🟢 products/posthog_ai/frontend/components/tool/widgets/VisualizationWidget.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
🟢 products/posthog_ai/frontend/components/tool/widgets/RecordingsWidget.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
🟢 src/queries/Query/Query.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
🟢 products/posthog_ai/frontend/api/primitives.ts stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
🟢 src/scenes/notebooks/Notebook/notebookLogic.ts stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
🟢 packages/quill/packages/quill/dist/ stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 node_modules/@tiptap/ stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 node_modules/prosemirror- stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 node_modules/marked/ stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 node_modules/frimousse/ stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/scenes/session-recordings/playlist/SessionRecordingsPlaylist.tsx stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/scenes/web-analytics/tiles/WebAnalyticsTile.tsx stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/queries/validators.js stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/queries/web-analytics-validators.js stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 node_modules/re2js/ stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 node_modules/kea-test-utils/ stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/queries/nodes/InsightViz/InsightViz.tsx stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/queries/nodes/DataVisualization/DataVisualization.tsx stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/queries/nodes/WebOverview/WebOverview.tsx stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/scenes/debug/HogDebug.tsx stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/queries/QueryEditor/QueryEditor.tsx stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 packages/quill/packages/quill/dist/ stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 node_modules/@tiptap/ stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 node_modules/prosemirror- stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 node_modules/marked/ stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 node_modules/frimousse/ stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 src/scenes/web-analytics/LiveMetricsDashboard/LiveWebAnalyticsMetrics.tsx stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 products/product_analytics/frontend/insights/trends/WorldMap/countryVectors.tsx stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 src/queries/validators.js stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 node_modules/re2js/ stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 node_modules/kea-test-utils/ stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 src/scenes/debug/HogDebug.tsx stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 src/queries/QueryEditor/QueryEditor.tsx stays out of src/scenes/web-analytics/WebAnalyticsScene.tsx
🟢 packages/quill/packages/quill/dist/ stays out of src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
🟢 node_modules/@tiptap/ stays out of src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
🟢 node_modules/prosemirror- stays out of src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
🟢 node_modules/marked/ stays out of src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
🟢 src/scenes/settings/SettingsMap.tsx stays out of src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
🟢 @jspm/core/nodelibs/browser/fs stays out of src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
🟢 node_modules/re2js/ stays out of src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
🟢 node_modules/kea-test-utils/ stays out of src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
🟢 node_modules/d3/src/ stays out of src/scenes/session-recordings/detail/SessionRecordingDetail.tsx

Largest files eagerly shipped from src/index.tsx
Size File
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
24.6 KiB ../node_modules/.pnpm/buffer@6.0.3/node_modules/buffer/index.js
6.3 KiB ../node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.production.min.js
4.7 KiB ../node_modules/.pnpm/@jspm+core@2.1.0/node_modules/@jspm/core/nodelibs/browser/process.js
4.0 KiB ../node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/cjs/scheduler.production.min.js
1.9 KiB src/lib/utils/bootTiming.ts
1.7 KiB src/index.tsx
1.7 KiB ../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js
1.2 KiB src/RootErrorBoundary.tsx
1.1 KiB src/lib/utils/deferredAppContext.ts
Largest files eagerly shipped from src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
Size File
359.8 KiB ../node_modules/.pnpm/posthog-js@1.447.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
224.1 KiB ../node_modules/.pnpm/@posthog+icons@0.39.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
105.7 KiB src/products.tsx
87.4 KiB src/lib/api.ts
68.7 KiB src/lib/lemon-ui/icons/icons.tsx
41.9 KiB ../node_modules/.pnpm/@dnd-kit+core@6.0.8_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@dnd-kit/core/dist/core.esm.js
36.4 KiB ../node_modules/.pnpm/kea@4.0.0-pre.6_patch_hash=139b8d1f1304f9d9da452a9a1244c94ea679dbcb85687d8999563146879fb6f5_react@18.3.1/node_modules/kea/lib/index.cjs.js
28.5 KiB src/lib/constants.tsx
24.6 KiB ../node_modules/.pnpm/buffer@6.0.3/node_modules/buffer/index.js
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
Size File
359.8 KiB ../node_modules/.pnpm/posthog-js@1.447.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
224.1 KiB ../node_modules/.pnpm/@posthog+icons@0.39.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
105.7 KiB src/products.tsx
87.4 KiB src/lib/api.ts
68.7 KiB src/lib/lemon-ui/icons/icons.tsx
41.9 KiB ../node_modules/.pnpm/@dnd-kit+core@6.0.8_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@dnd-kit/core/dist/core.esm.js
36.4 KiB ../node_modules/.pnpm/kea@4.0.0-pre.6_patch_hash=139b8d1f1304f9d9da452a9a1244c94ea679dbcb85687d8999563146879fb6f5_react@18.3.1/node_modules/kea/lib/index.cjs.js
32.5 KiB src/lib/utils/eventUsageLogic.ts
28.5 KiB src/lib/constants.tsx
Largest files eagerly shipped from src/scenes/dashboard/Dashboard.tsx
Size File
359.8 KiB ../node_modules/.pnpm/posthog-js@1.447.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
224.1 KiB ../node_modules/.pnpm/@posthog+icons@0.39.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
115.8 KiB ../node_modules/.pnpm/posthog-js@1.447.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/surveys-preview.js
111.3 KiB ../packages/quill/packages/primitives/dist/index.js
105.7 KiB src/products.tsx
96.1 KiB ../packages/quill/packages/components/dist/index.js
87.4 KiB src/lib/api.ts
79.0 KiB src/scenes/dashboard/dashboardLogic.tsx
68.7 KiB src/lib/lemon-ui/icons/icons.tsx
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
Size File
359.8 KiB ../node_modules/.pnpm/posthog-js@1.447.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
224.1 KiB ../node_modules/.pnpm/@posthog+icons@0.39.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
111.3 KiB ../packages/quill/packages/primitives/dist/index.js
105.7 KiB src/products.tsx
87.4 KiB src/lib/api.ts
68.7 KiB src/lib/lemon-ui/icons/icons.tsx
68.5 KiB ../products/posthog_ai/frontend/logics/runStreamLogic.ts
41.9 KiB ../node_modules/.pnpm/@dnd-kit+core@6.0.8_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@dnd-kit/core/dist/core.esm.js
36.4 KiB ../node_modules/.pnpm/kea@4.0.0-pre.6_patch_hash=139b8d1f1304f9d9da452a9a1244c94ea679dbcb85687d8999563146879fb6f5_react@18.3.1/node_modules/kea/lib/index.cjs.js
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
Size File
359.8 KiB ../node_modules/.pnpm/posthog-js@1.447.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
224.1 KiB ../node_modules/.pnpm/@posthog+icons@0.39.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
111.3 KiB ../packages/quill/packages/primitives/dist/index.js
105.7 KiB src/products.tsx
87.4 KiB src/lib/api.ts
68.7 KiB src/lib/lemon-ui/icons/icons.tsx
68.5 KiB ../products/posthog_ai/frontend/logics/runStreamLogic.ts
41.9 KiB ../node_modules/.pnpm/@dnd-kit+core@6.0.8_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@dnd-kit/core/dist/core.esm.js
41.7 KiB src/scenes/hog-functions/sub-templates/sub-templates.ts
Largest files eagerly shipped from src/scenes/activity/explore/EventsScene.tsx
Size File
359.8 KiB ../node_modules/.pnpm/posthog-js@1.447.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
224.1 KiB ../node_modules/.pnpm/@posthog+icons@0.39.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
111.3 KiB ../packages/quill/packages/primitives/dist/index.js
105.7 KiB src/products.tsx
96.1 KiB ../packages/quill/packages/components/dist/index.js
87.4 KiB src/lib/api.ts
79.0 KiB src/scenes/dashboard/dashboardLogic.tsx
68.7 KiB src/lib/lemon-ui/icons/icons.tsx
68.5 KiB ../products/posthog_ai/frontend/logics/runStreamLogic.ts
Largest files eagerly shipped from src/scenes/web-analytics/WebAnalyticsScene.tsx
Size File
359.8 KiB ../node_modules/.pnpm/posthog-js@1.447.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
224.1 KiB ../node_modules/.pnpm/@posthog+icons@0.39.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
115.8 KiB ../node_modules/.pnpm/posthog-js@1.447.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/surveys-preview.js
111.3 KiB ../packages/quill/packages/primitives/dist/index.js
105.7 KiB src/products.tsx
96.1 KiB ../packages/quill/packages/components/dist/index.js
87.4 KiB src/lib/api.ts
79.0 KiB src/scenes/dashboard/dashboardLogic.tsx
68.7 KiB src/lib/lemon-ui/icons/icons.tsx
Largest files eagerly shipped from src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
Size File
359.8 KiB ../node_modules/.pnpm/posthog-js@1.447.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
321.1 KiB ../node_modules/.pnpm/posthog-js@1.447.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/rrweb.js
224.1 KiB ../node_modules/.pnpm/@posthog+icons@0.39.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
111.3 KiB ../packages/quill/packages/primitives/dist/index.js
105.7 KiB src/products.tsx
96.1 KiB ../packages/quill/packages/components/dist/index.js
87.4 KiB src/lib/api.ts
68.7 KiB src/lib/lemon-ui/icons/icons.tsx
68.5 KiB ../products/posthog_ai/frontend/logics/runStreamLogic.ts

Posted automatically by check-eager-graph · sizes are eager output bytes (shipped, post-tree-shake) from the esbuild metafile · part of #32479

✅ Frontend layers — no new upward imports, 0 removed

Static imports from a lower frontend layer into a higher one (layers, lowest first: kernel, shell, query, features). Compared with the base branch, so an import that a PR also adds to layer-baseline.txt still shows here. Sizes are the source bytes on the eager path of every logged-in page.

Layer Eager source bytes Δ vs base
kernel 2.98 MiB no change
shell 2.36 MiB no change
query 56.2 KiB no change
features 273.8 KiB no change

Download the interactive layer graph for this PR.

Posted automatically by check-layers

✅ Toolbar bundle — eager 2.43 MiB within budget

What the toolbar ships to customer pages, measured from the esbuild output (minified, post-tree-shake). The eager set is the entry plus everything statically imported from it — fetched before any feature runs; deferred chunks load lazily. The eager guardrail is 5.72 MiB. Each output file must also stay below 10 MB, where CloudFront stops compressing it. The module boundary is enforced separately by check-toolbar-graph.

Metric Size Δ vs base Budget
Eager (shipped)
entry + static imports
2.43 MiB · 19 files no change ████░░░░░░ 42.4% of 5.72 MiB
Deferred (lazy) 2.64 MiB · 44 files no change n/a — loads on demand
Loader dist/toolbar.js 1.2 KiB no change █░░░░░░░░░ 6.0% of 19.5 KiB
Largest eagerly-shipped chunks
Size File
967.3 KiB dist/toolbar/toolbar-app-EN4VBQSO.css
732.3 KiB dist/toolbar/chunk-chunk-NZJIZZGR.js
290.5 KiB dist/toolbar/chunk-chunk-CBC3BDP6.js
137.0 KiB dist/toolbar/chunk-chunk-IMBY5JRZ.js
131.8 KiB dist/toolbar/chunk-chunk-FQJO25M6.js
75.7 KiB dist/toolbar/toolbar-app-FUQNQ6B2.js
69.0 KiB dist/toolbar/chunk-chunk-BFAXZMC5.js
33.8 KiB dist/toolbar/chunk-chunk-6EBAJOMK.js
21.9 KiB dist/toolbar/chunk-chunk-CXVFVCKX.js
6.8 KiB dist/toolbar/chunk-chunk-RVLGRPCH.js

Posted automatically by check-toolbar-size · sizes are toolbar output bytes (shipped, post-tree-shake) from the esbuild metafile

✅ Dist folder size — 🔺 +53.8 KiB (+0.0%)

Total size of the built frontend/dist folder (all assets), compared against the base branch.

Total: 991.14 MiB · 🔺 +53.8 KiB (+0.0%)

ℹ️ MCP UI apps size — 35 app(s), 29918.4 KB JS

Built size of each MCP UI app (main.js + styles.css).

App JS CSS
debug 864.4 KB 222.2 KB
explain-chart 1143.1 KB 222.2 KB
action 793.1 KB 222.2 KB
action-list 855.4 KB 222.2 KB
cohort 792.1 KB 222.2 KB
cohort-list 854.4 KB 222.2 KB
email-template 792.0 KB 222.2 KB
error-details 797.0 KB 222.2 KB
error-issue 794.1 KB 222.2 KB
error-issue-list 856.6 KB 222.2 KB
experiment 852.5 KB 222.2 KB
experiment-list 856.2 KB 222.2 KB
experiment-results 854.4 KB 222.2 KB
feature-flag 854.8 KB 222.2 KB
feature-flag-list 858.5 KB 222.2 KB
feature-flag-testing 795.4 KB 222.2 KB
inline-scan 792.6 KB 222.2 KB
insight-actors 853.9 KB 222.2 KB
llm-costs 851.2 KB 222.2 KB
session-recording 794.4 KB 222.2 KB
survey 793.7 KB 222.2 KB
survey-global-stats 851.2 KB 222.2 KB
survey-list 856.1 KB 222.2 KB
survey-stats 851.2 KB 222.2 KB
trace-span 792.5 KB 222.2 KB
trace-span-list 855.3 KB 222.2 KB
vision-observation-list 854.5 KB 222.2 KB
workflow 792.4 KB 222.2 KB
workflow-list 854.8 KB 222.2 KB
workflow-setup-status 792.1 KB 222.2 KB
query-results 1114.5 KB 222.2 KB
render-ui 1218.8 KB 222.2 KB
visual-review-snapshots 797.0 KB 222.2 KB
workflow-data-suggestions 794.8 KB 222.2 KB
workflow-sending-rules 793.5 KB 222.2 KB

puemos added a commit that referenced this pull request Nov 7, 2026
"Add to home" in the insight menus now lives in #131365. This PR keeps the key numbers changes on the home page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Generated-By: PostHog Desktop
Task-Id: 731c158e-22b1-4b23-87e2-779c3453cb27
@posthog

posthog Bot commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

👋 Visual changes detected for this PR.

Review and approve in PostHog Visual Review

If these changes are unexpected, they may be caused by a flaky test or a broken snapshot on master. Don't approve — rerun the job or wait for a fix.

Install the Visual Review Chrome extension to see visual review results at the top of your pull requests.

Generated-By: PostHog Desktop
Task-Id: 731c158e-22b1-4b23-87e2-779c3453cb27
@posthog

posthog Bot commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

PostHog Review · Deep · reviewed 3a5dc0f

Posted 6 findings: 4 Should fix, 2 Consider.

Step Status Result
Prepare the diff done 5 files, 1 chunk
Pick perspectives done 3 perspectives
Run review passes done 7 issues (+1 blind-spot)
Merge overlapping findings done 8 → 6
Validate findings done 6 kept, 0 dismissed
Publish done 6 posted (view review)

puemos commented Nov 8, 2026

Copy link
Copy Markdown
Contributor Author

Closing: we decided not to ship "Add to home" from the insight menus for now.

@puemos puemos closed this Nov 8, 2026

@posthog posthog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See this review and its findings in PostHog Review.

<IconPlus />
Add to dashboard
</DropdownMenuItem>
{isHomePinnable(insight) && <AddToHomeMenuItem insight={insight} />}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 · Make the insight action reachable on wide layouts

This action exists only in SceneTitleSecondaryActions.menu. That component hides its menu trigger when the content container exceeds 5xl. Neither its wide-layout children nor InsightSceneMenuBar provides the new action. Users on wide insight pages cannot add or remove a home number. Add the action to InsightSceneMenuBar under TODAY_RAIL_NAV, or provide an overflow menu that remains available on wide layouts. Retain the existing eligibility and disabled-state checks.

Comment on lines +109 to +115
loadHomePins: async (): Promise<PulsePinApi[] | null> => {
try {
const { pins } = await todayPulsePinsRetrieve(String(values.currentProjectId))
return pins
} catch (error) {
if (error instanceof ApiError && error.status === 404) {
return []

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3 · Discard load results after the menu unmounts

This loader returns results without a breakpoint check. If the user closes and reopens the menu while its GET is pending, the old request can finish after the new request or a successful save. kea-loaders dispatches the old result to the same action path, which overwrites the new mount's homePins. I reproduced a successful pin disappearing from local state when the previous menu's GET finished. A later save can also remove that pin from storage. Accept the loader's breakpoint argument and call breakpoint() after the request completes, before returning pins. Check cancellation before returning the 404 fallback too. Follow the existing loadPulseRecentInsights pattern in todayHighlightsLogic.ts.

Comment on lines +38 to +40
isInsightVizNode(query) &&
isTrendsQuery(query.source) &&
HOME_PIN_DISPLAYS.includes(query.source.trendsFilter?.display ?? ChartDisplayType.ActionsLineGraph)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 · Reject daily trends with weekday filters before pinning

This predicate accepts daily trends with nonempty query.source.dateRange.daysOfWeek. However, products/product_analytics/backend/insight_series.py::_supports_series rejects these queries. The pin request succeeds and shows 'Added to home', but the home resolver returns no metric. Home then shows 'Could not load' and reserves one of the four slots for a number that Retry cannot load. Match the backend eligibility rule before offering Add to home. Reject nonempty dateRange.daysOfWeek when the normalized interval is day. Preserve support for weekly and monthly trends.

if (pinned) {
return pins.filter((pin) => pin.key !== key)
}
return [...pins, { key, name: insight.name || insight.derived_name || 'Untitled insight', dashboard_id: null }]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 · Preserve dashboard context when creating a pin

Pins from dashboard cards always save dashboard_id as null. The pin API uses this field to preserve dashboard context. In products/today/backend/logic/pinned.py, _insight selects the standalone query when this field is null. The home metric therefore drops dashboard property filters, tile overrides, and variables. For example, a dashboard filtered to one region produces an unfiltered home metric. Pass dashboardId from InsightMeta through AddToHomeButton and toggleHomePin into the saved pin. Keep null for standalone insights. Follow the existing TodayPulse pin action, which preserves metric.dashboard_id.

actions.setHomePinsSaving(true)
let saved: PulsePinApi[]
try {
saved = (await todayPulsePinsUpdate(String(values.currentProjectId), { pins: next })).pins

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3 · Keep pin requests within the insight's source project

The new card action also appears on CrossProjectTile cards, which pass projectId for an insight from another project. This request always targets currentProjectId. Pin keys contain only the insight's short_id, and get_insight_series resolves that identifier within the request's project. The save succeeds but creates an unavailable pin in the active project's home. A matching identifier can resolve to an unrelated insight instead. Hide or disable the action when the card's projectId differs from currentProjectId. Alternatively, pass the source project into the logic and scope both pin loading and saving to that project.

Comment on lines +151 to +155
const next = nextHomePins(pins, insight, pinned)
actions.setHomePinsSaving(true)
let saved: PulsePinApi[]
try {
saved = (await todayPulsePinsUpdate(String(values.currentProjectId), { pins: next })).pins

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 · Keep the save guard active after the menu closes

The menu closes after a click and unmounts homePinsLogic while the PUT can still be pending. Opening another menu creates fresh state with homePinsSaving=false and loads the previous pin list. A second pin then sends another replacement list that excludes the first pin. I reproduced this with controlled API promises: pinning A and then B stores only B, although both actions report success. Keep the shared logic mounted until each save completes, or move mutation state outside the popup lifecycle. Block subsequent mutations until the saved list is reconciled.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant