ConstruCredit
From a credit application to the last payment.
ConstruCredit lends to families building their homes in Colombia. I build the software behind the public application site and the internal tools staff use to manage credit, clients, and payments.

- Role
- Sole developer, client work
- Year
- 2026
- Platform
- Web platform
- Status
- live
The problem
The public application and the staff’s credit records need to agree. A balance also depends on rounding rules, payment dates, and Colombian holidays. Those rules have to stay consistent across the site, the panel, and scheduled jobs.
What I built
A live platform covering applications, clients, payments, reports, notifications, and audit records. The public site runs on Vercel; the API and background work run on Google Cloud.
Inside the product.
Screens from the working product, with demonstration data.
Client portfolio
Staff can filter clients by credit line, advisor, and status, then inspect balances and days overdue.
Scroll sideways to inspect the interface.
Collections queue
Upcoming installments, late payments, and overdue credit have separate queues for follow-up.
Scroll sideways to inspect the interface.
The choices behind it.
As the sole developer, I built the public site, staff panel, API, background worker, and shared financial rules. The work includes access control, database changes, testing, and deployment.
Keep money and dates in one place
Shared domain packages own exact peso arithmetic, amortization, and the Colombian business calendar. Screens and jobs use those rules rather than calculating balances separately.
Give each role the right view
The staff panel filters access by role. Administrator access requires two-factor login, and provisional passwords must be changed on first use with server-side enforcement.
Make financial changes traceable
The platform keeps audit records and versions database changes. Tests for financial rules and a separate integration database protect the parts that alter credit and payment records.

From start to finish.
- Apply
A family reads the credit lines and sends an application through the public site.
- Manage credit
Authorized staff work with applications, clients, and credit records in the panel.
- Record and follow up
Payment records, reports, audit history, and scheduled notifications support the account.
- applications in the platform
- 4
- shared financial rule packages
- 3
- required for administrator access
- 2FA
Under the surface.
Public site
Credit information and the application flow for families.
Staff panel
Applications, clients, payments, reports, and audit views with role-based access.
API
The authenticated HTTP layer over credit, payment, client, and user records.
Background worker
Scheduled tasks and WhatsApp notifications.
Build details Stack, scope, and implementation
Built with
- TypeScript
- Next.js
- React
- Node
- PostgreSQL
- Drizzle ORM
- Zod
- Turborepo
- pnpm
- Vitest
- Tailwind CSS
- Vercel
- Google Cloud Run
- WhatsApp notifications
Areas
- fintech
- microcredit
- client work
- monorepo
- PostgreSQL
- role-based access
Problem context
A lender running on spreadsheets and WhatsApp can survive a hundred clients. It cannot survive a thousand. The arithmetic drifts, nobody can say who approved what, and every question about a balance costs an afternoon.
More about the project
ConstruCredit lends to families building their own homes in Colombia, one wall at a time. I build the software the whole business runs on.
There are two faces to it. The public site is where a family picks a credit line and applies. Behind it sits the panel the staff live in: applications, clients, payments, notifications, reports, administration and audit, each screen filtered to what that person's role may see.
Under both sits the part that has to be right. The amortization engine works over outstanding balance and the Colombian business calendar, so a payment landing on a holiday behaves the way the business says it should. The three packages that do the arithmetic are pinned at 100% line and function coverage, and the integration tests run against a real Postgres they refuse to touch unless its name marks it as the test one.
The schema is 36 tables across 61 versioned migrations, 56 of them shipped with the file that rolls them back. Site and panel deploy on Vercel, the API runs on Cloud Run, and a worker handles WhatsApp notifications and scheduled jobs.
Closed source, so this page links the live site instead of a repo.
Implementation notes
- The arithmetic is pinned at 100%. Coverage thresholds hold dominio, dinero and calendario at 100% lines and functions with autoUpdate: false, so the number never lowers itself to match a bad day. Last full run: 2,289 tests across 132 files, with dominio and dinero at 100% on lines, functions and branches.
- Pesos are exact. packages/dinero models money as its own type, so rounding is a decision the code makes on purpose.
- Dates answer to the Colombian calendar. packages/calendario carries the country's holidays, so due dates and late interest land where the business says they land.
- 61 migrations, 56 with a reverse. Most schema changes ship beside the file that undoes them, and the row-level security policies are versioned the same way.
- The panel is gated per role. Two-factor login required for the administrator role, provisional passwords rotated on first use and enforced server-side, and navigation filtered to the signed-in role across all seven modules.
- The test database cannot be the real one. The integration suite truncates tables, so it refuses to start unless the connection string names a test database. Four Vitest projects keep unit and integration runs from masking each other.
Build figures
- 36 tables
- 61 versioned migrations
- 2,289 tests passing
- 121 PRs merged in 19 days
- 4 apps · 8 shared packages
Parts of the project
- web app
- The public site where a family reads the three credit lines and applies.
- panel app
- The internal system the staff works in: applications, clients, payments, notifications, reports, administration and audit, filtered per role.
- api service
- The HTTP layer over clients, credits, payments, parameters, users and authentication, running on Cloud Run.
- worker worker
- Scheduled jobs and the WhatsApp notification lane.
- dominio library
- The calculation engine: amortization over outstanding balance, late interest, balances. No IO, and CI holds it at 100% coverage.
- dinero library
- Exact peso arithmetic as its own type, so rounding never happens by accident.
- calendario library
- The Colombian business calendar the due dates and late interest are computed against.
- db library
- Schema, versioned migrations with their reverse files, and the row-level security policies.

