The export builds, and draws with the component sheet

`next build --webpack` stopped at react-native-svg asking for
@react-native/assets-registry/registry; the web registry lives in
react-native-web, so the alias points there and the gui packages are
transpiled.

The server renders @hanzo/ui through its node entry, which imports no CSS,
so the export shipped without the sheet and the page drew as bare HTML.
The root layout imports @hanzo/ui/styles.css, and the Zen faces from
@hanzo/design, so tokens, themes and component rules reach every page.

The typecheck runs before a build creates next-env.d.ts, so *.css imports
are declared for TypeScript 7. tsconfig carries the two values Next writes
on every build. The install stops on no prompt: both jest build scripts
are answered.

Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
zooqueen
2026-09-15 11:19:58 -07:00
co-authored by Hanzo Dev
parent eb82a8ee15
commit 74c97542a0
8 changed files with 38 additions and 22 deletions
+2 -2
View File
@@ -1,8 +1,8 @@
/* What is true of the DOCUMENT, and nothing else.
*
* Everything a component draws with — the palette, the type scale, the surface
* ladder, the tap-highlight reset, the smoothing — arrives with `<Hanzo>` in
* layout.tsx, which imports the design system's own stylesheet. Tabs declares
* ladder, the tap-highlight reset, the smoothing — arrives with
* `@hanzo/ui/styles.css`, imported ahead of this file in layout.tsx. Tabs declares
* no palette. It used to declare three tokens and use forty-one, and every
* undefined one became a stark white hairline against black; an app inventing
* a palette is how an estate ends up with several, none of them right.
+9 -3
View File
@@ -1,6 +1,12 @@
import type { ReactNode } from 'react';
import { Hanzo } from '@hanzo/ui';
import { colors } from '@hanzo/ui/core';
// The sheet every component draws with: design tokens, gui themes and component
// rules. Imported here because the server renders @hanzo/ui's node entry, which
// carries no CSS, so only a root import puts the sheet in the export.
import '@hanzo/ui/styles.css';
// The Zen faces. The sheet above names the family; the files ship in @hanzo/design.
import '@hanzo/design/tokens/fonts.css';
import './globals.css';
export const metadata = {
@@ -37,9 +43,9 @@ export const viewport = {
initialScale: 1,
};
// `Hanzo` is the whole setup: it carries the design tokens, the stylesheet and
// the theme every component resolves `$background` and `$borderColor` against.
// Dark by default, which is the identity — there is no switch here to flip.
// `Hanzo` carries the config and the theme every component resolves
// `$background` and `$borderColor` against. Dark by default, which is the
// identity — there is no switch here to flip.
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en">
+4
View File
@@ -0,0 +1,4 @@
// A stylesheet import is resolved by the bundler, never by TypeScript. TS 7
// reports one it cannot resolve as TS2882, and next-env.d.ts, which declares
// them, exists only after a build, so the typecheck that runs first needs this.
declare module '*.css';
+8 -6
View File
@@ -8,19 +8,21 @@ export default {
output: 'export',
trailingSlash: true,
images: { unoptimized: true },
// The gui packages ship untranspiled ESM resolved against react-native.
transpilePackages: ['@hanzo/gui', '@hanzo/ui', 'react-native-web'],
// @hanzo/ui renders through @hanzo/gui, which is React Native's component
// model. On web `react-native` IS `react-native-web`, and the packages that
// reach for the former (@hanzogui/sheet, the icon set's svg backend) resolve
// to real React Native without this — a Flow-typed source webpack cannot
// parse. The `.web.*` extensions are the other half: a package that ships a
// web variant beside its native one is asking to be chosen by extension.
//
// react-native is pinned to 0.83 for a reason that is not cosmetic: 0.84
// renamed `@react-native/assets-registry` to `@react-native/asset-utils`, and
// react-native-svg 15 — which the gui icon set pulls in — still imports the
// old name. The pair does not resolve, and the build stops.
webpack(config) {
config.resolve.alias = { ...config.resolve.alias, 'react-native$': 'react-native-web' };
config.resolve.alias = {
...config.resolve.alias,
'react-native$': 'react-native-web',
// react-native-svg reads the asset registry; the web one lives here.
'@react-native/assets-registry/registry': 'react-native-web/dist/modules/AssetRegistry',
};
config.resolve.extensions = [
'.web.tsx',
'.web.ts',
+1
View File
@@ -15,6 +15,7 @@
"react-hook-form": "catalog:"
},
"devDependencies": {
"@hanzo/design": "catalog:",
"@hanzo/gui": "catalog:",
"@hanzo/iam": "catalog:",
"@hanzo/ui": "catalog:",
+7 -7
View File
@@ -6,6 +6,9 @@ settings:
catalogs:
default:
'@hanzo/design':
specifier: 0.5.24
version: 0.5.24
'@hanzo/gui':
specifier: 8.3.1
version: 8.3.1
@@ -67,6 +70,9 @@ importers:
specifier: 'catalog:'
version: 7.88.0([email protected])
devDependencies:
'@hanzo/design':
specifier: 'catalog:'
version: 0.5.24
'@hanzo/gui':
specifier: 'catalog:'
version: 8.3.1([email protected]([email protected]))([email protected](@babel/[email protected]([email protected]))(@react-native/[email protected](@babel/[email protected]([email protected]))([email protected]))(@types/[email protected])([email protected])([email protected]))([email protected])
@@ -571,10 +577,6 @@ packages:
'@hanzo/gui': '>=7.2.2'
react: '>=19'
'@hanzo/[email protected]':
resolution: {integrity: sha512-MmIjXUYHHFi6aG8qOpmrUEp4dWjHMxT9i4CxEH7uczHE5AMhCidgiIbnq5hdbLuXvBIbPh2En45C8znq4A8QcA==}
hasBin: true
'@hanzo/[email protected]':
resolution: {integrity: sha512-eXoD1Q3giJ3TEx2+rtCub/xZX5j4AflWixt3TXsf3dcYrWuChxSVhzRQdDWyibXzPPtn+msCtLX11IvvcHHUzw==}
hasBin: true
@@ -4218,7 +4220,7 @@ snapshots:
'@hanzo/[email protected]([email protected])':
dependencies:
'@hanzo/design': 0.5.23
'@hanzo/design': 0.5.24
react: 19.2.8
'@hanzo/[email protected]([email protected])':
@@ -4236,8 +4238,6 @@ snapshots:
- react-dom
- react-native-svg
'@hanzo/[email protected]': {}
'@hanzo/[email protected]': {}
'@hanzo/[email protected]([email protected])':
+5 -2
View File
@@ -2,6 +2,7 @@ minimumReleaseAgeExclude:
- '@hanzo/[email protected]'
catalog:
'@hanzo/design': '0.5.24'
'@hanzo/gui': '8.3.1'
'@hanzo/iam': '0.21.17'
'@hanzo/ui': '8.27.2'
@@ -21,6 +22,8 @@ catalog:
overrides:
'@noble/hashes': '1.8.0'
'zod': '^4.5.2'
# What may run its own install script. Both are jest's, and both only fetch a
# native binary that pnpm already installs as a platform package.
allowBuilds:
'@parcel/watcher': set this to true or false
unrs-resolver: set this to true or false
'@parcel/watcher': false
unrs-resolver: false
+2 -2
View File
@@ -11,7 +11,7 @@
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"jsx": "react-jsx",
"incremental": true,
"plugins": [{ "name": "next" }],
"paths": { "@/*": ["./*"] },
@@ -22,6 +22,6 @@
// before the bump hid it, so the count looked the same either way.
"types": ["jest", "node"]
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", ".next/dev/types/**/*.ts"],
"exclude": ["node_modules"]
}