SynaptrixAI
All notes
craft web

Boring on purpose

This site is static HTML with no JavaScript and no dependencies, built by a script we wrote. Here is the reasoning, and the bug that shows where the reasoning runs out.

The page you are reading is a static HTML file. There is no framework, no client-side JavaScript, and no node_modules directory anywhere in the project. It is assembled by a build script of roughly 300 lines that we wrote, and served as plain files.

That is an unusual choice in 2026 and it is worth explaining, including the part where it is the wrong choice.

What the site actually needs to do

Twelve pages. Some product descriptions and some articles. A menu, a list, some prose. New articles perhaps monthly. Two people will ever edit it.

Held against that, most of what a modern web toolchain provides is insurance against problems this site does not have. There is no interactivity to manage, no state to synchronise, no team large enough to need enforced conventions, and no scale at which a runtime would earn back what it costs.

What it does have is a maintenance cost that is easy to underestimate: every dependency is something that will need updating, will eventually publish a breaking change, and may one day be the reason the site cannot be rebuilt because a package disappeared. For a marketing site that must simply keep working for years with occasional edits, that cost is the whole risk.

Where the effects show up

Removing the runtime is not an aesthetic preference. It has concrete consequences:

  • The two behaviours that look like JavaScript — the progress rail that fills as you scroll, and the header gaining a hairline when it sticks — are CSS. Scroll-driven animations and scroll-state queries handle both, on the compositor, with nothing to load and nothing to execute.
  • Browsers without those features get a static rail and a plain header. Nothing is broken; the page is simply quieter. That is progressive enhancement doing its job, and it is only affordable because the effects are decorative.
  • The pages are files. They cannot fail to hydrate, they render before the fonts arrive, and they will still work if every service we depend on is down.

The build step exists for exactly one reason: so that a rename cannot silently break a link. Every internal href is checked against the files actually written, and the build fails on a dead one. That is the specific problem a hand-maintained set of HTML files has, and it is worth a script to solve.

The dependency we did not take, and the bug that followed

We render the articles from Markdown. The obvious move is to install a Markdown library. We wrote a small one instead — a documented subset that covers exactly what these articles use.

Then we got it wrong.

The first version handled inline code by pulling each code span out of the text, leaving a numbered placeholder behind, applying the emphasis rules to what remained, and putting the code back by matching the numbers. It reads fine. It passes an obvious test.

It also destroys any paragraph containing a bare number. Take a sentence with a code span in it and the words "in 2 years" later on, and the substitution finds the 2, decides it is placeholder number two, and replaces it with a copy of the code span.

The fix was to stop using placeholders at all: split the text into alternating prose and code segments, and apply the inline rules only to the prose. Collision is then impossible by construction rather than unlikely by convention. There is a test named after that exact sentence.

We are telling you this because it is the honest cost of the position. Writing your own version of a solved problem means you own its bugs, and you will have some. A published library would not have had that one — thousands of people would have hit it first.

So when is this the wrong call?

Nearly always, is the honest answer. The calculus that favours hand-rolling here depends on conditions that mostly do not hold:

  • The scope is genuinely small and genuinely stable.
  • The people maintaining it wrote it.
  • Being wrong is cheap. A rendering bug on a marketing page is an embarrassment, not an incident.

Change any one of those and the answer flips. For a client product we reach for the well-maintained library every time, because there the cost of a subtle bug is someone's business, the person maintaining it in two years is not us, and "we wrote our own" is a liability rather than a virtue.

Boring is not the same as minimal, and it is not a badge. It means choosing the option whose failure modes you already understand, and being clear-eyed about which option that actually is for the thing in front of you. For this site, that is a folder of HTML. For the software we build for other people, it is almost never that.

More notes

Tell us what you need built.

Send us the problem in a paragraph — what your company does, and what the software should take off your hands. We will tell you honestly whether we are the right studio for it, and what it would take.

hello@synaptrixai.com