Signal Architecture Research
The Things We Don't Install
September 13, 2026 · 7 min read
Clients ask us some version of this early on: why does your stack not have the things everyone else's stack has? No WordPress. No Cloudflare. No page builder. No JavaScript framework. It usually arrives politely, phrased as curiosity, and underneath it is a fair question about whether we are being principled or just stubborn.
The answer is that we apply one test to everything, and these are the things that fail it. The test is not whether a tool is good. Most of them are excellent. The test is whether it puts a copy of the truth somewhere we cannot inspect.
The test
Our architecture rests on one property: a fact lives in exactly one place, and everything else is generated from it. The page, the structured data, the sitemap, the internal links, the machine-readable catalog. Nothing is typed twice, which means nothing can quietly disagree with itself. We wrote about why that matters in From Websites to Signal Systems back in June, and it has been the load-bearing idea ever since.
So when we evaluate anything, we ask:
If this is wrong, how would we find out?
That is the whole test. Not "is this fast", not "is this popular", not "does this scale". If a component can be wrong in a way that produces no error and no symptom, it is a component we have to check by hand forever, and checking by hand forever is the thing the architecture exists to eliminate.
Most of what we leave out fails on exactly that. It does not fail loudly. It fails silently, and it keeps serving pages while it does.
WordPress
Roughly 40 percent of the web runs on WordPress, and for good reason. It is mature, the ecosystem is enormous, and a non-technical editor can be productive in it on day one. Those are genuine advantages and we are not going to pretend otherwise.
What it does to our test is this. Your content lives in a database, as rows, rendered through a theme and a chain of plugins. Ask the question: if a fact is wrong, how would you find out?
You would open the admin, search, and hope you searched the right way. You cannot diff a database the way you diff a file. You cannot read a row without a tool. When the same claim about the business appears in a widget, a page, a meta description, and a plugin's schema output, those are four copies, and nothing forces them to agree. They drift apart gradually and nobody is notified.
Then there is the rendering. Pages are assembled by code from many authors, several layers deep, updating on independent schedules. When something changes about the output, tracing it back to the cause is genuine archaeology.
Our content is files. A glossary term is a file. An article is a file. The organization description is one value in one file, and every place it appears reads from there. If you want to know what the site claims about something, you open it and read it. So can a machine, which turns out to matter more than we expected.
Cloudflare
This one costs us something specific and measurable, so it is worth being precise.
A full proxy replaces the visitor's IP address in your server log with its own edge address. For almost everyone that is a non-event, because almost nobody reads their server logs.
We read them. It is where the evidence comes from. Here is the current retained window across the portfolio, 2026-08-09 through 2026-09-13, 130 sites:
| Visitor class | Requests | Distinct IPs |
|---|---|---|
| Bots | 3,779,875 | 44,152 |
| Scanners | 2,445,548 | 12,419 |
| AI crawlers | 346,994 | 6,657 |
| Humans | 259,211 | 89,444 |
| Total | 6,831,628 | 146,430 |
Every row in that table is a classification, and every classification begins with the IP address. We resolve addresses to the networks that own them, currently 12,620 distinct autonomous systems across 214 countries, which is how we separate a real crawler from something wearing its name. Two of the six largest sources of AI crawler traffic in that window were OVH and IONOS, which are commodity hosting companies that do not operate AI crawlers. That is a useful thing to be able to see.
You can restore the original address behind a proxy. It travels in a header and an Apache module puts it back in the log. We are not claiming the data is hidden. We are pointing out that it becomes a per-site configuration dependency whose failure mode is silent: misconfigure it and nothing errors, the logs simply get less true while the reports keep rendering with the same confidence as before.
Apply the test. If it is wrong, how would we find out? We would not. That is the disqualifier, not the proxy itself.
We would still add it for a site under actual attack, or one serving heavy media globally, or where a compliance requirement calls for a managed firewall. Then we would restore the addresses and re-verify the classifications deliberately, instead of assuming.
Page builders and plugin stacks
Same failure, different shape. A page builder stores layout and content together in a serialized blob. The text of your value proposition ends up encoded inside a structure that exists to describe columns and spacing.
That content is now unreadable to anything except the builder that wrote it. Not private. Just impractical to read, which in practice is the same thing. You cannot generate structured data from it reliably, you cannot audit it across a portfolio, and you cannot move it anywhere without a rewrite.
JavaScript frameworks for content
We use JavaScript. We do not use it to deliver content that has to be understood.
Here is the reason, from the same window. Of 346,994 AI crawler requests:
| What was requested | Requests | Share |
|---|---|---|
| HTML documents | 301,842 | 87.0% |
| JSON endpoints | 29,318 | 8.4% |
| Images, CSS, fonts | 10,200 | 2.9% |
| JavaScript files | 5,634 | 1.6% |
AI crawlers asked for the JavaScript on 1.6 percent of their requests. They asked for the document 87 percent of the time.
Two caveats, because this number is easy to over-read. Requesting a JavaScript file is not the same as executing it, so this is a ceiling on execution, not a measurement of it. And Google's indexing infrastructure does render JavaScript, so this is not the 2015 argument about client-side rendering and search. It is a narrower claim: if your content only exists after JavaScript runs, the crawlers in this table mostly are not seeing it, because they mostly are not fetching the script that would produce it.
The other number in that table is the one we find more interesting. 29,318 requests went to JSON endpoints. Those are the machine-readable catalogs and manifests our sites publish. Something is reading them. We want to be careful here: reading is not citing, and we are not going to claim those requests produced mentions, rankings, or anything else. What we can say is that the structure is being fetched, repeatedly, and that is a better position than not being fetchable.
Headless and hosted CMS platforms
Shorter version, because the problem is easy to state. Your canonical content lives on someone else's infrastructure, behind an API, subject to someone else's roadmap and pricing. You are renting the single source of truth.
For a large editorial team with complex workflow needs, that trade is often correct. For a digital asset meant to appreciate over a decade, we would rather own the files.
What this adds up to
Every item above is the same decision applied to a different layer. We are not minimalists and this is not a performance argument. We are protecting one property, and it is worth naming plainly:
Anything that stands between the source records and what actually gets served is a place where the truth can drift without anyone noticing.
What we build instead: structured files as the content layer, generated output for everything downstream, server logs read directly, and published machine-readable endpoints alongside the human pages. When a correction is needed, it is applied once. When something looks wrong, it is readable. When we make a claim about a site, there is a record behind it.
That depth is not plumbing we are apologizing for. It is the product. People tend not to notice it at first, and then at some point they go looking, and it holds up. That is the intended experience.
Where we are honest about the tradeoff
This architecture is not free and it is not right for everyone.
- There is no familiar admin interface. If you need a large non-technical team publishing independently all day, WordPress solves a real problem that we do not.
- It requires server access. Log-based measurement does not work on hosting we cannot read. That is a genuine constraint and it shapes who we can work with.
- It is slower to start. Standing up a structured content layer takes longer than installing a theme. The return comes later, when a correction costs one edit instead of forty.
- For a small static site that will never change, it is over-engineering. The threshold is not page count. It is repetition. Once the same fact lives in two places, you have copies that will drift.
None of these choices are permanent convictions. They are the current answers to one question, and if a tool came along that passed the test, we would use it. Several of these would change immediately if their failure mode were loud instead of quiet.
Until then, the question stands, and it is the same one we would suggest you ask of anything already running on your own site.
If it were wrong, how would you find out?