Why LoyalBite
What makes it better
than the alternatives
- 01
POS-initiated transactions
Customers show a QR code at the till; staff scan and the server calculates points, stamps and redemptions with invoice deduplication (ProcessedInvoices table)
- 02
Multi-brand architecture
One customer account earns across many restaurant brands; UserRestaurantBalances table holds separate points and stamps per restaurant
- 03
Three authentication schemes
Identity cookies for admin panel, customer JWT for mobile app, staff JWT for POS terminals, each with role and ownership filters (ENDPOINT-AUTHORIZATION.md)
- 04
Dual mobile apps
Flutter customer app (BLoC, Dio, Firebase push) and POS scanner app (QR parsing, staff session, transaction service) with separate package IDs
- 05
Campaign and offer engine
Time-limited offers with branch assignment, draft/active states, redemption cap percentage, stamp thresholds and reward text per restaurant
Admin Panel (ASP.NET Core MVC)
- Dashboard with charts (Controllers/Dashboard.cs
- Views/Dashboard/Index.cshtml)
- Analytics screen (Controllers/Analytics.cs
- 7 chart endpoints)
- Restaurant management: logo
- banner
- menu images
- theme colour
- social links
- loyalty rules (Controllers/Restaurants.cs
- 13 actions)
- Branch management with map coordinates (Controllers/Branches.cs
- 8 actions)
- Campaign and offer creation with branch assignment (Controllers/Campaigns.cs
- Controllers/Offers.cs)
- Customer list and detail with points adjustment and QR regeneration (Controllers/Users.cs
- 9 actions)
- Manager accounts (Controllers/Managers.cs
- 6 actions)
- Notifications
- FAQs
- CMS pages (Controllers/Notifications.cs
- Faqs.cs
- Content.cs)
- Audit log (Controllers/Audit.cs
- AuditLogs table)
- Two roles: SuperAdmin (all restaurants) and RestaurantManager (own restaurant only)
Customer REST API (/api/v1)
- Registration with phone (optional email and password) (API/Controllers/AuthApiController.cs Register)
- Phone + OTP login (SendOtp
- VerifyOtp endpoints)
- Email + password login (EmailLogin endpoint)
- Set password and change password (SetPassword
- ChangePassword endpoints)
- Restaurant list with favourites (API/Controllers/CustomerRestaurantController.cs
- 5 endpoints)
- Restaurant detail with branches and offers (RestaurantDetail endpoint)
- Stamp token generation for QR display (API/Controllers/CustomerStampController.cs
- 2 endpoints)
- Points history and balance (API/Controllers/CustomerUserController.cs
- 6 endpoints)
- Profile update with image upload (UpdateProfile endpoint)
- Push token registration (UpdateFcmToken endpoint)
- Notifications inbox (API/Controllers/CustomerNotificationController.cs
- 3 endpoints)
- Public content: FAQs
- About
- Privacy
- Terms (API/Controllers/ContentApiController.cs
- 3 endpoints)
POS API (/api/v1/pos)
- Staff login with admin panel account (AuthApiController StaffLogin
- returns staff JWT with rid claim)
- Earn points from invoice (API/Controllers/PosController.cs Earn
- Services/Pos/EarnOperation.cs)
- Redeem points (RedeemPoints endpoint
- Services/Pos/RedeemPointsOperation.cs)
- Redeem stamp card (RedeemStamp endpoint
- Services/Pos/RedeemStampOperation.cs)
- Redeem offer (RedeemOffer endpoint
- Services/Pos/RedeemOfferOperation.cs)
- Invoice deduplication (ProcessedInvoices table with composite key InvoiceId + BranchId)
- Branch validation (TransactionService checks branch belongs to restaurant)
- HMAC-signed QR parsing (lib/models/qr_parse.dart in POS app)
- Audit logging of refused calls (AuditLogs table
- no foreign keys)
Customer Mobile App (Flutter)
- Sign in with phone + OTP or email + password (lib/features/auth/)
- Registration with optional email and birthday (lib/features/auth/presentation/signup_screen.dart)
- Home screen with balance card
- offers and restaurant list (lib/features/home/presentation/Home_screen.dart)
- Restaurant detail with branches
- offers and stamp card (lib/features/home/presentation/restaurant_reward_screen.dart)
- QR code display for POS scanning (lib/features/stamp/presentation/stamp_qr_screen.dart)
- Points history (lib/features/profile/presentation/transaction_history_screen.dart)
- Profile edit with image picker (lib/features/profile/presentation/edit_profile_screen.dart)
- Notifications inbox (lib/features/notification/presentation/notification_screen.dart)
- Favourites (lib/features/home/presentation/favourite_screen.dart)
- English and Arabic (lib/l10n/)
- light and dark themes
- Firebase push notifications (optional
- lib/core/services/notification_service.dart)
- BLoC state management
- get_it DI
- Dio HTTP (lib/api/datasource/remote/dio/)
POS Scanner App (Flutter)
- Staff login with email and password (lib/screens/settings_screen.dart
- lib/services/terminal_setup_service.dart)
- Terminal setup: restaurant ID and branch ID (lib/services/staff_session.dart)
- QR code scanner (lib/screens/scanner_screen.dart
- mobile_scanner package)
- Action selection: earn
- redeem points
- redeem stamp
- redeem offer (lib/screens/action_screen.dart)
- Transaction execution (lib/services/pos_transaction_service.dart
- returns PosOutcome)
- Result display (lib/screens/result_screen.dart)
- Staff token storage in flutter_secure_storage (lib/services/staff_session.dart)
- QR parsing with tests (lib/models/qr_parse.dart
- test/qr_parse_test.dart)
Loyalty Engine (Server-Side)
- Points calculation: invoice amount × points per AED (Services/Pos/EarnOperation.cs)
- Stamp increment with threshold and goal (Services/Pos/EarnOperation.cs
- Restaurants.StampThreshold and StampGoal)
- Redemption cap: max redeemable points = balance × RedemptionCapPercentage (Services/Pos/RedeemPointsOperation.cs)
- Balance tracking per restaurant (UserRestaurantBalances table
- composite key UserId + RestaurantId)
- Transaction history (Transactions table
- indexed on UserId and RestaurantId)
- Offer validation: active
- not draft
- within date range
- branch assigned (Services/Pos/RedeemOfferOperation.cs)
- Stamp token generation with HMAC signature (Services/CustomerOfferService.cs
- RedemptionTokens table)
- Invoice deduplication (ProcessedInvoices table
- composite primary key)
Campaign and Offer Management
- Campaigns with name
- description
- start and end dates (Models/Entities/Campaign.cs
- Controllers/Campaigns.cs)
- Offers with title
- description
- image
- points cost
- draft/active state (Models/Entities/Offer.cs
- Controllers/Offers.cs)
- Branch assignment (OfferBranches table
- many-to-many)
- Offer list filtered by restaurant
- draft state and date range (Services/OfferService.cs)
- Offer detail with branch list (Views/Offers/Detail.cshtml)
- Offer redemption through POS API (Services/Pos/RedeemOfferOperation.cs)
Notifications and Content
- Push notifications via Firebase Admin SDK (Services/NotificationService.cs
- FirebaseAdmin 3.7.0)
- In-app notifications (Notifications and UserNotifications tables)
- Notification inbox with read/unread state (API/Controllers/CustomerNotificationController.cs)
- FAQs with question and answer (Models/Entities/Faq.cs
- Controllers/Faqs.cs)
- CMS pages: About
- Privacy
- Terms (Models/Entities/CmsPage.cs
- Controllers/Content.cs)
- Public content API (API/Controllers/ContentApiController.cs
- anonymous access)
Database and Deployment
- SQL Server 2019+ with 24 tables (database/schema.sql)
- EF Core 10.0.12 with migrations (NET Project/Migrations/)
- Demo data script with 2 roles
- 3 restaurants
- 5 branches
- 7 accounts (database/seed.sql)
- Docker Compose with SQL Server
- database init and web app (docker-compose.yml)
- Connection string
- JWT key and HMAC key from environment (appsettings.json
- .env.example)
- Rate limiting on sign-in routes (Startup/RateLimiting.cs
- 20 attempts per 60 seconds per IP)
- Audit logging (AuditLogs table
- no foreign keys)
- 40 xUnit tests (NET Project/tests/LoyalBite.Tests/)
| Language | Version | Framework | Used for | Share of code |
|---|---|---|---|---|
| C# | — | — | Web, API, admin | 51.6% |
| Dart | — | — | Mobile app | 34.5% |
| C# (Razor) | — | — | Web pages | 9.9% |
| CSS | — | — | Styling | 1.8% |
| SQL | — | — | Database | 1.5% |
| JavaScript | — | — | Front-end | 0.2% |
| Java | — | — | API | 0.2% |
| Swift | — | — | Mobile app | 0.2% |
| Shell | — | — | Scripts | 0.1% |
| HTML | — | — | Front-end | 0.1% |
| Kotlin | — | — | Mobile app | 0% |
- Primary language
- C# 12 (.NET 10)
- Framework
- ASP.NET Core 10 MVC + EF Core 10
- Database
- SQL Server 2019
- Authentication
- ASP.NET Core Identity (admin cookie) + JWT (customer & staff API)
- Licence
- Single-site
- Screens
- 42
- Database tables
- 24
- Supported languages
- English, Arabic (RTL supported)
- Browser support
- Modern browsers (Chrome, Firefox, Safari, Edge)
| Minimum | Recommended | |
|---|---|---|
| CPU | 2 vCPU | 4 vCPU |
| RAM | 4 GB RAM / 20 GB storage | 8 GB RAM / 40 GB storage |
| OS | Linux or Windows Server, .NET 10 Runtime, SQL Server 2019+ | Linux or Windows Server, .NET 10 Runtime, SQL Server 2019+ |
| Est. monthly hosting | $35 | $35 |
```bash cp .env.example .env # Edit .env: set MSSQL_SA_PASSWORD, JWT_KEY, HMAC_KEY, ADMIN_EMAIL, ADMIN_PASSWORD docker compose up -d --build # Site: http://localhost:8080 ```
```bash # Install .NET 10 SDK, SQL Server 2019+ cd "NET Project" dotnet user-secrets set "ConnectionStrings:DefaultConnection" "Server=localhost;Database=LoyalBite;User Id=sa;Password=<YOUR_SQL_PASSWORD>;TrustServerCertificate=True;" dotnet user-secrets set "Jwt:Key" "<YOUR_JWT_KEY>" dotnet user-secrets set "Secrets:HmacKey" "<YOUR_HMAC_KEY>" dotnet user-secrets set "Seed:AdminEmail" "admin@example.com" dotnet user-secrets set "Seed:AdminPassword" "<YOUR_ADMIN_PASSWORD>" sqlcmd -S localhost -U sa -P '<YOUR_SQL_PASSWORD>' -C -b -i ../database/schema.sql dotnet build -c Release dotnet run --urls "http://0.0.0.0:5264" # Reverse proxy with nginx or Caddy for HTTPS ```
```bash # Create Azure SQL Database (S1 tier or higher) # Create App Service (Linux, .NET 10) # Set connection string and secrets in App Service Configuration cd "NET Project" dotnet publish -c Release -o ./publish az webapp deployment source config-zip --resource-group <RG> --name <APP_NAME> --src publish.zip ```
```bash # Install SQL Server 2019+ locally or use Docker: docker run -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=<YOUR_SQL_PASSWORD>" -p 1433:1433 -d mcr.microsoft.com/mssql/server:2019-latest cd "NET Project" dotnet user-secrets set "ConnectionStrings:DefaultConnection" "Server=localhost;Database=LoyalBite;User Id=sa;Password=<YOUR_SQL_PASSWORD>;TrustServerCertificate=True;" dotnet user-secrets set "Jwt:Key" "$(openssl rand -base64 48)" dotnet user-secrets set "Secrets:HmacKey" "$(openssl rand -base64 48)" dotnet user-secrets set "Seed:AdminEmail" "admin@example.com" dotnet user-secrets set "Seed:AdminPassword" "Admin123!" sqlcmd -S localhost -U sa -P '<YOUR_SQL_PASSWORD>' -C -b -i ../database/schema.sql dotnet run # Open http://localhost:5264 ```
Quality report
Manually reviewedHow to read the quality report
What this is. Every project on Vibe96 goes through an automated audit of its source code before a reviewer in Dubai checks it by hand. The score is out of 100; 75 is the minimum to be listed, and any single failing check blocks a listing regardless of the score.
- Security
- No real credentials in the code, every data-changing route protected, admin areas role-gated, no SQL built from user input.
- Code structure
- A developer can navigate and extend it: clear module boundaries, no giant files, little copy-paste.
- Docs & completeness
- The setup guide, example config, schema and required files the builder committed to are actually in the archive.
- Dependency health
- Packages pinned, no known critical vulnerabilities, no abandoned libraries in production paths.
- Build & deploy
- A clean machine can restore, build and start it by following the shipped instructions.
Warnings are problems that didn't block the listing; they stay visible here until a later version clears them. The audit reads the code — it does not run it — so always try the live demo before you buy. Lines of code are counted from the same audited archive.
What to know before you buy
4 non-blocking findings shown publicly: weak default passwords and placeholder firebase config present; flutter apps have outdated dependencies; .net project has no lockfile; strong authentication and authorization with minor ownership check gaps on read endpoints; moderate code duplication and some oversized files; structure generally sound but needs refactoring; build reproducible with minor setup gaps and missing firebase configuration. The seller has been notified; fixes ship in the next version.
Versions & updates
No updates yet. New versions appear here with a changelog.
Buyers receive updates free for 1 year.
What you get
- </>Full source codeThe complete audited source, delivered as a download from your account. No obfuscation.
- ▤DocumentationSetup guide, architecture notes, CLAUDE.md and AGENTS.md.
- ↻One year of updatesEvery new version the builder publishes, free for 12 months.
- ♧30 days of supportInstallation and defect support through Vibe96 tickets.