Kaufman Lab · AI architecture
Website and publishing

A website built with AI

This site was built with an AI model. The approach works on any platform, from a site builder or a CMS to hand-written pages: a person says what is needed and the model builds the pages. An edit takes minutes, not a day.

Volume19 pages from 7 projects
Running cost$0 · 4,391 lines of code
Market rate$4,900/mo — web developer
VerdictWorks

Published Aug 25, 2026 · figures checked Oct 8, 2026

How to build a website with AI: nine steps

  1. Topic and goal. Decide what the site is about and what a visitor should do on it: contact you, buy, or send a request.
  2. Model. Pick Claude, ChatGPT or Gemini. To keep the site on your own machine, Claude Code or Codex works better; Lovable, v0 and Bolt give a quick result in the browser.
  3. Questions for you. Ask: "Ask me 10 questions to understand what kind of site I need, and suggest two structure options."
  4. Research. Ask: "Find five sites in my field, break down their structure and tell me what they are missing."
  5. Tool. Choose what to build with: different jobs need different tools (see the list after the steps).
  6. First version. Ask for finished pages rather than a description, and request edits in plain words: "bigger font", "prices above the fold".
  7. Fact check. Check prices, dates, names and the phone number: the model writes fluently but mixes up facts.
  8. Domain and hosting. In Russia a domain costs about 200 RUB a year (about $2.30) and hosting starts at 200 RUB a month (about $2.30): the cheapest plan is enough for plain pages.
  9. Search. Add the site to Google Search Console and to Yandex Webmaster, the site console of Yandex, Russia's largest search engine. Submit the sitemap, and a week later check how many pages have been indexed.

Which tool for which job

  • Business card site, portfolio, landing page — plain HTML and CSS pages, or a site builder with AI such as Tilda or Craftum.
  • Blog, portfolio of work, documentation — a page generator fed from your data: an edit in one place reaches every page.
  • Online store — a ready-made platform such as InSales (a Russian e-commerce platform) or Shopify, or Lovable: the cart, payments and inventory are already written.
  • Service with a login — Next.js with a database, built in v0, Lovable or Claude Code.

Below is how this site itself is made: what was built, what it cost and what was given up in return.

01 · Stages

Where the project is now

DoneBuildbuild.py, 1,853 lines, no dependencies
DoneCheckcheck.py, 645 lines, 19 rule groups
DoneGeneratorarticles/, 1,662 lines, eight modules
DoneArticle stylesproekt.css, own fonts, no Google
DoneTextsall seven texts written, figures cross-checked
DoneServerlive since Aug 27, 2026, own server and TLS

The code is written and works. On this machine the build and the check together take 0.31 seconds.

Over the past day an article generator was added. A project page used to be assembled from markdown with a single template; now a finished article arrives as a separate file with its own diagram and its own numbers.

02 · Task

What was needed

There is one requirement: a lab whose whole position rests on verifiability needs a showcase that can be verified too. The numbers on the pages must agree with each other without anyone keeping watch, and every claim needs an address where it can be opened and checked.

The constraint that shaped the whole design: one edit in the source has to reach nine places. They are the registry on the home page, the counter in the topic chip, the "Total" row, the topic page, the ItemList markup, the sitemap, llms.txt, the "read also" block on a neighbouring page and the project page itself. Nine places cannot be kept in sync by hand.

MethodWhat we took from itCanonical name · source
One owner for the data · single source of trutha figure that repeats lives in src/data and reaches the text through the build. The number of projects is counted once, as the length of a listSingle source of truth; the DRY principleHunt & Thomas, "The Pragmatic Programmer", 1999
Split by checkability · error versus warningwhat can be checked mechanically stops the deployment; what needs human eyes is printed as a warning and does not block itSeverity levels: an error stops, a warning does notthe lab's own rule, no external source
Fail loudly, not silentlya stray closing tag is caught by parsing the markup and returns exit code 1 instead of reaching the server unnoticedFail fast; a gate before deploymentShore, "Fail Fast", IEEE Software, 2004
Acceptance by thresholds · the bar is set before the runthe thresholds are written in check.py, not in a checklist someone has to remember: exactly one h1 per page, a description present, a canonical presentPreregistered thresholds; WCAG 2.1 AA for contrastNosek et al., PNAS, 2018 · W3C, WCAG 2.1, 2018
Exact match instead of trustthe sitemap is compared with the files that actually exist, set against set: an extra address and a missing one are both errorsSet reconciliationthe lab's own rule, no external source
Tests at the seams · the seam between build and serverhashes of inline scripts are recalculated on every build and compared with what the nginx policy saysContract tests at the build → server boundaryFowler, "IntegrationContractTest", 2011
Deliberate exceptions with a reasona waived check goes into a separate file with an explanation, and the threshold stays as it is: five lines about the contrast of the brand magenta lived there until the color was darkened on Sep 8, 2026Documented exceptions (waivers)the lab's own rule, no external source
03 · Build

How it is built

The site was built together with an AI model (Claude): the change history has more than 280 commits, 229 of them marked as co-authored by it. A person states what should appear on the page, the model writes the markup, the styles and the build code, and the person accepts the work and decides what goes live. This way of working does not depend on the platform. A site on a site builder or a ready-made CMS can be run the same way; only the place where the result lands changes.

The pipeline is linear and one-way: src/ is read, site/ is written, and nothing flows back. The build reads seven projects, six research pages, fifteen data files and three pages, and creates 41 files, 21 of them HTML. It also recalculates the hashes of inline scripts and writes the finished security policy line to site/csp.txt.

Next, check.py reads the built files, not the sources: it checks the exact bytes that will go to the server. An error returns exit code 1, and deployment stops before the first file is copied.

The article generator sits outside this pipeline. It takes no part in building the site: an article is written once, placed in src/projects/ as a finished page and from then on only copied. It uses the same cell length limits as the check: a table of nine numbers lives in one file that both read.

SOURCESmarkdown, CSV7 projects · 15 data files · 3 pagesGENERATORarticles/ 1,662 linesJSON draft → finished pageBUILDbuild.py, 1,853 lines41 files, 21 HTMLCHECKcheck.py, 645 lines19 rule groups, 0.19 sno errorserror foundDEPLOYrsync --deleteSTOPexit 1 · no deployLIMITS9 cell limitsdashed: length limits · pink: the gate in front of deployment
The check sits between the build and the server, not after it: an error returns exit code 1, and rsync never runs.

A rule you cannot break by accident is worth more than a rule you have to remember.

04 · Rules

What holds the design together

Six rules, and none of them is a mere agreement: each one has a check behind it that returns exit code 1 and stops the deployment.

1
One sourcea figure that repeats lives in the data and reaches the text through the buildthe number of projects is counted once, as the length of a list, and goes to the ItemList markup, the chip counter, the "Total" row and llms.txt. The check compares all four places with each other
2
No hand-edited HTMLthe output folder is overwritten on every buildchanging a menu item is one line in menu.csv instead of 21 pages. Anything written into site/ by hand disappears on the next run
3
The checka gate, not advice: an error returns exit code 1the deploy script has set -euo pipefail, and the check runs as the second step, before rsync. There is no way around it without rewriting the script
4
Author textis always data: values are escaped on outputthe source dictionary returns values already escaped, and a raw value takes a separate call. Escaping can only be skipped on purpose
5
One external requestown fonts and styles, one third-party addresseight woff2 files instead of Google Fonts. On kaufmanlab.ru the only third-party address is the Yandex Metrica counter, Yandex's web analytics: it is named in the site data and allowed by name in the security policy. The check treats any other address as an error
6
Scripts allowed by hashfour inline scripts are listed by sha256the build computes the hashes and writes them as a ready line for nginx. A script edited without a rebuild would be blocked on the server, and the check reports this in advance
05 · Decisions

Decisions and their grounds

There are few decisions, because almost everything that could have been added was deliberately left out. Each one below explains why something is missing: a framework, a database, dependencies, an admin panel.

DecisionGrounds
Generator on the standard libraryno pip and no lock file: Python already ships with the Mac, there is nothing to install. The only external dependency is playwright, and it is kept separate: only the browser measurements need it, while the build and the regular check run without it
Static pages instead of a CMSno database, no PHP, no admin panel, no forms. There is nothing to break in the pages themselves: the attack surface is the server and nginx, not the site
Own micro-markdown instead of a librarythe site needs a second-level heading, a paragraph, a quote and three placeholder blocks. A full implementation of the spec would pull in a dependency for features nobody uses
An article arrives as a finished pageeach project has its own diagram, its own numbers and its own text length. One shared template cannot hold that, and several templates in one build amount to two builds
The build deletes nothingextra files are printed as a list, and deletion sits behind a separate flag. Otherwise the first mistake in a path would wipe the whole output folder
The 404 page stays out of the sitemap21 HTML files, 19 addresses: the 404 page and the privacy policy stay out. The check requires noindex on the 404 page and, as a separate rule, its absence from the sitemap
Waived checks go in a separate file with a reasonfive lines about the contrast of the brand magenta (4.32 against the 4.5 minimum) stayed there until the color was darkened to 5.00 on Sep 8, 2026. The threshold was never lowered; the file is empty now
Own check instead of an off-the-shelf lintera linter knows HTML, but it does not know that the number of projects on the home page must match the number of source files
06 · Limits

What the design costs

The design is cheap and rigid, and the rigidity is the price of the low cost. Everything that makes the build fast and checkable also shuts the door on anyone who wants to fix a single page on the spot.

DecisionWhat it limits
Static pages without formsvisitors cannot write from the site: the only way to get in touch is a Telegram link in the footer
Own micro-markdowna table, a list or a nested quote in the page body will not build: the parser has no rules for them
HTML only from the buildthere is nowhere to put a one-off edit to a single page: every change goes through the source and a full rebuild
Articles are not rebuiltthe text lives in the finished page. A shared style change spreads by itself, but a wording change has to be made by hand in the file
Policy based on script hashesany edit to an inline script needs a rebuild and a new line in the server config, otherwise the browser will not run it
Markup parsed by our own parserit catches tag balance and broken links, but not validity against the spec: a nesting error inside correctly closed tags gets through
Deployment with a single rsyncthere is no atomic switch: while the upload runs, the server holds a mix of the old and new versions
One editorshared editing in the browser is impossible by design: editing takes repository access and Python on the machine
07 · Result

What came out

addresses in the sitemap19grep -c <loc> site/sitemap.xml, Oct 8, 2026
build and check together0.31 s/usr/bin/time -p, best of five runs, Oct 8, 2026
lines of code, zero dependencies4,391wc -l build.py check.py og.py sokratit.py articles/*.py
pages published19live since Aug 27, 2026, recounted Oct 8, 2026
Lines of code by file
build.py — build1,853
check.py — check645
articles/research.py441
articles/razmetka.py340
articles/shema.py209
articles/sborka.py208
articles/dopolnit.py167
articles/predely.py161
og.py — previews160
sokratit.py71
articles/sobrat.py71
articles/kanon.py65
Section 13 of the showcase standard added 165 lines to the check. On Sep 1, 2026 the generator gained a dictionary of canonical names and the ability to add blocks to finished articles. Grey marks files shorter than a third of the build.
What is in site/ after the build
files in total611.9 MB
created by the build4167%
of them HTML2134%
in the sitemap1931%
The gap between 61 and 41 is the social media images: a separate script, og.py, draws them, not the build. The 404 page and the privacy policy are left out of the sitemap on purpose.

Timings were taken on Oct 8, 2026 on the work machine with /usr/bin/time -p, best of five runs; lines of code were recounted on Oct 8, 2026. Everything that concerns the build and the check is measured.

Building 41 files takes 0.12 seconds, checking the result takes 0.19. Together that is under a third of a second: the loop "edit the source, see the whole site again" is shorter than opening an admin panel. This is how giving up a CMS pays for itself.

The check returns zero errors and zero warnings.

Reliability of the result
Sample
One site, 19 pages, one machine. Build and check times were taken on the work laptop; on another machine the numbers will differ, but the order of magnitude will not.
Spread
Best of five runs, not the average: the measurement shows that the loop fits into a fraction of a second, not how long it usually takes.
Checks
Lines of code are recounted from the repository by the obnovit-stroki.py script, not by hand, in both language versions of this article at once. This is how, on Sep 1, 2026, it turned out that the diagram said 1,148 build lines while the repository had 1,293.
Does not generalize
The market comparison uses a web developer's rate at Upwork; a site builder at 12,000 RUB a year (about $140) covers part of the same job and is compared in the questions below. Both comparisons are valid, but they measure different things.
Not measured
How fast the server delivers pages, and how readers behave: only the build and the check on the author's machine were measured.
Works

The site went live on Aug 27, 2026 and now has 19 pages on its own server with TLS and zero external dependencies in the build. The build and the check finish in 0.31 seconds and return zero errors.

Repeat it yourself
Architectureflowchart above ↑Rulessix rules ↑Build codebuild.py, 1,853 lines

Kaufman Lab is an AI architecture lab. We design processes and methods. Code goes stale with every new generation of models; the method does not, so the method is what each project lays out. Any current AI model can build a system from this diagram.

08 · Pitfalls

What went wrong

A review on Aug 24, 2026 went through every page in the light and dark themes and produced 20 findings; 17 were fixed the same day. Below are the ones that became check rules: an error that is only caught by eye keeps coming back.

beforeafter126

Projects on the 404 pagea repeated number lives in one place

One stray closing tag broke the layout of all six pagesthe "Pitfalls" section, related projects and the footer broke out of the column and spread across the full screen width. Now a rule: tag balance is parsed on every build
The 404 page promised twelve projects while the site had sixthe figure was typed by hand, a leftover from an old mockup. Now a rule: a repeated number lives in one place and is checked everywhere it appears
Three pages linked to code that no longer existedthe methodology, questions and dashboard pages still pointed to the repository after it was made private. Now a rule: every internal link is checked for an existing file
The "Prompt" and "Data" links led to an empty anchorthe placeholder looked like a working link with an arrow, but clicking it went nowhere. Now a rule: href="#" is an error, not a detail
The generator cut captions at thirty charactersthe number strip ended up with "answered the client's question and t". Now a rule: if it does not fit, rewrite it shorter; cutting at a character count is not allowed
The registry ran off the screen in a 414 px windowthe cause was a shared minimum-width rule for tables. Now a rule: horizontal scroll is measured in the browser at six widths
A menu item had to be edited on fourteen pages at oncenow a rule: anything that appears on every page lives as one line in a data table
09 · Possibilities

What else can be added to the code

Everything that repeats lives in src/data, and check.py stands as a gate before deployment. So a new block, language or rule is added as a data row plus a check, without reworking the build. Below is what could strengthen the site next, paid services included.

SpeedA performance budget at the build gateLighthouse CI runs every page in a browser and compares weight, render time and accessibility with set thresholds. The threshold goes into check.py next to the other checks. A page that has grown heavier will not reach the server until it is slimmed down.
AI modelsA "question → page" tableThe dashboard already measures a fixed set of 20 questions. The table will show, for each question, which page of the site made it into the AI model's answer. An empty cell becomes the brief for the next article.
SearchSite search with no database or serverPagefind builds a search index during the build, and its files sit on the site's own domain next to the pages. No database, forms or third-party addresses are needed, and any addition to the security policy is made by name. A reader finds a project by a word instead of scrolling the registry.
DeploymentA new version goes live in one switchThe build is uploaded to a new folder on the server, and nginx moves to it by changing one link. Readers never see a mix of old and new versions, and a rollback is the same switch in reverse.
TeamText edits from the browser through CIThe build and the check can run in CI, for example GitHub Actions, on every commit to a private repository. A second author edits texts and data tables in the web interface without Python on their machine. check.py guards the gate the same way: if it finds an error, nothing is deployed.
DeliveryPages served from the node nearest the readerFinished files with no database suit a CDN as they are, for example Yandex Cloud CDN or Selectel CDN, two Russian providers. The server stays the origin, while pages and fonts are served from a node close to the reader. A traffic spike lands on the CDN, not on the site's own server.
10 · Questions

What people usually ask

Below are the questions people ask about the design itself: what giving up a site builder costs, how much it takes to keep the site running and why the build works the way it does.

What is an AI-built website?

An AI-built website is a site whose pages an AI model writes and assembles, while a person sets the task and accepts the work. It suits a studio or a lab that needs the numbers on its pages to agree with each other. The Kaufman Lab build makes 41 files from markdown and tables and verifies them with a check before deployment. It gives no admin panel, no forms and no text editing in the browser.

How much does it cost to keep a site like this?

The build itself costs nothing: no paid services, no subscriptions, only Python, which is already on the machine. You pay for the domain and the server, and that is the only expense line. Elsewhere the same set of features comes with a subscription: Tilda Business costs 12,000 RUB a year (about $140) by its published price list, and that price includes an editor this site does not have and will not have.

Why doesn't the build delete extra files by itself?

Because the first mistake in a path would wipe the whole output folder. Extra files are printed as a list at the end of the run, and deletion sits behind a separate --chistka flag that has to be typed by hand. This order costs one extra line of output and removes a whole class of failures in which the generator erases files it did not build.

What stops you from editing one page by hand?

Nothing: the edit simply disappears on the next build, because the site/ folder is overwritten in full. This is not a side effect but what keeps the numbers consistent. Once one page may be edited on its own, the number of projects on the home page stops being the same number as in the sitemap, and there is nothing left to check.

What stops deployment if the markup has an error?

The check is the second step of the deploy script, before rsync, and it returns exit code 1. The script declares set -euo pipefail, so a non-zero code stops it before the first file is copied. There is no way around this order without rewriting the script itself: the list of rules and the deployment threshold live in one file.

What external requests does the site make?

On kaufmanlab.ru, exactly one: the counter of Yandex Metrica, Yandex's web analytics. Eight font files sit on the site's own domain instead of Google Fonts, and there are no images from other servers. The security policy starts with default-src 'none', and inline scripts are allowed by name through their sha256 hash. The only third-party address in it is mc.yandex.ru; the check treats any other as an error and stops deployment. This is a rule, not a recommendation.

How long does a full rebuild of the site take?

Building 41 files takes 0.12 seconds and checking the result takes 0.19; together 0.31, best of five runs of /usr/bin/time -p on Oct 8, 2026. What matters in practice is not speed but the length of the loop: editing the source and viewing the full result fit into one keystroke, so checking the whole site is cheaper than looking at one page.

Which platforms work if you build a site with AI?

The way of working does not depend on the platform: the AI writes the markup and the text, and the result can go into a site builder, a ready-made CMS or your own pages. This site takes the third path: pages are built in advance and served as finished files.

What does the AI do by itself, and what is still done by hand?

The AI writes the markup, the styles and the build code. A person states the task, accepts the work and starts the deployment: it runs from the person's machine, and there is no automatic version switch on the server.

How long does one edit take?

Building 19 pages takes 0.12 seconds, and 0.31 seconds together with the check, on the work laptop. How fast pages reach the reader was not measured.

Sources
  1. Hunt A., Thomas D. The Pragmatic Programmer. Addison-Wesley, 1999 — the DRY principle: every piece of knowledge has a single authoritative representation.
  2. Shore J. Fail Fast. IEEE Software, 21(5), 2004. doi:10.1109/MS.2004.1331296
  3. Nosek B. A., Ebersole C. R., DeHaven A. C., Mellor D. T. The preregistration revolution. PNAS, 115(11), 2018. doi:10.1073/pnas.1708274114
  4. Fowler M. IntegrationContractTest, 2011. martinfowler.com
  5. W3C. Content Security Policy Level 2, 2016 — hash-source. w3.org
  6. W3C. Web Content Accessibility Guidelines (WCAG) 2.1, criterion 1.4.3 Contrast (Minimum), 2018. w3.org
  7. OWASP. Cross Site Scripting Prevention Cheat Sheet — output encoding. cheatsheetseries.owasp.org

Need a system like this?

Message me on Telegram: I answer myself, look at your task and tell you which of this fits it.

Message on Telegram→
More projects from the lab
↑ top