Anatomy of a forge engagement
A craft forge reached out to us in late 2024 with a request that looked simple on the surface: a site that reflected the discipline of the craft, and an order channel the owner could operate himself from the workshop, without going through an agency every time a piece in the catalogue changed.
The client is real; we are keeping the name anonymous at the studio’s request. What follows is the anatomy of the engagement — what was built, why, and how it has held up without team intervention over the past year.
Constraints of the engagement
Before the first line of code, we calibrated four constraints that ended up shaping the entire architecture:
- The owner operates the site from his phone, in fifteen-minute pauses between pieces. The admin surface had to fit on one screen.
- The catalogue changes slowly — between three and six new pieces per month. Any heavy CMS would have been waste.
- The operating budget was less than ten euros a month, indefinitely.
- The site had to survive multi-month periods without us touching it.
The architecture we delivered
One box, one database, no optional external services. The mental diagram fits on one line: browser → static CDN → a small VPS with Postgres and a binary.
-- complete workshop database schema
CREATE TABLE pieces (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
slug text UNIQUE NOT NULL,
title text NOT NULL,
description text NOT NULL,
price_cents integer NOT NULL CHECK (price_cents > 0),
status text NOT NULL CHECK (status IN ('draft','published','sold')),
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX pieces_status_created_idx ON pieces (status, created_at DESC);
That is it. Eleven columns, one index, one CHECK constraint over status. The workshop catalogue is pieces; pieces have three states; the site renders the published ones and orders them by date.
The admin surface is a classic HTML <form> posting to an endpoint in the same process, authenticated with a signed cookie. No React in the panel. No SPA. The owner can edit the catalogue from a 3G connection in the middle of a field and the change appears live in two seconds.
Why Postgres for everything
Several people asked us why we did not use a specialized service for images, another for search, another for queues. The answer is the same as always: every new service is an operating commitment the client ends up paying for — in money, in time, or in mental complexity.
Postgres, instead, is a part the owner does not have to maintain. The hosting platform upgrades it; we left it configured with a weekly pg_dump to a cold bucket; recovery is measured in minutes.
What has happened in fifteen months
The site has been in production for fifteen months. In that period we have touched the code four times — three of those at the explicit request of the client (new fields in the order form), one for a minor Postgres migration. Average response time on the primary domain: under 200 ms at p95. Monthly operating cost: under twelve euros, all in.
If you want to see the pattern applied to another sector, read also Small, durable systems — the technical manifesto we start every engagement from.
The criterion that remains
We do not sell sophisticated architectures. We sell systems the client can operate and we can step away from without the client noticing. That is the contract.
— Ithildin Labs