A sketch, not a system. I built it to find out whether the idea held, so read it as thinking rather than as architecture.

kin

A connector marketplace for builders

Role
Solo — architecture, schema, build
Since
2026
Status
building
Stack
  • Next.js App Router
  • TypeScript
  • Postgres
  • Drizzle
  • Better Auth
  • Docker

Two kinds of people never find each other.

Someone who wants to be picked up by a team. Someone building and short of hands.

kin is two cards and a feed. Nothing more, on purpose.

01 How I thought about it

I wrote the design doc before the first line of code

Not because process is nice. Because I wanted to be able to argue with myself while it was still cheap. The doc names what version one contains, what it deliberately does not, and the exact condition under which each excluded thing comes back.

Monolith now, service later — with the trigger written down

One Next.js app is the fewest moving parts for a solo build: one deploy, one repo, shared types. I did not pretend that scales forever. The doc says a separate FastAPI service gets split out when matching needs embeddings and stops being a database query. Until that day, splitting is cost with no benefit.

GitHub login is the verification, not just the login

Requiring GitHub OAuth to create a card means every author has a public history. That is cheap trust with no moderation queue. Reading stays open to everyone — only writes are behind auth.

02 Architecture

Browser
Next.js — App Router
RSC (reads)Server Actions (writes)Better Auth → GitHub
Drizzle ORM
Postgres
Reads render on the server and hit the database directly — no client fetch, so the feed is fast and indexable. Writes go through server actions, so there is no hand-written REST layer to keep in sync.

03 Decisions, with the reason attached

  • links as a jsonb column, not a separate table

    Nobody filters by link. Normalising it would buy a join and pay nothing back.

  • tags as text[] with a GIN index

    "Cards tagged React" is the main query on the feed. A GIN index makes contains-element fast instead of a full scan.

  • Feed index on (status, created_at DESC)

    The feed only ever asks one question: active cards, newest first. The index matches the question exactly.

  • UNIQUE (card_id, reporter_id) on reports

    Idempotency at the schema level. One person cannot report the same card twice, and a retry cannot create a duplicate.

  • Timezone-aware timestamps everywhere

    The audience is not in one country. A naive timestamp is a bug waiting for the first user abroad.

04 Where it landed

Schema, migrations and auth are in. The feed renders from the database on the server.

Versioned SQL migrations are generated from the TypeScript schema, so the database and the types cannot drift.

What I'd change

Not launched yet. The matching is a database query and nothing cleverer, which is the correct amount of cleverness for zero users.

Projects & Advisory

Building something like this — or putting AI agents into production?

I design AI systems, orchestrate the agents that run them and own the backend underneath. Founding-engineer and systems-architect work, and advisory for teams that need it to run unattended and stay within budget. Abu Dhabi (ADGM) / Remote.

Next case precheck → Grant readiness scoring for founders