Nexora Supply Intelligence
Supply-chain analytics · Case study
Nexora Supply Intelligence
A faithful port of a supply-chain analytics platform from a Cloudflare edge stack to a self-hosted ASP.NET Core (.NET 10) API over PostgreSQL 18 — serving the same React frontend, with parity guaranteed by construction.
{ "ok": true, "data": { "kpis": [ { "metricId": "revenue", "value": 802343764, "previousValue": 966125736, "deltaPct": -0.1695, "sparkline": [ /* 12 buckets */ ] }, /* …29 more metrics */ ] }, "meta": { "generatedAt": "2026-…" } }
The brief
The original Nexora ran entirely on Cloudflare — a React frontend, Pages Functions in TypeScript, and a D1 (edge SQLite) database. The goal: move it to a self-hosted, portable stack that any team can run on their own infrastructure, without changing a single pixel of the frontend.
The constraint that shaped everything: parity by construction. Rather than hand-transcribing logic and hoping it matched, the port reuses the original's validated artifacts — the same metric definitions, the same deterministic data generator — so the new edition produces the same numbers as the old one, provably.
Architecture
The React build is served as static files straight from wwwroot; every /api/* call lands on an ASP.NET Core minimal API, which reads through Dapper and hand-written SQL against PostgreSQL. A domain layer holds the metric registry and KPI math.
| Concern | Original — Cloudflare | This edition |
|---|---|---|
| Frontend | React 18 · Vite · ECharts | same build, served from wwwroot |
| API | Pages Functions (TypeScript) | ASP.NET Core minimal API (.NET 10) |
| Data access | D1 SQL bindings | Dapper + hand-written SQL |
| Database | D1 — edge SQLite | PostgreSQL 18 |
| AI copilot | Workers AI binding | disabled — no edge binding off Cloudflare |
What's inside
One source of metric truth
Thirty metric definitions — formats, targets, status bands, direction — extracted verbatim from the original TypeScript registry into a single metrics.json, so definitions match exactly rather than being re-typed.
Dapper + hand-written SQL
No ORM guesswork — explicit SQL against PostgreSQL, with null-safe ratio math, ABC/XYZ segmentation, and alert-rule metadata ported into the domain layer.
Same generator, same rows
Seed data is emitted by the same validated TypeScript generator as the original, as PostgreSQL INSERTs. A deterministic RNG means the same rows as the D1 database — locked down by 21 xUnit parity tests.
Faithful API contract
Each route mirrors its Pages Functions counterpart — the same response envelope, filters, pagination, and cache + security headers / CSP — so the untouched React app can't tell the difference.
Data model & API surface
Four PostgreSQL migrations (translated from the SQLite schema) load a deterministic seed of ~62,000 rows across six tables. Dates are stored as ISO text and booleans as smallint 0/1, matching D1 for parity.
Ship it
Because it's self-contained, deployment doesn't depend on the host having a runtime installed — the whole thing travels as one artifact and points at a Postgres it can reach.
- LiveSelf-contained win-x64 build — the .NET 10 runtime is bundled, so it runs on shared Windows hosting regardless of installed frameworks.
- LiveDeployed to SmarterASP.NET over a remote PostgreSQL, with the connection string injected via configuration — no control-panel setup beyond the app pool.
- LiveVerified end-to-end — schema + ~62k-row seed loaded remotely, and every endpoint returns real data against the live database.
- NextRe-enable an AI copilot through a pluggable provider, restoring the natural-language query path the edge binding used to serve.
Nexora Consumer Products, Inc. is a fictitious company. All data is synthetic and generated for demonstration purposes only. Metrics, seed counts, and the API contract shown here reflect the actual build.