Lootlark

October 10, 2026 (2w ago)

Stack: C#, .NET 8, ASP.NET Core, .NET Aspire, EF Core, PostgreSQL, Azure Service Bus, Stripe, Keycloak, React, TypeScript, Vite, Testcontainers · Repo: Axeloooo/GameStore (the codebase keeps the original name GameStore in its projects, routes and Keycloak realm)

Problem

A store that sells digital goods must not hand out duplicate codes when the browser double-clicks, Stripe redelivers a webhook, or the process crashes between writing to the database and publishing a message. Lootlark is a full-stack game store (browse and filter the catalog, keep a basket, check out with Stripe in test mode, receive codes) built around making that payment-to-fulfilment path safe. Admins can create, edit and delete games, including cover image upload.

Architecture diagram

  React SPA --OIDC--> Keycloak (local) / Entra ID
      |
      | Bearer JWT                          Stripe.js card entry
      v                                            |
  GameStore.Api --create Checkout Session--> Stripe (test mode)
      ^   |                                        |
      |   +--> PostgreSQL, Blob storage            |
      |                                            |
      +--- signed webhook: checkout.session.completed
      |
      | one transaction: order -> Processing,
      | basket cleared, OutboxMessage written
      v
  OutboxProcessor (polls every 10 s)
      | publishes OrderPaid
      v
  Service Bus queue "orders" --> GameStore.Worker
      |                              | generates codes,
      |                              v order -> Completed (PostgreSQL)
      +-- no MessageType --> dead-letter queue --> logging processor

The API is a .NET 8 minimal API in vertical feature slices (Games, Genres, Baskets, Orders, Payments). Order states run Pending, Processing, Completed. A .NET Aspire AppHost starts PostgreSQL, Azurite, the Service Bus emulator, Keycloak and two Stripe CLI containers.

Key decisions

Challenges

Results

Links