EN NL
Projects · 02 / 05

Clio

Private app, login only

A log for meetings and client conversations: one input line that colours +client, @person, #tag and !deadline as you type, with action items, export, summaries and an MCP connection for AI.

Period
2026
Role
Design and development
Built with
LaravelPHPMySQLFrankenPHPMCP

Screenshots show made-up demo data, not real accounts.

  • 5token types coloured as you type
  • 190+automated tests in PHP and JavaScript
  • 3export formats
  • 2FAon every login
About the project

Clio is my log for meetings and client conversations. Everything starts with one input line: type what was discussed and Clio recognises the client, people, tags, deadlines and time spent while you type.

From those notes Clio builds a timeline, a list of open action items and summaries per client. It is built on Laravel 13 and FrankenPHP without a frontend build step, behind two-factor login and a strict content security policy.

What I built
  • Live colouring of +client, @person, #tag, !deadline and ~time, from one grammar shared by the PHP parser and the JavaScript tokenizer
  • Autocomplete for clients, people and tags, with keyboard shortcuts for almost everything
  • Open action items grouped by overdue and later, ticked off right in the timeline
  • Summaries per client and day that link back to their sources
  • Export to Markdown, CSV and JSON, following the current filter
  • An MCP server so an AI assistant can read the log; writing needs a separate token permission
  • Every user has a separate log, enforced in the models and checked by automated tests
Under the hood

How it works

One grammar, two parsers

Notes are parsed twice: in JavaScript while you type, for the colours and suggestions, and in PHP when you save. Both run against one shared file of test cases, so what you see while typing is always what gets stored.

AI access without opening the door

The MCP endpoint is the only route outside the login and two-factor check. Tokens can only read unless they get write permission, are stored as a hash, and are rate-limited before the token is even checked. Failed attempts are logged for fail2ban.

Testing never touches live data

The local setup has its own database. Commands that write data refuse to run in production or against any other database, and the test suite stops if it is not pointed at the test container. Real data only comes in through Clio's own JSON export.

Search and history

Search uses a MySQL full-text index where every word counts as a prefix. Every edit is saved as a revision and deleting is a soft delete with undo, so nothing in the log is ever lost by accident.