Skip to content

Frens System — Implementation Summary

Date: January 9, 2026
Status: ✅ Design Phase Complete (Frontend Scaffold)


What Was Built

A complete privacy-first reconnection system that allows users to save connections from in-person meetings while maintaining Lantern's core anonymity and privacy principles.


Core Innovation

Venue-Bound Broadcasting Model

Unlike traditional social apps where you track other people, Lantern inverts the model:

Traditional: "Let me see where my friends are"
Lantern: "Let my friends see where I am (at specific venues I choose)"

Key Difference: You broadcast TO people, not track them. Each venue is a separate, intentional choice.


Files Created

Documentation

Components

Screens

Storybook Stories

Routes

  • Updated src/App.jsx to include:
    • #/frens - Frens list
    • #/frens/:id - Individual fren profile

How It Works

The User Flow

1. You meet someone at Coffee House

2. Accept their wave → Chat

3. Tap "Save Connection"

4. You're now broadcasting to them at Coffee House
   → They can see YOUR lantern when you're at Coffee House
   → You can't see theirs (unless they save you back)

5. If they save you back:
   → 🎉 Mutual connection notification
   → Both see each other at shared venues

6. Later, you both show up at The Speakeasy
   → Option to add as broadcast venue
   → Each venue is a separate choice

Privacy Model

StateYou See ThemThey See You
Neither saved
You saved them✅ (at broadcast venues)
They saved you✅ (at broadcast venues)
Mutual save✅ (at shared venues)✅ (at shared venues)

Key Features Implemented

1. SaveConnectionPrompt

  • Clear explanation of venue-bound broadcasting
  • Visual confirmation of what they're agreeing to
  • Success state with celebration
  • Privacy-first messaging

2. FrensList

  • Filters: All, Lit (active), Mutual
  • Search: Filter by lantern name
  • Real-time status: Lit indicator with pulse animation
  • Lit banner: "X frens have lit lanterns" priority section
  • Empty state: Educational onboarding

3. FrenProfile

  • Current status: Lit/not lit with venue
  • Interests: Visual tags
  • Connection info: Where/when you met
  • Venue broadcasting:
    • Who you broadcast to (📡)
    • Who broadcasts to you (👀)
    • Shared venues highlight (✨)
  • Actions: Wave, manage venues, remove connection
  • Privacy notice: Explanation of how it works

4. ManageVenuesModal

  • Checkbox list: Toggle venues on/off
  • Mutual indicators: Show which venues are mutually broadcast
  • Explanatory text: How broadcasting works
  • Save state: Only enable save if changes made
  • Privacy reminder: Can change anytime

Design Decisions

Why Venue-Bound Broadcasting?

Problem with traditional location tracking:

  • Reveals patterns (every Tuesday at gym)
  • Enables stalking
  • Creepy factor

Solution:

  • Only see someone at venues you BOTH chose
  • Each venue is intentional
  • Can't build routines or patterns
  • Natural privacy boundaries

Why Asymmetric Visibility?

You save someone = You broadcast to them

  • Like leaving a standing invitation
  • "If you want to find me again, here's my signal"
  • NOT "Let me track where you are"
  • Consent flows with the action

Why No Persistent Chat?

Forces real-world connection:

  • Chat only when both at venues
  • 2-hour post-meetup window for logistics
  • Prevents "pen-pal" syndrome
  • Beacon Invites for coordination

What's Next

Phase 2: Firebase Integration

  • [ ] Firestore connections collection schema
  • [ ] Real-time listeners for lit lanterns
  • [ ] Cloud Functions for mutual detection
  • [ ] Notification system (mutual save, fren lit)
  • [ ] Connection CRUD operations

Phase 3: Real-Time Features

  • [ ] Live updates when frens light lanterns
  • [ ] Priority wave queue for frens
  • [ ] Venue expansion prompts
  • [ ] Connection removal handling

Phase 4: Beacon Invites

  • [ ] "I'll be at X venue on Y date" invites
  • [ ] One-way coordination (no chat)
  • [ ] Calendar integration
  • [ ] Reminder system

Phase 5: Polish & Analytics

  • [ ] Track save rates
  • [ ] Monitor venue expansion patterns
  • [ ] A/B test messaging
  • [ ] User feedback integration
  • [ ] Performance optimization

Testing in Storybook

bash
npm run storybook

Navigate to:

  • Frens/SaveConnectionPrompt - Save modal variations
  • Frens/FrensList - List views and filters
  • Frens/FrenProfile - Profile states (mutual, one-way, lit, not lit)
  • Frens/ManageVenuesModal - Venue management

Testing in App

bash
npm run dev

Navigate to:

  • http://localhost:5173/#/frens - Frens list
  • http://localhost:5173/#/frens/1 - Fren profile (mock data)

Data Model (Preview)

javascript
// Firestore: connections/{connectionId}
{
  connectionId: "abc123",
  user1Id: "user123",
  user2Id: "user456",
  
  // Venue-specific broadcasting
  user1Broadcasts: [
    { venueId: "coffee-house", venueName: "Coffee House", addedDate: "2026-01-09" }
  ],
  user2Broadcasts: [],
  
  // Metadata
  metAt: "Coffee House",
  metDate: "2026-01-09",
  isMutual: false,
  
  // Cached profile data
  user1LanternName: "Amber Beacon",
  user1Interests: ["Jazz", "Coffee", "Art"]
}

Success Metrics (Proposed)

Engagement

  • % of wave acceptances → saves
  • Average frens per user
  • Average venues per mutual connection
  • Reconnection rate (7+ days later)

Privacy Health

  • % users with >10 broadcast venues (spam indicator)
  • Venue expansion rate
  • Connection removal rate

Feature Adoption

  • % users with ≥1 fren
  • % users with ≥1 mutual fren
  • Frens feature DAU/MAU


Design Highlights

Visual Language

  • Amber glow: Active/lit lanterns
  • Purple badges: Mutual connections
  • Gray dots: Inactive status
  • Pulse animation: Real-time activity

UX Patterns

  • Progressive disclosure: Only show complexity when needed
  • Educational empty states: Guide users to first action
  • Celebration moments: Mutual save notification
  • Clear affordances: What's clickable is obvious

Accessibility

  • Color contrast: WCAG AA compliant
  • Focus states: Keyboard navigation support
  • Screen reader labels: Semantic HTML
  • Touch targets: 44px minimum

Status: Ready for Firebase backend integration. All frontend components are functional with mock data and fully documented.

Built with VitePress