From 73aee64401330fe8305a735c3d4db9bc6fbf317e Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Wed, 18 Feb 2026 14:20:57 -0700 Subject: [PATCH] feat: add path-based community routing under subdomain namespaces cca.rspace.online/campaign/demo now loads the campaign-demo community. Path segments are joined with hyphens to derive the slug. Subdomain acts as a brand namespace; root path still loads the subdomain slug. Co-Authored-By: Claude Opus 4.6 --- server/index.ts | 18 ++++++++++++++++-- website/canvas.html | 13 ++++++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/server/index.ts b/server/index.ts index 87107ae..b7825f2 100644 --- a/server/index.ts +++ b/server/index.ts @@ -210,10 +210,24 @@ const server = Bun.serve({ } // Community canvas route (subdomain detected) + // Supports path-based slugs: cca.rspace.online/campaign/demo → slug "campaign-demo" if (subdomain) { - const community = await loadCommunity(subdomain); + const pathSegments = url.pathname.split("/").filter(Boolean); + + // Derive slug: path segments joined with "-", or subdomain if at root + const slug = pathSegments.length > 0 ? pathSegments.join("-") : subdomain; + + const community = await loadCommunity(slug); if (!community) { - return new Response("Community not found", { status: 404 }); + // Path slug not found — fall back to subdomain slug if path was given + if (pathSegments.length > 0) { + const fallback = await loadCommunity(subdomain); + if (!fallback) { + return new Response("Community not found", { status: 404 }); + } + } else { + return new Response("Community not found", { status: 404 }); + } } // Serve canvas.html for community diff --git a/website/canvas.html b/website/canvas.html index 02151c9..559c3b6 100644 --- a/website/canvas.html +++ b/website/canvas.html @@ -343,11 +343,22 @@ FolkSocialPost.define(); // Get community info from URL + // Supports path-based slugs: cca.rspace.online/campaign/demo → slug "campaign-demo" const hostname = window.location.hostname; const subdomain = hostname.split(".")[0]; const isLocalhost = hostname === "localhost" || hostname === "127.0.0.1"; const urlParams = new URLSearchParams(window.location.search); - const communitySlug = urlParams.get("space") || (isLocalhost ? "demo" : subdomain); + + const pathSegments = window.location.pathname.split("/").filter(Boolean); + const ignorePaths = ["canvas", "settings", "api"]; + const cleanSegments = pathSegments.filter(s => !ignorePaths.includes(s)); + + let communitySlug = urlParams.get("space"); + if (!communitySlug && cleanSegments.length > 0) { + communitySlug = cleanSegments.join("-"); + } else if (!communitySlug) { + communitySlug = isLocalhost ? "demo" : subdomain; + } // Update UI document.getElementById("community-name").textContent = communitySlug;