cloudbase.foundation — CMS and build-cost options
Date: 2026-08-07 · Owner: Jonathan · Status: Options for discussion — no decision taken Context: raised when a deploy took longer than expected on launch day. Related: post-launch roadmap
What the build actually costs
Measured against the repo on 2026-08-07.
| What we publish | 12 routes, 13 content files (10 JSON, 3 Markdown) |
| Packages installed per build | 1,806 |
node_modules |
2.1 GB |
| Attributable to TinaCMS | ≥468 MB — @tinacms 178 · tinacms 54 · react-icons 84 · monaco-editor 76 · mermaid 76 |
| Tina admin UI shipped to the Worker | 11 MB, 92 files, on every deploy |
There are no stray dependencies. Direct dependencies are six runtime
(next, react, react-dom, next-intl, tinacms, @tinacms/cli) and nine
dev. react-icons, monaco-editor and mermaid are not ours — npm ls
traces all three to tinacms alone. The tree is Tina.
The build is three sequential passes: tinacms build (generates a schema and
typed GraphQL client, then indexes content against Tina Cloud over the
network), next build, then opennextjs-cloudflare build, which re-bundles
the whole Next server into one Worker.
The tinacms build pass is the disproportionate one. It needs TINA_TOKEN
exported, it requires a 4 GB heap — it died with "Reached heap limit" on
3 August — and it makes network round-trips to a hosted service. That cost is
fixed. It would not shrink if we deleted every page, and it will not grow much
as content grows.
What Tina is buying us
Not nothing — this is the part that makes the decision real rather than obvious.
- 40 "TinaCMS content update" commits, 11 May → 3 August, from at least two editors. It is in genuine use, not shelfware.
- Product Principle #5 is "the staff can change the words" — narrative content editable without a developer and without a deploy. Removing Tina without a replacement breaks a stated product principle, not just a convenience.
- Real-time preview: editors see changes live as they type.
Worth noting the split we already run: narrative content is in Tina, but UI
microcopy lives in messages/en.json / es.json and is edited by developers,
in git, with no CMS at all. So both models are already in production here.
The coupling, honestly
Every fetching page.tsx imports the generated client and calls
client.queries.<name>({ relativePath }), then passes data, query and
variables into a *PageClient.tsx that calls useTina() and uses generated
TypeScript types. That is roughly 12 files across six page pairs, plus the
tina/ directory.
The content itself is already plain JSON and Markdown in the repo. Nothing is locked in a proprietary store — this is a code-coupling problem, not a data- migration problem. That is what makes every option below tractable.
Option 1 — Keep Tina, cache the install · in progress
Turn on Build Caching in Workers Builds. Nothing else changes.
- Effort: one dashboard toggle. Risk: none. Reversible: instantly.
- Fixes: the 1,806-package install, likely the largest single block.
- Does not fix: the
tinacms buildpass, the Tina Cloud round-trip, the 4 GB heap, or the 11 MB of admin assets shipped on every deploy.
The honest first move regardless of what we decide long-term — it is cheap and it tells us how much of the wait is install versus Tina.
How: Cloudflare dashboard → the cbf-site Worker → Settings → Builds →
Build Caching. It is a dashboard setting, still in beta; there is no wrangler
command and nothing in wrangler.toml for it, so it cannot be scripted or
code-reviewed. Whoever enables it should note the date here.
Baseline to beat — measured on the launch-day deploy, uncached:
| PR #14 merged | 2026-08-07 14:27:16Z |
| Worker deployment created | 2026-08-07 14:46:48Z |
| Wall clock | 19 min 32 s |
The next push after caching is enabled is the comparison. If it lands near 19 minutes, the install was never the problem and the cost is Tina and OpenNext — which makes Option 3 considerably more attractive. If it drops sharply, Option 1 may be the whole answer and the rest of this document can wait.
Either way the number is worth recording here rather than remembered.
Option 2 — Keep Tina for editing, remove it from the build
Read content/*.json directly at build time and delete the GraphQL layer.
Editors keep using Tina, which commits to the repo as it does now; the site
simply stops querying it.
- Effort: the ~12-file refactor. Risk: medium.
- Fixes: the
tinacms buildpass and the Tina Cloud dependency. - Costs: real-time preview goes away — editors save, then wait for a build.
Keeping the
/adminUI working still means keeping the packages somewhere.
The awkward middle. It removes the build cost but keeps the dependency, so the saving is smaller than it looks.
Option 3 — Replace Tina with PagesCMS
We already run PagesCMS on the documents repo. Same organisation, same
pattern, known quantity, no new vendor and no new account.
PagesCMS is entirely external — it edits files in the repo through GitHub and contributes zero npm packages and zero build steps.
- Effort: the same ~12-file refactor, plus porting
tina/config.tsto a.pages.yml. Risk: medium. - Fixes: all of it. 468 MB of dependencies, the whole
tinacms buildpass, the 4 GB heap, and 11 MB of shipped admin assets — to zero. - Costs: no real-time preview. Editing UI is less polished than Tina's. Staff who have learned Tina have to learn something else.
- Preserves Product Principle #5: staff still edit without a developer.
Strongest candidate on the numbers, and the least novel — we would be consolidating on a tool we already operate rather than adopting one.
Option 4 — No CMS
Content edited in git by developers, like messages/*.json already is.
- Effort: the refactor, minus any CMS wiring. Risk: low technically.
- Cost: breaks Product Principle #5 outright. Every copy change becomes a developer task.
Named for completeness and for the honest reason that it is the cheapest to build. Recommending it would mean deciding the principle was wrong — which is a board-level call about how the organisation works, not an engineering one.
For the discussion
- Do Option 1 now regardless. It is cheap, reversible, and it produces the measurement the rest of this depends on.
- The real question is 3 versus 1. Is a polished editing experience with live preview worth ~468 MB, a build pass and a hosted dependency — for thirteen content files?
- Who actually edits, and how often? Two people, forty times in three months. If that is the steady state, it is worth asking whether it justifies the heaviest thing in the stack.
- What we do not know yet: the wall-clock split between install, Tina, Next and OpenNext. Nobody has read a Workers Build log for this project. We now have a total — 19 min 32 s uncached — but not a breakdown. Option 1 gives us the comparison; the build log itself would give us the split. Any decision made before both is a guess.
Nothing here is a recommendation to act during launch week.