From 3a82416dfa0c7eecbb1f2dcabbb0b5af7b93c3e1 Mon Sep 17 00:00:00 2001
From: Elliot Braem
Date: Thu, 13 Aug 2026 13:55:46 -0500
Subject: [PATCH 01/12] wip
---
.env.example | 3 -
api/src/contract.ts | 30 ++
.../db/migrations/0002_awesome_madame_web.sql | 3 +
api/src/db/migrations/meta/0002_snapshot.json | 176 ++++++++
api/src/db/migrations/meta/_journal.json | 9 +-
api/src/db/schema.ts | 13 +-
api/src/index.ts | 10 +
api/src/services/tenants.ts | 52 ++-
api/tests/unit/tenants-service.test.ts | 56 +++
bos.config.json | 3 -
host/.env.example | 3 -
host/src/services/binding-resolver.ts | 148 +++++++
host/src/services/tenant-runtime.ts | 164 +-------
.../integration/tenant-host-nested.test.ts | 45 ++-
host/tests/integration/tenant-runtime.test.ts | 322 ++++++++++-----
tests/regression/http/tenant_bindings_test.go | 184 +++++++++
ui/src/routes/_layout.tsx | 380 +-----------------
ui/src/routes/_layout/_authenticated.tsx | 251 +++++++++++-
.../_layout/_authenticated/admin/index.tsx | 104 +++++
.../_layout/_authenticated/admin/system.tsx | 73 ++++
ui/src/routes/_layout/_public.tsx | 53 +++
ui/src/routes/_layout/{ => _public}/about.tsx | 2 +-
ui/src/routes/_layout/_public/index.tsx | 111 +++++
ui/src/routes/_layout/{ => _public}/login.tsx | 50 +--
ui/src/routes/_layout/index.tsx | 122 ------
ui/src/routes/_layout/skill.tsx | 126 ------
26 files changed, 1563 insertions(+), 930 deletions(-)
create mode 100644 api/src/db/migrations/0002_awesome_madame_web.sql
create mode 100644 api/src/db/migrations/meta/0002_snapshot.json
create mode 100644 host/src/services/binding-resolver.ts
create mode 100644 tests/regression/http/tenant_bindings_test.go
create mode 100644 ui/src/routes/_layout/_authenticated/admin/index.tsx
create mode 100644 ui/src/routes/_layout/_authenticated/admin/system.tsx
create mode 100644 ui/src/routes/_layout/_public.tsx
rename ui/src/routes/_layout/{ => _public}/about.tsx (99%)
create mode 100644 ui/src/routes/_layout/_public/index.tsx
rename ui/src/routes/_layout/{ => _public}/login.tsx (86%)
delete mode 100644 ui/src/routes/_layout/index.tsx
delete mode 100644 ui/src/routes/_layout/skill.tsx
diff --git a/.env.example b/.env.example
index 450772d4..452789fd 100644
--- a/.env.example
+++ b/.env.example
@@ -3,9 +3,6 @@
# app.host
CORS_ORIGIN=http://localhost:4100
-TENANT_WHITELIST=
-ALLOW_OVERRIDE=
-ALLOW_UNTRUSTED_SSR=
CSP_STRICT=
# app.api
diff --git a/api/src/contract.ts b/api/src/contract.ts
index 5887408c..92bc79b2 100644
--- a/api/src/contract.ts
+++ b/api/src/contract.ts
@@ -20,6 +20,9 @@ export const TenantSchema = z.object({
orgId: z.string(),
name: z.string(),
status: TenantStatusSchema,
+ allowUiOverrides: z.boolean(),
+ allowBackendOverrides: z.boolean(),
+ allowSsr: z.boolean(),
createdAt: z.string(),
updatedAt: z.string(),
deletedAt: z.string().nullable(),
@@ -27,6 +30,17 @@ export const TenantSchema = z.object({
export type Tenant = z.infer;
+export const TenantBindingSchema = z.object({
+ hostname: z
+ .string()
+ .describe("Subdomain hostname that routes to this tenant on the parent domain"),
+ accountId: z.string(),
+ allowUiOverrides: z.boolean(),
+ allowBackendOverrides: z.boolean(),
+ allowSsr: z.boolean(),
+ status: TenantStatusSchema,
+});
+
const ThingSchema = z.object({
thingId: z.string().describe("Unique identifier for the thing"),
type: z.string().describe("Plugin-derived thing type"),
@@ -80,6 +94,9 @@ export const contract = oc.router({
name: z.string(),
accountId: z.string(),
status: z.enum(["active", "pending"]).optional(),
+ allowUiOverrides: z.boolean().default(true),
+ allowBackendOverrides: z.boolean().default(false),
+ allowSsr: z.boolean().default(false),
}),
)
.output(TenantSchema)
@@ -94,6 +111,9 @@ export const contract = oc.router({
subdomain: z.string().optional(),
accountId: z.string().optional(),
status: TenantStatusSchema.optional(),
+ allowUiOverrides: z.boolean().optional(),
+ allowBackendOverrides: z.boolean().optional(),
+ allowSsr: z.boolean().optional(),
}),
)
.output(TenantSchema)
@@ -128,6 +148,16 @@ export const contract = oc.router({
.output(TenantSchema)
.errors({ NOT_FOUND }),
+ listTenantBindings: oc
+ .route({
+ method: "GET",
+ path: "/tenants/bindings",
+ summary: "List all active tenant domain bindings",
+ description:
+ "Public — returns the subdomain-to-config mapping used by the host's BindingResolver.",
+ })
+ .output(z.array(TenantBindingSchema)),
+
tenantPreflight: oc
.route({ method: "POST", path: "/tenants/preflight" })
.input(
diff --git a/api/src/db/migrations/0002_awesome_madame_web.sql b/api/src/db/migrations/0002_awesome_madame_web.sql
new file mode 100644
index 00000000..e39a3327
--- /dev/null
+++ b/api/src/db/migrations/0002_awesome_madame_web.sql
@@ -0,0 +1,3 @@
+ALTER TABLE "tenants" ADD COLUMN "allow_ui_overrides" boolean DEFAULT true NOT NULL;--> statement-breakpoint
+ALTER TABLE "tenants" ADD COLUMN "allow_backend_overrides" boolean DEFAULT false NOT NULL;--> statement-breakpoint
+ALTER TABLE "tenants" ADD COLUMN "allow_ssr" boolean DEFAULT false NOT NULL;
\ No newline at end of file
diff --git a/api/src/db/migrations/meta/0002_snapshot.json b/api/src/db/migrations/meta/0002_snapshot.json
new file mode 100644
index 00000000..fda7cde0
--- /dev/null
+++ b/api/src/db/migrations/meta/0002_snapshot.json
@@ -0,0 +1,176 @@
+{
+ "id": "7b8a421a-d0c7-414a-96e8-0c259935178b",
+ "prevId": "3e88c17e-53d5-4809-b872-33d2f87a8a90",
+ "version": "7",
+ "dialect": "postgresql",
+ "tables": {
+ "public.tenants": {
+ "name": "tenants",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true,
+ "default": "gen_random_uuid()"
+ },
+ "subdomain": {
+ "name": "subdomain",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "account_id": {
+ "name": "account_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "org_id": {
+ "name": "org_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "status": {
+ "name": "status",
+ "type": "tenant_status",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'active'"
+ },
+ "allow_ui_overrides": {
+ "name": "allow_ui_overrides",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": true
+ },
+ "allow_backend_overrides": {
+ "name": "allow_backend_overrides",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "allow_ssr": {
+ "name": "allow_ssr",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "deleted_at": {
+ "name": "deleted_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "tenants_subdomain_idx": {
+ "name": "tenants_subdomain_idx",
+ "columns": [
+ {
+ "expression": "subdomain",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "tenants_account_id_idx": {
+ "name": "tenants_account_id_idx",
+ "columns": [
+ {
+ "expression": "account_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "tenants_subdomain_unique": {
+ "name": "tenants_subdomain_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "subdomain"
+ ]
+ },
+ "tenants_account_id_unique": {
+ "name": "tenants_account_id_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "account_id"
+ ]
+ },
+ "tenants_org_id_unique": {
+ "name": "tenants_org_id_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "org_id"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ }
+ },
+ "enums": {
+ "public.tenant_status": {
+ "name": "tenant_status",
+ "schema": "public",
+ "values": [
+ "active",
+ "pending",
+ "suspended",
+ "pending_deletion"
+ ]
+ }
+ },
+ "schemas": {},
+ "sequences": {},
+ "roles": {},
+ "policies": {},
+ "views": {},
+ "_meta": {
+ "columns": {},
+ "schemas": {},
+ "tables": {}
+ }
+}
\ No newline at end of file
diff --git a/api/src/db/migrations/meta/_journal.json b/api/src/db/migrations/meta/_journal.json
index c939ec4a..9e5e42bb 100644
--- a/api/src/db/migrations/meta/_journal.json
+++ b/api/src/db/migrations/meta/_journal.json
@@ -15,6 +15,13 @@
"when": 1786078137908,
"tag": "0001_brief_magik",
"breakpoints": true
+ },
+ {
+ "idx": 2,
+ "version": "7",
+ "when": 1786645659094,
+ "tag": "0002_awesome_madame_web",
+ "breakpoints": true
}
]
-}
+}
\ No newline at end of file
diff --git a/api/src/db/schema.ts b/api/src/db/schema.ts
index b141f76b..c689380d 100644
--- a/api/src/db/schema.ts
+++ b/api/src/db/schema.ts
@@ -1,4 +1,12 @@
-import { pgEnum, pgTable, text, timestamp, uniqueIndex, uuid } from "drizzle-orm/pg-core";
+import {
+ boolean,
+ pgEnum,
+ pgTable,
+ text,
+ timestamp,
+ uniqueIndex,
+ uuid,
+} from "drizzle-orm/pg-core";
export const tenantStatus = pgEnum("tenant_status", [
"active",
@@ -16,6 +24,9 @@ export const tenants = pgTable(
orgId: text("org_id").notNull().unique(),
name: text("name").notNull(),
status: tenantStatus("status").default("active").notNull(),
+ allowUiOverrides: boolean("allow_ui_overrides").default(true).notNull(),
+ allowBackendOverrides: boolean("allow_backend_overrides").default(false).notNull(),
+ allowSsr: boolean("allow_ssr").default(false).notNull(),
createdAt: timestamp("created_at", { mode: "date", withTimezone: true }).defaultNow().notNull(),
updatedAt: timestamp("updated_at", { mode: "date", withTimezone: true }).defaultNow().notNull(),
deletedAt: timestamp("deleted_at", { mode: "date", withTimezone: true }),
diff --git a/api/src/index.ts b/api/src/index.ts
index df235000..9ebbaed8 100644
--- a/api/src/index.ts
+++ b/api/src/index.ts
@@ -144,6 +144,9 @@ export default createPlugin.withPlugins()({
accountId: input.accountId,
orgId: context.organization.activeOrganizationId,
status: input.status,
+ allowUiOverrides: input.allowUiOverrides,
+ allowBackendOverrides: input.allowBackendOverrides,
+ allowSsr: input.allowSsr,
});
}),
@@ -159,6 +162,9 @@ export default createPlugin.withPlugins()({
subdomain: input.subdomain,
accountId: input.accountId,
status: input.status,
+ allowUiOverrides: input.allowUiOverrides,
+ allowBackendOverrides: input.allowBackendOverrides,
+ allowSsr: input.allowSsr,
});
}),
@@ -223,6 +229,10 @@ export default createPlugin.withPlugins()({
return tenant;
}),
+ listTenantBindings: builder.listTenantBindings.handler(async () =>
+ services.tenants.listBindings(),
+ ),
+
tenantPreflight: builder.tenantPreflight.use(requireAuth).handler(async ({ input }) => {
const subdomainValid = SUBDOMAIN_SEGMENT_REGEX.test(input.subdomain);
const accountId = `${input.subdomain}.${input.parentAccount}`;
diff --git a/api/src/services/tenants.ts b/api/src/services/tenants.ts
index 2754489d..4cdb1aa5 100644
--- a/api/src/services/tenants.ts
+++ b/api/src/services/tenants.ts
@@ -13,25 +13,46 @@ export interface TenantRecord {
orgId: string;
name: string;
status: TenantStatus;
+ allowUiOverrides: boolean;
+ allowBackendOverrides: boolean;
+ allowSsr: boolean;
createdAt: string;
updatedAt: string;
deletedAt: string | null;
}
+export interface TenantBinding {
+ hostname: string;
+ accountId: string;
+ allowUiOverrides: boolean;
+ allowBackendOverrides: boolean;
+ allowSsr: boolean;
+ status: TenantStatus;
+}
+
export interface TenantInput {
subdomain: string;
name: string;
accountId: string;
orgId: string;
status?: TenantStatus;
+ allowUiOverrides?: boolean;
+ allowBackendOverrides?: boolean;
+ allowSsr?: boolean;
}
export interface TenantsService {
listTenantsByOrgIds(orgIds: string[]): Promise;
+ listBindings(): Promise;
createTenant(input: TenantInput): Promise;
updateTenant(
id: string,
- input: Partial>,
+ input: Partial<
+ Pick<
+ TenantInput,
+ "name" | "subdomain" | "accountId" | "status" | "allowUiOverrides" | "allowBackendOverrides" | "allowSsr"
+ >
+ >,
): Promise;
softDeleteTenant(id: string): Promise;
suspendTenant(id: string): Promise;
@@ -55,6 +76,9 @@ function toTenantRecord(row: TenantRow): TenantRecord {
orgId: row.orgId,
name: row.name,
status: row.status,
+ allowUiOverrides: row.allowUiOverrides,
+ allowBackendOverrides: row.allowBackendOverrides,
+ allowSsr: row.allowSsr,
createdAt: row.createdAt instanceof Date ? row.createdAt.toISOString() : String(row.createdAt),
updatedAt: row.updatedAt instanceof Date ? row.updatedAt.toISOString() : String(row.updatedAt),
deletedAt: row.deletedAt instanceof Date ? row.deletedAt.toISOString() : null,
@@ -88,6 +112,27 @@ export const TenantsLive = Layer.effect(
}
},
+ listBindings: async () => {
+ try {
+ const rows = await db
+ .select({
+ subdomain: tenantsTable.subdomain,
+ accountId: tenantsTable.accountId,
+ allowUiOverrides: tenantsTable.allowUiOverrides,
+ allowBackendOverrides: tenantsTable.allowBackendOverrides,
+ allowSsr: tenantsTable.allowSsr,
+ status: tenantsTable.status,
+ })
+ .from(tenantsTable);
+ return rows.map(({ subdomain, ...binding }) => ({
+ ...binding,
+ hostname: subdomain,
+ }));
+ } catch (error) {
+ throw toOrpcError(error);
+ }
+ },
+
createTenant: async (input) => {
try {
const [row] = await db
@@ -98,6 +143,11 @@ export const TenantsLive = Layer.effect(
accountId: input.accountId,
orgId: input.orgId,
...(input.status !== undefined && { status: input.status }),
+ ...(input.allowUiOverrides !== undefined && { allowUiOverrides: input.allowUiOverrides }),
+ ...(input.allowBackendOverrides !== undefined && {
+ allowBackendOverrides: input.allowBackendOverrides,
+ }),
+ ...(input.allowSsr !== undefined && { allowSsr: input.allowSsr }),
})
.onConflictDoNothing()
.returning();
diff --git a/api/tests/unit/tenants-service.test.ts b/api/tests/unit/tenants-service.test.ts
index 427ad07f..fd04bd4b 100644
--- a/api/tests/unit/tenants-service.test.ts
+++ b/api/tests/unit/tenants-service.test.ts
@@ -147,6 +147,62 @@ describe("TenantsService", () => {
expect(await runService(layer, (svc) => svc.listTenantsByOrgIds([]))).toEqual([]);
});
+ it("lists active and non-deleted bindings with default permissions", async () => {
+ const layer = freshLayer();
+ await runService(layer, (svc) =>
+ svc.createTenant({
+ ...baseInput,
+ subdomain: "acme",
+ accountId: "acme.example.near",
+ }),
+ );
+ const suspended = await runService(layer, (svc) =>
+ svc.createTenant({
+ ...baseInput,
+ subdomain: "beta",
+ accountId: "beta.example.near",
+ orgId: "org-2",
+ }),
+ );
+ await runService(layer, (svc) => svc.suspendTenant(suspended.id));
+
+ const bindings = await runService(layer, (svc) => svc.listBindings());
+
+ expect(bindings).toHaveLength(2);
+ expect(bindings.find((b) => b.hostname === "acme")).toMatchObject({
+ hostname: "acme",
+ accountId: "acme.example.near",
+ allowUiOverrides: true,
+ allowBackendOverrides: false,
+ allowSsr: false,
+ status: "active",
+ });
+ expect(bindings.find((b) => b.hostname === "beta")?.status).toBe("suspended");
+ });
+
+ it("persists allow_* overrides on create and update", async () => {
+ const layer = freshLayer();
+ const created = await runService(layer, (svc) =>
+ svc.createTenant({
+ ...baseInput,
+ allowUiOverrides: false,
+ allowBackendOverrides: true,
+ allowSsr: true,
+ }),
+ );
+ expect(created).toMatchObject({
+ allowUiOverrides: false,
+ allowBackendOverrides: true,
+ allowSsr: true,
+ });
+
+ const updated = await runService(layer, (svc) =>
+ svc.updateTenant(created.id, { allowSsr: false }),
+ );
+ expect(updated.allowSsr).toBe(false);
+ expect(updated.allowUiOverrides).toBe(false);
+ });
+
it("updates a tenant name", async () => {
const layer = freshLayer();
const created = await runService(layer, (svc) => svc.createTenant(baseInput));
diff --git a/bos.config.json b/bos.config.json
index b31993ec..436021f2 100644
--- a/bos.config.json
+++ b/bos.config.json
@@ -18,9 +18,6 @@
"production": "https://elliot-braem-7253-host-everything-dev-nearbuilder-aa7d0803c-ze.zephyrcloud.app",
"secrets": [
"CORS_ORIGIN",
- "TENANT_WHITELIST",
- "ALLOW_OVERRIDE",
- "ALLOW_UNTRUSTED_SSR",
"CSP_STRICT"
]
},
diff --git a/host/.env.example b/host/.env.example
index 1283ab78..f5d82332 100644
--- a/host/.env.example
+++ b/host/.env.example
@@ -1,8 +1,5 @@
# app.host
CORS_ORIGIN=http://localhost:3000
-TENANT_WHITELIST=
-ALLOW_OVERRIDE=
-ALLOW_UNTRUSTED_SSR=
CSP_STRICT=
# app.api
diff --git a/host/src/services/binding-resolver.ts b/host/src/services/binding-resolver.ts
new file mode 100644
index 00000000..30ed5ee4
--- /dev/null
+++ b/host/src/services/binding-resolver.ts
@@ -0,0 +1,148 @@
+import { logger } from "../utils/logger";
+import { resolveDomain } from "../utils/normalize";
+import type { RuntimeConfig } from "./config";
+
+export type TenantBindingStatus = "active" | "pending" | "suspended" | "pending_deletion";
+
+export interface TenantBinding {
+ hostname: string;
+ accountId: string;
+ allowUiOverrides: boolean;
+ allowBackendOverrides: boolean;
+ allowSsr: boolean;
+ status: TenantBindingStatus;
+}
+
+const BINDINGS_TTL_MS = 30_000;
+
+interface CachedBindings {
+ apiUrl: string;
+ expiresAt: number;
+ entries: Map;
+ refetching?: Promise
- );
-}
diff --git a/ui/src/routes/_layout/_admin/admin/index.tsx b/ui/src/routes/_layout/_admin/admin/index.tsx
new file mode 100644
index 00000000..fd5a7378
--- /dev/null
+++ b/ui/src/routes/_layout/_admin/admin/index.tsx
@@ -0,0 +1,152 @@
+import { createFileRoute, Link } from "@tanstack/react-router";
+import { Building2, Settings, Users } from "lucide-react";
+import { getAccount } from "@/app";
+import { Button, Card } from "@/components";
+import { InfoRow } from "@/components/ui/info-row";
+
+export const Route = createFileRoute("/_layout/_admin/admin/")({
+ head: () => ({
+ meta: [{ title: "Admin Dashboard | app" }],
+ }),
+ component: AdminDashboard,
+});
+
+function AdminDashboard() {
+ const { auth, tenant } = Route.useRouteContext();
+ const account = getAccount();
+ const user = auth?.user ?? null;
+
+ return (
+
+
+
+
+
+ Dashboard
+
+
+ Signed in as {account}
+
+
+
+
+
+
+
+
+ Manage
+
+
+
+
+
+ Organizations
+
+ Manage organizations, members, roles, and invitations.
+
+
+
+
+
+
+
+
+ Settings
+
+ Update your profile, auth methods, and security preferences.
+
+
+
+
+
+
+ {tenant && (
+
+
+
+
+ Configuration
+
+
+
+
+
+
+
+
+
+
+ )}
+
+ {tenant && (
+
+
+
+
+ This tenant is backed by an organization. Manage members, roles, and invitations
+ there.
+
+
+
+ open organization
+
+
+
+ )}
+
+ );
+}
+
+function StatCard({
+ label,
+ value,
+ mono,
+}: {
+ label: string;
+ value: React.ReactNode;
+ mono?: boolean;
+}) {
+ return (
+
+
+ {label}
+
+
+ {value}
+
+
+ );
+}
+
+function SectionHeader({ title, action }: { title: string; action?: React.ReactNode }) {
+ return (
+
+
{title}
+ {action}
+
+ );
+}
diff --git a/ui/src/routes/_layout/_admin/admin/system.tsx b/ui/src/routes/_layout/_admin/admin/system.tsx
new file mode 100644
index 00000000..a64457a3
--- /dev/null
+++ b/ui/src/routes/_layout/_admin/admin/system.tsx
@@ -0,0 +1,70 @@
+import { createFileRoute } from "@tanstack/react-router";
+import { getAccount, getActiveRuntime, getAppName, getRepository } from "@/app";
+import { Card } from "@/components";
+import { InfoRow } from "@/components/ui/info-row";
+
+export const Route = createFileRoute("/_layout/_admin/admin/system")({
+ loader: async ({ context }) => ({
+ runtimeConfig: context.runtimeConfig,
+ }),
+ head: () => ({
+ meta: [{ title: "Admin System | app" }],
+ }),
+ component: AdminSystem,
+});
+
+function AdminSystem() {
+ const { runtimeConfig } = Route.useLoaderData();
+ const account = getAccount(runtimeConfig);
+ const appName = getAppName(runtimeConfig);
+ const repository = getRepository(runtimeConfig);
+ const runtime = getActiveRuntime(runtimeConfig);
+
+ const env = runtimeConfig?.env;
+ const networkId = runtimeConfig?.networkId;
+ const hostUrl = runtimeConfig?.hostUrl;
+ const apiBase = runtimeConfig?.apiBase;
+ const rpcBase = runtimeConfig?.rpcBase;
+ const assetsUrl = runtimeConfig?.assetsUrl;
+ const runtimeBasePath = runtime?.runtimeBasePath;
+
+ return (
+
+
+
+
+
+ Runtime
+
+
+
+
+
+
+
+ Deployment
+
+
+
+
+
+
+
+ Endpoints
+
+
+
+
+
+
+ );
+}
diff --git a/ui/src/routes/_layout/_authenticated.tsx b/ui/src/routes/_layout/_authenticated.tsx
index 869f23e3..72eae14a 100644
--- a/ui/src/routes/_layout/_authenticated.tsx
+++ b/ui/src/routes/_layout/_authenticated.tsx
@@ -94,7 +94,7 @@ function AuthenticatedLayout() {
const isAdmin = session?.user?.role === "admin";
const sidebarItems: SidebarItem[] = [
- { icon: Home, label: "home", to: "/home", roleRequired: "anon" },
+ { icon: Home, label: "dashboard", to: "/dashboard", roleRequired: "anon" },
{ icon: Shield, label: "admin", to: "/admin", roleRequired: "admin" },
{ icon: MessageSquare, label: "nostr", to: "/nostr", roleRequired: "admin" },
];
@@ -221,7 +221,7 @@ function MobileTabBar({
style={{ paddingBottom: "env(safe-area-inset-bottom, 0px)" }}
>
-
+
diff --git a/ui/src/routes/_layout/_authenticated/admin/index.tsx b/ui/src/routes/_layout/_authenticated/admin/index.tsx
deleted file mode 100644
index 65c3c2d3..00000000
--- a/ui/src/routes/_layout/_authenticated/admin/index.tsx
+++ /dev/null
@@ -1,104 +0,0 @@
-import { createFileRoute, Link } from "@tanstack/react-router";
-import { Building2, Settings, Users } from "lucide-react";
-import { getAccount } from "@/app";
-import { Button, Card } from "@/components";
-import { PageContainer } from "@/components/layout/page-container";
-
-export const Route = createFileRoute("/_layout/_authenticated/admin/")({
- head: () => ({
- meta: [{ title: "Admin Dashboard | app" }],
- }),
- component: AdminDashboard,
-});
-
-function AdminDashboard() {
- const { auth } = Route.useRouteContext();
- const account = getAccount();
- const user = auth?.user ?? null;
-
- return (
-
-
-
-
-
-
- Dashboard
-
-
- Signed in as {account}
-
-
-
-
-
-
-
-
- Manage
-
-
-
-
-
- Organizations
-
- Manage organizations, members, roles, and invitations.
-
-
-
-
-
-
-
-
- Settings
-
- Update your profile, auth methods, and security preferences.
-
-
-
-
-
-
-
- );
-}
-
-function StatCard({
- label,
- value,
- mono,
-}: {
- label: string;
- value: React.ReactNode;
- mono?: boolean;
-}) {
- return (
-
-
- {label}
-
-
- {value}
-
-
- );
-}
diff --git a/ui/src/routes/_layout/_authenticated/admin/system.tsx b/ui/src/routes/_layout/_authenticated/admin/system.tsx
deleted file mode 100644
index a98296af..00000000
--- a/ui/src/routes/_layout/_authenticated/admin/system.tsx
+++ /dev/null
@@ -1,73 +0,0 @@
-import { createFileRoute } from "@tanstack/react-router";
-import { getAccount, getActiveRuntime, getAppName, getRepository } from "@/app";
-import { Card } from "@/components";
-import { PageContainer } from "@/components/layout/page-container";
-import { InfoRow } from "@/components/ui/info-row";
-
-export const Route = createFileRoute("/_layout/_authenticated/admin/system")({
- loader: async ({ context }) => ({
- runtimeConfig: context.runtimeConfig,
- }),
- head: () => ({
- meta: [{ title: "Admin System | app" }],
- }),
- component: AdminSystem,
-});
-
-function AdminSystem() {
- const { runtimeConfig } = Route.useLoaderData();
- const account = getAccount(runtimeConfig);
- const appName = getAppName(runtimeConfig);
- const repository = getRepository(runtimeConfig);
- const runtime = getActiveRuntime(runtimeConfig);
-
- const env = runtimeConfig?.env;
- const networkId = runtimeConfig?.networkId;
- const hostUrl = runtimeConfig?.hostUrl;
- const apiBase = runtimeConfig?.apiBase;
- const rpcBase = runtimeConfig?.rpcBase;
- const assetsUrl = runtimeConfig?.assetsUrl;
- const runtimeBasePath = runtime?.runtimeBasePath;
-
- return (
-
-
-
-
-
-
- Runtime
-
-
-
-
-
-
-
- Deployment
-
-
-
-
-
-
-
- Endpoints
-
-
-
-
-
-
-
- );
-}
diff --git a/ui/src/routes/_layout/_authenticated/home.tsx b/ui/src/routes/_layout/_authenticated/dashboard.tsx
similarity index 98%
rename from ui/src/routes/_layout/_authenticated/home.tsx
rename to ui/src/routes/_layout/_authenticated/dashboard.tsx
index 1fccff0e..86f23a6c 100644
--- a/ui/src/routes/_layout/_authenticated/home.tsx
+++ b/ui/src/routes/_layout/_authenticated/dashboard.tsx
@@ -13,7 +13,7 @@ import { Card } from "@/components";
import { PageContainer } from "@/components/layout/page-container";
import { InfoRow } from "@/components/ui/info-row";
-export const Route = createFileRoute("/_layout/_authenticated/home")({
+export const Route = createFileRoute("/_layout/_authenticated/dashboard")({
beforeLoad: async ({ context }) => {
const { apiClient, runtimeConfig } = context;
const accountId = getAccount(runtimeConfig);
diff --git a/ui/src/routes/_layout/apps/$accountId/$gatewayId.tsx b/ui/src/routes/_layout/_public/apps/$accountId/$gatewayId.tsx
similarity index 99%
rename from ui/src/routes/_layout/apps/$accountId/$gatewayId.tsx
rename to ui/src/routes/_layout/_public/apps/$accountId/$gatewayId.tsx
index 279e4782..52984590 100644
--- a/ui/src/routes/_layout/apps/$accountId/$gatewayId.tsx
+++ b/ui/src/routes/_layout/_public/apps/$accountId/$gatewayId.tsx
@@ -19,7 +19,7 @@ const getStartCommand = (accountId: string, gatewayId: string) =>
const getExtendsCommand = (accountId: string, gatewayId: string) =>
`bunx everything-dev@latest init --extends bos://${accountId}/${gatewayId}`;
-export const Route = createFileRoute("/_layout/apps/$accountId/$gatewayId")({
+export const Route = createFileRoute("/_layout/_public/apps/$accountId/$gatewayId")({
loader: async ({ params, context }) => {
const { queryClient, apiClient } = context;
await queryClient.prefetchQuery({
diff --git a/ui/src/routes/_layout/apps/$accountId/index.tsx b/ui/src/routes/_layout/_public/apps/$accountId/index.tsx
similarity index 99%
rename from ui/src/routes/_layout/apps/$accountId/index.tsx
rename to ui/src/routes/_layout/_public/apps/$accountId/index.tsx
index 904bdaf7..0ec1eb61 100644
--- a/ui/src/routes/_layout/apps/$accountId/index.tsx
+++ b/ui/src/routes/_layout/_public/apps/$accountId/index.tsx
@@ -9,7 +9,7 @@ import { TooltipProvider } from "@/components/ui/tooltip";
const BASE_RUNTIME = "bos://dev.everything.near/everything.dev";
-export const Route = createFileRoute("/_layout/apps/$accountId/")({
+export const Route = createFileRoute("/_layout/_public/apps/$accountId/")({
loader: async ({ params, context }) => {
const { queryClient, apiClient } = context;
await queryClient.prefetchQuery({
diff --git a/ui/src/routes/_layout/apps/index.tsx b/ui/src/routes/_layout/_public/apps/index.tsx
similarity index 99%
rename from ui/src/routes/_layout/apps/index.tsx
rename to ui/src/routes/_layout/_public/apps/index.tsx
index 8ea8263f..4ce3c601 100644
--- a/ui/src/routes/_layout/apps/index.tsx
+++ b/ui/src/routes/_layout/_public/apps/index.tsx
@@ -21,7 +21,7 @@ type SearchParams = {
preview?: string;
};
-export const Route = createFileRoute("/_layout/apps/")({
+export const Route = createFileRoute("/_layout/_public/apps/")({
validateSearch: (search: Record
): SearchParams => ({
preview:
typeof search.preview === "string" && search.preview.length > 0 ? search.preview : undefined,
diff --git a/ui/src/routes/_layout/_public/login.tsx b/ui/src/routes/_layout/_public/login.tsx
index fdc771d9..abc68a82 100644
--- a/ui/src/routes/_layout/_public/login.tsx
+++ b/ui/src/routes/_layout/_public/login.tsx
@@ -24,7 +24,7 @@ export const Route = createFileRoute("/_layout/_public/login")({
queryClient.getQueryData(sessionQueryOptions(authClient, initialSession).queryKey);
if (session?.user) {
- const redirectTo = search.redirect?.startsWith("/") ? search.redirect : "/home";
+ const redirectTo = search.redirect?.startsWith("/") ? search.redirect : "/dashboard";
throw redirect({ to: redirectTo, search: {} });
}
},
@@ -57,7 +57,7 @@ function LoginPage() {
}, [auth.near]);
const handleSuccess = async (message: string) => {
- const redirectTo = redirect?.startsWith("/") ? redirect : "/home";
+ const redirectTo = redirect?.startsWith("/") ? redirect : "/dashboard";
toast.success(message);
queryClient.invalidateQueries({ queryKey: ["session"] });
navigate({ to: redirectTo, replace: true, search: {} });
@@ -110,7 +110,7 @@ function LoginPage() {
};
if (session?.user) {
- const redirectTo = redirect?.startsWith("/") ? redirect : "/home";
+ const redirectTo = redirect?.startsWith("/") ? redirect : "/dashboard";
return ;
}
diff --git a/ui/src/routes/_layout/things/$thingId.tsx b/ui/src/routes/_layout/_public/things/$thingId.tsx
similarity index 98%
rename from ui/src/routes/_layout/things/$thingId.tsx
rename to ui/src/routes/_layout/_public/things/$thingId.tsx
index 0fdb7405..ac3184f4 100644
--- a/ui/src/routes/_layout/things/$thingId.tsx
+++ b/ui/src/routes/_layout/_public/things/$thingId.tsx
@@ -6,7 +6,7 @@ import { sessionQueryOptions, useApiClient, useAuthClient } from "@/app";
import { Badge, Button } from "@/components";
import { Skeleton } from "@/components/ui/skeleton";
-export const Route = createFileRoute("/_layout/things/$thingId")({
+export const Route = createFileRoute("/_layout/_public/things/$thingId")({
head: ({ params }) => ({
meta: [
{ title: `${params.thingId} | Things | everything.dev` },
diff --git a/ui/src/routes/_layout/things/index.tsx b/ui/src/routes/_layout/_public/things/index.tsx
similarity index 97%
rename from ui/src/routes/_layout/things/index.tsx
rename to ui/src/routes/_layout/_public/things/index.tsx
index 6cbee7e0..fba26c37 100644
--- a/ui/src/routes/_layout/things/index.tsx
+++ b/ui/src/routes/_layout/_public/things/index.tsx
@@ -1,7 +1,7 @@
import { createFileRoute, Link, useNavigate } from "@tanstack/react-router";
import { useState } from "react";
-export const Route = createFileRoute("/_layout/things/")({
+export const Route = createFileRoute("/_layout/_public/things/")({
head: () => ({
meta: [
{ title: "Things | everything.dev" },
diff --git a/ui/src/routes/_layout/things/live.tsx b/ui/src/routes/_layout/_public/things/live.tsx
similarity index 98%
rename from ui/src/routes/_layout/things/live.tsx
rename to ui/src/routes/_layout/_public/things/live.tsx
index 7be8f0c6..674d7813 100644
--- a/ui/src/routes/_layout/things/live.tsx
+++ b/ui/src/routes/_layout/_public/things/live.tsx
@@ -4,7 +4,7 @@ import { useCallback, useEffect, useRef, useState } from "react";
import { useApiClient } from "@/app";
import { Badge } from "@/components";
-export const Route = createFileRoute("/_layout/things/live")({
+export const Route = createFileRoute("/_layout/_public/things/live")({
head: () => ({
meta: [
{ title: "Live Stream | Things | everything.dev" },
From 9c90224a15ff2a60e38d7eade3f0f6e20f95ab15 Mon Sep 17 00:00:00 2001
From: Elliot Braem
Date: Thu, 13 Aug 2026 17:44:55 -0500
Subject: [PATCH 06/12] test(regression): update /home references to /dashboard
after route rename
---
tests/regression/browser/helpers/seeded.ts | 2 +-
tests/regression/browser/specs/auth-client.spec.ts | 4 ++--
tests/regression/browser/specs/auth-redirect.spec.ts | 4 ++--
tests/regression/browser/specs/logout.spec.ts | 4 ++--
4 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/tests/regression/browser/helpers/seeded.ts b/tests/regression/browser/helpers/seeded.ts
index 560e0aad..c580e4f9 100644
--- a/tests/regression/browser/helpers/seeded.ts
+++ b/tests/regression/browser/helpers/seeded.ts
@@ -42,7 +42,7 @@ export function loadSeedData(): SeedData {
}
export async function verifyAuthenticated(page: Page) {
- await page.goto("/home", { waitUntil: "domcontentloaded" });
+ await page.goto("/dashboard", { waitUntil: "domcontentloaded" });
await page.waitForTimeout(500);
await page.waitForLoadState("networkidle");
await expect(page.locator("button[title='account menu']")).toBeVisible({ timeout: 10000 });
diff --git a/tests/regression/browser/specs/auth-client.spec.ts b/tests/regression/browser/specs/auth-client.spec.ts
index bda4857d..970989f7 100644
--- a/tests/regression/browser/specs/auth-client.spec.ts
+++ b/tests/regression/browser/specs/auth-client.spec.ts
@@ -58,9 +58,9 @@ test.describe("authClient", () => {
await anonymousBtn.click();
await signInDone;
- await page.waitForURL(/\/home$/, { timeout: 15000 });
+ await page.waitForURL(/\/dashboard$/, { timeout: 15000 });
await page.reload();
- await page.waitForURL(/\/home$/, { timeout: 15000 });
+ await page.waitForURL(/\/dashboard$/, { timeout: 15000 });
await page.waitForLoadState("networkidle");
await waitForApp(page);
diff --git a/tests/regression/browser/specs/auth-redirect.spec.ts b/tests/regression/browser/specs/auth-redirect.spec.ts
index f0b3aede..afbaf19a 100644
--- a/tests/regression/browser/specs/auth-redirect.spec.ts
+++ b/tests/regression/browser/specs/auth-redirect.spec.ts
@@ -26,8 +26,8 @@ test.describe("Auth redirect", () => {
expectNoHydrationFailure(pageErrors);
});
- test("unauthenticated /home redirects to /login", async ({ page }) => {
- await page.goto("/home", { waitUntil: "domcontentloaded" });
+ test("unauthenticated /dashboard redirects to /login", async ({ page }) => {
+ await page.goto("/dashboard", { waitUntil: "domcontentloaded" });
await waitForApp(page);
await page.waitForURL(/\/login/, { timeout: 15000 });
diff --git a/tests/regression/browser/specs/logout.spec.ts b/tests/regression/browser/specs/logout.spec.ts
index cef410e9..97642bcd 100644
--- a/tests/regression/browser/specs/logout.spec.ts
+++ b/tests/regression/browser/specs/logout.spec.ts
@@ -23,9 +23,9 @@ test.describe("logout", () => {
await anonymousBtn.click();
await signInDone;
- await page.waitForURL(/\/home$/, { timeout: 15000 });
+ await page.waitForURL(/\/dashboard$/, { timeout: 15000 });
await page.reload();
- await page.waitForURL(/\/home$/, { timeout: 15000 });
+ await page.waitForURL(/\/dashboard$/, { timeout: 15000 });
await page.waitForLoadState("networkidle");
await waitForApp(page);
await page.locator("button[title='account menu']").click();
From 7f1b9dc11e98cdd98a404914dcde0c2bbb0bffb2 Mon Sep 17 00:00:00 2001
From: Elliot Braem
Date: Thu, 13 Aug 2026 17:56:16 -0500
Subject: [PATCH 07/12] refactor(ui): add _anon mount for login, rename
organizations to orgs, remove nostr
- move login from public layout into new _anon pathless layout that redirects authed users to /dashboard and provides theme toggle header
- rename organization route group from /organizations to /orgs; move invitation acceptance to /orgs/invites/$id
- remove stale nostr entry from authenticated sidebar
- changeset: ui-anon-orgs
---
.changeset/ui-anon-orgs.md | 9 +
ui/src/components/org-switcher.tsx | 2 +-
ui/src/components/user-nav.tsx | 2 +-
ui/src/routeTree.gen.ts | 224 ++++++++++--------
ui/src/routes/_layout/_admin/admin.tsx | 4 +-
ui/src/routes/_layout/_admin/admin/index.tsx | 4 +-
ui/src/routes/_layout/_anon.tsx | 57 +++++
.../_layout/{_public => _anon}/login.tsx | 4 +-
ui/src/routes/_layout/_authenticated.tsx | 3 +-
.../{organizations => orgs}/$slug.tsx | 12 +-
.../{organizations => orgs}/index.tsx | 10 +-
.../invites.$id.tsx} | 10 +-
.../{organizations => orgs}/new.tsx | 10 +-
.../_authenticated/tenant/$tenantId.tsx | 2 +-
14 files changed, 220 insertions(+), 133 deletions(-)
create mode 100644 .changeset/ui-anon-orgs.md
create mode 100644 ui/src/routes/_layout/_anon.tsx
rename ui/src/routes/_layout/{_public => _anon}/login.tsx (98%)
rename ui/src/routes/_layout/_authenticated/{organizations => orgs}/$slug.tsx (99%)
rename ui/src/routes/_layout/_authenticated/{organizations => orgs}/index.tsx (98%)
rename ui/src/routes/_layout/_authenticated/{accept-invitation.$id.tsx => orgs/invites.$id.tsx} (95%)
rename ui/src/routes/_layout/_authenticated/{organizations => orgs}/new.tsx (96%)
diff --git a/.changeset/ui-anon-orgs.md b/.changeset/ui-anon-orgs.md
new file mode 100644
index 00000000..d1e2a805
--- /dev/null
+++ b/.changeset/ui-anon-orgs.md
@@ -0,0 +1,9 @@
+---
+"ui": minor
+---
+
+Add a dedicated anonymous mount and reorganize organization routes.
+
+- Add a `/_layout/_anon` pathless layout for pre-auth pages. Move login from the public layout into it; the layout redirects authenticated users to `/dashboard` and provides the theme toggle header.
+- Rename the organization route group from `/organizations` to `/orgs` (`/orgs`, `/orgs/new`, `/orgs/$slug`) and move invitation acceptance to `/orgs/invites/$id`.
+- Remove the stale nostr entry from the authenticated sidebar.
\ No newline at end of file
diff --git a/ui/src/components/org-switcher.tsx b/ui/src/components/org-switcher.tsx
index 8d4eada0..7760d57f 100644
--- a/ui/src/components/org-switcher.tsx
+++ b/ui/src/components/org-switcher.tsx
@@ -64,7 +64,7 @@ export function OrgSwitcher({ organizations, activeOrgId, onSwitch }: OrgSwitche
)}
-
+
new organization
diff --git a/ui/src/components/user-nav.tsx b/ui/src/components/user-nav.tsx
index ba6a6107..084aca2f 100644
--- a/ui/src/components/user-nav.tsx
+++ b/ui/src/components/user-nav.tsx
@@ -151,7 +151,7 @@ export function UserNav() {
{activeOrg && (
-
+
{activeOrg.name}
diff --git a/ui/src/routeTree.gen.ts b/ui/src/routeTree.gen.ts
index 359bd53d..4ad07bcf 100644
--- a/ui/src/routeTree.gen.ts
+++ b/ui/src/routeTree.gen.ts
@@ -12,19 +12,20 @@ import { Route as rootRouteImport } from './routes/__root'
import { Route as LayoutRouteImport } from './routes/_layout'
import { Route as LayoutPublicRouteImport } from './routes/_layout/_public'
import { Route as LayoutAuthenticatedRouteImport } from './routes/_layout/_authenticated'
+import { Route as LayoutAnonRouteImport } from './routes/_layout/_anon'
import { Route as LayoutAdminRouteImport } from './routes/_layout/_admin'
import { Route as LayoutPublicIndexRouteImport } from './routes/_layout/_public/index'
import { Route as LayoutPublicSkillRouteImport } from './routes/_layout/_public/skill'
-import { Route as LayoutPublicLoginRouteImport } from './routes/_layout/_public/login'
import { Route as LayoutPublicAboutRouteImport } from './routes/_layout/_public/about'
import { Route as LayoutPublicAccountIdRouteImport } from './routes/_layout/_public/$accountId'
import { Route as LayoutAuthenticatedSettingsRouteImport } from './routes/_layout/_authenticated/settings'
import { Route as LayoutAuthenticatedDashboardRouteImport } from './routes/_layout/_authenticated/dashboard'
+import { Route as LayoutAnonLoginRouteImport } from './routes/_layout/_anon/login'
import { Route as LayoutAdminAdminRouteImport } from './routes/_layout/_admin/admin'
import { Route as LayoutPublicThingsIndexRouteImport } from './routes/_layout/_public/things/index'
import { Route as LayoutPublicAppsIndexRouteImport } from './routes/_layout/_public/apps/index'
import { Route as LayoutAuthenticatedSettingsIndexRouteImport } from './routes/_layout/_authenticated/settings/index'
-import { Route as LayoutAuthenticatedOrganizationsIndexRouteImport } from './routes/_layout/_authenticated/organizations/index'
+import { Route as LayoutAuthenticatedOrgsIndexRouteImport } from './routes/_layout/_authenticated/orgs/index'
import { Route as LayoutAdminAdminIndexRouteImport } from './routes/_layout/_admin/admin/index'
import { Route as LayoutPublicThingsLiveRouteImport } from './routes/_layout/_public/things/live'
import { Route as LayoutPublicThingsThingIdRouteImport } from './routes/_layout/_public/things/$thingId'
@@ -34,12 +35,12 @@ import { Route as LayoutAuthenticatedTenantTenantIdRouteImport } from './routes/
import { Route as LayoutAuthenticatedSettingsSecurityRouteImport } from './routes/_layout/_authenticated/settings/security'
import { Route as LayoutAuthenticatedSettingsProfileRouteImport } from './routes/_layout/_authenticated/settings/profile'
import { Route as LayoutAuthenticatedSettingsAuthMethodsRouteImport } from './routes/_layout/_authenticated/settings/auth-methods'
-import { Route as LayoutAuthenticatedOrganizationsNewRouteImport } from './routes/_layout/_authenticated/organizations/new'
-import { Route as LayoutAuthenticatedOrganizationsSlugRouteImport } from './routes/_layout/_authenticated/organizations/$slug'
-import { Route as LayoutAuthenticatedAcceptInvitationIdRouteImport } from './routes/_layout/_authenticated/accept-invitation.$id'
+import { Route as LayoutAuthenticatedOrgsNewRouteImport } from './routes/_layout/_authenticated/orgs/new'
+import { Route as LayoutAuthenticatedOrgsSlugRouteImport } from './routes/_layout/_authenticated/orgs/$slug'
import { Route as LayoutAdminAdminSystemRouteImport } from './routes/_layout/_admin/admin/system'
import { Route as LayoutPublicAppsAccountIdIndexRouteImport } from './routes/_layout/_public/apps/$accountId/index'
import { Route as LayoutPublicAppsAccountIdGatewayIdRouteImport } from './routes/_layout/_public/apps/$accountId/$gatewayId'
+import { Route as LayoutAuthenticatedOrgsInvitesIdRouteImport } from './routes/_layout/_authenticated/orgs/invites.$id'
const LayoutRoute = LayoutRouteImport.update({
id: '/_layout',
@@ -53,6 +54,10 @@ const LayoutAuthenticatedRoute = LayoutAuthenticatedRouteImport.update({
id: '/_authenticated',
getParentRoute: () => LayoutRoute,
} as any)
+const LayoutAnonRoute = LayoutAnonRouteImport.update({
+ id: '/_anon',
+ getParentRoute: () => LayoutRoute,
+} as any)
const LayoutAdminRoute = LayoutAdminRouteImport.update({
id: '/_admin',
getParentRoute: () => LayoutRoute,
@@ -67,11 +72,6 @@ const LayoutPublicSkillRoute = LayoutPublicSkillRouteImport.update({
path: '/skill',
getParentRoute: () => LayoutPublicRoute,
} as any)
-const LayoutPublicLoginRoute = LayoutPublicLoginRouteImport.update({
- id: '/login',
- path: '/login',
- getParentRoute: () => LayoutPublicRoute,
-} as any)
const LayoutPublicAboutRoute = LayoutPublicAboutRouteImport.update({
id: '/about',
path: '/about',
@@ -94,6 +94,11 @@ const LayoutAuthenticatedDashboardRoute =
path: '/dashboard',
getParentRoute: () => LayoutAuthenticatedRoute,
} as any)
+const LayoutAnonLoginRoute = LayoutAnonLoginRouteImport.update({
+ id: '/login',
+ path: '/login',
+ getParentRoute: () => LayoutAnonRoute,
+} as any)
const LayoutAdminAdminRoute = LayoutAdminAdminRouteImport.update({
id: '/admin',
path: '/admin',
@@ -115,10 +120,10 @@ const LayoutAuthenticatedSettingsIndexRoute =
path: '/',
getParentRoute: () => LayoutAuthenticatedSettingsRoute,
} as any)
-const LayoutAuthenticatedOrganizationsIndexRoute =
- LayoutAuthenticatedOrganizationsIndexRouteImport.update({
- id: '/organizations/',
- path: '/organizations/',
+const LayoutAuthenticatedOrgsIndexRoute =
+ LayoutAuthenticatedOrgsIndexRouteImport.update({
+ id: '/orgs/',
+ path: '/orgs/',
getParentRoute: () => LayoutAuthenticatedRoute,
} as any)
const LayoutAdminAdminIndexRoute = LayoutAdminAdminIndexRouteImport.update({
@@ -173,22 +178,16 @@ const LayoutAuthenticatedSettingsAuthMethodsRoute =
path: '/auth-methods',
getParentRoute: () => LayoutAuthenticatedSettingsRoute,
} as any)
-const LayoutAuthenticatedOrganizationsNewRoute =
- LayoutAuthenticatedOrganizationsNewRouteImport.update({
- id: '/organizations/new',
- path: '/organizations/new',
+const LayoutAuthenticatedOrgsNewRoute =
+ LayoutAuthenticatedOrgsNewRouteImport.update({
+ id: '/orgs/new',
+ path: '/orgs/new',
getParentRoute: () => LayoutAuthenticatedRoute,
} as any)
-const LayoutAuthenticatedOrganizationsSlugRoute =
- LayoutAuthenticatedOrganizationsSlugRouteImport.update({
- id: '/organizations/$slug',
- path: '/organizations/$slug',
- getParentRoute: () => LayoutAuthenticatedRoute,
- } as any)
-const LayoutAuthenticatedAcceptInvitationIdRoute =
- LayoutAuthenticatedAcceptInvitationIdRouteImport.update({
- id: '/accept-invitation/$id',
- path: '/accept-invitation/$id',
+const LayoutAuthenticatedOrgsSlugRoute =
+ LayoutAuthenticatedOrgsSlugRouteImport.update({
+ id: '/orgs/$slug',
+ path: '/orgs/$slug',
getParentRoute: () => LayoutAuthenticatedRoute,
} as any)
const LayoutAdminAdminSystemRoute = LayoutAdminAdminSystemRouteImport.update({
@@ -208,20 +207,25 @@ const LayoutPublicAppsAccountIdGatewayIdRoute =
path: '/apps/$accountId/$gatewayId',
getParentRoute: () => LayoutPublicRoute,
} as any)
+const LayoutAuthenticatedOrgsInvitesIdRoute =
+ LayoutAuthenticatedOrgsInvitesIdRouteImport.update({
+ id: '/orgs/invites/$id',
+ path: '/orgs/invites/$id',
+ getParentRoute: () => LayoutAuthenticatedRoute,
+ } as any)
export interface FileRoutesByFullPath {
'/': typeof LayoutPublicIndexRoute
'/admin': typeof LayoutAdminAdminRouteWithChildren
+ '/login': typeof LayoutAnonLoginRoute
'/dashboard': typeof LayoutAuthenticatedDashboardRoute
'/settings': typeof LayoutAuthenticatedSettingsRouteWithChildren
'/$accountId': typeof LayoutPublicAccountIdRoute
'/about': typeof LayoutPublicAboutRoute
- '/login': typeof LayoutPublicLoginRoute
'/skill': typeof LayoutPublicSkillRoute
'/admin/system': typeof LayoutAdminAdminSystemRoute
- '/accept-invitation/$id': typeof LayoutAuthenticatedAcceptInvitationIdRoute
- '/organizations/$slug': typeof LayoutAuthenticatedOrganizationsSlugRoute
- '/organizations/new': typeof LayoutAuthenticatedOrganizationsNewRoute
+ '/orgs/$slug': typeof LayoutAuthenticatedOrgsSlugRoute
+ '/orgs/new': typeof LayoutAuthenticatedOrgsNewRoute
'/settings/auth-methods': typeof LayoutAuthenticatedSettingsAuthMethodsRoute
'/settings/profile': typeof LayoutAuthenticatedSettingsProfileRoute
'/settings/security': typeof LayoutAuthenticatedSettingsSecurityRoute
@@ -231,24 +235,24 @@ export interface FileRoutesByFullPath {
'/things/$thingId': typeof LayoutPublicThingsThingIdRoute
'/things/live': typeof LayoutPublicThingsLiveRoute
'/admin/': typeof LayoutAdminAdminIndexRoute
- '/organizations/': typeof LayoutAuthenticatedOrganizationsIndexRoute
+ '/orgs/': typeof LayoutAuthenticatedOrgsIndexRoute
'/settings/': typeof LayoutAuthenticatedSettingsIndexRoute
'/apps/': typeof LayoutPublicAppsIndexRoute
'/things/': typeof LayoutPublicThingsIndexRoute
+ '/orgs/invites/$id': typeof LayoutAuthenticatedOrgsInvitesIdRoute
'/apps/$accountId/$gatewayId': typeof LayoutPublicAppsAccountIdGatewayIdRoute
'/apps/$accountId/': typeof LayoutPublicAppsAccountIdIndexRoute
}
export interface FileRoutesByTo {
'/': typeof LayoutPublicIndexRoute
+ '/login': typeof LayoutAnonLoginRoute
'/dashboard': typeof LayoutAuthenticatedDashboardRoute
'/$accountId': typeof LayoutPublicAccountIdRoute
'/about': typeof LayoutPublicAboutRoute
- '/login': typeof LayoutPublicLoginRoute
'/skill': typeof LayoutPublicSkillRoute
'/admin/system': typeof LayoutAdminAdminSystemRoute
- '/accept-invitation/$id': typeof LayoutAuthenticatedAcceptInvitationIdRoute
- '/organizations/$slug': typeof LayoutAuthenticatedOrganizationsSlugRoute
- '/organizations/new': typeof LayoutAuthenticatedOrganizationsNewRoute
+ '/orgs/$slug': typeof LayoutAuthenticatedOrgsSlugRoute
+ '/orgs/new': typeof LayoutAuthenticatedOrgsNewRoute
'/settings/auth-methods': typeof LayoutAuthenticatedSettingsAuthMethodsRoute
'/settings/profile': typeof LayoutAuthenticatedSettingsProfileRoute
'/settings/security': typeof LayoutAuthenticatedSettingsSecurityRoute
@@ -258,10 +262,11 @@ export interface FileRoutesByTo {
'/things/$thingId': typeof LayoutPublicThingsThingIdRoute
'/things/live': typeof LayoutPublicThingsLiveRoute
'/admin': typeof LayoutAdminAdminIndexRoute
- '/organizations': typeof LayoutAuthenticatedOrganizationsIndexRoute
+ '/orgs': typeof LayoutAuthenticatedOrgsIndexRoute
'/settings': typeof LayoutAuthenticatedSettingsIndexRoute
'/apps': typeof LayoutPublicAppsIndexRoute
'/things': typeof LayoutPublicThingsIndexRoute
+ '/orgs/invites/$id': typeof LayoutAuthenticatedOrgsInvitesIdRoute
'/apps/$accountId/$gatewayId': typeof LayoutPublicAppsAccountIdGatewayIdRoute
'/apps/$accountId': typeof LayoutPublicAppsAccountIdIndexRoute
}
@@ -269,20 +274,20 @@ export interface FileRoutesById {
__root__: typeof rootRouteImport
'/_layout': typeof LayoutRouteWithChildren
'/_layout/_admin': typeof LayoutAdminRouteWithChildren
+ '/_layout/_anon': typeof LayoutAnonRouteWithChildren
'/_layout/_authenticated': typeof LayoutAuthenticatedRouteWithChildren
'/_layout/_public': typeof LayoutPublicRouteWithChildren
'/_layout/_admin/admin': typeof LayoutAdminAdminRouteWithChildren
+ '/_layout/_anon/login': typeof LayoutAnonLoginRoute
'/_layout/_authenticated/dashboard': typeof LayoutAuthenticatedDashboardRoute
'/_layout/_authenticated/settings': typeof LayoutAuthenticatedSettingsRouteWithChildren
'/_layout/_public/$accountId': typeof LayoutPublicAccountIdRoute
'/_layout/_public/about': typeof LayoutPublicAboutRoute
- '/_layout/_public/login': typeof LayoutPublicLoginRoute
'/_layout/_public/skill': typeof LayoutPublicSkillRoute
'/_layout/_public/': typeof LayoutPublicIndexRoute
'/_layout/_admin/admin/system': typeof LayoutAdminAdminSystemRoute
- '/_layout/_authenticated/accept-invitation/$id': typeof LayoutAuthenticatedAcceptInvitationIdRoute
- '/_layout/_authenticated/organizations/$slug': typeof LayoutAuthenticatedOrganizationsSlugRoute
- '/_layout/_authenticated/organizations/new': typeof LayoutAuthenticatedOrganizationsNewRoute
+ '/_layout/_authenticated/orgs/$slug': typeof LayoutAuthenticatedOrgsSlugRoute
+ '/_layout/_authenticated/orgs/new': typeof LayoutAuthenticatedOrgsNewRoute
'/_layout/_authenticated/settings/auth-methods': typeof LayoutAuthenticatedSettingsAuthMethodsRoute
'/_layout/_authenticated/settings/profile': typeof LayoutAuthenticatedSettingsProfileRoute
'/_layout/_authenticated/settings/security': typeof LayoutAuthenticatedSettingsSecurityRoute
@@ -292,10 +297,11 @@ export interface FileRoutesById {
'/_layout/_public/things/$thingId': typeof LayoutPublicThingsThingIdRoute
'/_layout/_public/things/live': typeof LayoutPublicThingsLiveRoute
'/_layout/_admin/admin/': typeof LayoutAdminAdminIndexRoute
- '/_layout/_authenticated/organizations/': typeof LayoutAuthenticatedOrganizationsIndexRoute
+ '/_layout/_authenticated/orgs/': typeof LayoutAuthenticatedOrgsIndexRoute
'/_layout/_authenticated/settings/': typeof LayoutAuthenticatedSettingsIndexRoute
'/_layout/_public/apps/': typeof LayoutPublicAppsIndexRoute
'/_layout/_public/things/': typeof LayoutPublicThingsIndexRoute
+ '/_layout/_authenticated/orgs/invites/$id': typeof LayoutAuthenticatedOrgsInvitesIdRoute
'/_layout/_public/apps/$accountId/$gatewayId': typeof LayoutPublicAppsAccountIdGatewayIdRoute
'/_layout/_public/apps/$accountId/': typeof LayoutPublicAppsAccountIdIndexRoute
}
@@ -304,16 +310,15 @@ export interface FileRouteTypes {
fullPaths:
| '/'
| '/admin'
+ | '/login'
| '/dashboard'
| '/settings'
| '/$accountId'
| '/about'
- | '/login'
| '/skill'
| '/admin/system'
- | '/accept-invitation/$id'
- | '/organizations/$slug'
- | '/organizations/new'
+ | '/orgs/$slug'
+ | '/orgs/new'
| '/settings/auth-methods'
| '/settings/profile'
| '/settings/security'
@@ -323,24 +328,24 @@ export interface FileRouteTypes {
| '/things/$thingId'
| '/things/live'
| '/admin/'
- | '/organizations/'
+ | '/orgs/'
| '/settings/'
| '/apps/'
| '/things/'
+ | '/orgs/invites/$id'
| '/apps/$accountId/$gatewayId'
| '/apps/$accountId/'
fileRoutesByTo: FileRoutesByTo
to:
| '/'
+ | '/login'
| '/dashboard'
| '/$accountId'
| '/about'
- | '/login'
| '/skill'
| '/admin/system'
- | '/accept-invitation/$id'
- | '/organizations/$slug'
- | '/organizations/new'
+ | '/orgs/$slug'
+ | '/orgs/new'
| '/settings/auth-methods'
| '/settings/profile'
| '/settings/security'
@@ -350,30 +355,31 @@ export interface FileRouteTypes {
| '/things/$thingId'
| '/things/live'
| '/admin'
- | '/organizations'
+ | '/orgs'
| '/settings'
| '/apps'
| '/things'
+ | '/orgs/invites/$id'
| '/apps/$accountId/$gatewayId'
| '/apps/$accountId'
id:
| '__root__'
| '/_layout'
| '/_layout/_admin'
+ | '/_layout/_anon'
| '/_layout/_authenticated'
| '/_layout/_public'
| '/_layout/_admin/admin'
+ | '/_layout/_anon/login'
| '/_layout/_authenticated/dashboard'
| '/_layout/_authenticated/settings'
| '/_layout/_public/$accountId'
| '/_layout/_public/about'
- | '/_layout/_public/login'
| '/_layout/_public/skill'
| '/_layout/_public/'
| '/_layout/_admin/admin/system'
- | '/_layout/_authenticated/accept-invitation/$id'
- | '/_layout/_authenticated/organizations/$slug'
- | '/_layout/_authenticated/organizations/new'
+ | '/_layout/_authenticated/orgs/$slug'
+ | '/_layout/_authenticated/orgs/new'
| '/_layout/_authenticated/settings/auth-methods'
| '/_layout/_authenticated/settings/profile'
| '/_layout/_authenticated/settings/security'
@@ -383,10 +389,11 @@ export interface FileRouteTypes {
| '/_layout/_public/things/$thingId'
| '/_layout/_public/things/live'
| '/_layout/_admin/admin/'
- | '/_layout/_authenticated/organizations/'
+ | '/_layout/_authenticated/orgs/'
| '/_layout/_authenticated/settings/'
| '/_layout/_public/apps/'
| '/_layout/_public/things/'
+ | '/_layout/_authenticated/orgs/invites/$id'
| '/_layout/_public/apps/$accountId/$gatewayId'
| '/_layout/_public/apps/$accountId/'
fileRoutesById: FileRoutesById
@@ -418,6 +425,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof LayoutAuthenticatedRouteImport
parentRoute: typeof LayoutRoute
}
+ '/_layout/_anon': {
+ id: '/_layout/_anon'
+ path: ''
+ fullPath: '/'
+ preLoaderRoute: typeof LayoutAnonRouteImport
+ parentRoute: typeof LayoutRoute
+ }
'/_layout/_admin': {
id: '/_layout/_admin'
path: ''
@@ -439,13 +453,6 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof LayoutPublicSkillRouteImport
parentRoute: typeof LayoutPublicRoute
}
- '/_layout/_public/login': {
- id: '/_layout/_public/login'
- path: '/login'
- fullPath: '/login'
- preLoaderRoute: typeof LayoutPublicLoginRouteImport
- parentRoute: typeof LayoutPublicRoute
- }
'/_layout/_public/about': {
id: '/_layout/_public/about'
path: '/about'
@@ -474,6 +481,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof LayoutAuthenticatedDashboardRouteImport
parentRoute: typeof LayoutAuthenticatedRoute
}
+ '/_layout/_anon/login': {
+ id: '/_layout/_anon/login'
+ path: '/login'
+ fullPath: '/login'
+ preLoaderRoute: typeof LayoutAnonLoginRouteImport
+ parentRoute: typeof LayoutAnonRoute
+ }
'/_layout/_admin/admin': {
id: '/_layout/_admin/admin'
path: '/admin'
@@ -502,11 +516,11 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof LayoutAuthenticatedSettingsIndexRouteImport
parentRoute: typeof LayoutAuthenticatedSettingsRoute
}
- '/_layout/_authenticated/organizations/': {
- id: '/_layout/_authenticated/organizations/'
- path: '/organizations'
- fullPath: '/organizations/'
- preLoaderRoute: typeof LayoutAuthenticatedOrganizationsIndexRouteImport
+ '/_layout/_authenticated/orgs/': {
+ id: '/_layout/_authenticated/orgs/'
+ path: '/orgs'
+ fullPath: '/orgs/'
+ preLoaderRoute: typeof LayoutAuthenticatedOrgsIndexRouteImport
parentRoute: typeof LayoutAuthenticatedRoute
}
'/_layout/_admin/admin/': {
@@ -572,25 +586,18 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof LayoutAuthenticatedSettingsAuthMethodsRouteImport
parentRoute: typeof LayoutAuthenticatedSettingsRoute
}
- '/_layout/_authenticated/organizations/new': {
- id: '/_layout/_authenticated/organizations/new'
- path: '/organizations/new'
- fullPath: '/organizations/new'
- preLoaderRoute: typeof LayoutAuthenticatedOrganizationsNewRouteImport
+ '/_layout/_authenticated/orgs/new': {
+ id: '/_layout/_authenticated/orgs/new'
+ path: '/orgs/new'
+ fullPath: '/orgs/new'
+ preLoaderRoute: typeof LayoutAuthenticatedOrgsNewRouteImport
parentRoute: typeof LayoutAuthenticatedRoute
}
- '/_layout/_authenticated/organizations/$slug': {
- id: '/_layout/_authenticated/organizations/$slug'
- path: '/organizations/$slug'
- fullPath: '/organizations/$slug'
- preLoaderRoute: typeof LayoutAuthenticatedOrganizationsSlugRouteImport
- parentRoute: typeof LayoutAuthenticatedRoute
- }
- '/_layout/_authenticated/accept-invitation/$id': {
- id: '/_layout/_authenticated/accept-invitation/$id'
- path: '/accept-invitation/$id'
- fullPath: '/accept-invitation/$id'
- preLoaderRoute: typeof LayoutAuthenticatedAcceptInvitationIdRouteImport
+ '/_layout/_authenticated/orgs/$slug': {
+ id: '/_layout/_authenticated/orgs/$slug'
+ path: '/orgs/$slug'
+ fullPath: '/orgs/$slug'
+ preLoaderRoute: typeof LayoutAuthenticatedOrgsSlugRouteImport
parentRoute: typeof LayoutAuthenticatedRoute
}
'/_layout/_admin/admin/system': {
@@ -614,6 +621,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof LayoutPublicAppsAccountIdGatewayIdRouteImport
parentRoute: typeof LayoutPublicRoute
}
+ '/_layout/_authenticated/orgs/invites/$id': {
+ id: '/_layout/_authenticated/orgs/invites/$id'
+ path: '/orgs/invites/$id'
+ fullPath: '/orgs/invites/$id'
+ preLoaderRoute: typeof LayoutAuthenticatedOrgsInvitesIdRouteImport
+ parentRoute: typeof LayoutAuthenticatedRoute
+ }
}
}
@@ -642,6 +656,18 @@ const LayoutAdminRouteWithChildren = LayoutAdminRoute._addFileChildren(
LayoutAdminRouteChildren,
)
+interface LayoutAnonRouteChildren {
+ LayoutAnonLoginRoute: typeof LayoutAnonLoginRoute
+}
+
+const LayoutAnonRouteChildren: LayoutAnonRouteChildren = {
+ LayoutAnonLoginRoute: LayoutAnonLoginRoute,
+}
+
+const LayoutAnonRouteWithChildren = LayoutAnonRoute._addFileChildren(
+ LayoutAnonRouteChildren,
+)
+
interface LayoutAuthenticatedSettingsRouteChildren {
LayoutAuthenticatedSettingsAuthMethodsRoute: typeof LayoutAuthenticatedSettingsAuthMethodsRoute
LayoutAuthenticatedSettingsProfileRoute: typeof LayoutAuthenticatedSettingsProfileRoute
@@ -669,31 +695,27 @@ const LayoutAuthenticatedSettingsRouteWithChildren =
interface LayoutAuthenticatedRouteChildren {
LayoutAuthenticatedDashboardRoute: typeof LayoutAuthenticatedDashboardRoute
LayoutAuthenticatedSettingsRoute: typeof LayoutAuthenticatedSettingsRouteWithChildren
- LayoutAuthenticatedAcceptInvitationIdRoute: typeof LayoutAuthenticatedAcceptInvitationIdRoute
- LayoutAuthenticatedOrganizationsSlugRoute: typeof LayoutAuthenticatedOrganizationsSlugRoute
- LayoutAuthenticatedOrganizationsNewRoute: typeof LayoutAuthenticatedOrganizationsNewRoute
+ LayoutAuthenticatedOrgsSlugRoute: typeof LayoutAuthenticatedOrgsSlugRoute
+ LayoutAuthenticatedOrgsNewRoute: typeof LayoutAuthenticatedOrgsNewRoute
LayoutAuthenticatedTenantTenantIdRoute: typeof LayoutAuthenticatedTenantTenantIdRoute
LayoutAuthenticatedTenantNewRoute: typeof LayoutAuthenticatedTenantNewRoute
LayoutAuthenticatedThingsNewRoute: typeof LayoutAuthenticatedThingsNewRoute
- LayoutAuthenticatedOrganizationsIndexRoute: typeof LayoutAuthenticatedOrganizationsIndexRoute
+ LayoutAuthenticatedOrgsIndexRoute: typeof LayoutAuthenticatedOrgsIndexRoute
+ LayoutAuthenticatedOrgsInvitesIdRoute: typeof LayoutAuthenticatedOrgsInvitesIdRoute
}
const LayoutAuthenticatedRouteChildren: LayoutAuthenticatedRouteChildren = {
LayoutAuthenticatedDashboardRoute: LayoutAuthenticatedDashboardRoute,
LayoutAuthenticatedSettingsRoute:
LayoutAuthenticatedSettingsRouteWithChildren,
- LayoutAuthenticatedAcceptInvitationIdRoute:
- LayoutAuthenticatedAcceptInvitationIdRoute,
- LayoutAuthenticatedOrganizationsSlugRoute:
- LayoutAuthenticatedOrganizationsSlugRoute,
- LayoutAuthenticatedOrganizationsNewRoute:
- LayoutAuthenticatedOrganizationsNewRoute,
+ LayoutAuthenticatedOrgsSlugRoute: LayoutAuthenticatedOrgsSlugRoute,
+ LayoutAuthenticatedOrgsNewRoute: LayoutAuthenticatedOrgsNewRoute,
LayoutAuthenticatedTenantTenantIdRoute:
LayoutAuthenticatedTenantTenantIdRoute,
LayoutAuthenticatedTenantNewRoute: LayoutAuthenticatedTenantNewRoute,
LayoutAuthenticatedThingsNewRoute: LayoutAuthenticatedThingsNewRoute,
- LayoutAuthenticatedOrganizationsIndexRoute:
- LayoutAuthenticatedOrganizationsIndexRoute,
+ LayoutAuthenticatedOrgsIndexRoute: LayoutAuthenticatedOrgsIndexRoute,
+ LayoutAuthenticatedOrgsInvitesIdRoute: LayoutAuthenticatedOrgsInvitesIdRoute,
}
const LayoutAuthenticatedRouteWithChildren =
@@ -702,7 +724,6 @@ const LayoutAuthenticatedRouteWithChildren =
interface LayoutPublicRouteChildren {
LayoutPublicAccountIdRoute: typeof LayoutPublicAccountIdRoute
LayoutPublicAboutRoute: typeof LayoutPublicAboutRoute
- LayoutPublicLoginRoute: typeof LayoutPublicLoginRoute
LayoutPublicSkillRoute: typeof LayoutPublicSkillRoute
LayoutPublicIndexRoute: typeof LayoutPublicIndexRoute
LayoutPublicThingsThingIdRoute: typeof LayoutPublicThingsThingIdRoute
@@ -716,7 +737,6 @@ interface LayoutPublicRouteChildren {
const LayoutPublicRouteChildren: LayoutPublicRouteChildren = {
LayoutPublicAccountIdRoute: LayoutPublicAccountIdRoute,
LayoutPublicAboutRoute: LayoutPublicAboutRoute,
- LayoutPublicLoginRoute: LayoutPublicLoginRoute,
LayoutPublicSkillRoute: LayoutPublicSkillRoute,
LayoutPublicIndexRoute: LayoutPublicIndexRoute,
LayoutPublicThingsThingIdRoute: LayoutPublicThingsThingIdRoute,
@@ -734,12 +754,14 @@ const LayoutPublicRouteWithChildren = LayoutPublicRoute._addFileChildren(
interface LayoutRouteChildren {
LayoutAdminRoute: typeof LayoutAdminRouteWithChildren
+ LayoutAnonRoute: typeof LayoutAnonRouteWithChildren
LayoutAuthenticatedRoute: typeof LayoutAuthenticatedRouteWithChildren
LayoutPublicRoute: typeof LayoutPublicRouteWithChildren
}
const LayoutRouteChildren: LayoutRouteChildren = {
LayoutAdminRoute: LayoutAdminRouteWithChildren,
+ LayoutAnonRoute: LayoutAnonRouteWithChildren,
LayoutAuthenticatedRoute: LayoutAuthenticatedRouteWithChildren,
LayoutPublicRoute: LayoutPublicRouteWithChildren,
}
diff --git a/ui/src/routes/_layout/_admin/admin.tsx b/ui/src/routes/_layout/_admin/admin.tsx
index e57fd806..9fee1727 100644
--- a/ui/src/routes/_layout/_admin/admin.tsx
+++ b/ui/src/routes/_layout/_admin/admin.tsx
@@ -55,7 +55,7 @@ function AdminPage() {
home
organizations
@@ -93,7 +93,7 @@ function AdminPage() {
label="Organization"
value={
diff --git a/ui/src/routes/_layout/_admin/admin/index.tsx b/ui/src/routes/_layout/_admin/admin/index.tsx
index fd5a7378..137d4e33 100644
--- a/ui/src/routes/_layout/_admin/admin/index.tsx
+++ b/ui/src/routes/_layout/_admin/admin/index.tsx
@@ -53,7 +53,7 @@ function AdminDashboard() {
Manage organizations, members, roles, and invitations.
diff --git a/ui/src/routes/_layout/_authenticated.tsx b/ui/src/routes/_layout/_authenticated.tsx
index 72eae14a..75ca082d 100644
--- a/ui/src/routes/_layout/_authenticated.tsx
+++ b/ui/src/routes/_layout/_authenticated.tsx
@@ -1,5 +1,5 @@
import { createFileRoute, Link, Outlet, redirect, useRouterState } from "@tanstack/react-router";
-import { ClipboardList, Compass, Globe, Home, Menu, MessageSquare, Shield } from "lucide-react";
+import { ClipboardList, Compass, Globe, Home, Menu, Shield } from "lucide-react";
import { useState } from "react";
import type { SessionData } from "@/app";
import { getAccount, getActiveRuntime, getAppName, sessionQueryOptions } from "@/app";
@@ -96,7 +96,6 @@ function AuthenticatedLayout() {
const sidebarItems: SidebarItem[] = [
{ icon: Home, label: "dashboard", to: "/dashboard", roleRequired: "anon" },
{ icon: Shield, label: "admin", to: "/admin", roleRequired: "admin" },
- { icon: MessageSquare, label: "nostr", to: "/nostr", roleRequired: "admin" },
];
const visibleItems = filterSidebarByRole(sidebarItems, getUserRole(true, isAdmin));
diff --git a/ui/src/routes/_layout/_authenticated/organizations/$slug.tsx b/ui/src/routes/_layout/_authenticated/orgs/$slug.tsx
similarity index 99%
rename from ui/src/routes/_layout/_authenticated/organizations/$slug.tsx
rename to ui/src/routes/_layout/_authenticated/orgs/$slug.tsx
index e95cc943..ae78e315 100644
--- a/ui/src/routes/_layout/_authenticated/organizations/$slug.tsx
+++ b/ui/src/routes/_layout/_authenticated/orgs/$slug.tsx
@@ -59,7 +59,7 @@ const orgMembersQueryKey = (orgId: string) => ["org-members", orgId] as const;
const orgInvitationsQueryKey = (orgId: string) => ["org-invitations", orgId] as const;
const orgApiKeysQueryKey = (orgId: string) => ["org-api-keys", orgId] as const;
-export const Route = createFileRoute("/_layout/_authenticated/organizations/$slug")({
+export const Route = createFileRoute("/_layout/_authenticated/orgs/$slug")({
head: () => ({
title: "Organization | auth.everything.dev",
meta: [{ name: "description", content: "Manage organization details and members." }],
@@ -328,7 +328,7 @@ function OrganizationDetail() {
onSuccess: async () => {
toast.success("You have left the organization");
await queryClient.invalidateQueries({ queryKey: ["organizations"] });
- await router.navigate({ to: "/organizations" });
+ await router.navigate({ to: "/orgs" });
},
onError: (error: Error) => toast.error(error.message || "Failed to leave organization"),
});
@@ -341,7 +341,7 @@ function OrganizationDetail() {
onSuccess: async () => {
toast.success("Organization deleted");
await queryClient.invalidateQueries({ queryKey: ["organizations"] });
- await router.navigate({ to: "/organizations" });
+ await router.navigate({ to: "/orgs" });
},
onError: (error: Error) => toast.error(error.message || "Failed to delete organization"),
});
@@ -369,7 +369,7 @@ function OrganizationDetail() {
description="This organization does not exist or you do not have access."
action={
}
/>
@@ -383,7 +383,7 @@ function OrganizationDetail() {
@@ -122,7 +122,7 @@ function NewOrganization() {
- );
+ )
}
function Field({
diff --git a/ui/src/routes/_layout/_authenticated/tenant/$tenantId.tsx b/ui/src/routes/_layout/_authenticated/tenant/$tenantId.tsx
index 4a49f5c9..e9d6e78b 100644
--- a/ui/src/routes/_layout/_authenticated/tenant/$tenantId.tsx
+++ b/ui/src/routes/_layout/_authenticated/tenant/$tenantId.tsx
@@ -403,7 +403,7 @@ function TenantDetail() {
there.