testfly.me: the test bed we prove our own solutions on, and a paraglider gear publication
A site that makes a technology earn its place: 105 test reports in two languages served as static files, and the modules that grew here already run on client sites.

The test bed
testfly.me is our own site, and that is exactly what makes it useful. There is no client to talk into an experiment, no approvals, and no need for “let us do it the usual way”. So we try new solutions boldly here, on a real site with real visitors, and only then offer them to clients.
The rule is simple: client projects get what has survived here for at least a year. What did not survive was an idea that only looked good on paper — but clients will never know ;)
At the same time, testfly.me is much more than a safe sandbox. It is a full-fledged bilingual publication about paragliding gear: detailed test reports on wings, harnesses and instruments, written since 1996 and paid for by nobody.
What was road-tested here
OutputTransformer. The module that tidies up the rendered HTML: it drops the extra whitespace, applies typography and runs replacements. Its first commit is in this repository, 24 December 2025. Nine months on a live site later, it had survived a rewritten cleanup, and in September 2026 we published it.
StaticPages. A static cache: ProcessWire builds a page once, and Apache serves it as an ordinary file from then on. Easy to check — the home page answers with an ETag and a last-modified date of 22 August 2026, so an ordinary visit never starts PHP at all.
The frontend build. In August 2026 we replaced the old gulp and rollup setup here with our own build package — the same one that now builds atis.pro. Breaking the build on your own site costs nothing; breaking it on a client’s costs a day.
Our own fields. Specification tables, mark calculation — each is a field type or a module written for this site, and later useful elsewhere.
A report: marks inside the text


The engine works out the mark, not the author
A wing’s overall mark is not a number somebody types at the end. The tester marks the small things: the brake handles on their own, the behaviour in a turn on its own, the behaviour under a collapse on its own. Those add up to a subsection’s mark, subsections to a section’s, sections to the whole aircraft’s.
Our Marks module does that arithmetic when the page is saved. The editor never types the total, and it cannot be changed without changing the individual marks. Which is also a defence against oneself: if the overall impression says “a nine” and the individual marks say 8.2, the report says 8.2.
Short reports work more simply: a handful of marks and one average. Two templates, one module, the same arithmetic.
Specifications as tables


The brand filter: 700 bytes and not one request
In a category with three dozen wings, the manufacturers’ logos sit in a strip above the list. Tapping a logo leaves only that maker’s wings; tapping it again brings the rest back. That is what the clip above shows.
No request is made. Every card is already in the HTML, and each carries a small JSON object in its data attribute: brand, certification, year, positioning. The filter compares the field it was asked for and toggles a class on the cards — the browser redraws the list itself.
The whole filter file is 699 bytes built. It knows nothing about brands: the field name comes from the link’s attribute, so the same code filters by year or by class without another line.
The data travels in the markup
<!-- each card carries what it can be filtered by -->
<div class="report item" data='{"brand":"ParAAvis","homologation":"EN B","year":2017}'>…</div>
<!-- the logo strip: the value is the link's own title -->
<a title="ParAAvis" data-filter><img src="/…/paraavis.png" alt="ParAAvis"></a>
// one call, any field of that JSON
dataFilter('.report.item', 'brand', 'ParAAvis') // or 'year', 2017 — same code Nothing but markup and a single call: the server hands over the finished list, the browser decides what to show.
Two languages, one page tree
The site runs in two languages: the Russian reports are read at home, the English ones by manufacturers curious about what was written on their wing. These are not two sites, nor copies: in ProcessWire a second language is a set of sibling fields on the same page, so marks, specifications and photographs are shared and only the text is translated.
First drafts come from a translator built into the admin, then they are edited by hand. For technical writing about wings that saves an evening per report, but it does not replace the author: paragliding terms come back confident and wrong.


