--- id: TASK-69 title: folk-rapp auto-derives space context + subdomain URL canonicalization status: Done assignee: [] created_date: '2026-02-28 00:29' updated_date: '2026-02-28 00:29' labels: - fix - routing - canvas dependencies: [] priority: high --- ## Description Two fixes ensuring rApps on canvas load as applets directly in the correct space: 1. **folk-rapp race condition fix**: `createRenderRoot` unconditionally read `getAttribute("module-id")` which returned `""` and overwrote the `moduleId` already set via JS property setter — showing the picker menu instead of loading the module. Fixed to preserve JS-set properties. 2. **Auto-derive spaceSlug**: folk-rapp now reads the current URL path (`/{space}/canvas` → space) to auto-derive spaceSlug so embedded rApps always know their space context without explicit passing. 3. **Subdomain canonicalization**: `rspace.online/{space}/{moduleId}` now 301-redirects to `{space}.rspace.online/{moduleId}`. Spaces are subdomains, not path segments. ## Acceptance Criteria - [x] #1 folk-rapp shapes with moduleId set load the iframe directly without showing picker - [x] #2 spaceSlug auto-derived from URL when not explicitly provided - [x] #3 rspace.online/{space}/{moduleId} redirects 301 to {space}.rspace.online/{moduleId} - [x] #4 newShapeElement passes communitySlug as fallback spaceSlug when restoring folk-rapp from sync - [x] #5 bun run build passes with zero errors ## Final Summary Fixed folk-rapp shapes to load as applets directly in the current space. Resolved race condition where createRenderRoot overwrote JS-set moduleId. Added auto-derivation of spaceSlug from URL. Added 301 redirect from path-based space URLs to subdomain form. Commits: 09d23f8, 9f3c9ab. Deployed to production.