How a Data-Driven Tools Subsystem Works: Adding a Calculator Is a Config Entry
This site's /tools section is built to be extended without touching code. A new calculator is a YAML entry plus one math function. Here is how the pieces fit, because the architecture is the product.
The three layers
1. Definitions (YAML). Each tool has a page-level entry — title, slug, SEO description, intro — in a single calculators.yaml:
- id: sqlite-size
title: "SQLite Database Size Estimator"
slug: sqlite-size
meta_description: "Estimate disk usage from rows, row size, and indexes."
intro: "Planning a SQLite-backed app? Estimate before you build."
2. The math engine (Go). The actual formulas live in a tested Go package. Each calculator is a Def with typed inputs and a Compute function, registered by ID. This is the source of truth.
3. The front-end (JS mirror). The browser needs to recompute as you type. The same math is mirrored in a plain JS file, so pages work with zero backend round-trips.
Why the split matters
- Server-side defaults for SEO. The Go engine computes results with default inputs at render time, so every tool page ships with real numbers in the HTML — before any JavaScript runs. No-JS users and search engines see a working calculator.
- Client-side for interactivity. The JS mirror recomputes on every keystroke. Consistency between the two is verified by a test that runs both against the same inputs and compares output line by line.
- Adding a tool = a bounded change. Write one math function, add one YAML block, restart. No theme edits, no route edits, no new templates.
What I learned
- Data-driven beats code-generated. The tool pages were a natural fit for "config + template" once the math was isolated.
- Two implementations must be locked together. A "test that compares Go vs JS output" is not optional — it is the only thing that keeps the mirror honest.
- Server-side defaults are an SEO feature. Pre-rendered numbers make calculator pages useful and indexable, not just interactive.
If you build a tools-heavy site, this split — config, tested math, JS mirror, server defaults — is the pattern I would repeat. And the /tools section here is the live example.
Comments (0)
No comments yet.