Portfolio / Multilingual site, SEO and operations
Nine languages, 747 pages and no application server.
powerabode is a commercial-systems company for energy operators: it turns supply-chain doctrine — tendering, contracts, cost recovery — into software and into services bought by the deliverable. Its readers run procurement and contracts at national and international oil companies across Europe, the Middle East, Asia and Africa. The site arrived as a static package ready to upload. The brief was to take it to production and make it a system: generated in nine languages without the copies drifting, every URL the one Google and the models expect, measured without asking where the law requires it and without over-asking where it doesn't, and alerting before the client notices when something stops working.

01The brief
A site read in nine languages.
Whoever lands on powerabode.com is not comparing agencies: it is a contracts director at a state operator who wants to know whether anyone understands why cost recovery stalls at 85% instead of 99. They read English, but their team reads Arabic, Portuguese or Bahasa, and a committee makes the call. That is why the site exists in nine languages, and why each language had to be a complete site rather than a translated menu.
The package the client handed over was strong on content and fragile everywhere else: 728 hand-written or copied pages, a sitemap with 40 URLs for a 360-page site, relative links that sent the Spanish reader to the English page, a cookie notice that did not describe what the site did, and a demonstration form with nothing behind it. None of that shows in a visual review. All of it costs rankings, leads or trust.
The underlying decision was not to change platform. There is no dynamic data, no users, no catalogue: a static site is the right architecture. What was missing was the system around it — generators, validator, deployment, measurement and monitoring — so that 747 files behave as one site.
What it had to solve
- 01Nine languages without drifting copies
- 02One canonical URL per page and per language
- 03Right-to-left Arabic without breaking the layout
- 04Content that search engines and models can answer from
- 05Analytics that are lawful in the EU and useful outside it
- 06Real bookings on the client's Outlook
- 07Knowing the site is down before the client does
- 08Running on shared hosting, with no framework
Our role
Static-system architecture, language, menu and content generators, validator, technical SEO, schema and answer templates, content pieces, consent and analytics, Clarity analysis, the booking backend on Microsoft Graph and Resend, deployment and the health probe.
02The rule
What decided every script.
If someone has to remember, it will fail.
Two of the incidents this site went through in production share one cause. A new stylesheet shipped under the same version string as the previous one; browsers that had it cached painted the new menu with the old CSS, and the header went from 73 to 2,233 pixels. Nobody got the code wrong: someone forgot to change a string by hand.
From then on the rule was that nothing depends on memory. The asset version is the hash of its content. Internal links are rewritten by a script. The sitemap is derived from each page's canonical. The menu is built by reading the pages it links to. And every pass is idempotent: running it twice produces no diff, and the validator rejects the build if anything is out of step.
GenerateValidatePublish
03Information architecture
Product, solutions and evidence.
The flat menu in the handover mixed product, services and reading. It was reorganised around the three questions a technical buyer arrives with, in a mega menu that is identical across 747 pages and nine languages because it is generated from each page's own content, never written twice.
What the system is.
The Workbench — the platform that brings the doctrine into the contracts team's daily work — and Codex, the body of knowledge behind it. It is the door for whoever wants to see software before talking to anyone.
What is bought, and on what terms.
Seven services, each with fixed scope, fee and delivery date, plus the cost recovery, cost-and-value leadership, procurement architecture and G2G programmes. Every service links to the insights that explain it, and every insight to the service that delivers it.
Why believe them.
Insights, Academy, the philosophy and the IP glossary. The menu's featured rail is generated from the Insights index, so it always shows the latest analysis in the reader's language, and the build fails if a menu link leads nowhere.
04Visual system
Group blue, reading teal.
Headlines, primary buttons and dark bands
- HEX
- #1B3764
- RGB
- 27 · 55 · 100
Labels, links and the menu's active state
- HEX
- #267A73
- RGB
- 38 · 122 · 115
Badges, underlines and the Value Disk
- HEX
- #45B5AA
- RGB
- 69 · 181 · 170
Body copy
- HEX
- #24344A
- RGB
- 36 · 52 · 74
Operational state on the health badge
- HEX
- #7FB069
- RGB
- 127 · 176 · 105
Chart and diagram accents
- HEX
- #8FC7E8
- RGB
- 143 · 199 · 232
Alternate bands and cards
- HEX
- #F7F9FB
- RGB
- 247 · 249 · 251
05Typography
The question in Light, the answer in Bold.
Open Sans
Who decides what a contract costs?
300 Light · 600 · 700 Bold
Open Sans
Eight to twelve people determine a contract's real cost.
300 · 400 · 600
Comfortaa
powerabode
400 · 500
How do you optimise value?
Light with a Bold tailSeven services, one chain
Light, tight leadingCost recovery
SemiboldWhat gets tendered is only 20% of the value at stake.
17 px · 300 · 1.7 leadingTHE WORKBENCH
Uppercase in text teal · +0.16 em trackingpowerabode
Comfortaa, lowercase06The site
The pages, as the domain serves them.

The buyer's question in Light and the seller's in Bold, over a carousel of energy imagery. Two actions: book a demonstration or read the philosophy.

Three figures from real engagements below the fold: 25–30% off spend across 45 North Sea contracts, 99.7% cost recovery on a Middle-East joint venture, three weeks against a four-to-six-month estimate for a national tender architecture.

“Which link in your contract lifecycle leaks the most value?” The services page opens with the question and answers with seven services sold by the deliverable, not by the hour.

The “oil and gas procurement” pillar page: a definition, the seven-stage lifecycle with a link to each service, and only figures already published and sourced in the insights.

The phone mockup was a 2020 PNG with a third-party oil major's logo and “Contract Summery” on a panel. It is now markup: it translates with the page, scales, and a screen reader can read it.

A sunburst that was unreadable at column width became a donut that steps through one category at a time. Its labels are read from each language's table, so the chart cannot contradict the text beside it.

Two first-person notes of 1,400 characters each, turned into a card deck with a switcher. Without JavaScript they read as two full columns: nothing is hidden from a crawler.

An asynchronous request or a scheduled call, in steps that validate when a field is left and never while typing. Available slots come from the client's Outlook calendar, shown in the visitor's time zone.

Languages, sitemap and a status badge that used to be the words “All systems normal” stamped into 729 pages. It now reads the probe's latest result and turns grey when that reading is more than 45 minutes old.
07The build
Eleven passes, an order that isn't negotiable.
The English pages and the translation sources are the only things edited by hand. Everything else — the eight translated editions, the menu, the rails, the clean routes and the sitemaps — is produced by dependency-free Node scripts, in an order that matters: the language generator rebuilds the translations from English, so every content pass has to run after it.
Sources
English HTML and i18n/Generators
Languages, menu, rails, chartsAsset hash
Version derived from contentRoutes and sitemaps
Derived from canonicalsValidator
747 pages, zero broken links
- 01
Generate the languages
Eight editions from English and `i18n/`, each with its own `lang`, direction and `base` tag. Nested pages keep their links inside the chosen language.
- 02
Compose what is shared
Founders deck, Insights index, mega menu, G2G call to action and Value Disk. Each pass reads the already approved copy from every page and language; none of them writes new copy.
- 03
Version by content
The `?v=` on `pa3.css` and `pa3.js` is the sha256 of both files. It moves when they move, and only then: a content pass does not touch 728 pages for nothing.
- 04
Inject the head
Google and Bing verification, Consent Mode and Clarity between markers, from a single file. Re-running replaces the block rather than stacking it.
- 05
Canonicalise links and routes
All 26,235 internal links are rewritten to their canonical path with the language prefix, and fallback folders are generated so every clean URL answers 200 on any host.
- 06
Derive the sitemaps and validate
One sitemap per language under an index, each URL with its full hreflang cluster, read from the pages themselves. Then the validator: links, assets, every article's table-of-contents anchors, doctype, `lang` and asset version.
9 languages · 747 pages validated · 0 npm dependencies
08Nine languages
A translation that doesn't send you back to English.
English, Arabic, Bengali, Spanish, French, Indonesian, Japanese, Portuguese and Russian. Having the pages translated was the easy part; the hard part was keeping readers in their language and letting Google understand which page is the version of which.
Eight languages sent readers to English.
Links were relative and the clean pages declared `<base href="/">`: on `/es/about/` every menu link resolved against the root and took the reader to the English page. They were all rewritten as absolute paths with their prefix, and the generator can no longer reintroduce the bug.
One x-default per page, not per site.
All 728 pages pointed `x-default` at the home page, so every cluster claimed the same URL, and Google discards hreflang when that happens. Each page now points at its own English version, and English-only pages no longer advertise translations that don't exist.
The browser decides; the time zone doesn't.
First visits fell back to time zone when the browser didn't match, so an English reader in Madrid ended up on the Spanish edition. An explicit browser preference now always wins. Arabic uses logical properties, so the drawer, menu and table of contents mirror on their own.
09The editions
The same site, right to left.

The Arabic home page with direction reversed: logo on the right, mirrored navigation and the proof figures in reading order.

The same hierarchy in Japanese. The headline's Light-and-Bold pattern survives in a script without capitals.

Live-demonstrations badge, full logo and a flag language switcher, at 390 px.

Expandable groups with 44 px targets. A closed panel also leaves the tab order: before, keyboard users walked through invisible links.

The drawer and language switcher swap sides; the badge and headline read right to left.
10Technical SEO
One URL per page. Not one more.
Before writing a single word to rank, the site had to become indexable as one site. Each page existed at up to four addresses, and the sitemap knew about one in nine.
One host, one slash, no .html.
`www` redirects to the apex and HTTP to HTTPS. `/about.html` and `/about/` both answered 200; the first now 301s to the second, matched against the original request so the internal rewrites cannot loop. Canonical, hreflang, Open Graph, JSON-LD and sitemap all declare the same form: the one with the trailing slash.
From 40 URLs to 369.
An index with one sitemap per language and every URL carrying its hreflang cluster, derived from the pages' canonicals: if a page changes, the sitemap cannot fall behind. All 369 URLs were verified to answer 200 against the production Apache.
31 redirects and a real 404.
An audit of every URL the domain had ever had indexed found old paths with external backlinks still answering 404. Each now hops once to its canonical target, and an invented path answers a real 404, not a 200 with the home page. Bing verification is served as XML, exempt from the host redirect.
11AEO and content
Written so the answer can be cited.
A procurement buyer no longer starts on page ten of Google: they ask an assistant. The content was written to win both readings at once — the search engine's and the summarising model's — with the answer on top, the structure declared and nothing left for the model to guess.
Short answer, contents, FAQ, sources.
All 25 insights share one shape: hero, quick answer, introduction, anchored table of contents, body, toolkit, author, FAQ, summary and references. Each declares BlogPosting, BreadcrumbList and FAQPage, and the visible FAQ is the one in the JSON-LD.
Titles that say what is searched for.
Using DataforSEO data for Google US, the titles and descriptions of the services hub, the seven services and six insights now lead with the phrase the buyer types: procurement consulting, category management, contract management, should-cost analysis. Four new guides targeted terms with demand no insight covered, without cannibalising the existing ones.
Organisation, services and terms.
The home page declares Organization with legal name, both offices, logo and knowsAbout, plus WebSite. Each service declares Service with provider, audience and area served. The glossary is a DefinedTermSet. And insights link to the service that delivers the idea, with keyword anchors, and back.
12Insights
The answer first. The reasoning after.

“What we publish. What stays inside the work.” The index separates, from the headline, what is published from what stays inside client work.

The featured rail came from a hand-typed block that hadn't moved since July. It is now generated from a date-ordered catalogue with optional editorial pinning, and it also feeds the menu on all 736 pages.

Every article opens with two or three sentences that answer its title. It is the paragraph a model quotes and the one a search engine can show as a snippet.

Anchors keep the clean URL and the language, move focus to the section, and a progress line marks the active section. With reduced motion, everything is instant.

Questions the buyer types as-is into a search box or a chat, in an accessible accordion and declared as FAQPage.
13GEO
Visible to whoever answers, not to whoever trains.
The crawler policy separates two uses most sites lump together. `robots.txt` declares content signals — search yes, training no, use as reference — and shuts out the crawlers that collect data to train models: GPTBot, ClaudeBot, Google-Extended, CCBot and some thirty more. Search engines and assistants that answer with a link still get in.
It is a business decision, not a technical one. powerabode sells doctrine; letting a model absorb it without attribution is giving it away, and an assistant citing it with a link is exactly the channel it wants. The Clarity dashboard already shows sessions arriving from Copilot, next to those from Google and Bing.
For that citation to happen, the content is written to be extracted: a short answer up front, headings that are questions, figures with their sources and a JSON-LD graph tying organisation, services, articles and terms together. What Insights publishes can be cited; what lives inside client work is not published.
What each crawler sees
- 01Googlebot and Bingbot: the whole site
- 02Assistants that link: the whole site
- 03Training crawlers: nothing
- 04Declared signal: search=yes, ai-train=no
- 05Permitted use: reference, with a link
Pending
An `llms.txt` mapping doctrine, services and insights: the domain currently answers 404 on that path.
14Measurement
Ask where the law requires it.
The first version measured only with consent, worldwide, and the site went nearly blind for weeks: a buyer in Riyadh or Jakarta does not click a cookie notice. The final version applies the rule where the law imposes it and measures by default where it doesn't, with the same way out for everyone.
Consent Mode v2, by region.
Analytics storage starts granted, with a region-scoped denied default for the EEA, UK and Switzerland that Google applies by IP. Ad storage stays denied everywhere. A stored choice always wins, is read before the tag loads, and is never asked again.
Record from the first view, cookieless.
Clarity has no region switch, so a `Europe/*` time zone stands in for one. The tag used to load only on acceptance, so heatmaps never saw the first view — the one that matters most. It now always loads in cookieless mode, and a single call lifts Clarity and GA4 together on acceptance.
Reject, in nine languages.
The notice names Google Analytics and Clarity, offers “Reject” with the same weight as accepting and, on rejection, withdraws both and clears their cookies. Consent is versioned: anyone who accepted wording that didn't mention session replay is asked again. And 234 pages that had shipped without the notice now build it.
15Clarity · 30 days
Few visitors, a precise read.
The project's Microsoft Clarity dashboard, last 30 days as of 27 October 2026. This is a niche site for a very specific buyer: the number is small and is published as it is. Clarity also excluded 248 bot sessions, more than twice the human ones.
- 117
- Human sessions, from 112 distinct users
- 34%
- Average scroll depth
- 0%
- Sessions with rage clicks
- 0
- JavaScript errors recorded
16Heatmaps
Where the reading stops.

33 desktop views of the home page. 52% reach 20% of the page, 21% get past 25% and 12% reach the end. The strip of proof figures sits right on the edge where half the readers are lost.

Eight clicks in thirty days: two on contact, two on the consent notice's “Continue”, one on the demonstrations badge and one in the footer. At this volume the map decides nothing on its own; it is read alongside the recordings.

The consent bar sits on the bottom edge of the first viewport, exactly where the scroll map cools. Accept and reject carry the same weight.
17What we read
Three readings, three decisions.
Clarity wasn't installed to have a dashboard: it was installed to find what a static audit can't see. With little traffic the rule is to read behaviour that repeats, not percentages, and to check every reading against the code before touching anything.
Move the figures into the first viewport.
Only 21% of home page views get past 25% of the page, and the three figures that carry the argument — savings, recovery and lead time — sit just below the fold. The proposal is to fold them into the hero, where everyone who arrives sees them.
Two legacy paths were still alive out there.
Two URLs from the previous architecture, under `/systems-delivery/`, showed up among the entry pages answering 404 to real people. They were in no redirect map; traffic found them. Each one is mapped to its current equivalent.
The host was serving a copy of the site.
Four sessions came in through the hosting provider's temporary subdomain, which served the full site. The canonical pointed correctly, so no duplicate content was indexed, but the right rule is a 301 from the temporary host to the apex.
18Operations
A site that alerts before the client does.
A static site doesn't go down like an application: it degrades quietly. One release's CSS ends up next to another's HTML, a certificate expires, a form stops delivering. Operations were designed to see exactly those failures, which an uptime ping can't.
GitHub Actions
Deploy and probeBluehost
public_html over rsync and SSHCloudflare
TLS, cache and crawlersProbe
17 checks every 15 minAlert
Email only on state change
- 01
Publish without the internals
Every push to `main` syncs the repository to `public_html`. `.htaccess` answers 404 for hidden files, `docs/`, `tools/` and the repository config: the server serves the site and nothing else.
- 02
Probe what matters
Critical pages, two translated editions, sitemap and robots, the CSS and JS at the exact version the live home page asks for, the 404 of an invented path, the HTTPS redirect, certificate expiry and the state of the booking backend.
- 03
Publish the state
The result is written to `status.json` next to the pages, and the deploy excludes it so a stale repository copy never overwrites a real reading. The footer badge reads it.
- 04
Alert on transition
An HTML email when the state changes — operational, degraded, down, recovered — and a reminder every sixth failing run. Without that, a 15-minute cron turns a two-day outage into 192 identical emails.
- 05
Don't hide the alert
If the email fails, the probe doesn't fail with it: the report is still uploaded as a workflow artifact. The alerting channel must not mask what it was meant to report.
17 checks · every 15 minutes and after every deploy · public state at /status.json
19Bookings
A form that doesn't promise what it didn't do.
The demonstration form had always looked fine. There was nothing behind it, and when it failed it opened the visitor's mail client and showed the success card: for a booking, it said the slot was confirmed without having written it to any calendar.
Outlook 365 through Microsoft Graph.
A booking is written as a tentative hold with no attendees, because adding an attendee is what makes Outlook send an invitation. The internal email carries signed, single-use links to confirm or decline; confirming creates the Teams link and notifies the client in their language, Arabic included.
Resend to notify, one minute to acknowledge.
The team gets the request instantly, with Reply-To set to the visitor. The visitor's acknowledgement goes out a minute later, because an instant reply reads as an autoresponder. Credentials live outside `public_html` and outside the repository.
No mailto, no false success.
If the backend doesn't answer, the form says so, keeps what was typed and offers to copy it, in nine languages. Validation no longer repaints the step on every keystroke — the field used to lose focus after the first character — and slots are computed in the organiser's time zone, not the visitor's.
20The domain today
What powerabode.com declares.
Counted on what powerabode.com serves and on the repository's validator, 27 October 2026.
- 747
- HTML pages validated on every build
- 369
- Canonical URLs in 9 per-language sitemaps
- 25
- Insights published
- 31
- Legacy paths 301-redirected to their target
21Status
What is done and what comes next.
The site is live at powerabode.com, behind Cloudflare, with 369 URLs in per-language sitemaps, verification in Google Search Console and Bing Webmaster Tools, and the probe reporting every 15 minutes. Certificate, redirects, 404, versioned assets and all nine editions pass on every reading.
In search, the site is at the start. Canonical URLs, the full sitemap and intent-led content were published between July and October 2026; in that month's query, DataforSEO records the domain's first positions on Google US, still beyond the first page. In a technical niche like this one, authority is built in quarters, not weeks, and this case doesn't claim it early.
What did change can be measured in the code: a site that existed at up to four addresses per page now has one; eight languages that were never submitted to Google now have sitemaps; a form with no backend now has one, with an honest error; and a site nobody watched now raises its own alarm.
Next quarter
- 01Move the proof figures into the hero
- 02Redirect the two legacy paths still answering 404
- 03301 the temporary subdomain to the apex
- 04Publish an llms.txt mapping the doctrine
- 05Review the inherited inbound link profile
- 06Translate the body of the newest insights
What this case doesn't claim
There are no lead, conversion or first-page ranking figures, because they don't exist yet. The behaviour figures cover one month and are published with their denominator. The discovery and measurement infrastructure is built and can be checked; the traffic it brings is an outcome that will be reported when it arrives.
Keep exploring
A site that validates, measures and raises its own alarm.
Multilingual sites, technical B2B, high-trust services: in these projects what costs most isn't the design, it's what breaks quietly afterwards. We build the system around it so it doesn't.
Tell us about your project