Loyalty programs often start as a paper card and end as a collection of operational exceptions. App Sticker, part of the EatSticker platform, starts from a different idea: make progress visible, enjoyable, and straightforward for both the person visiting a venue and the business operating it.

Instead of abstract points, people collect stickers in digital albums. A visit can begin with a QR code; every album has rules, progress, and a reward. It sounds lightweight, but it raises a concrete engineering question: how do you pair an instant mobile experience with business rules, authorization, and operations that need to be dependable?

The product bridges two journeys

The system has two sides that must work together.

For consumers, the app provides album discovery and tracking, collection progress, reward requests, and notifications. For businesses, it offers tools to create campaigns, configure rewards, manage QR codes, review requests, and grant stickers.

That separation is more than an interface decision. These audiences have different rhythms and responsibilities. A consumer expects to finish an action in seconds. A business needs controls, context, and history before approving a request. Treating them as one application would have simplified the beginning, but made it harder for each journey to evolve well.

A QR code starts the flow; it is not final proof

A QR code lowers friction: someone visits a venue, points a camera, and enters the right context. Still, a code alone should not grant an unlimited benefit.

When someone already participates in an album, another scan can create a sticker request for the business to review. That flow has explicit states — pending, approved, rejected, or expired — and protects both sides with repeat limits, deduplication, expiration, and business-scoped authorization.

The outcome is an important balance for products that connect digital and physical worlds: the experience can be fast without confusing convenience with trust.

Business rules belong in the domain

A reward is not merely a completed screen. It depends on rules such as the deadline after an album is completed, eligibility, campaign configuration, and the business’s subscribed plan.

On the backend, the platform separates API, domain, data, and workers into distinct responsibilities. The domain holds the rules; the data layer uses Entity Framework Core and PostgreSQL; the REST API serves mobile apps and the admin console; and background processes handle work that does not belong in an interactive user path.

This separation is particularly useful for plans and entitlements. For example, access to shared or custom stickers is a product policy, not a validation scattered across screens. Centralizing that decision keeps different app versions from interpreting the same rule in incompatible ways.

Two mobile apps, one shared decision layer

App Sticker is moving to consumer and business applications built with Kotlin Multiplatform and Compose Multiplatform. Shared code keeps authentication, HTTP communication, serialization, flow rules, and domain components consistent across Android and iOS, while platform-specific integrations remain where they make sense.

Ktor handles networking; Supabase Auth manages sessions; Firebase supports Android messaging; and each app retains its own navigation and interface language. It is an approach that reduces duplication without pretending that the audiences — or platforms — are identical.

There is also a web-based administrative interface built with React, TypeScript, and Vite. It complements the business app with a surface better suited to operational tasks, data, and management.

Notifications are a system, not a visual effect

One of the richest parts of the architecture is notification delivery. The app registers device tokens; the domain creates an intent to notify; and an outbox records the work transactionally. A dispatcher sends items to a queue, and a worker processes email or push messages, recording delivery events and updating the lifecycle.

This separation keeps an important action — such as approving a request — from depending on the immediate availability of a push provider. It also creates an audit trail and enables failures, inactive tokens, and delivery attempts to be handled without blocking the main flow.

The apps also treat notification permissions and preferences as part of the experience, rather than as an abrupt prompt on first launch.

The architecture behind the experience

Today, the system combines:

  • .NET 8 and C# for the API, domain, jobs, and workers;
  • PostgreSQL and Supabase for data, authentication, and JWT sessions;
  • Kotlin Multiplatform and Compose Multiplatform for the consumer and business mobile apps;
  • React, TypeScript, and Vite for the administrative console;
  • Kubernetes on Oracle Cloud and GitHub Actions for packaging and delivery;
  • queues, an outbox, and email/push providers for asynchronous work.

This is not about using a large number of technologies for their own sake. Each boundary exists because the product needs to separate fast interaction, business rules, persistence, and eventual processing.

What this project keeps teaching me

App Sticker is a reminder that gamification works only when the operation behind it is dependable. A beautiful album does not compensate for an ambiguous reward; a simple QR scan does not remove the need for policies; a useful notification depends on an entire chain of correct decisions.

That combination is what makes the project interesting: bringing a physical and emotional experience — completing a collection — into a system that needs to be secure, auditable, multilingual, and sustainable as more businesses and consumers join the platform.

Explore the platform at app-sticker.com.