feat(world): react/gui foundation — deps, isolated vite/tsconfig, tamagui config

This commit is contained in:
zeekay
2026-07-23 20:51:28 -07:00
parent 73ec6bafaa
commit 000019d5fd
8 changed files with 8939 additions and 301 deletions
+1
View File
@@ -2,6 +2,7 @@ node_modules/
.idea/
.planning/
dist/
dist-react/
.DS_Store
*.log
.env
+8789 -300
View File
File diff suppressed because it is too large Load Diff
+14
View File
@@ -7,6 +7,9 @@
"scripts": {
"lint:md": "markdownlint-cli2 '**/*.md'",
"dev": "vite",
"dev:react": "vite --config vite.react.config.ts",
"build:react": "vite build --config vite.react.config.ts",
"typecheck:react": "tsc -p tsconfig.react.json --noEmit",
"dev:tech": "VITE_VARIANT=tech vite",
"dev:finance": "VITE_VARIANT=finance vite",
"build": "tsc && vite build",
@@ -51,9 +54,13 @@
"@tauri-apps/cli": "^2.10.0",
"@types/d3": "^7.4.3",
"@types/maplibre-gl": "^1.13.2",
"@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3",
"@types/topojson-client": "^3.1.5",
"@types/topojson-specification": "^1.0.5",
"@vitejs/plugin-react": "^4.7.0",
"markdownlint-cli2": "^0.20.0",
"react-native": "^0.83.2",
"typescript": "^5.7.2",
"vite": "^6.0.7",
"vite-plugin-pwa": "^1.2.0",
@@ -66,7 +73,11 @@
"@deck.gl/layers": "^9.2.6",
"@deck.gl/mapbox": "^9.2.6",
"@hanzo/ai": "^0.2.1",
"@hanzo/brand": "^1.4.1",
"@hanzo/event": "^0.3.1",
"@hanzo/gui": "^7.3.0",
"@hanzogui/config": "^7.3.0",
"@hanzogui/shell": "^7.4.1",
"@upstash/redis": "^1.36.1",
"@xenova/transformers": "^2.17.2",
"d3": "^7.9.0",
@@ -76,6 +87,9 @@
"mapbox-gl": "^3.26.0",
"maplibre-gl": "^5.16.0",
"onnxruntime-web": "^1.23.2",
"react": "^19.2.8",
"react-dom": "^19.2.8",
"react-native-web": "^0.21.2",
"topojson-client": "^3.1.0"
}
}
+24
View File
@@ -0,0 +1,24 @@
// The ONE Tamagui runtime config for the React surface. We build on @hanzogui's
// canonical v4 preset (tokens + shorthands + themes) rather than hand-rolling a
// config, so world inherits the same design system as every other Hanzo product.
// Runtime-only: no compiler/extraction step is required — @hanzo/gui generates
// atomic styles at runtime, which is all this foundation slice needs. Brand
// theming (monochrome, --hanzo-accent:#fff) rides on top via CSS variables in
// theme.css; this config supplies the primitive scales the @hanzogui/* stacks,
// text, button and card components resolve against.
import { defaultConfig } from '@hanzogui/config/v4';
import { createGui } from '@hanzo/gui';
export const guiConfig = createGui(defaultConfig);
export type GuiConf = typeof guiConfig;
// Register the config type globally so @hanzogui/* primitives get token
// autocompletion and typed props against OUR config (one source of truth). The
// GuiCustomConfig interface is declared in @hanzogui/web — the augmentation must
// target THAT module for declaration merging to reach the components.
declare module '@hanzogui/web' {
interface GuiCustomConfig extends GuiConf {}
}
export default guiConfig;
+39
View File
@@ -0,0 +1,39 @@
/*
* Brand theming for the React surface. @hanzo/brand's variables.css supplies the
* canonical Hanzo token set (monochrome ramp, spacing, radii); world is the
* monochrome surface, so the accent collapses to white — one knob, set here.
* Imported once by the React entry so both the unified shell (HanzoAppHeader,
* which reads --hanzo-* / accent tokens) and our own React islands theme
* identically.
*/
@import '@hanzo/brand/styles/variables.css';
:root {
/* World is monochrome: the accent is white. This is the single brand knob the
shell + islands read; everything else inherits the brand ramp above. */
--hanzo-accent: #fff;
--hanzo-accent-rgb: 255, 255, 255;
}
/* The React foundation renders full-viewport, dark, no page scroll — the globe is
the hero and panels float over it, matching the vanilla surface. */
html,
body,
#react-root {
height: 100%;
margin: 0;
}
body {
background: #000;
color: #fff;
font-family:
-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial,
sans-serif;
overflow: hidden;
}
#react-root {
display: flex;
flex-direction: column;
}
+1 -1
View File
@@ -24,5 +24,5 @@
}
},
"include": ["src"],
"exclude": ["src/workers/ml.worker.ts"]
"exclude": ["src/workers/ml.worker.ts", "src/react"]
}
+11
View File
@@ -0,0 +1,11 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"jsx": "react-jsx",
"types": ["vite/client", "react", "react-dom"],
"noEmit": true,
"skipLibCheck": true
},
"include": ["src/react"],
"exclude": []
}
+60
View File
@@ -0,0 +1,60 @@
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { resolve } from 'node:path';
import { readFileSync } from 'node:fs';
// Dedicated Vite config for the React + @hanzo/gui (Tamagui) surface. It is fully
// separate from the shipping vanilla vite.config.ts so the two entries never
// interfere: `npm run build` still builds the vanilla app at index.html untouched,
// while `npm run build:react` builds THIS entry (index.react.html) into dist-react/.
//
// @hanzo/gui is consumed at runtime (no compile-time extraction needed for the
// foundation): @vitejs/plugin-react gives JSX + fast-refresh, and the three knobs
// Tamagui-on-web needs are set below — the react-native → react-native-web alias,
// React de-duplication, and the TAMAGUI_TARGET / __DEV__ defines.
const pkg = JSON.parse(readFileSync(resolve(__dirname, 'package.json'), 'utf8'));
const isDev = process.env.NODE_ENV !== 'production';
export default defineConfig({
root: __dirname,
define: {
__APP_VERSION__: JSON.stringify(pkg.version),
'process.env.TAMAGUI_TARGET': JSON.stringify('web'),
__DEV__: JSON.stringify(isDev),
},
plugins: [react()],
resolve: {
alias: {
'@': resolve(__dirname, 'src'),
// Tamagui/@hanzo/gui primitives resolve react-native APIs at runtime through
// react-native-web on the web.
'react-native': 'react-native-web',
},
// Never let a transitive copy split the React runtime — one instance each.
dedupe: ['react', 'react-dom', 'react-native-web'],
},
optimizeDeps: {
include: ['react', 'react-dom', 'react-dom/client', 'react-native-web'],
esbuildOptions: {
// react-native-web / some @hanzogui packages ship .js containing JSX.
loader: { '.js': 'jsx' },
},
},
build: {
outDir: 'dist-react',
emptyOutDir: true,
rollupOptions: {
input: resolve(__dirname, 'index.react.html'),
},
},
server: {
port: 5273,
},
});