mirror of
https://github.com/hanzoai/sites.git
synced 2026-10-30 18:22:43 +00:00
The four are not four applications. They are one application whose `module` is a
value read off the hostname, because the thing behind all four — the framework
DocType engine — already treats an app lane as a module tag over a registry. The
first DNS label picks the site; the registered domain picks the brand. Keeping
those two resolutions apart is why erp.zoo.ngo is an ordinary sentence and not a
special case.
The renderer is @hanzo/ui/framework (list / detail / form from DocType metadata
alone), so this repo holds no per-module code and adding a fifth product is one
entry in SITES plus a DNS record. Auth is the console's IAM PKCE path — the access
token is the only credential, and cloud derives the org from its membership claim,
so this app never chooses a tenant.
Proven locally against a real cloud binary serving /v1/framework: nine Playwright
cases sign in through the app's own button and photograph all four hosts at 390x844
and 1440x900, asserting real records are on screen and that nothing scrolls
sideways on a phone.
Found on the way: @hanzo/brand's getBrand() takes a HOST, not a brand id, so
getBrand('lux') silently returns the Hanzo brand — every white-label caller keying
it by id is quietly wrong.
Co-authored-by: Hanzo Dev <[email protected]>
38 lines
1.5 KiB
JavaScript
38 lines
1.5 KiB
JavaScript
/**
|
|
* @hanzo/gui is consumed at runtime (Next's own `transpilePackages` + the
|
|
* provider's runtime CSS injection) — the same arrangement the console uses and
|
|
* for the same reason: the published gui next-plugin has a broken dependency,
|
|
* and the optimizing compiler is an optimization, not a requirement.
|
|
*/
|
|
import { readdirSync } from 'node:fs'
|
|
import { fileURLToPath } from 'node:url'
|
|
import { dirname, join } from 'node:path'
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
|
|
/** Every installed `@hanzogui/*`, discovered rather than hardcoded. */
|
|
function guiPackages() {
|
|
try {
|
|
return readdirSync(join(__dirname, 'node_modules', '@hanzogui')).map((n) => `@hanzogui/${n}`)
|
|
} catch {
|
|
return []
|
|
}
|
|
}
|
|
|
|
/** @type {import('next').NextConfig} */
|
|
export default {
|
|
reactStrictMode: true,
|
|
// The dev overlay badge floats over the UI and would sit in every screenshot.
|
|
devIndicators: false,
|
|
transpilePackages: ['@hanzo/gui', '@hanzo/ui', '@hanzo/data', '@hanzo/iam', 'react-native-web', ...guiPackages()],
|
|
experimental: { esmExternals: true },
|
|
webpack: (config) => {
|
|
config.resolve.alias = { ...config.resolve.alias, 'react-native$': 'react-native-web' }
|
|
// `.web.*` FIRST is what makes the react-native ecosystem resolve its web
|
|
// variants. Without it, a package like react-native-svg resolves its native
|
|
// entry and webpack chokes on React Native's Flow source.
|
|
config.resolve.extensions = ['.web.tsx', '.web.ts', '.web.jsx', '.web.js', ...config.resolve.extensions]
|
|
return config
|
|
},
|
|
}
|