Realtime Team Chat
Build a team chat app for Android in Kotlin with chat rooms, login, and live messages over WebSockets. The server is written with Ktor, which handles accounts, rooms, message history and the WebSocket connections; the app is built with Jetpack Compose, uses the Ktor client to connect, and stores messages in Room, so the history appears instantly and is readable offline. Messages sent without a connection wait in a queue and go out when the connection returns, without ever being sent twice. You'll learn Ktor on both the server and the client, WebSockets, token-based login, Room as a local cache, Kotlin coroutines and Flow, and handling unreliable mobile networks.
- Estimate
- ~15.5h
- Steps
- 7
- Completed by
- 0
- Proposed by
- codeseed.app
Jetpack Compose · Room · Ktor
Project roadmap
- 01
Define the system
~1.5hWrite DESIGN.md: accounts (register and log in with a token), rooms (list, create, join), message history (GET /rooms/{id}/messages?before= for paging), and the WebSocket messages as JSON (send message with a client id, new message, and user joined or left). Describe how the app handles going offline and how duplicates are avoided with client ids. Done when: DESIGN.md defines the API, the socket messages and offline behavior.
- 02
Build the Ktor server
~3hBuild the server with Ktor: register and log in (passwords hashed, returning a JWT), rooms and paginated history stored in a database (with Exposed), and a /ws endpoint that requires the token, subscribes the connection to its rooms, saves incoming messages (ignoring repeated client ids) and broadcasts them to the room's connections. Done when: two WebSocket test clients can chat, and history returns saved messages.
- 03
Build login and rooms in the app
~2hBuild login and register screens in Compose that call the API with the Ktor client, storing the token securely (for example with DataStore and encryption) and showing clear errors. Build a room list with creating and joining rooms. Done when: users can log in, stay logged in after restarting, and see their rooms.
- 04
Show messages from Room
~2.5hStore messages in a Room database and show a room's messages from a Flow, so the screen always reflects the local database. Load history from the API into Room when opening a room, and load older messages when scrolling up. Show your messages and others' differently, with names and times. Done when: a room's history appears instantly when reopened, even offline.
- 05
Connect with WebSockets
~2.5hOpen a WebSocket with the Ktor client after login, and write every incoming message into Room, so the screen updates by itself. Reconnect with increasing waits when the connection drops, and after reconnecting, fetch messages missed in the meantime. Show the connection state in the app. Done when: messages from another user appear live, and the app reconnects by itself after losing the network.
- 06
Queue messages sent offline
~2hWhen sending, save the message in Room as pending with a new client id, and show it right away with a pending mark. Send pending messages in order when connected, and mark them sent when the server's echo with the same client id arrives. Allow retrying failed messages. Done when: messages written in airplane mode are delivered exactly once after reconnecting.
- 07
Test it
~2hWrite server tests with Ktor's testApplication (login, rooms, history paging, WebSocket broadcast and duplicate client ids), and app tests: Room DAO tests, and the send queue and reconnect logic with a fake socket. Done when: all tests pass.
Resources
Ready to build this?
Get a GitHub repo and start building. Your AI reviewer checks each step as you go.
Tech stack