Skip to main content

Data Flow

How data moves through the TrickBook application.

Authentication Flow

App Startup Flow

// app/_layout.tsx - Simplified
const RootLayout = () => {
const { user, isLoading, loadStoredAuth } = useAuthStore();

useEffect(() => {
loadStoredAuth(); // Restore token from SecureStore
}, []);

if (isLoading) return <SplashScreen />;

return (
<QueryClientProvider client={queryClient}>
<ThemeProvider>
<Stack>
{user ? (
<Stack.Screen name="(tabs)" />
) : (
<Stack.Screen name="(auth)" />
)}
</Stack>
</ThemeProvider>
</QueryClientProvider>
);
};

Data Fetching with React Query

All API data flows through React Query for caching, deduplication, and automatic refetching.

// Example: Fetching trick lists
const { data: trickLists, isLoading, refetch } = useQuery({
queryKey: ['trickLists'],
queryFn: () => trickbookApi.getTrickLists(),
staleTime: 5 * 60 * 1000, // 5 minutes
});

// Example: Creating a trick list (mutation)
const createMutation = useMutation({
mutationFn: (data: CreateTrickListData) =>
trickbookApi.createTrickList(data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['trickLists'] });
},
});
React Query Cache Flow:

Component mounts → Check cache

├── Cache fresh → Return cached data

├── Cache stale → Return cached data + refetch in background

└── No cache → Fetch from API


apiClient.get('/listings')


Auto-inject x-auth-token header


Return data → Cache → Component

Trick List Data Flow

Creating a Trick List

1. User taps "+" button


2. Form with React Hook Form + Zod validation


3. useMutation → POST /api/listings
{ name: "Kickflips to learn" }


4. Backend creates in MongoDB
db.tricklists.insertOne({...})


5. Return { _id, name, tricks: [] }


6. Invalidate ['trickLists'] query → auto-refetch


7. Navigate to trick list detail screen

Tracking Trick Progress

PUT /api/listing/{trickId}
{
checked: "Landed" // "Not Started" | "Learning" | "Landed" | "Mastered"
}


Update in MongoDB


Invalidate query cache


Update StatusBadge + ProgressBar UI

Social Feed Data Flow

Creating a Post

Feed Algorithm Scoring

Feed posts are ranked by a scoring algorithm:

score = (engagement * 0.35) + (recency * 0.25) +
(completion * 0.25) + (interaction * 0.15)

Homie boost: Posts from friends get 2.5x multiplier
Recency: 48-hour half-life decay

Image Upload Flow

Direct Messaging Flow

Subscription Flow

Real-Time Data Flow

Socket.IO Connection Lifecycle:

App Launch


Connect to Socket.IO server

├── Auth: Pass JWT in handshake

├── /feed namespace
│ │
│ ├── Join room: user:{userId}
│ ├── Listen: 'post:update' → update React Query cache
│ ├── Listen: 'reaction:update' → update reaction counts
│ └── Listen: 'comment:new' → show notification

└── /messages namespace

├── Join room: user:{userId}
├── Listen: 'message:new' → add to conversation
├── Listen: 'typing' → show indicator
└── Listen: 'read' → update read receipts

API Request Pattern

All authenticated requests flow through a custom fetch client:

// src/lib/api/client.ts
const apiClient = {
get: async (url: string) => {
const token = await SecureStore.getItemAsync('authToken');
const response = await fetch(`${BASE_URL}${url}`, {
headers: {
'x-auth-token': token ?? '',
'Content-Type': 'application/json',
},
});
return response.json();
},
// post, put, delete follow same pattern
};

Features:

  • Auto-injects auth token from Secure Store
  • Retry logic (3 attempts with 1s delay)
  • Custom timeouts (30s default, 120s for uploads)
  • Environment-aware base URL (dev vs production)