Case Study

Social Networking and Multi-Account Messaging

A shared mobile and web client for feeds, conversations and multiple accounts.

When someone likes a post and then opens its thread, that like should still be there. This client keeps that shared state across feeds, profiles and conversations. It runs on iOS, Android and the web. The same application also brings media publishing, chat and several accounts together in one place.

We treated account switching as part of the data design. Choosing another account changes more than the profile picture. It swaps the session, the query cache and the stored data behind the interface.

The challenge

People act faster than a network request can finish. Someone may like and then unlike a post within a second, or switch accounts while requests are still open. Every screen needs to show the latest intended action while the server confirms it.

The platforms also expect different navigation. Native tabs keep their own screen stacks, a web client has to work with browser history, and the shared screens had to fit both.

What we built

The client offers following and custom feeds, with profiles and threads. Users can compose image or video posts. A user can also line up a series of posts and submit the thread as one related set of records.

Startup restores preferences and the chosen session before the account interface appears, and each account carries its own query client and persisted query storage. Switching accounts remounts the interface around that account's data.

Chat reads a cursor-based event stream and keeps separate state for each conversation. Pending messages go out in order, and the client retries a transient failure within the session. Lists and labels organise who and what a user sees. Mutes and blocks round out the moderation controls.

Keeping views in agreement

A pending overlay holds the change to a post and merges it with the fetched data. Each change carries the post identifier. Notifications then let any supported view react to it, which saves every list from tracking its own mutation state.

Toggle actions keep one active request and one pending intent. A newer tap can replace the queued intent, and the confirmed result then guides the next request. A fast like-unlike sequence lands on a defined result, and the app does not send every tap along the way.

Separating account data on the device

Persisted queries stay apart from general preferences and account settings. Only chosen queries with versioned keys reach the disk, and account identifiers keep their cached data separate.

Real request results tell the client whether the network is available. While the app is offline and in the foreground, it can check again for a connection. Cached reads help during a short interruption. Pending changes never form a durable offline write queue, so the client stays online-first. True offline first mobile messaging would need to keep that durable queue, which this design deliberately leaves out.

Publishing a thread and navigating between screens

Media uploads finish before the thread records are submitted through one atomic batch. A draft record can live on the server while its media stays on the device, so the two parts carry different storage jobs.

On native platforms, bottom tabs hold separate navigation stacks. The web version follows browser navigation, and the shared screens sit inside whichever structure the platform uses.

Project success

A pending post action can show up across feeds, profiles and threads. The user sees one consistent view while the server confirms it. Switching accounts picks a separate query client and cache, which keeps the interface tied to the active session.

Publishing and conversation run on the same client. Media composition leads into an atomic thread submission, and chat handles conversation events in order. These flows work across native and web navigation, with the recovery limits of an online-first application stated plainly.

Technology stack

Application

React Native, React, TypeScript

Server-state handling

TanStack Query

Device storage

AsyncStorage, MMKV

Navigation

React Navigation

Service interfaces

AT Protocol, typed XRPC clients

Supporting web services

Go, Express, PostgreSQL

Recognize the pattern?

If one of these looks like your situation, the discovery call is where we find out how close.