Skip to content

fix(frontend): enable /inbox and /code routes to embed Terragon via iframe#984

Open
vdimarco wants to merge 1 commit into
masterfrom
fix/inbox-code-embedding-routes
Open

fix(frontend): enable /inbox and /code routes to embed Terragon via iframe#984
vdimarco wants to merge 1 commit into
masterfrom
fix/inbox-code-embedding-routes

Conversation

@vdimarco

@vdimarco vdimarco commented Feb 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Remove /inbox and /code redirects from redirects.ts that were bypassing the iframe embedding
  • Update /code/page.tsx to re-export /inbox/page (same Terragon embedding)
  • Update /code/layout.tsx with InboxLayoutClient for full-height iframe rendering
  • Add /code route to CSP frame-ancestors headers in next.config.ts

Problem

The /inbox and /code routes had redirects configured that immediately sent users to the external Terragon Railway URL (https://terragon-www-production.up.railway.app/dashboard). This bypassed the page components that embed Terragon via iframe with proper postMessage authentication.

Solution

Removed the redirects so the page components are served instead. Now both /inbox and /code properly embed Terragon with:

  • Iframe with ?embed=true&awaitAuth=true parameters
  • postMessage authentication flow
  • Proper CSP headers to allow embedding

Test plan

  • Visit /inbox - should show embedded Terragon inbox (not redirect)
  • Visit /code - should show embedded Terragon inbox (not redirect)
  • Authentication should work via postMessage
  • Both pages should have proper full-height layout

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Updates
    • Reconfigured the /code route with updated branding, messaging, and layout.
    • Enhanced security headers for iframe embedding capabilities on the /code route.
    • Modified route handling and removed obsolete redirects for improved page routing.

Greptile Summary

Removed redirects for /inbox and /code routes to enable proper Terragon iframe embedding with postMessage authentication.

Key Changes:

  • Removed /inbox and /code redirects from redirects.ts that were bypassing page components
  • Updated /code/page.tsx to re-export /inbox/page for consistent Terragon embedding
  • Modified /code/layout.tsx to use InboxLayoutClient for full-height iframe rendering
  • Added /code route to CSP frame-ancestors headers in next.config.ts to allow embedding from trusted GatewayZ origins

Technical Implementation:

  • Both routes now properly embed Terragon via iframe with embed mode and authentication parameters
  • Authentication flows via secure postMessage API instead of URL parameters
  • CSP headers restrict embedding to trusted origins only

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • All changes are well-structured and follow existing patterns. The PR correctly removes redirects to enable iframe embedding, updates the /code route to reuse the /inbox implementation, and adds proper CSP headers for security. The implementation is consistent with the existing /inbox setup and includes appropriate comments explaining the changes.
  • No files require special attention

Important Files Changed

Filename Overview
src/config/redirects.ts Removed /inbox and /code redirects to allow page components to embed Terragon via iframe
src/app/code/page.tsx Changed to re-export /inbox/page instead of /claude-code/page for Terragon embedding
src/app/code/layout.tsx Updated to use InboxLayoutClient for full-height iframe rendering and improved metadata
next.config.ts Added /code route to CSP frame-ancestors headers to allow embedding from trusted origins

Last reviewed commit: 35164a4

…frame

Previously, /inbox and /code had redirects that bypassed the iframe
embedding page, sending users directly to the external Terragon URL.
This broke the postMessage authentication flow.

Changes:
- Remove /inbox and /code redirects from redirects.ts
- Update /code/page.tsx to re-export /inbox/page (same embedding)
- Update /code/layout.tsx with InboxLayoutClient for full-height iframe
- Add /code route to CSP frame-ancestors in next.config.ts

Now both routes serve the embedded Terragon inbox with proper auth.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

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

vercel Bot commented Feb 23, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
gatewayz-frontend Ready Ready Preview, Comment Feb 23, 2026 4:04am

@coderabbitai

coderabbitai Bot commented Feb 23, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

The /code route is reconfigured to embed the Terragon inbox via iframe instead of serving Claude Code. CSP headers are added to allow iframe embedding from trusted origins, static redirects are removed to enable page-based embedding, and layout/metadata are updated accordingly.

Changes

Cohort / File(s) Summary
Security Headers Configuration
next.config.ts
Adds new header rule for /code route to permit iframe embedding from trusted GatewayZ origins with CSP frame-ancestors policy, mirroring existing /inbox rule.
Routing & Redirects
src/config/redirects.ts
Removes static redirects for /inbox and /code paths to TERRAGON_DASHBOARD_URL; adds explanatory note indicating these routes are handled by page components embedding Terragon via iframe.
Code Route Layout & Page Components
src/app/code/layout.tsx, src/app/code/page.tsx
Wraps code route children with InboxLayoutClient for full-height inbox-style layout; re-exports inbox page content from /code route instead of claude-code content; updates metadata (title, description, OpenGraph, Twitter card) to reflect embedding behavior.

Possibly related PRs

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 The code route now hops through iframe gates,
With CSP headers that seal the fates,
No more redirects shall lead astray,
Just inbox views in embedded display!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main objective of the changeset: enabling iframe embedding of Terragon on both /inbox and /code routes by removing redirects and adding necessary configuration.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/inbox-code-embedding-routes

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@blacksmith-sh

blacksmith-sh Bot commented Feb 23, 2026

Copy link
Copy Markdown
Contributor

Found 33 test failures on Blacksmith runners:

Failures

Test View Logs
ModelsClient Multi-Provider - Pricing Normalization › Price filtering with normalized p
rices/should filter models by price range correctly
View Logs
Next.js config redirects › /code redirect/
should not have host-based restriction (redirects for all hosts)
View Logs
Next.js config redirects › /code redirect/should use temporary redirect (not permanent) View Logs
Next.js config redirects › /inbox redirect/
should not have host-based restriction (redirects for all hosts)
View Logs
Next.js config redirects › /inbox redirect/
should use temporary redirect (not permanent)
View Logs
Organization Page - Pricing Display › Price filtering/
should filter models by price range correctly
View Logs
src/tests/next-config-redirects.test.ts/should have a redirect rule for /code View Logs
src/tests/next-config-redirects.test.ts/should have a redirect rule for /inbox View Logs
src/tests/next-config-redirects.test.ts/
should not have host-based restriction (redirects for all hosts)
View Logs
src/tests/next-config-redirects.test.ts/should redirect /code to Terragon dashboard View Logs
src/tests/next-config-redirects.test.ts/should redirect /
inbox to Terragon dashboard
View Logs
src/tests/next-config-redirects.test.ts/
should use temporary redirect (not permanent)
View Logs
src/app/models/[...name]/tests/pricing-display.test.tsx/
should display correct pricing for providers from different gateways
View Logs
src/app/models/[...name]/tests/pricing-display.test.tsx/
should format OneRouter per-token pricing for display
View Logs
src/app/models/[...name]/tests/pricing-display.test.tsx/
should format OpenRouter per-token pricing for display
View Logs
src/app/models/[...name]/tests/pricing-display.test.tsx/
should handle various pricing formats from OneRouter
View Logs
src/app/models/[...name]/tests/pricing-display.test.tsx/
should handle various pricing formats from OpenRouter
View Logs
src/app/models/[...name]/tests/pricing-display.test.tsx/
should handle very large prices
View Logs
src/app/models/[...name]/tests/pricing-display.test.tsx/
should handle very small prices
View Logs
src/app/models/tests/models-client-multi-provider.test.tsx/
should display correct pricing for OneRouter models (per-token format)
View Logs
src/app/models/tests/models-client-multi-provider.test.tsx/
should display correct pricing for OpenRouter models (per-token format)
View Logs
src/app/models/tests/models-client-multi-provider.test.tsx/
should filter models by price range correctly
View Logs
src/app/models/tests/models-client.test.tsx/
should display pricing correctly in table view
View Logs
src/app/models/tests/models-client.test.tsx/
should display same price for equivalent models from different gateways
View Logs
src/app/models/tests/models-client.test.tsx/
should filter models correctly regardless of gateway pricing format
View Logs
src/app/models/tests/models-client.test.tsx/
should format pricing correctly for OneRouter (per-token format)
View Logs
src/app/models/tests/models-client.test.tsx/
should format pricing correctly for OpenRouter (per-token format)
View Logs
src/app/organizations/[name]/tests/pricing-display.test.tsx/
should filter models by price range correctly
View Logs
src/app/organizations/[name]/tests/pricing-display.test.tsx/
should format pricing correctly for OneRouter models
View Logs
src/app/organizations/[name]/tests/pricing-display.test.tsx/
should format pricing correctly for OpenRouter models
View Logs
src/app/organizations/[name]/tests/pricing-display.test.tsx/
should handle models with numeric pricing values
View Logs
src/lib/tests/model-detail-utils.test.ts/
should convert pricing from per-million to per-token format for standard gateways
View Logs
src/lib/tests/model-detail-utils.test.ts/
should convert pricing to per-token format for all gateways (unified format)
View Logs

Fix in Cursor

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
src/app/code/layout.tsx (2)

2-2: Consider moving InboxLayoutClient to a shared location.

Importing InboxLayoutClient from a sibling route (../inbox/inbox-layout-client) creates an inter-route dependency. If the inbox route is restructured or removed, this import breaks. A shared path like src/components/layouts/InboxLayoutClient (or src/app/_shared/) would give this component a stable home for reuse across routes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/code/layout.tsx` at line 2, Move the InboxLayoutClient component out
of the sibling route and into a stable shared location (e.g.,
src/components/layouts/InboxLayoutClient or src/app/_shared/InboxLayoutClient),
then update imports that reference InboxLayoutClient in layout.tsx and any other
files to the new path; ensure the component's export (named or default) is
preserved in the new file so references to InboxLayoutClient still resolve.

10-10: Hardcoded site URL violates the environment-variable guideline.

url: 'https://gatewayz.ai/code' is baked in; staging/preview deployments will emit incorrect canonical OG URLs. Per coding guidelines, all configuration values should use environment variables prefixed with NEXT_PUBLIC_.

♻️ Proposed fix
-    url: 'https://gatewayz.ai/code',
+    url: `${process.env.NEXT_PUBLIC_SITE_URL ?? 'https://gatewayz.ai'}/code`,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/code/layout.tsx` at line 10, Replace the hardcoded url value with an
env var: use process.env.NEXT_PUBLIC_SITE_URL (or a new NEXT_PUBLIC_SITE_URL)
and append the path segment '/code' when building the URL so staging/preview
picks up the correct domain; update the metadata creation in layout.tsx (the
object containing url: 'https://gatewayz.ai/code') to compute url:
`${process.env.NEXT_PUBLIC_SITE_URL}/code` (optionally provide a sensible
fallback) so canonical/OG URLs are driven by NEXT_PUBLIC_ env vars.
next.config.ts (1)

155-177: Extract the shared frame-ancestors CSP value into a named constant.

The same Content-Security-Policy value is now duplicated verbatim between the /inbox rule (line 162) and the new /code rule (line 174). A single origin list edit (e.g., adding a staging domain) must now be made in two places.

♻️ Proposed refactor
+      // Trusted origins that may embed GatewayZ routes in an iframe
+      const trustedEmbedOrigins =
+        "frame-ancestors 'self' https://beta.gatewayz.ai https://gatewayz.ai https://www.gatewayz.ai https://inbox.gatewayz.ai";

       {
         source: '/inbox',
         headers: [
           ...commonSecurityHeaders,
           {
             key: 'Content-Security-Policy',
-            value: "frame-ancestors 'self' https://beta.gatewayz.ai https://gatewayz.ai https://www.gatewayz.ai https://inbox.gatewayz.ai",
+            value: trustedEmbedOrigins,
           },
         ],
       },
       {
         source: '/code',
         headers: [
           ...commonSecurityHeaders,
           {
             key: 'Content-Security-Policy',
-            value: "frame-ancestors 'self' https://beta.gatewayz.ai https://gatewayz.ai https://www.gatewayz.ai https://inbox.gatewayz.ai",
+            value: trustedEmbedOrigins,
           },
         ],
       },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@next.config.ts` around lines 155 - 177, The CSP frame-ancestors string is
duplicated in the headers for the '/inbox' and '/code' route rules; extract that
value into a single named constant (e.g., FRAME_ANCESTORS_CSP or
INBOX_FRAME_ANCESTORS) and reference the constant in both header objects instead
of embedding the literal, updating the header value assignments where key:
'Content-Security-Policy' is set and keeping the rest of the header arrays
(including ...commonSecurityHeaders) unchanged so a future origin list edit only
needs to change the constant.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/app/code/layout.tsx`:
- Line 16: openGraph.images[0].url and twitter.images[0] currently point to the
beta URL 'https://beta.gatewayz.ai/og-inbox.jpg' which can break the /code
social card; update both references (openGraph.images[0].url and
twitter.images[0]) to use either the production URL (e.g.,
'https://gatewayz.ai/og-inbox.jpg' or a dedicated '/code' image) or read the
base image host from an environment variable (e.g.,
NEXT_PUBLIC_SOCIAL_IMAGE_BASE) and compose the final path (e.g.,
`${process.env.NEXT_PUBLIC_SOCIAL_IMAGE_BASE}/og-code.jpg`) so both places use
the same, non-beta source.

---

Nitpick comments:
In `@next.config.ts`:
- Around line 155-177: The CSP frame-ancestors string is duplicated in the
headers for the '/inbox' and '/code' route rules; extract that value into a
single named constant (e.g., FRAME_ANCESTORS_CSP or INBOX_FRAME_ANCESTORS) and
reference the constant in both header objects instead of embedding the literal,
updating the header value assignments where key: 'Content-Security-Policy' is
set and keeping the rest of the header arrays (including
...commonSecurityHeaders) unchanged so a future origin list edit only needs to
change the constant.

In `@src/app/code/layout.tsx`:
- Line 2: Move the InboxLayoutClient component out of the sibling route and into
a stable shared location (e.g., src/components/layouts/InboxLayoutClient or
src/app/_shared/InboxLayoutClient), then update imports that reference
InboxLayoutClient in layout.tsx and any other files to the new path; ensure the
component's export (named or default) is preserved in the new file so references
to InboxLayoutClient still resolve.
- Line 10: Replace the hardcoded url value with an env var: use
process.env.NEXT_PUBLIC_SITE_URL (or a new NEXT_PUBLIC_SITE_URL) and append the
path segment '/code' when building the URL so staging/preview picks up the
correct domain; update the metadata creation in layout.tsx (the object
containing url: 'https://gatewayz.ai/code') to compute url:
`${process.env.NEXT_PUBLIC_SITE_URL}/code` (optionally provide a sensible
fallback) so canonical/OG URLs are driven by NEXT_PUBLIC_ env vars.

Comment thread src/app/code/layout.tsx
description: 'Delegate coding tasks to AI background agents. Run coding agents in parallel inside remote sandboxes with Claude Code, Codex, and more.',
images: [
{
url: 'https://beta.gatewayz.ai/og-inbox.jpg',

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

OG/Twitter image hosted on beta.gatewayz.ai with an inbox-specific filename.

Both openGraph.images[0].url and twitter.images[0] point to https://beta.gatewayz.ai/og-inbox.jpg. If the beta subdomain is deprecated or the image is updated only for inbox, the /code social card silently breaks. Consider either:

  • Using the production domain (https://gatewayz.ai/og-inbox.jpg) and/or a /code-specific image, or
  • Storing the base image URL in a NEXT_PUBLIC_ environment variable consistent with the site URL.

Also applies to: 28-28

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/code/layout.tsx` at line 16, openGraph.images[0].url and
twitter.images[0] currently point to the beta URL
'https://beta.gatewayz.ai/og-inbox.jpg' which can break the /code social card;
update both references (openGraph.images[0].url and twitter.images[0]) to use
either the production URL (e.g., 'https://gatewayz.ai/og-inbox.jpg' or a
dedicated '/code' image) or read the base image host from an environment
variable (e.g., NEXT_PUBLIC_SOCIAL_IMAGE_BASE) and compose the final path (e.g.,
`${process.env.NEXT_PUBLIC_SOCIAL_IMAGE_BASE}/og-code.jpg`) so both places use
the same, non-beta source.

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