01
Admin dashboard
KPIs, 30/90-day charts from our own SVG component, distributor and KAM rankings and alerts. Each panel is its own TanStack Query; reports sit in a multi-level Redis cache.
Case study · 04 / 09
B2B ordering & promotions platform
Order campaigns, point budgets, promotions, warehouse and ERP integrations for a manufacturer and its sales network — rebuilt from a legacy app on a strict, secure modern stack.
Manufacturer & its distribution network
FMCG · B2B sales
Web app (React SPA + API)
Rebuild, end to end
The product
Three roles share one platform. Admins run order campaigns with point budgets per key-account manager, promotions with distributor balances and vouchers, the warehouse and integrations. KAMs manage their distributors. Distributors order and join promotions — on desktop or phone.
Our part
We rewrote the old Laravel 9 + React 17 app from scratch: a React 19 + TypeScript (strict) SPA and a Laravel 13 pure-API backend in CQRS with domain models separated from Eloquent, architecture tests and PHPStan at max level.
Under the hood
Commands and queries go through a Tactician bus, domain models stay independent of the ORM, and Pest architecture tests stop layers from leaking into each other.
Access token only in memory, refresh token in an httpOnly cookie, and an axios interceptor that folds parallel 401s into a single refresh.
HMAC-SHA256 signed payloads, exponential backoff from 30 seconds to 6 hours over five attempts, a full delivery log, manual retry and secret rotation.
TOTP two-factor with recovery codes, time-boxed “log in as” for support with a required reason and audit trail, and an activity log that hides personal data by default.
The outcome
Inside the product
Demo data · click any screen to enlarge
01
KPIs, 30/90-day charts from our own SVG component, distributor and KAM rankings and alerts. Each panel is its own TanStack Query; reports sit in a multi-level Redis cache.
02
Status driven by a state machine — draft, active, finished, archived — with point budgets for each assigned KAM. The active tab lives in the URL and lifecycle actions refresh the cache by themselves.
03
Every delivery to the external ERP: HTTP code, attempts, full JSON payload and response, with manual retry and secret rotation. Signed with HMAC-SHA256 and retried with exponential backoff in the queue.
04
Domain events with actor, aggregate and description, loaded with cursor pagination. Personal data is hidden unless explicitly revealed, and CSV export runs as a background job.
05
Support impersonation needs a reason and a 1–240 minute lifetime. Sessions can be ended early, and the backend closes expired ones on its own.
06
Six TOTP boxes that jump between fields, handle backspace and pasting the whole code, with resend countdown and recovery codes — verified by Laravel Fortify.
07
Same app, different role: banners, featured promotion, KPIs and recent orders, collapsing to one column with a slide-out drawer menu.
Stack
Next case