diff --git a/server/index.ts b/server/index.ts index 48d2d21..c4c8b03 100644 --- a/server/index.ts +++ b/server/index.ts @@ -319,14 +319,17 @@ app.get("/", async (c) => { }); // Create new space page -app.get("/new", async (c) => { - const file = Bun.file(resolve(DIST_DIR, "index.html")); +app.get("/create-space", async (c) => { + const file = Bun.file(resolve(DIST_DIR, "create-space.html")); if (await file.exists()) { return new Response(file, { headers: { "Content-Type": "text/html" } }); } return c.text("Create space", 200); }); +// Legacy redirect +app.get("/new", (c) => c.redirect("/create-space", 301)); + // Space root: /:space → redirect to /:space/canvas app.get("/:space", (c) => { const space = c.req.param("space"); diff --git a/vite.config.ts b/vite.config.ts index e295fb0..896441c 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -704,6 +704,7 @@ export default defineConfig({ input: { index: resolve(__dirname, "./website/index.html"), canvas: resolve(__dirname, "./website/canvas.html"), + "create-space": resolve(__dirname, "./website/create-space.html"), }, }, modulePreload: { diff --git a/website/create-space.html b/website/create-space.html new file mode 100644 index 0000000..d3c241d --- /dev/null +++ b/website/create-space.html @@ -0,0 +1,317 @@ + + + + + + + Create a Space — rSpace + + + + + +
+
+ + +
+
+ +
+
+
+
+

Create a Space

+

Start a collaborative community space with all the r* tools built in.

+ +
+
+ + +
+
+ + +

Your space will be at: ___.rspace.online

+
+
+ + +

You can change this later in space settings.

+
+ + +
+ + ← Back to rSpace +
+
+ + + + diff --git a/website/index.html b/website/index.html index 9ca9d78..888c994 100644 --- a/website/index.html +++ b/website/index.html @@ -52,75 +52,47 @@ margin-bottom: 3rem; } - .create-form { + .cta-buttons { display: flex; - flex-direction: column; gap: 1rem; - background: rgba(255, 255, 255, 0.05); - padding: 2rem; - border-radius: 16px; - border: 1px solid rgba(255, 255, 255, 0.1); + justify-content: center; + flex-wrap: wrap; } - .form-group { - display: flex; - flex-direction: column; - gap: 0.5rem; - text-align: left; - } - - label { - font-size: 0.875rem; - color: #94a3b8; - } - - input { - padding: 12px 16px; + .cta-primary { + display: inline-block; + padding: 14px 32px; border-radius: 8px; - border: 1px solid rgba(255, 255, 255, 0.2); - background: rgba(255, 255, 255, 0.05); - color: white; - font-size: 1rem; - } - - input:focus { - outline: none; - border-color: #14b8a6; - } - - input::placeholder { - color: #64748b; - } - - .slug-preview { - font-size: 0.875rem; - color: #64748b; - margin-top: 0.25rem; - } - - .slug-preview span { - color: #14b8a6; - } - - button { - padding: 14px 28px; - border-radius: 8px; - border: none; background: linear-gradient(135deg, #14b8a6, #0d9488); color: white; font-size: 1rem; font-weight: 600; - cursor: pointer; + text-decoration: none; transition: transform 0.2s, box-shadow 0.2s; } - button:hover { + .cta-primary:hover { transform: translateY(-2px); box-shadow: 0 8px 20px rgba(20, 184, 166, 0.3); } - button:active { - transform: translateY(0); + .cta-secondary { + display: inline-block; + padding: 14px 32px; + border-radius: 8px; + background: rgba(255, 255, 255, 0.05); + border: 1px solid rgba(255, 255, 255, 0.2); + color: #94a3b8; + font-size: 1rem; + font-weight: 600; + text-decoration: none; + transition: transform 0.2s, border-color 0.2s, color 0.2s; + } + + .cta-secondary:hover { + transform: translateY(-2px); + border-color: rgba(255, 255, 255, 0.4); + color: white; } .features { @@ -149,17 +121,6 @@ color: #64748b; } - .error { - color: #ef4444; - font-size: 0.875rem; - margin-top: 0.5rem; - } - - .success { - color: #22c55e; - font-size: 0.875rem; - } - /* EncryptID & Ecosystem Sections */ .section { @@ -354,30 +315,10 @@

rSpace

Collaborative community spaces powered by FolkJS

-
-
- - -
-
- - -

Your space will be at: ___.rspace.online

-
- - -
+
+ Create a Space + Try the Demo +
@@ -580,94 +521,14 @@ import { RStackIdentity } from "@shared/components/rstack-identity"; import { RStackAppSwitcher } from "@shared/components/rstack-app-switcher"; import { RStackSpaceSwitcher } from "@shared/components/rstack-space-switcher"; - import { requireAuth, isAuthenticated, getAccessToken } from "@shared/components/rstack-identity"; - // Register shell header components RStackIdentity.define(); RStackAppSwitcher.define(); RStackSpaceSwitcher.define(); - // Load module list for app switcher fetch("/api/modules").then(r => r.json()).then(data => { document.querySelector("rstack-app-switcher")?.setModules(data.modules || []); }).catch(() => {}); - - const nameInput = document.getElementById("community-name"); - const slugInput = document.getElementById("community-slug"); - const slugPreview = document.getElementById("slug-preview"); - const form = document.getElementById("create-form"); - const errorMessage = document.getElementById("error-message"); - - // Auto-generate slug from name - nameInput.addEventListener("input", () => { - const slug = nameInput.value - .toLowerCase() - .replace(/[^a-z0-9]+/g, "-") - .replace(/^-|-$/g, ""); - slugInput.value = slug; - slugPreview.textContent = slug ? `${slug}.rspace.online` : "___.rspace.online"; - }); - - slugInput.addEventListener("input", () => { - const slug = slugInput.value.toLowerCase().replace(/[^a-z0-9-]/g, ""); - slugInput.value = slug; - slugPreview.textContent = slug ? `${slug}.rspace.online` : "___.rspace.online"; - }); - - async function submitCreateCommunity() { - errorMessage.style.display = "none"; - - const name = nameInput.value.trim(); - const slug = slugInput.value.trim(); - - if (!name || !slug) { - errorMessage.textContent = "Please fill in all fields"; - errorMessage.style.display = "block"; - return; - } - - const token = getAccessToken(); - if (!token) { - errorMessage.textContent = "Authentication token missing. Please sign in again."; - errorMessage.style.display = "block"; - return; - } - - try { - const response = await fetch("/api/communities", { - method: "POST", - headers: { - "Content-Type": "application/json", - "Authorization": `Bearer ${token}`, - }, - body: JSON.stringify({ name, slug }), - }); - - const data = await response.json(); - - if (!response.ok) { - throw new Error(data.error || "Failed to create community"); - } - - // Redirect to the new community space - window.location.href = data.url; - } catch (err) { - errorMessage.textContent = err.message; - errorMessage.style.display = "block"; - } - } - - form.addEventListener("submit", (e) => { - e.preventDefault(); - - // If not authenticated, show auth modal; after success, re-submit - if (!isAuthenticated()) { - requireAuth(() => submitCreateCommunity()); - return; - } - - submitCreateCommunity(); - });