We started from templates and built without one
A research firm's bilingual one-page website. The design stands, the content is being finalised — this page describes where it is now.
- The situation
- A Budapest research firm trading since 2003 had an aged website. They wanted a single scrolling page with anchor navigation that looks like a menu, their own visual identity, in Hungarian and English.
- What I have built so far
- A custom theme with no page builder: eight sections, two languages without a multilingual plugin, three legal subpages in both languages, and a map that does not keep people waiting.
- Where it stands
- The first complete design went over in July 2026; the client is finalising the copy. The work runs on a development subdomain while the live site keeps working.
The work in numbers
| Collaboration started | June 2025 |
|---|---|
| Status | in progress — content being finalised |
| Structure | one page, 8 sections, anchor navigation |
| Languages | 2 — Hungarian and English, same structure |
| Legal subpages | 3, in both languages — 6 addresses |
| Where it is built | on a dev subdomain; the live site untouched |
- Project
- market and opinion research
- Role
- Custom theme, bilingual setup, legal pages, operations
- Engagement
- Contracted build + monthly maintenance
The template question the client asked
The work started with a template shortlist: I sent over a few sites I found more distinctive than average. Their question back was precise, and it decided the direction of the project — they asked what is fixed in a template, what cannot be changed.
The answer turned out to be nothing. Nor did they have to choose one template: collect what you like from each, and I will assemble a single coherent version from that. Where there is no instruction, I either improvise or ask along the way.
In the end not one template made it in. What is being built is a custom theme — the templates stayed in only insofar as they showed what the client likes.
The domain did not have to be moved
The site sat with an earlier provider, together with the company mailboxes. I looked into it and concluded that the domain did not need moving: a development subdomain with an A record pointing at my server was enough. The main domain's settings stayed as they were, email kept working, and no new contract was needed.
The client's own systems administrator set it up, from a request written out point by point in the client's own email. Moving a domain tends to be the developer's convenience rather than a technical necessity.
What this means if you are in a similar position
If you want a one-page introductory site, a page builder gives little: there are no many subpages to maintain, and in exchange it puts layers underneath. With a custom theme the result is exactly what we agreed on, and an editable part can still be added later where it is actually needed.
And if you are changing developers: ask why anything would have to be moved. Often it does not, and disturbing a working email system is the most expensive part of a step that can be skipped.
If you need a one-page bilingual introductory site, or you are changing developers and do not know what has to be moved, write a few sentences about where things stand. One exchange of emails usually shows how much work it is.
kristof@kristofkarner.comFrom here the details: two languages without a plugin, legal pages that build, the measurement behind a stalling map, and a cookie banner that currently gates nothing.
The size of the build
| Custom theme | 30 PHP templates, 7,301 lines of PHP + CSS + JS |
|---|---|
| Sections | 8 live + 8 archived from the first design |
| String keys | 143 Hungarian and 143 English, same structure |
| Rewrite rules | 14 — language, legal pages, design version |
| Page builder | none |
| Multilingual plugin | none |
$ find . -name "*.php" -not -path "*/vendor/*" | wc -l 30 $ cat $(find . -name "*.php" -o -name "*.css" -o -name "*.js" | grep -v vendor | grep -v rough.min) | wc -l 7301 $ grep -c "=>" inc/strings.hu.php inc/strings.en.php inc/strings.hu.php:143 inc/strings.en.php:143
Two languages without a plugin
Multilingual plugins bring a large system with them: their own database structure, their own editing interface, their own upgrade risk. On an eight-section one-page site that is more weight than it removes.
Instead the texts live in two PHP files with identical structure, and 14
custom rewrite rules handle the addresses: the /en/ prefix
switches to English, and the legal subpages have their own English addresses.
The two string sets are identical, at 143 keys — if one goes
missing from either, the comparison shows it.
The English legal addresses had to go before the general
^en/(.+?) pattern in the rule list. Placed after it,
WordPress would have tried to resolve them as page names and would not have
found their template.
The legal pages build
The imprint, the privacy notice and the cookie notice are not hand-written HTML. Each is generated from a configuration file and a Markdown template, in both languages, from a single source. The company data lives in one place; the Hungarian and the English version come from the same origin.
The generation passes through two gates, and if either one stops it, no output is produced:
- Placeholder gate. If any unfilled placeholder is left in the template, the run exits with an error code.
- Statutory gate. The configuration lists all eight points of the imprint section of the Hungarian e-commerce act. Each point carries either proof — configuration paths whose values must appear verbatim in the finished text — or a justification for why it does not apply; and that justification has to reach the page too.
Of the eight points, six carry proof and two are closed with a justification. The reason this is worth it: an imprint tends to be silently incomplete. It renders neatly, it looks right, and meanwhile the hosting provider is missing from it — precisely the item most people forget. So putting the data in the configuration is not enough: if its place is left out of the template, the build fails.
- 01 Data + template
- 02 Two gates
- 03 Finished text
- 04 1. unfilled placeholder if any is left, the run stops
- 05 2. the eight statutory points proof or justification, verbatim
single source · stops → no output · Hungarian and English
The map was not waiting to be drawn
There is a map in the contact section. The first version behaved so that after scrolling stopped it stayed a motionless grey box for 1.3 to 3.4 seconds. It would have been natural to blame the browser's main thread.
The measurement said otherwise. Of the 1,550 milliseconds it took to come up, only 165 fell on the main thread; the rest was network waiting, because the thirteen requests to the tile service only started once the visitor had already arrived. The single slowest request was the font set, at 730 milliseconds.
The fix was not speeding things up but moving them earlier. The connection to the tile service is established at page load, and a warm-up step pulls the style, the sprite and the fonts into the browser cache during idle time, after loading. The map itself still only builds when the visitor comes near it.
Measured: dead time fell by 60 per cent on desktop and 31 per cent on mobile, at zero extra main-thread cost — the warm-up is a network operation, not drawing.
What is not obvious
The cookie banner currently gates nothing
Replacing the map provider removed the last element on the site requiring consent, so the cookie plugin would not have shown the banner by itself. The client decided it should stay, because measurement or advertising may come later.
That is a defensible decision, but the code records that the banner currently gates nothing, and exactly what has to be deleted once measurement arrives. On another site the same question led to the opposite answer — this site has no banner, because there is nothing to consent to.
Where the plugin loads, it is already too late
Forcing the banner did not fit in the theme. The cookie plugin creates its banner loader as it starts up, and the theme runs later than that. The setting therefore went into a separate module that loads earlier — and since it is not in the theme, a theme update does not carry it, so it has to be installed separately on the live site. This is the kind of dependency that tends to surface at handover.
Two designs, one of them archived
Two complete versions of the design were made, and for a while both were reachable at their own addresses — so the client chose by comparing working pages, not descriptions. After the decision the older version did not go in the bin: its files stayed in the codebase, they simply no longer load. Eight sections sit in that archive.
Questions about this project
Why build a website without a page builder?
Because a page builder trades editability for layers underneath the site, and ties the design to its own limits. On this project the client asked for a single scrolling page with their own visual identity — a builder does not help there, because there are no many subpages to maintain. A custom theme went in instead: 30 PHP templates, 7,301 lines, eight sections in separate files. If an editable part is needed later, it can be built exactly where it is needed — the reverse of handing everything to a builder and then trying to take control back.
Does the domain have to be moved when a new developer takes over a website?
Usually not. On this project the client's domain and company mailboxes sat with an earlier provider; I looked into it, and a development subdomain with an A record pointing at my server was enough. The main domain's settings stayed untouched, email kept working, and no new contract was needed. Moving the domain is most often the developer's convenience rather than a technical necessity — it is worth asking what justifies it.
How can a WordPress site be bilingual without a multilingual plugin?
With custom rewrite rules and string files. On this project 14 rewrite rules translate readable addresses into internal parameters: the /en/ prefix switches language, and the legal subpages have their own English addresses. The texts live in two PHP files with identical structure — both the Hungarian and the English set hold 143 keys, so if one goes missing it shows up in the comparison. For an eight-section site this is less weight than a multilingual plugin and its database structure.
Why does an embedded map stall, and what can be done about it?
Because it is usually the network that is slow, not the drawing. On this site the map stayed a motionless grey box for 1.3 to 3.4 seconds after scrolling stopped. Measurement showed that of the 1,550 milliseconds it took to come up, only 165 fell on the browser's main thread; the rest was network waiting, because the thirteen requests to the tile service only start once the visitor has already arrived. The fix was to move the work earlier: prepare the connection at page load, and warm the style, the sprite and the fonts during idle time. The dead time fell by 60 per cent on desktop and 31 per cent on mobile, at zero extra main-thread cost.
Is a cookie banner needed if the site measures nothing?
Legally no, if there really is no storage that could be refused. On this project an open map service replaced Google Maps, which removed the last element requiring consent — so the cookie plugin would not have shown the banner by itself. The client decided the banner should stay, because measurement or advertising may come later. That is a defensible decision, but the code records that while there is no actual measurement the banner gates nothing, and what has to be deleted once measurement arrives.
Summary
A bilingual one-page website for a Budapest research firm trading since 2003 has been in the making since June 2025. The client asked for anchor navigation that looks like a menu, with their own visual identity; we started from a template shortlist, but the answer to their question — what is fixed in a template — was that nothing is, and in the end not one template made it in. What is being built is a custom theme: 30 PHP templates, 7,301 lines, eight sections, no page builder. The two languages run on 14 custom rewrite rules and two string files of identical structure, 143 keys each, rather than a multilingual plugin. The three legal subpages are generated from a configuration file and Markdown templates through two gates: an unfilled placeholder, or a missing proof for one of the eight statutory points, and there is no output. The contact section's map stall turned out on measurement to sit on the network rather than the main thread; with an early connection and a warm-up the dead time fell by 60 per cent on desktop. The domain did not have to be moved: the work runs on a subdomain, and the live site and the company email are untouched. The first complete design went over in July 2026; the content is being finalised.