Skip to content

experiment(embed): bootable embedded mode for the webapp inside PostHog Code#71087

Draft
mariusandra wants to merge 2 commits into
masterfrom
code-embed-experiment
Draft

experiment(embed): bootable embedded mode for the webapp inside PostHog Code#71087
mariusandra wants to merge 2 commits into
masterfrom
code-embed-experiment

Conversation

@mariusandra

@mariusandra mariusandra commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

Experiment: run the webapp inside PostHog Code (desktop app)

Draft/experiment — not intended to merge as-is. User-approved companion to PostHog/code#3475, which consumes this branch.

Adds an embed vite entry that boots the full webapp inside an iframe hosted by the PostHog Code desktop app, which serves it behind a local same-origin proxy that injects the desktop's OAuth token into /api/* calls (so no CORS and no session cookie needed).

  • frontend/src/embed/index.tsx — new entry: clears JS_POSTHOG_API_KEY (posthog-js opts out, exporter/render-query pattern), sets __POSTHOG_EMBED__, reads ?__posthog_embed_theme=, dynamic-imports the main entry + the bridge.
  • frontend/src/embed/bridge.ts — postMessage protocol: host→iframe navigate (via router.actions.push) and setTheme; iframe→host ready and routeChanged. Also intercepts window.open and capture-phase clicks on <a target="_blank">: same-origin URLs forward to the host as openTab (the host opens them as its own browser tabs), external URLs keep native behavior.
  • themeLogic — new embedForcedTheme reducer checked first in isDarkModeOn, so the embedding host's theme wins over user/system preference.
  • navigationLogic — new embedMode reducer (seeded from __POSTHOG_EMBED__, same pattern as embedForcedTheme) that short-circuits the mode selector to 'none', the existing tested no-chrome path: no PanelLayout sidebar, no top bar, no SidePanel — the scene fills the iframe while all nav logics stay mounted.
  • Registered in frontend/vite.config.mts rollup inputs, so vite build emits it alongside exporter/render_query/toolbar.

Verified live from the desktop app against us.posthog.com: notebooks (including embedded insights executing queries), feature flags, and dashboards scenes render chrome-less; navigation, theme, and new-tab intents bridge both directions.

Known limitation surfaced by this experiment: DRF actions without required_scopes 403 under token auth — typed query subresources (/query/TrendsQuery/ etc.), tags, user_product_list. Fixing that class upstream would unlock Activity/Persons/insight-creation in embedded mode (and Python/DuckDB notebook cells in PostHog Code).

Screenshots (webapp running chrome-less inside the desktop app)

Embedded webapp, dark, chrome-less

Embedded webapp, light, two host tabs

🤖 Generated with Claude Code

EXPERIMENT: adds an `embed` vite entry that boots the full app inside an
iframe served by PostHog Code's local auth-injecting proxy. Tracking is
disabled (no JS_POSTHOG_API_KEY -> posthog-js opts out, exporter pattern),
and a postMessage bridge syncs navigation (kea-router push / locationChanged)
and theme both ways. themeLogic gains an embedForcedTheme override so the
host window's light/dark choice wins over user/system preference.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

🤖 CI report

Bundle size — 🟢 -7.8 KiB (-0.0%)

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

Total: 64.79 MiB · 🟢 -7.8 KiB (-0.0%)

File Size Δ vs base
exporter/src/exporter/scenes/ExporterDashboardScene.js 266.6 KiB 🟢 -5.4 KiB (-2.0%)
render-query/src/render-query/render-query.js 21.26 MiB 🟢 -2.1 KiB (-0.0%)

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.22 MiB · 22 files 🔺 +35 B (+0.0%) ███░░░░░░░ 28.4% of 4.29 MiB
authenticated shell (every logged-in page)
src/scenes/AuthenticatedShell.tsx
8.14 MiB · 2,979 files 🟢 -2.1 KiB (-0.0%) █████████░ 88.0% of 9.25 MiB

🟢 node_modules/monaco-editor/ stays out of src/index.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 node_modules/monaco-editor/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.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.5 KiB ../node_modules/.pnpm/@jspm+core@2.1.0/node_modules/@jspm/core/nodelibs/browser/process.js
3.9 KiB ../node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/cjs/scheduler.production.min.js
1.4 KiB ../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js
1.3 KiB src/RootErrorBoundary.tsx
912 B ../node_modules/.pnpm/ieee754@1.2.1/node_modules/ieee754/index.js
789 B src/scenes/ChunkLoadErrorBoundary.tsx
762 B src/index.tsx
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
Size File
281.1 KiB ../node_modules/.pnpm/posthog-js@1.401.0/node_modules/posthog-js/dist/rrweb.js
267.7 KiB ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
235.5 KiB src/taxonomy/core-filter-definitions-by-group.json
222.7 KiB ../node_modules/.pnpm/posthog-js@1.401.0/node_modules/posthog-js/dist/module.js
164.0 KiB src/queries/validators.js
154.3 KiB ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.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
106.1 KiB src/lib/api.ts
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js
92.7 KiB ../packages/quill/packages/quill/dist/index.js

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

Dist folder size — 🟢 -20.2 KiB (-0.0%)

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

Total: 1308.70 MiB · 🟢 -20.2 KiB (-0.0%)

- navigationLogic gains an embedMode reducer (seeded from
  window.__POSTHOG_EMBED__, like themeLogic's embedForcedTheme) that forces
  navigation mode 'none': no PanelLayout sidebar, no top bar, no side panel —
  scene content takes the full iframe. mode='none' is the existing tested
  path used by onboarding's hidden-navbar variants.
- embed bridge intercepts window.open and <a target="_blank"> clicks on
  same-origin URLs and forwards them to the host as `openTab` messages, so
  "open in new tab" affordances become host browser tabs instead of being
  dropped. External URLs keep native behavior; in-app kea-router pushes
  still navigate in place.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@trunk-io

trunk-io Bot commented Jul 15, 2026

Copy link
Copy Markdown

Static BadgeStatic BadgeStatic BadgeStatic Badge

View Full Report ↗︎Docs

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