From fa80968b7f8bc6b5e1fa31be852e7832f7f832bb Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Wed, 18 Feb 2026 07:47:47 +0000 Subject: [PATCH] Replace EncryptID landing page with real auth UI Replace marketing-only landing page with a functional auth page that lets users register and sign in with passkeys. Shows profile view after login with DID, passkey list, session info, and recovery email setup. Still includes feature descriptions and r-suite app links. Co-Authored-By: Claude Opus 4.6 --- src/encryptid/server.ts | 465 ++++++++++++++++++++++++++++++---------- 1 file changed, 355 insertions(+), 110 deletions(-) diff --git a/src/encryptid/server.ts b/src/encryptid/server.ts index 2a96f39..4e91399 100644 --- a/src/encryptid/server.ts +++ b/src/encryptid/server.ts @@ -959,7 +959,7 @@ app.use('/dist/*', serveStatic({ root: './src/encryptid/' })); app.use('/demo/*', serveStatic({ root: './src/encryptid/' })); app.use('/static/*', serveStatic({ root: './public/' })); -// Serve index +// Serve index — landing page with real auth app.get('/', (c) => { return c.html(` @@ -974,149 +974,394 @@ app.get('/', (c) => { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); min-height: 100vh; - display: flex; - align-items: center; - justify-content: center; color: #fff; } - .container { - text-align: center; - padding: 2rem; - max-width: 600px; - } - .logo { - font-size: 4rem; - margin-bottom: 1rem; - } - h1 { + .page { max-width: 720px; margin: 0 auto; padding: 3rem 1.5rem; } + + /* Header */ + .header { text-align: center; margin-bottom: 2.5rem; } + .header h1 { font-size: 2.5rem; - margin-bottom: 0.5rem; background: linear-gradient(90deg, #00d4ff, #7c3aed); -webkit-background-clip: text; -webkit-text-fill-color: transparent; } - .tagline { - font-size: 1.25rem; - color: #94a3b8; - margin-bottom: 2rem; + .header .tagline { font-size: 1.1rem; color: #94a3b8; margin-top: 0.5rem; } + + /* Auth card */ + .auth-card { + background: rgba(255,255,255,0.06); + border: 1px solid rgba(255,255,255,0.12); + border-radius: 1rem; + padding: 2rem; + margin-bottom: 2.5rem; } - .features { - display: grid; - grid-template-columns: repeat(2, 1fr); - gap: 1rem; - margin-bottom: 2rem; + .auth-card h2 { font-size: 1.25rem; margin-bottom: 0.25rem; } + .auth-card .sub { color: #94a3b8; font-size: 0.875rem; margin-bottom: 1.5rem; } + + /* Tabs */ + .tabs { display: flex; border-radius: 0.5rem; overflow: hidden; border: 1px solid rgba(255,255,255,0.15); margin-bottom: 1.5rem; } + .tab { flex: 1; padding: 0.6rem; text-align: center; font-size: 0.875rem; font-weight: 600; cursor: pointer; transition: background 0.2s; background: transparent; color: #94a3b8; border: none; } + .tab.active { background: linear-gradient(90deg, #00d4ff, #7c3aed); color: #fff; } + + /* Form */ + .form-group { margin-bottom: 1rem; } + .form-group label { display: block; font-size: 0.8rem; color: #94a3b8; margin-bottom: 0.4rem; font-weight: 500; } + .form-group input { + width: 100%; padding: 0.7rem 1rem; border-radius: 0.5rem; border: 1px solid rgba(255,255,255,0.15); + background: rgba(255,255,255,0.05); color: #fff; font-size: 0.95rem; outline: none; transition: border 0.2s; } - .feature { - background: rgba(255,255,255,0.05); - padding: 1rem; - border-radius: 0.5rem; - border: 1px solid rgba(255,255,255,0.1); + .form-group input:focus { border-color: #7c3aed; } + .form-group input::placeholder { color: #475569; } + + .btn-primary { + width: 100%; padding: 0.75rem; border-radius: 0.5rem; border: none; + background: linear-gradient(90deg, #00d4ff, #7c3aed); color: #fff; + font-size: 1rem; font-weight: 600; cursor: pointer; transition: transform 0.15s, opacity 0.15s; } - .feature-icon { - font-size: 1.5rem; - margin-bottom: 0.5rem; + .btn-primary:hover { transform: translateY(-1px); } + .btn-primary:disabled { opacity: 0.5; cursor: not-allowed; transform: none; } + + .error { background: rgba(239,68,68,0.15); border: 1px solid rgba(239,68,68,0.3); border-radius: 0.5rem; padding: 0.6rem 1rem; font-size: 0.85rem; color: #fca5a5; margin-bottom: 1rem; display: none; } + .success { background: rgba(34,197,94,0.15); border: 1px solid rgba(34,197,94,0.3); border-radius: 0.5rem; padding: 0.6rem 1rem; font-size: 0.85rem; color: #86efac; margin-bottom: 1rem; display: none; } + + /* Profile (shown when logged in) */ + .profile { display: none; } + .profile-header { display: flex; align-items: center; gap: 1rem; margin-bottom: 1.5rem; } + .profile-avatar { width: 56px; height: 56px; border-radius: 50%; background: linear-gradient(135deg, #00d4ff, #7c3aed); display: flex; align-items: center; justify-content: center; font-size: 1.5rem; font-weight: 700; flex-shrink: 0; } + .profile-info h3 { font-size: 1.1rem; } + .profile-info .did { font-family: monospace; font-size: 0.75rem; color: #94a3b8; word-break: break-all; } + .profile-row { display: flex; justify-content: space-between; padding: 0.6rem 0; border-bottom: 1px solid rgba(255,255,255,0.08); font-size: 0.875rem; } + .profile-row .label { color: #94a3b8; } + .profile-actions { display: flex; gap: 0.75rem; margin-top: 1.5rem; flex-wrap: wrap; } + .btn-secondary { + padding: 0.6rem 1.25rem; border-radius: 0.5rem; border: 1px solid rgba(255,255,255,0.15); + background: transparent; color: #fff; font-size: 0.85rem; font-weight: 500; cursor: pointer; transition: background 0.2s; } - .feature-title { - font-weight: 600; - margin-bottom: 0.25rem; - } - .feature-desc { - font-size: 0.875rem; - color: #94a3b8; - } - .btn { - display: inline-block; - padding: 0.75rem 2rem; - background: linear-gradient(90deg, #00d4ff, #7c3aed); - color: #fff; - text-decoration: none; - border-radius: 0.5rem; - font-weight: 600; - margin: 0.5rem; - transition: transform 0.2s; - } - .btn:hover { - transform: translateY(-2px); - } - .btn-outline { - background: transparent; - border: 2px solid #7c3aed; - } - .apps { - margin-top: 2rem; - padding-top: 2rem; - border-top: 1px solid rgba(255,255,255,0.1); - } - .apps-title { - font-size: 0.875rem; - color: #64748b; - margin-bottom: 1rem; - } - .app-icons { - display: flex; - justify-content: center; - gap: 1.5rem; - } - .app-icon { - color: #64748b; - text-decoration: none; - transition: color 0.2s; - } - .app-icon:hover { - color: #00d4ff; + .btn-secondary:hover { background: rgba(255,255,255,0.08); } + .btn-danger { border-color: rgba(239,68,68,0.4); color: #fca5a5; } + .btn-danger:hover { background: rgba(239,68,68,0.15); } + + /* Passkeys list */ + .passkeys { margin-top: 1.5rem; } + .passkeys h4 { font-size: 0.9rem; margin-bottom: 0.75rem; color: #94a3b8; } + .passkey-item { display: flex; justify-content: space-between; align-items: center; padding: 0.6rem 0.75rem; background: rgba(255,255,255,0.04); border-radius: 0.5rem; margin-bottom: 0.5rem; font-size: 0.8rem; } + .passkey-id { font-family: monospace; color: #94a3b8; } + .passkey-date { color: #64748b; } + + /* Recovery email */ + .recovery-section { margin-top: 1.5rem; padding-top: 1.5rem; border-top: 1px solid rgba(255,255,255,0.08); } + .recovery-section h4 { font-size: 0.9rem; margin-bottom: 0.75rem; color: #94a3b8; } + .recovery-row { display: flex; gap: 0.5rem; } + .recovery-row input { flex: 1; } + .recovery-row button { white-space: nowrap; } + + /* Features */ + .features { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1rem; margin-bottom: 2rem; } + .feature { background: rgba(255,255,255,0.04); padding: 1rem; border-radius: 0.5rem; border: 1px solid rgba(255,255,255,0.08); text-align: center; } + .feature-title { font-weight: 600; font-size: 0.9rem; margin-bottom: 0.25rem; } + .feature-desc { font-size: 0.8rem; color: #94a3b8; } + + /* Apps bar */ + .apps { text-align: center; padding-top: 2rem; border-top: 1px solid rgba(255,255,255,0.08); } + .apps-title { font-size: 0.8rem; color: #64748b; margin-bottom: 0.75rem; } + .app-links { display: flex; flex-wrap: wrap; justify-content: center; gap: 1rem; } + .app-links a { color: #64748b; text-decoration: none; font-size: 0.85rem; transition: color 0.2s; } + .app-links a:hover { color: #00d4ff; } + + .link-row { text-align: center; margin-top: 1rem; font-size: 0.8rem; } + .link-row a { color: #7c3aed; text-decoration: none; } + .link-row a:hover { text-decoration: underline; } + + @media (max-width: 480px) { + .features { grid-template-columns: 1fr; } + .header h1 { font-size: 2rem; } } -
- -

EncryptID

-

Unified Identity for the r-Ecosystem

+
+
+

EncryptID

+

Unified Identity for the r-Ecosystem

+
+ + +
+ +
+

Get started

+

Sign in with your passkey or create a new account. No passwords, no tracking.

+ +
+ + +
+ +
+
+ + + + + +
+ + +
+
+
?
+
+

Loading...

+
+
+
+ +
SessionActive
+
Token expires--
+ +
+

Your Passkeys

+
Loading...
+
+ +
+

Recovery Email

+

Set an email to recover your account if you lose your passkey.

+
+ + +
+ +
+ +
+ SDK Demo + +
+
+
-
🔑
Passkey Auth
-
Hardware-backed, phishing-resistant
+
Hardware-backed, phishing-resistant login. No passwords ever.
-
🛡️
Social Recovery
-
No seed phrases needed
+
Recover your account via email. No seed phrases needed.
-
🔐
E2E Encryption
-
Keys never leave your device
+
Derive keys from your passkey. Keys never leave your device.
-
💰
-
Web3 Ready
-
Account abstraction wallets
+
Cross-App Identity
+
One passkey works across every app in the r-suite.
- Try Demo - GitHub -
-
Works with the r-Ecosystem
-
- rSpace - rWallet - rVote - rMaps - rFiles - rNotes - rTrips - rFunds - rNetwork - rCart - rTube - rStack +
One identity across the r-Ecosystem
+
+ + `);