---
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

<!-- SECTION:DESCRIPTION:BEGIN -->
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.
<!-- SECTION:DESCRIPTION:END -->

## Acceptance Criteria
<!-- AC:BEGIN -->
- [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
<!-- AC:END -->

## Final Summary

<!-- SECTION:FINAL_SUMMARY:BEGIN -->
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.
<!-- SECTION:FINAL_SUMMARY:END -->
