GMAB — Menuiserie Aluminium & Bois
From an invisible React SPA to 67 indexable joinery pages across Morocco: a French Astro 7 site where every page has its own JSON-LD, share card and FAQ, and every claim is checked at build time.


A joinery company that search engines could not see.
GMAB (Global Menuiserie Aluminium et Bois) is a Moroccan joinery and interior fit-out company. It makes aluminium and wood joinery, made-to-measure kitchens, parquet and cladding, wardrobes and dressings, office furniture, and complete fit-outs for shops, cafés, restaurants, hotels and gyms. Its buyers are homeowners planning a kitchen, architects specifying cladding and business owners fitting out a new venue, and almost all of them start the same way: a French-language search for a trade, often with a city attached, such as "bardage bois", "placard sur mesure", "cuisine moderne" or "menuiserie Casablanca".
The previous gmab.ma could not answer any of those searches. It was a client-rendered React single-page app: one real URL, an initial HTML file with no content in it, a sitemap whose entries pointed at #services, #gallery and #contact anchors, and a Workbox service worker that cached the whole app on visitors' devices. A Semrush check of the Morocco database, run by RAIN on 22 September 2026 before any work started, found the domain ranking for one keyword, unrelated to the business, at position 27, and drawing no organic visits. Meanwhile Semrush estimates monthly French-language demand in Morocco at about 2,900 searches for "cuisine moderne", 2,400 for "placard", 2,400 for "bardage bois" and 1,900 for parquet terms. Those are third-party estimates, not results, but they showed the size of the gap.
The brief to RAIN Design Studio had a second, stricter half: everything the new site says about GMAB had to be true. No prices, because none were ever published. No street address, because GMAB does not publish one. No materials or promises the old site never claimed. We answered with a French-language (fr-MA) static site on Astro 7, built page by page from one data registry:
- 6 service ("savoir-faire") pages: made-to-measure kitchens, parquet and cladding, dressings and wardrobes, professional furniture, commercial fit-out, and doors and staircases.
- 12 city pages for Casablanca, Marrakech, Rabat, Tanger, Agadir, Fès, Meknès, Oujda, Kénitra, Tétouan, Salé and Mohammedia, each describing the joinery market of that city.
- 20 topic landings aimed at measured searches, such as bardage bois, placard sur mesure, cuisine moderne, menuiserie aluminium and fenêtre aluminium, and 14 service × city pages such as parquet in Casablanca or a made-to-measure kitchen in Marrakech.
- 7 buying guides with their own index, a filterable gallery of 16 projects, a hub of the 12 cities, an HTML site plan and an interactive /seo map of every page and the links between them.
That makes 68 HTML pages: 67 indexable URLs plus a 404, where the old site had one. Every page carries its own JSON-LD graph, a generated 1200×630 share card, canonical and fr-MA hreflang tags, and an entry in the sitemap, the image sitemap and llms.txt. The look is editorial and brutalist: oversized stacked uppercase headlines, bracketed monospace labels, numbered sections, one-pixel rules, full-bleed photography and a single accent, the yellow sampled from GMAB's own logo, on a near-black background, with a contrast-checked light theme. The build is versioned as v27.1.2 and its deploy-ready output was committed on 30 September 2026.
Real URLs, React SPA to static build
Pages carrying a JSON-LD graph
FAQ answers in FAQPage schema on 61 pages
Generated 1200×630 share cards
Real pages, one registry, and an audit that refuses invented claims.
A single-page app hides its content behind JavaScript. The fix was not a plugin or a pre-render service but a different kind of site: every page written to disk as HTML, every page generated from the same data, and every build checked before it ships.
Real HTML for every URL
Astro 7 renders the whole site statically with build.format: 'file', trailingSlash: 'never' and compressed HTML. /contact is a real contact.html with its own title, content and links. On Apache, the shipped .htaccess maps extensionless URLs to their files and 301-redirects .html addresses, trailing slashes and legacy routes such as /galerie-realisations to their new homes.
One registry, many outputs
All copy and data live in src/data/. A single URL registry feeds the HTML site plan, the sitemap, the image sitemap, llms.txt, the footer links and the share cards. Adding a city to cities.ts generates its page, its sitemap entries, its footer link and the cross-links from every service page, with no hand-edited lists to forget.
Three templates, one catch-all route
A service template, a city template and an article template cover every generated page. One [slug].astro route renders services, cities, topic landings and service × city pages; guides have their own route. Text for the 40 SEO pages sits in one JSON file, and their structure (parent page, city, image, gallery category) in a typed meta file.
Structured data that tells the truth
Every page carries an @graph with Organization + HomeAndConstructionBusiness and WebSite, then Service, FAQPage, BreadcrumbList, Article or ImageGallery as the page needs. City pages are modelled as a Service with areaServed, deliberately not as fake LocalBusiness branches, because GMAB has no premises in each city.
A facts file and a banned-phrase audit
Every claim about GMAB must come from docs/facts-gmab.md, extracted from the old site. A post-build audit fails the build on about 45 phrases that once slipped in as inventions (prices, dirhams, "48h", PVC, MDF, showroom and others), on schema that claims a price range, opening hours or a local business, and on duplicate titles or identical FAQ blocks.
Meta, links and FAQs checked on every build
The same audit checks that titles stay within 62 characters and descriptions between 70 and 160, that each page has exactly one H1, a canonical, fr-MA hreflang, Open Graph and Twitter tags and a share card that exists on disk, that every internal link resolves, that visible FAQs match the FAQPage schema one for one, that no JSON-LD reference dangles, and that the sitemap lists exactly the pages built.
A generated share card per page
Satori and sharp render a 1200×630 PNG card for each of the 67 indexable pages at build time, using self-hosted Plus Jakarta Sans and Fragment Mono. Each card ships with an editable SVG twin, and og:image points to the PNG, because social networks do not display SVG.
Motion that can never hide content
One module built on Motion, the vanilla version of Framer Motion, hooks into existing markup: word-by-word headline reveals, blur-up sections, photo wipes, counters, parallax and a reading-progress bar. Nothing animates under prefers-reduced-motion, and the hidden starting state lives only under a class that is removed after 4 seconds if the module fails to load, so neither a visitor nor a crawler sees a blank page.
Retiring the old app from visitors' devices
The React build had registered a Workbox service worker at the site root, so returning visitors would keep seeing the old app from their cache. The new site ships a kill-switch sw.js that unregisters it and clears its caches, served from the root without long caching.
An interactive map of the site's own links
/seo draws every page as a node and every internal link as an edge, coloured by page family and link type, derived from the same data the templates use, so the map cannot drift from what the site actually links. It offers search, filter chips, zoom and pan, and a side panel with each page's keywords and measured search volume.
From a kitchen in Marrakech to cladding in Tanger.
Not a one-page portfolio with an anchor menu. gmab.ma is now a French-language page network, a filterable gallery, a set of buying guides and an interactive map of itself, built to be found by trade and by city. Hover any item to see what it does.
- Homepage
- 6 service pages
- 12 city pages
- 20 topic landings
- 14 service × city pages
- 7 guides + index
- Catch-all route
- 12 cities
- City market context
- Neighbourhoods named
- Measured signals
- Zones hub
- Cross-links
- Why GMAB
- What the offer covers
- Materials & finishes
- In detail
- Process
- Project photos
- Further reading
- FAQ + other trades
- Organization + business
- WebSite
- Service · 52 pages
- FAQPage · 61 pages
- BreadcrumbList · 66 pages
- Article · 8 pages
- Honest areaServed
- Gallery, contact, about
- 67-URL sitemap
- Image sitemap
- llms.txt
- AI crawlers allowed
- Canonical + fr-MA
- Open Graph & Twitter
- Legacy redirects
- Verification slots
- Facts file
- Banned phrases
- No prices
- No fake branches
- Flagged new copy
- Schema guard
- One yellow accent
- Stacked display type
- Bracketed labels
- 1 px grids
- Full-bleed photos
- Arabic accent line
- Dark default
- Contrast-checked light theme
- Split-word headlines
- Blur-up reveals
- Photo wipes
- Animated counters
- Parallax
- Reading progress bar
- Magnetic buttons & tilt cards
- Reduced-motion safe
- SVG link graph
- Live search
- Family filters
- Link-type filters
- Zoom & pan
- Page panel
- Plain-HTML list
- Mailto quote form
- WhatsApp option
- Deferred live chat
- Filterable gallery
- Kill-switch service worker
- Apache rules
- Manifest & icons
- Release zip
74 capabilities across 10 areas, in one French-language static build.
From one invisible URL to a page for every search.
Semrush found no organic competitors for gmab.ma at all, because the old site was not in the race. The real comparison is with the kinds of sites Moroccan joinery and kitchen firms usually run, and with the site GMAB had before.
| gmab.ma v27 | Previous React SPA | WordPress + SEO plugin | Hosted site builder | |
|---|---|---|---|---|
| Content in the initial HTML | ✓ | — | ✓ | ✓ |
| Page per trade and city | ✓ | — | ○ | ○ |
| JSON-LD graph on every page | ✓ | — | ○ | ○ |
| FAQ schema matched to visible FAQ | ✓ | — | ○ | ○ |
| Generated share card per page | ✓ | — | ○ | — |
| llms.txt and AI-crawler rules | ✓ | — | ○ | ○ |
| Build fails on invented claims | ✓ | — | — | — |
| Interactive internal-link map | ✓ | — | — | — |
| No database or plugins to patch | ✓ | ✓ | — | ○ |
| Light and dark themes | ✓ | ✓ | ○ | ○ |
Sixty-seven indexable pages where there was one.
Version 27.1.2 was committed on 30 September 2026 with a deploy-ready build: 68 HTML pages, 67 sitemap URLs, 99 images in the image sitemap, structured data on every page, 302 FAQ answers in schema and a share card for every indexable URL. Against a measured starting point of one ranking keyword and no organic visits, the site now gives search engines and AI answer engines 67 real pages to read instead of one empty shell. A homeowner in Fès looking for a dressing, an architect in Tanger specifying wood cladding or a café owner in Casablanca planning a fit-out now has a page written for that trade, and often for that city, with a FAQ and a direct way to ask for a quote.
The release is packaged for upload to GMAB's Apache host; this case study does not confirm which version is currently live. We have no post-launch ranking, traffic or lead data, and we make no claims about business results. The Semrush search volumes quoted above are third-party estimates, not outcomes. Open items are documented in the project: two new pages (dressings and wardrobes, doors and staircases) are waiting for GMAB to validate their wording, search-console verification codes are still to be added, project photos could move to Astro's image pipeline for responsive WebP and AVIF variants, and price-led pages would need GMAB's own price grid before anything is published. Because every page comes from one registry and is checked by the same audit, each of those additions will ship linked, marked up and truthful from day one.
GMAB — Menuiserie Aluminium & Bois — FAQ
RAIN Design Studio rebuilt gmab.ma as a static French-language Astro 7 site of 68 HTML pages: 6 service pages, 12 city pages, 20 topic landings, 14 service × city pages and 7 buying guides, plus a gallery, a zones hub, a site plan, an interactive /seo map and a 404 page.
It was a client-rendered React single-page app with one real URL and no content in its initial HTML. A Semrush check of the Morocco database on 22 September 2026 found it ranking for one unrelated keyword and drawing no organic visits.
Every claim about the company must come from a facts file extracted from the old site. A post-build audit fails the build if any of about 45 previously invented phrases appear, such as prices or materials GMAB never offered, or if the structured data claims a price range, opening hours or a local branch.
Every page carries a JSON-LD graph, 61 pages carry FAQPage markup with 302 answers in total, and the site publishes a sitemap, an image sitemap and llms.txt. robots.txt explicitly admits GPTBot, OAI-SearchBot, PerplexityBot, ClaudeBot and Google-Extended.
Not yet. The only measured figure is the pre-rebuild baseline of one keyword and no organic visits. RAIN has no post-launch ranking, traffic or lead data for this project and makes no claims about business results.
Yes. RAIN Design Studio in Casablanca rebuilds JavaScript-only sites as static Astro page networks generated from structured data, with schema and audits built in. Custom fixed-scope projects start at $10,000, and a free 15-minute call is the first step.