POS System Architecture

Multi-store retail point-of-sale — Complete structure map

6
Apps
9
Packages
22
HQ Modules
18
Store Modules
40
DB Tables
1017
Tests
12
Containers

System Overview

High-level architecture showing all apps, servers, databases, and connections

Internet / Traefik
Reverse proxy + SSL termination
HQ Web App
hq.pos.eddieadiaz.com
Vue 3 PWA (shared build)
Store 1 Web
tienda1.pos.eddieadiaz.com
Vue 3 PWA (shared build)
Store 2 Web
tienda2.pos.eddieadiaz.com
Vue 3 PWA (shared build)
HQ Manager
Tauri Desktop
Store Manager
Tauri Desktop
POS Terminal
Tauri Desktop
HQ Server
Fastify · Port 3000
22 modules · WebSocket hub
WebSocket Sync
+ HTTP Pull/Push
Store Servers
Fastify · Port 3002
18 modules · Sync client
HQ PostgreSQL
pos_hq · Port 5434
40 tables · Source of truth
Redis
Port 6379
Job queues (BullMQ)
Store 1 PostgreSQL
pos_store · Per-store DB
Store 2 PostgreSQL
pos_store · Per-store DB
Portal
pos.eddieadiaz.com
Docs
docs.pos.eddieadiaz.com
VitePress EN+ES
Tracking
tracking.pos.eddieadiaz.com
Analysis
analysis.pos.eddieadiaz.com
Research
research.pos.eddieadiaz.com
Structure
structure.pos.eddieadiaz.com

Monorepo Structure

pnpm workspaces + Turborepo — click each section to expand

apps/hq-server/ TypeScript

Fastify API · Port 3000 · HQ Database
  • src/
    • modules/ — 22 route modules
      • auth/ customers/ departments/ inventory/ products/
      • purchase-orders/ registers/ reports/ roles/ sales/
      • sales-reps/ specials/ store-config/ store-prices/
      • stores/ suppliers/ sync/ taxes/ tenders/
      • transfers/ users/ worksheets/
    • db/
      • schema/ — 14 schema files (Drizzle ORM)
        • products.ts users.ts sales.ts sales-reps.ts inventory.ts
        • transfers.ts registers.ts stores.ts sync.ts audit.ts
        • tenders.ts customers.ts worksheets.ts index.ts
      • migrations/ — 15 SQL migrations
      • connection.ts seed.ts run-migrations.ts run-store-migrations.ts
    • lib/ — auth-guard.ts, config-registry.ts, permission-registry.ts
    • jobs/ — BullMQ job queues (index.ts, queues.ts)
    • websocket/ — WebSocket server (index.ts, server.ts)
    • __tests__/ — 373 tests across 25 test files
    • app.ts config.ts index.ts
  • Dockerfile drizzle.config.ts package.json tsconfig.json vitest.config.ts

apps/store-server/ TypeScript

Fastify API · Port 3002 · Store Database
  • src/
    • modules/ — 18 route modules
      • auth/ customers/ departments/ inventory/ products/
      • purchase-orders/ registers/ reports/ sales/ sales-reps/
      • specials/ store-config/ stores/ suppliers/ taxes/
      • tenders/ transfers/ users/
    • db/
      • schema/ — 13 schema files
        • products.ts users.ts sales.ts sales-reps.ts inventory.ts
        • transfers.ts registers.ts stores.ts sync.ts audit.ts
        • tenders.ts customers.ts index.ts
      • migrations/ — 7 SQL migrations
    • sync/ — outbox.ts, pull-service.ts, push-service.ts, sync-service.ts, ws-client.ts
    • lib/ — auth-guard.ts, config-registry.ts, store-config-helper.ts
    • __tests__/ — 185 tests across 22 test files
    • app.ts config.ts index.ts
  • Dockerfile drizzle.config.ts package.json tsconfig.json vitest.config.ts

apps/web-client/ Vue 3

PWA · Shared frontend (HQ + Store + POS)
  • src/
    • views/ — 7 root + 20 HQ + 12 store + 4 POS views
      • hq/ — 20 views
      • store/ — 12 views
      • pos/ — 4 views
      • AppSelectorView DashboardView InventoryView LoginView PosView StoresView UnauthorizedView
    • layouts/ — AppLayout, HqLayout, PosLayout, StoreLayout
    • stores/ — 11 Pinia stores
      • auth cart checkout dashboard inventory products purchaseOrders register reports stores sync
    • components/ — AppConfirmDialog, CrossStoreStockDialog, ReceiptDialog
    • composables/ — useBarcodeScanner, useConfirmDialog, useForceRefresh, useTheme, useVersionCheck
    • __tests__/ — 248 tests across 45 test files
    • App.vue main.ts router.ts config.ts modules/index.ts
  • index.html nginx.conf nginx-store.conf package.json vite.config.ts vitest.config.ts

apps/pos-terminal/ Vue Rust

Tauri Desktop · POS operations
  • src/ (Vue frontend)
    • features/ — auth/, register/, sales/, unauthorized/
    • stores/ — auth, cart, checkout, products, register, sync
    • composables/ — useBarcodeScanner
    • layouts/ — PosLayout
    • App.vue main.ts router.ts
  • src-tauri/ (Rust backend)
    • src/commands/ — auth, hardware, products, register, sales, sync
    • src/db/ — connection, queries
    • src/hardware/ — drawer, printer, receipt
    • src/sync/ — client, manager, websocket
    • lib.rs main.rs Cargo.toml tauri.conf.json

apps/store-manager/ Vue Rust

Tauri Desktop · Store management
  • src/ (Vue frontend)
    • features/ — auth/, dashboard/, employees/, inventory/, reports/, transfers/, unauthorized/
    • stores/ — auth, inventory, reports, sync, transfers
    • App.vue main.ts router.ts layouts/ManagerLayout
  • src-tauri/ (Rust backend)
    • src/commands/ — inventory, reports, sync, transfers
    • src/db/ — connection
    • src/sync/ — client, manager, websocket
    • lib.rs main.rs Cargo.toml tauri.conf.json

apps/hq-manager/ Vue Rust

Tauri Desktop · HQ management
  • src/ (Vue frontend)
    • features/ — auth/, dashboard/, departments/, products/, reports/, roles/, stores/, suppliers/, taxes/, unauthorized/, users/
    • stores/ — auth, departments, products, reports, suppliers, sync, taxes
    • App.vue main.ts router.ts layouts/HqLayout
  • src-tauri/ (Rust backend)
    • lib.rs main.rs Cargo.toml tauri.conf.json

packages/ TypeScript

9 shared packages
  • shared-types/ — TypeScript interfaces (product, user, sale, inventory, transfer, register, store, sync, audit, purchase-order, worksheet, api, module)
  • pos-logic/ — Shared Pinia stores (auth, cart, checkout, products, register, sync, dashboard, inventory, reports, stores, purchaseOrders) + composables (useBarcodeScanner, useTheme, useConfirmDialog) + config + modules
  • backend-adapter/ — Web HTTP / Tauri IPC adapter (setAdapter, getAdapter, createTauriAdapter, createWebAdapter)
  • rule-engine/ — Before/after hook framework (RuleEngine, BeforeHook, AfterHook, RuleContext, RuleResult)
  • tax-engine/ — Tax calculation (calculateLineTax, calculateSaleTax, compound tax support)
  • i18n/ — EN + ES translations via vue-i18n (messages, defaultLocale, supportedLocales)
  • ui-kit/ — PrimeVue theme + components (PosNumpad, PosMoneyDisplay, PosSyncStatus, PosSearchBar, posTheme)
  • event-bus/ — Typed event system (EventBus, PosEvents: 22 event types)
  • sync-protocol/ — Sync message types + receipt number generator (generateReceiptNumber, createSyncEnvelope)

tools/ · deploy/ · docs/

Scripts, configs, documentation
  • tools/
    • scripts/ — deploy.sh, deploy-web.sh, setup-dev.sh, validate-i18n.js
    • docker-init/ — hq-init.sql, store-init.sql
    • store-db-compose.yml
  • deploy/
    • hq/ — config.json
    • store1/ — config.json, nginx.conf
    • store2/ — config.json, nginx.conf
    • landing/ — index.html, nginx.conf
  • docs/ — VitePress (EN + ES), 40+ pages
    • en/ — getting-started, hq-manager, store-manager, pos-terminal, admin, developer
    • es/ — same structure in Spanish
  • docker-compose.prod.yml docker-compose.yml turbo.json tsconfig.base.json pnpm-workspace.yaml

Package Dependency Graph

Arrows show dependency direction: consumer ← dependency

shared-types
Core interfaces
↓ used by ↓
backend-adapter
Web / Tauri adapter
tax-engine
Tax calculation
sync-protocol
Sync messages
↓ used by ↓
pos-logic
Shared Pinia stores + composables
↓ used by ↓
web-client
Vue PWA
pos-terminal
Tauri POS
store-manager
Tauri Store
hq-manager
Tauri HQ
rule-engine
Before/after hooks
i18n
EN + ES translations
event-bus
Event system
ui-kit
PrimeVue components
rule-engine → hq-server, store-server   |   i18n, event-bus, ui-kit → all frontend apps

HQ Server Modules

22 Fastify route modules — all prefixed /api/v1/

auth /api/v1/auth

  • POST/login
  • POST/pin-login
  • POST/refresh
  • GET/me
  • POST/change-credential

products /api/v1/products

  • GET/ (list)
  • GET/:id
  • POST/ (create)
  • PUT/:id (update)
  • PATCH/:id/toggle-active
  • DEL/:id
  • GET/:productId/suppliers
  • POST/:productId/suppliers
  • PUT/:productId/suppliers/:supplierId
  • DEL/:productId/suppliers/:supplierId

departments /api/v1/departments

  • GET/ (list)
  • GET/:id
  • POST/ (create)
  • PUT/:id
  • DEL/:id

suppliers /api/v1/suppliers

  • GET/ (list)
  • GET/:id
  • POST/ (create)
  • PUT/:id
  • DEL/:id

taxes /api/v1/taxes

  • GET/ (rates list)
  • GET/:id
  • POST/ (create rate)
  • PUT/:id
  • DEL/:id
  • GET/groups
  • GET/groups/:id
  • POST/groups
  • PUT/groups/:id
  • DEL/groups/:id

users /api/v1/users

  • GET/ (list)
  • GET/:id
  • POST/ (create)
  • PUT/:id
  • DEL/:id
  • GET/:id/store-roles
  • PUT/:id/store-roles

roles /api/v1/roles

  • GET/ (list)
  • GET/:id
  • POST/ (create)
  • PUT/:id
  • DEL/:id
  • GET/:id/permissions
  • PUT/:id/permissions
  • GET/permissions/all

stores /api/v1/stores

  • GET/ (list)
  • GET/:id
  • POST/ (create)
  • PUT/:id
  • DEL/:id
  • POST/:id/provision
  • GET/dashboard

sales /api/v1/sales

  • GET/ (list)
  • GET/:id
  • POST/ (create sale)
  • POST/validate
  • POST/validate-action
  • PUT/:id/void

registers /api/v1/registers

  • GET/ (sessions list)
  • GET/:id
  • POST/ (open)
  • PUT/:id/close

inventory /api/v1/inventory

  • GET/ (stock levels)
  • GET/adjustments
  • GET/cross-store
  • POST/adjustments

transfers /api/v1/transfers

  • GET/ (list)
  • GET/:id
  • POST/ (create)
  • PATCH/:id/send
  • PATCH/:id/receive
  • PATCH/:id/cancel

tenders /api/v1/tenders

  • GET/ (list)
  • GET/:id
  • POST/ (create)
  • PUT/:id
  • DEL/:id

customers /api/v1/customers

  • GET/ (list)
  • GET/:id
  • POST/ (create)
  • PUT/:id
  • DEL/:id

reports /api/v1/reports

  • GET/sales-summary
  • GET/x-report
  • GET/z-report
  • GET/zz-report
  • GET/tax
  • GET/inventory-value
  • GET/product-performance
  • GET/sales-by-period
  • GET/sales-by-rep
  • GET/profit-margin
  • GET/cashier-performance
  • GET/department-sales
  • GET/inventory-turnover
  • GET/discount-analysis

specials /api/v1/specials

  • GET/ (list)
  • GET/active
  • GET/:id
  • POST/ (create)
  • PUT/:id
  • DEL/:id

purchase-orders /api/v1/purchase-orders

  • GET/ (list)
  • GET/:id
  • POST/ (create)
  • PUT/:id
  • POST/:id/items
  • PUT/:id/items/:itemId
  • DEL/:id/items/:itemId
  • PATCH/:id/submit
  • PATCH/:id/approve
  • PATCH/:id/send
  • PATCH/:id/receive
  • PATCH/:id/cancel
  • DEL/:id

worksheets /api/v1/worksheets

  • GET/ (list)
  • GET/:id
  • POST/ (create)
  • PUT/:id
  • DEL/:id
  • PATCH/:id/submit
  • PATCH/:id/approve
  • PATCH/:id/apply

sales-reps /api/v1/sales-reps

  • GET/ (list)
  • GET/:id
  • POST/ (create)
  • PUT/:id
  • PATCH/:id/toggle-active
  • DEL/:id

store-config /api/v1/store-config

  • GET/registry
  • GET/:storeId
  • PUT/:storeId

store-prices /api/v1/store-prices

  • GET/ (list)
  • PUT/ (bulk update)

sync /api/v1/sync

  • POST/pull
  • POST/push
  • GET/dashboard
  • GET/errors

Store Server Modules

18 Fastify route modules — subset of HQ, local data only

auth /api/v1/auth

  • POST/login
  • POST/pin-login
  • POST/refresh
  • GET/me
  • POST/change-credential

products /api/v1/products

  • GET/ (list with tax/specials)
  • GET/:id

departments /api/v1/departments

  • GET/ (read-only)

inventory /api/v1/inventory

  • GET/ (stock levels)
  • GET/adjustments
  • POST/adjustments

sales /api/v1/sales

  • GET/ (list)
  • GET/:id
  • POST/ (create)
  • POST/validate
  • POST/validate-action
  • PUT/:id/void

registers /api/v1/registers

  • GET/ · GET/:id
  • POST/ (open) · PUT/:id/close

reports /api/v1/reports

  • GET/sales-summary
  • GET/x-report · /z-report · /zz-report
  • GET/tax · /inventory-value
  • GET/product-performance · /sales-by-period
  • GET/cashier-performance · /department-sales
  • GET/discount-analysis

transfers /api/v1/transfers

  • GET/ · GET/:id
  • POST/ (create)
  • PATCH/:id/send · receive · cancel

purchase-orders /api/v1/purchase-orders

  • GET/ · /:id
  • POST/ · /:id/items
  • PUT/:id · /:id/items/:itemId
  • PATCHsubmit/approve/send/receive/cancel
  • DEL/:id · /:id/items/:itemId

customers /api/v1/customers

  • GET/ · /:id
  • POST/ · PUT/:id · DEL/:id

suppliers /api/v1/suppliers

  • GET/ · /:id (read-only)

taxes /api/v1/taxes

  • GET/ · /:id · /groups · /groups/:id (read-only)

tenders /api/v1/tenders

  • GET/ (read-only)

stores /api/v1/stores

  • GET/ · /current

users /api/v1/users

  • GET/ (read-only local users)

sales-reps /api/v1/sales-reps

  • GET/ · /:id (read-only)

specials /api/v1/specials

  • GET/active (read-only)

store-config /api/v1/store-config

  • GET/ (local config)
  • PUT/ (update local)

Database Schema Map

40 tables across HQ + Store databases, grouped by domain

Products Domain

productsproducts.ts
departmentsproducts.ts
tax_ratesproducts.ts
tax_groupsproducts.ts
tax_group_ratesproducts.ts
suppliersproducts.ts
product_suppliersproducts.ts
product_specialsproducts.ts

Sales Domain

salessales.ts
sale_itemssales.ts
sale_item_taxessales.ts
sale_paymentssales.ts

Users & Permissions Domain

usersusers.ts
permissionsusers.ts
rolesusers.ts
role_permissionsusers.ts
user_store_rolesusers.ts

Stores Domain

storesstores.ts
store_product_dynamicstores.ts
store_configstores.ts
purchase_ordersstores.ts
purchase_order_itemsstores.ts

Inventory Domain

inventoryinventory.ts
inventory_adjustmentsinventory.ts

Transfer Domain

transferstransfers.ts
transfer_itemstransfers.ts

Register Domain

register_sessionsregisters.ts
monthly_closingsregisters.ts (HQ only)

Sync Domain

sync_outboxsync.ts
sync_statussync.ts
sync_logsync.ts
sequencessync.ts

Other

customerscustomers.ts
sales_repssales-reps.ts
tenderstenders.ts
worksheetsworksheets.ts (HQ only)
worksheet_itemsworksheets.ts (HQ only)
worksheet_storesworksheets.ts (HQ only)
audit_logaudit.ts
Key Relationships
products → departments (departmentId) → departments (parentId, self-ref)
products → tax_groups (taxGroupId)
tax_group_rates → tax_groups + tax_rates
product_suppliers → products + suppliers
product_specials → products
sales → users (cashierId) + stores (storeId) + register_sessions (sessionId) + customers (customerId)
sale_items → sales + products + sales_reps
sale_item_taxes → sale_items + tax_rates
sale_payments → sales + tenders
inventory → products + stores
inventory_adjustments → products + stores + users
transfers → stores (fromStoreId, toStoreId) + users
transfer_items → transfers + products
store_product_dynamic → stores + products (per-store price/tax overrides)
store_config → stores
purchase_orders → stores + suppliers + users
purchase_order_items → purchase_orders + products
role_permissions → roles + permissions
user_store_roles → users + stores + roles
worksheets → users (createdBy/approvedBy)
worksheet_items → worksheets + products
worksheet_stores → worksheets + stores
sync_outbox → entity tracking (entityType, entityId)

Frontend Views Map

All Vue views organized by app and layout

Web Client HQ Layout

  • HqDashboardView
  • ProductsView
  • DepartmentsView
  • SuppliersView
  • TaxRatesView
  • TendersView
  • UsersView
  • RolesView
  • StoresView
  • HqReportsView
  • HqSalesView
  • SalesRepsView
  • SpecialsView
  • PurchaseOrdersView
  • PurchaseOrderDetailView
  • WorksheetsView
  • WorksheetDetailView
  • CustomersView
  • SyncView
  • StoreConfigView

Web Client Store Layout

  • DashboardView
  • StoreInventoryView
  • TransfersView
  • StoreReportsView
  • StoreSalesView
  • EmployeesView
  • CustomersView
  • SalesRepsView
  • PurchaseOrdersView
  • PurchaseOrderDetailView
  • StoreConfigView
  • RegisterSessionsView
  • SuppliersView

Web Client POS Layout

  • PosTerminalView
  • CheckoutView
  • JournalView
  • RegisterView

Web Client Root / App

  • LoginView
  • AppSelectorView
  • StoresView
  • InventoryView
  • PosView
  • UnauthorizedView

POS Terminal (Tauri) PosLayout

  • LoginView
  • POSView
  • CheckoutView
  • SaleView
  • RegisterOpenView
  • RegisterCloseView
  • UnauthorizedView

Store Manager (Tauri) ManagerLayout

  • LoginView
  • DashboardView
  • InventoryView
  • AdjustmentsLog
  • InventoryAdjustmentDialog
  • TransfersView
  • TransferDetailView
  • CreateTransferDialog
  • ReportsView
  • EmployeesView
  • UnauthorizedView

HQ Manager (Tauri) HqLayout

  • LoginView
  • DashboardView
  • ProductsView
  • ProductForm
  • DepartmentsView
  • DepartmentForm
  • SuppliersView
  • TaxesView
  • UsersView
  • RolesView
  • StoresView
  • ReportsView
  • UnauthorizedView

Shared Components ui-kit + web-client

  • PosNumpad
  • PosMoneyDisplay
  • PosSyncStatus
  • PosSearchBar
  • AppConfirmDialog
  • CrossStoreStockDialog
  • ReceiptDialog

Data Flow Diagrams

Key operational flows through the system

Sale Flow (POS Terminal or Web POS)
Scan/Search Product
addItem (cart store)
Apply Discount?
POST /validate-action
Start Checkout
POST /validate
Add Payments
POST /sales (create)
Deduct Inventory
Sync Outbox
Sync Flow (Store ↔ HQ)
Store Server boots
WebSocket connect to HQ
Authenticated (SYNC_TOKEN)
HQ entity changes
WS notification to stores
Store HTTP pull (/sync/pull)
Store creates sale/adjustment
sync_outbox insert
Push service (30s interval)
POST /sync/push to HQ
HQ processes + stores in DB
Rule Engine Flow (Before/After Hooks)
Module registers rules
Action triggered (e.g. sale.create)
runBefore(ctx)
Check allowed?
Execute action
runAfter(ctx)
Transfer Lifecycle
Create Transfer
DRAFT
SENT (deduct from source)
Sync to HQ → Notify dest
RECEIVED (add to dest)
Variance check
Purchase Order Lifecycle
Create PO
DRAFT
SUBMITTED
APPROVED
SENT to supplier
RECEIVED (add stock)
Authentication Flow
Username/Password or PIN
POST /auth/login or /pin-login
bcrypt verify
JWT token (access + refresh)
Load permissions via user_store_roles
Route guard + requirePermission()
Store Provisioning
HQ: Create Store
POST /:id/provision
Generate SYNC_TOKEN (JWT)
Set store_code, token_version
Deploy store-server + store-web
Initial sync pull

Infrastructure Map

Docker Compose production containers, ports, and domains

pos-hq-server

Internal: 3000
Fastify API. Depends on hq-postgres + redis.
Networks: pos-internal, coolify

pos-hq-postgres

Host: 5434 → Container: 5432
PostgreSQL 16. DB: pos_hq. User: pos_admin
Volume: hq-pgdata

pos-hq-web

hq.pos.eddieadiaz.com
Nginx serving web-client dist + HQ config.json

pos-store1-server

Internal: 3002
Store ST01 (Downtown). STORE_ID: da92c128...
Syncs to hq-server via WebSocket

pos-store1-postgres

Container: 5432 (no host port)
PostgreSQL 16. DB: pos_store. User: pos_store

pos-store1-web

tienda1.pos.eddieadiaz.com
Nginx + store1 config.json + store nginx.conf

pos-store2-server

Internal: 3002
Store ST02 (Mall). STORE_ID: 4a5f2b28...

pos-store2-postgres

Container: 5432 (no host port)
PostgreSQL 16. DB: pos_store. User: pos_store

pos-store2-web

tienda2.pos.eddieadiaz.com
Nginx + store2 config.json

pos-redis

Internal: 6379
Redis 7. BullMQ job queues. Volume: redis-data

pos-portal

pos.eddieadiaz.com
Landing page with links to all apps

pos-docs

docs.pos.eddieadiaz.com
VitePress docs (EN + ES)

pos-tracking

tracking.pos.eddieadiaz.com
Project tracking site

pos-analysis

analysis.pos.eddieadiaz.com
Codebase analysis site

pos-research

research.pos.eddieadiaz.com
Industry research site

Traefik (external)

Reverse proxy on Coolify network
HTTPS/SSL via Let's Encrypt. Routes by Host header.

Docker Networks

pos-internal — All servers + databases + Redis (isolated)
coolify — External network for Traefik routing (web + server containers)

Volumes

hq-pgdata
store1-pgdata
store2-pgdata
redis-data