---
id: TASK-HIGH.1
title: 'Bare-domain module routing — rspace.online/{moduleId} as default'
status: Done
assignee: []
created_date: '2026-02-26 03:34'
updated_date: '2026-02-26 06:20'
labels: []
dependencies: []
parent_task_id: TASK-HIGH
---

## Description

<!-- SECTION:DESCRIPTION:BEGIN -->
App dropdown links go to rspace.online/r* (bare domain) instead of demo.rspace.online/r*. Only 'Try Demo' button links to demo subdomain. Server internally rewrites bare-domain module paths to /demo/{moduleId}.
<!-- SECTION:DESCRIPTION:END -->

## Acceptance Criteria
<!-- AC:BEGIN -->
- [x] #1 App dropdown generates bare-domain URLs (/{moduleId}) on rspace.online
- [x] #2 Server rewrites rspace.online/{moduleId} → /demo/{moduleId} internally
- [x] #3 url-helpers isBareDomain() + getCurrentSpace/Module handle bare domain
- [x] #4 Try Demo button visible on bare domain, hidden on demo.rspace.online
- [x] #5 Auto-provision redirects authenticated users to personal subdomain
<!-- AC:END -->

## Implementation Notes

<!-- SECTION:NOTES:BEGIN -->
Implemented in commit a732478. Changed url-helpers.ts (isBareDomain, rspaceNavUrl), server/index.ts (fetch handler rewrite), server/shell.ts (data-hide + client JS for Try Demo). Merged to main.

Follow-up fix (c15fc15): app switcher fallback was 'personal' → 'demo', landing page demo links & ecosystem app links updated to use rspace.online/r* bare domain pattern
<!-- SECTION:NOTES:END -->
