/* ======================================================================
KOREALM — App shell: top bar, role switcher, sidebar, router
Role modules register into window.KOREALM.roles[role] = { nav, Screen }
====================================================================== */
window.KOREALM = window.KOREALM || { roles: {} };
/* Randomized display name for the account menu (regenerated each load) */
const DISPLAY_NAME = (() => {
const first = ["Maya", "Leo", "Nadia", "Owen", "Priya", "Theo", "Zara", "Felix", "Imani", "Rohan"];
const last = ["Carter", "Nguyen", "Okafor", "Silva", "Hansen", "Moreau", "Patel", "Kowalski", "Reyes", "Doyle"];
return first[Math.floor(Math.random() * first.length)] + " " + last[Math.floor(Math.random() * last.length)];
})();
/* ---------------- Brand mark ---------------- */
function Logo({ size = 30, variant = "compact", onDark = false }) {
const isFull = variant === "full";
const src = isFull ? "logo-full.png" : "logo-compact.png";
const h = isFull ? 130 : 42;
const plate = onDark
? { background: "#ffffff", padding: isFull ? "20px 26px" : "12px 16px", borderRadius: 18, boxShadow: "0 16px 40px rgba(8,18,33,0.34)" }
: { background: "#ffffff", padding: "7px 13px", borderRadius: 12, border: "1px solid var(--line-2)", boxShadow: "var(--sh-1)" };
return (
);
}
/* ---------------- Role switcher ---------------- */
const ROLE_META = {
public: { label: "Public", icon: "search", path: "/", desc: "Marketing site & listings" },
tenant: { label: "Tenant", icon: "user", path: "/tenant", desc: "Renter workspace" },
landlord: { label: "Landlord", icon: "building", path: "/landlord", desc: "Owner workspace" },
admin: { label: "Admin", icon: "shield", path: "/admin", desc: "Operations console" },
};
/* ---------------- Route Dashboard (persona router) ---------------- */
function RouteSwitcher() {
const app = useApp();
const { session, setRole, db, me } = app;
const [open, setOpen] = useState(false);
const ref = useRef();
useEffect(() => {
const h = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
document.addEventListener("mousedown", h); return () => document.removeEventListener("mousedown", h);
}, []);
const cur = ROLE_META[session.role];
const subRoutes = (r) => {
if (r === "public") return 0;
try { const cfg = window.KOREALM.roles[r]; return cfg ? cfg.nav(db, me(r), app).length : 0; } catch (e) { return 0; }
};
return (
setOpen(o => !o)}>
Route
{cur.path}
{open && (
Route Dashboard
Switch the active persona route
{Object.keys(ROLE_META).map(r => {
const m = ROLE_META[r];
const active = session.role === r;
const n = subRoutes(r);
return (
{ setRole(r); setOpen(false); }}>
{m.label}
{active && active }
korealm.app{m.path}
{r === "public" ? "site" : n + " routes"}
);
})}
Each persona is served as an isolated route.
)}
);
}
/* ---------------- Route counting helper ---------------- */
function countRoutes(r, app) {
if (r === "public") return 0;
try { const cfg = window.KOREALM.roles[r]; return cfg ? cfg.nav(app.db, app.me(r), app).length : 0; } catch (e) { return 0; }
}
/* ---------------- Route Map landing (POC launcher) ---------------- */
function RouteLanding() {
const app = useApp();
const { setRole } = app;
const order = ["public", "tenant", "landlord", "admin"];
const total = order.reduce((s, r) => s + countRoutes(r, app), 0);
return (
POC · Route map
Where would you like to start?
Korealm serves each persona as an isolated route off a single origin. Choose a route to enter that workspace — you can switch anytime from the top bar.
korealm.app
production origin · {total} routes
online
{order.map(r => {
const m = ROLE_META[r];
const n = countRoutes(r, app);
return (
setRole(r)}>
{r === "public" ? "site" : n + " routes"}
{m.label}
korealm.app{m.path}
{m.desc}
Enter route
);
})}
Sandbox build · payments use a test gateway, no real charges occur.
);
}
/* ---------------- Account menu ---------------- */
function AccountMenu() {
const { session, db, me, actions, go, setRole } = useApp();
const [open, setOpen] = useState(false);
const ref = useRef();
useEffect(() => {
const h = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
document.addEventListener("mousedown", h); return () => document.removeEventListener("mousedown", h);
}, []);
const u = session.role === "public" ? null : me(session.role);
const displayName = u && u.registered ? u.name : DISPLAY_NAME;
return (
actions.reset()}>
{u ? (
setOpen(o => !o)}>
{displayName.split(" ")[0]}
{u.role}
) : (
go("auth", { mode: "signin" })}>Sign in
go("auth", { mode: "register" })}>Get started
)}
{open && u && (
{ setOpen(false); }}> Profile & settings
{ setOpen(false); }}> Notifications
{ setOpen(false); setRole("public"); }}> Sign out
)}
);
}
/* ---------------- Top bar ---------------- */
function TopBar() {
const { session, setRole } = useApp();
const launch = session.role === "launch";
return (
{!launch &&
}
{!launch && (
{session.role !== "public" &&
}
)}
);
}
/* ---------------- Page header ---------------- */
function PageHeader({ title, sub, actions, back, children }) {
return (
{back &&
{back.label}}
{title}
{sub &&
{sub}
}
{actions &&
{actions}
}
{children}
);
}
/* ---------------- Sidebar (dashboard roles) ---------------- */
function Sidebar({ role }) {
const app = useApp();
const { session, go, db, me } = app;
const cfg = window.KOREALM.roles[role];
const items = cfg.nav(db, me(role), app);
return (
);
}
/* ---------------- App body / router ---------------- */
function AppBody() {
const app = useApp();
const { session } = app;
const role = session.role;
if (role === "launch") {
return ;
}
if (role === "public") {
return ;
}
const cfg = window.KOREALM.roles[role];
const Screen = cfg.Screen;
return (
);
}
function Shell() {
return (
);
}
Object.assign(window, { Logo, PageHeader, Shell, ROLE_META });