feat: initial rStack.online landing page
Static site listing all r-Stack ecosystem apps with EncryptID identity section. Dockerized with nginx + Traefik labels. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
commit
4c4dce784b
|
|
@ -0,0 +1,4 @@
|
|||
FROM nginx:alpine
|
||||
COPY index.html /usr/share/nginx/html/index.html
|
||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||
EXPOSE 80
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
services:
|
||||
rstack:
|
||||
build: .
|
||||
restart: unless-stopped
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.rstack.rule=Host(`rstack.online`) || Host(`www.rstack.online`)"
|
||||
- "traefik.http.services.rstack.loadbalancer.server.port=80"
|
||||
networks:
|
||||
- traefik-public
|
||||
|
||||
networks:
|
||||
traefik-public:
|
||||
external: true
|
||||
|
|
@ -0,0 +1,442 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>📦</text></svg>">
|
||||
<title>rStack - Community-Owned Tools for Collaboration</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
|
||||
color: #e2e8f0;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* ── Hero ─────────────────────────────────────── */
|
||||
|
||||
.hero {
|
||||
text-align: center;
|
||||
padding: 6rem 1.5rem 4rem;
|
||||
max-width: 720px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
font-size: 3.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
background: linear-gradient(135deg, #14b8a6, #7c3aed, #f97316);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
.hero .tagline {
|
||||
font-size: 1.3rem;
|
||||
color: #94a3b8;
|
||||
margin-bottom: 1.5rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.hero .description {
|
||||
font-size: 1rem;
|
||||
color: #64748b;
|
||||
line-height: 1.7;
|
||||
max-width: 560px;
|
||||
margin: 0 auto 2.5rem;
|
||||
}
|
||||
|
||||
.hero .description .hl {
|
||||
color: #00d4ff;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* ── Pillars ──────────────────────────────────── */
|
||||
|
||||
.pillars {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 1rem;
|
||||
max-width: 720px;
|
||||
margin: 0 auto 4rem;
|
||||
padding: 0 1.5rem;
|
||||
}
|
||||
|
||||
.pillar {
|
||||
background: rgba(255,255,255,0.04);
|
||||
border: 1px solid rgba(255,255,255,0.08);
|
||||
border-radius: 12px;
|
||||
padding: 1.5rem 1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.pillar-icon { font-size: 1.75rem; margin-bottom: 0.5rem; }
|
||||
.pillar-title { font-weight: 600; font-size: 0.95rem; margin-bottom: 0.25rem; }
|
||||
.pillar-desc { font-size: 0.82rem; color: #64748b; line-height: 1.4; }
|
||||
|
||||
/* ── App Grid ─────────────────────────────────── */
|
||||
|
||||
.apps-section {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1.5rem 5rem;
|
||||
}
|
||||
|
||||
.apps-section h2 {
|
||||
text-align: center;
|
||||
font-size: 1.75rem;
|
||||
margin-bottom: 0.5rem;
|
||||
background: linear-gradient(90deg, #00d4ff, #7c3aed);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
.apps-section .section-desc {
|
||||
text-align: center;
|
||||
color: #64748b;
|
||||
font-size: 0.95rem;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
.app-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.app-card {
|
||||
background: rgba(255,255,255,0.04);
|
||||
border: 1px solid rgba(255,255,255,0.08);
|
||||
border-radius: 14px;
|
||||
padding: 1.5rem;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
transition: border-color 0.2s, transform 0.2s;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.app-card:hover {
|
||||
border-color: rgba(0, 212, 255, 0.35);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.app-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.app-emoji { font-size: 1.75rem; }
|
||||
|
||||
.app-name {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 700;
|
||||
color: #f1f5f9;
|
||||
}
|
||||
|
||||
.app-domain {
|
||||
font-size: 0.75rem;
|
||||
color: #475569;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.app-desc {
|
||||
font-size: 0.88rem;
|
||||
color: #94a3b8;
|
||||
line-height: 1.6;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.app-tag {
|
||||
display: inline-block;
|
||||
margin-top: 0.75rem;
|
||||
font-size: 0.72rem;
|
||||
color: #64748b;
|
||||
background: rgba(255,255,255,0.05);
|
||||
padding: 0.2rem 0.6rem;
|
||||
border-radius: 4px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
/* ── EncryptID Banner ─────────────────────────── */
|
||||
|
||||
.encryptid-banner {
|
||||
max-width: 720px;
|
||||
margin: 0 auto 5rem;
|
||||
padding: 0 1.5rem;
|
||||
}
|
||||
|
||||
.encryptid-card {
|
||||
background: linear-gradient(135deg, rgba(0,212,255,0.06), rgba(124,58,237,0.06));
|
||||
border: 1px solid rgba(124,58,237,0.25);
|
||||
border-radius: 16px;
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.encryptid-card h3 {
|
||||
font-size: 1.25rem;
|
||||
margin-bottom: 0.75rem;
|
||||
color: #c4b5fd;
|
||||
}
|
||||
|
||||
.encryptid-card p {
|
||||
color: #94a3b8;
|
||||
line-height: 1.7;
|
||||
font-size: 0.95rem;
|
||||
max-width: 520px;
|
||||
margin: 0 auto 1.25rem;
|
||||
}
|
||||
|
||||
.encryptid-card .hl {
|
||||
color: #00d4ff;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.encryptid-link {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.6rem 1.5rem;
|
||||
background: linear-gradient(90deg, rgba(0,212,255,0.15), rgba(124,58,237,0.15));
|
||||
border: 1px solid rgba(124,58,237,0.35);
|
||||
border-radius: 8px;
|
||||
color: #c4b5fd;
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
font-size: 0.9rem;
|
||||
transition: transform 0.2s, border-color 0.2s;
|
||||
}
|
||||
|
||||
.encryptid-link:hover {
|
||||
transform: translateY(-2px);
|
||||
border-color: rgba(124,58,237,0.6);
|
||||
}
|
||||
|
||||
/* ── Footer ───────────────────────────────────── */
|
||||
|
||||
footer {
|
||||
text-align: center;
|
||||
padding: 2rem 1.5rem 3rem;
|
||||
color: #475569;
|
||||
font-size: 0.82rem;
|
||||
border-top: 1px solid rgba(255,255,255,0.05);
|
||||
}
|
||||
|
||||
footer a {
|
||||
color: #64748b;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
footer a:hover { color: #94a3b8; }
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.hero h1 { font-size: 2.5rem; }
|
||||
.pillars { grid-template-columns: 1fr; }
|
||||
.app-grid { grid-template-columns: 1fr; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="hero">
|
||||
<h1>rStack</h1>
|
||||
<p class="tagline">Community-owned tools for collaboration, governance, and knowledge.</p>
|
||||
<p class="description">
|
||||
The <span class="hl">r-Stack</span> is a suite of interoperable, local-first applications
|
||||
unified by <span class="hl">EncryptID</span> — a single secure login that keeps your
|
||||
keys on your device. Every tool shares the same real-time sync layer, so your community's
|
||||
data flows freely between apps without import/export, APIs, or vendor lock-in.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="pillars">
|
||||
<div class="pillar">
|
||||
<div class="pillar-icon">🔐</div>
|
||||
<div class="pillar-title">One Identity</div>
|
||||
<div class="pillar-desc">EncryptID passkey login across every app. No passwords, no third-party auth.</div>
|
||||
</div>
|
||||
<div class="pillar">
|
||||
<div class="pillar-icon">🏠</div>
|
||||
<div class="pillar-title">Local-First</div>
|
||||
<div class="pillar-desc">Your keys and data live on your device. Sync peer-to-peer via CRDTs.</div>
|
||||
</div>
|
||||
<div class="pillar">
|
||||
<div class="pillar-icon">🔗</div>
|
||||
<div class="pillar-title">Interoperable</div>
|
||||
<div class="pillar-desc">Shared data layer means a vote in rVote can reference a budget in rFunds.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="apps-section">
|
||||
<h2>The Apps</h2>
|
||||
<p class="section-desc">Each tool is independent but stronger together. Log in once, use them all.</p>
|
||||
|
||||
<div class="app-grid">
|
||||
<a href="https://rspace.online" class="app-card">
|
||||
<div class="app-header">
|
||||
<span class="app-emoji">🌌</span>
|
||||
<div>
|
||||
<div class="app-name">rSpace</div>
|
||||
<div class="app-domain">rspace.online</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-desc">Collaborative spatial canvas. The integration hub where all r-Stack tools come together on a shared, infinite workspace.</div>
|
||||
<span class="app-tag">canvas & dashboard</span>
|
||||
</a>
|
||||
|
||||
<a href="https://rvote.online" class="app-card">
|
||||
<div class="app-header">
|
||||
<span class="app-emoji">🗳</span>
|
||||
<div>
|
||||
<div class="app-name">rVote</div>
|
||||
<div class="app-domain">rvote.online</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-desc">Community governance and decision-making. Create polls, weighted votes, and conviction-style proposals.</div>
|
||||
<span class="app-tag">governance</span>
|
||||
</a>
|
||||
|
||||
<a href="https://rwallet.online" class="app-card">
|
||||
<div class="app-header">
|
||||
<span class="app-emoji">💰</span>
|
||||
<div>
|
||||
<div class="app-name">rWallet</div>
|
||||
<div class="app-domain">rwallet.online</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-desc">Community treasury management. Track shared resources, contributions, and funding flows with Web3-ready smart wallets.</div>
|
||||
<span class="app-tag">treasury</span>
|
||||
</a>
|
||||
|
||||
<a href="https://rfunds.online" class="app-card">
|
||||
<div class="app-header">
|
||||
<span class="app-emoji">📊</span>
|
||||
<div>
|
||||
<div class="app-name">rFunds</div>
|
||||
<div class="app-domain">rfunds.online</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-desc">Budget tracking and expense management. Split costs, allocate funds, and maintain transparent community finances.</div>
|
||||
<span class="app-tag">budgets & expenses</span>
|
||||
</a>
|
||||
|
||||
<a href="https://rmaps.online" class="app-card">
|
||||
<div class="app-header">
|
||||
<span class="app-emoji">🗺</span>
|
||||
<div>
|
||||
<div class="app-name">rMaps</div>
|
||||
<div class="app-domain">rmaps.online</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-desc">Collaborative mapping and geospatial data. Pin locations, plan routes, and visualize your community across the world.</div>
|
||||
<span class="app-tag">mapping</span>
|
||||
</a>
|
||||
|
||||
<a href="https://rfiles.online" class="app-card">
|
||||
<div class="app-header">
|
||||
<span class="app-emoji">📁</span>
|
||||
<div>
|
||||
<div class="app-name">rFiles</div>
|
||||
<div class="app-domain">rfiles.online</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-desc">End-to-end encrypted file storage and sharing. Your community's documents, images, and media — owned by you.</div>
|
||||
<span class="app-tag">storage</span>
|
||||
</a>
|
||||
|
||||
<a href="https://rnotes.online" class="app-card">
|
||||
<div class="app-header">
|
||||
<span class="app-emoji">📝</span>
|
||||
<div>
|
||||
<div class="app-name">rNotes</div>
|
||||
<div class="app-domain">rnotes.online</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-desc">Collaborative note-taking and knowledge base. Real-time shared notebooks, checklists, and meeting notes.</div>
|
||||
<span class="app-tag">notes & docs</span>
|
||||
</a>
|
||||
|
||||
<a href="https://rtrips.online" class="app-card">
|
||||
<div class="app-header">
|
||||
<span class="app-emoji">✈</span>
|
||||
<div>
|
||||
<div class="app-name">rTrips</div>
|
||||
<div class="app-domain">rtrips.online</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-desc">Group trip planning. Itineraries, destinations, packing lists, and expenses — all linked across rMaps, rFunds, and rNotes.</div>
|
||||
<span class="app-tag">travel</span>
|
||||
</a>
|
||||
|
||||
<a href="https://rnetwork.online" class="app-card">
|
||||
<div class="app-header">
|
||||
<span class="app-emoji">🕸</span>
|
||||
<div>
|
||||
<div class="app-name">rNetwork</div>
|
||||
<div class="app-domain">rnetwork.online</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-desc">Community directory and relationship mapping. See who's connected, discover collaborators, and grow your network.</div>
|
||||
<span class="app-tag">people & connections</span>
|
||||
</a>
|
||||
|
||||
<a href="https://rcart.online" class="app-card">
|
||||
<div class="app-header">
|
||||
<span class="app-emoji">🛒</span>
|
||||
<div>
|
||||
<div class="app-name">rCart</div>
|
||||
<div class="app-domain">rcart.online</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-desc">Group purchasing and crowdfunding. Pool resources, compare options, and fund community projects together.</div>
|
||||
<span class="app-tag">commerce</span>
|
||||
</a>
|
||||
|
||||
<a href="https://rtube.online" class="app-card">
|
||||
<div class="app-header">
|
||||
<span class="app-emoji">🎬</span>
|
||||
<div>
|
||||
<div class="app-name">rTube</div>
|
||||
<div class="app-domain">rtube.online</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-desc">Community video sharing and streaming. Host, curate, and discuss video content without platform algorithms or ads.</div>
|
||||
<span class="app-tag">video</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="encryptid-banner">
|
||||
<div class="encryptid-card">
|
||||
<h3>Powered by EncryptID</h3>
|
||||
<p>
|
||||
Every r-Stack app authenticates through <span class="hl">EncryptID</span>, a
|
||||
self-sovereign identity system built on WebAuthn passkeys. One login, all apps.
|
||||
Your cryptographic keys are <span class="hl">derived locally</span> and never
|
||||
leave your device. If you lose access, <span class="hl">social recovery</span>
|
||||
with trusted guardians gets you back in — no seed phrases, no central authority.
|
||||
</p>
|
||||
<a href="https://encryptid.jeffemmett.com" class="encryptid-link">
|
||||
🔐 Learn more about EncryptID
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<p>rStack — community-owned, local-first, interoperable</p>
|
||||
<p style="margin-top: 0.5rem;">
|
||||
<a href="https://rspace.online">rSpace</a> ·
|
||||
<a href="https://encryptid.jeffemmett.com">EncryptID</a> ·
|
||||
<a href="https://github.com/jeffemmett">GitHub</a>
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
server {
|
||||
listen 80;
|
||||
server_name rstack.online www.rstack.online;
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# Cache static assets
|
||||
location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff2?)$ {
|
||||
expires 7d;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
|
||||
# Security headers
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
}
|
||||
Loading…
Reference in New Issue