Help us measure site usage?

With your permission, we use self-hosted analytics to understand page usage. It is optional and does not affect the Service. Learn more.

DartadvancedmobileAI generated

Collaborative Kanban Mobile

Build a Flutter Kanban app where several people share the same board: columns like To do, Doing and Done, with cards you drag between them. Moves appear instantly on your screen (optimistic updates) and are sent to a small sync server, which broadcasts them to everyone else over a WebSocket. The app works offline, keeping a local copy in a Drift (SQLite) database, and when two people move the same card at the same time, a clear rule decides who wins so every device ends up with the same board. You'll build both the app and a tiny Dart server, and learn Riverpod state management, Drift for local persistence, WebSockets, optimistic updates with rollback, and ordering cards reliably.

Estimate
~17.5h
Steps
7
Completed by
0
Proposed by
codeseed.app

Flutter · Riverpod · Drift

Project roadmap

  1. 01

    Model boards, columns and cards with Drift

    ~2.5h

    Create a Flutter app with flutter_riverpod and drift. Define Drift tables for boards, columns and cards. Each card has an id (UUID), columnId, title, a position stored as a double, a version integer and updatedAt. Using a double for position lets you place a card between two others by taking the average of their positions. Seed one board with three columns. Done when: the app starts and loads the seeded board from the local database.

  2. 02

    Show the board and drag cards

    ~3h

    Build the board screen: columns side by side, each showing its cards sorted by position. Make cards draggable with Draggable and DragTarget (or LongPressDraggable) so they can move within a column and between columns. On drop, compute the new position between the neighboring cards and save it to Drift through a Riverpod notifier. Done when: dragging a card moves it, and the order survives an app restart.

  3. 03

    Build a small sync server

    ~3h

    In a server/ folder, write a Dart server with shelf and shelf_web_socket that keeps the board in memory. Clients send JSON messages such as {"type":"moveCard","cardId":...,"columnId":...,"position":...,"baseVersion":...}. The server accepts a move only if baseVersion equals the card's current version, increases the version, and broadcasts the result to every client. Otherwise it replies with a rejection and the current card. Done when: two WebSocket clients see each other's accepted moves.

  4. 04

    Send moves optimistically

    ~2.5h

    When the user moves a card, update the UI and Drift immediately, then send the move to the server. If the server accepts it, store the new version. If it rejects it, roll the card back to the server's version and show a short message like This card was moved by someone else. Done when: moves feel instant, and a rejected move puts the card back where the server says it is.

  5. 05

    Apply remote changes

    ~2h

    Listen to the server's broadcasts and apply other people's moves to Drift, which updates the UI through Riverpod. Ignore broadcasts of your own moves that you've already applied. When connecting, ask the server for the full board and replace the local copy. Done when: a card moved on one device appears in its new place on another device within a second.

  6. 06

    Work offline and reconnect

    ~2.5h

    When the WebSocket is disconnected, keep accepting moves and store them in a pending queue table in Drift. Reconnect automatically with growing delays (1, 2, 4 seconds, up to 30). After reconnecting, send the pending moves in order; any that are rejected roll back as in step 4. Show a small Online, Offline or Syncing indicator. Done when: moves made offline are sent after the connection returns, and the board matches the server.

  7. 07

    Test the tricky parts

    ~2h

    Write tests for: calculating a position between two cards (including the first and last places in a column), the server accepting or rejecting moves by version, a rollback after rejection, and the pending queue being sent in order. Use an in-memory Drift database for app tests. Done when: flutter test and the server's dart test both pass.

Ready to build this?

Get a GitHub repo and start building. Your AI reviewer checks each step as you go.

~17.5h · 7 steps

Tech stack

FlutterRiverpodDrift