Jaedan Persaud
Home
In progressSince January 2026

Yard.tt

One marketplace, four kinds of user, one API

Yard.tt is a property marketplace for Trinidad & Tobago: a public site for finding a place, a portal for agents to list and manage inquiries, a flat-fee path for owners to list their own home, and an admin side to approve and moderate all of it. The website and the mobile app run on the same typed API.

user roles
4
API procedures
157
database tables
27
email templates
19

Why it needed to exist

Looking for a place in Trinidad & Tobago means checking a lot of different places, and listing one means posting it in all of them. I wanted a single place where the listings are structured — price, parish, bedrooms, a pin on a map — so a search can actually be a search.

A marketplace like this is really four products sharing a database. Visitors browse without an account. Registered users save homes and searches. Agents list, answer inquiries and pay to promote. Admins approve agents and moderate everything. Each needs a different view of the same data, and each is a place where one wrong check leaks someone else's.

What it is

The public site

Search by area and type with live counts, a map view, listing pages, favourites, and saved searches that email you when something new matches. The brand comes from a painted day-and-night view of a verandah house that switches with the theme.

The agent portal

Onboarding with admin approval, a listing editor, an inquiries inbox, paid promotions that lift a listing to the top of matching searches, and a Pro plan.

Owner listings

Someone letting or selling their own place can list it without an agent for a flat fee — TT$150 for 30 days to rent, TT$300 for 60 days to sell — and hear from people directly.

The mobile app

An Expo app in the same pnpm workspace. It imports the API's types but none of its code, and signs in with the same accounts through bearer tokens.

The decisions behind it

  1. 1

    Authorization lives in the procedure, not the page

    Every API call is built from one of a handful of procedure types — public, signed-in user, approved agent, admin — and the type is the check. Signed-in is never treated as authorised. A smoke test walks every admin and agent procedure as the wrong kind of user, so a new endpoint without the right guard fails the build instead of shipping.

  2. 2

    One API for the web and the phone

    The website and the app call the same tRPC router, and the app imports its types without importing any server code. A field renamed on the server is a type error in the app the same minute, rather than a crash report a week later.

  3. 3

    A shared package with a short list of rules

    Validation schemas, formatters and domain types live in a package both apps use. It is not allowed to depend on Next, React, the database or the auth provider — the moment it does, it stops being shareable, so the rule is written down and kept.

  4. 4

    Public writes go through the server, not the API

    Contact forms and inquiries are callable only from server actions, which add rate limiting and a CAPTCHA before they reach the database. Nothing a stranger can submit is exposed as an endpoint they can script.

  5. 5

    Payments behind an interface

    Promotions, Pro and owner listings all pay through one provider interface, so the payment company is a detail rather than a dependency. It already has two implementations behind it.

Where it stands

  • Public site: search, map, listing pages, favourites and saved-search alerts
  • Agent portal: onboarding and approval, listings, inquiries, promotions and Pro
  • Owner listings with flat-fee checkout
  • Staging and production on separate database branches, with CI checking every change
  • The mobile app at parity with the website
  • Launch, with real agents and real listings

What changed once it existed

It isn't launched yet, so the honest outcome is about the build. Four roles on one API has held up: the access-control smoke test has been the difference between trusting a new endpoint and re-reading it line by line.

The shared package paid for itself the first time the mobile app needed a form. The validation, the price formatting and the feature labels were already there, and already the same as the website's.

Built with

TypeScriptNext.js 16tRPCDrizzle ORMPostgreSQLClerkExpoTailwind CSSResend

Where the line is

Yard.tt is a marketplace, not a brokerage. It gives agents and owners a structured place to list and gives buyers and renters a real search. It doesn't handle the sale itself, and it isn't trying to.

Have a look

If you are solving the same problem in your own stack, or you want this kind of foundation for your team, email me at hi@jaedan.me.