Merge branch 'dev': port 10 module landing pages from standalone sites

This commit is contained in:
Jeff Emmett 2026-02-28 04:09:27 +00:00
commit c20a79078a
10 changed files with 1709 additions and 1180 deletions

View File

@ -1,152 +1,202 @@
/** /**
* rCal landing page relational calendar. * rCal landing page relational calendar.
* Ported from rcal-online Next.js page.tsx (318 lines).
*/ */
export function renderLanding(): string { export function renderLanding(): string {
return ` return `
<!-- Hero --> <!-- Hero -->
<div class="rl-hero"> <div class="rl-hero">
<span class="rl-tagline">rCal</span> <span class="rl-tagline" style="color:#60a5fa;background:rgba(96,165,250,0.1);border-color:rgba(96,165,250,0.2)">
<h1 class="rl-heading">(You)rCal, your rhythm.</h1> Relational Calendar
<p class="rl-subtitle">Time is shared. Your calendar should be too.</p> </span>
<h1 class="rl-heading" style="background:linear-gradient(to right,#60a5fa,#818cf8,#a78bfa);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">
Time is shared. Your calendar should be too.
</h1>
<p class="rl-subtitle">
A collaborative calendar for communities, cooperatives, and coordinated groups.
</p>
<p class="rl-subtext"> <p class="rl-subtext">
A spatiotemporal calendar that couples where and when, supports natural cycles, rCal rethinks the calendar as a <span style="color:#60a5fa;font-weight:600">shared, spatial, and cyclical</span> tool.
and zooms from 30-second moments to geological epochs. See events across time and place, overlay lunar cycles, zoom from a single hour to a whole decade,
and keep everyone on the same page &mdash; without the back-and-forth.
</p> </p>
<div class="rl-cta-row"> <div class="rl-cta-row">
<a href="https://demo.rspace.online/rcal" class="rl-cta-primary" id="ml-primary">Open Calendar</a> <a href="https://demo.rspace.online/rcal" class="rl-cta-primary" id="ml-primary"
<a href="/create-space" class="rl-cta-secondary">Create a Space</a> style="background:linear-gradient(to right,#60a5fa,#6366f1);color:#0b1120">
Try the Demo
</a>
<a href="#features" class="rl-cta-secondary">Learn More</a>
</div> </div>
</div> </div>
<!-- Features --> <!-- Principles (4-card grid) -->
<section class="rl-section"> <section class="rl-section" style="border-top:none">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">What rCal Handles</h2>
<div class="rl-grid-4"> <div class="rl-grid-4">
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center" style="padding:2rem">
<div class="rl-icon-box">&#128301;</div> <div class="rl-icon-box" style="background:rgba(96,165,250,0.12);font-size:1.5rem">
<h3>Temporal Zoom</h3> <span style="font-size:1.5rem">&#129309;</span>
<p>Ten zoom levels from 30-second moments to cosmic time. Year, month, week, day &mdash; and beyond.</p> </div>
<h3>Shared by Default</h3>
<p>One calendar for the whole group. Everyone sees the same context &mdash; no more fragmented schedules.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center" style="padding:2rem">
<div class="rl-icon-box">&#128197;</div> <div class="rl-icon-box" style="background:rgba(129,140,248,0.12);font-size:1.5rem">
<h3>Shared Events</h3> <span style="font-size:1.5rem">&#128506;</span>
<p>Calendars belong to spaces, not individuals. Everyone sees the same schedule by default.</p> </div>
<h3>Spatiotemporal</h3>
<p>Events have a where, not just a when. See your schedule on a map and a timeline simultaneously.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center" style="padding:2rem">
<div class="rl-icon-box">&#127769;</div> <div class="rl-icon-box" style="background:rgba(167,139,250,0.12);font-size:1.5rem">
<h3>Lunar Phases</h3> <span style="font-size:1.5rem">&#127769;</span>
<p>Moon phases, solstices, and seasonal rhythms overlaid on the Gregorian grid. Plan with natural cycles.</p> </div>
<h3>Natural Cycles</h3>
<p>Lunar phases, eclipses, and solstices built in. Reconnect your planning to the rhythms of the natural world.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center" style="padding:2rem">
<div class="rl-icon-box">&#128506;</div> <div class="rl-icon-box" style="background:rgba(52,211,153,0.12);font-size:1.5rem">
<h3>Location-Aware</h3> <span style="font-size:1.5rem">&#128301;</span>
<p>Events have places, not just times. Spatial and temporal zoom are coupled at every level.</p> </div>
<h3>Multi-Scale Zoom</h3>
<p>Ten levels of time &mdash; from a 30-second moment to a cosmic era. See today or plan a decade ahead.</p>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- How It Works --> <!-- Why rCal -->
<section class="rl-section rl-section--alt"> <section id="features" class="rl-section rl-section--alt">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">How It Works</h2> <span class="rl-tagline" style="color:#60a5fa;background:rgba(96,165,250,0.1);border-color:rgba(96,165,250,0.2)">
<div class="rl-grid-3"> Why rCal?
<div class="rl-step"> </span>
<span class="rl-step__num">1</span> <h2 class="rl-heading" style="background:linear-gradient(135deg,#60a5fa,#818cf8);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">
<h3>Create events</h3> Calendars were never meant to be personal silos
<p>Add events with time, location, and source context. Pull from ICS feeds, CalDAV, or other r* modules.</p> </h2>
<p class="rl-subtext" style="margin-bottom:2.5rem">
Mainstream calendars treat time as private property. rCal treats it as a <span style="color:#60a5fa;font-weight:600">commons</span> &mdash;
something groups navigate together. Here&rsquo;s what makes it different.
</p>
<div class="rl-grid-2">
<div class="rl-card" style="border-color:rgba(96,165,250,0.12)">
<div style="font-size:1.75rem;margin-bottom:1rem">&#128205;</div>
<h3>Where + When, Together</h3>
<p>Every event lives on both a timeline and a map. rCal&rsquo;s split view lets you see where everyone is meeting and when &mdash; with nine spatial zoom levels from planet to street address.</p>
</div> </div>
<div class="rl-step"> <div class="rl-card" style="border-color:rgba(96,165,250,0.12)">
<span class="rl-step__num">2</span> <div style="font-size:1.75rem;margin-bottom:1rem">&#128279;</div>
<h3>Zoom and explore</h3> <h3>Coupled Zoom</h3>
<p>Navigate across ten temporal zoom levels. Spatial and temporal zoom are coupled &mdash; zoom out in time and the map zooms out too.</p> <p>Lock temporal and spatial zoom together: zoom out in time and the map zooms out to match. Planning a week? See the city. Planning a decade? See the continent.</p>
</div> </div>
<div class="rl-step"> <div class="rl-card" style="border-color:rgba(96,165,250,0.12)">
<span class="rl-step__num">3</span> <div style="font-size:1.75rem;margin-bottom:1rem">&#128225;</div>
<h3>Share with your space</h3> <h3>Multi-Source Sync</h3>
<p>Space members see the same calendar. rWork sprints, rVote deadlines, rTrips itineraries &mdash; all in one view.</p> <p>Import from Google, Outlook, Apple, CalDAV, ICS feeds, and Obsidian. Layer multiple sources with per-source color coding and visibility controls.</p>
</div>
<div class="rl-card" style="border-color:rgba(96,165,250,0.12)">
<div style="font-size:1.75rem;margin-bottom:1rem">&#127761;</div>
<h3>Lunar Overlay</h3>
<p>Eight moon phases rendered on every calendar view with illumination percentages and eclipse detection. Plan gatherings, gardens, and ceremonies around natural cycles.</p>
</div>
<div class="rl-card" style="border-color:rgba(96,165,250,0.12)">
<div style="font-size:1.75rem;margin-bottom:1rem">&#129513;</div>
<h3>r* Ecosystem Embeds</h3>
<p>rTrips, rMaps, rNetwork, rCart, and rNotes can all embed a calendar view through the context API. One calendar, surfaced everywhere it&rsquo;s needed.</p>
</div>
<div class="rl-card" style="border-color:rgba(96,165,250,0.12)">
<div style="font-size:1.75rem;margin-bottom:1rem">&#127968;</div>
<h3>Self-Hosted &amp; Sovereign</h3>
<p>Open source and Dockerized. Your events live on your infrastructure &mdash; not in a corporate cloud. Full data sovereignty with rIDs authentication.</p>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- Temporal Zoom --> <!-- Temporal Zoom Levels -->
<section class="rl-section"> <section class="rl-section">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Temporal zoom</h2> <span class="rl-tagline" style="color:#818cf8;background:rgba(129,140,248,0.1);border-color:rgba(129,140,248,0.2)">
<p class="rl-subtext" style="text-align:center">Ten levels of time &mdash; from the blink of an eye to deep time.</p> Temporal Navigation
<div class="rl-card" style="max-width:700px;margin:2rem auto 0"> </span>
<div class="rl-zoom-bar"> <h2 class="rl-heading" style="background:linear-gradient(135deg,#818cf8,#a78bfa);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">
Ten levels of time
</h2>
<p class="rl-subtext">
Most calendars show you a month. rCal lets you zoom from a single moment to a cosmic era &mdash;
each level revealing a different kind of pattern.
</p>
<div class="rl-card" style="max-width:700px;margin:2rem auto 0;overflow-x:auto">
<div class="rl-zoom-bar" style="min-width:460px">
<div class="rl-zoom-bar__row"> <div class="rl-zoom-bar__row">
<span class="rl-zoom-bar__label">0</span> <span class="rl-zoom-bar__label">0</span>
<div class="rl-zoom-bar__bar" style="width:10%;background:rgba(99,102,241,0.3)"> <div class="rl-zoom-bar__bar" style="width:4%;background:rgba(59,130,246,0.25)">
<span class="rl-zoom-bar__name">Moment</span> <span class="rl-zoom-bar__name">Moment</span>
</div> </div>
<span class="rl-zoom-bar__span">30 s</span> <span class="rl-zoom-bar__span">30 seconds</span>
</div> </div>
<div class="rl-zoom-bar__row"> <div class="rl-zoom-bar__row">
<span class="rl-zoom-bar__label">1</span> <span class="rl-zoom-bar__label">1</span>
<div class="rl-zoom-bar__bar" style="width:15%;background:rgba(99,102,241,0.28)"> <div class="rl-zoom-bar__bar" style="width:8%;background:rgba(96,165,250,0.25)">
<span class="rl-zoom-bar__name">Minute</span> <span class="rl-zoom-bar__name">Hour</span>
</div> </div>
<span class="rl-zoom-bar__span">1&ndash;10 min</span> <span class="rl-zoom-bar__span">60 minutes</span>
</div> </div>
<div class="rl-zoom-bar__row"> <div class="rl-zoom-bar__row">
<span class="rl-zoom-bar__label">2</span> <span class="rl-zoom-bar__label">2</span>
<div class="rl-zoom-bar__bar" style="width:22%;background:rgba(99,102,241,0.25)"> <div class="rl-zoom-bar__bar" style="width:14%;background:rgba(96,165,250,0.22)">
<span class="rl-zoom-bar__name">Hour</span> <span class="rl-zoom-bar__name">Day</span>
</div> </div>
<span class="rl-zoom-bar__span">1&ndash;6 hrs</span> <span class="rl-zoom-bar__span">24 hours</span>
</div> </div>
<div class="rl-zoom-bar__row"> <div class="rl-zoom-bar__row">
<span class="rl-zoom-bar__label">3</span> <span class="rl-zoom-bar__label">3</span>
<div class="rl-zoom-bar__bar" style="width:30%;background:rgba(99,102,241,0.22)"> <div class="rl-zoom-bar__bar" style="width:22%;background:rgba(129,140,248,0.22)">
<span class="rl-zoom-bar__name">Day</span>
</div>
<span class="rl-zoom-bar__span">24 hrs</span>
</div>
<div class="rl-zoom-bar__row">
<span class="rl-zoom-bar__label">4</span>
<div class="rl-zoom-bar__bar" style="width:40%;background:rgba(99,102,241,0.20)">
<span class="rl-zoom-bar__name">Week</span> <span class="rl-zoom-bar__name">Week</span>
</div> </div>
<span class="rl-zoom-bar__span">7 days</span> <span class="rl-zoom-bar__span">7 days</span>
</div> </div>
<div class="rl-zoom-bar__row"> <div class="rl-zoom-bar__row">
<span class="rl-zoom-bar__label">5</span> <span class="rl-zoom-bar__label">4</span>
<div class="rl-zoom-bar__bar" style="width:50%;background:rgba(99,102,241,0.18)"> <div class="rl-zoom-bar__bar" style="width:32%;background:rgba(129,140,248,0.20)">
<span class="rl-zoom-bar__name">Lunar</span> <span class="rl-zoom-bar__name">Month</span>
</div> </div>
<span class="rl-zoom-bar__span">29.5 days</span> <span class="rl-zoom-bar__span">~30 days</span>
</div>
<div class="rl-zoom-bar__row">
<span class="rl-zoom-bar__label">5</span>
<div class="rl-zoom-bar__bar" style="width:44%;background:rgba(167,139,250,0.20)">
<span class="rl-zoom-bar__name">Season</span>
</div>
<span class="rl-zoom-bar__span">~3 months</span>
</div> </div>
<div class="rl-zoom-bar__row"> <div class="rl-zoom-bar__row">
<span class="rl-zoom-bar__label">6</span> <span class="rl-zoom-bar__label">6</span>
<div class="rl-zoom-bar__bar" style="width:60%;background:rgba(99,102,241,0.16)"> <div class="rl-zoom-bar__bar" style="width:58%;background:rgba(167,139,250,0.18)">
<span class="rl-zoom-bar__name">Season</span>
</div>
<span class="rl-zoom-bar__span">~90 days</span>
</div>
<div class="rl-zoom-bar__row">
<span class="rl-zoom-bar__label">7</span>
<div class="rl-zoom-bar__bar" style="width:70%;background:rgba(99,102,241,0.14)">
<span class="rl-zoom-bar__name">Year</span> <span class="rl-zoom-bar__name">Year</span>
</div> </div>
<span class="rl-zoom-bar__span">365 days</span> <span class="rl-zoom-bar__span">365 days</span>
</div> </div>
<div class="rl-zoom-bar__row"> <div class="rl-zoom-bar__row">
<span class="rl-zoom-bar__label">8</span> <span class="rl-zoom-bar__label">7</span>
<div class="rl-zoom-bar__bar" style="width:85%;background:rgba(99,102,241,0.12)"> <div class="rl-zoom-bar__bar" style="width:72%;background:rgba(192,132,252,0.18)">
<span class="rl-zoom-bar__name">Epoch</span> <span class="rl-zoom-bar__name">Decade</span>
</div> </div>
<span class="rl-zoom-bar__span">decades&ndash;centuries</span> <span class="rl-zoom-bar__span">10 years</span>
</div>
<div class="rl-zoom-bar__row">
<span class="rl-zoom-bar__label">8</span>
<div class="rl-zoom-bar__bar" style="width:86%;background:rgba(168,85,247,0.16)">
<span class="rl-zoom-bar__name">Century</span>
</div>
<span class="rl-zoom-bar__span">100 years</span>
</div> </div>
<div class="rl-zoom-bar__row"> <div class="rl-zoom-bar__row">
<span class="rl-zoom-bar__label">9</span> <span class="rl-zoom-bar__label">9</span>
<div class="rl-zoom-bar__bar" style="width:100%;background:rgba(99,102,241,0.10)"> <div class="rl-zoom-bar__bar" style="width:100%;background:rgba(147,51,234,0.15)">
<span class="rl-zoom-bar__name">Cosmic</span> <span class="rl-zoom-bar__name">Cosmic</span>
</div> </div>
<span class="rl-zoom-bar__span">geological</span> <span class="rl-zoom-bar__span">Geological</span>
</div> </div>
</div> </div>
</div> </div>
@ -156,31 +206,63 @@ export function renderLanding(): string {
<!-- Calendar Views --> <!-- Calendar Views -->
<section class="rl-section rl-section--alt"> <section class="rl-section rl-section--alt">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Four views</h2> <span class="rl-tagline" style="color:#a78bfa;background:rgba(167,139,250,0.1);border-color:rgba(167,139,250,0.2)">
<div class="rl-grid-4" style="margin-top:2rem"> Four Views
<div class="rl-card rl-card--center"> </span>
<div class="rl-icon-box"><span style="font-size:1.25rem">&#128197;</span></div> <h2 class="rl-heading" style="background:linear-gradient(135deg,#a78bfa,#c084fc);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">
<h3>Temporal</h3> One calendar, four perspectives
<p>Classic calendar grid &mdash; day, week, month. The view you know.</p> </h2>
<p style="font-size:0.7rem;color:#64748b;margin-top:0.5rem"><kbd style="background:rgba(255,255,255,0.1);padding:0.1rem 0.3rem;border-radius:3px;font-size:0.65rem">T</kbd> to switch</p> <p class="rl-subtext">
Switch between views with keyboard shortcuts (1&ndash;4) to see your events from the angle that matters most right now.
</p>
<div class="rl-grid-2" style="margin-top:2rem">
<div class="rl-card">
<div style="display:flex;align-items:center;gap:0.75rem;margin-bottom:1rem">
<div style="width:2.5rem;height:2.5rem;border-radius:0.75rem;background:rgba(59,130,246,0.12);display:flex;align-items:center;justify-content:center;font-size:1.1rem">
&#128197;
</div>
<div>
<h3 style="margin-bottom:0">Temporal</h3>
<span style="font-size:0.7rem;color:#64748b;font-family:monospace">Press 1</span>
</div>
</div>
<p>The classic calendar view &mdash; month, week, day, year, and season &mdash; enhanced with multi-granularity zoom and event indicators.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card">
<div class="rl-icon-box"><span style="font-size:1.25rem">&#128506;</span></div> <div style="display:flex;align-items:center;gap:0.75rem;margin-bottom:1rem">
<h3>Spatial</h3> <div style="width:2.5rem;height:2.5rem;border-radius:0.75rem;background:rgba(52,211,153,0.12);display:flex;align-items:center;justify-content:center;font-size:1.1rem">
<p>Map view with events pinned to locations. Zoom couples time and space.</p> &#128506;
<p style="font-size:0.7rem;color:#64748b;margin-top:0.5rem"><kbd style="background:rgba(255,255,255,0.1);padding:0.1rem 0.3rem;border-radius:3px;font-size:0.65rem">S</kbd> to switch</p> </div>
<div>
<h3 style="margin-bottom:0">Spatial</h3>
<span style="font-size:0.7rem;color:#64748b;font-family:monospace">Press 2</span>
</div>
</div>
<p>Interactive map powered by Leaflet. Events cluster by location with nine spatial granularity levels from planet to GPS coordinates.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card">
<div class="rl-icon-box"><span style="font-size:1.25rem">&#127769;</span></div> <div style="display:flex;align-items:center;gap:0.75rem;margin-bottom:1rem">
<h3>Lunar</h3> <div style="width:2.5rem;height:2.5rem;border-radius:0.75rem;background:rgba(245,158,11,0.12);display:flex;align-items:center;justify-content:center;font-size:1.1rem">
<p>Moon-phase overlay with illumination percentages. Plan with natural rhythms.</p> &#127769;
<p style="font-size:0.7rem;color:#64748b;margin-top:0.5rem"><kbd style="background:rgba(255,255,255,0.1);padding:0.1rem 0.3rem;border-radius:3px;font-size:0.65rem">L</kbd> to switch</p> </div>
<div>
<h3 style="margin-bottom:0">Lunar</h3>
<span style="font-size:0.7rem;color:#64748b;font-family:monospace">Press 3</span>
</div>
</div>
<p>Moon phase overlay with illumination percentages, eclipse detection, and phase-colored day cells. Plan around the eight phases of the lunar cycle.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card">
<div class="rl-icon-box"><span style="font-size:1.25rem">&#129513;</span></div> <div style="display:flex;align-items:center;gap:0.75rem;margin-bottom:1rem">
<h3>Context</h3> <div style="width:2.5rem;height:2.5rem;border-radius:0.75rem;background:rgba(34,211,238,0.12);display:flex;align-items:center;justify-content:center;font-size:1.1rem">
<p>Events grouped by r* source module. See your rWork sprints next to rVote deadlines.</p> &#129513;
<p style="font-size:0.7rem;color:#64748b;margin-top:0.5rem"><kbd style="background:rgba(255,255,255,0.1);padding:0.1rem 0.3rem;border-radius:3px;font-size:0.65rem">C</kbd> to switch</p> </div>
<div>
<h3 style="margin-bottom:0">Context</h3>
<span style="font-size:0.7rem;color:#64748b;font-family:monospace">Press 4</span>
</div>
</div>
<p>When embedded inside another r* tool, this view shows calendar data filtered for that tool&rsquo;s entity &mdash; a trip, a network, a map layer.</p>
</div> </div>
</div> </div>
</div> </div>
@ -189,115 +271,78 @@ export function renderLanding(): string {
<!-- Ecosystem Integration --> <!-- Ecosystem Integration -->
<section class="rl-section"> <section class="rl-section">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Ecosystem integration</h2> <span class="rl-tagline" style="color:#34d399;background:rgba(52,211,153,0.1);border-color:rgba(52,211,153,0.2)">
<p class="rl-subtext" style="text-align:center">rCal pulls events from across the r* ecosystem automatically.</p> Ecosystem
</span>
<h2 class="rl-heading" style="background:linear-gradient(135deg,#34d399,#22d3ee);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">
Part of the r* stack
</h2>
<p class="rl-subtext">
rCal connects to the full suite of community tools. Any r* app can display or create calendar events through the shared context API.
</p>
<div class="rl-grid-3" style="margin-top:2rem"> <div class="rl-grid-3" style="margin-top:2rem">
<div class="rl-integration"> <div class="rl-integration" style="border-color:rgba(52,211,153,0.15)">
<div class="rl-icon-box" style="flex-shrink:0"><span style="font-size:1.25rem">&#9992;&#65039;</span></div>
<div>
<h3><a href="/rtrips" style="color:#e2e8f0;text-decoration:none">rTrips</a></h3>
<p>Travel itineraries appear as multi-day calendar events with location pins.</p>
</div>
</div>
<div class="rl-integration">
<div class="rl-icon-box" style="flex-shrink:0"><span style="font-size:1.25rem">&#128506;</span></div> <div class="rl-icon-box" style="flex-shrink:0"><span style="font-size:1.25rem">&#128506;</span></div>
<div> <div>
<h3><a href="/rmaps" style="color:#e2e8f0;text-decoration:none">rMaps</a></h3> <h3>rTrips</h3>
<p>Location-tagged events render on the spatial view map layer.</p> <p>Trip itineraries auto-populate with calendar events for departure, accommodation, and activities.</p>
</div> </div>
</div> </div>
<div class="rl-integration"> <div class="rl-integration" style="border-color:rgba(52,211,153,0.15)">
<div class="rl-icon-box" style="flex-shrink:0"><span style="font-size:1.25rem">&#128205;</span></div>
<div>
<h3>rMaps</h3>
<p>Location-tagged events appear on shared community maps with time-filtered layers.</p>
</div>
</div>
<div class="rl-integration" style="border-color:rgba(52,211,153,0.15)">
<div class="rl-icon-box" style="flex-shrink:0"><span style="font-size:1.25rem">&#128101;</span></div> <div class="rl-icon-box" style="flex-shrink:0"><span style="font-size:1.25rem">&#128101;</span></div>
<div> <div>
<h3><a href="/rnetwork" style="color:#e2e8f0;text-decoration:none">rNetwork</a></h3> <h3>rNetwork</h3>
<p>Meeting events auto-link to participant profiles and relationship context.</p> <p>See when your community members are available and schedule group meetings.</p>
</div> </div>
</div> </div>
<div class="rl-integration"> <div class="rl-integration" style="border-color:rgba(52,211,153,0.15)">
<div class="rl-icon-box" style="flex-shrink:0"><span style="font-size:1.25rem">&#128722;</span></div> <div class="rl-icon-box" style="flex-shrink:0"><span style="font-size:1.25rem">&#128722;</span></div>
<div> <div>
<h3><a href="/rcart" style="color:#e2e8f0;text-decoration:none">rCart</a></h3> <h3>rCart</h3>
<p>Group-buy deadlines and fulfillment ETAs show up as calendar milestones.</p> <p>Product launches, market days, and delivery windows sync to your calendar.</p>
</div> </div>
</div> </div>
<div class="rl-integration"> <div class="rl-integration" style="border-color:rgba(52,211,153,0.15)">
<div class="rl-icon-box" style="flex-shrink:0"><span style="font-size:1.25rem">&#128221;</span></div> <div class="rl-icon-box" style="flex-shrink:0"><span style="font-size:1.25rem">&#128221;</span></div>
<div> <div>
<h3><a href="/rnotes" style="color:#e2e8f0;text-decoration:none">rNotes</a></h3> <h3>rNotes</h3>
<p>Meeting notes link back to the calendar event that spawned them.</p> <p>Meeting notes link back to calendar events. Transcriptions attach to the moment they happened.</p>
</div> </div>
</div> </div>
<div class="rl-integration"> <div class="rl-integration" style="border-color:rgba(52,211,153,0.15)">
<div class="rl-icon-box" style="flex-shrink:0"><span style="font-size:1.25rem">&#127760;</span></div> <div class="rl-icon-box" style="flex-shrink:0"><span style="font-size:1.25rem">&#127760;</span></div>
<div> <div>
<h3><a href="/" style="color:#e2e8f0;text-decoration:none">rSpace</a></h3> <h3>rSpace</h3>
<p>Space-level milestones and deadlines aggregate across all modules into one timeline.</p> <p>Each space gets its own calendar. Subdomain routing means each community has a dedicated view.</p>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- Built on Open Source -->
<section class="rl-section rl-section--alt">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Built on Open Source</h2>
<p class="rl-subtext" style="text-align:center">The libraries and tools that power rCal.</p>
<div class="rl-grid-3">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128451;</div>
<h3>PostgreSQL</h3>
<p>Rock-solid relational database for events, sources, locations, and calendar metadata.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128663;</div>
<h3>OSRM</h3>
<p>Open-source routing engine for location-based scheduling, travel times, and spatial queries.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128293;</div>
<h3>Hono</h3>
<p>Ultrafast web framework for the API layer. Lightweight, edge-ready, and built for speed.</p>
</div>
</div>
</div>
</section>
<!-- Your Data, Protected -->
<section class="rl-section">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">Your Data, Protected</h2>
<p class="rl-subtext">How rCal keeps your information safe.</p>
<div class="rl-grid-3">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128274;</div>
<h3>End-to-End Encryption</h3>
<span class="rl-badge">Coming Soon</span>
<p>All content encrypted before it leaves your device. Not even the server can read it.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128373;</div>
<h3>Zero-Knowledge Architecture</h3>
<span class="rl-badge">Coming Soon</span>
<p>The server processes your requests without ever seeing your data in the clear.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#127968;</div>
<h3>Self-Hosted</h3>
<p>Run on your own infrastructure. Your server, your rules, your data.</p>
</div>
</div>
</div>
</section>
<!-- CTA --> <!-- CTA -->
<section class="rl-section rl-section--alt"> <section class="rl-section rl-section--alt">
<div class="rl-container" style="text-align:center"> <div class="rl-container" style="text-align:center">
<h2 class="rl-heading">(You)rCal, your rhythm.</h2> <h2 class="rl-heading" style="background:linear-gradient(to right,#60a5fa,#818cf8,#a78bfa);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">
<p class="rl-subtext">Try the demo or create a space to get started.</p> See time differently
</h2>
<p class="rl-subtext">
Try the spatiotemporal calendar with lunar overlays, multi-source sync, and community sharing.
No account needed for the demo.
</p>
<div class="rl-cta-row"> <div class="rl-cta-row">
<a href="https://demo.rspace.online/rcal" class="rl-cta-primary">Open Calendar</a> <a href="https://demo.rspace.online/rcal" class="rl-cta-primary"
<a href="/create-space" class="rl-cta-secondary">Create a Space</a> style="background:linear-gradient(to right,#60a5fa,#6366f1);color:#0b1120">
Open the Demo
</a>
<a href="https://rstack.online" class="rl-cta-secondary">Explore rStack</a>
</div> </div>
</div> </div>
</section> </section>

View File

@ -1,165 +1,198 @@
/** /**
* rChoices rich landing page body. * rChoices landing page quick collaborative decisions.
* Returned by landingPage() in the module export; * Ported from the Next.js page.tsx. Interactive React demos (SpiderDemo,
* the shell wraps it with header, CSS, and analytics. * RankingDemo, VotingDemo) replaced with text descriptions.
*/ */
export function renderLanding(): string { export function renderLanding(): string {
return ` return `
<!-- Hero --> <!-- Hero -->
<div class="rl-hero"> <div class="rl-hero">
<span class="rl-tagline">rChoices</span> <span class="rl-tagline">Quick collaborative decisions</span>
<h1 class="rl-heading">(You)rChoices, your voice.</h1> <h1 class="rl-heading">What should <span style="color:#5eead4">5 friends</span><br>do tonight?</h1>
<p class="rl-subtitle">Decide Together, Fairly</p>
<p class="rl-subtext"> <p class="rl-subtext">
Quadratic voting, ranked choice, and multi-criteria scoring &mdash; all as Spider plots to weigh trade-offs. Rankings to sort preferences.
interactive shapes on your canvas. Drop a choice, let members vote, Live voting to decide fast. Powered by rSpace real-time sync.
watch results emerge in real time.
</p> </p>
<div class="rl-cta-row"> <div class="rl-cta-row">
<a href="https://demo.rspace.online/rchoices" class="rl-cta-primary" id="ml-primary">Start Deciding</a> <a href="https://demo.rspace.online/rchoices" class="rl-cta-primary" id="ml-primary">Create a Choice Room</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a> <a href="/create-space" class="rl-cta-secondary">Create a Space</a>
</div> </div>
</div> </div>
<!-- Features --> <!-- Three tools -->
<section class="rl-section"> <section class="rl-section">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">What rChoices Handles</h2> <h2 class="rl-heading" style="text-align:center">Three decision tools</h2>
<div class="rl-grid-4"> <div class="rl-grid-3">
<div class="rl-card rl-card--center"> <!-- Spider Plots -->
<div class="rl-icon-box">&#9878;</div> <div class="rl-card">
<h3>Quadratic Voting</h3> <div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.5rem">
<p>Express intensity of preference. The cost of additional votes grows exponentially, balancing passion with fairness.</p> <span style="font-size:0.7rem;padding:0.2rem 0.6rem;border-radius:9999px;background:rgba(168,85,247,0.1);color:#c084fc">Compare</span>
</div>
<h3 style="font-size:1.05rem;margin-bottom:0.35rem">Spider Plots</h3>
<p>Everyone rates options on multiple criteria. See where preferences
overlap &mdash; and where they don&rsquo;t.</p>
<div style="margin-top:1rem;padding:1rem;border-radius:0.75rem;background:rgba(168,85,247,0.05);border:1px solid rgba(168,85,247,0.1);text-align:center">
<svg width="120" height="100" viewBox="0 0 120 100" style="margin:0 auto;display:block">
<!-- Spider web axes -->
<line x1="60" y1="10" x2="60" y2="90" stroke="#334155" stroke-width="0.5"/>
<line x1="17" y1="35" x2="103" y2="65" stroke="#334155" stroke-width="0.5"/>
<line x1="17" y1="65" x2="103" y2="35" stroke="#334155" stroke-width="0.5"/>
<!-- Outer ring -->
<polygon points="60,10 103,35 103,65 60,90 17,65 17,35" fill="none" stroke="#334155" stroke-width="0.5"/>
<!-- Mid ring -->
<polygon points="60,30 88,42 88,58 60,70 32,58 32,42" fill="none" stroke="#334155" stroke-width="0.5"/>
<!-- Data shape 1 (purple) -->
<polygon points="60,18 96,38 90,62 60,78 28,55 25,38" fill="rgba(168,85,247,0.15)" stroke="#c084fc" stroke-width="1.5"/>
<!-- Data shape 2 (teal) -->
<polygon points="60,25 85,45 98,58 60,72 35,60 22,42" fill="rgba(20,184,166,0.15)" stroke="#14b8a6" stroke-width="1.5"/>
<!-- Axis labels -->
<text x="60" y="6" text-anchor="middle" fill="#64748b" font-size="7">Price</text>
<text x="110" y="34" text-anchor="start" fill="#64748b" font-size="7">Vibe</text>
<text x="110" y="70" text-anchor="start" fill="#64748b" font-size="7">Menu</text>
<text x="60" y="98" text-anchor="middle" fill="#64748b" font-size="7">Distance</text>
<text x="10" y="70" text-anchor="end" fill="#64748b" font-size="7">Speed</text>
<text x="10" y="34" text-anchor="end" fill="#64748b" font-size="7">Reviews</text>
</svg>
<p style="font-size:0.7rem;color:#64748b;margin-top:0.5rem">Multi-criteria comparison at a glance</p>
</div>
</div> </div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128203;</div> <!-- Rankings -->
<h3>Ranked Choice Voting</h3> <div class="rl-card">
<p>Order preferences from first to last. Instant-runoff tabulation finds the option with the broadest support.</p> <div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.5rem">
<span style="font-size:0.7rem;padding:0.2rem 0.6rem;border-radius:9999px;background:rgba(245,158,11,0.1);color:#fbbf24">Rank</span>
</div>
<h3 style="font-size:1.05rem;margin-bottom:0.35rem">Rankings</h3>
<p>Drag to order your top picks. Borda count or instant-runoff finds
the group&rsquo;s true consensus.</p>
<div style="margin-top:1rem;padding:0.75rem;border-radius:0.75rem;background:rgba(245,158,11,0.05);border:1px solid rgba(245,158,11,0.1)">
<div style="display:flex;flex-direction:column;gap:0.4rem">
<div style="display:flex;align-items:center;gap:0.5rem;padding:0.4rem 0.6rem;border-radius:0.375rem;background:rgba(245,158,11,0.12);border:1px solid rgba(245,158,11,0.2)">
<span style="font-size:0.7rem;font-weight:700;color:#fbbf24;width:1.2rem">1st</span>
<span style="font-size:0.8rem;color:#e2e8f0">Thai place on 5th</span>
</div>
<div style="display:flex;align-items:center;gap:0.5rem;padding:0.4rem 0.6rem;border-radius:0.375rem;background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.06)">
<span style="font-size:0.7rem;font-weight:700;color:#94a3b8;width:1.2rem">2nd</span>
<span style="font-size:0.8rem;color:#e2e8f0">New pizza spot</span>
</div>
<div style="display:flex;align-items:center;gap:0.5rem;padding:0.4rem 0.6rem;border-radius:0.375rem;background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.06)">
<span style="font-size:0.7rem;font-weight:700;color:#94a3b8;width:1.2rem">3rd</span>
<span style="font-size:0.8rem;color:#e2e8f0">Taco truck</span>
</div>
<div style="display:flex;align-items:center;gap:0.5rem;padding:0.4rem 0.6rem;border-radius:0.375rem;background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.06)">
<span style="font-size:0.7rem;font-weight:700;color:#94a3b8;width:1.2rem">4th</span>
<span style="font-size:0.8rem;color:#e2e8f0">Sushi bar</span>
</div>
</div>
<p style="font-size:0.7rem;color:#64748b;margin-top:0.5rem;text-align:center">Drag to reorder &mdash; consensus emerges</p>
</div>
</div> </div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128260;</div> <!-- Live Voting -->
<h3>CRDT-Based Shared State</h3> <div class="rl-card">
<p>Automerge CRDTs keep all participants in sync &mdash; no conflicts, no lost votes, even offline.</p> <div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.5rem">
</div> <span style="font-size:0.7rem;padding:0.2rem 0.6rem;border-radius:9999px;background:rgba(34,211,238,0.1);color:#22d3ee">Vote</span>
<div class="rl-card rl-card--center"> </div>
<div class="rl-icon-box">&#9889;</div> <h3 style="font-size:1.05rem;margin-bottom:0.35rem">Live Voting</h3>
<h3>Real-Time Collaboration</h3> <p>Cast your vote and watch results shift in real time. Perfect for
<p>Tallies, rankings, and spider charts update live as members vote. Results emerge instantly.</p> quick polls and tiebreakers.</p>
<div style="margin-top:1rem;padding:0.75rem;border-radius:0.75rem;background:rgba(34,211,238,0.05);border:1px solid rgba(34,211,238,0.1)">
<div style="display:flex;flex-direction:column;gap:0.5rem">
<div>
<div style="display:flex;justify-content:space-between;font-size:0.75rem;margin-bottom:0.25rem">
<span style="color:#e2e8f0">Hike</span>
<span style="color:#22d3ee;font-weight:600">45%</span>
</div>
<div style="height:0.4rem;border-radius:9999px;background:rgba(255,255,255,0.06);overflow:hidden">
<div style="height:100%;width:45%;border-radius:9999px;background:#22d3ee"></div>
</div>
</div>
<div>
<div style="display:flex;justify-content:space-between;font-size:0.75rem;margin-bottom:0.25rem">
<span style="color:#e2e8f0">Beach</span>
<span style="color:#22d3ee;font-weight:600">35%</span>
</div>
<div style="height:0.4rem;border-radius:9999px;background:rgba(255,255,255,0.06);overflow:hidden">
<div style="height:100%;width:35%;border-radius:9999px;background:#22d3ee"></div>
</div>
</div>
<div>
<div style="display:flex;justify-content:space-between;font-size:0.75rem;margin-bottom:0.25rem">
<span style="color:#e2e8f0">Stay in</span>
<span style="color:#22d3ee;font-weight:600">20%</span>
</div>
<div style="height:0.4rem;border-radius:9999px;background:rgba(255,255,255,0.06);overflow:hidden">
<div style="height:100%;width:20%;border-radius:9999px;background:#22d3ee"></div>
</div>
</div>
</div>
<p style="font-size:0.7rem;color:#64748b;margin-top:0.5rem;text-align:center">Results update live &mdash; 9 votes in</p>
</div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- How It Works --> <!-- How it works -->
<section class="rl-section rl-section--alt"> <section class="rl-section rl-section--alt">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">How It Works</h2> <h2 class="rl-heading" style="text-align:center">How it works</h2>
<div class="rl-grid-3"> <div class="rl-grid-3">
<div class="rl-step"> <div class="rl-step">
<div class="rl-step__num">1</div> <div class="rl-step__num">1</div>
<h3>Create a Decision</h3> <h3>Create</h3>
<p>Pick a voting method, name it, and add options. The choice shape appears on the canvas.</p> <p>Name your choice room. It comes pre-loaded with vote, rank, and spider tools.</p>
</div> </div>
<div class="rl-step"> <div class="rl-step">
<div class="rl-step__num">2</div> <div class="rl-step__num">2</div>
<h3>Add Options &amp; Invite Voters</h3> <h3>Share</h3>
<p>Space members interact with the shape to cast votes, rank preferences, or score criteria.</p> <p>Send the link. Everyone joins the same real-time canvas &mdash; add options, cast votes.</p>
</div> </div>
<div class="rl-step"> <div class="rl-step">
<div class="rl-step__num">3</div> <div class="rl-step__num">3</div>
<h3>Results Calculated Fairly in Real Time</h3> <h3>Decide</h3>
<p>Live tallies update as votes arrive. View charts, rankings, and spider diagrams instantly.</p> <p>Results aggregate live. The group sees consensus emerge in seconds.</p>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- Voting Methods --> <!-- Use cases -->
<section class="rl-section"> <section class="rl-section">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Voting Methods</h2> <h2 class="rl-heading" style="text-align:center">Decisions, not debates</h2>
<p class="rl-subtext" style="text-align:center"> <p class="rl-subtext" style="text-align:center">
Three powerful mechanisms, each designed for different decision contexts. Built for the everyday choices that stall group chats
</p> </p>
<div class="rl-grid-3"> <div class="rl-grid-2" style="margin-top:2rem">
<div class="rl-card rl-card--center"> <div class="rl-card">
<div class="rl-icon-box">&#9878;</div> <h3 style="margin-bottom:0.35rem">Where to eat?</h3>
<h3>Quadratic Voting</h3> <p>Rate restaurants on price, distance, vibe. The spider plot finds the sweet spot.</p>
<p>Express intensity of preference. The cost of additional votes on one option grows exponentially, balancing passion with fairness.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card">
<div class="rl-icon-box">&#128203;</div> <h3 style="margin-bottom:0.35rem">What to watch?</h3>
<h3>Ranked Choice</h3> <p>Everyone ranks their top 3 movies. Instant-runoff picks the winner.</p>
<p>Order your preferences from first to last. Instant-runoff tabulation finds the option with the broadest support.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card">
<div class="rl-icon-box">&#128376;</div> <h3 style="margin-bottom:0.35rem">Weekend plans?</h3>
<h3>Multi-Criteria Scoring</h3> <p>Quick poll: hike, beach, or stay in? Results in 30 seconds.</p>
<p>Score options across weighted attributes. Spider diagrams reveal trade-offs at a glance.</p>
</div> </div>
</div> <div class="rl-card">
</div> <h3 style="margin-bottom:0.35rem">Team retro priorities?</h3>
</section> <p>Rank improvement ideas by impact. Borda count surfaces what the team really wants.</p>
<!-- Built on Open Source -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Built on Open Source</h2>
<p class="rl-subtext" style="text-align:center">The libraries and tools that power rChoices.</p>
<div class="rl-grid-3">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128260;</div>
<h3>Automerge</h3>
<p>Conflict-free replicated data types for shared state &mdash; real-time sync without merge conflicts.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128451;</div>
<h3>PostgreSQL</h3>
<p>Reliable relational storage for decisions, vote records, and result history.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#9889;</div>
<h3>Hono</h3>
<p>Ultrafast web framework for the API layer &mdash; lightweight, typed, and edge-ready.</p>
</div>
</div>
</div>
</section>
<!-- Your Data, Protected -->
<section class="rl-section rl-section--alt">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">Your Data, Protected</h2>
<p class="rl-subtext">How rChoices keeps your information safe.</p>
<div class="rl-grid-3">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128274;</div>
<h3>End-to-End Encryption</h3>
<span class="rl-badge">Coming Soon</span>
<p>All content encrypted before it leaves your device. Not even the server can read it.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128373;</div>
<h3>Zero-Knowledge Architecture</h3>
<span class="rl-badge">Coming Soon</span>
<p>The server processes your requests without ever seeing your data in the clear.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#127968;</div>
<h3>Self-Hosted</h3>
<p>Run on your own infrastructure. Your server, your rules, your data.</p>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- CTA --> <!-- CTA -->
<section class="rl-section"> <section class="rl-section rl-section--alt">
<div class="rl-container" style="text-align:center"> <div class="rl-container" style="text-align:center">
<h2 class="rl-heading">(You)rChoices, your voice.</h2> <h2 class="rl-heading">What should 5 friends do tonight?</h2>
<p class="rl-subtext">Try the demo or create a space to get started.</p> <p class="rl-subtext">Create a room and find out in 30 seconds.</p>
<div class="rl-cta-row"> <div class="rl-cta-row">
<a href="https://demo.rspace.online/rchoices" class="rl-cta-primary">Start Deciding</a> <a href="https://demo.rspace.online/rchoices" class="rl-cta-primary">Create a Choice Room</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a> <a href="/create-space" class="rl-cta-secondary">Create a Space</a>
</div> </div>
</div> </div>

View File

@ -1,5 +1,6 @@
/** /**
* Forum module landing page static HTML, no React. * rForum landing page Discourse forum provisioning.
* Ported from /opt/apps/rforum-online/src/app/page.tsx
*/ */
export function renderLanding(): string { export function renderLanding(): string {
return ` return `
@ -18,61 +19,41 @@ export function renderLanding(): string {
</div> </div>
</div> </div>
<!-- Features -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">What rForum Handles</h2>
<div class="rl-grid-4">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#9881;</div>
<h3>Automated Provisioning</h3>
<p>One-click Discourse deployment. Server creation, installation, and configuration handled automatically.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#9729;</div>
<h3>Cloud VPS Deployment</h3>
<p>Deploy on Hetzner Cloud in Germany, Finland, or the US. Transparent pricing with no markup.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#127760;</div>
<h3>DNS Integration</h3>
<p>Automatic DNS setup for your subdomain via Cloudflare. SSL certificates provisioned with Let's Encrypt.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128736;</div>
<h3>No DevOps Required</h3>
<p>No command line, no SSH &mdash; just fill in your settings and watch your forum come online.</p>
</div>
</div>
</div>
</section>
<!-- How It Works --> <!-- How It Works -->
<section class="rl-section rl-section--alt"> <section class="rl-section">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">How It Works</h2> <h2 class="rl-heading" style="text-align:center">How It Works</h2>
<div class="rl-grid-3"> <div class="rl-grid-3">
<div class="rl-step"> <div class="rl-card rl-card--center">
<div class="rl-step__num">1</div> <div class="rl-icon-box" style="background:rgba(99,102,241,0.15)">
<h3>Configure</h3> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#818cf8" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.066 2.573c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.573 1.066c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.066-2.573c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/><circle cx="12" cy="12" r="3"/></svg>
<p>Choose your subdomain, server region, and instance size. Add SMTP credentials for email delivery. Set your admin email.</p> </div>
<h3>1. Configure</h3>
<p>Choose your subdomain, server region, and instance size.
Add SMTP credentials for email delivery. Set your admin email.</p>
</div> </div>
<div class="rl-step"> <div class="rl-card rl-card--center">
<div class="rl-step__num">2</div> <div class="rl-icon-box" style="background:rgba(139,92,246,0.15)">
<h3>Provision</h3> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#a78bfa" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14M12 5l7 7-7 7"/></svg>
<p>We create a cloud server on Hetzner, install Discourse, configure SSL via Let's Encrypt, and set up DNS. Takes about 10-15 minutes.</p> </div>
<h3>2. Provision</h3>
<p>We create a cloud server on Hetzner, install Discourse,
configure SSL via Let's Encrypt, and set up DNS. Takes about 10-15 minutes.</p>
</div> </div>
<div class="rl-step"> <div class="rl-card rl-card--center">
<div class="rl-step__num">3</div> <div class="rl-icon-box" style="background:rgba(168,85,247,0.15)">
<h3>Go Live</h3> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#c084fc" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 10V3L4 14h7v7l9-11h-7z"/></svg>
<p>Your forum is ready. Log in as admin, customize your community, invite members, and start conversations. Full SSH access included.</p> </div>
<h3>3. Go Live</h3>
<p>Your forum is ready. Log in as admin, customize your community,
invite members, and start conversations. Full SSH access included.</p>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- Pricing --> <!-- Pricing -->
<section class="rl-section" id="pricing"> <section class="rl-section rl-section--alt" id="pricing">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Transparent Pricing</h2> <h2 class="rl-heading" style="text-align:center">Transparent Pricing</h2>
<p class="rl-subtext" style="text-align:center"> <p class="rl-subtext" style="text-align:center">
@ -132,31 +113,49 @@ export function renderLanding(): string {
</section> </section>
<!-- What You Get --> <!-- What You Get -->
<section class="rl-section rl-section--alt"> <section class="rl-section">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">What You Get</h2> <h2 class="rl-heading" style="text-align:center">What You Get</h2>
<div class="rl-grid-3" style="margin-top:2rem"> <div class="rl-grid-3" style="margin-top:2rem">
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(99,102,241,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#818cf8" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
</div>
<h3>Automated SSL</h3> <h3>Automated SSL</h3>
<p>Let's Encrypt certificates provisioned automatically during setup.</p> <p>Let's Encrypt certificates provisioned automatically during setup.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(99,102,241,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#818cf8" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 014 10 15.3 15.3 0 01-4 10 15.3 15.3 0 01-4-10 15.3 15.3 0 014-10z"/></svg>
</div>
<h3>Multiple Regions</h3> <h3>Multiple Regions</h3>
<p>Deploy in Germany, Finland, or the US East/West Coast.</p> <p>Deploy in Germany, Finland, or the US East/West Coast.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(99,102,241,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#818cf8" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="M7 15l3-3 3 3"/><path d="M8 8h.01M12 8h.01"/></svg>
</div>
<h3>Full SSH Access</h3> <h3>Full SSH Access</h3>
<p>Your server, your rules. SSH in anytime for custom configuration.</p> <p>Your server, your rules. SSH in anytime for custom configuration.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(99,102,241,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#818cf8" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 014-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 01-4 4H3"/></svg>
</div>
<h3>One-Click Updates</h3> <h3>One-Click Updates</h3>
<p>Discourse's built-in admin panel handles version upgrades.</p> <p>Discourse's built-in admin panel handles version upgrades.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(99,102,241,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#818cf8" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9"/></svg>
</div>
<h3>DNS Management</h3> <h3>DNS Management</h3>
<p>Automatic DNS setup for *.rforum.online subdomains.</p> <p>Automatic DNS setup for *.rforum.online subdomains.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(99,102,241,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#818cf8" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg>
</div>
<h3>Real-Time Logs</h3> <h3>Real-Time Logs</h3>
<p>Watch your forum provision step-by-step in the dashboard.</p> <p>Watch your forum provision step-by-step in the dashboard.</p>
</div> </div>
@ -165,24 +164,36 @@ export function renderLanding(): string {
</section> </section>
<!-- Built on Open Source --> <!-- Built on Open Source -->
<section class="rl-section"> <section class="rl-section rl-section--alt">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Built on Open Source</h2> <h2 class="rl-heading" style="text-align:center">Built on Open Source</h2>
<p class="rl-subtext" style="text-align:center">The libraries and tools that power rForum.</p> <p class="rl-subtext" style="text-align:center">The libraries and tools that power rForum.</p>
<div class="rl-grid-4"> <div class="rl-grid-4">
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(139,92,246,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#a78bfa" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z"/></svg>
</div>
<h3>Discourse</h3> <h3>Discourse</h3>
<p>The world's most popular open-source forum platform.</p> <p>The world's most popular open-source forum platform.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(139,92,246,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#a78bfa" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="2" width="20" height="8" rx="2" ry="2"/><rect x="2" y="14" width="20" height="8" rx="2" ry="2"/><line x1="6" y1="6" x2="6.01" y2="6"/><line x1="6" y1="18" x2="6.01" y2="18"/></svg>
</div>
<h3>Hetzner Cloud API</h3> <h3>Hetzner Cloud API</h3>
<p>Automated VPS provisioning in multiple regions.</p> <p>Automated VPS provisioning in multiple regions.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(139,92,246,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#a78bfa" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
</div>
<h3>Cloudflare API</h3> <h3>Cloudflare API</h3>
<p>DNS management and SSL termination.</p> <p>DNS management and SSL termination.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(139,92,246,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#a78bfa" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M13 10V3L4 14h7v7l9-11h-7z"/></svg>
</div>
<h3>Hono</h3> <h3>Hono</h3>
<p>Ultra-fast, lightweight API framework powering the backend.</p> <p>Ultra-fast, lightweight API framework powering the backend.</p>
</div> </div>
@ -191,7 +202,7 @@ export function renderLanding(): string {
</section> </section>
<!-- Your Data, Protected --> <!-- Your Data, Protected -->
<section class="rl-section rl-section--alt"> <section class="rl-section">
<div class="rl-container" style="text-align:center"> <div class="rl-container" style="text-align:center">
<h2 class="rl-heading">Your Data, Protected</h2> <h2 class="rl-heading">Your Data, Protected</h2>
<p class="rl-subtext">How rForum keeps your information safe.</p> <p class="rl-subtext">How rForum keeps your information safe.</p>
@ -218,12 +229,12 @@ export function renderLanding(): string {
</section> </section>
<!-- CTA --> <!-- CTA -->
<section class="rl-section"> <section class="rl-section rl-section--alt">
<div class="rl-container" style="text-align:center"> <div class="rl-container" style="text-align:center">
<h2 class="rl-heading">(You)rForum, your community.</h2> <h2 class="rl-heading">Ready to launch your community?</h2>
<p class="rl-subtext">Try the demo or create a space to get started.</p> <p class="rl-subtext">Deploy a production Discourse forum in under 15 minutes. No DevOps experience needed.</p>
<div class="rl-cta-row"> <div class="rl-cta-row">
<a href="https://demo.rspace.online/rforum" class="rl-cta-primary">Get Started</a> <a href="https://demo.rspace.online/rforum" class="rl-cta-primary">Launch Your Forum</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a> <a href="/create-space" class="rl-cta-secondary">Create a Space</a>
</div> </div>
</div> </div>
@ -231,6 +242,5 @@ export function renderLanding(): string {
<div class="rl-back"> <div class="rl-back">
<a href="/">&larr; Back to rSpace</a> <a href="/">&larr; Back to rSpace</a>
</div> </div>`;
`;
} }

View File

@ -1,5 +1,6 @@
/** /**
* rFunds rich landing page body. * rFunds rich landing page body.
* Ported from rfunds-online/app/page.tsx (Next.js/Tailwind).
* Returned by landingPage() in the module export; * Returned by landingPage() in the module export;
* the shell wraps it with header, CSS, and analytics. * the shell wraps it with header, CSS, and analytics.
*/ */
@ -8,66 +9,107 @@ export function renderLanding(): string {
<!-- Hero --> <!-- Hero -->
<div class="rl-hero"> <div class="rl-hero">
<span class="rl-tagline">rFunds</span> <span class="rl-tagline">rFunds</span>
<h1 class="rl-heading">(You)rFunds, your flow.</h1> <h1 class="rl-heading" style="background:linear-gradient(to right,#fcd34d,#6ee7b7,#93c5fd);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">
<p class="rl-subtitle">Visualize Your Community's Money</p> Threshold-Based Flow Funding
<p class="rl-subtext"> </h1>
Budget flows, river visualization, and conviction funding. <p class="rl-subtext" style="font-size:1.25rem;max-width:48rem;margin:0 auto 2rem">
Watch resources move through your community in real time. Design continuous funding flows that respond dynamically to threshold conditions.
Connect funnels, set overflow rules, and track outcomes in real-time.
</p> </p>
<div class="rl-cta-row"> <div class="rl-cta-row">
<a href="https://demo.rspace.online/rfunds" class="rl-cta-primary" id="ml-primary">View Flows</a> <a href="https://demo.rspace.online/rfunds" class="rl-cta-secondary" id="ml-primary">Try the Demo</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a> <a href="/create-space" class="rl-cta-primary">Create Your Own</a>
</div> </div>
</div> </div>
<!-- Features --> <!-- How It Works -->
<section class="rl-section"> <section class="rl-section">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">What rFunds Handles</h2> <h2 class="rl-heading" style="text-align:center">How It Works</h2>
<div class="rl-grid-4"> <div class="rl-grid-3">
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center">
<div class="rl-icon-box">&#127754;</div> <div style="width:3rem;height:3rem;background:rgba(245,158,11,0.2);border-radius:0.75rem;display:flex;align-items:center;justify-content:center;margin:0 auto 1rem">
<h3>Budget Flow Visualization</h3> <svg style="width:1.5rem;height:1.5rem;color:#fbbf24" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<p>Animated flow diagram showing how funds move between pools, funnels, and outcomes in real time.</p> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z" />
</svg>
</div>
<h3>Create Funnels</h3>
<p>Each funnel represents a funding pool with three zones: overflow (above max),
healthy (between thresholds), and critical (below min). Set thresholds by
dragging handles.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128202;</div> <div style="width:3rem;height:3rem;background:rgba(16,185,129,0.2);border-radius:0.75rem;display:flex;align-items:center;justify-content:center;margin:0 auto 1rem">
<h3>Treasury Dashboards</h3> <svg style="width:1.5rem;height:1.5rem;color:#34d399" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<p>Full overview of balances, inflows, outflows, and historical transaction data for your community.</p> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6" />
</svg>
</div>
<h3>Connect Flows</h3>
<p>Connect funnels with overflow edges (sideways) so excess funds automatically
route to other pools. Add spending edges (downward) to fund outcomes and
deliverables.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128161;</div> <div style="width:3rem;height:3rem;background:rgba(59,130,246,0.2);border-radius:0.75rem;display:flex;align-items:center;justify-content:center;margin:0 auto 1rem">
<h3>Conviction-Based Funding</h3> <svg style="width:1.5rem;height:1.5rem;color:#60a5fa" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<p>Continuous signaling lets community members express preferences that compound over time.</p> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z" />
</div> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
<div class="rl-card rl-card--center"> </svg>
<div class="rl-icon-box">&#128168;</div> </div>
<h3>River Metaphor</h3> <h3>Simulate &amp; Share</h3>
<p>Named budget streams between funding pools with configurable rates, thresholds, and activation rules.</p> <p>Run simulations to see how funds flow through your system. Watch edge widths
scale proportionally. Save your space locally and share it with a link.</p>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- How It Works --> <!-- The Funnel Metaphor -->
<section class="rl-section rl-section--alt"> <section class="rl-section rl-section--alt">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">How It Works</h2> <div style="background:rgba(30,41,59,0.3);border-radius:1rem;border:1px solid rgba(51,65,85,0.5);padding:2rem">
<div class="rl-grid-3"> <h2 class="rl-heading" style="text-align:center;margin-bottom:2rem">The Funnel Metaphor</h2>
<div class="rl-step"> <div style="max-width:28rem;margin:0 auto;font-family:monospace;font-size:0.875rem;text-align:center">
<div class="rl-step__num">1</div>
<h3>Connect Your Treasury</h3> <!-- Overflow Zone -->
<p>Link funding pools and define budget streams with rates, thresholds, and allocation rules.</p> <div style="color:#fbbf24">
</div> <div style="background:rgba(245,158,11,0.1);border:1px solid rgba(245,158,11,0.3);border-radius:0.75rem 0.75rem 0 0;padding:0.75rem 2rem">
<div class="rl-step"> <div style="font-weight:600">OVERFLOW ZONE</div>
<div class="rl-step__num">2</div> <div style="font-size:0.75rem;color:#fcd34d">Above MAX threshold</div>
<h3>Map Budget Flows Visually</h3> <div style="font-size:0.75rem;color:rgba(252,211,77,0.7)">Excess funds redistribute to other funnels</div>
<p>The river visualization animates budget movement in real time &mdash; deposits, withdrawals, and funnels.</p> </div>
</div> </div>
<div class="rl-step">
<div class="rl-step__num">3</div> <!-- Max Threshold Line -->
<h3>Decide Funding with Conviction</h3> <div style="font-size:0.75rem;color:#f59e0b;font-weight:700;border-bottom:2px dashed rgba(245,158,11,0.5);padding:0.25rem 0;background:rgba(245,158,11,0.05)">
<p>Community members signal preferences through conviction funding. Resources flow where attention goes.</p> -- MAX THRESHOLD --
</div>
<!-- Healthy Zone -->
<div style="color:#34d399">
<div style="background:rgba(16,185,129,0.1);border-left:1px solid rgba(16,185,129,0.3);border-right:1px solid rgba(16,185,129,0.3);padding:1rem 2rem">
<div style="font-weight:600">HEALTHY ZONE</div>
<div style="font-size:0.75rem;color:#6ee7b7">Normal operations</div>
<div style="font-size:0.75rem;color:rgba(110,231,183,0.7)">Full flow rate, balanced funding</div>
</div>
</div>
<!-- Min Threshold Line -->
<div style="font-size:0.75rem;color:#ef4444;font-weight:700;border-bottom:2px dashed rgba(239,68,68,0.5);padding:0.25rem 0;background:rgba(239,68,68,0.05)">
-- MIN THRESHOLD --
</div>
<!-- Critical Zone -->
<div style="color:#94a3b8">
<div style="background:rgba(51,65,85,0.3);border:1px solid rgba(71,85,105,0.3);border-radius:0 0 0.75rem 0.75rem;padding:0.75rem 2rem">
<div style="font-weight:600;color:#f87171">CRITICAL ZONE</div>
<div style="font-size:0.75rem;color:#fca5a5">Below MIN threshold</div>
<div style="font-size:0.75rem;color:#64748b">Outflow restricted, conservation mode</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -100,7 +142,7 @@ export function renderLanding(): string {
</section> </section>
<!-- Built on Open Source --> <!-- Built on Open Source -->
<section class="rl-section"> <section class="rl-section rl-section--alt">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Built on Open Source</h2> <h2 class="rl-heading" style="text-align:center">Built on Open Source</h2>
<p class="rl-subtext" style="text-align:center">The libraries and tools that power rFunds.</p> <p class="rl-subtext" style="text-align:center">The libraries and tools that power rFunds.</p>
@ -125,7 +167,7 @@ export function renderLanding(): string {
</section> </section>
<!-- Your Data, Protected --> <!-- Your Data, Protected -->
<section class="rl-section rl-section--alt"> <section class="rl-section">
<div class="rl-container" style="text-align:center"> <div class="rl-container" style="text-align:center">
<h2 class="rl-heading">Your Data, Protected</h2> <h2 class="rl-heading">Your Data, Protected</h2>
<p class="rl-subtext">How rFunds keeps your information safe.</p> <p class="rl-subtext">How rFunds keeps your information safe.</p>
@ -152,13 +194,13 @@ export function renderLanding(): string {
</section> </section>
<!-- CTA --> <!-- CTA -->
<section class="rl-section"> <section class="rl-section rl-section--alt">
<div class="rl-container" style="text-align:center"> <div class="rl-container" style="text-align:center">
<h2 class="rl-heading">(You)rFunds, your flow.</h2> <h2 class="rl-heading">Ready to design your funding flows?</h2>
<p class="rl-subtext">Try the demo or create a space to get started.</p> <p class="rl-subtext">Start with the interactive demo or create your own space with custom funnels and connections.</p>
<div class="rl-cta-row"> <div class="rl-cta-row">
<a href="https://demo.rspace.online/rfunds" class="rl-cta-primary">View Flows</a> <a href="https://demo.rspace.online/rfunds" class="rl-cta-primary">Try the Demo</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a> <a href="/create-space" class="rl-cta-secondary">Create Your Own</a>
</div> </div>
</div> </div>
</section> </section>

View File

@ -1,203 +1,188 @@
/** /**
* Inbox module landing page static HTML, no React. * rInbox (rChats) landing page encrypted community chat.
* Ported from rchats-online Next.js page.tsx (shadcn/ui + Lucide).
*/ */
export function renderLanding(): string { export function renderLanding(): string {
return ` return `
<!-- Hero --> <!-- Hero -->
<div class="rl-hero"> <div class="rl-hero">
<span class="rl-tagline">rInbox</span> <span class="rl-tagline">Part of the rSpace Ecosystem</span>
<h1 class="rl-heading" style="background:linear-gradient(135deg,#67e8f9,#93c5fd,#c4b5fd);-webkit-background-clip:text;background-clip:text">(You)rInbox, your team's voice.</h1> <h1 class="rl-heading">Encrypted<br>
<p class="rl-subtitle" style="background:linear-gradient(135deg,#67e8f9,#93c5fd,#c4b5fd);-webkit-background-clip:text;background-clip:text">Collaborative Multi-Sig Inbox</p> <span style="background:linear-gradient(135deg,#3b82f6,#14b8a6);-webkit-background-clip:text;background-clip:text;color:transparent">Community Chat</span>
</h1>
<p class="rl-subtext"> <p class="rl-subtext">
A shared email client where teams read, discuss, and approve messages Secure messaging powered by <strong style="color:#e2e8f0">EncryptID passkeys</strong>.
together &mdash; with cryptographic multi-signature workflows before anything gets sent. No passwords, no seed phrases &mdash; just <strong style="color:#e2e8f0">hardware-backed encryption</strong> and
full data ownership for your community.
</p> </p>
<div class="rl-cta-row"> <div class="rl-cta-row">
<a href="https://demo.rspace.online/rinbox" class="rl-cta-primary" id="ml-primary">Open Inbox</a> <a href="https://demo.rspace.online/rinbox" class="rl-cta-primary" id="ml-primary">
<a href="/create-space" class="rl-cta-secondary">Create a Space</a> Try the Demo &rarr;
</a>
<a href="https://demo.rspace.online/rinbox" class="rl-cta-secondary">Get Started</a>
</div> </div>
</div> </div>
<!-- Features -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">What rInbox Handles</h2>
<div class="rl-grid-4">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128231;</div>
<h3>Shared Team Email</h3>
<p>Your team shares one real email address. Every member sees every thread in real time &mdash; no forwarding, no BCC chains.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#9989;</div>
<h3>Multi-Signature Approval</h3>
<p>Outbound emails require M-of-N cryptographic signatures before sending. Every approval is auditable &mdash; no rogue replies.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128172;</div>
<h3>Threaded Discussions</h3>
<p>Comment on any thread privately before replying. Tag members, discuss strategy, and reach consensus alongside the original message.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128273;</div>
<h3>Cryptographic Signing</h3>
<p>Every outbound message is cryptographically signed. Full audit trail of approvals, rejections, and edits.</p>
</div>
</div>
</div>
</section>
<!-- How It Works --> <!-- How It Works -->
<section class="rl-section rl-section--alt"> <section class="rl-section rl-section--alt">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">How It Works</h2> <div style="text-align:center;margin-bottom:1.5rem">
<span class="rl-badge">How It Works</span>
<h2 class="rl-heading" style="margin-top:0.75rem">Secure Chat in 30 Seconds</h2>
<p class="rl-subtext">
<strong style="color:#3b82f6">Create a passkey</strong> on your device,
<strong style="color:#14b8a6">join a community</strong>, and
<strong style="color:#e2e8f0">chat with end-to-end encryption</strong>.
</p>
</div>
<div class="rl-grid-3"> <div class="rl-grid-3">
<div class="rl-step"> <div class="rl-card" style="border:2px solid rgba(59,130,246,0.4);background:linear-gradient(135deg,rgba(59,130,246,0.1),rgba(59,130,246,0.05))">
<div class="rl-step__num">1</div> <div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.75rem">
<h3>Connect a Mailbox</h3> <div style="height:2rem;width:2rem;border-radius:50%;background:#3b82f6;display:flex;align-items:center;justify-content:center">
<p>Your team shares one real email address. Every member sees every thread in real time &mdash; no forwarding, no lost context.</p> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 10V4a2 2 0 00-4 0v6"/><path d="M18 11a6 6 0 00-12 0v3"/><rect x="3" y="14" width="18" height="8" rx="2"/><line x1="12" y1="18" x2="12" y2="18"/></svg>
</div>
<h3 style="font-weight:700;font-size:1.125rem;color:#e2e8f0">1. Create a Passkey</h3>
</div>
<p style="font-size:0.875rem;color:#94a3b8;line-height:1.6">
Register with EncryptID using your device's biometrics or security key.
No passwords to remember or leak.
<strong style="color:#e2e8f0;display:block;margin-top:0.5rem">Your keys never leave your device.</strong>
</p>
</div> </div>
<div class="rl-step">
<div class="rl-step__num">2</div> <div class="rl-card" style="border:2px solid rgba(20,184,166,0.4);background:linear-gradient(135deg,rgba(20,184,166,0.1),rgba(20,184,166,0.05))">
<h3>Discuss Messages as a Team</h3> <div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.75rem">
<p>Comment on any thread privately before replying. Tag members, discuss strategy, and reach consensus alongside the original message.</p> <div style="height:2rem;width:2rem;border-radius:50%;background:#14b8a6;display:flex;align-items:center;justify-content:center">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 21v-2a4 4 0 00-4-4H6a4 4 0 00-4-4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 00-3-3.87"/><path d="M16 3.13a4 4 0 010 7.75"/></svg>
</div>
<h3 style="font-weight:700;font-size:1.125rem;color:#e2e8f0">2. Join a Community</h3>
</div>
<p style="font-size:0.875rem;color:#94a3b8;line-height:1.6">
Create or join a community chat space. Invite members with role-based
access: viewers, participants, moderators, and admins.
<strong style="color:#e2e8f0;display:block;margin-top:0.5rem">One identity across all r* apps.</strong>
</p>
</div> </div>
<div class="rl-step">
<div class="rl-step__num">3</div> <div class="rl-card" style="border:2px solid rgba(100,116,139,0.4);background:linear-gradient(135deg,rgba(100,116,139,0.1),rgba(100,116,139,0.05))">
<h3>Approve and Send with Multi-Sig</h3> <div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.75rem">
<p>Outbound emails require M-of-N cryptographic signatures before sending. Every approval is auditable &mdash; no rogue replies.</p> <div style="height:2rem;width:2rem;border-radius:50%;background:#64748b;display:flex;align-items:center;justify-content:center">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z"/><rect x="9" y="9" width="6" height="1" rx="0.5"/></svg>
</div>
<h3 style="font-weight:700;font-size:1.125rem;color:#e2e8f0">3. Chat Securely</h3>
</div>
<p style="font-size:0.875rem;color:#94a3b8;line-height:1.6">
Messages are encrypted with keys derived from your passkey.
Only community members can read them.
<strong style="color:#e2e8f0;display:block;margin-top:0.5rem">True end-to-end encryption.</strong>
</p>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- Collaboration Features --> <!-- Features Row 1 -->
<section class="rl-section"> <section class="rl-section">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Collaboration Features</h2> <h2 class="rl-heading" style="text-align:center">Built on Self-Sovereign Identity</h2>
<p class="rl-subtext" style="text-align:center">Built for collective intelligence, not individual productivity.</p> <p class="rl-subtext" style="text-align:center">Security without compromise, powered by EncryptID</p>
<div class="rl-grid-2" style="margin-top:2rem">
<div class="rl-card">
<h3 style="color:#06b6d4;margin-bottom:0.75rem">Real-Time Collaboration</h3>
<ul class="rl-check-list">
<li><strong>Threaded Comments</strong> &mdash; discuss any email privately before replying</li>
<li><strong>Draft Reviews</strong> &mdash; collaborative draft editing with inline suggestions</li>
<li><strong>Forwarding Rules</strong> &mdash; route incoming messages by sender, subject, or tag</li>
<li><strong>Inline Signatures</strong> &mdash; per-mailbox signature templates with merge fields</li>
<li><strong>Read Receipts</strong> &mdash; see who has read each thread and when</li>
</ul>
</div>
<div class="rl-card">
<h3 style="color:#8b5cf6;margin-bottom:0.75rem">Approval Workflows</h3>
<ul class="rl-check-list">
<li><strong>Multi-sig sending</strong> &mdash; outbound emails require M-of-N approval</li>
<li><strong>Configurable thresholds</strong> &mdash; set approval requirements per mailbox</li>
<li><strong>Audit trail</strong> &mdash; every approval, rejection, and edit is logged</li>
<li><strong>Role-based access</strong> &mdash; Admin, Reviewer, Approver, Viewer, Bot</li>
<li><strong>Deadline alerts</strong> &mdash; notifications when approvals are waiting</li>
</ul>
</div>
</div>
</div>
</section>
<!-- Team Roles -->
<section class="rl-section rl-section--alt">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Team Roles</h2>
<p class="rl-subtext" style="text-align:center">Fine-grained access control for every team member.</p>
<div style="display:grid;grid-template-columns:repeat(5,1fr);gap:0.75rem;margin-top:2rem">
<div class="rl-card rl-card--center" style="padding:1.25rem">
<p style="font-size:0.875rem;font-weight:600;color:#06b6d4">Admin</p>
<p style="font-size:0.75rem;color:#64748b;margin-top:0.35rem">Full control, manage members</p>
</div>
<div class="rl-card rl-card--center" style="padding:1.25rem">
<p style="font-size:0.875rem;font-weight:600;color:#3b82f6">Reviewer</p>
<p style="font-size:0.75rem;color:#64748b;margin-top:0.35rem">Read, comment, suggest edits</p>
</div>
<div class="rl-card rl-card--center" style="padding:1.25rem">
<p style="font-size:0.875rem;font-weight:600;color:#8b5cf6">Approver</p>
<p style="font-size:0.75rem;color:#64748b;margin-top:0.35rem">Sign outbound emails</p>
</div>
<div class="rl-card rl-card--center" style="padding:1.25rem">
<p style="font-size:0.875rem;font-weight:600;color:#94a3b8">Viewer</p>
<p style="font-size:0.75rem;color:#64748b;margin-top:0.35rem">Read-only access</p>
</div>
<div class="rl-card rl-card--center" style="padding:1.25rem">
<p style="font-size:0.875rem;font-weight:600;color:#94a3b8">Bot</p>
<p style="font-size:0.75rem;color:#64748b;margin-top:0.35rem">Automated integrations</p>
</div>
</div>
</div>
</section>
<!-- Built on Open Source -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Built on Open Source</h2>
<p class="rl-subtext" style="text-align:center">The libraries and tools that power rInbox.</p>
<div class="rl-grid-4"> <div class="rl-grid-4">
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center">
<h3>ImapFlow</h3> <div class="rl-icon-box" style="background:linear-gradient(135deg,#3b82f6,rgba(59,130,246,0.6))">
<p>High-performance IMAP client for real-time email synchronization.</p> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0110 0v4"/></svg>
</div>
<h3>End-to-End Encryption</h3>
<p>AES-256-GCM encryption with keys derived from your passkey. Messages are unreadable to the server.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center">
<h3>Mailparser</h3> <div class="rl-icon-box" style="background:linear-gradient(135deg,#14b8a6,rgba(20,184,166,0.6))">
<p>Email parsing and MIME handling for reliable message processing.</p> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 10V4a2 2 0 00-4 0v6"/><path d="M18 11a6 6 0 00-12 0v3"/><rect x="3" y="14" width="18" height="8" rx="2"/><line x1="12" y1="18" x2="12" y2="18"/></svg>
</div>
<h3>Passkey Authentication</h3>
<p>WebAuthn passkeys backed by biometrics or hardware security keys. Phishing-resistant by design.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center">
<h3>Gnosis Safe</h3> <div class="rl-icon-box" style="background:linear-gradient(135deg,#22c55e,#059669)">
<p>Multisig approval protocol adapted for email signing workflows.</p> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 21v-2a4 4 0 00-4-4H6a4 4 0 00-4-4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 00-3-3.87"/><path d="M16 3.13a4 4 0 010 7.75"/></svg>
</div>
<h3>Community Spaces</h3>
<p>Create isolated chat spaces with role-based access. Viewer, participant, moderator, and admin roles.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center">
<h3>PostgreSQL</h3> <div class="rl-icon-box" style="background:linear-gradient(135deg,#f97316,#d97706)">
<p>Threads, approvals, and audit trails stored in a reliable relational database.</p> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 014 10 15.3 15.3 0 01-4 10 15.3 15.3 0 01-4-10 15.3 15.3 0 014-10z"/></svg>
</div>
<h3>Cross-App SSO</h3>
<p>One identity across rSpace, rVote, rMaps, rWork, and the full r* ecosystem via EncryptID.</p>
</div> </div>
</div> </div>
</div>
</section>
<!-- Your Data, Protected --> <!-- Features Row 2 -->
<section class="rl-section rl-section--alt"> <div class="rl-grid-4" style="margin-top:1rem">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">Your Data, Protected</h2>
<p class="rl-subtext">How rInbox keeps your information safe.</p>
<div class="rl-grid-3">
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128274;</div> <div class="rl-icon-box" style="background:linear-gradient(135deg,#a855f7,#7c3aed)">
<h3>End-to-End Encryption</h3> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20.42 4.58a5.4 5.4 0 00-7.65 0l-.77.78-.77-.78a5.4 5.4 0 00-7.65 7.65l.78.77L12 20.64l7.64-7.64.78-.77a5.4 5.4 0 000-7.65z"/><path d="M12 5.36V12"/><path d="M8.5 8.5L12 12l3.5-3.5"/></svg>
<span class="rl-badge">Coming Soon</span> </div>
<p>All content encrypted before it leaves your device. Not even the server can read it.</p> <h3>Social Recovery</h3>
<p>No seed phrases. Designate trusted guardians who can help you recover access to your account.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128373;</div> <div class="rl-icon-box" style="background:linear-gradient(135deg,#3b82f6,#0891b2)">
<h3>Zero-Knowledge Architecture</h3> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 11-7.778 7.778 5.5 5.5 0 017.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"/></svg>
<span class="rl-badge">Coming Soon</span> </div>
<p>The server processes your requests without ever seeing your data in the clear.</p> <h3>No Passwords</h3>
<p>Passkeys replace passwords entirely. Nothing to leak, nothing to forget, nothing to phish.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center">
<div class="rl-icon-box">&#127968;</div> <div class="rl-icon-box" style="background:linear-gradient(135deg,#f43f5e,#ec4899)">
<h3>Self-Hosted</h3> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
<p>Run on your own infrastructure. Your server, your rules, your data.</p> </div>
<h3>Self-Sovereign</h3>
<p>You own your identity and encryption keys. No platform lock-in, no central authority.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:linear-gradient(135deg,#14b8a6,#0891b2)">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z"/><rect x="9" y="9" width="6" height="1" rx="0.5"/></svg>
</div>
<h3>rSpace Ecosystem</h3>
<p>Chat integrates with rSpace canvas, rVote governance, rFunds treasury, and more.</p>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- CTA --> <!-- CTA -->
<section class="rl-section"> <section class="rl-section rl-section--alt">
<div class="rl-container" style="text-align:center"> <div class="rl-container">
<h2 class="rl-heading">(You)rInbox, your team's voice.</h2> <div class="rl-card" style="border:2px solid rgba(59,130,246,0.3);background:linear-gradient(135deg,rgba(59,130,246,0.1),rgba(20,184,166,0.05),rgba(100,116,139,0.1));text-align:center;padding:3rem 1.5rem;position:relative;overflow:hidden">
<p class="rl-subtext">Try the demo or create a space to get started.</p> <div style="position:absolute;top:0;right:0;width:16rem;height:16rem;background:rgba(59,130,246,0.1);border-radius:50%;filter:blur(48px)"></div>
<div class="rl-cta-row"> <div style="position:absolute;bottom:0;left:0;width:16rem;height:16rem;background:rgba(20,184,166,0.1);border-radius:50%;filter:blur(48px)"></div>
<a href="https://demo.rspace.online/rinbox" class="rl-cta-primary">Open Inbox</a> <div style="position:relative">
<a href="/create-space" class="rl-cta-secondary">Create a Space</a> <span class="rl-badge">Try EncryptID</span>
<h2 class="rl-heading" style="margin-top:1rem">See it in action</h2>
<p class="rl-subtext" style="max-width:36rem;margin:0.5rem auto 0">
Try the interactive EncryptID demo &mdash; register a passkey, derive encryption keys,
and test signing and encryption right in your browser. No account needed.
</p>
<div class="rl-cta-row" style="margin-top:1.5rem">
<a href="https://demo.rspace.online/rinbox" class="rl-cta-primary">
Launch Demo &rarr;
</a>
</div>
</div>
</div> </div>
</div> </div>
</section> </section>
<div class="rl-back"> <div class="rl-back">
<a href="/">&larr; Back to rSpace</a> <a href="/">&larr; Back to rSpace</a>
</div> </div>`;
`;
} }

View File

@ -1,109 +1,90 @@
/** /**
* rPubs landing page community pocket press. * rPubs landing page community pocket press.
* Ported from the Next.js page.tsx with all unique visual elements preserved.
*/ */
export function renderLanding(): string { export function renderLanding(): string {
return ` return `
<!-- Hero --> <!-- Hero -->
<div class="rl-hero"> <div class="rl-hero">
<span class="rl-tagline">rPubs</span> <span class="rl-tagline">Community Pocket Press</span>
<h1 class="rl-heading">(You)rPubs, your press.</h1> <h1 class="rl-heading">Write it. Press it.<br>Share it.</h1>
<p class="rl-subtitle">Write it. Press it. Share it.</p>
<p class="rl-subtext"> <p class="rl-subtext">
Drop in a markdown document, pick a pocket format, and get a print-ready PDF in seconds. Instant local publishing for your writing. Paste in your text, pick a
Group up with other authors to unlock bulk pricing through collaborative print runs. pocket format, and get a print-ready book in seconds &mdash; then find a
local print shop or bind it yourself.
</p> </p>
<div class="rl-cta-row"> <div class="rl-cta-row">
<a href="https://demo.rspace.online/rpubs" class="rl-cta-primary" id="ml-primary">Try the Press</a> <a href="https://demo.rspace.online/rpubs" class="rl-cta-primary" id="ml-primary">
<span style="display:inline-flex;align-items:center;gap:0.5rem">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20h9"/><path d="M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z"/></svg>
Start Writing
</span>
</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a> <a href="/create-space" class="rl-cta-secondary">Create a Space</a>
</div> </div>
</div> </div>
<!-- Features --> <!-- How it works -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">What rPubs Handles</h2>
<div class="rl-grid-4">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128196;</div>
<h3>Markdown &#8594; PDF</h3>
<p>Drop in markdown or rich text. rPubs typesets it with Typst and produces a print-ready PDF in seconds.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128214;</div>
<h3>4 Pocket Formats</h3>
<p>A7 Pocket, Quarter Letter, A6 Booklet, and Digest. All print-ready at 300&nbsp;dpi with bleeds.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#129309;</div>
<h3>Collaborative Print Runs</h3>
<p>Pool orders across titles and authors. The more copies in a run, the cheaper each one gets.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128722;</div>
<h3>rCart Integration</h3>
<p>Publish your artifact to the rCart catalog with one click. Group carts, revenue splits, and fulfillment built in.</p>
</div>
</div>
</div>
</section>
<!-- How It Works -->
<section class="rl-section rl-section--alt"> <section class="rl-section rl-section--alt">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">How It Works</h2> <h2 class="rl-heading" style="text-align:center">From draft to booklet in three steps</h2>
<div class="rl-grid-3"> <div class="rl-grid-3">
<div class="rl-step"> <div class="rl-step">
<span class="rl-step__num">1</span> <div class="rl-step__num" style="position:relative">
<h3>Write / paste</h3> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#14b8a6" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20h9"/><path d="M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z"/></svg>
<p>Drop in markdown or rich text. Headings, images, footnotes &mdash; it all just works.</p> </div>
<h3>Write or paste</h3>
<p>Type directly, paste your markdown, or drop in a .md file. The editor handles the rest.</p>
</div> </div>
<div class="rl-step"> <div class="rl-step">
<span class="rl-step__num">2</span> <div class="rl-step__num" style="position:relative">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#14b8a6" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>
</div>
<h3>Press it</h3> <h3>Press it</h3>
<p>Pick a pocket format. rPubs typesets your document with Typst and generates a print-ready PDF.</p> <p>Pick a pocket format &mdash; from A7 pocket to digest &mdash; and generate a typeset PDF in seconds.</p>
</div> </div>
<div class="rl-step"> <div class="rl-step">
<span class="rl-step__num">3</span> <div class="rl-step__num" style="position:relative">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#14b8a6" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>
</div>
<h3>Print locally</h3> <h3>Print locally</h3>
<p>Print at home, at a local shop, or list it on rCart for cosmolocal fulfillment.</p> <p>Find a community print shop nearby, or download an imposition PDF and bind it at home.</p>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- Pocket Formats --> <!-- Four pocket formats -->
<section class="rl-section"> <section class="rl-section">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Four pocket formats</h2> <h2 class="rl-heading" style="text-align:center">Four pocket formats</h2>
<p class="rl-subtext" style="text-align:center">From palm-sized zines to digest readers. All print-ready at 300 dpi with bleeds.</p> <p class="rl-subtext" style="text-align:center">
From tiny zines that fit in your back pocket to digest-sized readers for longer works.
</p>
<div class="rl-grid-4" style="margin-top:2rem"> <div class="rl-grid-4" style="margin-top:2rem">
<div class="rl-card rl-card--center"> <div class="rl-card" style="text-align:left">
<div class="rl-icon-box"> <h3 style="margin-bottom:0.15rem">A7 Pocket</h3>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5A2.5 2.5 0 016.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 014 19.5v-15A2.5 2.5 0 016.5 2z"/></svg> <p style="font-size:0.75rem;color:#14b8a6;margin-bottom:0.5rem">74 &times; 105 mm</p>
</div> <p>Fits in your pocket. Perfect for poems, manifestos, and quick reads.</p>
<h3>A7 Pocket</h3> <p style="font-size:0.75rem;color:#64748b;margin-top:0.5rem">8&ndash;32 pages</p>
<p>74 &times; 105 mm &mdash; fits in a shirt pocket. Perfect for poems, manifestos, tiny zines.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card" style="text-align:left">
<div class="rl-icon-box"> <h3 style="margin-bottom:0.15rem">Quarter Letter</h3>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5A2.5 2.5 0 016.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 014 19.5v-15A2.5 2.5 0 016.5 2z"/></svg> <p style="font-size:0.75rem;color:#14b8a6;margin-bottom:0.5rem">4.25 &times; 5.5&quot;</p>
</div> <p>Classic zine size. Great for essays, short stories, and pamphlets.</p>
<h3>Quarter Letter</h3> <p style="font-size:0.75rem;color:#64748b;margin-top:0.5rem">16&ndash;64 pages</p>
<p>4.25 &times; 5.5&quot; &mdash; half a half-sheet. Great for chapbooks and field guides.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card" style="text-align:left">
<div class="rl-icon-box"> <h3 style="margin-bottom:0.15rem">A6 Booklet</h3>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5A2.5 2.5 0 016.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 014 19.5v-15A2.5 2.5 0 016.5 2z"/></svg> <p style="font-size:0.75rem;color:#14b8a6;margin-bottom:0.5rem">105 &times; 148 mm</p>
</div> <p>Postcard-sized. Ideal for field guides, chapbooks, and handbooks.</p>
<h3>A6 Booklet</h3> <p style="font-size:0.75rem;color:#64748b;margin-top:0.5rem">24&ndash;96 pages</p>
<p>105 &times; 148 mm &mdash; postcard size. The workhorse format for essays and readers.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card" style="text-align:left">
<div class="rl-icon-box"> <h3 style="margin-bottom:0.15rem">Digest</h3>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5A2.5 2.5 0 016.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 014 19.5v-15A2.5 2.5 0 016.5 2z"/></svg> <p style="font-size:0.75rem;color:#14b8a6;margin-bottom:0.5rem">5.5 &times; 8.5&quot;</p>
</div> <p>Standard indie publishing size. For novellas, collections, and readers.</p>
<h3>Digest</h3> <p style="font-size:0.75rem;color:#64748b;margin-top:0.5rem">32&ndash;200+ pages</p>
<p>5.5 &times; 8.5&quot; &mdash; half-letter. Standard trade paperback for longer works.</p>
</div> </div>
</div> </div>
</div> </div>
@ -112,117 +93,253 @@ export function renderLanding(): string {
<!-- Group Buys --> <!-- Group Buys -->
<section class="rl-section rl-section--alt"> <section class="rl-section rl-section--alt">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Group buys &mdash; better together</h2> <h2 class="rl-heading" style="text-align:center">Bulk orders, better prices</h2>
<p class="rl-subtext" style="text-align:center">Pool orders across titles. The more copies in a run, the cheaper each one gets.</p> <p class="rl-subtext" style="text-align:center">
The more copies a community funds together, the cheaper each one gets.
Group buys unlock better binding and lower per-copy costs.
</p>
<!-- Tier cards -->
<div class="rl-grid-3" style="margin-top:2rem"> <div class="rl-grid-3" style="margin-top:2rem">
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center" style="position:relative">
<h3>25+ copies</h3> <p style="font-size:1.75rem;font-weight:700;color:#e2e8f0;margin-bottom:0.15rem">25+</p>
<p>Saddle-stitch binding</p> <p style="font-size:0.9rem;font-weight:600;color:#14b8a6;margin-bottom:0.5rem">Saddle-stitch</p>
<p style="font-size:1.5rem;font-weight:700;color:#14b8a6;margin:0.5rem 0">$8</p> <p style="font-size:0.8rem;margin-bottom:1rem">Staple-bound booklet. Quick, lightweight, great for zines and short runs.</p>
<p style="font-size:0.75rem;color:#64748b">per copy</p> <p style="font-size:1.25rem;font-weight:700;color:#e2e8f0">$8<span style="font-size:0.75rem;color:#94a3b8;font-weight:400">/copy</span></p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center" style="position:relative">
<h3>50+ copies</h3> <span class="rl-badge" style="position:absolute;top:-0.6rem;right:0.75rem">save 25%</span>
<p>Perfect-bind</p> <p style="font-size:1.75rem;font-weight:700;color:#e2e8f0;margin-bottom:0.15rem">50+</p>
<p style="font-size:1.5rem;font-weight:700;color:#14b8a6;margin:0.5rem 0">$6</p> <p style="font-size:0.9rem;font-weight:600;color:#14b8a6;margin-bottom:0.5rem">Perfect-bind</p>
<span class="rl-badge">Save 25%</span> <p style="font-size:0.8rem;margin-bottom:1rem">Glued spine with cover wrap. Professional feel, sits on a shelf like a real book.</p>
<p style="font-size:0.75rem;color:#64748b;margin-top:0.5rem">per copy</p> <p style="font-size:1.25rem;font-weight:700;color:#e2e8f0">$6<span style="font-size:0.75rem;color:#94a3b8;font-weight:400">/copy</span></p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center" style="position:relative">
<h3>100+ copies</h3> <span class="rl-badge" style="position:absolute;top:-0.6rem;right:0.75rem">save 44%</span>
<p>Trade edition</p> <p style="font-size:1.75rem;font-weight:700;color:#e2e8f0;margin-bottom:0.15rem">100+</p>
<p style="font-size:1.5rem;font-weight:700;color:#14b8a6;margin:0.5rem 0">$4.50</p> <p style="font-size:0.9rem;font-weight:600;color:#14b8a6;margin-bottom:0.5rem">Trade edition</p>
<span class="rl-badge">Save 44%</span> <p style="font-size:0.8rem;margin-bottom:1rem">Full trade paperback. Robust binding, printed cover, retail-ready quality.</p>
<p style="font-size:0.75rem;color:#64748b;margin-top:0.5rem">per copy</p> <p style="font-size:1.25rem;font-weight:700;color:#e2e8f0">$4.50<span style="font-size:0.75rem;color:#94a3b8;font-weight:400">/copy</span></p>
</div> </div>
</div> </div>
</div>
</section>
<!-- How collaborative print runs work --> <!-- How collaborative print runs work -->
<section class="rl-section"> <div class="rl-card" style="margin-top:2.5rem">
<div class="rl-container"> <h3 style="text-align:center;margin-bottom:1.25rem">How collaborative print runs work</h3>
<h2 class="rl-heading" style="text-align:center">How collaborative print runs work</h2> <div class="rl-grid-4" style="text-align:center">
<div class="rl-grid-4" style="margin-top:2rem"> <div>
<div class="rl-step"> <div style="width:2rem;height:2rem;border-radius:9999px;background:rgba(20,184,166,0.1);display:flex;align-items:center;justify-content:center;margin:0 auto 0.5rem">
<span class="rl-step__num">1</span> <span style="font-size:0.7rem;font-weight:700;color:#14b8a6">1</span>
<h3>Authors list titles</h3> </div>
<p>Publish your print-ready artifact to the rCart catalog.</p> <p style="font-size:0.75rem;color:#94a3b8;line-height:1.5">
</div> A title gets <a href="https://demo.rspace.online/rpubs" style="color:#14b8a6;text-decoration:none">funded</a> by the community
<div class="rl-step"> </p>
<span class="rl-step__num">2</span> </div>
<h3>Readers pre-order</h3> <div>
<p>Buyers add copies to a shared cart. Orders accumulate toward tier thresholds.</p> <div style="width:2rem;height:2rem;border-radius:9999px;background:rgba(20,184,166,0.1);display:flex;align-items:center;justify-content:center;margin:0 auto 0.5rem">
</div> <span style="font-size:0.7rem;font-weight:700;color:#14b8a6">2</span>
<div class="rl-step"> </div>
<span class="rl-step__num">3</span> <p style="font-size:0.75rem;color:#94a3b8;line-height:1.5">
<h3>Threshold met</h3> Backers join the group buy as it hits each tier
<p>When the combined order hits a tier, the print run triggers automatically.</p> </p>
</div> </div>
<div class="rl-step"> <div>
<span class="rl-step__num">4</span> <div style="width:2rem;height:2rem;border-radius:9999px;background:rgba(20,184,166,0.1);display:flex;align-items:center;justify-content:center;margin:0 auto 0.5rem">
<h3>Local fulfillment</h3> <span style="font-size:0.7rem;font-weight:700;color:#14b8a6">3</span>
<p>The nearest cosmolocal provider prints and ships. Revenue splits to creator, community, and provider.</p> </div>
<p style="font-size:0.75rem;color:#94a3b8;line-height:1.5">
Order is placed with the nearest print shop via <a href="https://rcart.online" style="color:#14b8a6;text-decoration:none">rCart</a>
</p>
</div>
<div>
<div style="width:2rem;height:2rem;border-radius:9999px;background:rgba(20,184,166,0.1);display:flex;align-items:center;justify-content:center;margin:0 auto 0.5rem">
<span style="font-size:0.7rem;font-weight:700;color:#14b8a6">4</span>
</div>
<p style="font-size:0.75rem;color:#94a3b8;line-height:1.5">
Books are printed locally and distributed to backers
</p>
</div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- Cross-title batching --> <!-- Cross-title batching -->
<section class="rl-section rl-section--alt"> <section class="rl-section">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Cross-title batching</h2> <h2 class="rl-heading" style="text-align:center">Bundle across titles, not just within them</h2>
<p class="rl-subtext" style="text-align:center"> <p class="rl-subtext" style="text-align:center">
Orders from <em>different</em> titles count toward the same tier. A community reading list Printer discounts are based on <em>total volume at the press</em>, not copies of a single book.
can hit trade-edition pricing even if no single title has 100 orders. When multiple titles route to the same local printer, everyone benefits from the combined run.
</p> </p>
<div class="rl-card" style="max-width:640px;margin:2rem auto 0">
<h3 style="margin-bottom:1rem">Example batch</h3> <!-- Cross-title batching example -->
<div style="display:flex;flex-direction:column;gap:0.5rem"> <div class="rl-card" style="max-width:680px;margin:2rem auto 0">
<div style="display:flex;justify-content:space-between;font-size:0.875rem"> <p style="font-size:0.7rem;font-weight:600;color:#94a3b8;text-transform:uppercase;letter-spacing:0.08em;margin-bottom:1rem;text-align:center">
<span style="color:#e2e8f0">The Commons</span><span style="color:#14b8a6;font-weight:600">35 copies</span> How cross-title batching unlocks tiers
</p>
<div class="rl-grid-3" style="margin-bottom:1rem">
<div style="border:1px solid rgba(255,255,255,0.06);border-radius:0.5rem;padding:0.75rem;text-align:center">
<p style="font-size:0.875rem;font-weight:600;color:#e2e8f0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis">The Commons</p>
<p style="font-size:0.75rem;color:#94a3b8">J. Emmett</p>
<p style="font-size:0.65rem;color:#64748b;margin-top:0.25rem">governance</p>
<p style="font-size:1.25rem;font-weight:700;color:#14b8a6;margin-top:0.5rem">35</p>
<p style="font-size:0.6rem;color:#94a3b8">pre-committed copies</p>
</div> </div>
<div style="display:flex;justify-content:space-between;font-size:0.875rem"> <div style="border:1px solid rgba(255,255,255,0.06);border-radius:0.5rem;padding:0.75rem;text-align:center">
<span style="color:#e2e8f0">Mycelial Networks</span><span style="color:#14b8a6;font-weight:600">40 copies</span> <p style="font-size:0.875rem;font-weight:600;color:#e2e8f0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis">Mycelial Networks</p>
<p style="font-size:0.75rem;color:#94a3b8">M. Stamets</p>
<p style="font-size:0.65rem;color:#64748b;margin-top:0.25rem">ecology</p>
<p style="font-size:1.25rem;font-weight:700;color:#14b8a6;margin-top:0.5rem">40</p>
<p style="font-size:0.6rem;color:#94a3b8">pre-committed copies</p>
</div> </div>
<div style="display:flex;justify-content:space-between;font-size:0.875rem"> <div style="border:1px solid rgba(255,255,255,0.06);border-radius:0.5rem;padding:0.75rem;text-align:center">
<span style="color:#e2e8f0">Cosmolocal Reader</span><span style="color:#14b8a6;font-weight:600">30 copies</span> <p style="font-size:0.875rem;font-weight:600;color:#e2e8f0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis">Cosmolocal Reader</p>
<p style="font-size:0.75rem;color:#94a3b8">Collective</p>
<p style="font-size:0.65rem;color:#64748b;margin-top:0.25rem">economics</p>
<p style="font-size:1.25rem;font-weight:700;color:#14b8a6;margin-top:0.5rem">30</p>
<p style="font-size:0.6rem;color:#94a3b8">pre-committed copies</p>
</div> </div>
</div> </div>
<div class="rl-divider"><span>combined</span></div> <div class="rl-divider"><span>at the same local printer</span></div>
<div style="text-align:center"> <div style="text-align:center">
<span style="font-size:1.5rem;font-weight:700;color:#14b8a6">105 copies</span> <p style="font-size:1.5rem;font-weight:700;color:#e2e8f0">105 copies</p>
<span style="display:block;font-size:0.8rem;color:#64748b;margin-top:0.25rem">= Trade edition @ $4.50/copy</span> <p style="font-size:0.875rem;color:#14b8a6;font-weight:500">
Trade edition tier unlocked &mdash; $4.50/copy for all three titles
</p>
<p style="font-size:0.75rem;color:#94a3b8;margin-top:0.25rem">
No single title hit 100 alone, but together they clear the threshold
</p>
</div>
</div>
<!-- Pre-commitments from rSpace -->
<div class="rl-integration" style="margin-top:2rem;max-width:680px;margin-left:auto;margin-right:auto">
<div style="width:2.5rem;height:2.5rem;border-radius:0.5rem;background:rgba(20,184,166,0.2);display:flex;align-items:center;justify-content:center;flex-shrink:0">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#14b8a6" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2zM22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/></svg>
</div>
<div>
<h3>Pre-commitments flow from rSpace</h3>
<p style="margin-bottom:0.75rem">
Every reading group, community, and network keeps a
<span style="color:#e2e8f0;font-weight:500">CRDT ledger</span> in their
<a href="https://rspace.online" style="color:#14b8a6;text-decoration:none">{space}</a>.
When members signal intent to buy, those pre-commitments sync across
clients &mdash; conflict-free, append-only, and auditable.
</p>
<p style="margin-bottom:0.75rem">
As pre-commitments accumulate across titles, genres, and networks that share a
local printer, the combined volume triggers better pricing tiers.
A poetry collective and a tech reading group in the same city don&rsquo;t need to know
each other &mdash; their orders batch automatically at the press.
</p>
<div style="display:flex;flex-wrap:wrap;gap:0.5rem">
<a href="https://demo.rspace.online/rpubs" style="display:inline-flex;align-items:center;gap:0.4rem;padding:0.5rem 1rem;border-radius:0.5rem;background:#14b8a6;color:white;font-size:0.75rem;font-weight:500;text-decoration:none">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2v20M2 12h20"/></svg>
Fund a print run
</a>
<a href="https://rspace.online" style="display:inline-block;padding:0.5rem 1rem;border-radius:0.5rem;border:1px solid rgba(255,255,255,0.15);color:#94a3b8;font-size:0.75rem;font-weight:500;text-decoration:none">
Learn about {space} ledgers
</a>
</div>
</div>
</div>
<!-- Signal / Aggregate / Release -->
<div class="rl-grid-3" style="margin-top:2rem;text-align:center">
<div>
<div style="width:2rem;height:2rem;border-radius:9999px;background:rgba(20,184,166,0.1);display:flex;align-items:center;justify-content:center;margin:0 auto 0.5rem">
<span style="font-size:0.7rem;font-weight:700;color:#14b8a6">1</span>
</div>
<p style="font-size:0.8rem;font-weight:600;color:#e2e8f0;margin-bottom:0.15rem">Signal</p>
<p style="font-size:0.75rem;color:#94a3b8;line-height:1.5">
Communities pre-commit in their {space} CRDT ledger &mdash; &ldquo;I want 3 copies&rdquo;
</p>
</div>
<div>
<div style="width:2rem;height:2rem;border-radius:9999px;background:rgba(20,184,166,0.1);display:flex;align-items:center;justify-content:center;margin:0 auto 0.5rem">
<span style="font-size:0.7rem;font-weight:700;color:#14b8a6">2</span>
</div>
<p style="font-size:0.8rem;font-weight:600;color:#e2e8f0;margin-bottom:0.15rem">Aggregate</p>
<p style="font-size:0.75rem;color:#94a3b8;line-height:1.5">
Pre-commitments across titles and networks
<a href="https://demo.rspace.online/rpubs" style="color:#14b8a6;text-decoration:none">flow into the fund</a>,
batched by printer region
</p>
</div>
<div>
<div style="width:2rem;height:2rem;border-radius:9999px;background:rgba(20,184,166,0.1);display:flex;align-items:center;justify-content:center;margin:0 auto 0.5rem">
<span style="font-size:0.7rem;font-weight:700;color:#14b8a6">3</span>
</div>
<p style="font-size:0.8rem;font-weight:600;color:#e2e8f0;margin-bottom:0.15rem">Release</p>
<p style="font-size:0.75rem;color:#94a3b8;line-height:1.5">
When volume hits a tier threshold, the print run triggers &mdash; everyone gets the bulk rate
</p>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- rCart integration --> <!-- rCart integration -->
<section class="rl-section"> <section class="rl-section rl-section--alt">
<div class="rl-container"> <div class="rl-container">
<div class="rl-grid-2"> <div class="rl-grid-2">
<div> <div>
<h2 class="rl-heading">rCart integration</h2> <div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:1rem">
<p class="rl-subtext" style="margin-bottom:1.5rem"> <span style="width:1.75rem;height:1.75rem;border-radius:0.375rem;background:#fdba74;display:flex;align-items:center;justify-content:center;font-size:0.6rem;font-weight:900;color:#0f172a;line-height:1">rCt</span>
Group purchasing is built right into the shop. Every rPubs artifact can be listed, <span style="font-size:0.875rem;font-weight:600;color:#e2e8f0">rCart</span>
batched, and fulfilled through rCart. <span style="font-size:0.75rem;color:#94a3b8">&times;</span>
<span style="width:1.75rem;height:1.75rem;border-radius:0.375rem;background:#fda4af;display:flex;align-items:center;justify-content:center;font-size:0.6rem;font-weight:900;color:#0f172a;line-height:1">rP</span>
<span style="font-size:0.875rem;font-weight:600;color:#e2e8f0">rPubs</span>
</div>
<h2 class="rl-heading">Group purchasing, built in</h2>
<p style="color:#94a3b8;line-height:1.65;margin-bottom:1rem;font-size:0.95rem">
rCart handles the commerce side of group buys &mdash; collecting orders,
splitting payments, and coordinating delivery. When a title hits its
funding goal, rCart automatically batches the order to the best local
print shop.
</p> </p>
<ul class="rl-check-list"> <ul class="rl-check-list">
<li><strong>One-click listing</strong> &mdash; publish to the rCart catalog straight from the press</li> <li><strong>Shared carts</strong> &mdash; friends, reading groups, or whole communities pool orders for better rates</li>
<li><strong>Group carts</strong> &mdash; space members pool orders automatically</li> <li><strong>Automatic tier unlock</strong> &mdash; as more copies are ordered, the price drops for everyone</li>
<li><strong>Revenue splits</strong> &mdash; creator, community, and provider shares via <a href="/rfunds" style="color:#14b8a6">rFunds</a></li> <li><strong>Local fulfillment</strong> &mdash; orders route to the nearest registered print shop, not a distant warehouse</li>
<li><strong>Cosmolocal fulfillment</strong> &mdash; nearest provider prints and ships</li> <li><strong>Transparent pricing</strong> &mdash; 30% to the author, 10% to the community, 60% to print and delivery</li>
<li><strong>Order tracking</strong> &mdash; real-time status from press to doorstep</li>
</ul> </ul>
</div> </div>
<div class="rl-card rl-card--center" style="display:flex;align-items:center;justify-content:center"> <div class="rl-card" style="padding:1.5rem">
<div> <p style="font-size:0.7rem;font-weight:600;color:#94a3b8;text-transform:uppercase;letter-spacing:0.08em;margin-bottom:1rem">Example group buy</p>
<div class="rl-icon-box" style="margin:0 auto 1rem"> <!-- Mini order summary -->
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="9" cy="21" r="1"/><circle cx="20" cy="21" r="1"/><path d="M1 1h4l2.68 13.39a2 2 0 002 1.61h9.72a2 2 0 002-1.61L23 6H6"/></svg> <div style="margin-bottom:1rem">
<div style="display:flex;align-items:center;justify-content:space-between;font-size:0.875rem;margin-bottom:0.75rem">
<span style="font-weight:500;color:#e2e8f0">The Commons</span>
<span style="color:#94a3b8">by J. Emmett</span>
</div> </div>
<h3>Shop + Press</h3> <div class="rl-progress">
<p>rPubs creates the artifact.<br>rCart sells and fulfills it.</p> <div class="rl-progress__fill" style="width:72%"></div>
</div>
<div style="display:flex;align-items:center;justify-content:space-between;font-size:0.75rem;color:#94a3b8;margin-top:0.5rem">
<span>36 of 50 copies ordered</span>
<span style="color:#14b8a6;font-weight:500">72%</span>
</div>
</div>
<!-- Tier indicator -->
<div class="rl-tier">
<div class="rl-tier__item rl-tier__item--active">
<p><strong>25+</strong></p>
<p style="opacity:0.7">$8/copy</p>
</div>
<div class="rl-tier__item rl-tier__item--active">
<p><strong>50+</strong></p>
<p style="opacity:0.7">$6/copy</p>
</div>
<div class="rl-tier__item">
<p><strong style="color:#64748b">100+</strong></p>
<p style="color:#64748b">$4.50</p>
</div>
</div>
<div style="font-size:0.75rem;color:#94a3b8;line-height:1.55;margin-top:1rem">
<p style="margin-bottom:0.25rem"><span style="font-weight:500;color:#e2e8f0">Current tier:</span> Saddle-stitch at $8/copy</p>
<p><span style="font-weight:500;color:#e2e8f0">14 more copies</span> to unlock perfect-bind at $6/copy &mdash; everyone saves.</p>
</div> </div>
</div> </div>
</div> </div>
@ -230,76 +347,38 @@ export function renderLanding(): string {
</section> </section>
<!-- Cosmolocal --> <!-- Cosmolocal -->
<section class="rl-section rl-section--alt"> <section class="rl-section">
<div class="rl-container" style="text-align:center"> <div class="rl-container" style="text-align:center">
<span class="rl-tagline">rPubs &times; Cosmolocal</span>
<h2 class="rl-heading">Design global, manufacture local</h2> <h2 class="rl-heading">Design global, manufacture local</h2>
<p class="rl-subtext"> <p class="rl-subtext">
Every print run is routed to the nearest capable provider. Reduce shipping emissions, rPubs connects you to a cosmolocal network of independent print shops.
support local economies, and still benefit from shared design and pooled demand. Your writing is typeset in the cloud and printed close to where it&rsquo;s
needed &mdash; reducing shipping, supporting local makers, and keeping
publishing accessible.
</p> </p>
</div> <div style="display:flex;align-items:center;justify-content:center;gap:0.75rem;flex-wrap:wrap">
</section> <a href="https://demo.rspace.online/rpubs" style="display:inline-flex;align-items:center;gap:0.4rem;padding:0.5rem 1rem;border-radius:0.5rem;border:1px solid rgba(20,184,166,0.3);color:#14b8a6;font-size:0.875rem;font-weight:500;text-decoration:none">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>
<!-- Built on Open Source --> Register Your Print Shop
<section class="rl-section"> </a>
<div class="rl-container"> <a href="https://demo.rspace.online/rpubs" style="display:inline-block;padding:0.5rem 1rem;border-radius:0.5rem;border:1px solid rgba(255,255,255,0.15);color:#94a3b8;font-size:0.875rem;font-weight:500;text-decoration:none">
<h2 class="rl-heading" style="text-align:center">Built on Open Source</h2> Fund a Title
<p class="rl-subtext" style="text-align:center">The libraries and tools that power rPubs.</p> </a>
<div class="rl-grid-3"> <a href="https://rcart.online" style="display:inline-flex;align-items:center;gap:0.4rem;padding:0.5rem 1rem;border-radius:0.5rem;border:1px solid rgba(255,255,255,0.15);color:#94a3b8;font-size:0.875rem;font-weight:500;text-decoration:none">
<div class="rl-card rl-card--center"> <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="9" cy="21" r="1"/><circle cx="20" cy="21" r="1"/><path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"/></svg>
<div class="rl-icon-box">&#9881;</div> Browse on rCart
<h3>Typst</h3> </a>
<p>Document compilation engine. Transforms markdown into beautifully typeset, print-ready PDFs.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128293;</div>
<h3>Hono</h3>
<p>Ultrafast web framework for the API layer. Lightweight, edge-ready, and built for speed.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128451;</div>
<h3>PostgreSQL</h3>
<p>Rock-solid relational database for catalog storage, orders, and artifact metadata.</p>
</div>
</div>
</div>
</section>
<!-- Your Data, Protected -->
<section class="rl-section rl-section--alt">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">Your Data, Protected</h2>
<p class="rl-subtext">How rPubs keeps your information safe.</p>
<div class="rl-grid-3">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128274;</div>
<h3>End-to-End Encryption</h3>
<span class="rl-badge">Coming Soon</span>
<p>All content encrypted before it leaves your device. Not even the server can read it.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128373;</div>
<h3>Zero-Knowledge Architecture</h3>
<span class="rl-badge">Coming Soon</span>
<p>The server processes your requests without ever seeing your data in the clear.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#127968;</div>
<h3>Self-Hosted</h3>
<p>Run on your own infrastructure. Your server, your rules, your data.</p>
</div>
</div> </div>
</div> </div>
</section> </section>
<!-- CTA --> <!-- CTA -->
<section class="rl-section"> <section class="rl-section rl-section--alt">
<div class="rl-container" style="text-align:center"> <div class="rl-container" style="text-align:center">
<h2 class="rl-heading">(You)rPubs, your press.</h2> <h2 class="rl-heading">Write it. Press it. Share it.</h2>
<p class="rl-subtext">Try the demo or create a space to get started.</p> <p class="rl-subtext">Try the demo or create a space to get started.</p>
<div class="rl-cta-row"> <div class="rl-cta-row">
<a href="https://demo.rspace.online/rpubs" class="rl-cta-primary">Try the Press</a> <a href="https://demo.rspace.online/rpubs" class="rl-cta-primary">Start Writing</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a> <a href="/create-space" class="rl-cta-secondary">Create a Space</a>
</div> </div>
</div> </div>

View File

@ -1,79 +1,177 @@
/** /**
* rTrips landing page group travel planning. * rTrips landing page group travel planning.
* Ported from /opt/websites/rtrips-online/src/app/page.tsx
*/ */
export function renderLanding(): string { export function renderLanding(): string {
return ` return `
<!-- Hero --> <!-- Hero -->
<div class="rl-hero"> <div class="rl-hero">
<span class="rl-tagline">rTrips</span> <span class="rl-tagline">rTrips</span>
<h1 class="rl-heading">(You)rTrips, your horizon.</h1> <h1 class="rl-heading" style="background:linear-gradient(135deg,#5eead4,#67e8f9,#93c5fd);-webkit-background-clip:text;background-clip:text">(You)rTrips, your horizon.</h1>
<p class="rl-subtitle">Plan Your Trip, Naturally</p> <p class="rl-subtitle" style="background:linear-gradient(135deg,#5eead4,#67e8f9,#93c5fd);-webkit-background-clip:text;background-clip:text">Plan Your Trip, Naturally</p>
<p class="rl-subtext"> <p class="rl-subtext">
Describe your dream trip in plain language. We'll structure it into Describe your dream trip in plain language. We'll structure it into
itineraries, budgets, and bookings &mdash; then give you a collaborative itineraries, budgets, and bookings &mdash; then give you a collaborative
canvas to plan together in real-time. canvas to plan together in real-time.
</p> </p>
<div class="rl-cta-row"> <div class="rl-cta-row">
<a href="https://demo.rspace.online/rtrips" class="rl-cta-primary" id="ml-primary">Plan a Trip</a> <a href="https://demo.rspace.online/rtrips" class="rl-cta-primary" id="ml-primary">Start Planning</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a> <a href="/create-space" class="rl-cta-secondary">Create a Space</a>
</div> </div>
</div> </div>
<!-- Features --> <!-- How It Works -->
<section class="rl-section"> <section class="rl-section">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">What rTrips Handles</h2> <h2 class="rl-heading" style="text-align:center">How It Works</h2>
<div class="rl-grid-4"> <div class="rl-grid-3">
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128506;</div> <div class="rl-icon-box" style="background:rgba(20,184,166,0.15)">
<h3>Route Planning</h3> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#2dd4bf" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z"/></svg>
<p>Visualize your entire trip on rMaps. See routes between destinations and nearby points of interest.</p> </div>
<h3>Describe It</h3>
<p>Tell us about your trip in natural language. &ldquo;Fly from Toronto to Bali
for 2 weeks in March, budget $3000.&rdquo; We parse it into structured data
you can refine.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128197;</div> <div class="rl-icon-box" style="background:rgba(6,182,212,0.15)">
<h3>Itinerary Building</h3> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#22d3ee" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"/></svg>
<p>Build day-by-day plans together. Add destinations, suggest activities, and rearrange the schedule.</p> </div>
<h3>We Structure It</h3>
<p>AI extracts destinations, dates, budgets, and bookings into organized views.
Edit itineraries, track expenses, manage packing lists &mdash; all structured
and searchable.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128176;</div> <div class="rl-icon-box" style="background:rgba(59,130,246,0.15)">
<h3>Expense Splitting</h3> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#60a5fa" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0z"/></svg>
<p>Split costs and track expenses across the group. Everyone knows exactly where the money goes.</p> </div>
</div> <h3>Collaborate on Canvas</h3>
<div class="rl-card rl-card--center"> <p>Open the collaborative canvas to plan visually with your travel partners.
<div class="rl-icon-box">&#128101;</div> Drag destinations, connect itineraries, and brainstorm together in real-time
<h3>Group Coordination</h3> or async.</p>
<p>Real-time collaborative canvas for travel partners. Plan visually, brainstorm together, stay in sync.</p>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- How It Works --> <!-- Features -->
<section class="rl-section rl-section--alt"> <section class="rl-section rl-section--alt">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">How It Works</h2> <h2 class="rl-heading" style="text-align:center">Everything You Need to Travel Together</h2>
<div class="rl-grid-3"> <p class="rl-subtext" style="text-align:center">
<div class="rl-step"> rTrips brings every piece of trip planning into one place &mdash; so your group
<span class="rl-step__num">1</span> spends less time coordinating and more time exploring.
<h3>Create a trip</h3> </p>
<p>Describe your trip in natural language. &ldquo;Fly from Toronto to Bali for 2 weeks in March, budget $3000.&rdquo; We parse it into structured data you can refine.</p> <div class="rl-grid-3" style="margin-top:2rem">
<!-- Collaborative Itineraries -->
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(16,185,129,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#34d399" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M18 18.72a9.094 9.094 0 003.741-.479 3 3 0 00-4.682-2.72m.94 3.198l.001.031c0 .225-.012.447-.037.666A11.944 11.944 0 0112 21c-2.17 0-4.207-.576-5.963-1.584A6.062 6.062 0 016 18.719m12 0a5.971 5.971 0 00-.941-3.197m0 0A5.995 5.995 0 0012 12.75a5.995 5.995 0 00-5.058 2.772m0 0a3 3 0 00-4.681 2.72 8.986 8.986 0 003.74.477m.94-3.197a5.971 5.971 0 00-.94 3.197M15 6.75a3 3 0 11-6 0 3 3 0 016 0zm6 3a2.25 2.25 0 11-4.5 0 2.25 2.25 0 014.5 0zm-13.5 0a2.25 2.25 0 11-4.5 0 2.25 2.25 0 014.5 0z"/></svg>
</div>
<h3>Collaborative Itineraries</h3>
<p>Build day-by-day plans together in real-time. Everyone can add destinations,
suggest activities, and rearrange the schedule &mdash; changes sync instantly.</p>
</div> </div>
<div class="rl-step">
<span class="rl-step__num">2</span> <!-- Smart Suggestions -->
<h3>Plan your route</h3> <div class="rl-card rl-card--center">
<p>AI extracts destinations, dates, budgets, and bookings into organized views. Edit itineraries, track expenses, manage packing lists.</p> <div class="rl-icon-box" style="background:rgba(16,185,129,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#34d399" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M9.813 15.904L9 18.75l-.813-2.846a4.5 4.5 0 00-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 003.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 003.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 00-3.09 3.09zM18.259 8.715L18 9.75l-.259-1.035a3.375 3.375 0 00-2.455-2.456L14.25 6l1.036-.259a3.375 3.375 0 002.455-2.456L18 2.25l.259 1.035a3.375 3.375 0 002.455 2.456L21.75 6l-1.036.259a3.375 3.375 0 00-2.455 2.456z"/></svg>
</div>
<h3>Smart Suggestions</h3>
<p>AI-powered recommendations for destinations, restaurants, and activities based
on your group's interests, budget, and travel dates.</p>
</div> </div>
<div class="rl-step">
<span class="rl-step__num">3</span> <!-- Budget Tracking -->
<h3>Split expenses</h3> <div class="rl-card rl-card--center">
<p>Track costs across the group with automatic splitting. Pay your share, see the running total, and keep finances transparent.</p> <div class="rl-icon-box" style="background:rgba(16,185,129,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#34d399" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M2.25 18.75a60.07 60.07 0 0115.797 2.101c.727.198 1.453-.342 1.453-1.096V18.75M3.75 4.5v.75A.75.75 0 013 6h-.75m0 0v-.375c0-.621.504-1.125 1.125-1.125H20.25M2.25 6v9m18-10.5v.75c0 .414.336.75.75.75h.75m-1.5-1.5h.375c.621 0 1.125.504 1.125 1.125v9.75c0 .621-.504 1.125-1.125 1.125h-.375m1.5-1.5H21a.75.75 0 00-.75.75v.75m0 0H3.75m0 0h-.375a1.125 1.125 0 01-1.125-1.125V15m1.5 1.5v-.75A.75.75 0 003 15h-.75M15 10.5a3 3 0 11-6 0 3 3 0 016 0zm3 0h.008v.008H18V10.5zm-12 0h.008v.008H6V10.5z"/></svg>
</div>
<h3>Budget Tracking</h3>
<p>Split costs, track expenses across the group, and keep a running total so
everyone knows exactly where the money goes. No more messy spreadsheets.</p>
</div>
<!-- Map Integration -->
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(16,185,129,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#34d399" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M9 6.75V15m6-6v8.25m.503 3.498l4.875-2.437c.381-.19.622-.58.622-1.006V4.82c0-.836-.88-1.38-1.628-1.006l-3.869 1.934c-.317.159-.69.159-1.006 0L9.503 3.252a1.125 1.125 0 00-1.006 0L3.622 5.689C3.24 5.88 3 6.27 3 6.695V19.18c0 .836.88 1.38 1.628 1.006l3.869-1.934c.317-.159.69-.159 1.006 0l4.994 2.497c.317.158.69.158 1.006 0z"/></svg>
</div>
<h3>Map Integration</h3>
<p>Visualize your entire trip on rMaps. See routes between destinations,
nearby points of interest, and real-time location sharing during travel days.</p>
</div>
<!-- Packing Lists -->
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(16,185,129,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#34d399" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M9 12h3.75M9 15h3.75M9 18h3.75m3 .75H18a2.25 2.25 0 002.25-2.25V6.108c0-1.135-.845-2.098-1.976-2.192a48.424 48.424 0 00-1.123-.08m-5.801 0c-.065.21-.1.433-.1.664 0 .414.336.75.75.75h4.5a.75.75 0 00.75-.75 2.25 2.25 0 00-.1-.664m-5.8 0A2.251 2.251 0 0113.5 2.25H15a2.25 2.25 0 012.15 1.586m-5.8 0c-.376.023-.75.05-1.124.08C9.095 4.01 8.25 4.973 8.25 6.108V8.25m0 0H4.875c-.621 0-1.125.504-1.125 1.125v11.25c0 .621.504 1.125 1.125 1.125h9.75c.621 0 1.125-.504 1.125-1.125V9.375c0-.621-.504-1.125-1.125-1.125H8.25zM6.75 12h.008v.008H6.75V12zm0 3h.008v.008H6.75V15zm0 3h.008v.008H6.75V18z"/></svg>
</div>
<h3>Packing Lists</h3>
<p>Shared checklists so nothing gets forgotten. Assign items to people, mark
off as you pack, and see at a glance what the group still needs.</p>
</div>
<!-- Offline Access -->
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(16,185,129,0.12)">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#34d399" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5M16.5 12L12 16.5m0 0L7.5 12m4.5 4.5V3"/></svg>
</div>
<h3>Offline Access</h3>
<p>Download your full itinerary, maps, and booking confirmations for travel
without connectivity. Everything you need, even without a signal.</p>
</div>
</div>
</div>
</section>
<!-- Built for Groups -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Built for Groups</h2>
<p class="rl-subtext" style="text-align:center">
Solo trip planners are everywhere. rTrips is purpose-built for the messy, beautiful
reality of traveling with other people.
</p>
<div class="rl-grid-3" style="margin-top:2rem">
<!-- Friends & Family -->
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(16,185,129,0.08)">
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#34d399" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12z"/></svg>
</div>
<h3>Friends &amp; Family</h3>
<p>Family reunions, friend getaways, multi-generational trips. Everyone contributes
ideas, votes on restaurants, and stays in sync without endless group chats.</p>
</div>
<!-- Teams & Offsites -->
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(16,185,129,0.08)">
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#34d399" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M20.25 14.15v4.25c0 1.094-.787 2.036-1.872 2.18-2.087.277-4.216.42-6.378.42s-4.291-.143-6.378-.42c-1.085-.144-1.872-1.086-1.872-2.18v-4.25m16.5 0a2.18 2.18 0 00.75-1.661V8.706c0-1.081-.768-2.015-1.837-2.175a48.114 48.114 0 00-3.413-.387m4.5 8.006c-.194.165-.42.295-.673.38A23.978 23.978 0 0112 15.75c-2.648 0-5.195-.429-7.577-1.22a2.016 2.016 0 01-.673-.38m0 0A2.18 2.18 0 013 12.489V8.706c0-1.081.768-2.015 1.837-2.175a48.111 48.111 0 013.413-.387m7.5 0V5.25A2.25 2.25 0 0013.5 3h-3a2.25 2.25 0 00-2.25 2.25v.894m7.5 0a48.667 48.667 0 00-7.5 0M12 12.75h.008v.008H12v-.008z"/></svg>
</div>
<h3>Teams &amp; Offsites</h3>
<p>Company retreats, conference travel, team offsites. Coordinate logistics,
share flight details, and manage group bookings from a single shared workspace.</p>
</div>
<!-- Retreats & Events -->
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:rgba(16,185,129,0.08)">
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#34d399" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12.75 3.03v.568c0 .334.148.65.405.864l1.068.89c.442.369.535 1.01.216 1.49l-.51.766a2.25 2.25 0 01-1.161.886l-.143.048a1.107 1.107 0 00-.57 1.664c.369.555.169 1.307-.427 1.605L9 13.125l.423 1.059a.956.956 0 01-1.652.928l-.679-.906a1.125 1.125 0 00-1.906.172L4.5 15.75l-.612.153M12.75 3.031a9 9 0 00-8.862 12.872M12.75 3.031a9 9 0 016.69 14.036m0 0l-.177-.529A2.25 2.25 0 0017.128 15H16.5l-.324-.324a1.453 1.453 0 00-2.328.377l-.036.073a1.586 1.586 0 01-.982.816l-.99.282c-.55.157-.894.702-.8 1.267l.073.438a2.25 2.25 0 01-1.228 2.446L10.5 21l-.652-.174M12.75 3.031l.176.53"/></svg>
</div>
<h3>Retreats &amp; Events</h3>
<p>Yoga retreats, wedding trips, festival crews. Organize large groups with
sub-itineraries, optional activities, and shared costs that stay transparent.</p>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- Built on Open Source --> <!-- Built on Open Source -->
<section class="rl-section"> <section class="rl-section rl-section--alt">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Built on Open Source</h2> <h2 class="rl-heading" style="text-align:center">Built on Open Source</h2>
<p class="rl-subtext" style="text-align:center">The libraries and tools that power rTrips.</p> <p class="rl-subtext" style="text-align:center">The libraries and tools that power rTrips.</p>
@ -98,7 +196,7 @@ export function renderLanding(): string {
</section> </section>
<!-- Your Data, Protected --> <!-- Your Data, Protected -->
<section class="rl-section rl-section--alt"> <section class="rl-section">
<div class="rl-container" style="text-align:center"> <div class="rl-container" style="text-align:center">
<h2 class="rl-heading">Your Data, Protected</h2> <h2 class="rl-heading">Your Data, Protected</h2>
<p class="rl-subtext">How rTrips keeps your information safe.</p> <p class="rl-subtext">How rTrips keeps your information safe.</p>
@ -125,10 +223,10 @@ export function renderLanding(): string {
</section> </section>
<!-- CTA --> <!-- CTA -->
<section class="rl-section"> <section class="rl-section rl-section--alt">
<div class="rl-container" style="text-align:center"> <div class="rl-container" style="text-align:center">
<h2 class="rl-heading">(You)rTrips, your horizon.</h2> <h2 class="rl-heading">Ready to plan your next adventure?</h2>
<p class="rl-subtext">Try the demo or create a space to get started.</p> <p class="rl-subtext">Just describe where you want to go. We'll handle the rest.</p>
<div class="rl-cta-row"> <div class="rl-cta-row">
<a href="https://demo.rspace.online/rtrips" class="rl-cta-primary">Plan a Trip</a> <a href="https://demo.rspace.online/rtrips" class="rl-cta-primary">Plan a Trip</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a> <a href="/create-space" class="rl-cta-secondary">Create a Space</a>

View File

@ -1,163 +1,195 @@
/** /**
* Tube module landing page rich content for rspace.online/rtube * rTube rich landing page body.
* Ported from rtube-online/app/page.tsx (Next.js/Tailwind).
* Returned by landingPage() in the module export;
* the shell wraps it with header, CSS, and analytics.
*/ */
export function renderLanding(): string { export function renderLanding(): string {
return ` return `
<!-- Hero --> <!-- Hero -->
<div class="rl-hero"> <div class="rl-hero">
<span class="rl-tagline">rTube</span> <span class="rl-tagline">rTube</span>
<h1 class="rl-heading">(You)rTube, your channel.</h1> <h1 class="rl-heading" style="background:linear-gradient(to right,#f87171,#f9a8d4,#fdba74);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">
<p class="rl-subtitle">Community Video Platform</p> Community Video Hosting, Storage &amp; Streaming
<p class="rl-subtext"> </h1>
Host, stream, and share video without big tech. <p class="rl-subtitle">Who needs YouTube, when you have (ou)rTube!</p>
Your community's video library with HLS streaming and RTMP ingest. <p class="rl-subtext">
</p> Self-hosted video recording, live streaming, and storage for your rSpace community.
<div class="rl-cta-row"> No corporate surveillance. No algorithmic feeds. Just your community's content.
<a href="https://demo.rspace.online/rtube" class="rl-cta-primary" id="ml-primary">Start Streaming</a> </p>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a> <div class="rl-cta-row">
<a href="https://demo.rspace.online/rtube" class="rl-cta-secondary" id="ml-primary">Browse Videos</a>
<a href="https://demo.rspace.online/rtube" class="rl-cta-primary" style="background:#dc2626">Start Streaming</a>
</div>
</div>
<!-- How It Works -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">How It Works</h2>
<div class="rl-grid-3">
<div class="rl-card rl-card--center">
<div style="width:3rem;height:3rem;background:rgba(239,68,68,0.2);border-radius:0.75rem;display:flex;align-items:center;justify-content:center;margin:0 auto 1rem">
<svg style="width:1.5rem;height:1.5rem;color:#f87171" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<circle cx="12" cy="12" r="10" stroke-width="2" />
<circle cx="12" cy="12" r="4" fill="currentColor" />
</svg>
</div>
<h3>Record</h3>
<p>Stream directly from OBS, browser, or any RTMP-compatible tool. Your content
goes straight to your community's server &mdash; no third-party platforms involved.</p>
</div>
<div class="rl-card rl-card--center">
<div style="width:3rem;height:3rem;background:rgba(236,72,153,0.2);border-radius:0.75rem;display:flex;align-items:center;justify-content:center;margin:0 auto 1rem">
<svg style="width:1.5rem;height:1.5rem;color:#f472b6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z" />
</svg>
</div>
<h3>Stream Live</h3>
<p>Community members watch in real-time via HLS adaptive streaming.
Low-latency delivery through your own nginx-rtmp server with automatic
quality adaptation.</p>
</div>
<div class="rl-card rl-card--center">
<div style="width:3rem;height:3rem;background:rgba(249,115,22,0.2);border-radius:0.75rem;display:flex;align-items:center;justify-content:center;margin:0 auto 1rem">
<svg style="width:1.5rem;height:1.5rem;color:#fb923c" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 8h14M5 8a2 2 0 110-4h14a2 2 0 110 4M5 8v10a2 2 0 002 2h10a2 2 0 002-2V8m-9 4h4" />
</svg>
</div>
<h3>Archive &amp; Store</h3>
<p>Completed streams are automatically converted to MP4 and archived to
R2 cloud storage. Browse, search, and replay your community's entire
video library anytime.</p>
</div>
</div> </div>
</div> </div>
</section>
<!-- Features --> <!-- Built for Communities -->
<section class="rl-section"> <section class="rl-section rl-section--alt">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">What rTube Handles</h2> <div style="background:rgba(30,41,59,0.3);border-radius:1rem;border:1px solid rgba(51,65,85,0.5);padding:2rem">
<div class="rl-grid-4"> <h2 class="rl-heading" style="text-align:center;margin-bottom:2rem">Built for Communities</h2>
<div class="rl-card rl-card--center"> <div class="rl-grid-2" style="max-width:48rem;margin:0 auto">
<div class="rl-icon-box">&#128250;</div> <div style="display:flex;align-items:flex-start;gap:0.75rem">
<h3>Video Hosting</h3> <span style="color:#f87171;font-size:1.125rem;margin-top:2px">&#9679;</span>
<p>Upload video files in any major format. MP4, WebM, MKV, MOV &mdash; they all work.</p> <div>
<h4 style="font-weight:500;margin-bottom:0.25rem">Self-Hosted</h4>
<p style="font-size:0.875rem;color:#94a3b8">Your server, your data. No YouTube, no Twitch, no corporate middlemen.</p>
</div>
</div> </div>
<div class="rl-card rl-card--center"> <div style="display:flex;align-items:flex-start;gap:0.75rem">
<div class="rl-icon-box">&#128225;</div> <span style="color:#f472b6;font-size:1.125rem;margin-top:2px">&#9679;</span>
<h3>HLS Adaptive Streaming</h3> <div>
<p>Adaptive bitrate streaming ensures smooth playback on any connection speed or device.</p> <h4 style="font-weight:500;margin-bottom:0.25rem">RTMP Ingest</h4>
<p style="font-size:0.875rem;color:#94a3b8">Standard RTMP protocol &mdash; works with OBS, Streamlabs, FFmpeg, and more.</p>
</div>
</div> </div>
<div class="rl-card rl-card--center"> <div style="display:flex;align-items:flex-start;gap:0.75rem">
<div class="rl-icon-box">&#128225;</div> <span style="color:#fb923c;font-size:1.125rem;margin-top:2px">&#9679;</span>
<h3>RTMP Live Ingest</h3> <div>
<p>Go live with OBS, Streamlabs, or any RTMP-compatible streaming software. One URL, instant broadcast.</p> <h4 style="font-weight:500;margin-bottom:0.25rem">R2 Cloud Storage</h4>
<p style="font-size:0.875rem;color:#94a3b8">Cloudflare R2 for cost-effective, globally distributed video storage.</p>
</div>
</div> </div>
<div class="rl-card rl-card--center"> <div style="display:flex;align-items:flex-start;gap:0.75rem">
<div class="rl-icon-box">&#127909;</div> <span style="color:#fbbf24;font-size:1.125rem;margin-top:2px">&#9679;</span>
<h3>R2 Cloud Storage &amp; Community Channels</h3> <div>
<p>Videos stored on Cloudflare R2 for fast delivery. Each space gets its own channel.</p> <h4 style="font-weight:500;margin-bottom:0.25rem">HLS Playback</h4>
<p style="font-size:0.875rem;color:#94a3b8">Adaptive bitrate streaming works on every device and browser.</p>
</div>
</div>
<div style="display:flex;align-items:flex-start;gap:0.75rem">
<span style="color:#fb7185;font-size:1.125rem;margin-top:2px">&#9679;</span>
<div>
<h4 style="font-weight:500;margin-bottom:0.25rem">Auto-Archive</h4>
<p style="font-size:0.875rem;color:#94a3b8">Streams are automatically converted to MP4 and uploaded when they end.</p>
</div>
</div>
<div style="display:flex;align-items:flex-start;gap:0.75rem">
<span style="color:#e879f9;font-size:1.125rem;margin-top:2px">&#9679;</span>
<div>
<h4 style="font-weight:500;margin-bottom:0.25rem">Community-Scoped</h4>
<p style="font-size:0.875rem;color:#94a3b8">Each rSpace community gets its own video library and streaming channel.</p>
</div>
</div> </div>
</div> </div>
</div> </div>
</section> </div>
</section>
<!-- How It Works --> <!-- Built on Open Source -->
<section class="rl-section rl-section--alt"> <section class="rl-section">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">How It Works</h2> <h2 class="rl-heading" style="text-align:center">Built on Open Source</h2>
<div class="rl-grid-3"> <p class="rl-subtext" style="text-align:center">The libraries and tools that power rTube.</p>
<div class="rl-step"> <div class="rl-grid-4">
<div class="rl-step__num">1</div> <div class="rl-card rl-card--center">
<h3>Upload or Stream Live</h3> <div class="rl-icon-box">&#9729;</div>
<p>Drop video files in any format or point OBS at your space's RTMP ingest URL and go live instantly.</p> <h3>AWS S3 SDK</h3>
</div> <p>Cloudflare R2 object storage via the S3-compatible API. Fast, globally distributed, no egress fees.</p>
<div class="rl-step"> </div>
<div class="rl-step__num">2</div> <div class="rl-card rl-card--center">
<h3>Automatic HLS Transcoding</h3> <div class="rl-icon-box">&#128250;</div>
<p>FFmpeg transcodes uploads into adaptive bitrate HLS streams for smooth playback on any device.</p> <h3>HLS.js</h3>
</div> <p>Adaptive bitrate streaming library. Smooth playback with automatic quality switching in the browser.</p>
<div class="rl-step"> </div>
<div class="rl-step__num">3</div> <div class="rl-card rl-card--center">
<h3>Share with Your Community</h3> <div class="rl-icon-box">&#127910;</div>
<p>Videos are organized by space. Share links, embed on your canvas, or browse the community library.</p> <h3>FFmpeg</h3>
</div> <p>Industry-standard video transcoding. Converts uploads into multi-bitrate HLS streams automatically.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128293;</div>
<h3>Hono</h3>
<p>Ultrafast web framework for the API layer. Lightweight, type-safe, and runs on any JavaScript runtime.</p>
</div> </div>
</div> </div>
</section> </div>
</section>
<!-- Technical Details (module-specific) --> <!-- Your Data, Protected -->
<section class="rl-section"> <section class="rl-section rl-section--alt">
<div class="rl-container"> <div class="rl-container" style="text-align:center">
<h2 class="rl-heading" style="text-align:center">Technical Details</h2> <h2 class="rl-heading">Your Data, Protected</h2>
<div class="rl-card" style="max-width:600px;margin:0 auto;"> <p class="rl-subtext">How rTube keeps your information safe.</p>
<ul class="rl-check-list"> <div class="rl-grid-3">
<li><strong>H.264 / H.265</strong> hardware-accelerated codec support</li> <div class="rl-card rl-card--center">
<li><strong>WebM</strong> (VP8/VP9) for open-format video</li> <div class="rl-icon-box">&#128274;</div>
<li><strong>Adaptive bitrate HLS</strong> for smooth playback on any connection</li> <h3>End-to-End Encryption</h3>
<li><strong>HTTP Range requests</strong> for efficient seeking and partial downloads</li> <span class="rl-badge">Coming Soon</span>
<li><strong>RTMP ingest</strong> compatible with OBS, Streamlabs, and ffmpeg</li> <p>All content encrypted before it leaves your device. Not even the server can read it.</p>
</ul> </div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128373;</div>
<h3>Zero-Knowledge Architecture</h3>
<span class="rl-badge">Coming Soon</span>
<p>The server processes your requests without ever seeing your data in the clear.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#127968;</div>
<h3>Self-Hosted</h3>
<p>Run on your own infrastructure. Your server, your rules, your data.</p>
</div> </div>
</div> </div>
</section> </div>
</section>
<!-- Built on Open Source --> <!-- CTA -->
<section class="rl-section rl-section--alt"> <section class="rl-section">
<div class="rl-container"> <div class="rl-container" style="text-align:center">
<h2 class="rl-heading" style="text-align:center">Built on Open Source</h2> <h2 class="rl-heading">Ready to take back your video?</h2>
<p class="rl-subtext" style="text-align:center">The libraries and tools that power rTube.</p> <p class="rl-subtext">Browse the community video library or start a live stream for your rSpace.</p>
<div class="rl-grid-4"> <div class="rl-cta-row">
<div class="rl-card rl-card--center"> <a href="https://demo.rspace.online/rtube" class="rl-cta-primary" style="background:#dc2626">Start Streaming</a>
<div class="rl-icon-box">&#9729;</div> <a href="https://demo.rspace.online/rtube" class="rl-cta-secondary">Browse Videos</a>
<h3>AWS S3 SDK</h3>
<p>Cloudflare R2 object storage via the S3-compatible API. Fast, globally distributed, no egress fees.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128250;</div>
<h3>HLS.js</h3>
<p>Adaptive bitrate streaming library. Smooth playback with automatic quality switching in the browser.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#127910;</div>
<h3>FFmpeg</h3>
<p>Industry-standard video transcoding. Converts uploads into multi-bitrate HLS streams automatically.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128293;</div>
<h3>Hono</h3>
<p>Ultrafast web framework for the API layer. Lightweight, type-safe, and runs on any JavaScript runtime.</p>
</div>
</div>
</div> </div>
</section> </div>
</section>
<!-- Your Data, Protected --> <div class="rl-back">
<section class="rl-section"> <a href="/">&larr; Back to rSpace</a>
<div class="rl-container" style="text-align:center"> </div>`;
<h2 class="rl-heading">Your Data, Protected</h2>
<p class="rl-subtext">How rTube keeps your information safe.</p>
<div class="rl-grid-3">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128274;</div>
<h3>End-to-End Encryption</h3>
<span class="rl-badge">Coming Soon</span>
<p>All content encrypted before it leaves your device. Not even the server can read it.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128373;</div>
<h3>Zero-Knowledge Architecture</h3>
<span class="rl-badge">Coming Soon</span>
<p>The server processes your requests without ever seeing your data in the clear.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#127968;</div>
<h3>Self-Hosted</h3>
<p>Run on your own infrastructure. Your server, your rules, your data.</p>
</div>
</div>
</div>
</section>
<!-- CTA -->
<section class="rl-section rl-section--alt">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">(You)rTube, your channel.</h2>
<p class="rl-subtext">Try the demo or create a space to get started.</p>
<div class="rl-cta-row">
<a href="https://demo.rspace.online/rtube" class="rl-cta-primary">Start Streaming</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a>
</div>
</div>
</section>
<div class="rl-back">
<a href="/">&larr; Back to rSpace</a>
</div>`;
} }

View File

@ -1,216 +1,353 @@
/** /**
* rVote landing page democratic backlog prioritization. * rVote landing page democratic backlog prioritization.
* Ported from rvote-online Next.js page.tsx (423 lines, shadcn/ui).
*/ */
export function renderLanding(): string { export function renderLanding(): string {
return ` return `
<!-- Hero --> <!-- Hero -->
<div class="rl-hero"> <div class="rl-hero">
<span class="rl-tagline">rVote</span> <span class="rl-tagline" style="color:#818cf8;background:rgba(129,140,248,0.1);border-color:rgba(129,140,248,0.2)">
<h1 class="rl-heading">(You)rVote, your voice.</h1> Part of the rSpace Ecosystem
<p class="rl-subtitle">Democratic Backlog Prioritization</p> </span>
<p class="rl-subtext"> <h1 class="rl-heading" style="background:linear-gradient(to right,#818cf8,#c084fc);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;font-size:2.5rem">
Quadratic conviction voting with time-decay. Surface the ideas your community actually cares about &mdash; Democratic<br>Backlog Prioritization
not just the loudest voices. </h1>
<p class="rl-subtitle">
rVote uses <strong style="color:#e2e8f0">Quadratic Proposal Ranking</strong> to let your community democratically
prioritize proposals. The best ideas rise to the top through collective intelligence,
then advance to final voting.
</p> </p>
<div class="rl-cta-row"> <div class="rl-cta-row">
<a href="https://demo.rspace.online/rvote" class="rl-cta-primary" id="ml-primary">Start Voting</a> <a href="https://demo.rspace.online/rvote" class="rl-cta-primary" id="ml-primary"
style="background:linear-gradient(to right,#818cf8,#6366f1);color:white">
<span style="display:inline-flex;align-items:center;gap:0.5rem">
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor" stroke="none"><polygon points="5,3 19,12 5,21"/></svg>
Try the Demo
</span>
</a>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a> <a href="/create-space" class="rl-cta-secondary">Create a Space</a>
</div> </div>
</div> </div>
<!-- Features --> <!-- ELI5 Section: rVote in 30 Seconds -->
<section class="rl-section"> <section class="rl-section" style="border-top:none">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">What rVote Handles</h2> <div style="text-align:center;margin-bottom:2rem">
<div class="rl-grid-4"> <span class="rl-badge" style="background:#1e293b;color:#94a3b8;font-size:0.7rem;padding:0.25rem 0.75rem">ELI5</span>
<div class="rl-card rl-card--center"> <h2 class="rl-heading" style="margin-top:0.75rem;background:linear-gradient(135deg,#e2e8f0,#cbd5e1);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">
<div class="rl-icon-box"><span style="font-size:1.25rem;font-weight:700">x&#178;</span></div> rVote in 30 Seconds
<h3>Conviction Voting</h3> </h2>
<p>Proposals accumulate conviction score from community votes. The most supported ideas float to the top.</p> <p style="font-size:1.05rem;color:#94a3b8;max-width:640px;margin:0.5rem auto 0">
</div> A <strong style="color:#f97316">quadratic</strong>
<div class="rl-card rl-card--center"> <strong style="color:#3b82f6"> Reddit-style ranking system</strong>
<div class="rl-icon-box">&#9878;</div> with <strong style="color:#a855f7"> time-delayed vote decay</strong>
<h3>Quadratic Voting</h3> for proposal prioritization.
<p>Each additional vote costs quadratically more credits. Balances intensity of preference with breadth of support.</p> </p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128336;</div>
<h3>Proposal Lifecycle</h3>
<p>From ranking through promotion to final pass/fail vote. Proposals advance automatically when thresholds are met.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#127963;</div>
<h3>Democratic Governance</h3>
<p>Daily credit allowances, vote decay, and sybil resistance. One person, one identity, one voice.</p>
</div>
</div> </div>
</div>
</section>
<!-- How It Works -->
<section class="rl-section rl-section--alt">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">How It Works</h2>
<div class="rl-grid-3"> <div class="rl-grid-3">
<div class="rl-step"> <!-- Quadratic -->
<span class="rl-step__num">1</span> <div class="rl-card" style="border:2px solid rgba(249,115,22,0.35);background:linear-gradient(to bottom right,rgba(249,115,22,0.08),rgba(249,115,22,0.03))">
<h3>Ranking (QPR)</h3> <div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.75rem">
<p>Community members spend credits to upvote proposals. Conviction score accumulates with quadratic cost.</p> <div style="width:2rem;height:2rem;border-radius:9999px;background:#f97316;display:flex;align-items:center;justify-content:center">
<span style="color:white;font-weight:700;font-size:0.8rem">x&sup2;</span>
</div>
<h3 style="color:#fb923c;font-size:1.05rem;margin-bottom:0">Quadratic</h3>
</div>
<p>
Voting more costs exponentially more credits. 1 vote = 1 credit, 2 votes = 4, 3 votes = 9.
<strong style="display:block;margin-top:0.5rem;color:#e2e8f0">No single voice can dominate.</strong>
</p>
</div> </div>
<div class="rl-step">
<span class="rl-step__num">2</span> <!-- Reddit-style -->
<h3>Score reaches +100</h3> <div class="rl-card" style="border:2px solid rgba(59,130,246,0.35);background:linear-gradient(to bottom right,rgba(59,130,246,0.08),rgba(59,130,246,0.03))">
<p>When a proposal crosses the promotion threshold (default 100), it automatically enters the final vote.</p> <div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.75rem">
<div style="width:2rem;height:2rem;border-radius:9999px;background:#3b82f6;display:flex;align-items:center;justify-content:center">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="18 15 12 9 6 15"/></svg>
</div>
<h3 style="color:#60a5fa;font-size:1.05rem;margin-bottom:0">Reddit-style</h3>
</div>
<p>
Upvote or downvote proposals. Scores aggregate from all community votes.
<strong style="display:block;margin-top:0.5rem;color:#e2e8f0">Best ideas rise to the top.</strong>
</p>
</div> </div>
<div class="rl-step">
<span class="rl-step__num">3</span> <!-- Vote Decay -->
<h3>Pass / Fail Vote</h3> <div class="rl-card" style="border:2px solid rgba(168,85,247,0.35);background:linear-gradient(to bottom right,rgba(168,85,247,0.08),rgba(168,85,247,0.03))">
<p>A time-limited binary vote (Yes / No / Abstain) decides the outcome. Simple majority wins.</p> <div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.75rem">
<div style="width:2rem;height:2rem;border-radius:9999px;background:#a855f7;display:flex;align-items:center;justify-content:center">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
</div>
<h3 style="color:#c084fc;font-size:1.05rem;margin-bottom:0">Vote Decay</h3>
</div>
<p>
Votes fade after 30&ndash;60 days. Old support expires, requiring renewed interest.
<strong style="display:block;margin-top:0.5rem;color:#e2e8f0">Rankings stay fresh and relevant.</strong>
</p>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- What is QPR --> <!-- Live Demo (textual description, no interactive component) -->
<section class="rl-section rl-section--alt">
<div class="rl-container" style="text-align:center">
<span class="rl-badge" style="background:#1e293b;color:#94a3b8;font-size:0.7rem;padding:0.25rem 0.75rem">Live Demo</span>
<h2 class="rl-heading" style="margin-top:0.75rem;background:linear-gradient(135deg,#e2e8f0,#cbd5e1);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">
Try It Yourself
</h2>
<p style="color:#94a3b8;max-width:640px;margin:0 auto 2rem">
Vote on live polls synced across the r* ecosystem. Changes appear in real-time for everyone.
</p>
<a href="https://demo.rspace.online/rvote" class="rl-cta-primary"
style="background:linear-gradient(to right,#818cf8,#6366f1);color:white">
Open Interactive Demo
</a>
</div>
</section>
<!-- What is Quadratic Proposal Ranking -->
<section class="rl-section"> <section class="rl-section">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">What is Quadratic Priority Ranking?</h2> <div style="text-align:center;margin-bottom:2.5rem">
<div class="rl-grid-2" style="margin-top:2rem"> <span class="rl-tagline" style="color:#818cf8;background:rgba(129,140,248,0.1);border-color:rgba(129,140,248,0.2)">
<div class="rl-card"> The Core Concept
<h3 style="color:#f87171">The Problem</h3> </span>
<p>Traditional voting (1 person = 1 vote) lets small, passionate groups dominate. <h2 class="rl-heading" style="background:linear-gradient(135deg,#e2e8f0,#cbd5e1);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">
Token-weighted voting lets whales decide everything. Neither reflects genuine community preference.</p> What is Quadratic Proposal Ranking?
</h2>
<p style="font-size:1.05rem;color:#94a3b8;max-width:640px;margin:0 auto">
A system where expressing <em>strong</em> preference costs progressively more,
creating a fair and balanced priority list that reflects true community consensus.
</p>
</div>
<div class="rl-grid-2" style="max-width:900px;margin:0 auto">
<!-- The Problem -->
<div class="rl-card" style="border:2px solid rgba(239,68,68,0.2);background:rgba(239,68,68,0.04)">
<div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:1rem">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#ef4444" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3l2 7h7l-5.5 4 2 7L12 17l-5.5 4 2-7L3 10h7z"/></svg>
<h3 style="color:#f87171;margin-bottom:0;font-size:1.05rem">The Problem</h3>
</div>
<p style="margin-bottom:0.75rem">
Traditional priority systems let those with more time, resources, or influence dominate what gets attention.
</p>
<ul style="list-style:disc;padding-left:1.25rem;margin:0">
<li style="font-size:0.85rem;color:#94a3b8;line-height:1.6">Loudest voices set the agenda</li>
<li style="font-size:0.85rem;color:#94a3b8;line-height:1.6">Important but less flashy ideas get buried</li>
<li style="font-size:0.85rem;color:#94a3b8;line-height:1.6">No way to express intensity of preference</li>
<li style="font-size:0.85rem;color:#94a3b8;line-height:1.6">Backlogs become political battlegrounds</li>
</ul>
</div> </div>
<div class="rl-card">
<h3 style="color:#14b8a6">The Solution</h3> <!-- The Solution -->
<p>Quadratic voting makes strong preferences expensive. You <em>can</em> signal that you care a lot &mdash; <div class="rl-card" style="border:2px solid rgba(129,140,248,0.25);background:linear-gradient(to bottom right,rgba(129,140,248,0.05),rgba(192,132,252,0.05))">
but it costs quadratically more. This balances intensity of preference with breadth of support.</p> <div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:1rem">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#818cf8" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>
<h3 style="color:#a5b4fc;margin-bottom:0;font-size:1.05rem">The Solution: QPR</h3>
</div>
<p style="margin-bottom:0.75rem">
Quadratic Proposal Ranking balances participation and conviction by making additional votes progressively more expensive.
</p>
<ul style="list-style:disc;padding-left:1.25rem;margin:0">
<li style="font-size:0.85rem;color:#94a3b8;line-height:1.6">1 vote = 1 credit, 2 votes = 4, 3 = 9</li>
<li style="font-size:0.85rem;color:#94a3b8;line-height:1.6">Everyone can participate meaningfully</li>
<li style="font-size:0.85rem;color:#94a3b8;line-height:1.6">Express strong opinions, but at a cost</li>
<li style="font-size:0.85rem;color:#94a3b8;line-height:1.6">Naturally surfaces community consensus</li>
</ul>
</div> </div>
</div> </div>
<!-- Vote Cost Calculator -->
<div style="margin-top:2.5rem;max-width:540px;margin-left:auto;margin-right:auto">
<h3 style="text-align:center;font-size:1rem;font-weight:600;color:#e2e8f0;margin-bottom:1rem">
Vote Cost Calculator
</h3>
<div style="display:grid;grid-template-columns:repeat(5,1fr);gap:0.5rem;text-align:center">
<div class="rl-card" style="padding:0.75rem">
<div style="font-size:1.5rem;font-weight:700;color:#818cf8">1</div>
<div style="font-size:0.7rem;color:#64748b">vote</div>
<div style="font-size:1rem;font-family:monospace;margin-top:0.5rem;color:#c084fc">1</div>
<div style="font-size:0.65rem;color:#64748b">credit</div>
</div>
<div class="rl-card" style="padding:0.75rem">
<div style="font-size:1.5rem;font-weight:700;color:#818cf8">2</div>
<div style="font-size:0.7rem;color:#64748b">votes</div>
<div style="font-size:1rem;font-family:monospace;margin-top:0.5rem;color:#c084fc">4</div>
<div style="font-size:0.65rem;color:#64748b">credits</div>
</div>
<div class="rl-card" style="padding:0.75rem">
<div style="font-size:1.5rem;font-weight:700;color:#818cf8">3</div>
<div style="font-size:0.7rem;color:#64748b">votes</div>
<div style="font-size:1rem;font-family:monospace;margin-top:0.5rem;color:#c084fc">9</div>
<div style="font-size:0.65rem;color:#64748b">credits</div>
</div>
<div class="rl-card" style="padding:0.75rem">
<div style="font-size:1.5rem;font-weight:700;color:#818cf8">4</div>
<div style="font-size:0.7rem;color:#64748b">votes</div>
<div style="font-size:1rem;font-family:monospace;margin-top:0.5rem;color:#c084fc">16</div>
<div style="font-size:0.65rem;color:#64748b">credits</div>
</div>
<div class="rl-card" style="padding:0.75rem">
<div style="font-size:1.5rem;font-weight:700;color:#818cf8">5</div>
<div style="font-size:0.7rem;color:#64748b">votes</div>
<div style="font-size:1rem;font-family:monospace;margin-top:0.5rem;color:#c084fc">25</div>
<div style="font-size:0.65rem;color:#64748b">credits</div>
</div>
</div>
<p style="text-align:center;font-size:0.8rem;color:#64748b;margin-top:1rem">
Spreading votes across proposals you support is more efficient than concentrating on one.
</p>
</div>
</div> </div>
</section> </section>
<!-- Vote Cost Calculator --> <!-- From Chaos to Consensus (How It Works) -->
<section class="rl-section rl-section--alt"> <section class="rl-section rl-section--alt">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Vote cost calculator</h2> <div style="text-align:center;margin-bottom:2.5rem">
<p class="rl-subtext" style="text-align:center">The cost of conviction grows quadratically.</p> <span class="rl-tagline" style="color:#818cf8;background:rgba(129,140,248,0.1);border-color:rgba(129,140,248,0.2)">
<div class="rl-card" style="max-width:500px;margin:2rem auto 0"> How It Works
<div style="display:grid;grid-template-columns:repeat(5,1fr);gap:0.5rem;text-align:center"> </span>
<div> <h2 class="rl-heading" style="background:linear-gradient(135deg,#e2e8f0,#cbd5e1);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">
<div style="font-size:1.5rem;font-weight:700;color:#14b8a6">1</div> From Chaos to Consensus
<div style="font-size:0.7rem;color:#64748b">vote</div> </h2>
<div style="font-size:0.85rem;font-weight:600;color:#e2e8f0;margin-top:0.25rem">1 credit</div> <p style="font-size:1.05rem;color:#94a3b8;max-width:640px;margin:0 auto">
Transform your community&rsquo;s ideas into a democratically prioritized backlog
through two simple stages.
</p>
</div>
<div class="rl-grid-3">
<!-- Stage 1: QPR -->
<div class="rl-card" style="border-color:rgba(129,140,248,0.2)">
<div style="display:flex;align-items:center;gap:0.75rem;margin-bottom:1rem">
<div style="width:2.5rem;height:2.5rem;border-radius:9999px;background:linear-gradient(to bottom right,#818cf8,rgba(129,140,248,0.6));display:flex;align-items:center;justify-content:center">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="10" y1="6" x2="21" y2="6"/><line x1="10" y1="12" x2="21" y2="12"/><line x1="10" y1="18" x2="21" y2="18"/><path d="M4 6h1v4"/><path d="M4 10h2"/><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"/></svg>
</div>
<div>
<span class="rl-badge" style="background:rgba(129,140,248,0.1);color:#818cf8;margin-bottom:0.25rem">Stage 1</span>
<h3 style="margin-bottom:0;font-size:1rem">Quadratic Proposal Ranking</h3>
</div>
</div> </div>
<div> <ul style="list-style:none;padding:0;margin:0">
<div style="font-size:1.5rem;font-weight:700;color:#14b8a6">2</div> <li style="display:flex;align-items:flex-start;gap:0.5rem;font-size:0.85rem;color:#94a3b8;line-height:1.6;padding:0.2rem 0">
<div style="font-size:0.7rem;color:#64748b">votes</div> <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#818cf8" stroke-width="2" style="flex-shrink:0;margin-top:3px"><polyline points="23 6 13.5 15.5 8.5 10.5"/><polyline points="17 6 7.5 15.5 2.5 10.5"/></svg>
<div style="font-size:0.85rem;font-weight:600;color:#e2e8f0;margin-top:0.25rem">4 credits</div> <span>All proposals enter the ranking pool</span>
</li>
<li style="display:flex;align-items:flex-start;gap:0.5rem;font-size:0.85rem;color:#94a3b8;line-height:1.6;padding:0.2rem 0">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#818cf8" stroke-width="2" style="flex-shrink:0;margin-top:3px"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
<span>Upvote/downvote with quadratic cost</span>
</li>
<li style="display:flex;align-items:flex-start;gap:0.5rem;font-size:0.85rem;color:#94a3b8;line-height:1.6;padding:0.2rem 0">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#818cf8" stroke-width="2" style="flex-shrink:0;margin-top:3px"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg>
<span>Votes decay over 30&ndash;60 days</span>
</li>
<li style="display:flex;align-items:flex-start;gap:0.5rem;font-size:0.85rem;color:#94a3b8;line-height:1.6;padding:0.2rem 0">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#818cf8" stroke-width="2" style="flex-shrink:0;margin-top:3px"><circle cx="12" cy="12" r="3"/><circle cx="12" cy="12" r="10"/></svg>
<span>Creates a living priority queue</span>
</li>
</ul>
</div>
<!-- Threshold -->
<div class="rl-card" style="border-color:rgba(192,132,252,0.25);background:linear-gradient(to bottom right,rgba(192,132,252,0.08),rgba(129,140,248,0.06))">
<div style="display:flex;align-items:center;gap:0.75rem;margin-bottom:1rem">
<div style="width:2.5rem;height:2.5rem;border-radius:9999px;background:linear-gradient(to bottom right,#c084fc,#818cf8);display:flex;align-items:center;justify-content:center">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>
</div>
<div>
<span class="rl-badge" style="background:rgba(192,132,252,0.15);color:#c084fc;margin-bottom:0.25rem">Threshold</span>
<h3 style="margin-bottom:0;font-size:1rem">Score +100</h3>
</div>
</div> </div>
<div> <p>
<div style="font-size:1.5rem;font-weight:700;color:#14b8a6">3</div> When a proposal reaches a score of <strong style="color:#e2e8f0">+100</strong>, it
<div style="font-size:0.7rem;color:#64748b">votes</div> automatically advances to the final voting stage.
<div style="font-size:0.85rem;font-weight:600;color:#e2e8f0;margin-top:0.25rem">9 credits</div> </p>
</div> <p style="margin-top:0.5rem;font-size:0.8rem">
<div> This ensures only proposals with genuine community support move
<div style="font-size:1.5rem;font-weight:700;color:#14b8a6">4</div> forward for implementation decisions.
<div style="font-size:0.7rem;color:#64748b">votes</div> </p>
<div style="font-size:0.85rem;font-weight:600;color:#e2e8f0;margin-top:0.25rem">16 credits</div> </div>
</div>
<div> <!-- Stage 2: Pass/Fail -->
<div style="font-size:1.5rem;font-weight:700;color:#14b8a6">5</div> <div class="rl-card" style="border-color:rgba(148,163,184,0.2)">
<div style="font-size:0.7rem;color:#64748b">votes</div> <div style="display:flex;align-items:center;gap:0.75rem;margin-bottom:1rem">
<div style="font-size:0.85rem;font-weight:600;color:#e2e8f0;margin-top:0.25rem">25 credits</div> <div style="width:2.5rem;height:2.5rem;border-radius:9999px;background:linear-gradient(to bottom right,#94a3b8,rgba(148,163,184,0.6));display:flex;align-items:center;justify-content:center">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>
</div>
<div>
<span class="rl-badge" style="background:rgba(148,163,184,0.1);color:#94a3b8;margin-bottom:0.25rem">Stage 2</span>
<h3 style="margin-bottom:0;font-size:1rem">Pass/Fail Vote</h3>
</div>
</div> </div>
<ul style="list-style:none;padding:0;margin:0">
<li style="display:flex;align-items:flex-start;gap:0.5rem;font-size:0.85rem;color:#94a3b8;line-height:1.6;padding:0.2rem 0">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#94a3b8" stroke-width="2" style="flex-shrink:0;margin-top:3px"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>
<span>Yes / No / Abstain voting</span>
</li>
<li style="display:flex;align-items:flex-start;gap:0.5rem;font-size:0.85rem;color:#94a3b8;line-height:1.6;padding:0.2rem 0">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#94a3b8" stroke-width="2" style="flex-shrink:0;margin-top:3px"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
<span>One member = one vote</span>
</li>
<li style="display:flex;align-items:flex-start;gap:0.5rem;font-size:0.85rem;color:#94a3b8;line-height:1.6;padding:0.2rem 0">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#94a3b8" stroke-width="2" style="flex-shrink:0;margin-top:3px"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
<span>7-day voting period</span>
</li>
<li style="display:flex;align-items:flex-start;gap:0.5rem;font-size:0.85rem;color:#94a3b8;line-height:1.6;padding:0.2rem 0">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#94a3b8" stroke-width="2" style="flex-shrink:0;margin-top:3px"><polyline points="20 6 9 17 4 12"/></svg>
<span>Majority decides implementation</span>
</li>
</ul>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- Built for real governance --> <!-- Features: Built for Fair Prioritization -->
<section class="rl-section"> <section class="rl-section">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Built for real governance</h2> <div style="text-align:center;margin-bottom:2.5rem">
<div class="rl-grid-4" style="margin-top:2rem"> <h2 class="rl-heading" style="background:linear-gradient(135deg,#e2e8f0,#cbd5e1);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">
<div class="rl-card rl-card--center"> Built for Fair Prioritization
<div class="rl-icon-box"> </h2>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg> <p style="color:#94a3b8">Everything you need for democratic backlog management</p>
</div>
<div class="rl-grid-4">
<div class="rl-card rl-card--center" style="border-color:rgba(129,140,248,0.15)">
<div style="width:3rem;height:3rem;border-radius:9999px;background:linear-gradient(to bottom right,#22c55e,#059669);display:flex;align-items:center;justify-content:center;margin:0 auto 0.75rem">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
</div> </div>
<h3>Earn Credits Daily</h3> <h3>Earn Credits Daily</h3>
<p>Every verified member receives a daily credit allowance. No pay-to-play.</p> <p>Get 10 credits every day. Start with 50. Max 500.</p>
</div> </div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box"> <div class="rl-card rl-card--center" style="border-color:rgba(129,140,248,0.15)">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg> <div style="width:3rem;height:3rem;border-radius:9999px;background:linear-gradient(to bottom right,#3b82f6,#0891b2);display:flex;align-items:center;justify-content:center;margin:0 auto 0.75rem">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg>
</div> </div>
<h3>Vote Decay</h3> <h3>Vote Decay</h3>
<p>Votes decay linearly from day 30 to day 60. Stale support fades, keeping rankings fresh.</p> <p>Old votes fade away, keeping rankings fresh and dynamic.</p>
</div> </div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box"> <div class="rl-card rl-card--center" style="border-color:rgba(129,140,248,0.15)">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg> <div style="width:3rem;height:3rem;border-radius:9999px;background:linear-gradient(to bottom right,#a855f7,#7c3aed);display:flex;align-items:center;justify-content:center;margin:0 auto 0.75rem">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
</div> </div>
<h3>Sybil Resistant</h3> <h3>Sybil Resistant</h3>
<p>Passkey authentication via EncryptID. One person, one identity, one credit stream.</p> <p>Quadratic costs make fake account attacks expensive.</p>
</div> </div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box"> <div class="rl-card rl-card--center" style="border-color:rgba(129,140,248,0.15)">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 014-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 01-4 4H3"/></svg> <div style="width:3rem;height:3rem;border-radius:9999px;background:linear-gradient(to bottom right,#f97316,#d97706);display:flex;align-items:center;justify-content:center;margin:0 auto 0.75rem">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>
</div> </div>
<h3>Auto Promotion</h3> <h3>Auto Promotion</h3>
<p>Proposals that hit the threshold automatically move to a final pass/fail vote. No admin bottleneck.</p> <p>Top proposals automatically advance to voting.</p>
</div>
</div>
</div>
</section>
<!-- Built on Open Source -->
<section class="rl-section rl-section--alt">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Built on Open Source</h2>
<p class="rl-subtext" style="text-align:center">The libraries and tools that power rVote.</p>
<div class="rl-grid-3">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128451;</div>
<h3>PostgreSQL</h3>
<p>Rock-solid relational database for proposals, votes, credit balances, and governance history.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box"><span style="font-size:1.25rem;font-weight:700">x&#178;</span></div>
<h3>Conviction Voting Algorithm</h3>
<p>Continuous preference signaling with quadratic cost and time-decay. Open-source governance math.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128293;</div>
<h3>Hono</h3>
<p>Ultrafast web framework for the API layer. Lightweight, edge-ready, and built for speed.</p>
</div>
</div>
</div>
</section>
<!-- Your Data, Protected -->
<section class="rl-section">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">Your Data, Protected</h2>
<p class="rl-subtext">How rVote keeps your information safe.</p>
<div class="rl-grid-3">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128274;</div>
<h3>End-to-End Encryption</h3>
<span class="rl-badge">Coming Soon</span>
<p>All content encrypted before it leaves your device. Not even the server can read it.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128373;</div>
<h3>Zero-Knowledge Architecture</h3>
<span class="rl-badge">Coming Soon</span>
<p>The server processes your requests without ever seeing your data in the clear.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#127968;</div>
<h3>Self-Hosted</h3>
<p>Run on your own infrastructure. Your server, your rules, your data.</p>
</div> </div>
</div> </div>
</div> </div>
@ -218,12 +355,33 @@ export function renderLanding(): string {
<!-- CTA --> <!-- CTA -->
<section class="rl-section rl-section--alt"> <section class="rl-section rl-section--alt">
<div class="rl-container" style="text-align:center"> <div class="rl-container">
<h2 class="rl-heading">(You)rVote, your voice.</h2> <div class="rl-card" style="border:2px solid rgba(129,140,248,0.25);background:linear-gradient(to bottom right,rgba(129,140,248,0.08),rgba(192,132,252,0.04),rgba(148,163,184,0.06));text-align:center;padding:3rem 2rem;position:relative;overflow:hidden">
<p class="rl-subtext">Try the demo or create a space to get started.</p> <span class="rl-badge" style="background:rgba(129,140,248,0.1);color:#818cf8;font-size:0.7rem;padding:0.25rem 0.75rem">
<div class="rl-cta-row"> Join the rSpace Ecosystem
<a href="https://demo.rspace.online/rvote" class="rl-cta-primary">Start Voting</a> </span>
<a href="/create-space" class="rl-cta-secondary">Create a Space</a> <h2 style="font-size:1.75rem;font-weight:700;color:#e2e8f0;margin:1rem 0">
Ready to prioritize democratically?
</h2>
<p style="font-size:1.05rem;color:#94a3b8;max-width:560px;margin:0 auto 2rem;line-height:1.6">
Create a Space for your community and start using Quadratic Proposal Ranking.
Invite members, allot credits, and let the best ideas rise to the top.
</p>
<div class="rl-cta-row" style="margin-top:0">
<a href="/create-space" class="rl-cta-primary"
style="background:linear-gradient(to right,#818cf8,#c084fc);color:white">
<span style="display:inline-flex;align-items:center;gap:0.5rem">
Create a Space
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>
</span>
</a>
<a href="https://demo.rspace.online/rvote" class="rl-cta-secondary">
<span style="display:inline-flex;align-items:center;gap:0.5rem">
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" stroke="none"><polygon points="5,3 19,12 5,21"/></svg>
Interactive Demo
</span>
</a>
</div>
</div> </div>
</div> </div>
</section> </section>

View File

@ -1,136 +1,183 @@
/** /**
* rWork landing page collective task management. * rWork landing page collective task management.
* Ported from rwork-online Next.js page.tsx (shadcn/ui + Lucide).
*/ */
export function renderLanding(): string { export function renderLanding(): string {
return ` return `
<!-- Hero --> <!-- Hero -->
<div class="rl-hero"> <div class="rl-hero">
<span class="rl-tagline">rWork</span> <span class="rl-tagline">Part of the rSpace Ecosystem</span>
<h1 class="rl-heading">(You)rWork, your flow.</h1> <h1 class="rl-heading">Collective<br>
<p class="rl-subtitle">Get things done, together</p> <span style="background:linear-gradient(135deg,#3b82f6,#14b8a6);-webkit-background-clip:text;background-clip:text;color:transparent">Task Management</span>
</h1>
<p class="rl-subtext"> <p class="rl-subtext">
Kanban boards, team spaces, and real-time collaboration &mdash; built for groups Create <strong style="color:#e2e8f0">Spaces</strong> for your community to collaborate on shared projects.
that share work, not just assign it. Track tasks through pipelines with <strong style="color:#e2e8f0">real-time kanban boards</strong> powered
by markdown-native task management.
</p> </p>
<div class="rl-cta-row"> <div class="rl-cta-row">
<a href="https://demo.rspace.online/rwork" class="rl-cta-primary" id="ml-primary">Start Working</a> <a href="https://demo.rspace.online/rwork" class="rl-cta-primary" id="ml-primary">
<a href="/create-space" class="rl-cta-secondary">Create a Space</a> Get Started &rarr;
</a>
<a href="https://demo.rspace.online/rwork" class="rl-cta-secondary">View Dashboard</a>
</div> </div>
</div> </div>
<!-- Features -->
<section class="rl-section">
<div class="rl-container">
<h2 class="rl-heading" style="text-align:center">What rWork Handles</h2>
<div class="rl-grid-4">
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128203;</div>
<h3>Kanban Boards</h3>
<p>Drag-and-drop columns with customizable statuses. See everything at a glance.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#9745;</div>
<h3>Task Management</h3>
<p>Create tasks with titles, descriptions, labels, and priorities. Track progress across your team.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128200;</div>
<h3>Activity Logging</h3>
<p>Every change is tracked. See who moved what, when, and why &mdash; full audit trail.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128101;</div>
<h3>Workspace Collaboration</h3>
<p>Each workspace is scoped to a space. Members share boards, tasks, and activity in real time.</p>
</div>
</div>
</div>
</section>
<!-- How It Works --> <!-- How It Works -->
<section class="rl-section rl-section--alt"> <section class="rl-section rl-section--alt">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">How It Works</h2> <div style="text-align:center;margin-bottom:1.5rem">
<span class="rl-badge">How It Works</span>
<h2 class="rl-heading" style="margin-top:0.75rem">rWork in 30 Seconds</h2>
<p class="rl-subtext">
<strong style="color:#3b82f6">Create a Space</strong> for your community,
<strong style="color:#14b8a6">add tasks</strong> to your pipeline, and
<strong style="color:#e2e8f0">track progress</strong> together in real-time.
</p>
</div>
<div class="rl-grid-3"> <div class="rl-grid-3">
<div class="rl-step"> <div class="rl-card" style="border:2px solid rgba(59,130,246,0.4);background:linear-gradient(135deg,rgba(59,130,246,0.1),rgba(59,130,246,0.05))">
<span class="rl-step__num">1</span> <div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.75rem">
<h3>Create a workspace</h3> <div style="height:2rem;width:2rem;border-radius:50%;background:#3b82f6;display:flex;align-items:center;justify-content:center">
<p>Every workspace lives inside an rSpace &mdash; shared by default with your team.</p> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 20a2 2 0 002-2V8a2 2 0 00-2-2h-7.9a2 2 0 01-1.69-.9L9.6 3.9A2 2 0 007.93 3H4a2 2 0 00-2 2v13a2 2 0 002 2h16z"/><rect x="8" y="10" width="8" height="6" rx="1"/></svg>
</div>
<h3 style="font-weight:700;font-size:1.125rem;color:#e2e8f0">1. Create a Space</h3>
</div>
<p style="font-size:0.875rem;color:#94a3b8;line-height:1.6">
Set up a workspace for your project or community. Configure your pipeline
statuses and invite members.
<strong style="color:#e2e8f0;display:block;margin-top:0.5rem">Each Space gets its own kanban board.</strong>
</p>
</div> </div>
<div class="rl-step">
<span class="rl-step__num">2</span> <div class="rl-card" style="border:2px solid rgba(20,184,166,0.4);background:linear-gradient(135deg,rgba(20,184,166,0.1),rgba(20,184,166,0.05))">
<h3>Add tasks and boards</h3> <div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.75rem">
<p>Create tasks with titles, descriptions, labels, and priorities. Drag them across columns.</p> <div style="height:2rem;width:2rem;border-radius:50%;background:#14b8a6;display:flex;align-items:center;justify-content:center">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/></svg>
</div>
<h3 style="font-weight:700;font-size:1.125rem;color:#e2e8f0">2. Add Tasks</h3>
</div>
<p style="font-size:0.875rem;color:#94a3b8;line-height:1.6">
Create tasks with descriptions, priorities, labels, and acceptance criteria.
Assign them to team members.
<strong style="color:#e2e8f0;display:block;margin-top:0.5rem">Tasks are stored as plain markdown files.</strong>
</p>
</div> </div>
<div class="rl-step">
<span class="rl-step__num">3</span> <div class="rl-card" style="border:2px solid rgba(100,116,139,0.4);background:linear-gradient(135deg,rgba(100,116,139,0.1),rgba(100,116,139,0.05))">
<h3>Track progress together</h3> <div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.75rem">
<p>Assign, comment, and track progress in real time. Everyone sees the same board.</p> <div style="height:2rem;width:2rem;border-radius:50%;background:#64748b;display:flex;align-items:center;justify-content:center">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>
</div>
<h3 style="font-weight:700;font-size:1.125rem;color:#e2e8f0">3. Collaborate</h3>
</div>
<p style="font-size:0.875rem;color:#94a3b8;line-height:1.6">
Drag tasks through your pipeline in real-time. Everyone sees updates instantly
via WebSocket sync.
<strong style="color:#e2e8f0;display:block;margin-top:0.5rem">Work together, stay in sync.</strong>
</p>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- Built on Open Source --> <!-- Features Row 1 -->
<section class="rl-section"> <section class="rl-section">
<div class="rl-container"> <div class="rl-container">
<h2 class="rl-heading" style="text-align:center">Built on Open Source</h2> <h2 class="rl-heading" style="text-align:center">Built for Community Collaboration</h2>
<p class="rl-subtext" style="text-align:center">The libraries and tools that power rWork.</p> <p class="rl-subtext" style="text-align:center">Everything you need to coordinate shared work</p>
<div class="rl-grid-3">
<div class="rl-grid-4">
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128293;</div> <div class="rl-icon-box" style="background:linear-gradient(135deg,#3b82f6,rgba(59,130,246,0.6))">
<h3>Hono</h3> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/></svg>
<p>Ultrafast web framework for the API layer. Lightweight, edge-ready, and built for speed.</p> </div>
<h3>Kanban Boards</h3>
<p>Drag-and-drop tasks through customizable pipeline stages.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128451;</div> <div class="rl-icon-box" style="background:linear-gradient(135deg,#14b8a6,rgba(20,184,166,0.6))">
<h3>PostgreSQL</h3> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 21v-2a4 4 0 00-4-4H6a4 4 0 00-4-4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 00-3-3.87"/><path d="M16 3.13a4 4 0 010 7.75"/></svg>
<p>Rock-solid relational database for task storage, workspaces, boards, and activity logs.</p> </div>
<h3>Team Spaces</h3>
<p>Create isolated workspaces with role-based access control.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center">
<div class="rl-icon-box">&#9889;</div> <div class="rl-icon-box" style="background:linear-gradient(135deg,#22c55e,#059669)">
<h3>Bun</h3> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>
<p>All-in-one JavaScript runtime. Fast startup, native TypeScript, and built-in bundling.</p> </div>
<h3>Real-time Sync</h3>
<p>Changes appear instantly for all members via WebSocket.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:linear-gradient(135deg,#f97316,#d97706)">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="6" y1="3" x2="6" y2="15"/><circle cx="18" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M18 9a9 9 0 01-9 9"/></svg>
</div>
<h3>Markdown Native</h3>
<p>Tasks stored as plain .md files. Version-controllable, AI-friendly.</p>
</div> </div>
</div> </div>
</div>
</section>
<!-- Your Data, Protected --> <!-- Features Row 2 -->
<section class="rl-section rl-section--alt"> <div class="rl-grid-4" style="margin-top:1rem">
<div class="rl-container" style="text-align:center">
<h2 class="rl-heading">Your Data, Protected</h2>
<p class="rl-subtext">How rWork keeps your information safe.</p>
<div class="rl-grid-3">
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128274;</div> <div class="rl-icon-box" style="background:linear-gradient(135deg,#a855f7,#7c3aed)">
<h3>End-to-End Encryption</h3> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="7" width="20" height="14" rx="2" ry="2"/><path d="M16 21V5a2 2 0 00-2-2h-4a2 2 0 00-2 2v16"/></svg>
<span class="rl-badge">Coming Soon</span> </div>
<p>All content encrypted before it leaves your device. Not even the server can read it.</p> <h3>Custom Pipelines</h3>
<p>Define your own workflow stages beyond To Do / In Progress / Done.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center">
<div class="rl-icon-box">&#128373;</div> <div class="rl-icon-box" style="background:linear-gradient(135deg,#3b82f6,#0891b2)">
<h3>Zero-Knowledge Architecture</h3> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 8A6 6 0 006 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 01-3.46 0"/></svg>
<span class="rl-badge">Coming Soon</span> </div>
<p>The server processes your requests without ever seeing your data in the clear.</p> <h3>Notifications</h3>
<p>Stay informed when tasks are assigned, updated, or completed.</p>
</div> </div>
<div class="rl-card rl-card--center"> <div class="rl-card rl-card--center">
<div class="rl-icon-box">&#127968;</div> <div class="rl-icon-box" style="background:linear-gradient(135deg,#f43f5e,#ec4899)">
<h3>Self-Hosted</h3> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 11-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>
<p>Run on your own infrastructure. Your server, your rules, your data.</p> </div>
<h3>Acceptance Criteria</h3>
<p>Define checklists for what &ldquo;done&rdquo; means on each task.</p>
</div>
<div class="rl-card rl-card--center">
<div class="rl-icon-box" style="background:linear-gradient(135deg,#14b8a6,#0891b2)">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 014 10 15.3 15.3 0 01-4 10 15.3 15.3 0 01-4-10 15.3 15.3 0 014-10z"/></svg>
</div>
<h3>rSpace Ecosystem</h3>
<p>Integrates with rVote, rMaps, rNotes, and the full r* suite.</p>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- CTA --> <!-- CTA -->
<section class="rl-section"> <section class="rl-section rl-section--alt">
<div class="rl-container" style="text-align:center"> <div class="rl-container">
<h2 class="rl-heading">(You)rWork, your flow.</h2> <div class="rl-card" style="border:2px solid rgba(59,130,246,0.3);background:linear-gradient(135deg,rgba(59,130,246,0.1),rgba(20,184,166,0.05),rgba(100,116,139,0.1));text-align:center;padding:3rem 1.5rem;position:relative;overflow:hidden">
<p class="rl-subtext">Try the demo or create a space to get started.</p> <div style="position:absolute;top:0;right:0;width:16rem;height:16rem;background:rgba(59,130,246,0.1);border-radius:50%;filter:blur(48px)"></div>
<div class="rl-cta-row"> <div style="position:absolute;bottom:0;left:0;width:16rem;height:16rem;background:rgba(20,184,166,0.1);border-radius:50%;filter:blur(48px)"></div>
<a href="https://demo.rspace.online/rwork" class="rl-cta-primary">Start Working</a> <div style="position:relative">
<a href="/create-space" class="rl-cta-secondary">Create a Space</a> <span class="rl-badge">Join the rSpace Ecosystem</span>
<h2 class="rl-heading" style="margin-top:1rem">Ready to collaborate?</h2>
<p class="rl-subtext" style="max-width:36rem;margin:0.5rem auto 0">
Create a Space for your community and start tracking tasks together.
Invite members, configure your pipeline, and ship faster as a team.
</p>
<div class="rl-cta-row" style="margin-top:1.5rem">
<a href="https://demo.rspace.online/rwork" class="rl-cta-primary">
Create a Space &rarr;
</a>
</div>
</div>
</div> </div>
</div> </div>
</section> </section>