A deadline, and a portal built in 2003
Last year a complicated family situation had me looking for a house in Colombia on a very tight deadline. I had just read a Wall Street Journal piece on fix and flip strategies and figured judicial auctions were the obvious entry point.
Then I opened the portals. Thousands of legal records scattered across 33 departments, every judicial branch with its own site, its own format and its own idea of what a date looks like. The information is public by law. Public is not the same as usable, and that gap is the entire product.
A data entry farm, and what it was leaving on the table
The Colombian market leader against its Chilean equivalent.
The competitive audit told the story fast. The biggest player in Colombia runs a manual data entry farm: people paid to read legal edicts in local newspapers and type posts into a CMS. The Chilean equivalent works a market a third of the size and pulls 120K monthly visits. The Colombian leader barely hits 17K.
Chile has a third of Colombia's population, so the incumbent here serves three times the people and captures a tenth of the traffic. Match Chilean penetration and the addressable number clears 300K unique monthly visits. At a conservative 2% sign up rate that was enough to keep going. Automate the brute force, undercut the incumbent's subscription, deliver cleaner data at a fraction of the operating cost.
Before touching a pixel I wrote a PRFAQ and a PRD, the same frameworks I used at Amazon for years. You can take the designer out of Amazon...
The PRD. Scope settled on paper while it was still cheap to change my mind.
Nobody needs another index
Every platform in this market publishes a list of what exists. That is the easy half, and it is where all of them stop. The investor still has to answer the expensive questions somewhere else: is this actually a good deal, how much of my capital gets locked up to find out, is this court going to take two months or fourteen, and what do I need to do this week.
So I mapped the journey before I designed anything, and worked backwards from the decisions in it. Discovery, location, diligence, comparison, timing, and the track record of the court holding the hammer. Every surface sits on that one path, and each one exists to close a question.
Figma for tokens, the browser for everything else
The living design system: palette scale, semantic tokens, two type ramps off the same ratio, and usage rules.
Solo builder. Speed and cognitive load become the real design constraints, and with no engineering stakeholder to align, a shared source of truth in Figma stops earning its keep. I used Figma for exactly two things: foundational tokens, and the structural task flows that told me what content each screen owed the user. Everything else happened in code, in Next.js 15, Tailwind v4 and Radix primitives.
Cursor handled documentation and design system pages, Claude Code the heavy backend. Claude Code held a thread across long refactors, which is what kept my attention on the product.
The system was the agents' job
I wrote the token architecture and the rules, then the models built against them. 52 documented components and patterns shipped, and not one of them started life as a Figma component.
Real schemas over MCP
Supabase and MercadoPago exposed to the agents over MCP, so they read real schemas, real types and real payloads. An agent that can query the database stops inventing field names.
Living contracts
CONTRACT_FE.md and CONTRACT_BE.md hold tokens, API payloads and architectural constraints across multi day sessions. The design system is a markdown file. The docs site is a rendering of it.
The AI as architectural auditor
Before the first utility function I made the models audit the schema and the service boundaries. Modularity got baked in during the arguing, which is the cheapest place to put it.
Systems before screens
Schemas, API contracts and service boundaries became the new wireframes, and the pipeline turned out to be what most of my design decisions were actually about.
Playwright drives the scrapers through dynamic SPAs, SharePoint servers and PDF downloads across every department. Documents then hit a three tier model cascade, Gemini Flash Lite, Flash and Pro, routed by linguistic complexity, which cut expensive tier calls by 95% and makes a thousand documents a month affordable for one person.
Regex before inference
The cheapest extraction is the one that never reaches a model. Metadata comes out with regex first and the model only sees what regex could not resolve. Every token has to earn its place.
Confidence the model does not get to score
Cross type nullification, plausibility ceilings, financial cross validation, structural checks, and a confidence score computed locally. A model that grades its own homework is not a validation layer.
The job is a spreadsheet job
First stop on that path is a filtering decision, and filtering is spreadsheet work. The incumbents were making people do it inside a card grid.
So the front door is a table. 2,314 remates sorted on any column that carries weight, down to estrato, the Colombian socioeconomic band that quietly sets what utilities cost. Cargas and depósito get their own sortable columns, so the user can rank the national market by what it actually costs to play. Columns are configurable, the result set exports, and a pro tool that will not let you leave with your data is not a pro tool.
Density on purpose. The gaps are part of the reading.
Where, and what that where is worth
A number on a row cannot tell you whether a neighbourhood justifies the money. Explorar carries the filter model over and swaps the output: photo cards for scanning, a geocoded map for reading a whole city at once.
Getting one pin onto that map takes a chain nobody sees. Address normalization, geocoding, a Street View facade capture, then a PostGIS point in polygon lookup against 222,000 strata polygons that hands back estrato, transit and what is standing around the property.
Same filters, new question. The cluster labels answer where the volume is before you have read a single row.
A score that admits what it does not know
Drill into a listing and the product stops being neutral. It takes a position. 60 out of 100, Buena, scored on discount against appraisal, capital locked in the deposit, known charges, court performance and location.
Then it immediately undercuts itself. Confianza: Baja. 43% of the factors have real data behind them, four are unverified, and it names them: debt load, state of the process, condition of the property. That pair of numbers took longer to get right than anything else on the page, because a confident score with hidden gaps is worse than no score at all. It sends a first time investor to bid on a number nobody checked.
The bar draws base against appraisal at real scale, so the 30% has a size. The facade comes from Street View, so you see the power lines before you see the pitch. And the court is a link, so a 60 out of 100 sitting in a slow court is one click from being reconsidered.
The score and its own confidence rating, side by side.
Is this a good deal, and how would you know
Two remates side by side is where a shortlist turns into a decision, and it only works if the user understands what they are looking at. Avalúo, base de licitación, depósito, cargas. Misread one and you wire money you are not getting back.
So the comparator explains every row where the row lives. Base de licitación is 70% of the appraisal under article 448 of the CGP, not a decision the court made, and in 92% of the corpus it is exactly that value. Say that out loud in the interface and the 30% reads as arithmetic.
The number I care about most sits at the bottom, and it is not called price. Costo conocido, with the word "piso" next to it, because three charges have not been consulted yet and I would rather publish a floor than a fiction. There is a toggle for showing only the differences, which is what people came for anyway.
The left column is content design doing the heavy lifting.
What is urgent, and what can wait
Nothing in this market is evergreen. A remate has a hearing date, a deposit deadline, and then it is gone, so the home screen is organised around time.
$145,5 mil millones of appraised value in the next 30 days, down 43% against the previous 30, the capital you would need in deposits to actually play, and the 328 hearings behind the number. The cadence chart shows which days are dense and which are dead, which is how you plan a month of site visits before you open the calendar.
Underneath, two lists do the real work: what is next, and where the volume is. Bogotá, 59 remates, $11,5 mil millones in deposits, and one click opens the table already filtered to it. Every figure on this page is a door into a filtered view. A dashboard that only tells you things is a report.
Pipeline value, cadence, and the two lists that turn it into a next action.
Which courts actually close, and how fast
My favourite thing in the product. Judicial offices ranked by adjudicated value, broken out year by year, with annual variation, adjudication rate and days in process.
Those last two columns are the ones that change behaviour. A court that adjudicates 46% of what it lists in 64 days is a completely different investment from one sitting at 28% and 117 days, and until this page existed nobody in Colombia could tell them apart. Same asset, same discount, wildly different odds of ever holding the title.
This screen needs every remate parsed into the same shape, tied to the same court, across four years. The incumbent holds the same public records and structurally cannot build it. Under the ranking sits a coverage table: field by field, row count, fill rate. If I am asking people to trust extracted data, they get to see where it runs thin.
Market intelligence as a by product of clean extraction.
What ten years of compartmentalised skills add up to
After years working next to product managers, I know enough to be dangerous. The gap between designer and builder is smaller than it has ever been, which does not make it small. I had to sharpen prompting and documentation, learn to stand up MCP servers, get comfortable with schemas and data structures, and find out how much specificity a memory agent really needs.
The biggest lesson is knowing when to stop designing and start shipping. The version that proves the concept does not need pixel perfection. Everything after that is iteration.
The frugal stack
A $20 Supabase plan, Vercel's free tier, and free tiers for transactional email and SMS alerts, with Supabase Auth, OAuth, Stripe and MercadoPago all wired in. The only variable cost is roughly $100 a month in AI tokens.
Where this goes
Alafija launched in June 2026. No social media, no ads, no growth hacks. Organic search was the plan from the first line of the PRD, because people already type these queries into Google, so I am letting the SEO do its work while I keep shipping.
Two subscribers so far. I could tell you their names. Smaller than any number in the PRD and a much better feeling than I expected, because two subscribers means the whole thing held: the scrapers ran, the models parsed, the validation caught what it was supposed to catch, the checkout took real money, and somebody decided the data was worth paying for.
The market is large and underdeveloped, so I am already scheming. The backend is an obvious B2B API, attorneys and banks will pay for qualified leads, and there is a version of this where I sit between the banks and the investors on the financing.
We will find out. I will keep you posted.