Inspiration

Restia is a restaurant management app. While many similar apps exist on the market, we wanted to address some common issues and improve the overall user experience during development of the app.

A restaurant is managed by a diverse set of users, each with different roles. We have waiters, for example, who take orders from clients and communicate them to the kitchen, where the chefs prepare the food.

One of the critical problems in some restaurants is inconsistent network availability. Waiters have to move throughout different zones, some with poor network conditions, so their ability to use a mobile phone for taking orders can be severely affected.

Having this problem in mind, we eventually came up with a vision of a restaurant as a distributed system with different actors. Ideally, the apps used by the staff should work even when offline and then sync with the rest of the users when connectivity is restored. So, we started developing Restia as an offline-first app, where every action happens locally on the device first and is then eventually synced to other devices.

While designing the sync functionality, we considered different approaches and finally decided on using CRDTs(Conflict-free Replicated Data Types). By modeling our data with CRDTs, we could achieve a distributed and network partition-tolerant system.

What it has

  • Real-time table and order management across iOS and Android.
  • Multi-device sync that feels instantaneous.
  • Offline-first: All the operations on the app have 0 latency, all the transactions are final once done on the local device, changes are merged automatically once reconnected and conflicts automatically resolved thanks to our CRDTs approach.
  • RevenueCat subscriptions unlock pro features.
  • Local AI assistant (iOS): Leveraging our offline first architecture and on-device AI using iOS 26 Foundation Models (requires iPhone 15 or newer and a supported language for Apple Intelligence).

How we built it

  • Kotlin Multiplatform: Shared domain logic, sync engine, and state management for iOS and Android.
  • Custom sync engine: CRDTs-based, merging concurrent edits without conflicts.
  • OpenRouter: Easily switching between different AI models on our backend for scanning restaurant menus on the initial setup.
  • Transport: WebSockets via Elixir’s Phoenix channels for soft real-time communication.
  • Offline-first design: Every change is tracked, syncing seamlessly after disconnects.
  • Production apps: Both Android and iOS live. We released some updates including new features such as an AI assisted onboarding which scans the restaurant menu from photos or a PDF, extras on the orders and bug fixes from the feedback we received.

Challenges we ran into

  • Designing a sync engine that scales smoothly to many devices.
  • Handling lifecycle and coroutine scopes under frequent disconnect/reconnect scenarios.
  • Integrating RevenueCat entitlements directly into the app’s feature gating.
  • Running Foundation Models for the local AI chat had an small context window, so we had to do some hacky tricks to fit all the features we wanted on it.

Accomplishments that we're proud of

  • Shipped a production-ready, offline-first POS on both iOS and Android.
  • Real-time multi-device app that consistently synchronizes nearly instantaneous.
  • Shared sync logic entirely in Kotlin Multiplatform, ensuring feature parity across platforms.

What we learned

  • Practical design and implementation of a CRDTs-based sync engine.
  • How Kotlin Multiplatform enables a single source of truth for complex business logic across platforms.
  • The importance of observability when debugging sync and entitlement flows during fast iterations.
  • How to balance ambitious engineering with hackathon requirements.

What’s next

  • Print receipts.
  • Create a desktop app using Compose Multiplatform.
  • Create a web app and dashboard reusing our shared KMP sync engine and code.
  • Push further diff optimizations for even lower latency.
  • Deliver analytics dashboards for restaurant managers.
  • Expand developer tooling for diagnosing sync timelines and conflicts.
  • Increase on-device AI capabilities by expanding the available tools it has.

Extra resources

Sharing our journey

Built With

+ 1 more
Share this project:

Updates