Copiados Norte
A landing page, a back office and a client ordering app for a print and errands shop in Villa Gesell.

The shop does copies, ANSES and AFIP paperwork, tax payments and stationery. Orders, appointments, stock, printers and cash each need tracking. Customers need a way to order and get a price without calling. The owner needs numbers the counter staff should not see.
Three decisions that shaped it.
- 01
One core package for prices, types and state machines
Why. The landing quote, the counter POS and the client app read the same price table. An order moves through one defined flow everywhere.
Trade-off. Shared code is not shared data. With no backend, the client app keeps its own copy of the seed and its orders never reach the back office.
- 02
A single reducer, saved to a versioned localStorage key
Why. Every back office action goes through one reducer, so swapping in a database only changes where data comes from. Saved state is read after mount to avoid hydration errors.
Trade-off. Each browser holds its own data. Bumping the key version throws away what was saved before.
- 03
The monthly report is printable HTML, not a PDF library
Why. Three A4 pages styled with @page keep the brand fonts, vector text and the hatch patterns that make charts readable in black and white.
Trade-off. The PDF comes from the browser's print dialog. The owner has to pick "Save as PDF", and output can vary between browsers.




Copiados Norte
A landing page, a back office and a client ordering app for a print and errands shop in Villa Gesell.
- Role
- Sole developer: landing, back office, client app and shared core
- Stack
- Next.js 16, React 19, TypeScript, Tailwind CSS 4, Recharts, Expo

The shop does copies, ANSES and AFIP paperwork, tax payments and stationery. Orders, appointments, stock, printers and cash each need tracking. Customers need a way to order and get a price without calling. The owner needs numbers the counter staff should not see.
Three decisions that shaped it.
One core package for prices, types and state machines
Why. The landing quote, the counter POS and the client app read the same price table. An order moves through one defined flow everywhere.
Trade-off. Shared code is not shared data. With no backend, the client app keeps its own copy of the seed and its orders never reach the back office.
A single reducer, saved to a versioned localStorage key
Why. Every back office action goes through one reducer, so swapping in a database only changes where data comes from. Saved state is read after mount to avoid hydration errors.
Trade-off. Each browser holds its own data. Bumping the key version throws away what was saved before.
The monthly report is printable HTML, not a PDF library
Why. Three A4 pages styled with @page keep the brand fonts, vector text and the hatch patterns that make charts readable in black and white.
Trade-off. The PDF comes from the browser's print dialog. The owner has to pick "Save as PDF", and output can vary between browsers.



