A modern, event-driven multi-merchant commerce platform built with .NET 10 microservices.
| Service | Description |
|---|---|
| Catalog Service | Product catalog with CQRS: PostgreSQL write side, Elasticsearch read side |
| Order Service | Cart management, checkout, order tracking |
| Merchant Service | Merchant registration and product management |
| Payment Service | Payment processing via Stripe |
| Inventory Service | Stock reservation and management |
| Identity Service | Authentication and authorization (Duende IdentityServer) |
| API Gateway | Single entry point with YARP reverse proxy and rate limiting |
- React 19 + TypeScript (Vite, Tailwind CSS 4) β customer-facing SPA located in
src/Frontend/urbanx-react
- PostgreSQL β dedicated database per service
- Apache Kafka β asynchronous event messaging between services
- Elasticsearch β product search index (Catalog read side)
- .NET Aspire β orchestration, service discovery, health checks, and distributed tracing
- Product search and browse (Elasticsearch-powered)
- Shopping cart management
- Checkout and online payment (Stripe)
- Order tracking with status timeline
- Product CRUD with inventory management
- Order acceptance and fulfillment workflow
- Transactional Outbox β Catalog, Order, Payment, and Inventory services atomically persist domain events to an outbox table before publishing to Kafka, ensuring no message loss.
- Saga (Choreography) β Order fulfillment is coordinated via events:
OrderCreatedβ Inventory reserved/failed β Payment processed/failed β Merchant notified - CQRS β Catalog service writes to PostgreSQL and reads from Elasticsearch.
- Rate Limiting β API Gateway enforces 100 requests per minute per IP with HTTP 429 +
Retry-Afterheader. - Policy-Based Authorization β All sensitive endpoints require JWT bearer tokens; policies:
CustomerOnly,MerchantOnly,CustomerOrMerchant.
- .NET 10 SDK
- Node.js 20+
- Docker & Docker Compose
Aspire automatically provisions PostgreSQL and Kafka, wires up service discovery, and streams all logs and traces to a dashboard.
- Install the Aspire workload (if not already installed):
dotnet workload install aspire- Start all backend services:
cd src/AppHost/UrbanX.AppHost
dotnet runThis starts the Aspire dashboard at http://localhost:15260 and launches all microservices.
- Start the frontend (in a separate terminal):
cd src/Frontend/urbanx-react
npm install
npm run devThe application is available at:
- Frontend: http://localhost:5173
- API Gateway: Dynamically assigned (see Aspire Dashboard)
- Aspire Dashboard: http://localhost:15260
- Start infrastructure (PostgreSQL & Kafka):
docker-compose up -d- Start each backend service in separate terminals:
# Identity Service
cd src/Services/Identity/UrbanX.Services.Identity && dotnet run
# Catalog Service
cd src/Services/Catalog/UrbanX.Services.Catalog && dotnet run
# Order Service
cd src/Services/Order/UrbanX.Services.Order && dotnet run
# Merchant Service
cd src/Services/Merchant/UrbanX.Services.Merchant && dotnet run
# Payment Service
cd src/Services/Payment/UrbanX.Services.Payment && dotnet run
# Inventory Service
cd src/Services/Inventory/UrbanX.Services.Inventory && dotnet run
# API Gateway
cd src/Gateway/UrbanX.Gateway && dotnet run- Start the frontend:
cd src/Frontend/urbanx-react
npm install
npm run devThe application is available at:
- Frontend: http://localhost:5173
- API Gateway: http://localhost:5000
- Identity Service: http://localhost:5005
All routes below are accessed via the API Gateway. Endpoints marked π require a JWT bearer token.
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/api/products |
Public | List/search products |
GET |
/api/products/{id} |
Public | Get product by ID |
GET |
/api/products/merchant/{merchantId} |
Public | List merchant products |
POST |
/api/products |
π Merchant | Create product |
PUT |
/api/products/{id} |
π Merchant | Update product |
DELETE |
/api/products/{id} |
π Merchant | Delete product |
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/api/cart/{customerId} |
π Customer | Get customer cart |
POST |
/api/cart/{customerId}/items |
π Customer | Add item to cart |
DELETE |
/api/cart/{customerId}/items/{itemId} |
π Customer | Remove item from cart |
POST |
/api/orders |
π Customer | Create order |
GET |
/api/orders/{orderId} |
π Customer/Merchant | Get order details |
GET |
/api/orders/customer/{customerId} |
π Customer | List customer orders |
PUT |
/api/orders/{orderId}/status |
π Merchant | Update order status |
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/api/merchants/{id} |
Public | Get merchant details |
POST |
/api/merchants |
π Merchant | Register merchant |
GET |
/api/merchants/{merchantId}/products |
Public | List merchant products |
POST |
/api/merchants/{merchantId}/products |
π Merchant | Add product |
PUT |
/api/merchants/{merchantId}/products/{productId} |
π Merchant | Update product |
DELETE |
/api/merchants/{merchantId}/products/{productId} |
π Merchant | Delete product |
| Method | Path | Auth | Description |
|---|---|---|---|
POST |
/api/payments |
π Customer | Process payment (Stripe) |
GET |
/api/payments/{id} |
π Customer/Merchant | Get payment by ID |
GET |
/api/payments/order/{orderId} |
π Customer/Merchant | Get payment by order |
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/api/inventory/{productId} |
π Merchant | Get inventory item |
POST |
/api/inventory |
π Merchant | Create inventory item |
PUT |
/api/inventory/{productId} |
π Merchant | Update stock quantity |
GET |
/api/inventory/reservations/{orderId} |
π Customer/Merchant | Get reservations for order |
- .NET 10 / ASP.NET Core Minimal APIs
- .NET Aspire (orchestration, service discovery, observability)
- Entity Framework Core + PostgreSQL (per-service database)
- Apache Kafka (event streaming)
- Elasticsearch (product search)
- Duende IdentityServer (JWT authentication)
- Stripe SDK (payment processing)
- YARP (API Gateway reverse proxy)
- OpenTelemetry (distributed tracing & metrics)
- React 19 + TypeScript
- Vite
- Tailwind CSS 4
- React Router
- oidc-client-ts (OIDC authentication)
- Lucide React (icons)
UrbanX.Shared.Securityβ JWT authorization policies, input validation, global exception handlerUrbanX.ServiceDefaultsβ Aspire service defaults (health checks, telemetry, resilience)
urbanx-sample/
βββ src/
β βββ AppHost/
β β βββ UrbanX.AppHost/ # .NET Aspire orchestrator
β βββ ServiceDefaults/
β β βββ UrbanX.ServiceDefaults/ # Shared Aspire configuration
β βββ Services/
β β βββ Catalog/ # Product catalog (CQRS + Elasticsearch)
β β βββ Order/ # Cart, orders, saga coordinator
β β βββ Merchant/ # Merchant & product management
β β βββ Payment/ # Stripe payment processing
β β βββ Inventory/ # Stock reservation & management
β β βββ Identity/ # Duende IdentityServer
β βββ Gateway/
β β βββ UrbanX.Gateway/ # YARP reverse proxy + rate limiting
β βββ Frontend/
β β βββ urbanx-react/ # Customer-facing React SPA
β βββ Shared/
β βββ UrbanX.Shared/ # Shared domain models
β βββ UrbanX.Shared.Security/ # Security utilities
βββ tests/ # Unit and integration tests
βββ kubernetes/ # Kubernetes manifests
βββ docker-compose.yml # Infrastructure (PostgreSQL, Kafka)
βββ docker-compose.production.yml # Production Docker Compose
βββ generate-migrations.sh # EF Core migration helper script
βββ UrbanX.sln # Solution file
Run dotnet run from src/AppHost/UrbanX.AppHost to start everything. The Aspire Dashboard provides real-time logs, traces, and health status for all services.
dotnet test UrbanX.slnBoth unit and integration tests are provided for each service under the tests/ directory.
Migrations are applied automatically on service startup. To generate a new migration:
cd src/Services/<Service>/UrbanX.Services.<Service>
dotnet ef migrations add <MigrationName> --context <Service>DbContextSee DATABASE_MIGRATIONS.md for detailed guidance.
Copy .env.example to .env and fill in the required values (database passwords, Stripe keys, etc.) before running manually.
- JWT bearer authentication on all sensitive endpoints
- Policy-based authorization (
CustomerOnly,MerchantOnly,CustomerOrMerchant) - Per-IP rate limiting in the API Gateway (100 req/min)
- Input validation on all write endpoints (
UrbanX.Shared.Security.RequestValidation) - Global exception handler with environment-aware error details
- Security headers (X-Content-Type-Options, X-Frame-Options, X-XSS-Protection, Referrer-Policy)
See SECURITY.md for production security guidance.
Docker and Kubernetes manifests are included:
# Production Docker Compose
docker-compose -f docker-compose.production.yml up -d
# Kubernetes
kubectl apply -f kubernetes/See PRODUCTION_DEPLOYMENT.md for a full deployment guide.
MIT