© 2026 Thibaud Geisler - SIRET 880 419 122 00036
Single-user admin space built into my portfolio: a freelance CRM that replaces Notion, GDPR compliance handled in the code and a foundation ready for AI agents. Next.js, PostgreSQL, Google login. In production.

I run my freelance business from Notion, through a full CRM powered by my own Claude Code skills. I first set it up as a POC and it worked very well, but I quickly hit its limits: queries that were neither fast nor precise enough, and a database that got harder to manage as the data piled up. Not to mention the dependency on an external tool.
The site had the same kind of problem: the content lived in the code, so every correction meant a new deployment.
So I built my own admin space, right inside the portfolio application. It now manages the site content and the freelance CRM. Next, it will host mission tracking, accounting, finances and AI agents.
Goal: a real professional tool, built to my own standards, instead of paying for a service or hacking something together.
My role: design, development and operations, solo.
My Notion databases were a first attempt at a model, with quite a few approximations: information copied from one database to another, concepts that had no database of their own. Not to mention values I typed by hand when they could have been derived.
Solutions: I rebuilt the model as a relational database, with one simple rule: each piece of data lives in one place only. Opportunities now have their own table, linked to the IT services firm and to the end client. A person exists only once, whether they are a prospect or a contact. About ten values, such as the first contact or the weekly review counters, are computed automatically instead of being entered. The CRM also offers a kanban pipeline, a calendar of actions, interview tracking and buying signals.

Prospecting means storing data about people who did not give it to me themselves. So I wanted to be compliant before recording the first lead rather than fixing things after the fact.
Solutions: the processing is declared in my register and my privacy policy was updated beforehand, with retention periods based on the CNIL guidelines (the French data protection authority). Objection and erasure are two separate actions: a person who objects can no longer be contacted, their record only keeps a trace of the refusal, then it is deleted after 3 years. If you think you are in my CRM, you can object at any time, without giving a reason, by following my privacy policy.
The admin space runs in the same application as the public site. The slightest authorization mistake could expose private data to any visitor.
Solutions: login goes through Google only, with a single allowed address and no stored password. Permissions are checked at three levels: at the admin entrance, on every page and in every action. At the end of the work, I checked that an action called with a fake cookie is indeed rejected. And no admin data ever reaches the browser.
I had to bring over the whole history of the Notion CRM in a single pass, without losing data and without any risk of overwriting production.
Solutions: a Claude session connected to Notion prepares the data, then a script checks it with the same rules as the admin forms. It first runs as a dry run, then writes everything in a single transaction. It also refuses to write if the database already contains data. And I take a backup before every step.
To display company logos, Logo.dev forbids storing the images on its free plan and costs $150 per month on its Pro plan.
Solutions: the app fetches the icon directly from the company's website, or from a Wayback archive when the site no longer exists. Since the server calls an address entered by hand, I added SSRF protection: internal addresses are blocked and both the size and the duration of responses are capped.
The upcoming AI agents will have to act on the app without putting the public site at risk. They will also have to run on my Claude subscription rather than pay-as-you-go.
Solutions: all data management stays in the app. Whatever requires judgment or computing time will move to separate services. I also built a prototype of the agent engine before writing a single line of the real service: it launches Claude Code with my whole working environment and asks me its questions on my phone.