Back

Madori

A calm, collaborative workspace for small teams — tasks, boards, calendar and docs in shared Spaces, plus an LLM assistant over its own data. Built solo.

Madori
Role
Sole developer
When
Apr 2026 – Present
Client
Personal
Symfony 7.4API PlatformPostgreSQLMercureNext.jsTypeScriptKubernetes

Madori brings everything a small team is working on into one place: tasks, boards, a calendar and long-form docs, organized into shared Spaces, plus time tracking and invoicing. The pitch is deliberately narrow — no bloat, no busywork. It is currently in beta.

Architecture

An API Platform application on Symfony 7.4 and PHP 8.4, backed by PostgreSQL through Doctrine ORM, with a Next.js/React front end in TypeScript consuming it. The two are genuinely separate: the API is the product surface, not an implementation detail of the UI.

Real-time updates go over Mercure. Anything that should not block a request — notifications, imports, scheduled jobs on cron expressions — goes onto Symfony Messenger on a Doctrine transport with a dedicated worker.

The parts that take the real time are the ones nobody demos: BlockNote behind the long-form editor, dnd-kit for the boards, server-side PDF generation and image processing. It is containerised and deployed with Helm, with Sentry wired through both the API and the front end, and an end-to-end suite of its own.

Security

The part of a multi-tenant workspace that has to be right before anything else is worth building:

  • Two-factor authentication — TOTP with backup codes.
  • OpenID Connect and OAuth sign-in with Google, GitHub, Facebook and Apple, alongside API-token and bearer authentication for programmatic access.
  • Authorization as voters rather than scattered checks — per-space access, segment-level rules, and audited impersonation for support.

Assistant surface

Madori exposes its own data to LLM clients through a Model Context Protocol server: a tool registry with per-tool policy, authorization and billing gates in front of it, and a serializer that decides what a model is allowed to see. It is the same argument as the AI work I do for clients — the model is the easy part, and what decides whether it is safe to ship is the policy layer around it.

What I built

All of it. Product design, backend, front end, deployment and operations are mine, which means every trade-off in it is one I had to make and live with.

That is the reason it sits in this portfolio next to the client work. Contract engagements show what I can do inside someone else's constraints; this shows what I choose when the constraints are mine — where the seams go, what gets a test, what is worth building twice, and what is worth leaving out.