Phase 1 — Fix scope system: new scope-resolver.ts resolves global vs
space-scoped docId prefixes. Server middleware sets effectiveSpace on
Hono context. All 18 modules updated to use dataSpace for Automerge
doc access while keeping space for display. Client runtime gets
setModuleScopes() and resolveDocSpace() for local-first scope
resolution.
Phase 2 — Seamless cross-space navigation: TabCache now tracks panes
per space:module key. OfflineRuntime maintains lazy WebSocket
connections per space. Space-switcher dispatches space-switch event
handled client-side with history.pushState instead of full reload.
Phase 3 — Spaces as layers: Layer type extended with spaceSlug and
spaceRole. Tab bar gains "Add Space Layer" picker. Canvas renders
cross-space shapes with visual indicators. Space layers persisted as
SpaceRefs via nesting API. Runtime provides getAllActiveSpaces() and
subscribeModuleAcrossSpaces() for module-level data aggregation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bare-domain URLs like rspace.online/rsocials/thread now render an info
page with CTAs instead of silently serving the functional app. The
functional app only appears inside a {space} context (e.g.
demo.rspace.online/rsocials/thread). API routes still pass through.
- Add SubPageInfo interface to shared/module.ts
- Add renderSubPageInfo() renderer to server/shell.ts
- Modify bare-domain routing: api/ passthrough → info page → demo fallback
- Add subPageInfos to 8 modules (rsocials, rflows, rnetwork, rtrips,
rbooks, rphotos, rinbox, rsplat)
- Add window.__rspaceSaveGate() auth prompt on write operations
- Wire save-gate into rsocials Thread Builder save handler
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Show sample data with an info banner instead of blank empty states
when Immich isn't configured or no mailboxes exist.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All modules had getApiBase() matching wrong module names (e.g. /vote
instead of /rvote) and requiring /{space}/ prefix in the URL path.
On subdomains like jeff.rspace.online, the browser URL is /rfunds/...
not /jeff/rfunds/..., so the regex never matched.
New pattern: /^(\/[^/]+)?\/rmodule/ handles both:
- Subdomain: /rfunds/... → base = /rfunds
- Direct: /demo/rfunds/... → base = /demo/rfunds
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extend RSpaceModule with scoping, lifecycle hooks (onInit, onSpaceCreate/Delete
with SpaceLifecycleContext, onSpaceEnable/Disable), and DocSchema support.
Add scoping to all 25 modules (8 space, 11 global-configurable, 6 global-fixed).
Consolidate 4 space creation endpoints into shared createSpace() function.
Add enabledModules enforcement middleware and module configuration API
(GET/PATCH /api/spaces/:slug/modules). Deprecation header on /api/communities.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix getApiBase() regex to match /rphotos instead of /photos, add
/album route with iframe embed via renderExternalAppShell, and update
Immich links to navigate within rSpace instead of opening externally.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add OutputPath type to RSpaceModule so each module declares what content
types it produces (e.g. notebooks, routes, campaigns). Auto-generate
browsable list pages at /:space/:moduleId/:path that render a card grid
inside the standard shell, fetching items from the module's API.
Declares outputPaths across 23 modules (rwallet/rinbox skipped).
Move campaign demo from standalone campaign-demo space to
/rsocials/campaign route with a dedicated timeline view and
/api/campaigns endpoint.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All 22 module directories under modules/ now match their module IDs
(e.g. modules/cart → modules/rcart, modules/canvas → modules/rspace).
Updated all import paths, vite build config, HTML template asset refs,
docker-compose standalone commands, and .gitignore accordingly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>