Rondo
A platform to create and run AI experts for the roles of a football club, with answers traceable to connected sources. The technical foundation exists; product features do not.
Technologies
- TypeScript
- Node.js
- PostgreSQL
Overview
Rondo is a platform to create and run experts: AI agents specialized in the roles of a football club, such as head coach or performance analyst, fed by connected data sources and answering with citations to them. It was called Analytics Personas before it took the Rondo name. The repository is a monorepo with a React web app, a Nest.js API and a local observability stack. It is a personal project.
Challenge
Football clubs keep knowledge in scattered tools: documents, wikis, tickets and spreadsheets. Each role needs that material turned into decisions quickly, and an answer that cannot be traced to its sources, or that invents data, is worse than no answer. The challenge is to build specialized experts whose answers are auditable, on a base where accounts and access to data can be trusted from the start.
Solution
The product idea is one expert per role, each with its own scope, authorized sources and delivery format, answering requests in natural language with citations and declaring a gap when context is missing. So far the work went into the base this needs: accounts with e-mail confirmation, sign-in and password recovery, an observable and load-tested API, and a design system with its own visual identity. Experts, connectors and the language model integration are planned and do not exist yet.
Architecture
A monorepo with a React and Vite web app (TanStack Router and Query), a Nest.js API in TypeScript, a Next.js documentation site and a shared design system package built on Tailwind CSS and shadcn/ui. The API is organized in vertical slices with domain, application, infrastructure and interface layers, one request handler per endpoint and one use case per flow. Data lives in PostgreSQL through a local Supabase, with row-level security on and no policies, so only the API can reach it. The API sends traces, metrics and logs through OpenTelemetry to a local Grafana stack (Loki, Tempo and Mimir), with a provisioned dashboard and alerts, and k6 load tests run against an isolated instance. Lint, formatting, unit, integration and end-to-end tests run locally; there is no CI pipeline yet.
Technical decisions
Authentication owned by the API.
Accounts, Argon2id password hashes and single-use link tokens, stored only as hashes, live in the API's own tables; Supabase Auth was deliberately not used.
Sessions that can be revoked at once.
The session token is a signed JWT, but every request also checks the session row in the database, so signing out or signing in elsewhere takes effect immediately and only the latest session of each person stays valid.
Protect the server before the features.
Rate limits on sign-up and sign-in, and a cap on simultaneous password hashing with a bounded queue that answers "busy" instead of stalling the whole API, a design shaped by load tests.
Observability from the start.
Metrics, traces and logs reach a single Grafana dashboard, with each attempt counted once in one place and no personal data in metric labels.
A visual identity of its own.
A retro 8-bit direction inspired by football and Brazil, with a pixel-art logo, a five-color palette and hard offset shadows, documented with accessibility rules aimed at WCAG 2.2 AA.
Current state
In development. Implemented: account creation with e-mail confirmation, sign-in, sign-out and password recovery, plus the observability and load-testing setup. Not implemented: experts, connectors, source ingestion, the language model integration, deployment and a CI pipeline. The interface is in English, and the screens shown here come from the local development build, with no real data.



