feat(web): marketing theme toggle, site search palette, and phone dev access

- Theme toggle in the nav: follows the device until chosen, remembers the choice, sets data-theme before first paint (no flash).
- Site search: Cmd/Ctrl+K command palette on every marketing page, opened by the shortcut, a nav Search button, or the Docs search field. Searches pages, docs topics and articles that have a page.
- Docs topics move to content.ts so the page and the search index share one source.
- next.config: allowedDevOrigins for private network ranges so a phone on the same Wi-Fi hydrates the dev site. Dev only.
- Sun and moon icons added by hand (not Figma exports); noted in the icons README.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
SinachPat
2026-10-13 22:27:34 +01:00
co-authored by Claude Sonnet 5.5
parent 0cff3902b2
commit f69ce33dd0
21 changed files with 818 additions and 17 deletions
+10 -2
View File
@@ -2,6 +2,8 @@ import { GeistMono } from 'geist/font/mono';
import { GeistSans } from 'geist/font/sans';
import type { Metadata } from 'next';
import type { ReactNode } from 'react';
import { CommandPaletteProvider } from '../../src/marketing/CommandPalette.tsx';
import { themeInitScript } from '../../src/marketing/theme.ts';
import '../../src/styles/tokens.css';
import '../../src/styles/marketing.css';
import '../../src/styles/product.css';
@@ -13,8 +15,14 @@ export const metadata: Metadata = {
export default function MarketingLayout({ children }: { children: ReactNode }) {
return (
<html lang="en" className={`${GeistSans.variable} ${GeistMono.variable}`}>
<body>{children}</body>
// suppressHydrationWarning: the head script sets data-theme on <html> before React hydrates.
<html lang="en" className={`${GeistSans.variable} ${GeistMono.variable}`} suppressHydrationWarning>
<head>
<script dangerouslySetInnerHTML={{ __html: themeInitScript }} />
</head>
<body>
<CommandPaletteProvider>{children}</CommandPaletteProvider>
</body>
</html>
);
}