A week-by-week log of building Linkette alone — the stack choices that compounded, the order of operations, and one thing I'd reverse if I started again.
Eight weeks ago, the repository was empty. I made the initial commit on a Saturday morning in late March, in a café on rue de Bretagne — the one with the white tile and the indifferent coffee — and I spent that first session writing a README.md that no longer survives in its original form. Today, Linkette is live, it has a paid tier, it accepts Mollie payments, it speaks to Mistral La Plateforme, and it has a small but real number of users.
I want to write down what each of those eight weeks actually contained, in the spirit of the indie SaaS public-build logs I read religiously when I was figuring out whether to do this. Not the heroic version. The actual ledger.
Week 1 — Spec, auth, magic links, landing
I spent the first three days writing a design specification. I know that is unfashionable; the standard advice is to ship something rough by Tuesday and revise. I have done that on previous projects and ended up rewriting fundamentals at month three, and the time saved at the start was always less than the time spent later untangling. So: a forty-page spec document, written in plain prose, that I still consult.
By Friday I had a Next.js 16 app deployed to Scaleway, Supabase auth wired with magic-link sign-in, and a landing page with a working email collection form. The form posted to Brevo. The auth used Supabase's built-in passwordless flow. The landing was three sections deep — hero, value props, the email field — and looked deliberately under-designed because I knew I would rewrite it in week six.
Week 2 — Editor MVP, Supabase migrations
The editor is the heart of Linkette. A creator lands in a single-page surface where they edit their links, drag to reorder, paste a URL and watch metadata fill in. Week two was building that surface end-to-end with the absolute minimum chrome, plus the Supabase migrations underneath. Tables for pages, links, themes. Row-level security from day one — not bolted on at week seven, when it would have been painful.
I cannot overstate how much time the early decision to enable RLS bought me. Every query is constrained at the database layer to rows the authenticated user owns. When week five arrived and I was building cron jobs that touch user data on behalf of users, the security model was already in place.
Week 3 — Mistral integration, onboarding flow
Mistral La Plateforme is, in 2026, a genuinely pleasant API to integrate. The OpenAI-compatible endpoint means the Vercel AI SDK works out of the box; you point baseURL at La Plateforme, swap the model name, and you are streaming tokens from a Paris-based model in under thirty minutes of integration work.
Week three was building the conversational onboarding — a small chat surface that asks a new creator a handful of questions about their work and proposes a starter page based on the answers. This is the moment in the product where a creator first encounters the AI surface, and I spent four days making sure the streaming felt right: tokens appear at human cadence, the proposed bio is editable in place rather than locked behind a confirm button, and the entire flow is dismissible if the creator prefers to start from a blank page.
Week 4 — Analytics, cookie-free tracking
I had a stronger opinion than I expected about this one. Every link-in-bio platform I looked at — Linktree, Bento, Beacons, the European also-rans — ships a cookie banner on the public creator page. I did not want a cookie banner. So I designed the analytics pipeline from scratch, in week four, to never write a cookie.
The mechanism is small: when a visitor hits a Linkette page, we compute a SHA-256 of the visitor's IP combined with a daily-rotating salt, a server-side pepper, and the page id, store twenty-four characters of that hash, and increment the appropriate counter. We never know who you are, and tomorrow's hash of you is different from today's hash of you. We can count uniques per day. We cannot identify you across days, which is the point.
Week 5 — Mollie, Founding Member tier, cron
Mollie is the European Stripe-equivalent that I keep recommending to other EU founders. The integration is direct. Week five was wiring the Founding Member checkout (€99, one-time payment, EU SEPA + cards), the webhook handler that decrements the seats_remaining counter atomically when a payment succeeds, and a small cron job on Scaleway that reconciles Mollie's record with our own once an hour.
The atomic decrement matters. If two people happen to click the checkout button at the same moment when the ninety-ninth seat is the last one, exactly one of them must succeed. I used a Postgres advisory lock to enforce this. It has been triggered exactly twice in production so far.
Week 6 — Themes, QR, brand assets
This was the design week. The two built-in themes — Atelier (cream paper, terracotta accent, deep ink text, the Fraunces variable serif) and Atelier Nocturne (warm near-black, brightened terracotta, never cold) — were both refined here, in pairs of long sessions where I designed in Figma in the morning and implemented in Tailwind v4 in the afternoon. I shipped the QR code generator for each public page, which writes the QR as a small server-rendered SVG with the page's accent color woven into the modules.
I also commissioned, finally, the typographic logotype that lives at the top of every Linkette surface. It is set in Fraunces, custom-spaced, with the small terracotta serif flourish on the first letter that I will probably revise within the year.
Week 7 — GDPR/CNIL audit, security hardening
I sat down with a CNIL-aligned checklist and walked through every data path in the product. I rewrote the privacy page to name every sub-processor by company, country, and purpose: Supabase (Paris, eu-west-3, primary database and auth), Scaleway (France, hosting), BunnyCDN (Slovenia, EU-owned, CDN), Brevo (France, transactional email), Plausible (Estonia, EU-hosted, internal analytics), Mistral La Plateforme (France, AI inference), Mollie (Netherlands, payments). I added the AI usage tracking table and the ai_weekly_brief_enabled opt-out toggle. I documented a data export endpoint and a deletion endpoint. I rotated all secrets.
The security hardening was mostly mundane: rate limiting on auth, CSRF protection on POST forms, strict CSP headers on the public page surface, SRI hashes on the very small number of external script tags (essentially: none in production).
Week 8 — Deployment, mobile, launch
Final week was the punch list. Mobile optimization, which I had deferred and somewhat regretted by this point (see below). Production deployment on Scaleway behind BunnyCDN. End-to-end smoke tests of every flow: sign up, build a page, publish, paste the URL into a phone, scan the QR, click a link. The launch itself was small and quiet: I emailed the early waitlist, posted once on a French indie maker forum, and went to bed.
The stack choices that compounded
Three constraints did more for my pace than anything else.
TypeScript in strict mode, from commit one. Every type error caught at compile time is a type error not debugged at 11pm. The cost is real — strict mode is slower to write — but the cost is paid in increments of seconds and the savings come back in increments of hours.
Tailwind v4 with design tokens in a single package. I built a small packages/tokens workspace that owns every color, spacing, and typography value as CSS variables, then consumed those tokens through Tailwind utilities. Nothing in the app hardcodes a color. When I redesigned Atelier Nocturne in week six to be warmer, I changed three token values and the entire app shifted.
The Vercel AI SDK as the only path to a model. Every AI call in Linkette goes through one module, lib/ai, which owns model selection, prompt assembly, and usage tracking. Nothing else imports the SDK. When I swap a model — say, Mistral Large for Mistral Medium on a specific task — I change one line.
Tools that saved time
Claude Code was the pair programmer I have always wanted and never had. Cursor as the IDE, because the inline completions on a TypeScript codebase are very good. Firecrawl for research: when I needed to understand exactly how a competitor structured their pricing page, I could scrape and analyze in seconds rather than the half-hour of copy-paste it used to be.
What I'd do differently
One thing. I designed for desktop first and adapted to mobile second. Every Linkette creator I have talked to since launch edits primarily on their phone. The desktop editor is beautiful and almost no one uses it as their primary surface. If I started again, I would build the mobile editor first — every layout, every interaction, every keyboard handler — and then expand to desktop as a secondary surface. I am rebuilding the editor along these lines now, but it is a much bigger refactor than it would have been if I had got it right the first time.
The rest, I would do again.
If you are building something solo in Europe right now and any of this is useful, write to me. I read everything that arrives at founder@linkette.eu. The next eight weeks I'm planning to be quieter than the first eight, but I'm taking notes.