import { installEkklesiaDesignTokens } from "@ekklesia/design-tokens"; import { EkklesiaUiStyles } from "@ekklesia/ui"; import { createRoot } from "react-dom/client"; import { consumeAuthLanding } from "../auth-protocol.js"; import { type EkklesiaHostConfig, resolveApiOrigin } from "../host-protocol.js"; import { HostApp } from "./HostApp.js"; /** * The one place the shell touches a browser global. * * The API that served this page wrote its own origin into `` * (ADR 0045): empty in the same-origin topology, the API's hostname when the Dashboard and the API * live on separate origins. Read at run time, so one built shell serves either topology. Everything * downstream receives the resolved origin as a plain argument, so no other file in this package * reads `window`. */ const apiBaseUrl = resolveApiOrigin( document.querySelector('meta[name="ekklesia-api-origin"]')?.content, window.location.origin, ); /** Read once, before anything renders, and stripped from the address bar in the same step. See * `consumeAuthLanding` for why the token must not stay in the URL. */ const authLanding = consumeAuthLanding(window.location, window.history); const container = document.getElementById("ekklesia-host"); if (!container) { throw new Error("The Ekklesia shell requires a #ekklesia-host element."); } /** * The host root installs the platform's default theme once, at the document (ADR 0039). * * This is what makes the tokens available to *everything* on the page, including each module UI * artifact mounted inside its own isolated root: CSS custom properties inherit through a shadow * boundary, so a module reads `var(--ekklesia-…)` without the host reaching into the artifact or the * artifact importing the host. Only the values live here — the platform ships no theme editor, and * an installation that wants different values overrides these declarations at its own root. */ installEkklesiaDesignTokens(document); /** * A page whose API origin is not a canonical origin fails closed: it makes no request at all, because * every request it would make carries credentials to an address it cannot vouch for. The message is * fixed and names no address. */ function renderHost(config: EkklesiaHostConfig | undefined) { if (!config) { return (
This page cannot start: the server address it was given is not valid.
); } return authLanding ? ( ) : ( ); } createRoot(container).render( <> {renderHost(apiBaseUrl === undefined ? undefined : { apiBaseUrl })} , );