Rukon
Back to Project Overview
Full Case StudyWebsites

ERTH

ERTH: production homepage, technical SEO and GEO implementation

ERTH mark
Role
Website Designer & Developer

Website Design (Figma), Production Frontend Build & TypeScript Migration (Team-based)

Affiliation / Client
ERTH (Malaysia's #1 E-Waste Collector, Jabatan Alam Sekitar Certified)
Timeline
2026 (completed, ongoing TypeScript migration)
Documentation Level
12 Engineering Sections

Operational Workflow & State Machine

End-to-End Pipeline
  1. 01Prototype in Figma
  2. 02Audit the approved design
  3. 03Rebuild as static HTML/CSS/JS
  4. 04Verify the build
  5. 05Deploy
01

Overview

ERTH is Malaysia's #1 e-waste collection and recycling service, officially certified by Jabatan Alam Sekitar (JAS) Malaysia and operated in partnership with Blue Bee Technologies: doorstep pickup, free shipping through Pos Malaysia, a 24/7 drop-off point in Cyberjaya, and cashless rewards. The site is a comprehensive single-page digital gateway covering residential and corporate e-waste pickups, real-time device pricing, accepted electronics catalogs, enterprise recycling compliance, and JAS-certified environmental standards.

As Website Designer and Developer working alongside our engineering team, I handled the project across its lifecycle: prototyping the complete interface and interaction design in Figma, engineering the approved design into a fast, zero-bloat production website (1,076 lines of markup, 534 lines of CSS and 228 lines of JavaScript bundled by Vite), and currently scaling the frontend architecture with TypeScript.

02

Problem

A recycling and trade-in service depends on people trusting it enough to hand over a device and the data on it. As Malaysia's #1 collector certified by Jabatan Alam Sekitar, the page has to make the process, the pricing, the eligibility rules and the handling of personal data legible before someone commits to anything.

The approved design existed only as a self-extracting design-tool bundle: fonts, images and markup encoded as base64 inside script blocks, unpacked in the browser at runtime, with React and Babel pulled from a CDN and a runtime that re-rendered inline styles on every state change. It demonstrated the design. It was not a website anyone should ship.

03

Context

The client's decision was that one design file was final and every earlier revision was superseded. That made the brief unusually precise: not build something like this, but ship exactly this, correctly.

A locked design is the interesting constraint. Meeting a long list of content, search and accessibility requirements is straightforward if you are allowed to add sections. Meeting them inside a design nobody may change is a different problem, and it is the one this build was.

04

My Role

I served as the Website Designer and Developer for ERTH within our engineering team. ERTH is Malaysia's #1 e-waste collector certified by Jabatan Alam Sekitar (JAS), demanding high institutional trust, full accessibility compliance, and lightning-fast mobile responsiveness.

In the first phase, I designed the interface and worked it out as an interactive Figma prototype before implementation, establishing the visual system, layout structure, and the user flow from selecting an electronic device through to collection booking and payout.

In the second phase, I built the production website: extracting assets from the approved bundle, rebuilding the page into clean semantic code, eliminating 250 kB of framework runtime, and implementing full technical SEO and Schema.org structured data. Alongside our engineering team, I am now modernizing and scaling the codebase with TypeScript.

Team project: I served as the website designer and frontend builder, and continue to develop features with TypeScript alongside our team for Malaysia's #1 JAS-certified e-waste recycler.

05

Engineering Approach

The stack decision was to remove rather than add. A single static page does not need React, Babel, a CDN dependency or a render pass before first paint. Dropping all of it took roughly 250 kB of JavaScript out of the page and left 3.7 kB that does nothing but handle interaction.

The inline styles were deliberately kept. In the approved file the inline style attributes are the design specification: every dimension, colour and clamp() lives there. Rewriting a thousand of them into class names would have introduced visual drift for no functional gain, so the markup was preserved and only the parts a static file cannot express moved into CSS.

Three things had to move. Hover attributes the prototype's runtime interpreted became real hover rules. Open and closed state the prototype expressed by rewriting inline display became hidden, aria-expanded and a class, with CSS deciding appearance. And the desktop and mobile split the prototype computed from window.innerWidth in JavaScript became a media query at the same breakpoint, so the correct layout is painted on the first frame instead of after hydration.

06

Fixing the prototype

Rebuilding a design file section by section surfaces defects that a demo hides. Four were real enough to fix.

The page wrapper closed early, part-way down the document, so every section after it never inherited the light text colour. One heading rendered black on a near-black background. The colours now live on the body element.

A dialog contained an iframe whose source was an unresolved template binding, so every page load fetched a URL that did not exist. No booking form was configured, so the iframe is gone and the contact-channel list the design already provided is the dialog body.

Six links pointed at the section they were already inside. They now resolve to the action they describe. And two grid definitions forced horizontal scrolling below 400px, which a minmax floor and a released column span fixed.

07

Verifying the build

A hand-built static page has no type checker, so the guarantees had to be written. A post-build script runs as part of every build and fails it on a referenced asset missing from the output, an in-page link or aria-controls pointing at an id that does not exist, an absent required head tag, JSON-LD that does not parse, an image with no alt text or no intrinsic size, more or fewer than one h1, or any prototype artefact surviving into the output.

That last check is the one that matters most on a project like this. A template binding or a generated class name that leaks into production is invisible in review and obvious to a visitor, and it is exactly the kind of thing a rebuild leaves behind.

08

Technical SEO

The head block was built out from nothing: the specified title and meta description, a canonical URL, robots directives, a full Open Graph set with the locale declared as Malaysian English, and a large-image Twitter card, plus robots.txt, sitemap.xml, a web manifest and a full favicon set.

Three JSON-LD blocks ship. An Organization node also typed as a recycling centre, carrying the alternate name, legal name, logo, contact details, a full postal address for the Cyberjaya premises, the areas served and a verified social profile. An FAQPage node mirroring the sixteen questions visible on the page. And a WebSite node stating the site name and alternate name.

Structure was treated as information architecture rather than decoration: one h1, section-level h2s, card-level h3s, descriptive alt text, and an internal-linking pass that found several sections were unreachable from the navigation despite being on the page. All page content is in the static HTML; nothing depends on JavaScript to be crawlable.

09

GEO / AI-search readability

Content an AI system can read and answer from directly is a different target from ranking a page. The approach was to test it rather than assert it: nine questions a visitor actually asks, each checked for whether the page answers it self-containedly.

Where a section needed to survive being extracted on its own, it was written to do so. The block explaining the difference between disposal and recycling defines both terms, states the distinction and says why it matters, so an answer engine quoting only that block still produces something correct.

Recognition claims were restructured to carry who recognised the achievement, when, and where it can be verified, because for an AI system an unattributed claim and an invented one look the same. The FAQ was expanded from the objections customers actually raise rather than from a keyword list, and the structured data mirrors exactly what a reader sees.

10

Content accuracy

A consistency pass across the page found six contradictions and unsupported claims. These were raised for a client decision rather than resolved unilaterally, because picking one reading of a business rule is not a developer's call to make.

One was a headline figure that appeared to confuse two different units: a large number presented as currency where the cited source reported it as a weight. Catching that before publication mattered more than any markup change in the engagement.

The working stance throughout was to verify, soften, or omit. No award, statistic, certification, testimonial or coverage claim was introduced that the source material did not support.

11

Performance and accessibility

Every font and image is self-hosted, so the page makes no third-party requests at all. Photographic and illustrative assets were re-encoded to WebP and the largest ones given srcset variants, taking the image payload from 12.0 MB to 2.7 MB. Every image carries intrinsic width and height so nothing shifts as they arrive, below-the-fold images are lazy, the hero backdrop is marked high priority, and the two Latin font subsets are preloaded.

On accessibility: a skip link, main, nav, footer and aside landmarks, accessible names on sections carrying no heading, a visible focus ring on every interactive element, aria-expanded and aria-controls on all disclosures and dropdowns, Escape and focus trapping in both dialogs with focus restored to the opener, keyboard-operable navigation dropdowns, underlines on inline links that colour alone did not distinguish, and prefers-reduced-motion honoured. axe-core reports zero violations in the default, mobile, menu-open, dialog-open and disclosure-open states.

12

Outcome

The website development is complete. The production homepage is built, verified and deployed on Vercel, serving the approved design as static files with no third-party requests, a passing post-build check, and a head block carrying full metadata and three structured-data blocks where previously there were none.

It is recognisably the same design the client approved. What changed is everything underneath it: a quarter of a megabyte of prototype JavaScript gone, an image payload cut by more than three quarters, four real defects fixed, and a build that refuses to ship if any of that regresses.

What's live, and what isn't

“It exists in the repository” and “it runs in production” are different claims. This is the difference, stated rather than left to be assumed.

  • ImplementedProduction homepage buildComplete and deployed. Static HTML, CSS and vanilla JavaScript bundled by Vite 7.
  • ImplementedTitle, meta description, canonical, robotsAll present in the shipped page; none existed before.
  • ImplementedOpen Graph and Twitter cardFull Open Graph set with Malaysian English locale, and a large-image Twitter card.
  • ImplementedStructured dataThree JSON-LD blocks: Organization / RecyclingCenter, a sixteen-question FAQPage, and WebSite.
  • ImplementedSemantic landmarks and accessibilitySkip link, main / nav / footer / aside landmarks, focus management in both dialogs. axe-core reports zero violations across five interaction states.
  • ImplementedPerformance passSelf-hosted fonts and images, WebP with srcset, intrinsic sizing, lazy loading. Image payload 12.0 MB to 2.7 MB.
  • ImplementedPost-build verificationRuns on every build and fails it on a missing asset, dead in-page link, missing head tag, unparseable JSON-LD, image without alt or intrinsic size, or a surviving prototype artefact.
  • Not connectedFree-pickup eligibility wordingA content question, not a build one. Two readings of the eligibility rule appear in the client-approved copy; it was raised for a ruling and both are carried through as supplied rather than silently picked between.
  • Built, not liveGallery and press-outlet imageryIntentional placeholders in the approved design, labelled as awaiting photography and carried through as-is.

Technical stack

Design & prototyping

FigmaInteractive prototypeComponent vocabulary

Implementation

TypeScriptHTML5CSS3Vanilla JavaScriptSemantic HTMLResponsive CSSVite 7

Search & structured data

Schema.org JSON-LDOrganization / RecyclingCenterFAQPageWebSiteOpen GraphTwitter cardsCanonical URLsrobots.txt / sitemap.xml

Performance & accessibility

Self-hosted WOFF2 subsetsWebP re-encodingsrcsetaxe-coreprefers-reduced-motionFocus management

Quality & platform

ESLint 9sharpPost-build verification scriptVercel

Limitations

  • The content and SEO strategy was supplied by the client. This engagement was the design prototyping, the production build and the compliance implementation, not the strategy.
  • Two sections are placeholders in the approved design pending client-supplied photography, and are carried through rather than invented.
  • One eligibility rule is stated two ways in the approved copy and remains a client content decision.

Source and further reading

Finished the technical breakdown?

Return to the concise HR overview or discover other projects in the portfolio.

Writing from this work

Building Software in Cyberjaya: The Development Environment Behind the Work

What a production operations system, a client website, an AI research assistant and a vision inspector actually get built on, from a laptop in Cyberjaya: the machine, the stack, where things are hosted, and the local details that shaped the code.

Cutting a Page's Image Payload From 12 MB to Under 3 MB

The performance and accessibility pass on a production homepage: what was actually slow, what fixed it, and why most of it was not clever.

Verifying a Static Site You Built by Hand

Hand-written HTML has no type checker and no test runner. On a production build I wrote the guarantees instead, as a post-build script that fails the build.

Rebuilding a Design-Tool Prototype as a Production Website

An approved design arrived as a self-extracting bundle running React from a CDN. Shipping it meant removing almost everything and keeping the part that was actually the specification.

Designing for Desktop and Mobile Before Development

Planning responsive behavior as part of the design phase, instead of leaving it as a problem for development to solve alone.

Translating Figma Components Into Reusable Code

How design components in Figma map to reusable UI components in code, and where that mapping gets harder than it looks.

From Figma Design to Production Website

What actually happens between a finished Figma design and a working, deployed website.

Designing a Website in Figma Before Development

Why doing the design work in Figma first, rather than designing in the browser, changes how the build goes.