Skip to main content

Documentation Index

Fetch the complete documentation index at: https://285e39fd5e337e58f16290.sightscreen.app/llms.txt

Use this file to discover all available pages before exploring further.

How it works

When a user taps Follow, the FollowManager on iOS drives the flow.
1

Local state first

FollowManager immediately writes the matchId to UserDefaults. This makes the bell icon update instantly — no waiting for the network round-trip.
2

API call

POST /user/follow/match with matchId and deviceId (identifierForVendor). The backend creates a record in match-follows with a TTL of 48 hours after the match ends.
3

If match is live: push-to-start

The backend returns the cached displayState so iOS can show initial data immediately. Simultaneously, it creates a PENDING record in live-activities and sends a push-to-start notification to the device.
4

LA creation on device

iOS receives the push-to-start and ActivityKit creates the Live Activity on the Lock Screen and Dynamic Island. If the user has LA permissions disabled, the follow still works (bell icon shows a warning badge) but no LA appears.
5

Token registration

Once the LA is created, iOS observes pushTokenUpdates on the Activity. TokenManager sends the token to POST /matches/:matchId/activity-token. The backend activates the LA record.
6

Score updates begin

The LACoordinator now includes this token when fanning out score updates for the match. See live score pipeline.

When LA permissions are disabled

If the user has denied Live Activity permissions (or the device doesn’t support them), the follow is still created on the backend. The user is “following” the match — they just won’t get a Lock Screen widget. The bell icon shows a warning state to communicate this. The user can still see match updates by opening the app.

Unfollowing

Key points about unfollow:
  • The backend sends an APNs end event to all devices for this user+match. Multi-device cleanup is server-authoritative.
  • FollowManager removes the matchId from UserDefaults immediately (optimistic UI).
  • If the DELETE request fails (offline), FollowManager queues it as a pending unfollow and retries on next app launch.
If the user dismisses the Live Activity directly on the Lock Screen (swipe to dismiss), iOS notifies LifecycleManager, which calls POST /matches/:matchId/activity-dismissed. The backend treats this as an unfollow. See LA lifecycle - user dismiss.

Syncing follows on login

On login, the iOS app calls GET /user/follows to fetch the list of active follow records from the backend. This reconciles local state with server truth and handles:
  • Follows created on another device
  • Local state lost due to app reinstall
  • Follows that expired while the user was signed out

Key tables

TableKey schemaPurpose
match-followsPK: userId, SK: matchIdTracks which users follow which matches (TTL: 48h post-match)
live-activitiesPK: matchId, SK: userId#deviceIdMaps active LA tokens to users and devices

Key endpoints

MethodPathPurpose
POST/user/follow/matchFollow a match
DELETE/user/follow/matchUnfollow a match
GET/user/followsList followed match IDs (sync on login)
POST/matches/:matchId/activity-tokenRegister LA update token
POST/matches/:matchId/activity-dismissedUser dismissed LA (triggers unfollow)