FOUNDER

Code of Maat

Code of Maat is my agency: software, AI and design. I built our starter theme and the GitHub Actions pipeline that deploys client sites.

ROLE
Founder
PLATFORM
Vite, Tailwind v4, ACF page builder, GitHub Actions

Challenge

My agency: software, AI and design. Websites, web and mobile apps, AI integrations. I built our starter theme (Vite, Tailwind v4, an ACF page builder) and the delivery pipeline: GitHub Actions with lint, type-check, build, atomic deploys with rollback and route checks, behind Cloudflare. Eight client sites built on it so far: clinics, a music school, artists and cultural organisations.

The client-site server has no Node. The build runs in CI, and only compiled output reaches the server. One extra parenthesis in a template reaches the server as a 500. An error in a page template had gone unnoticed while only the homepage was checked.

The agency’s own site was rebuilt, and its home page was checked against an approved design, section by section. The integration plan was written so that several engineers could work in parallel without talking to each other.

CRT line drawing: the scales of Maat over a four-stage pipeline: lint, type-check, build, deploy, close up
CRT line drawing: the scales of Maat over a four-stage pipeline, close up.

Approach

The agency theme renders every page as a stack of ACF flexible-content blocks, styled with Tailwind v4 utilities and built with Vite 8. A block is three files with the same name: field definition, renderer and an optional admin thumbnail. Renderers receive plain arrays and never call get_sub_field(). So the same renderer also works from a PHP array on the 404 page, the case single and the closing screen.

Each task in the integration plan owned listed files, and the shared contracts were fixed in the document. Section redesigns ran as rounds of standalone HTML artefacts, one per assigned direction, each screenshotted at 1440×900 and 390×844. Visual agents wrote the four service-header animations in parallel. A fix pass then worked from a verifier’s report on the four headers and fixed all high and medium findings.

Design variant sheet: a grid of twelve screenshots of the section 'How a project runs. Stop after any step.' Three rows show three options, labelled in Romanian '1 · Câmp de mozaic' (mosaic field), '2 · Linia în spațiu' (line in space) and '3 · Blueprint'. Four columns show each option at the steps Talk, Agree, Build and Hand over, with red, pink and white 3D blocks, lines and grids beside a numbered list of steps.
A design variant sheet: twelve screenshots of the section "How a project runs. Stop after any step." Rows show three options (mosaic field, line in space, blueprint); columns show the steps Talk, Agree, Build and Hand over.

Architecture

The client-site deploy I built runs in GitHub Actions on every push to main. It runs php -l on every PHP file, builds, and fails if manifest.json or the compiled CSS is missing. The theme is synced into a new directory. Two consecutive mv commands at the end switch it live, so the site never runs a half-copied theme. Then the job requests a list of routes and fails on any status other than 200, or on a PHP fatal-error message.

The agency theme has three entries: main on every page, home only where a visible hero_corridor or doors_3d row is, and styles. three.js r128 is vendored, never bundled, and printed only with the home entry. Inner pages request no three.js and create no WebGL context. Lazy hooks mount each module when its markup comes near the viewport, so pages without a block never download its code.

When three.js is missing or WebGL is unavailable, the hero adds html.no-gl, shows a poster, and the scene returns early. A hero-go fallback in the page head shows the hero copy after 2.6 s, even if the hero script never runs.

Code of Maat home page hero on a 1440 by 900 desktop screen. On a dark background, two walls of red pixel blocks recede towards a small red square in the centre, with thin red lines running to it. The headline 'Agents do the work. Your people decide.' sits at lower left; a short description, a red 'Talk to an engineer' button and a 'Watch an agent work' link sit at lower right. The top bar holds the logo, Services, Work, How we work and a red 'Book a call' button.The desktop hero's no-WebGL fallback at 1440 by 900. A static image of red pixel-block walls on both sides stands in for the 3D scene, without the centre square and lines. In front of it are the headline 'Agents do the work. Your people decide.', a red 'Talk to an engineer' button and an outlined 'See an agent at work' button.
The agency's home page hero at 1440×900: the 3D scene of red pixel-block walls, and the no-WebGL fallback, a static image of the walls.

Decisions

  • Services are child pages, not a custom post type: “There are only four.” Each needs its own block composition, and a custom post type would need its own templates and an archive replacement.
  • Content lives in seed files: running one twice leaves the database byte-identical.
  • three.js stays at r128, because the approved scene depends on r128 colour handling and on APIs that were removed later. The vendored file is served from the site’s own origin, not a CDN. That avoids an extra DNS and TLS handshake on the hero intro’s critical path.
  • I asked for no WebGL on service pages and the 3D devices only on the homepage. The per-service 3D headers came out, and inner pages went back to no WebGL context and no MAAT3D code.
  • The homepage section “What do you want to build” moved from the 3D devices scene to an abstract WebGL line, then to four canvas 2D columns. I approved the columns with two tweaks: bigger, redder diagrams and no swipe carousel on phones. With the columns, Home creates 2 contexts, one fewer than with the line.
  • Only one deploy runs at a time, and a running one is never cancelled. Two runs would rewrite the same files, and a stop mid-sync would leave the theme incomplete.
  • The server’s host key is pinned from a secret, so a man-in-the-middle cannot receive the deploy.
  • The deploy stops if the ACF field-group JSON on the server changed since the last deploy. An admin edit then reaches git first instead of being deleted.
  • Hashed JS and CSS files from the previous build that changed within the last week stay next to the new ones. Tabs opened before the deploy can still load their chunks.
Client-site deploy: keep recent hashed files, then switch the theme with two mv commands
# Keep the previous build's hashed files next to the new ones: tabs opened
# before this deploy can still load the chunks they ask for.
# (-p keeps their date, so after a week they drop out instead of piling up)
if [ -d "$THEME_DIR/assets/dist" ]; then find "$THEME_DIR/assets/dist" -maxdepth 1 -type f ( -name '*.js' -o -name '*.css' ) -mtime -7 -exec cp -p --update=none {} "$RELEASE/assets/dist/" ; || true; fi
mkdir -p "$(dirname "$BACKUP")"
rm -rf "$BACKUP"
if [ -d "$THEME_DIR" ]; then mv "$THEME_DIR" "$BACKUP"; fi
mv "$RELEASE" "$THEME_DIR"
The same hero on a 390-pixel-wide phone screen. Red pixel-block surfaces above and below a small outlined square in the centre, with red lines leading to it. Below them are the headline 'Agents do the work. Your people decide.', a short description, a full-width red 'Talk to an engineer' button and a 'Watch an agent work' link. The header holds the Code of Maat logo, a Menu button and a red 'Book a call' button.
The agency's home page hero on a 390-pixel-wide phone screen.

Outcome

site.spec.js checks every page for a skip link, visible focus, alt on every image, one H1 and no sideways scroll. The integration pass recorded content-rules.mjs --all at 29 loads, 0 failing; php-lint.sh at 107 files, 0 errors; and site.spec.js at 59 passed, 1 skipped. Verification measured Home parity at 0–0.017 % for every DOM and canvas section.

The performance table passed 48 of 56 rows, with TTFB 125 ms and CSS 28.7 / main 10 / home 24.5 KB gzipped. The desktop TBT rows were recorded as FAIL on a machine with load average 8–15. In the same session, the approved file measured a desktop TBT of 131 ms and the built site 132 ms. Autoloading the site options cut MySQL Com_select per logged-out /about/ request to 43, from about 124.

A verifier’s cleanup script once deleted the real case studies, because name__in is ignored. The seeds restored them, and the rule became: delete only by recorded IDs.

> OUTPUT: Multilingual sites, schema.org graphs, llms.txt and WebGL heroes with fallbacks, plus a GDPR-grade patient portal with magic-link login and private uploads. The agency's own site is designed with multi-agent design pipelines.

  • WordPress
  • ACF
  • Tailwind v4
  • Vite
  • three.js
  • GSAP
  • GitHub Actions
  • Cloudflare
  • Playwright

ALL_FRAMES

CRT line drawing: the scales of Maat over a four-stage pipeline: lint, type-check, build, deploy, close upDesign variant sheet: a grid of twelve screenshots of the section 'How a project runs. Stop after any step.' Three rows show three options, labelled in Romanian '1 · Câmp de mozaic' (mosaic field), '2 · Linia în spațiu' (line in space) and '3 · Blueprint'. Four columns show each option at the steps Talk, Agree, Build and Hand over, with red, pink and white 3D blocks, lines and grids beside a numbered list of steps.Code of Maat home page hero on a 1440 by 900 desktop screen. On a dark background, two walls of red pixel blocks recede towards a small red square in the centre, with thin red lines running to it. The headline 'Agents do the work. Your people decide.' sits at lower left; a short description, a red 'Talk to an engineer' button and a 'Watch an agent work' link sit at lower right. The top bar holds the logo, Services, Work, How we work and a red 'Book a call' button.The desktop hero's no-WebGL fallback at 1440 by 900. A static image of red pixel-block walls on both sides stands in for the 3D scene, without the centre square and lines. In front of it are the headline 'Agents do the work. Your people decide.', a red 'Talk to an engineer' button and an outlined 'See an agent at work' button.The same hero on a 390-pixel-wide phone screen. Red pixel-block surfaces above and below a small outlined square in the centre, with red lines leading to it. Below them are the headline 'Agents do the work. Your people decide.', a short description, a full-width red 'Talk to an engineer' button and a 'Watch an agent work' link. The header holds the Code of Maat logo, a Menu button and a red 'Book a call' button.CRT line drawing: the scales of Maat over a four-stage pipeline: lint, type-check, build, deployCRT line drawing: the scales of Maat over a four-stage pipeline: lint, type-check, build, deploy, tuning in from staticCRT line drawing: the scales of Maat over a four-stage pipeline: lint, type-check, build, deploy, at phone density

FIELD_NOTES

  1. WEB & INFRA6 MIN An atomic deploy pipeline for WordPress themes Atomic deploys for WordPress themes: build in GitHub Actions, lint PHP, sync to a new directory, switch with two renames, then check the routes.