Case Study · Real Estate
Team Alord, from Excel to a custom ERP platform in production
Team Alord is a land sales business with financed credit portfolios that ran its entire operation on Excel. We built a custom ERP web platform with per-lot payment tracking, delinquency alerts, expense control, and automated reports. The system now runs in production as a multi-user system with real data. Here's how.
What was the problem?
Team Alord sells land with direct financing, clients sign a monthly payment plan and Alord manages the portfolio. When they came to us, that entire operation lived in multiple uncoordinated Excel sheets: one file per project, separate tabs for clients, payments, and collections, and a different copy on the computer of each team member who needed access.
The symptoms were predictable: zero real-time visibility into delinquency, manual (or nonexistent) alerts when a client missed a payment, no traceability between payments and lots, discrepancies between what the owner saw and what the operator recorded, and constant risk of losing money from late follow-up. When a buyer called to ask how much they owed, the team had to open today's Excel, cross-reference, and send a screenshot over WhatsApp, hopefully with the right number.
What did we consider before building?
We checked SaaS options first because they're almost always the correct default when they exist: Odoo (modular ERP), Siigo, Alegra, property management platforms. None fit well with the specific operation of selling land with direct financing: generic ERPs handle accounts receivable but don't model them per lot; real-estate platforms assume rentals, not financed sales; and forcing a generic SaaS meant months of configuration + permanent monthly rent + decisions we couldn't later change.
The critical question was: how many specific modules will this operation have in the next two years? The answer was "several", lots + portfolio yes, but also unified financial control, heavy machinery rentals, and document management. That size + that level of specificity pointed toward custom. A custom system costs more upfront but scales without friction and the code is yours.
How did we design the solution?
The architecture is a Next.js 14 (App Router) application backed by PostgreSQL via Prisma, deployed as a Docker container managed by Coolify on our own VPS. Structured in modules that share database and authentication but are functionally independent:
- Lots (lots + portfolio), CRUD for lots with statuses (available, sold cash, sold financed, reserved), buyer registry, payment schedules (monthly/biweekly), per-lot payment tracking, automatic delinquency detection.
- Finance, unified income and expense ledger. Payments logged in the lots module automatically create income entries here; business expenses (payroll, utilities, maintenance) are recorded with per-category budgets and recurrence.
- Machinery, rental equipment inventory with statuses, rental contracts, preventive and corrective maintenance records. Rental payments auto-reconcile with the finance ledger.
- Documents, polymorphic manager that lets you upload any file and associate it to an entity (lot, buyer, rental, equipment, payment). A single search point for "the PDF that so-and-so signed in March".
All modules share three user roles: admin (views and edits everything), operator (logs daily transactions but doesn't configure), and shareholder (read-only on key indicators). Menus and views adapt to the role automatically.
What stack did we use and why?
- Next.js 14 App Router, Server Components for data fetching without ceremony, Server Actions for all mutations (atomic forms without an intermediate REST API). Enormously reduces the amount of glue code between frontend and database.
- Prisma ORM + PostgreSQL 16, Prisma because end-to-end typing between schema, queries, and TypeScript eliminates a whole class of bugs. PostgreSQL because it's the most reliable transactional database and more than enough at this size.
- NextAuth v5, authentication with three roles (admin, operator, shareholder), JWT sessions, role-adapted sidebar. No dependency on Auth0 or external services.
- shadcn/ui + Tailwind, accessible, consistent components 100% under our control (it's not a library, it's files you copy into your repo). TanStack Table for data grids, Recharts for dashboards.
- Tesseract.js, server-side Spanish OCR so operators can upload photos of receipts and auto-extract amounts/dates. Eliminates manual data entry day-to-day.
- Installable PWA, field team can install the app on mobile as if native. Works offline for basic reads.
- Docker + Coolify + VPS (Hetzner), a multi-stage container, automatic deploys from GitHub, SSL via Let's Encrypt, full hosting control. Fixed monthly cost, no surprises.
What results did we deliver?
The system went from prototype to production with real data in a few weeks. Concrete outcomes:
- Credit portfolio organized and accessible in real time, anyone with permission sees the status of any lot in seconds
- Automatic delinquency alerts, the system flags overdue payments without human intervention
- Zero manual payment chasing, collection management no longer depends on remembering who to call today
- Multi-module operational visibility, the owner sees income, expenses, portfolio, and machinery on one live panel
- Multi-user system in production with three roles, each with its own view of the information
- Real data imported from existing Excel files with no loss of history
As important as what we built is what we stopped having: discrepancies between Excel copies, contradictory versions on different computers, and the constant anxiety of "is this number the right one?".
What did we learn?
Three reflections from this project we apply to every custom ERP since:
1. Modules should share a database but not couple in code. Lots, finance, machinery, and documents live in the same Postgres, but each has its own server actions, its own views, and its own business logic. This lets us add a new module without rewriting the existing ones, when the client asks "can we now manage X?", the answer is "yes, in two weeks", not "we'd have to redesign everything".
2. Server Actions are the correct pattern for internal ERPs. You don't need a separate REST API if your users are authenticated employees using a modern browser. Server Actions eliminate an entire layer of code (endpoints, fetch handlers, serialization) and keep mutations close to the business logic.
3. Data migration from Excel is the most delicate part. Writing the software is straightforward; importing the client's real data without losing history or corrupting references requires careful scripts, manual validation, and an honest conversation with the client about which data was broken from the start. Planning this phase explicitly from day one avoids surprises.
Is your operation trapped in Excel?
If your business tracks receivables, inventory, payments, or clients across spreadsheets nobody cross-references, there's a custom solution that fits your budget. Let's talk 10 minutes, no strings.
Tell us your problem