KoulTn is a ready-to-launch food delivery platform designed for restaurants, customers, and delivery partners. It offers a modern ordering experience, secure payments, and real-time delivery tracking. The system is modular, so it can grow with your business, whether you start small or scale to multiple cities.
In simple terms, KoulTn is the digital backbone of a food delivery company: it connects customers to restaurants, takes orders, processes payments, and coordinates deliveries in one coherent system.
KoulTn is composed of independent services that each handle a specific business function (authentication, restaurant management, orders, payments, delivery). A central API Gateway is the single entry point for the frontend, and each service has its own database to keep data organized and secure.
Architecture Overview
- Next.js Frontend is the customer and staff interface (web app).
- API Gateway is the smart router that directs each request to the correct service.
- Microservices are specialized components, each responsible for one area of the business.
- PostgreSQL Databases keep data safe and isolated per service.
Communication Flow (Simple View)
Customer / Admin / Deliverer
|
v
Next.js Frontend
|
v
API Gateway (Spring Cloud Gateway)
|
|-- AuthService (users, roles, login)
|-- RestaurantManagement (restaurants, menus)
|-- OrderService (orders and order items)
|-- PaymentService (payments)
|-- DeliveryService (delivery status + tracking)
Ports (Default)
- Frontend:
3000 - API Gateway:
8080 - AuthService:
8081 - RestaurantManagement:
8082 - PaymentService:
8083 - DeliveryService:
8084 - OrderService:
8085
Architecture Diagram Add architecture image here.
Why Microservices? (Business-Friendly Explanation)
- Reliability: If one area has an issue (e.g., payments), other parts can still work.
- Scalability: As business grows, we can scale only the busiest services (like orders).
- Faster Development: Different teams can work in parallel without blocking each other.
- Flexibility: You can add features later (loyalty, promotions, etc.) without rewriting the whole system.
Intro: The frontend is the visual part of the platform where customers browse menus, place orders, and track deliveries. Admins and delivery partners also use it to manage their activities.
What it does (in plain language)
- Lets customers browse restaurants and menu items
- Creates and tracks orders
- Handles payments by card or cash on delivery
- Provides login for customers, admins, and delivery partners
- Shows delivery progress in real time
Base URL
http://localhost:3000
Environment Variables
| Variable | Description |
|---|---|
NEXT_PUBLIC_API_BASE_URL |
API Gateway base URL (default: http://localhost:8080) |
NEXT_PUBLIC_APP_URL |
Frontend base URL (default: http://localhost:3000) |
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY |
Stripe publishable key (pk_test_...) for card tokenization |
User Experience Flow (Simple)
- User opens the app
- Logs in or registers
- Browses restaurants and menu items
- Adds items to cart and proceeds to checkout
- Fills in delivery information and selects a payment method (card or cash on delivery)
- If paying by card: card details are tokenized in the browser by Stripe.js and sent securely to the backend
- Order is created and payment is processed
- Confirmation page shows order status and payment result
- Follows delivery status
Intro: The gateway is like the receptionist of the platform. It receives all requests from the frontend and sends them to the correct service.
Architecture
- Spring Cloud Gateway (MVC)
- Centralized routing
- CORS handling for frontend access
Base URL
http://localhost:8080
Routes
| Path Prefix | Target Service | Purpose |
|---|---|---|
/api/v1/** |
AuthService | Login, register, user management |
/api/restaurants/** |
RestaurantManagement | Restaurants CRUD |
/api/categories/** |
RestaurantManagement | Categories CRUD |
/api/menu-items/** |
RestaurantManagement | Menu items CRUD |
/orders/** |
OrderService | Orders CRUD + payment status |
/api/payments/** |
PaymentService (REST) | Payment records |
/payment-ui/** |
PaymentService (UI) | Payment UI for tests |
/api/deliveries/** |
DeliveryService | Delivery tracking |
Architecture Diagram Add gateway routing image here.
Intro: AuthService manages who can log in, and what role they have (admin, customer, or delivery partner).
Architecture
- Spring Security + JWT
- PostgreSQL database
- Roles:
ADMIN,CLIENT,DELIVERER
Base URL (via Gateway)
http://localhost:8080/api/v1
Endpoints (Organized & Simple)
| Method | Endpoint | Description | Body Example |
|---|---|---|---|
| POST | /auth/register |
Register new user | { "firstname": "Admin", "lastname": "User", "email": "admin@kool.tn", "password": "admin123!", "roles": "ADMIN" } |
| POST | /auth/authenticate |
Login user | { "email": "admin@kool.tn", "password": "admin123!" } |
Architecture Diagram Add AuthService image here.
Intro: RestaurantManagement stores restaurants, their categories, and their menu items.
Architecture
- Spring Data JPA
- PostgreSQL database
Base URL (via Gateway)
http://localhost:8080/api
Endpoints
| Method | Endpoint | Description | Body Example |
|---|---|---|---|
| GET | /restaurants |
List restaurants | - |
| GET | /restaurants/{id} |
Get restaurant | - |
| POST | /restaurants |
Create restaurant | { "name": "Fast Bites", "email": "contact@fastbites.tn" } |
| PUT | /restaurants/{id} |
Update restaurant | { "name": "Fast Bites 2", "email": "contact@fastbites.tn" } |
| DELETE | /restaurants/{id} |
Delete restaurant | - |
| GET | /categories |
List categories | - |
| POST | /categories |
Create category | { "name": "Burgers" } |
| PUT | /categories/{id} |
Update category | { "name": "Pizza" } |
| DELETE | /categories/{id} |
Delete category | - |
| GET | /menu-items |
List menu items | - |
| GET | /menu-items/{id} |
Get menu item | - |
| POST | /menu-items |
Create menu item | { "name": "Cheese Burger", "description": "Double cheese", "price": 12.50, "categoryId": 1, "restaurantId": 1 } |
| PUT | /menu-items/{id} |
Update menu item | { "name": "Cheese Burger XL", "description": "Extra cheese", "price": 15.00, "categoryId": 1, "restaurantId": 1 } |
| DELETE | /menu-items/{id} |
Delete menu item | - |
Architecture Diagram Add RestaurantManagement image here.
Intro: OrderService manages customer orders and calculates total price using the selected menu items.
Architecture
- Spring Data JPA
- PostgreSQL database
- Total price is calculated dynamically for accuracy
Base URL (via Gateway)
http://localhost:8080/orders
Endpoints
| Method | Endpoint | Description | Body Example |
|---|---|---|---|
| POST | / |
Create order | { "restaurantId": 1, "userId": 1, "items": [{ "menuItemIds": [1, 2] }] } |
| GET | /{id} |
Get order by ID | - |
| GET | / |
List orders | - |
| PATCH | /{id}/payment-status |
Update payment status | { "paymentStatus": "PAID" } |
Architecture Diagram Add OrderService image here.
Intro: PaymentService handles payments and stores payment records linked to orders. Card payments use Stripe's Charges API: the frontend tokenizes the card via Stripe.js, and the backend uses that token to charge the card without ever handling raw card numbers.
Architecture
- Stripe API integration (Charges API with token)
- PostgreSQL database
- REST API + optional UI
Stripe Payment Flow
Frontend (Stripe.js)
|
| 1. Collect card details securely (CardNumberElement, CardExpiryElement, CardCvcElement)
| 2. stripe.createToken() → Stripe returns a short-lived token (e.g. tok_visa)
v
API Gateway → PaymentService
|
| 3. POST /api/payments with { orderId, userId, amount, currency, email, token }
| 4. PaymentService calls Stripe API to create a charge using the token
| 5. Stores result (SUCCEEDED / FAILED) in database
v
OrderService
| 6. PATCH /orders/{id}/payment-status → { "paymentStatus": "PAID" }
Configuration
| Property | Description |
|---|---|
stripe.key.public |
Stripe publishable key (pk_test_...) |
stripe.key.secret |
Stripe secret key (sk_test_...) used to create charges |
Base URL (via Gateway)
http://localhost:8080/api/payments
Endpoints
| Method | Endpoint | Description | Body Example |
|---|---|---|---|
| POST | / |
Create payment charge | { "orderId": 1, "userId": 1, "amount": 12.50, "currency": "usd", "email": "client@koul.tn", "token": "tok_visa" } |
| GET | /{id} |
Get payment by ID | - |
| GET | /?orderId={orderId} |
Get payments by order | - |
Payment Status Values
| Status | Meaning |
|---|---|
PENDING |
Payment initiated but not yet confirmed |
SUCCEEDED |
Stripe charge successful |
FAILED |
Stripe charge failed |
UI
http://localhost:8080/payment-ui/
Architecture Diagram Add PaymentService image here.
Intro: DeliveryService tracks delivery status and live courier location.
Architecture
- Spring Data JPA
- PostgreSQL database
- Live tracking via location updates
Base URL (via Gateway)
http://localhost:8080/api/deliveries
Endpoints
| Method | Endpoint | Description | Body Example |
|---|---|---|---|
| POST | / |
Create delivery | { "userId": 1, "orderId": 1, "restaurantId": 1, "pickupLocation": "Fast Bites", "dropoffLocation": "Client Address" } |
| GET | /{id} |
Get delivery by ID | - |
| GET | / |
List deliveries (filters: userId, orderId, restaurantId, status) | - |
| PATCH | /{id}/status |
Update status | { "status": "IN_TRANSIT" } |
| PATCH | /{id}/location |
Update live location | { "latitude": 36.8065, "longitude": 10.1815 } |
Architecture Diagram Add DeliveryService image here.
- Java 17+
- Node.js 18+ with pnpm
- PostgreSQL (one database per service, or separate schemas)
- Docker + Docker Compose (optional, for one-command setup)
| Service | Default Database |
|---|---|
| AuthService | auth_db |
| RestaurantManagement | restaurant_db |
| OrderService | order_db |
| PaymentService | payment_db |
| DeliveryService | delivery_db |
Use Docker Compose to run all services + Postgres databases with one command.
docker compose -f /Users/iheb/Desktop/2ING-CCV1/Koul++/docker-compose.yml up -d --buildNotes
- The compose file spins up 5 separate Postgres containers (one per service DB).
- Frontend reads
NEXT_PUBLIC_API_BASE_URLfrom compose and points to the gateway. - PaymentService expects Stripe keys; set
STRIPE_KEY_PUBLICandSTRIPE_KEY_SECRETindocker-compose.yml.
Start services in this order (Gateway depends on nothing; services are independent):
1. Backend services (each in its own terminal)
# AuthService
cd AuthService && mvn spring-boot:run
# RestaurantManagement
cd RestaurantManagement && mvn spring-boot:run
# OrderService
cd OrderService && mvn spring-boot:run
# PaymentService (set your Stripe keys in application.properties first)
cd spring-boot-stripe-payment-integration && mvn spring-boot:run
# DeliveryService
cd DeliveryService && mvn spring-boot:run
# API Gateway
cd api-gateway && mvn spring-boot:run2. Frontend
cd Frontend
cp .env.local.example .env.local # then fill in your values
pnpm install
pnpm devFrontend (.env.local)
NEXT_PUBLIC_API_BASE_URL=http://localhost:8080
NEXT_PUBLIC_APP_URL=http://localhost:3000
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_...
PaymentService (application.properties)
stripe.key.public=pk_test_...
stripe.key.secret=sk_test_...
Stripe keys: Get your test keys from dashboard.stripe.com/test/apikeys. Use test card
4242 4242 4242 4242, any future expiry, and any 3-digit CVC to simulate a successful payment.
- Business-ready: Covers the full workflow from menu browsing to delivery tracking.
- Scalable: Grow by scaling only the busiest components.
- Secure: JWT-based authentication and clear role separation.
- Maintainable: Each service is isolated, reducing complexity.
- Extensible: Easy to add new features like promotions or loyalty programs.
KoulTn is a complete, modular, and scalable food delivery solution designed for real business use. It provides the foundation for a full delivery operation, with flexibility to customize, expand, and brand as needed.