Other services · website design & SEO
Get found. Then get chosen.
Sites a crawler reads with JavaScript switched off and a buyer cannot scroll past. Prerendered, mapped, canonicalised, measured, and served from the city your visitor is standing in.
16
routes, all prerendered
0
pages that need JS to exist
14 kB
this document, over the wire
Every line above exists before a script runs. Check it yourself.
The uncomfortable truth
Get found first.
Nobody types your URL. They type a problem into Google and trust whatever surfaces. Everything below is the engineering that decides whether you are on that screen.
We still make them beautiful. Beauty is the closer, not the strategy.
Prerendering · exhibit A
So every route ships as finished HTML.
This site is React. It is also twenty-one real documents on disk, because a headless Chrome renders every route at build time and writes the result out. The framework is our convenience. The HTML is the product.
Fetched with JavaScript disabled
Nothing to read, nothing to rank. The content is a promise the crawler has to come back for.
Identical to what you are looking at, minus the animations. That is the whole trick.
Why the render queue is the whole story
The render queue
Google does execute JavaScript. It just does it later, on a second pass, out of a queue it will not show you.
The gap in the middle of the first lane is where a new page sits, crawled and not indexed, while somebody asks why the launch is not showing up. Static HTML deletes the gap. It also deletes every failure mode underneath it: a script that four-oh-fours, a hydration error, a consent wall, a rate limit on the API the page needed to render its own headline.
This page's heading outline
a level is never skipped, and there is exactly one h1
Semantics, where accessibility and ranking are the same job
One h1 per document, and it is not a copy of the title tag: the title answers the query, the h1 greets the human.
Levels never skip. An h4 under an h2 tells a screen reader and a parser that a section is missing.
Real landmarks: header, nav, main, footer. A crawler and a screen reader both use main to find the content and skip the furniture.
Alt text describes the picture, not the keyword. Decorative photography carries alt equal to empty string so it is skipped instead of narrated.
Links say where they go. Twelve links reading here on one page is twelve wasted anchors.
Contrast at 4.5:1 on body copy. The same fix that passes WCAG keeps the page readable on a phone in daylight.
Sitemap structure · generated, never maintained
Then a generated map hands Google all 21 of them.
Not a plugin's guess and not a file somebody updated in March. The build reads the route table, walks the source files, and writes the map. Forgetting a page stops being possible.
every entry resolves 200, is canonical, and is indexable. nothing else belongs in here.
robots.txt controls crawling, never indexing. a blocked URL can still be indexed from a link, without a description.
split by section long before the ceiling, so Search Console tells you which section broke.
robots.txt, and what it is actually for
Generated, never maintained
The build reads the route table and writes sitemap.xml from it. Adding a page to the router adds it to the map in the same commit. A human forgetting is no longer one of the failure modes.
lastmod from the filesystem
Each entry takes its date from the modification time of the source file that renders it, not from the day of the build. A sitemap where every URL changed today is a sitemap Google learns to ignore.
changefreq that matches reality
Weekly on the pages we actually edit, monthly on the service pages, yearly on privacy. It is a hint, not a command, and the hint is only worth giving if it is true.
Only canonical, only 200
No redirects, no noindex, no parameter variants, no URLs that four-oh-four. A sitemap is a list of pages you are willing to be judged on.
Every route is a document before it is an app.
MyWebGlory ships twenty-one prerendered documents, one canonical URL per page, a sitemap generated from the router at build time, and Organization, Service and Breadcrumb schema attached to the templates rather than sprinkled by hand.
The same team fills B2B virtual event rooms for a living: 50+ events marketed, 40,000+ attendees hosted, 60%+ of registrants showing up live against a 35% industry average.
your page, as Googlebot receives it. no scripts, no shell, no second request, no waiting.
What the map cannot fix
A sitemap is a hint, not an instruction. It gets a page discovered; it never gets a page indexed. Indexing is earned by the page being worth a slot: distinct from its neighbours, linked to from inside the site, fast enough to be worth rendering, and about something a person actually typed.
Which is why the crawl we run at the start of an engagement reports two numbers, not one: how many pages exist, and how many of them deserve to.
URL hygiene · one page, one address
Each one at exactly one address.
Two URLs serving one page is not a tidiness problem. It is two pages splitting the same links, the same authority and the same click data, and neither of them winning.
four round trips before a single byte of content. on a 3G handset that is most of a second, spent on nothing.
one permanent redirect straight to the final address, then a self-referencing canonical that agrees with it.
One canonical, pointing at itself
Every page declares an absolute, self-referencing canonical that matches the URL actually serving 200. A canonical pointing somewhere else is a request to be de-indexed, and plenty of sites make it by accident.
Trailing slash decided once
/pricing and /pricing/ are two URLs to a crawler. Pick one, 301 the other, and make the canonical, the sitemap, the internal links and the CMS all agree. Two half-ranked copies beat neither.
301, not 302
A 302 says keep the old URL indexed and expect it back. Permanent moves get 301 or 308. We only reach for 302 when something genuinely comes back next week.
No chains, no loops
http to https to www to slash is four hops and roughly half a second before a byte of content arrives. Every redirect resolves in one hop, straight to the final URL.
Pagination stays indexable
Page two of a listing is its own URL with its own self-referencing canonical. Canonicalising it back to page one hides everything after the first ten results. rel=prev and rel=next stopped being a Google signal in 2019; internal linking carries it now.
Parameters normalised
Casing, index.html, session ids and tracking parameters all resolve to the same clean address. Whatever survives gets a canonical rather than a crawl budget.

Metadata & structured data
Wearing metadata written to be clicked.
Ranking gets you onto the screen. The title tag and the description are what decide whether the thumb stops on you or on the result underneath.
How the result renders
Before
competitor.example › home
Home | Acme Digital Ltd | Welcome to our website
Acme Digital Ltd is a full-service agency founded in 2011 offering a wide range of solutions to help businesses…
52 characters of brand before a single word the searcher typed
After
mywebglory.com › services › website-design-seo
Website Design & Technical SEO Services | MyWebGlory
Static sites crawlers read with JavaScript off: prerendered routes, generated sitemaps, clean canonicals, green Core Web Vitals, edge caching worldwide.
the query answered in the first four words · breadcrumb from BreadcrumbList, not from the URL
The social card
mywebglory.com
Website Design & Technical SEO Services | MyWebGlory
Static sites crawlers read with JavaScript off.
- title
- 50 to 60 characters
- meta description
- 150 to 160 characters
- og:image
- 1200 x 630, under 8 MB
- twitter:card
- summary_large_image
- og:locale
- one per language
- og:image:alt
- always
roughly 600 px before Google rewrites it. Query first, brand last, separated by a pipe.
not a ranking factor, very much a click-through factor. Write the answer, not the mission statement.
1.91:1. Absolute https URL. Text large enough to survive a phone-sized preview.
plus twitter:title, description and image. LinkedIn and Slack read the Open Graph tags.
with og:locale:alternate for the rest of the set, matching the hreflang cluster exactly.
the social preview is an image, and images get described.
Which structured data Google actually consumes
JSON-LD, and what Google does with it
Shipping schema is easy. Knowing which of it ever reaches a searcher's eye is the part that separates a checklist from a strategy.
Feeds the knowledge panel: name, logo, founder, contact, sameAs profiles.
visible rich resultReplaces the raw URL in the result with a readable breadcrumb trail. Visible, immediately.
visible rich resultEligible for Top Stories, Discover and article rich results. Needs a real author and dates.
visible rich resultSince August 2023 the accordion only shows for authoritative health and government sites. Ship it for the entity graph, not for the pixels.
entity context onlyNot a rich result type. It tells Google what this page sells and how it relates to the organisation.
entity context onlyContext for the map pack: area served, hours, contact. Rendering depends on the query.
entity context onlyCore Web Vitals · the numbers Chrome reports on you
Loading before a visitor decides to leave.
Every Chrome user quietly sends these three numbers home. They are the only performance figures Google grades you on, and they are measured on your visitors' phones, not on your laptop.
Largest Contentful Paint
2.5 s or better
over 4.0 s is poor
when the biggest thing above the fold finishes painting. On a marketing page it is almost always the hero image or the h1.
Interaction to Next Paint
200 ms or better
over 500 ms is poor
replaced FID in March 2024, and it is harsher: it measures the worst interaction of the visit, not the first.
Cumulative Layout Shift
0.1 or better
over 0.25 is poor
how much the page moves under a thumb. Almost always an image, an ad slot or a font with no reserved box.
The waterfall we build toward
the image that becomes LCP starts downloading in the same breath as the stylesheet. the application bundle arrives after the page has already painted.
The LCP image is preloaded with fetchpriority=high and is never lazy loaded. loading=lazy on a hero image is the fastest way to lose a whole second, and it is on most sites we audit.
Every image, video and embed carries width and height, or an aspect-ratio box. The space is reserved before the bytes arrive, which is most of CLS solved for free.
Fonts: preconnect to the font origin, subset to the characters actually used, font-display swap so text paints in a fallback instead of hiding.
JavaScript is deferred and the page does not need it. Hydration is an upgrade, never the thing that makes the h1 appear.
Third parties load after paint, in an idle callback where possible. One chat widget can cost more INP than the entire application.
Measured at the 75th percentile of real Chrome visits over 28 days, per URL group. Your laptop on office wifi is not the measurement.
Before · as we found it
invisibleCore Web Vitals · p75 field data
Routes indexed
6 of 14 · 3 duplicate variants competing
Weight, first view
4.1 MB · 62 requests · 1.9 MB of unused JS
After · week 6
shippedCore Web Vitals · p75 field data
Routes indexed
14 of 14 · one canonical each
Weight, first view
0.4 MB · 14 requests · AVIF hero, brotli everything
Every route prerendered to real HTML, so the crawler stopped waiting on a render queue.
Three duplicate URL variants collapsed into one canonical each, with 301s instead of 302s.
sitemap.xml generated from the route table, lastmod taken from the source files.
The hero image preloaded at fetchpriority high, and un-lazy-loaded.
Title tags rewritten to answer the query, brand moved to the end.
Organization, Service and Breadcrumb JSON-LD attached to every template.
position #38 was a rendering problem, not a content problem. The words were already good.
Build, weight & the edge
Built small, and served from the nearest city.
Two numbers decide how a site feels: how many bytes it asks for, and how far those bytes travel. We hold both down, and we let you watch the build that proves it.
a copy fix is live worldwide in under two minutes. that is why the pages that win are the ones that got edited twenty times.
HTML revalidates on every request so a deploy is instant everywhere. hashed assets never revalidate at all.
Every byte, twice compressed
What actually goes over the wire
| file | raw | gzip | brotli | saved |
|---|---|---|---|---|
| index-BwGANaVv.js | 992.8 kB | 250.4 kB | 198.4 kB | 80% off |
| index-BI4039yt.css | 104.6 kB | 17.8 kB | 14.5 kB | 86% off |
| website-design-seo.html | 123.9 kB | 23.0 kB | 19.0 kB | 85% off |
One unprocessed portrait sitting in this very repository is 2.5 MB. The same photograph, as AVIF, at the size it actually displays, is under 60 kB. That single comparison is the entire argument for an image pipeline.
Code split per route
Dynamic imports at the route boundary, so the pricing page never downloads the blog's renderer. Rollup splits on those boundaries automatically and hoists what is genuinely shared.
Tree shaken on purpose
Named ESM imports only. One named icon import ships one icon; a namespace import ships the whole library. That single habit is worth more than most build flags.
Compressed twice
gzip is the floor and brotli level 11 is the ceiling. Brotli takes another 21% off our JavaScript and 19% off our CSS, at the edge, for nothing.
Images in this decade's formats
AVIF first, WebP as the fallback, in a picture element with a responsive srcset and a sizes attribute so a 375 px phone never downloads a 2560 px hero.
Hosting
Cloudflare Pages, because a static site deserves an origin that cannot fall over.
Cloudflare Pages. One deploy pushes the whole site to a network spanning 330+ cities in 120+ countries, so the nearest copy is a few milliseconds away wherever the query came from.
Content-hashed assets served immutable for a year. The hash changes when the bytes change, so there is no cache to purge, ever.
HTML served fresh with a revalidation check, so a copy fix is live worldwide the second the deploy finishes.
Atomic deploys with instant rollback to any previous build. A bad release is undone in one click, not in another build cycle.
HTTP/3 over QUIC and TLS 1.3, so a lossy mobile connection stops paying for head-of-line blocking.
Unmetered DDoS mitigation in front of it, and with a static site there is no origin left to knock over anyway.
International · hreflang done properly
In whatever language the query was typed in.
We shipped mydropai.com in 26 languages across 40+ pages, every one of them prerendered and every one carrying its full hreflang set. Here is what that actually takes.
The hreflang cluster, as it ships
| hreflang | language | href | why |
|---|---|---|---|
| x-default | Fallback | https://mydropai.com/features/ | every unmatched language lands here |
| en | English | https://mydropai.com/features/ | self-referencing, as required |
| fr | French | https://mydropai.com/fr/fonctionnalites/ | the slug is translated too |
| es | Spanish | https://mydropai.com/es/funciones/ | es, not es-ES, until Spain differs |
| pt-BR | Portuguese (BR) | https://mydropai.com/pt-br/recursos/ | region split earns its keep here |
| de | German | https://mydropai.com/de/funktionen/ | one of 26 in the cluster |
27 entries on every page in the cluster, including the page's own, plus x-default. Miss one and Google throws the whole set away.
The set is bidirectional
Every page in a language cluster lists every other page in that cluster, including itself. A one-way reference is thrown away silently, which is why most broken hreflang looks fine in the HTML.
x-default is not optional
It is the answer for the 60 languages you did not translate. Leave it out and Google picks for them.
One stable URL per locale
Not a cookie, not an IP sniff, not a JavaScript redirect. A crawler in California has to be able to reach the French page and stay on it.
The metadata gets translated too
Title, description, Open Graph, alt text, the JSON-LD name and description, and the slug. A French page wearing an English title tag ranks for nothing in French.
Region codes you can defend
Language first, region only when the region actually changes the content. pt and pt-BR, yes. en-IE splitting your own authority for no reason, no.
Localisation, not translation
Currency, date format, phone format, the case studies, the objections and the proof. The same sentence in two languages is often two different offers.

Receipts · view source on any of these
This site. Every route prerendered, sitemap generated from the router, deployed to the edge by one script.
Our AI social platform: 40+ marketing pages shipped in 26 languages, every one static, every one carrying its full hreflang set.
The community hub we designed and shipped for Kornit's print ecosystem, structured to be found before it was styled.
The same team fills virtual event rooms for a living.
That muscle is why these sites exist: something has to sell the room. Yours will be built by people whose own pipeline depends on pages that rank. See the flagship: virtual event marketing
50+
events marketed
40K+
attendees
60%+
show up live
How engagements run · priced on demand
1
You ask
One call. What the site must rank for, who it must convert, what exists today.
2
We crawl
A full crawl of what you have: status codes, canonicals, render diff, vitals, the index gap.
3
One flat quote
One number for the whole build. No hourly meter, no surprise retainer creep.
4
We ship
Design, build, technical SEO, launch, index. You watch positions move, not tickets.
A site is not a SKU. The flat number lands after the first call, and it does not move.
You've seen what found looks like.
Now let's make it look like you.
One call. We crawl your site the way Google does, name what is keeping it off page one, and send you the findings whether or not you hire us. Then one flat quote for the rebuild.
4.9/5 from 40+ organizersKeep going · the full stack









