<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <title>The avanserv build log</title>
  <subtitle>Dated write-ups of what I built for avanserv and why, from the infrastructure to the site you are reading.</subtitle>
  <id>https://avanserv.com/build-log</id>
  <link rel="self" type="application/atom+xml" href="https://avanserv.com/build-log/feed.xml" />
  <link rel="alternate" type="text/html" href="https://avanserv.com/build-log" />
  <updated>2026-09-26T00:00:00Z</updated>
  <author><name>Antoine Van Serveyt</name></author>
  <entry>
    <title>Holding the page still when the brand typeface loads</title>
    <id>https://avanserv.com/build-log/holding-the-page-still</id>
    <link rel="alternate" type="text/html" href="https://avanserv.com/build-log/holding-the-page-still" />
    <published>2026-09-26T00:00:00Z</published>
    <updated>2026-09-26T00:00:00Z</updated>
    <summary>Fitting fallback faces so text stops jumping when the brand typeface lands, and the three ways the measuring gate was blind to what visitors saw.</summary>
  </entry>
  <entry>
    <title>A business card a phone can scan and save</title>
    <id>https://avanserv.com/build-log/a-business-card-a-phone-can-save</id>
    <link rel="alternate" type="text/html" href="https://avanserv.com/build-log/a-business-card-a-phone-can-save" />
    <published>2026-09-23T00:00:00Z</published>
    <updated>2026-09-23T00:00:00Z</updated>
    <summary>A printed QR code that opens a card page and saves the contact, and what a Pixel taught me about vCard photos and Chrome on Android.</summary>
  </entry>
  <entry>
    <title>Publishing the legal documents as pages of the site</title>
    <id>https://avanserv.com/build-log/legal-documents-as-pages</id>
    <link rel="alternate" type="text/html" href="https://avanserv.com/build-log/legal-documents-as-pages" />
    <published>2026-09-22T00:00:00Z</published>
    <updated>2026-09-22T00:00:00Z</updated>
    <summary>The contracts and policies moved from a repository to pages of the site, each with a stored PDF, a link per clause and the security.txt its policy promised.</summary>
  </entry>
  <entry>
    <title>From a bare cluster to a staging environment reconciled from git</title>
    <id>https://avanserv.com/build-log/staging-from-git</id>
    <link rel="alternate" type="text/html" href="https://avanserv.com/build-log/staging-from-git" />
    <published>2026-09-19T00:00:00Z</published>
    <updated>2026-09-19T00:00:00Z</updated>
    <summary>How a bare Talos cluster became a staging environment that Argo CD reconciles from git, with its secrets, certificates and both web origins.</summary>
  </entry>
  <entry>
    <title>Parking an environment, and bringing it back unattended</title>
    <id>https://avanserv.com/build-log/parking-an-environment</id>
    <link rel="alternate" type="text/html" href="https://avanserv.com/build-log/parking-an-environment" />
    <published>2026-09-16T00:00:00Z</published>
    <updated>2026-09-16T00:00:00Z</updated>
    <summary>Taking staging down to what a rebuild reuses in 87 seconds, and back up unattended in about eleven minutes, with every plan read by a gate first.</summary>
  </entry>
  <entry>
    <title>Bootstrapping a self-hosted Kubernetes estate on Talos and Scaleway</title>
    <id>https://avanserv.com/build-log/talos-on-scaleway</id>
    <link rel="alternate" type="text/html" href="https://avanserv.com/build-log/talos-on-scaleway" />
    <published>2026-09-10T00:00:00Z</published>
    <updated>2026-09-10T00:00:00Z</updated>
    <summary>Why the platform runs its own Kubernetes control plane on Talos and Scaleway, and the traps met bringing the first cluster up from OpenTofu.</summary>
  </entry>
  <entry>
    <title>The pre-PR gate that stands in for a team</title>
    <id>https://avanserv.com/build-log/the-pre-pr-gate</id>
    <link rel="alternate" type="text/html" href="https://avanserv.com/build-log/the-pre-pr-gate" />
    <published>2026-08-28T00:00:00Z</published>
    <updated>2026-08-28T00:00:00Z</updated>
    <summary>With no second engineer to read a diff, every pull request passes scanners, a model review that blocks on security, and a local gate that signs a receipt.</summary>
  </entry>
  <entry>
    <title>Serving the site in French at its own paths</title>
    <id>https://avanserv.com/build-log/the-site-in-french</id>
    <link rel="alternate" type="text/html" href="https://avanserv.com/build-log/the-site-in-french" />
    <published>2026-08-22T00:00:00Z</published>
    <updated>2026-08-22T00:00:00Z</updated>
    <summary>Why French lives at /fr while English keeps the bare paths, and how one language choice follows a visitor from the site into the application.</summary>
  </entry>
  <entry>
    <title>Splitting the frontend and prerendering the public site</title>
    <id>https://avanserv.com/build-log/prerendering-the-public-site</id>
    <link rel="alternate" type="text/html" href="https://avanserv.com/build-log/prerendering-the-public-site" />
    <published>2026-08-19T00:00:00Z</published>
    <updated>2026-08-19T00:00:00Z</updated>
    <summary>How the public site became its own prerendered build, and how a lint rule between it and the application became a package boundary.</summary>
  </entry>
  <entry>
    <title>Taking the frontend to WCAG 2.2 AA</title>
    <id>https://avanserv.com/build-log/wcag-2-2-aa</id>
    <link rel="alternate" type="text/html" href="https://avanserv.com/build-log/wcag-2-2-aa" />
    <published>2026-08-06T00:00:00Z</published>
    <updated>2026-08-06T00:00:00Z</updated>
    <summary>Four gates that each own a class of accessibility defect, and what they found on the way to WCAG 2.2 AA.</summary>
  </entry>
  <entry>
    <title>The rebrand to avanserv, on a monochrome token system</title>
    <id>https://avanserv.com/build-log/the-rebrand</id>
    <link rel="alternate" type="text/html" href="https://avanserv.com/build-log/the-rebrand" />
    <published>2026-08-04T00:00:00Z</published>
    <updated>2026-08-04T00:00:00Z</updated>
    <summary>How the rebrand to avanserv turned every colour into a role on one ink ramp, and why the contrast gate had to be fixed before it could be trusted.</summary>
  </entry>
  <entry>
    <title>Per-organisation OIDC SSO with identifier-first login</title>
    <id>https://avanserv.com/build-log/per-organisation-sso</id>
    <link rel="alternate" type="text/html" href="https://avanserv.com/build-log/per-organisation-sso" />
    <published>2026-07-02T00:00:00Z</published>
    <updated>2026-07-02T00:00:00Z</updated>
    <summary>Signing in through each organisation&apos;s own identity provider, behind an email-first login, when the admins who configure that provider cannot be trusted.</summary>
  </entry>
  <entry>
    <title>Transactional email as a subsystem</title>
    <id>https://avanserv.com/build-log/transactional-email</id>
    <link rel="alternate" type="text/html" href="https://avanserv.com/build-log/transactional-email" />
    <published>2026-06-27T00:00:00Z</published>
    <updated>2026-06-27T00:00:00Z</updated>
    <summary>Email built once, as a subsystem: an outbox row in the caller&apos;s transaction, MJML compiled without Node, and an admin view to replay failures.</summary>
  </entry>
  <entry>
    <title>Access control as a declarative DSL, then roles and capabilities</title>
    <id>https://avanserv.com/build-log/access-control-as-a-dsl</id>
    <link rel="alternate" type="text/html" href="https://avanserv.com/build-log/access-control-as-a-dsl" />
    <published>2026-02-11T00:00:00Z</published>
    <updated>2026-02-11T00:00:00Z</updated>
    <summary>Access rules declared on each model and compiled to both a SQL filter and a record check, and the three tiers of rights that became roles and capabilities.</summary>
  </entry>
  <entry>
    <title>Multi-tenancy from the first model</title>
    <id>https://avanserv.com/build-log/multi-tenancy-from-the-first-model</id>
    <link rel="alternate" type="text/html" href="https://avanserv.com/build-log/multi-tenancy-from-the-first-model" />
    <published>2026-02-04T00:00:00Z</published>
    <updated>2026-02-04T00:00:00Z</updated>
    <summary>How organisation isolation went into the platform&apos;s base model in its first week, where the automatic filter stops, and what I still owe it.</summary>
  </entry>
  <entry>
    <title>Day one: a multi-tenant framework from an empty repository</title>
    <id>https://avanserv.com/build-log/day-one</id>
    <link rel="alternate" type="text/html" href="https://avanserv.com/build-log/day-one" />
    <published>2026-02-01T00:00:00Z</published>
    <updated>2026-02-01T00:00:00Z</updated>
    <summary>The platform&apos;s first evening: a written plan, a toolchain that refused sloppy code, and the request context that tenancy would hang from.</summary>
  </entry>
</feed>
