Shows an informational popup with rich landing page content on first
visit, re-openable via a fixed info button (bottom-right corner).
Dismissible via X button, overlay click, or Escape key. Uses
localStorage to track first-visit state.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reinforces the r-suite "your tools" philosophy across all rApp landing pages.
Also normalizes title separators to em-dash for consistency.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- AppSwitcher: rTube/rSwag → Creating, rSocials → Sharing, rData → Observing
- EcosystemFooter: updated link order to match new categories
- UserMenu: 🔑 Sign In button, 🔐 lock when logged in
- SpaceSwitcher: reads EncryptID token, sends Bearer header
- /api/spaces proxy: forwards to rspace.online (canonical spaces)
- /api/me: verifies EncryptID token for auth status
- Header.tsx: standardized bg-slate-900/85 across all apps
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace minimal 3-card landing page with comprehensive feature
presentation matching the rApp ecosystem style:
- Hero with ecosystem badge and gradient accents
- 4 core feature cards (GPS, navigation, meeting points, privacy)
- 6 differentiator cards (c3nav, pinging, Google import, PWA, QR, CRDT)
- How It Works steps
- Use case cards (festivals, city exploration, group coordination)
- Technical highlights grid (MapLibre, OSRM, c3nav, Automerge, etc.)
- Preserved existing Get Started form and room join flow
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Traefik wildcard HostRegexp for <space>.r*.online subdomains
- Middleware subdomain extraction and path rewriting
- Provision endpoint with owner_did acknowledgement
- Registry enforces space ownership via EncryptID JWT
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace inline nav/Navbar with shared Header component
- Header pattern: AppSwitcher dropdown / SpaceSwitcher / actions / Sign In
- SpaceSwitcher and UserMenu work without SDK dependency
- Consistent across all r*Apps
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Standardize to dark background (#0f172a / slate-900) and add emoji
data URI favicon matching the rStack ecosystem.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds the unified rStack app switcher with pastel badges, emoji icons,
and categorized navigation across all 17 rStack apps.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1. WebAuthn Related Origins: rmaps.online was missing the
.well-known/webauthn endpoint, so browsers couldn't use passkeys
registered under RP ID "rspace.online" on rmaps.online. Added
Next.js route handler returning { origins: ["https://rspace.online"] }.
2. Server: moved pingerName declaration before the WS message block
(was inside the push block, causing ReferenceError on every ping).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1. Server: pingerName was used before declaration in the WS message
block (defined inside the push block). Moved declaration above both
blocks. This caused all /push/request-location calls to crash with
ReferenceError.
2. Landing page: always auto-redirect returning users (have saved user
+ last room) instead of only in standalone mode. Shows a loading
spinner during redirect so the landing page doesn't flash.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1. Installed PWA (standalone mode) auto-redirects to last visited room
on launch instead of showing the landing page. Uses localStorage
rmaps_last_room + display-mode: standalone media query.
2. Manual pings now show visible feedback in three ways:
- In-app toast: green banner "Alice pinged you for your location!"
- Browser notification: fires Notification API when permission granted
- Vibration: unchanged [200, 100, 200, 100, 400] pattern
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ping notifications now show who pinged: "<Name> pinged you for your
location!" instead of generic "Someone is looking for you". Caller name
flows through WS messages, silent push payloads, SW postMessage, URL
params (?pinger=), and visible push notifications.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Three fixes for offline ping gaps:
1. SW silent push fallback: when a manual ping arrives as a silent push
but no app window is open, show a visible notification with vibration
instead of failing silently.
2. SW notificationclick: when opening a fresh window (app was closed),
append ?ping=manual to the URL so the app can detect it was pinged.
3. page.tsx: on mount, detect ?ping=manual param, clean it from the URL,
and auto-fire GPS once the WebSocket connection is established.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tap the QR icon (bottom-right on mobile, top-right on desktop) to show
an inline QR code overlay. Scan-to-join — tapping the QR dismisses it.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Manual "Ping All" now sends `manual: true` flag through WebSocket and
push channels. Receiving clients vibrate and respond with a one-shot
getCurrentPosition() regardless of sharing toggle. Auto-periodic 60s
pings stay silent and only respond if sharing is enabled.
Also fixes: SW cache invalidation (v2→v3), navigation requests now
network-first, sync server lastSeen uses ISO strings, Dockerfile
includes verify-token.js.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Server-side participant dedup on join: remove ghost entries with same name but different ID
- Reduce stale participant threshold from 1hr to 15min to match client-side cleanup
- Refactor push subscriptions from Set to Map keyed by endpoint (prevents duplicate pushes)
- Store participantId with push subscriptions for identity-aware routing
- Exclude joining user from their own "Friend Joined" push notification
- Callout (ping) sends visible push to offline users ("X is looking for you!") instead of silent push
- Return last known locations in callout API response for immediate display
- Service worker: 10s cooldown on location request pushes to prevent burst on app reopen
- Service worker: suppress join/leave notifications when app window is focused
- Pass callerName from ParticipantList so offline callout shows who's looking
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace static SVG map with real-time WebSocket connection to the
shared demo community. Alpine route map with interactive markers,
all changes sync across the r* ecosystem in real-time.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Overhaul landing page from login screen to proper hero + features.
Add interactive demo page showing CCC Camp 2026 event with SVG camp
map, animated friend markers, status system, and friend list panel.
Add ecosystem footer to both pages.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Verify JWT tokens on WebSocket connections via query param. Check room
visibility before allowing access. Block writes from read-only connections.
Add room config endpoint. Require auth for creating new rooms.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add optional passkey identity (anonymous access remains default):
- Add Zustand auth store with EncryptID login/register/logout
- Add AuthButton component to home page
- Auto-fill name from EncryptID when authenticated
- Use DID as persistent participant ID in rooms when signed in
- Update useRoom hook to accept optional encryptIdDid
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Shows a prominent button at bottom-left (mobile) or top-left (desktop)
to reopen the friends list after closing it.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add googleMapsParser.ts utility for parsing Google Takeout GeoJSON
- Add ImportModal component with drag-and-drop file upload
- Three-step wizard: Upload → Preview → Success
- Preview list with checkboxes and select/deselect all
- Add "Import Places" button to ParticipantList footer
- Imported places become waypoints with type "poi"
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- JoinForm now pre-populates name/emoji from localStorage and shows
a "Quick Join as [name]" button for returning users
- Home page shows "Rejoin /[room]" button when user has visited before
- Room slug saved to localStorage on every visit for quick rejoin
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add inline JoinForm when navigating directly to room URL
- No longer redirects to home page for new users
- Replace c3nav iframe with fallback UI (c3nav blocks iframe embedding)
- Add 'Open c3nav' button to open indoor map in new tab
- Still shows friend markers with indoor locations
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When clicking a user from the participant list:
1. Map zooms to their location
2. Navigation panel appears with "Navigate here" option
3. Clicking "Navigate here" calculates route to that user
The selectedParticipant state is now lifted to the page level and
passed to DualMapView so both components stay in sync.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace all Google Maps navigation links with in-app zoom functionality.
When clicking on a participant or waypoint to navigate, the map now
smoothly flies to their location at zoom level 17 instead of opening
an external Google Maps link.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Request push notification permission automatically when joining a room,
similar to how location permission is requested.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Auto-subscribe to push notifications when location sharing starts
- Use C3NavEmbed (iframe) for faster indoor map loading
- Set event to 39c3 for current congress
- Increase c3nav API cache to 1 hour with stale-while-revalidate
- Add strong vibration pattern and sound for notifications
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Navigate button now opens Google Maps directions to friend's location
- Added PWA install banner for non-installed users
- iOS users get manual instructions for Add to Home Screen
- Banner can be dismissed and stays dismissed for session
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Server sends request_location via WebSocket to connected clients
- Falls back to silent push for offline/background clients
- Client responds with current GPS location when requested
- Refresh button now works for online friends (no push subscription needed)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Sends silent push to all friends requesting location updates
- Shows spinner while refreshing
- Displays feedback message with count of pinged friends
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Background Sync API support for location sync when coming back online
- Add silent push notifications for requesting location updates
- Add useServiceWorkerMessages hook for handling SW messages
- Connect service worker to location sharing for background updates
This enables:
- Silent location requests via push without showing notifications
- Automatic location sync when device comes back online
- Service worker communication for background location updates
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add 39c3 to all valid event lists
- Change default event ID from 38c3 to 39c3
- Update examples and placeholders throughout codebase
- Maintain backwards compatibility with 38c3 and older events
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add WaypointModal component with delete and navigate actions
- Navigate button opens Google Maps directions to waypoint
- Delete button removes waypoint with confirmation
- Sync server now preserves offline users' last locations
- Users marked as offline instead of removed when disconnecting
- Stale participant cleanup still runs after 1 hour threshold
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remember location sharing preference per room
- Auto-start sharing when returning to a room
- Restore last known location immediately on page load (if < 1 hour old)
- Location updates are saved to localStorage for faster reload
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Move room page from /room/[slug] to /[slug]
- Update all navigation links to use /<slug> format
- Update share URL generation
- Update middleware for subdomain handling
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Location fixes:
- Add coordinate validation to reject invalid (0,0) and out-of-bounds locations
- Clean up stale participants after 15 minutes (was 1 hour)
- Remove invalid locations from localStorage on load
- Use CCH venue center instead of (0,0) for indoor positions without GPS
Session persistence:
- Remember user name and emoji across sessions on home page
- Pre-fill profile form with saved user info
Mobile UI improvements:
- Add floating location share button inside the map
- Visible on all screen sizes with responsive text
- Prominent styling: white when inactive, green when sharing
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add /api/routing endpoint for route calculation
- Support OSRM for outdoor walking/driving routes
- Support c3nav API for indoor routes at CCC events
- Add RouteOverlay component for map route visualization
- Add NavigationPanel for participant/waypoint navigation UI
- Integrate route state management into Zustand store
- Display route line on outdoor map with distance/time estimates
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add c3nav tile proxy API route with session handling
- Add c3nav data API proxy for locations/bounds
- Create IndoorMapView component with MapLibre GL
- Add floor level selector (Level 0-4)
- Tap-to-set-position on indoor map
- Sync indoor positions between participants
- Easter egg: Triple-click Level 0 for "The Underground of the Underground"
- Fix race condition in useRoom when no user data
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix Indoor Map button being covered by participant panel (z-30)
- Implement Set Meeting Point modal with emoji selection
- Add waypoint markers rendering on the map
- Pass waypoints from room through DualMapView to MapView
- Fix TypeScript types for WaypointType
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>