diff --git a/server/landing.ts b/server/landing.ts
index f7f96782..f55cb6a2 100644
--- a/server/landing.ts
+++ b/server/landing.ts
@@ -17,10 +17,11 @@ export function renderMainLanding(modules: ModuleInfo[]): string {
const ecosystemCards = modules
.map(
(m) => `
-
-
- ${escapeHtml(m.description)} ${escapeHtml(m.description)}${escapeHtml(m.name)}
- ${escapeHtml(m.name)}
+ ${m.standaloneDomain ? `${escapeHtml(m.standaloneDomain)}` : ""}
+
Remember back when the internet was cool?
++ Remember back when the internet was cool? +
++ We may not have MySpace anymore, but we have (you)rSpace. +
- A collaborative, local-first platform with ${modules.length}+ interoperable tools. - Own your data, run your community, connect your world — no landlords required. + Build digital spaces to collaborate on improving your physical world. + Local-first, zero-knowledge privacy, outside the walls of big tech.
Budget rivers, revenue splits, and enoughness thresholds. Transparent finances with quadratic funding built in.
Real-time chat, threaded discussions, and async forums. All synced across devices with CRDT magic.
Upload, organize, and share with memory cards. Public links, folder trees, and metadata that travels with content.
One passwordless login for the entire ecosystem. EncryptID uses WebAuthn — no passwords to leak, no accounts to hack.
Community analytics, voting results, spatial canvases. See everything at a glance and drill into what matters.
Your data lives on your device first. End-to-end encrypted sync, per-document keys, zero-knowledge architecture.
+ Secure by default, not by opt-in. +
Sign in once with your fingerprint or device PIN. Your passkey works - across every rApp — no passwords, no email verification loops, - no third-party auth providers. + across every rApp — no passwords, no email loops, + no third-party auth providers watching over your shoulder.
Touch your fingerprint sensor, tap your security key, or use your device PIN. That’s it.
+Touch. Tap. Done.
Only changed bytes travel over the wire. Reconnect after days offline and catch up in seconds.
+ Under the hood: Automerge CRDTs model every document as a mergeable data structure. + IndexedDB persists the full state locally so you never lose work. + A Service Worker caches the app shell for instant loads — even without a network connection. +
++ Every rApp reads and writes to the same sync layer. + No import/export rituals — data flows between tools automatically. +
+ rDocs rCal rTasks rMaps rWallet ...
+ | | | | |
+ v v v v v
+ +--------------------------------------+
+ | Automerge Sync Layer |
+ | (encrypted, per-document keys) |
+ +--------------------------------------+
+ | | | | |
+ v v v v v
+ Your Your Your Your Your
+ Device Phone Laptop Server Backup
+ +
No algorithms deciding what you see. No ads. No data harvesting. Just tools that work for you, run by you, owned by you. - rSpace is infrastructure for communities who refuse to rent their digital commons. +
++ rSpace is infrastructure for communities who refuse to rent their digital commons + from landlords who read the mail, count the footsteps, and sell the maps. +
++ Your space. Your community. Your rules.
@@ -227,14 +292,25 @@ export function renderMainLanding(modules: ModuleInfo[]): string { @@ -432,7 +508,9 @@ const SPACE_DASHBOARD_CSS = ` `; const MAIN_LANDING_CSS = ` -/* Main landing page extras (on top of rl-* utilities) */ +/* ── Main landing page extras (on top of rl-* utilities) ── */ + +/* Background + diagonal stripe overlay */ body { background: linear-gradient( 170deg, @@ -445,8 +523,57 @@ body { ); background-attachment: fixed; } +body::before { + content: ""; + position: fixed; inset: 0; + background: repeating-linear-gradient( + -45deg, + transparent, + transparent 60px, + rgba(20,184,166,0.015) 60px, + rgba(20,184,166,0.015) 61px + ); + pointer-events: none; + z-index: 0; +} +[data-theme="light"] body { + background: linear-gradient(170deg, #f8fafc 0%, #f1f5f9 50%, #e2e8f0 100%); +} +[data-theme="light"] body::before { + background: repeating-linear-gradient( + -45deg, + transparent, + transparent 60px, + rgba(20,184,166,0.03) 60px, + rgba(20,184,166,0.03) 61px + ); +} + +/* ── Hero ── */ +.hero-glow-wrap { position: relative; overflow: hidden; } +.hero-glow { + position: absolute; + top: 50%; left: 50%; + width: 600px; height: 600px; + transform: translate(-50%, -60%); + border-radius: 50%; + background: radial-gradient(circle, rgba(20,184,166,0.15) 0%, transparent 70%); + animation: hero-pulse 4s ease-in-out infinite; + pointer-events: none; + z-index: 0; +} +[data-theme="light"] .hero-glow { + background: radial-gradient(circle, rgba(20,184,166,0.1) 0%, transparent 70%); +} +@keyframes hero-pulse { + 0%, 100% { opacity: 0.6; transform: translate(-50%, -60%) scale(1); } + 50% { opacity: 1; transform: translate(-50%, -60%) scale(1.08); } +} +.rl-hero > * { position: relative; z-index: 1; } + .main-wordmark { font-size: 3.5rem; + text-shadow: 0 0 40px rgba(20,184,166,0.2); } @media (min-width: 640px) { .main-wordmark { font-size: 4.5rem; } } .main-wordmark__accent { @@ -454,12 +581,218 @@ body { -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } + +.accent-cool { + color: var(--rs-accent); + font-weight: 700; + -webkit-text-fill-color: var(--rs-accent); +} + +/* Badge bar with star separators */ .main-badges { display: flex; gap: 0.5rem; justify-content: center; flex-wrap: wrap; + align-items: center; margin-top: 1.5rem; } +.main-badges .rl-badge { + font-weight: 800; + letter-spacing: 0.04em; +} +.badge-sep { + color: var(--rs-accent); + font-size: 0.5rem; + opacity: 0.6; +} + +/* ── Feature Cards (SVG icons, border glow) ── */ +.feat-card { + background: var(--rs-card-bg); + border: 2px solid var(--rs-card-border); + border-radius: 1rem; + padding: 1.75rem; + text-align: center; + transition: border-color 0.25s, box-shadow 0.25s, transform 0.2s; +} +.feat-card:hover { + transform: translateY(-2px); +} +.feat-card--teal:hover { + border-color: rgba(20,184,166,0.5); + box-shadow: 0 0 20px rgba(20,184,166,0.12); +} +.feat-card--indigo:hover { + border-color: rgba(99,102,241,0.5); + box-shadow: 0 0 20px rgba(99,102,241,0.12); +} +.feat-card__icon { + width: 3rem; height: 3rem; border-radius: 0.75rem; + display: flex; align-items: center; justify-content: center; + margin: 0 auto 1rem; + font-size: 1.5rem; +} +.feat-card--teal .feat-card__icon { + background: rgba(20,184,166,0.12); color: #14b8a6; +} +.feat-card--indigo .feat-card__icon { + background: rgba(99,102,241,0.12); color: #6366f1; +} +.feat-card h3 { + font-size: 0.95rem; font-weight: 600; color: var(--rs-text-primary); margin-bottom: 0.5rem; +} +.feat-card p { + font-size: 0.875rem; color: var(--rs-text-secondary); line-height: 1.6; +} + +/* ── EncryptID Visual ── */ +.encryptid-visual { + text-align: center; +} +.encryptid-shield { + width: 140px; height: 160px; + color: var(--rs-accent); + filter: drop-shadow(0 0 20px rgba(20,184,166,0.2)); +} +.encryptid-visual__label { + font-size: 0.9rem; font-weight: 600; + color: var(--rs-text-secondary); + margin-top: 1rem; +} + +/* ── Offline-First Explainer ── */ +.offline-explain { + text-align: center; + font-size: 0.85rem; + color: var(--rs-text-muted); + line-height: 1.65; + max-width: 640px; + margin: 2rem auto 0; + border-top: 1px solid var(--rs-border-subtle); + padding-top: 1.5rem; +} +.offline-explain strong { + color: var(--rs-text-secondary); + font-weight: 600; +} + +/* ── Interop Diagram ── */ +.interop-diagram { + margin-top: 2rem; +} +.interop-pre { + display: inline-block; + text-align: left; + font-family: "SF Mono", "Fira Code", "Cascadia Code", monospace; + font-size: 0.78rem; + line-height: 1.6; + color: var(--rs-text-secondary); + background: var(--rs-card-bg); + border: 1px solid var(--rs-card-border); + border-radius: 0.75rem; + padding: 1.5rem 2rem; + overflow-x: auto; + max-width: 100%; + box-shadow: 0 2px 12px rgba(0,0,0,0.15); +} +[data-theme="light"] .interop-pre { + box-shadow: 0 2px 12px rgba(0,0,0,0.06); +} + +/* ── Philosophy Punch ── */ +.philosophy-punch { + font-size: 1.3rem; + font-weight: 700; + background: var(--rs-gradient-brand); + -webkit-background-clip: text; -webkit-text-fill-color: transparent; + background-clip: text; + margin: 1.5rem 0 0; + letter-spacing: -0.01em; +} + +/* ── Ecosystem Cards ── */ +.eco-card { + background: var(--rs-card-bg); + border: 2px solid var(--rs-card-border); + border-radius: 1rem; + padding: 1.5rem; + text-align: center; + transition: border-color 0.25s, box-shadow 0.25s, transform 0.2s; + display: flex; flex-direction: column; align-items: center; +} +.eco-card:hover { + border-color: rgba(20,184,166,0.4); + box-shadow: 0 0 16px rgba(20,184,166,0.1); + transform: translateY(-2px); +} +.eco-card__icon { + font-size: 1.75rem; + margin-bottom: 0.5rem; +} +.eco-card__name { + font-size: 0.9rem; font-weight: 600; + color: var(--rs-text-primary); + margin: 0 0 0.15rem; +} +.eco-card__domain { + font-size: 0.65rem; font-weight: 600; + color: var(--rs-accent); + opacity: 0.75; + letter-spacing: 0.02em; + margin-bottom: 0.4rem; + display: block; +} +.eco-card__desc { + font-size: 0.78rem; color: var(--rs-text-secondary); + line-height: 1.5; margin: 0; +} + +/* ── Footer ── */ .main-footer { border-top: 1px solid var(--rs-border-subtle); - padding: 2.5rem 1.5rem; + padding: 2.5rem 1.5rem 2rem; +} +.footer-quicklinks { + display: flex; gap: 1.25rem; justify-content: center; flex-wrap: wrap; + margin-bottom: 1.25rem; +} +.footer-quicklinks a { + font-size: 0.75rem; font-weight: 600; + color: var(--rs-text-muted); + text-decoration: none; + transition: color 0.2s; +} +.footer-quicklinks a:hover { color: var(--rs-accent); } +.footer-tagline { + font-size: 0.8rem; font-weight: 700; + color: var(--rs-accent); + letter-spacing: 0.06em; + text-transform: uppercase; + margin: 0 0 1rem; + opacity: 0.7; +} +.footer-links { + display: flex; gap: 1.5rem; justify-content: center; flex-wrap: wrap; + margin-bottom: 1rem; +} +.footer-links a { + color: #94a3b8; font-size: 0.8rem; text-decoration: none; + transition: color 0.2s; +} +.footer-links a:hover { color: var(--rs-text-primary); } +.footer-tech { + color: #64748b; font-size: 0.75rem; margin: 0; +} + +/* ── Retro Shadow Utility ── */ +.retro-shadow { + box-shadow: 2px 2px 0 var(--rs-card-border); +} + +/* ── Responsive ── */ +@media (max-width: 480px) { + .main-wordmark { font-size: 2.75rem; } + .hero-glow { width: 350px; height: 350px; } + .interop-pre { font-size: 0.65rem; padding: 1rem; } + .philosophy-punch { font-size: 1.1rem; } + .footer-quicklinks { gap: 0.75rem; } } `;