Compare commits

...
Author SHA1 Message Date
lawrencecchen 05cd823370 Merge remote-tracking branch 'origin/main' into fix-app-pricing-nested-html 2026-07-07 22:35:06 -07:00
lawrencecchen 37ceabae0e Merge remote-tracking branch 'origin/main' into fix-app-pricing-nested-html 2026-07-07 21:38:55 -07:00
lawrencecchen a0e756e439 Retrigger Vercel preview again (queue starvation) 2026-07-07 21:27:56 -07:00
lawrencecchen 2b4d78964e Retrigger Vercel preview (queued deployment starved for 2h) 2026-07-07 20:26:21 -07:00
lawrencecchen 79eee0ecca Fix nested <html> in the app-pricing layout
web/app/layout.tsx became the root layout for every route, so
AppPricingLayout's own <html>/<head>/<body> now renders inside the root
<body>. Browsers reject html-in-body, React logs 'mounting a new html
component', and hydration fails, regenerating the tree on the client
(the in-app cmux Upgrade page flashed and the dev overlay showed 7
issues).

The layout keeps only what it added on top of the root layout: the
transparent-background CSS overrides and the transparent theme-color
(now a viewport export). The Geist font setup and globals.css import
were duplicates of the root layout, and the page already applies the
appearance/background query params itself.
2026-07-07 18:34:20 -07:00
+25 -35
View File
@@ -1,49 +1,39 @@
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "../globals.css";
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
});
import type { Metadata, Viewport } from "next";
export const metadata: Metadata = {
title: "cmux Upgrade",
description: "cmux upgrade pricing inside the cmux app.",
};
export const viewport: Viewport = {
themeColor: "transparent",
};
// Nested layout under the root layout (web/app/layout.tsx), which already
// renders <html>/<body> with the Geist font variables. Rendering another
// <html> here nests it inside <body> and breaks hydration, so this layout
// only contributes the transparent-background overrides the in-app pricing
// webview needs; the page applies the appearance/background query params on
// top of these light-theme defaults.
export default function AppPricingLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en" suppressHydrationWarning style={{ background: "transparent" }}>
<head>
<meta name="theme-color" content="transparent" />
<style>{`
:root {
--background: transparent;
--foreground: #171717;
--muted: #5f6368;
--border: rgba(0, 0, 0, 0.14);
--code-bg: rgba(245, 245, 245, 0.78);
--button-foreground: #ffffff;
}
html, body { background: transparent !important; }
`}</style>
</head>
<body
className={`${geistSans.variable} ${geistMono.variable} font-sans antialiased`}
style={{ background: "transparent" }}
>
{children}
</body>
</html>
<>
<style>{`
:root {
--background: transparent;
--foreground: #171717;
--muted: #5f6368;
--border: rgba(0, 0, 0, 0.14);
--code-bg: rgba(245, 245, 245, 0.78);
--button-foreground: #ffffff;
}
html, body { background: transparent !important; }
`}</style>
{children}
</>
);
}