Wave-to-Meet Feature
Overview
The Wave-to-Meet feature enables users to initiate connections, chat anonymously, and meet up in person using synchronized color beacons.
User Flow
1. User sees lit lantern → Sends wave 👋
2. Recipient receives wave notification → Accepts/Declines
3. If accepted → Both users can now chat 💬
4. Either user can activate "Hold Up Lantern" → Both phones show matching color 🏮
5. Users find each other in venue using color-matching beaconsComponents
1. WaveManager (src/components/WaveManager.jsx)
Purpose: Displays incoming wave notifications and handles acceptance/decline actions.
Props:
waves(array): List of incoming wave objectsonAccept(function): Handler for accepting a waveonDecline(function): Handler for declining a waveonOpenChat(function): Handler for opening chat with accepted connection
Wave Object Schema:
{
id: string | number,
interest: string, // User's stated interest
mood: string, // Mood/intention (e.g., "Conversation")
venue: string, // Venue name
time: string, // Relative time (e.g., "5m ago")
status: 'pending' | 'accepted',
connectionId?: string // Present if status is 'accepted'
}Features:
- Slide-up animation for new waves
- Amber glow effect matching Lantern brand
- Shows user interest and mood anonymously
- Persistent "Open Chat" button for accepted waves
2. Chat (src/components/Chat.jsx)
Purpose: Anonymous chat interface for accepted connections with quick access to beacon feature.
Props:
connection(object): Connection detailsonClose(function): Handler for closing chatonHoldUpLantern(function): Handler for activating beaconmessages(array): Chat message history
Connection Object Schema:
{
id: string,
interest: string,
mood: string,
venue: string,
matchColor: 'amber' | 'purple' | 'blue' | 'green' | 'pink',
timestamp: Date
}Message Object Schema:
{
id: number | string,
text: string,
from: 'me' | 'them',
timestamp: string // Formatted time (e.g., "2:45 PM")
}Features:
- Full-screen overlay chat interface
- Gradient purple-to-pink theme (differentiates from amber Lantern branding)
- Connection info banner showing venue and interest
- Prominent "Hold Up Lantern to Meet" CTA
- Auto-scroll to latest messages
- Real-time message input
Backend Integration Points:
// Send message
POST /api/messages
Body: { connectionId, text, timestamp }
// Fetch messages
GET /api/messages?connectionId={id}
Response: { messages: [...] }3. LanternBeacon (src/components/LanternBeacon.jsx)
Purpose: Full-screen synchronized color beacon for finding connection in person.
Props:
connection(object): Connection detailsmatchColor(string): Color scheme identifieronClose(function): Handler for closing beacon
Color Schemes:
amber: Warm amber/orange gradientpurple: Mystic purple/pink gradientblue: Ocean blue/cyan gradientgreen: Forest green/teal gradientpink: Rose pink gradient
Features:
- Full-screen immersive color display
- Pulsing animation (0.8x to 1.2x scale)
- Radial glow effect for visibility
- Auto-hides instructions after 5 seconds
- Safety reminder at bottom
- Matching colors ensure both users see identical beacon
Technical Details:
- 60 FPS pulse animation via
setInterval(50ms) - CSS gradients + filter effects for glow
- Brightness modulation for attention
- Accessible close button
Integration with Dashboard
State Management
Dashboard manages all wave/connection state:
const [incomingWaves, setIncomingWaves] = useState([])
const [activeConnections, setActiveConnections] = useState([])
const [activeChat, setActiveChat] = useState(null)
const [showBeacon, setShowBeacon] = useState(false)Event Handlers
handleSendWave(lanternId)
- Triggered when user clicks "Wave" on a lantern
- TODO: POST to
/api/waves
handleAcceptWave(waveId)
- Generates random matching color
- Creates connection object
- Moves wave from
incomingWavestoactiveConnections - TODO: POST to
/api/waves/{id}/accept
handleDeclineWave(waveId)
- Removes wave from
incomingWaves - TODO: POST to
/api/waves/{id}/decline
handleOpenChat(connectionId)
- Sets
activeChatstate - Opens full-screen chat overlay
handleHoldUpLantern()
- Sets
showBeaconto true - Displays LanternBeacon with matching color
Backend Requirements
Endpoints
1. Send Wave
POST /api/waves
Body: {
targetLanternId: string,
senderLanternId: string
}
Response: {
waveId: string,
status: "sent"
}2. Accept/Decline Wave
POST /api/waves/:waveId/accept
Body: {
matchColor: string // Generated on client
}
Response: {
connectionId: string,
matchColor: string
}
POST /api/waves/:waveId/decline
Response: { status: "declined" }3. Real-time Wave Notifications
Recommended: WebSocket or Server-Sent Events (SSE)
WebSocket: /ws/waves
Message format: {
type: "wave_received",
wave: { id, interest, mood, venue, time }
}4. Chat Messages
POST /api/messages
Body: {
connectionId: string,
text: string,
timestamp: string
}
GET /api/messages?connectionId={id}
Response: {
messages: [{ id, text, from, timestamp }]
}5. Color Sync
GET /api/connections/:id/beacon
Response: {
matchColor: string,
expiresAt: timestamp // Optional: time-limit beacon availability
}Security & Privacy Considerations
Anonymity
- No user names or photos exchanged
- Only interest/mood visible until connection
- Messages are connection-scoped (not user-scoped)
Safety Features
- Geofencing: Verify users are at claimed venue before allowing waves
- Rate Limiting: Prevent spam waves
- Reporting: Add ability to report inappropriate behavior
- Time Windows: Auto-expire connections after venue check-out
- Block List: Allow users to block lanterns
Data Retention
- Messages: Delete after 24h or connection closure
- Connections: Expire when either user leaves venue
- Waves: Auto-decline after 15-30 minutes
Testing
Storybook Stories
WaveManager.stories.jsx: All wave notification statesChat.stories.jsx: Empty and populated chat statesLanternBeacon.stories.jsx: All 5 color variants
Manual Testing Flow
- Run
npm run dev - Click "Simulate Wave" button (dev only)
- Accept wave → Chat opens
- Send test messages
- Click "Hold Up Lantern" → Beacon activates
- Test all 5 beacon colors
Unit Tests (TODO)
npm testTest coverage should include:
- Wave acceptance creates connection
- Wave decline removes notification
- Messages send/receive correctly
- Beacon colors match between users
- Chat auto-scrolls on new messages
Future Enhancements
- Voice/Video Chat: Upgrade from text to rich media
- Group Meetups: Allow multiple users to join same beacon color
- Venue Check-in Verification: Require QR scan at venue
- Interest Matching Algorithm: Suggest waves based on compatibility
- Post-Meetup Feedback: Optional rating/review system
- Persistent Connections: Allow users to re-connect at different venues
- Beacon Patterns: Add pulsing patterns for differentiation (same color, different rhythm)
Demo & Development
Simulate Wave (Development Only)
A "Simulate Wave" button appears in top-right corner during development:
{process.env.NODE_ENV === 'development' && (
<button onClick={simulateIncomingWave}>
Simulate Wave
</button>
)}Remove or comment out before production deployment.
Architecture Diagram
┌─────────────────────────────────────────────────┐
│ Dashboard (Main View) │
│ ┌───────────────────────────────────────────┐ │
│ │ HomeView / VenueView │ │
│ │ • Browse venues │ │
│ │ • See lit lanterns │ │
│ │ • Click "Wave" button ──────────────┐ │ │
│ └───────────────────────────────────────┘ │ │
│ │ │
│ ┌──────────────────────────────────────┐ │ │
│ │ WaveManager │◄───┘ │
│ │ • Incoming wave notifications │ │
│ │ • Accept/Decline actions ───────┐ │ │
│ └──────────────────────────────────┘ │ │
│ │ │
│ ┌──────────────────────────────────┐ │ │
│ │ Chat Component │◄──┘ │
│ │ • Anonymous messaging │ │
│ │ • "Hold Up Lantern" CTA ────┐ │ │
│ └──────────────────────────────┘ │ │
│ │ │
│ ┌──────────────────────────────┐ │ │
│ │ LanternBeacon │◄──┘ │
│ │ • Full-screen color glow │ │
│ │ • Synchronized matching │ │
│ └──────────────────────────────┘ │
└─────────────────────────────────────────────────┘For questions or contributions, see CONTRIBUTING.md.