Files
tabs/app/layout.tsx
T
zeekay 42cb7819b0 an icon, so the tab is not blank
The export declared no icon and the bucket had none to serve, so /favicon.ico
answered 404 and every Tabs pane sat behind a blank tab — in a product whose
whole premise is telling one tab from another.

public/ carries the Hanzo mark from @hanzo/brand as .svg and .ico, and the
layout declares both. The .ico is there because a browser asks for it whether
or not a page names one, and a bucket has no server to answer with anything
else.
2026-08-21 00:26:08 -07:00

50 lines
2.0 KiB
TypeScript

import type { ReactNode } from 'react';
import { colors } from '@hanzo/design';
import './globals.css';
export const metadata = {
metadataBase: new URL('https://tabs.hanzo.ai'),
title: { default: 'Hanzo Tabs', template: '%s — Hanzo Tabs' },
description: 'Keep tabs on your agents. A browser terminal workspace for machines you have linked.',
// Both files are the Hanzo mark from @hanzo/brand, copied into public/. The
// .ico is here because a browser asks for /favicon.ico whether or not a page
// declares one, and the bucket has no server to answer that with anything
// else — an undeclared icon is a 404 and a blank tab.
icons: {
icon: [
{ url: '/favicon.svg', type: 'image/svg+xml' },
{ url: '/favicon.ico', sizes: '48x48' },
],
},
openGraph: {
title: 'Hanzo Tabs — keep tabs on your agents',
description: 'Every shell your coding agents work in, split and tiled, from anywhere.',
url: 'https://tabs.hanzo.ai',
siteName: 'Hanzo Tabs',
},
};
export const viewport = {
// The browser chrome paints this before any stylesheet loads, so it is the one
// colour that cannot be a var() — it has to be a literal. Taking it from the
// token module rather than typing one keeps it the SAME literal the page then
// paints, which is what stops the address bar and the page disagreeing.
themeColor: colors.background,
// The workspace is full-bleed and the terminal owns the bottom edge.
viewportFit: 'cover' as const,
width: 'device-width',
initialScale: 1,
};
// No theme class on <html>: the tokens ARE the dark values at :root, and
// `.light` is what inverts them. A `dark` class selects nothing in either the
// design system or Tailwind here, so carrying one only suggests a switch that
// does not exist.
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en">
<body className="min-h-dvh bg-background text-foreground antialiased">{children}</body>
</html>
);
}