Skip to content

Repository files navigation

Kahawa Connect POS

Kahawa Connect POS is an Expo SDK 56 React Native app for running a small cafe workflow. It includes a cashier POS screen, order queue, inventory tracking, simulated M-Pesa payment handling, sales ledger, and a local Node backend API backed by SQLite.

The project is currently best understood as a functional prototype: it has working frontend screens and a backend with persisted local SQLite state, but it is not yet production-ready because it does not include authentication, a real database, real M-Pesa Daraja integration, or deployment configuration.

Project Status

Area Status Notes
Expo app Working prototype Runs through Expo Router on mobile and web
POS screen Working prototype Menu, cart, checkout, payment method selection
Operations screen Working prototype Order queue, status updates, inventory, sales view
Backend API Working local backend Node HTTP server backed by SQLite
Persistence SQLite database Uses backend/kahawa.sqlite; suitable for development and stronger than JSON, but still needs production hardening
M-Pesa Simulated Confirms with mock PIN flow and generated receipt code
Tests Not implemented TypeScript validation works, but no test suite exists
Production readiness Not ready Needs auth, DB, real payments, logging, deployment, CI

Tech Stack

  • Expo SDK 56
  • React 19
  • React Native 0.85
  • Expo Router
  • TypeScript strict mode
  • Node.js backend using built-in http, path, and node:sqlite
  • SQLite persistence

Important Expo note: this project follows the local instruction in AGENTS.md to reference Expo SDK 56 documentation before code changes.

Directory Overview

.
├── app.json
├── package.json
├── README.md
├── backend/
│   ├── README.md
│   └── server.js
├── src/
│   ├── app/
│   │   ├── _layout.tsx
│   │   ├── index.tsx
│   │   └── explore.tsx
│   ├── components/
│   ├── constants/
│   ├── hooks/
│   ├── services/
│   │   └── kahawaApi.ts
│   └── store/
│       └── kahawaStore.tsx
└── assets/

Main App Flow

The app models this cafe workflow:

  1. Cashier opens the POS screen.
  2. Cashier selects menu items.
  3. Items are added to the cart.
  4. Cashier enters customer details.
  5. Cashier selects payment method: M-Pesa, Cash, or Card.
  6. Checkout creates an order.
  7. Inventory is reserved or deducted depending on payment type.
  8. Operations staff move orders through the kitchen queue.
  9. Served orders appear in the ledger and sales report.

Frontend Screens

POS Cashier

File: src/app/index.tsx

The POS screen includes:

  • category filtering: All, Coffee, Tea & Dawa, Snacks
  • menu cards with stock availability labels
  • cart quantity controls
  • customer name input
  • item customization input
  • payment selector
  • cash amount and change calculation
  • checkout action

This screen currently still uses the local React context state. A typed backend API client exists in src/services/kahawaApi.ts, but the frontend has not yet been fully migrated from local context to API-driven state.

Operations

File: src/app/explore.tsx

The operations screen includes:

  • active order queue
  • order status actions
  • completed order history
  • sales summary
  • inventory management
  • restock inputs
  • transaction ledger

Order statuses are:

Pending Payment
Brewing
Ready
Served
Cancelled

State And Business Logic

Current Frontend State

File: src/store/kahawaStore.tsx

The original app state is stored in a React context provider. It contains:

  • menu data
  • inventory data
  • current cart
  • order history
  • mock M-Pesa state
  • cart operations
  • checkout logic
  • inventory deduction
  • restocking logic

This frontend store is useful for demo behavior, but it is not reliable enough for a real POS because data resets on reload and business rules are enforced only on the client.

Backend State

File: backend/server.js

The backend adds server-side business logic and SQLite persistence. It stores data in:

backend/kahawa.sqlite

That database file is created automatically when the API first starts. The backend uses Node 22 built-in node:sqlite, so it does not require Express or an external SQLite package. Node currently labels node:sqlite as experimental, so production work should either pin an appropriate Node runtime or move to a mature database driver.

Backend API

Run the backend:

npm run api

Default base URL:

http://localhost:4000/api

You can override the port:

PORT=4010 npm run api

You can override the data file:

KAHAWA_DB_FILE=/tmp/kahawa.sqlite npm run api

Endpoints

Method Endpoint Purpose
GET /api/health Check whether the API is running
GET /api/menu Return menu items
GET /api/inventory Return inventory with available, reserved, and low fields
PATCH /api/inventory/:id/restock Add stock to one inventory item
POST /api/orders Create an order
GET /api/orders List orders; supports status, from, and to filters
GET /api/orders/:id Get one order
PATCH /api/orders/:id/status Update order status
POST /api/payments/mpesa/:id/confirm Confirm a pending M-Pesa order
POST /api/payments/mpesa/:id/cancel Cancel a pending M-Pesa order
GET /api/ledger Return served orders only
GET /api/reports/sales Return sales totals and totals by payment method

Backend Business Rules

The backend corrects several important flaws from the original frontend-only logic:

  • order IDs are generated from a persisted counter
  • cash checkout records cashPaid and changeDue
  • customizations are stored in order items
  • M-Pesa orders reserve inventory first
  • M-Pesa confirmation deducts reserved inventory
  • cancelling pending M-Pesa orders releases reserved inventory
  • cancelling deducted orders restores inventory
  • finalized orders cannot be changed
  • Served orders are the only orders counted in the ledger and sales report
  • reports support from and to date filters

Valid status movement:

Pending Payment -> Brewing -> Ready -> Served
Pending Payment -> Cancelled
Brewing -> Cancelled
Ready -> Cancelled

The backend blocks invalid transitions such as serving an order before it is ready or brewing an M-Pesa order before payment confirmation.

Frontend API Client

File: src/services/kahawaApi.ts

This file maps frontend actions to backend endpoints. It exports kahawaApi with methods such as:

  • getMenu()
  • getInventory()
  • createOrder()
  • getOrders()
  • updateOrderStatus()
  • confirmMpesaPayment()
  • cancelMpesaPayment()
  • getLedger()
  • getSalesReport()

Default API URL:

http://localhost:4000/api

For Expo, set this environment variable if needed:

EXPO_PUBLIC_KAHAWA_API_URL=http://localhost:4000/api

For Android emulator, localhost from the app may not point to your machine. You may need:

http://10.0.2.2:4000/api

For a physical phone, use your computer's LAN IP address.

Running The Project

Install dependencies:

npm install

Start the backend:

npm run api

Start Expo in a second terminal:

npm run start

Run web:

npm run web

Run Android:

npm run android

Run iOS:

npm run ios

Validate TypeScript:

npx tsc --noEmit

Check backend syntax:

node --check backend/server.js

Workability Assessment

What Works Now

  • Expo app structure is valid.
  • The app has clear POS and operations screens.
  • Menu, inventory, orders, and payments are modeled coherently.
  • The local backend starts successfully with npm run api.
  • API endpoints support the key POS workflows.
  • Backend inventory handling is more correct than the original frontend-only logic.
  • The backend can persist local state across restarts using backend/data.json.
  • TypeScript validation passes.

What Partly Works

  • The frontend still primarily uses KahawaProvider local state.
  • The backend API client exists, but the UI has not yet been fully wired to call it.
  • M-Pesa behavior is realistic as a simulation, but not real payment processing.
  • Card payment exists as a payment method, but there is no card authorization flow.
  • Sales reports are available through the backend, but the frontend screen still computes some values locally.

What Does Not Exist Yet

  • real Safaricom Daraja integration
  • authentication and roles
  • user accounts
  • server-side sessions
  • audit log table
  • receipt printing
  • offline sync
  • CI pipeline
  • automated tests
  • production deployment setup

Main Remaining Flaws

  1. Frontend is not fully API-driven yet.

    The app has a backend and API client, but the existing screens still read from local context. The next important step is to replace local store actions with API calls and refresh server state after mutations.

  2. Persistence now uses SQLite.

    This is a real database and is a major improvement over JSON persistence. For a multi-terminal production POS, PostgreSQL or another client/server database is still preferable.

  3. M-Pesa is simulated.

    The current flow confirms a 4-digit PIN locally and generates a fake receipt code. A real implementation needs Safaricom Daraja STK Push, callback handling, transaction reconciliation, retries, and failure states.

  4. No authentication.

    Any client can call any endpoint. Production needs user login, role-based permissions, and endpoint authorization.

  5. No automated tests.

    The backend business rules should be tested, especially inventory deduction, reservation, cancellation, and order status transitions.

  6. No concurrency protection.

    The JSON backend is not safe for multiple simultaneous cashiers. A real database transaction should protect inventory and order writes.

  7. No production logging or monitoring.

    The backend returns API errors, but it does not yet have structured logs, request IDs, metrics, or alerting.

Recommended Next Steps

  1. Wire src/services/kahawaApi.ts into KahawaProvider or replace the provider with API-backed state.
  2. Add loading and error states in both screens.
  3. Add backend tests for checkout, stock, cancellation, reports, and status transitions.
  4. Add migration tooling and consider PostgreSQL for multi-device production use.
  5. Add authentication and staff roles.
  6. Add real M-Pesa Daraja integration.
  7. Add a .env.example file for API configuration.
  8. Add CI checks for TypeScript, linting, and backend tests.

Production Readiness Summary

This project is viable as a prototype and learning project. It now has enough backend logic to map the main app actions to real endpoints and enforce the most important business rules on the server.

It is not yet viable as a real cafe POS until the frontend is connected to the backend, database migrations/backups are formalized, payment integration is real, and authentication plus tests are added.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages