Skip to content

feat(marketing): redesign the T3 Code website - #5452

Closed
shivamhwp wants to merge 1 commit into
pingdotgg:mainfrom
shivamhwp:agent/marketing-site-main
Closed

feat(marketing): redesign the T3 Code website#5452
shivamhwp wants to merge 1 commit into
pingdotgg:mainfrom
shivamhwp:agent/marketing-site-main

Conversation

@shivamhwp

@shivamhwp shivamhwp commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

The current marketing site does not clearly show how T3 Code works across desktop, web, and mobile, and its download flow does not distinguish release channels well.

This redesign gives the site a product-led story with a real interactive app demo, stage-aware Latest/Nightly/Dev presentation, dedicated desktop and mobile download paths, T3 Connect and multi-device sections, and refreshed legal and mobile documentation. The demo fixtures are isolated from normal app state, and the footer wordmark now follows the selected release channel.

Visual reference:

Verification:

  • vp run --filter @t3tools/marketing typecheck
  • vp test run apps/marketing/src/lib/releases.test.ts apps/web/src/branding.test.ts apps/web/src/demo/fixtures.test.ts apps/web/src/demo/seedState.test.ts apps/web/src/demo/server.test.ts packages/client-runtime/src/state/server.test.ts (56 tests)

Generated with GPT-5.6 in T3 Code through the Codex harness.


Note

Medium Risk
Marketing-only surface area is large (layout, download logic, build scripts), and the new workflow pushes commits to the default branch with a GitHub App token—worth validating permissions and that automated commits do not race with human merges.

Overview
Redesigns the T3 Code marketing site around a product-led story, Latest / Nightly / Dev release channels, and richer download and social metadata.

Site shell and downloadLayout.astro adds canonical/OG/Twitter tags, stage-aware favicons and accent colors, a layered blur nav, and a footer wordmark that follows the selected channel. The download page gains a channel picker (latest, nightly, or build-from-source dev), GitHub-backed asset resolution via findReleaseAssetUrl / fetchNightlyRelease, and explicit mobile store links.

Marketing assets pipelinedev/build run prepare:assets: build the web sidebar demo, then capture-demo-screenshots.mjs (Playwright) writes demo-states crops, og-source.png, and a WebGL-composited og-image.png from showcase-spec.json and og-studio-setup.json. sidebar-demo is gitignored; demo and mobile preview paths get cache headers in astro.config.mjs.

CI and docsmobile-showcase-screenshots.yml adds publish_marketing_preview, which on successful iOS+Android dark captures on the default branch copies screenshots into apps/marketing/public/mobile-states, writes source.json, and commits when images change. README documents mobile app links; LegalPage supports a simple layout variant.

Reviewed by Cursor Bugbot for commit 50e470c. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Redesign the T3 Code marketing website with a live demo iframe, release channel switching, and mobile app support

  • Replaces the marketing homepage hero with an interactive app demo iframe, animated provider name rotation, a swipeable mobile screenshot carousel, and a channel-aware CTA supporting Latest/Nightly/Dev stages.
  • Adds a fully in-memory demo backend in apps/web/src/demo/ that serves snapshots, threads, diffs, and VCS state over a fake WebSocket, allowing the embedded demo to run without a real server.
  • Introduces release channel switching across the site: selecting a channel updates the favicon, nav trigger, download links, and stage art; selection is persisted to localStorage and communicated to the demo iframe via postMessage.
  • Rewrites the download page with a stage picker that shows platform-specific assets for Latest/Nightly or source-clone instructions for Dev; mobile visitors see App Store / Google Play links.
  • Overhauls the Layout with canonical/OG/Twitter meta tags, a layered blur nav, and a reorganized footer; the GitHub star count is removed from the nav CTA.
  • Adds a build pipeline that compiles the web app as a sidebar demo bundle and captures OG screenshots via headless Chromium before each Astro dev/build run.
  • Risk: dev/build scripts now run prepare:assets (Vite build + Playwright screenshot capture) before Astro starts, which significantly increases cold-start time.
📊 Macroscope summarized 50e470c. 34 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted

🗂️ Filtered Issues

No issues evaluated.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 76a08c9e-e2a4-4645-9105-718b0141ce18

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Aug 5, 2026
Comment thread apps/web/src/demo/seed.ts
}
}
});
request.addEventListener("blocked", () => settle(false));

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.

🟡 Medium demo/seed.ts:138

When the blocked event fires, settle(false) marks the seed as failed but leaves the indexedDB.open request alive. If another tab then closes its connection and the blocked request proceeds, the success handler sees settled === true, calls database.close() on the newly-upgraded database, and returns without writing the catalog. The database is now upgraded but empty, so the app boots with no demo remote machines registered, and they only appear after a reload retries seeding. Consider calling request.abort() (or ignoring the result without closing in the already-settled branch) so a late success does not close an empty upgraded database.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/web/src/demo/seed.ts around line 138:

When the `blocked` event fires, `settle(false)` marks the seed as failed but leaves the `indexedDB.open` request alive. If another tab then closes its connection and the blocked request proceeds, the `success` handler sees `settled === true`, calls `database.close()` on the newly-upgraded database, and returns without writing the catalog. The database is now upgraded but empty, so the app boots with no demo remote machines registered, and they only appear after a reload retries seeding. Consider calling `request.abort()` (or ignoring the result without closing in the already-settled branch) so a late `success` does not close an empty upgraded database.

index 3f1c2aa..9e84b71 100644
--- a/apps/web/src/components/chat/ChatComposer.tsx
+++ b/apps/web/src/components/chat/ChatComposer.tsx
@@ -41,6 +41,9 @@ export function ChatComposer(props: ChatComposerProps) {

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.

🟠 High demo/fixtures.ts:676

The hunk headers in DEMO_COMPOSER_DIFF are inconsistent with their bodies. The first hunk declares @@ -41,6 +41,9 @@ (6 old lines, 9 new lines) but the body contains only 3 old lines and 6 new lines, and the new-file hunk declares 11 lines but supplies 7. A unified-diff parser relying on the header counts will reject or truncate the diff or assign incorrect line numbers when the composer demo's diff panel opens. Consider correcting the line counts in the hunk headers to match the actual body.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/web/src/demo/fixtures.ts around line 676:

The hunk headers in `DEMO_COMPOSER_DIFF` are inconsistent with their bodies. The first hunk declares `@@ -41,6 +41,9 @@` (6 old lines, 9 new lines) but the body contains only 3 old lines and 6 new lines, and the new-file hunk declares 11 lines but supplies 7. A unified-diff parser relying on the header counts will reject or truncate the diff or assign incorrect line numbers when the composer demo's diff panel opens. Consider correcting the line counts in the hunk headers to match the actual body.


// The browser preview surface needs the Electron desktop bridge, so the web
// demo showcases the right panel with the diff surface instead.
const DEMO_COMPOSER_DIFF = `diff --git a/apps/web/src/components/chat/ChatComposer.tsx b/apps/web/src/components/chat/ChatComposer.tsx

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.

🟡 Medium demo/fixtures.ts:672

The DEMO_COMPOSER_DIFF fixture only contains changes for ChatComposer.tsx and DropOverlay.tsx, but the thread-composer checkpoint metadata advertises ChatComposer.tsx, ChatView.tsx, and composerDraftStore.ts. When demoThreadDiff selects DEMO_COMPOSER_DIFF for thread-composer, the resulting diff omits ChatView.tsx and composerDraftStore.ts, so the displayed file summary disagrees with the actual diff content. Update DEMO_COMPOSER_DIFF so its changed files match the checkpoint's advertised file list.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/web/src/demo/fixtures.ts around line 672:

The `DEMO_COMPOSER_DIFF` fixture only contains changes for `ChatComposer.tsx` and `DropOverlay.tsx`, but the `thread-composer` checkpoint metadata advertises `ChatComposer.tsx`, `ChatView.tsx`, and `composerDraftStore.ts`. When `demoThreadDiff` selects `DEMO_COMPOSER_DIFF` for `thread-composer`, the resulting diff omits `ChatView.tsx` and `composerDraftStore.ts`, so the displayed file summary disagrees with the actual diff content. Update `DEMO_COMPOSER_DIFF` so its changed files match the checkpoint's advertised file list.

}
return this.removeProject(command.projectId);
}
default: {

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.

🟠 High demo/server.ts:458

dispatch silently no-ops on thread.pin and thread.unpin commands: both fall into the default case and return the current sequence without updating pinnedAt or emitting a stream event. SidebarV2's pin/unpin controls therefore do nothing in the demo. Consider adding cases that set/clear pinnedAt (and any related fields) and call upsertThread.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/web/src/demo/server.ts around line 458:

`dispatch` silently no-ops on `thread.pin` and `thread.unpin` commands: both fall into the `default` case and return the current sequence without updating `pinnedAt` or emitting a stream event. SidebarV2's pin/unpin controls therefore do nothing in the demo. Consider adding cases that set/clear `pinnedAt` (and any related fields) and call `upsertThread`.

const isDev = stage === "dev";
devSource?.toggleAttribute("hidden", !isDev);
desktopSections.forEach((section) => section.toggleAttribute("hidden", isDev));
mobileSection?.toggleAttribute("hidden", isDev);

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.

🟠 High pages/download.astro:228

When the user selects the Dev stage, applyStage hides the entire mobile section, so the App Store and Google Play download links disappear even though they are channel-independent. The picker is labeled "Desktop release channel," so selecting Dev should only replace the desktop platform cards with the build-from-source section — mobile downloads should remain available. Consider removing the mobileSection hide so only the desktop sections are toggled for the Dev stage.

Suggested change
mobileSection?.toggleAttribute("hidden", isDev);
desktopSections.forEach((section) => section.toggleAttribute("hidden", isDev));
🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/marketing/src/pages/download.astro around line 228:

When the user selects the Dev stage, `applyStage` hides the entire mobile section, so the App Store and Google Play download links disappear even though they are channel-independent. The picker is labeled "Desktop release channel," so selecting Dev should only replace the desktop platform cards with the build-from-source section — mobile downloads should remain available. Consider removing the `mobileSection` hide so only the desktop sections are toggled for the Dev stage.

return data;
}

export async function fetchNightlyRelease(): Promise<Release> {

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.

🟡 Medium lib/releases.ts:154

fetchNightlyRelease searches only the first 100 releases returned by RELEASES_API_URL and never follows GitHub pagination, so it throws No nightly release was found when the newest matching nightly falls outside that first page. Consider following Link/page pagination, or use a tagged nightly/latest endpoint to avoid relying on the first 100 entries.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/marketing/src/lib/releases.ts around line 154:

`fetchNightlyRelease` searches only the first 100 releases returned by `RELEASES_API_URL` and never follows GitHub pagination, so it throws `No nightly release was found` when the newest matching nightly falls outside that first page. Consider following `Link`/`page` pagination, or use a tagged nightly/latest endpoint to avoid relying on the first 100 entries.

Comment thread apps/web/src/demo/seed.ts
settle(true);
return;
}
const staleStores = ["shell", "thread", "server-config", "vcs-refs"].filter((store) =>

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.

🟠 High demo/seed.ts:167

When force is true, seedConnectionCatalog clears all stores (shell, thread, server-config, vcs-refs) and overwrites the entire catalog document with demoCatalogDocument(). Any visitor-added connections or credentials — and cached state for non-fixture environments — are silently deleted. The fix is to update only the demo-owned records instead of wholesale replacing the catalog and clearing every store.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/web/src/demo/seed.ts around line 167:

When `force` is `true`, `seedConnectionCatalog` clears all stores (`shell`, `thread`, `server-config`, `vcs-refs`) and overwrites the entire catalog document with `demoCatalogDocument()`. Any visitor-added connections or credentials — and cached state for non-fixture environments — are silently deleted. The fix is to update only the demo-owned records instead of wholesale replacing the catalog and clearing every store.

checkpoints.flatMap((checkpoint) => checkpoint.files).map((file) => [file.path, file]),
);
const diff =
threadId === "thread-composer" && fromTurnCount >= 1 && filesByPath.size > 0

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.

🟡 Medium demo/fixtures.ts:822

When demoReviewDiffPreview calls demoThreadDiff with fromTurnCount = 0, the DEMO_COMPOSER_DIFF fixture is skipped because the guard requires fromTurnCount >= 1. The composer full-review preview then falls back to generated diffs that omit DropOverlay.tsx, so opening the full review for the featured composer demo shows an incomplete diff. Consider dropping the fromTurnCount >= 1 condition (or handling 0 explicitly) so the full-diff path uses DEMO_COMPOSER_DIFF as intended.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/web/src/demo/fixtures.ts around line 822:

When `demoReviewDiffPreview` calls `demoThreadDiff` with `fromTurnCount = 0`, the `DEMO_COMPOSER_DIFF` fixture is skipped because the guard requires `fromTurnCount >= 1`. The composer full-review preview then falls back to generated diffs that omit `DropOverlay.tsx`, so opening the full review for the featured composer demo shows an incomplete diff. Consider dropping the `fromTurnCount >= 1` condition (or handling `0` explicitly) so the full-diff path uses `DEMO_COMPOSER_DIFF` as intended.

Comment thread apps/web/src/demo/seed.ts
* Opens the right panel (on the diff surface — the browser preview needs the
* desktop bridge) on the showcase threads for first-time visitors.
*/
function seedRightPanelState(force: boolean): boolean {

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.

🟡 Medium demo/seed.ts:203

When the fixture marker is stale, seedRightPanelState overwrites the entire persisted byThreadKey document — including all existing entries — instead of only replacing the fixture-owned showcase entries. A fixture-version change therefore deletes a returning visitor's panel visibility/layout for every thread (including unrelated or still-valid demo threads), despite seeding being intended to preserve visitor changes. The same wholesale-replace problem occurs in seedDiffPanelSelection, which discards all visitor-selected turns/files and branchBaseRefByThreadKey values. Both functions should merge the new fixture entries into the existing persisted state rather than replacing the whole document.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/web/src/demo/seed.ts around line 203:

When the fixture marker is stale, `seedRightPanelState` overwrites the entire persisted `byThreadKey` document — including all existing entries — instead of only replacing the fixture-owned showcase entries. A fixture-version change therefore deletes a returning visitor's panel visibility/layout for every thread (including unrelated or still-valid demo threads), despite seeding being intended to preserve visitor changes. The same wholesale-replace problem occurs in `seedDiffPanelSelection`, which discards all visitor-selected turns/files and `branchBaseRefByThreadKey` values. Both functions should merge the new fixture entries into the existing persisted state rather than replacing the whole document.

@cursor cursor 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.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 50e470c. Configure here.

"dev": "npm run prepare:assets && astro dev",
"build": "npm run prepare:assets && astro build",
"prepare:assets": "npm run build:sidebar-demo",
"build:sidebar-demo": "npm run --prefix ../web build:sidebar-demo && node scripts/capture-demo-screenshots.mjs",

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.

Demo build missing web deps

High Severity

Marketing build/dev now run build:sidebar-demo, which builds @t3tools/web into the gitignored public/sidebar-demo tree, but @t3tools/marketing does not depend on @t3tools/web. The Vercel install filter @t3tools/marketing... therefore never installs web’s packages, so the interactive hero demo cannot be produced in that environment and the marketing build fails.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 50e470c. Configure here.

@macroscopeapp

macroscopeapp Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

9 blocking correctness issues found. Diff is too large for automated approval analysis. A human reviewer should evaluate this PR.

You can customize Macroscope's approvability policy. Learn more.

@shivamhwp

Copy link
Copy Markdown
Collaborator Author

Superseded by #5457, now published from agent/marketing-core-value against main.

@shivamhwp shivamhwp closed this Aug 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant