Skip to content

Kundvagn · 2021 · university project

Kundvagn - Shopping Cart Android App

A university project: an Android shopping-cart app in Kotlin. The part I cared about was sync: two phones, one cart, and Firestore keeping them honest in real time.

Layers
interface, application, data
Built with
Kotlin · Android SDK · Firebase · Firestore · Mobile Development
Elsewhere
source on GitHub
09:41 09:41 kundvagn uid 3f…A mjölk×2 · 34 kr bröd×1 · 42 kr kaffe×1 · 69 kr pay · 145 kr PHONE A · ADDS kundvagn uid 3f…B mjölk×2 · 34 kr bröd×1 · 42 kr kaffe×1 · 69 kr pay · 145 kr PHONE B · LISTENS Firestore europe‑west1 carts/ {uid}/ items/ k7f2 { name:"kaffe", qty:1 } a91c { name:"mjölk", qty:2 } c04e { name:"bröd", qty:1 } rules: auth.uid == uid index: items.addedAt ↑ offline: writes queued set() onSnapshot onSnapshot set() NO CONNECTION set() waits locally → replayed on reconnect ~200 ms write to visible change, Jönköping → europe‑west1 → Jönköping 1 2 3 4 5
Fig. 01 — Two phones, one cart. Firestore keeps them honest, even when one of them is offline for a while.
  1. 1Firebase Auth · sign-in, one cart per user
  2. 2Snapshot listener · every device hears every write
  3. 3Document path · carts/{uid}/items/{id}
  4. 4Offline queue · writes wait locally, then replay
  5. 5Total · recomputed on every change

The problem

A university project in Android development with a brief that sounds simple: a shopping-cart app. The hard part was the one I chose to care about: two phones, one cart, and the cart never disagreeing with itself.

What I built

Kundvagn, Swedish for shopping cart, in Kotlin, with Firebase Authentication1 for sign-in and Firestore for the cart itself3. The cart is a live query: a snapshot listener2 keeps every signed-in device in sync in real time, so an item added on one phone shows up on another within a moment. Around that core: product management, automatic totals5, and a Material Design interface kept deliberately plain.

What I learned

Real-time sync is a user-experience feature before it is a technical one. The moment two devices show different totals, trust is gone. I also learned to keep the app thin and let the backend own the truth, a habit that has served me in every system since.