Student App API Vision
This document outlines potential API designs for optimizing the FindU iOS app experience. Currently, the app communicates directly with Supabase.
This is a design reference document. These endpoints do not currently exist. The iOS app uses Supabase Swift SDK for all operations.
Current Implementation
The iOS app currently:
- Uses Supabase Swift SDK
- Handles authentication via Supabase Auth
- Queries database directly
- Manages real-time subscriptions
// Current approach
let schools = try await supabase
.from("schools")
.select("*")
.order("match_score", ascending: false)
.limit(20)
.execute()
Future API Benefits
A dedicated Student API could provide:
1. Mobile Optimization
Reduced payload sizes and batched data:
// Future API approach
let recommendations = try await api.getRecommendations(
compressed: true,
includeImages: .thumbnail
)
2. Offline Support
Cache-friendly endpoints with sync capabilities:
// Sync local changes when online
let syncResult = try await api.syncOfflineActions(
swipes: localSwipes,
messages: localDrafts
)
3. Simplified Data Access
Pre-computed and enriched responses:
// Get everything needed for home screen in one call
let homeData = try await api.getHomeScreen()
// Returns: recommendations, unread messages, new matches, etc.
Proposed Endpoint Structure
Authentication & Profile
POST /student/auth/apple
POST /student/auth/google
POST /student/auth/refresh
GET /student/profile
POST /student/profile
PATCH /student/profile
POST /student/profile/avatar
Discovery & Matching
GET /student/recommendations
POST /student/swipe
GET /student/schools/:id
POST /student/schools/:id/save
GET /student/matches
GET /student/match/:schoolId/details
Messaging
GET /student/conversations
GET /student/conversations/:id
POST /student/messages
PATCH /student/messages/:id/read
GET /student/notifications
Social Features
GET /student/friends
POST /student/friends/add
POST /student/friends/share-profile
GET /student/friends/:id/schools
POST /student/compare-schools
Scholarships
GET /student/scholarships
GET /student/scholarships/saved
POST /student/scholarships/:id/save
GET /student/scholarships/:id
Mobile-First Design Patterns
Compressed Responses
// Full response
interface School {
id: string;
name: string;
location: { city: string; state: string; };
stats: { /* 20+ fields */ };
images: string[];
}
// Compressed for lists
interface SchoolCompressed {
i: string; // id
n: string; // name
l: string; // location "City, ST"
m: number; // matchScore
img: string; // thumbnail
}
Progressive Data Loading
// Initial load - minimal data
GET /student/recommendations?fields=minimal
// User shows interest - load details
GET /student/schools/:id?fields=full
// Background sync - preload next batch
GET /student/recommendations/preload
Optimistic Updates
// Immediate response with pending status
POST /student/swipe
Response: { status: 'pending', tempId: 'tmp_123' }
// Confirm via websocket or polling
WS: { event: 'swipe.confirmed', tempId: 'tmp_123', id: 'swipe_456' }
Caching Strategy
// Cache headers for different resources
interface CachePolicy {
schools: 'max-age=3600', // 1 hour
profile: 'max-age=300', // 5 minutes
recommendations: 'private, max-age=1800', // 30 minutes
messages: 'no-cache' // Always fresh
}
Batch Operations
// Batch multiple operations
POST /student/batch
{
operations: [
{ method: 'POST', path: '/swipe', body: {...} },
{ method: 'GET', path: '/recommendations' },
{ method: 'PATCH', path: '/messages/123/read' }
]
}
Delta Sync
// Only get changes since last sync
GET /student/sync?since=2024-01-15T10:00:00Z
Response: {
newMessages: [...],
updatedSchools: [...],
deletedItems: [...]
}
Push Notification Integration
// Register for notifications
POST /student/devices
{
token: "APNS_TOKEN",
platform: "ios",
preferences: {
messages: true,
matches: true,
reminders: true
}
}
// Notification payload
{
aps: {
alert: "MIT liked you back! 🎉",
badge: 1,
sound: "match.caf"
},
findu: {
type: "match",
schoolId: "mit_123",
deepLink: "findu://school/mit_123"
}
}
Implementation Considerations
iOS SDK Design
// Clean SDK interface
class FindUAPI {
func getRecommendations() async throws -> [School]
func recordSwipe(_ direction: SwipeDirection, for school: School) async throws
func sendMessage(_ text: String, to conversation: Conversation) async throws
}
// With offline support
class FindUOfflineAPI: FindUAPI {
private let cache: CacheManager
private let queue: OfflineQueue
override func recordSwipe(...) async throws {
try queue.enqueue(.swipe(direction, school))
try await syncIfOnline()
}
}
Error Handling
enum FindUError: LocalizedError {
case offline
case invalidProfile(missing: [String])
case rateLimited(retryAfter: TimeInterval)
case schoolNotFound
var errorDescription: String? {
switch self {
case .offline:
return "You're offline. Changes will sync when connected."
case .invalidProfile(let fields):
return "Complete your profile: \(fields.joined(separator: ", "))"
case .rateLimited(let retry):
return "Too many requests. Try again in \(Int(retry)) seconds."
case .schoolNotFound:
return "This school is no longer available."
}
}
}
Migration Strategy
If implementing this API:
-
Phase 1: Read-only endpoints
- Recommendations
- School details
- Profile data
-
Phase 2: Core interactions
- Swipe recording
- Message sending
- Profile updates
-
Phase 3: Advanced features
- Offline sync
- Batch operations
- Push notifications
Current Alternative
For now, the iOS app can optimize using:
- Supabase SDK with selective queries
- Local caching with UserDefaults/CoreData
- Background refresh tasks
- Supabase real-time for instant updates
See iOS App Architecture for current implementation details.