Skip to content

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 beacons

Components โ€‹

1. WaveManager (src/components/WaveManager.jsx) โ€‹

Purpose: Displays incoming wave notifications and handles acceptance/decline actions.

Props:

  • waves (array): List of incoming wave objects
  • onAccept (function): Handler for accepting a wave
  • onDecline (function): Handler for declining a wave
  • onOpenChat (function): Handler for opening chat with accepted connection

Wave Object Schema:

js
{
  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 details
  • onClose (function): Handler for closing chat
  • onHoldUpLantern (function): Handler for activating beacon
  • messages (array): Chat message history

Connection Object Schema:

js
{
  id: string,
  interest: string,
  mood: string,
  venue: string,
  matchColor: 'amber' | 'purple' | 'blue' | 'green' | 'pink',
  timestamp: Date
}

Message Object Schema:

js
{
  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:

js
// 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 details
  • matchColor (string): Color scheme identifier
  • onClose (function): Handler for closing beacon

Color Schemes:

  • amber: Warm amber/orange gradient
  • purple: Mystic purple/pink gradient
  • blue: Ocean blue/cyan gradient
  • green: Forest green/teal gradient
  • pink: 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:

js
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 incomingWaves to activeConnections
  • TODO: POST to /api/waves/{id}/accept

handleDeclineWave(waveId)

  • Removes wave from incomingWaves
  • TODO: POST to /api/waves/{id}/decline

handleOpenChat(connectionId)

  • Sets activeChat state
  • Opens full-screen chat overlay

handleHoldUpLantern()

  • Sets showBeacon to 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 โ€‹

  1. Geofencing: Verify users are at claimed venue before allowing waves
  2. Rate Limiting: Prevent spam waves
  3. Reporting: Add ability to report inappropriate behavior
  4. Time Windows: Auto-expire connections after venue check-out
  5. 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 states
  • Chat.stories.jsx: Empty and populated chat states
  • LanternBeacon.stories.jsx: All 5 color variants

Manual Testing Flow โ€‹

  1. Run npm run dev
  2. Click "Simulate Wave" button (dev only)
  3. Accept wave โ†’ Chat opens
  4. Send test messages
  5. Click "Hold Up Lantern" โ†’ Beacon activates
  6. Test all 5 beacon colors

Unit Tests (TODO) โ€‹

bash
npm test

Test 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 โ€‹

  1. Voice/Video Chat: Upgrade from text to rich media
  2. Group Meetups: Allow multiple users to join same beacon color
  3. Venue Check-in Verification: Require QR scan at venue
  4. Interest Matching Algorithm: Suggest waves based on compatibility
  5. Post-Meetup Feedback: Optional rating/review system
  6. Persistent Connections: Allow users to re-connect at different venues
  7. 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:

js
{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.

Built with VitePress