Skip to content

Add the Stoa: walkable spaces with live presence, rooms, and calls - #2

Merged
guohai merged 71 commits into
mainfrom
feat/stoa-world
Oct 11, 2026
Merged

guohai merged 71 commits into
mainfrom
feat/stoa-world

Conversation

@guohai

@guohai guohai commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

Why

Agora.build is becoming a walkable world built around resource discovery. This PR brings in the Stoa: the plaza, its first-come rooms, and people's own spaces, with live presence, chat and calls on Agora. It covers Plans A, B, C1 and C2 of the spec and replaces PR #1, which held only Plan A.

  • Spec: docs/superpowers/specs/2026-10-07-stoa-spaces-design.md
  • Plans: docs/superpowers/plans/2026-10-07-spaces-core.md (A), 2026-10-07-world-engine.md (B), 2026-10-08-stoa-live.md (C1), 2026-10-08-stoa-rooms.md (C2)

What changes

  • Spaces core (A):
    • Listed, unlisted and private spaces with separate access rules, one can() check, entry leases, and hosts.
    • Lot rooms from the map. User spaces with invites and members.
    • Agora RTC and Signaling tokens. Secret-derived channel names and per-space keys that rotate on removal.
    • Private spaces return 404 to people who can't see them.
  • World engine and themes (B):
    • Tiled maps with semantic roles, and A* pathfinding shared by browser and server.
    • A canvas renderer.
    • Data-only themes (Agora, Minimal, Cyberpunk) validated at startup.
    • Click, tap and keyboard movement, and reduced-motion support.
  • Live Stoa (C1):
    • Presence, movement and room chat over Agora Signaling, with encrypted payloads in unlisted and private spaces.
    • Rate limits and receiver checks.
    • A plaza capped at 200, ready for area-of-interest cells later.
  • Rooms (C2):
    • Calls inside rooms. A UI-free RTC client, plus theme video layouts: over avatars, strip, or grid.
    • Decorate mode for hosts, with the server's placement rules checked as you edit.
    • Host hand-over and removal; removal moves the room to a new channel.
    • Creating and managing your own spaces: settings, invite links, members, and delete.
  • Meetings retired:
    • /meet/<id> and meetings.html redirect into the Stoa, and /api/rooms returns 410.
    • "Start a room" buttons open the Stoa's create dialog.
    • Sign-in can return to Stoa pages.

Existing meeting rooms are migrated into unlisted, members-only spaces with the same IDs, so old links keep working.

Configuration

.env.example adds SPACE_CHANNEL_SECRET, AGORA_RTM_PERMISSIONS and PLATFORM_ADMINS. The Agora project needs Signaling enabled. Without Agora credentials, the Stoa still loads; live presence and calls show as not connected.

Verification

  • npm test: 288 pass, 0 fail, 1 skipped (the PostgreSQL test, which needs a database). npm run build succeeds.
  • Every task had a spec and code review, each plan had a final whole-branch review, and the review fixes are in the branch.
  • Live checks with real Agora, using two signed-in browsers and a guest:
    • C1: presence in about 1.6 s and chat in about 0.3 s. Lot rooms and topics, a private space with an invite, and no plaintext in captured websocket frames.
    • C2: video over avatars in about 0.2 s and screen share in 0.9 s. Decorations reach others in 0.2 s. Removal takes effect in about 0.3 s, and re-entry is refused. A private space invite and call worked.
    • Results are recorded at the end of the C1 and C2 plans.
  • Desktop (1280 px) and mobile (390 px) screenshots were checked locally for the plaza, rooms, calls, decorate mode and the space dialogs. They aren't attached here.

Known gaps and follow-ups

  • Tab restore: headless Chromium never restored the page from the back/forward cache, so reload-on-restore is untested. A plain Back works.
  • Hosting hand-over: it shows in about 3 s, because room refreshes are limited to one every 5 s.
  • Removed callers: a removed person's client could stay on the call until its RTC token expires (at most 1 hour), as the spec allows.
  • Next:
    • Plan D: Agora Chat for team messages and DMs.
    • Plan E: discovery hooks.
    • Area-of-interest cells for a bigger plaza.

Generated with SMT smt@agora.build

guohai added 30 commits October 7, 2026 17:56
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
…istener safety

🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
…nput guards

🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
…el, engine hardening

🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
guohai added 26 commits October 8, 2026 09:26
Carry the tile on face messages, coalesce room refreshes, expire ghosts, batch and cull for large plazas, update room rows in place, handle second tabs and lost leases, and connect Signaling in the background.

🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
Culling hid walkers from the redraw decision, so with reduced motion or the Minimal theme a person crossing into view was only drawn once they stopped. Positions are now computed for everyone, a slow check keeps running while someone walks off-screen, and only nearby people are drawn.

🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
…d pick hooks

🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
Old /meet links and meetings.html redirect into the Stoa, the /api/rooms
routes answer 410, and starting a room from any page opens the Stoa's
Start a space dialog.

🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
- Removing a member from the manage dialog rekeys the room you are in, like the in-room Remove button (stage.rekeyRoom).
- Call tiles: screen shares first, then your camera, then video; strip and grid scroll within their own band of the map.
- Heartbeat access is always kept, so a later live connection opens the current channel and key.
- Extra heartbeats run one at a time, at most one every two seconds unless forced.
- Heading follows the stage's room; ?start= survives signing in; bfcache restores reload.
- Host topic form needs a live lease; a full plaza lists your spaces once; draw frames are built only while tiles float.
- stage.fromHost replaces three copies of the host check; dead decorArea removed.

🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
A rekey that arrives inside the two-second gap, or while a heartbeat is
in flight, now runs as one trailing beat, so a second removal never
leaves the room split across channels. The strip of call tiles only
covers the width its tiles need.

🤖 Built with SMT <smt@agora.build>
🤖 Built with SMT <smt@agora.build>
@guohai
guohai merged commit 602165f into main Oct 11, 2026
4 checks passed
@guohai
guohai deleted the feat/stoa-world branch October 11, 2026 05:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant