Zulma
Managing partnerHandles the VIP property portfolio and the relationships with long-standing owners.
The internal software of a boutique real estate agency in Coghlan. Three partners, a neighbourhood office, a system that respects the way they work.
Cantú Propiedades serves buyers and sellers of apartments in Coghlan, Villa Urquiza, and Belgrano R. It's one of those neighbourhood agencies that knows the doormen, knows which building has damp problems, and remembers the name of every owner's dog.
Three partners. Working this way for nearly thirty years, before real estate CRMs existed.
Handles the VIP property portfolio and the relationships with long-standing owners.
Shows properties, leads visits, closes deals.
Keeps the schedule, confirms visits, and stays in active contact with everyone.
Real case. Names and details changed for confidentiality.
When they reached out to us, the business was running. But it was running on Zulma, Martín, and Carolina patching the gaps in the system.
Zulma's personal Excel with her VIP owners lived on her laptop. If the laptop died, fifteen years of relational capital went with it.
Carolina's printed calendar took up half the office wall. Visits were pencilled in. When Martín rescheduled something from the street, Carolina found out two hours later on WhatsApp.
Leads came in through six different channels. When someone wrote on Instagram and then called on the phone, they ended up entered twice without anyone noticing.
The monthly reports for owners were done by hand. Every month. Every time.
None of this made them a bad agency. It made them an agency with an invisible ceiling: they couldn't take on more properties without breaking the operation.
We ran three interviews the same week. One with each partner, separately. We learned things that weren't even in the brief.
The brief mentioned five lead channels: Zonaprop, Mercadolibre, their own website, social media, and referrals. During the interview with Zulma, a sixth appeared: "referred by me." It's different from a standard referral because it comes from her personal circle and carries a particular kind of commitment. It's information Zulma doesn't share with the rest of the team's leads.
That channel ended up as its own column with restricted permissions.
In the interview with Martín we learned that he never enters data himself. He sends information over WhatsApp and Carolina puts it into the system.
If we had built the system thinking of Martín as the operational user of the software, we would have failed. The operational user is Carolina, and the entire system had to be designed for her first.
Don Eduardo Vázquez (not his real name) has spent twenty years buying and selling exclusively with Zulma. No one else on the team can see the reservation price, the internal notes, or the special commission arrangement. Not out of distrust — because that kind of personalised information only holds up inside a relationship.
Implementing asymmetric confidentiality at the database level was a decision that came directly from that conversation.
After discovery, the scope changed. Some things from the initial brief were dropped. Others the brief never mentioned were added.
Zulma sees everything, including the special arrangements. Martín sees operational data but not the arrangements. Carolina sees the full schedule but not the internal notes. The difference wasn't built by hiding buttons in the frontend — it was built at the Postgres level. If someone tries to access something they shouldn't via the SQL console, the database returns zero rows. It's the only sustainable approach for an operation that requires real confidentiality.
When someone starts typing a phone number that already exists, the system warns them before saving. It came directly from the problem of Lucía Fernández (not her real name), who appeared twice in different spreadsheets.
Short asynchronous messages like "the owner wants to raise the price — call him Monday." Visible to all three, marked as read by whoever saw them. It's the closest thing to having all three in the same office.
The brief asked for it. We evaluated it. We ruled it out for this stage: serious AFIP billing implementation is three extra months of work, and it's not where the business is losing money right now. Having that conversation directly with the client was one of the most important moments in the project.
Getting a Meta-verified Business number takes two to three weeks, and nobody wants to depend on Meta's timeline. Planned for a later round.
Properties are currently loaded with an external URL. The next round includes it.
Cantú didn't need another SaaS dashboard. It needed something that felt like its calling card. So the design system didn't come from a modern kit — it came from a conversation about what makes an owner feel comfortable handing their keys to an agency.
The visual reference was editorial stationery: British arched portals, old agency stamps, typographic posters made by print shops. Not out of nostalgia — because that vocabulary works as a visual synonym for craft.
A modern Italian serif with editorial details. It appears on addresses, lead names, and key figures. We didn't use it because it looks good — we used it because it makes the data feel like it matters.
A clean, neutral sans-serif that doesn't steal the spotlight. Mono for tabular numbers and uppercase labels. Prices right-aligned in tabular nums read differently.
Warm cream as the background, a warm black as ink, a single accent colour (brick) that appears only where the eye needs to go. No blue. No violet. No "OK" green or "error" red. Restraint is the decision.
Stack: Next.js 14 with App Router for the frontend and API endpoints. Supabase for the database (Postgres), authentication, and storage. Tailwind v3 for the style system. Vercel for hosting and deploys.
The database has nine main entities and approximately thirty-two active Row Level Security policies. Every query that goes through the app is filtered by those policies in Postgres before any data is returned. Don Eduardo's confidentiality doesn't depend on the frontend remembering to hide a button — it depends on Postgres refusing to return that row if the user making the query isn't Zulma.
Deployment is continuous. Every commit to the main GitHub branch deploys automatically. No servers to maintain, no manual release processes. If we break something, we know in thirty seconds. If we fix something, it's live in thirty seconds.
The public demo resets every twenty-four hours. A cron job runs at four in the morning, Argentina time, and restores the demo data to its original state. Any visitor can try the product without permanently altering it.
We worked with Claude Code as a pair programmer. That description is precise: pair programmer, not autopilot. It speeds up implementation but doesn't make product decisions.
The decisions you see in this case study — the sixth channel, asymmetric confidentiality, the news/updates module, what we left out — came from the interviews and from the studio's thinking. Claude Code wrote most of the code that implements them.
The product is live at cantu.js80.studio. It has three demo users:
Log in as any of the three by clicking the large buttons on the login screen. No password needed. Data resets every night.
That means it keeps evolving. Next rounds:
JS80 is a digital solutions studio based in Buenos Aires. We build complete products for real businesses: one idea, one team, one delivery that works.