NorteAR
Own product
Under construction · Next.js · TypeScript
Management system for service SMEs that measures real margin, not revenue.

See the full panel

The case, in six beats
01
Problem
A service business invoices well and by month's end there is nothing left. The system shows sales; what it does not show is how much stock was consumed to produce each of those sales — the tube of colour that yields a few applications, the product that was thrown out, the appointment that cost more than it charged.
Almost every management system measures what comes in. Very few measure what was spent so it could come in. And without that, "we sold more" and "we earned more" are the same sentence — until they stop being.
02
Decision
Margin is the headline metric, not one more report in a menu: it is the figure the system returns by default. If the main number is revenue, the user keeps looking at what they already looked at.
Services, not retail. A shop that resells knows its unit cost. A service business does not: stock is consumed in fractions and nobody writes them down. That is the gap.
Multi-tenant from the data model, not as a layer on top: every table filters by company. The alternative — one database per client — scales worse the moment you need to touch all of them at once, and here the business is precisely measuring and comparing, not isolating.
03
Mechanism
The hard problem is not accounting, it is modelling: how to know how much stock a service consumed if nobody weighs it. The answer was to tie each service to its supplies and draw down against real stock.
- Appointment
- Supplies
- Stock
- Margin
// Every service carries its supplies (serviceSupplies): what it consumes and // how much of each. Selling it draws down real stock, not an estimate. const consumptions = serviceItems.flatMap((item) => { const service = services.find((s) => s.id === item.serviceId)!; // quantityNeeded counts service uses; convert to base-unit stock consumption. return service.serviceSupplies.map((ss) => ({ supplyId: ss.supplyId, consumed: unitsPerUse(ss.packageContent, ss.servingsPerPackage) * Number(ss.quantityNeeded) * item.quantity, })); }); const stockDelta = new Map<string, number>(); for (const { supplyId, consumed } of consumptions) { stockDelta.set(supplyId, (stockDelta.get(supplyId) ?? 0) + consumed); }04
Trade-off
Loading the supplies is the user's work, and that work is the product's barrier to entry: without supplies loaded there is no margin, and with an empty system the value is invisible. Everything else is subordinate to lowering that initial cost.
What was left out on purpose: electronic invoicing (AFIP/ARCA does not exist in the schema), multi-branch and a native app. Narrow scope by decision, not by technical limit — the product is built for one kind of business, not for everyone.
05
Result
- Active businesses
- 2
- Trial → paid
- 2
- 3-month retention
- 2/2
- In production since
- Junio 2026
06
Afterwards
If I started over, I would not stretch the scope from day one. I kept adding complexity — multi-branch, roles, per-professional reports — for what, at this first stage, is a handful of known clients. That complexity costs development time that does not come back, and the product did not need it yet to prove it worked.