From a6ae90fd629e74358d9846e8feb968ebfa522864 Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Tue, 24 Feb 2026 20:19:09 -0800 Subject: [PATCH] fix: dark background + emoji favicon for rStack design consistency Standardize to dark background (#0f172a / slate-900) and add emoji data URI favicon matching the rStack ecosystem. Co-Authored-By: Claude Opus 4.6 --- ...s-user-.r-.online-with-local-first-data.md | 74 +++++++++++++++++++ ...tcher-dropdown-across-all-r-App-headers.md | 64 ++++++++++++++++ src/app/globals.css | 4 +- src/app/layout.tsx | 3 + 4 files changed, 143 insertions(+), 2 deletions(-) create mode 100644 backlog/tasks/task-15 - EncryptID-personal-subdomains-user-.r-.online-with-local-first-data.md create mode 100644 backlog/tasks/task-16 - Add-rStack-AppSwitcher-dropdown-across-all-r-App-headers.md diff --git a/backlog/tasks/task-15 - EncryptID-personal-subdomains-user-.r-.online-with-local-first-data.md b/backlog/tasks/task-15 - EncryptID-personal-subdomains-user-.r-.online-with-local-first-data.md new file mode 100644 index 0000000..ebe9951 --- /dev/null +++ b/backlog/tasks/task-15 - EncryptID-personal-subdomains-user-.r-.online-with-local-first-data.md @@ -0,0 +1,74 @@ +--- +id: TASK-15 +title: 'EncryptID personal subdomains: .r*.online with local-first data' +status: In Progress +assignee: [] +created_date: '2026-02-25 03:01' +updated_date: '2026-02-25 03:54' +labels: + - architecture + - auth + - encryptid + - infrastructure + - cross-app +dependencies: [] +priority: high +--- + +## Description + + +When a user logs in via EncryptID, they should operate out of `.r*.online` (e.g., `alice.rnotes.online`, `alice.rspace.online`), with all their data saved securely to their local space. + +## Scope + +This is a cross-cutting feature affecting all rStack apps. Key areas: + +### 1. DNS & Routing +- Wildcard DNS for each `r*.online` domain (`*.rnotes.online`, `*.rspace.online`, etc.) +- Cloudflare wildcard CNAME records pointing to the tunnel +- Traefik wildcard Host rules to route `*.r*.online` to the correct app container + +### 2. Auth / EncryptID Integration +- On login, redirect to `.r*.online` +- Middleware to extract subdomain, validate it matches the authenticated EncryptID +- Reject requests where subdomain doesn't match session identity + +### 3. Data Isolation & Local-First Storage +- Each user's data is scoped to their EncryptID +- Explore local-first / CRDTs (e.g., Yjs, Automerge) for offline-capable storage +- Sync strategy: local device ↔ user's personal encrypted space on server +- Encryption at rest using keys derived from EncryptID + +### 4. Multi-App Consistency +- Shared auth session across `*.r*.online` subdomains (cross-subdomain cookies or token-based) +- AppSwitcher links should resolve to `.rspace.online`, `.rnotes.online`, etc. when logged in +- Consistent UX: user always sees their subdomain in the URL bar + +### 5. Migration +- Existing data needs a migration path to the new per-user scoped storage +- Backward compat for users accessing the root domain (redirect to subdomain after login) + +## Open Questions +- What is the EncryptID identifier format? (alphanumeric, length constraints, case sensitivity) +- Should unauthenticated users see public content at the root domain? +- How does this interact with rSpace's existing space/room model? +- Storage backend: SQLite per user? Postgres row-level security? Encrypted blob store? + + +## Acceptance Criteria + +- [ ] #1 Wildcard DNS configured for all r*.online domains +- [ ] #2 Middleware extracts and validates EncryptID from subdomain +- [ ] #3 User data is scoped and encrypted per EncryptID +- [ ] #4 AppSwitcher links resolve to user's personal subdomain when logged in +- [ ] #5 Cross-subdomain auth session works across rStack apps +- [ ] #6 Migration path defined for existing data +- [ ] #7 Local-first storage strategy documented and prototyped + + +## Implementation Notes + + +Research complete - EncryptID uses DID format (did:key:z, 50+ chars). DIDs too long for DNS labels (63 char limit). Username-based subdomains recommended but usernames are currently optional. + diff --git a/backlog/tasks/task-16 - Add-rStack-AppSwitcher-dropdown-across-all-r-App-headers.md b/backlog/tasks/task-16 - Add-rStack-AppSwitcher-dropdown-across-all-r-App-headers.md new file mode 100644 index 0000000..cbe82e6 --- /dev/null +++ b/backlog/tasks/task-16 - Add-rStack-AppSwitcher-dropdown-across-all-r-App-headers.md @@ -0,0 +1,64 @@ +--- +id: TASK-16 +title: Add rStack AppSwitcher dropdown across all r*App headers +status: Done +assignee: [] +created_date: '2026-02-25 03:47' +labels: + - feature + - ui + - cross-app + - branding +dependencies: [] +priority: high +--- + +## Description + + +Added the unified rStack AppSwitcher dropdown to the header/nav of all 19 r*-online repos plus the rSpace platform Web Component. + +## What was done + +### rSpace platform (rspace-online) +- Rewrote `shared/components/rstack-app-switcher.ts` Web Component with: + - Pastel rainbow badges (rS, rN, rP, rC, rT, etc.) replacing plain emoji icons + - Emoji moved to right of app name in dropdown items + - rStack header with gradient badge at top of dropdown + - rStack footer link at bottom + - Canvas renamed to rSpace + - rMaps moved to Planning category + - "Sharing & Media" renamed to "Social & Sharing" with rNetwork at top +- Fixed light→dark theme across all 21 modules (was causing white header bar) +- Renamed canvas module to "rSpace" + +### rnotes-online +- Created React `AppSwitcher.tsx` component +- Created shared `Header.tsx` with AppSwitcher + SpaceSwitcher + breadcrumbs +- Integrated into all 9 page files + +### 14 other Next.js repos +- Copied `AppSwitcher.tsx` React component into each +- Integrated into existing Header/Navbar components +- Repos: rPubs, rauctions, rcal, rcart, rchats, rfunds, rinbox, rmail, rmaps, rsocials, rtrips, rtube, rvote, rwork + +### 4 non-Next.js repos +- Created standalone HTML/CSS/JS AppSwitcher (no framework dependencies) +- Repos: rNetwork (Vite), rfiles (Django), rstack (static), rwallet (static) + +All repos committed and pushed to main on Gitea. + + +## Acceptance Criteria + +- [ ] #1 AppSwitcher shows pastel badges with r* abbreviations +- [ ] #2 Emoji displayed to the right of app name +- [ ] #3 rStack header with gradient badge at top of dropdown +- [ ] #4 5 categories: Creating, Planning, Discussing & Deciding, Funding & Commerce, Social & Sharing +- [ ] #5 rMaps under Planning, rNetwork at top of Social & Sharing +- [ ] #6 All 19 standalone repos have AppSwitcher integrated +- [ ] #7 rSpace Web Component updated with matching branding +- [ ] #8 Dark theme applied to all rSpace module shells +- [ ] #9 All repos pushed to main on Gitea +- [ ] #10 rspace-online and rnotes-online deployed to production + diff --git a/src/app/globals.css b/src/app/globals.css index 6ef68c3..5aacd63 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -3,8 +3,8 @@ @tailwind utilities; :root { - --background: #0a0a0a; - --foreground: #ededed; + --background: #0f172a; + --foreground: #e2e8f0; } body { diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 0a70057..5dc2ac2 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -12,6 +12,9 @@ const inter = Inter({ export const metadata: Metadata = { title: 'rNotes - Universal Knowledge Capture', description: 'Capture notes, clips, bookmarks, code, and files. Organize in notebooks, tag freely, and collaborate on a visual canvas shared across r*Spaces.', + icons: { + icon: "data:image/svg+xml,📝", + }, manifest: '/manifest.json', appleWebApp: { capable: true,