Solar DNA
A revamp of an existing site. Keep the brand, colours and fonts; rebuild everything under them.
The live site
- BRAND SCRAPED
- CONTRAST MEASURED
- PHOTOS SELF-HOSTED
- 14 ROUTES BUILT
- FORM BUG FIXED
- SHIPPED
Solar DNA already had a website. The job was a revamp, not a replacement, so the brand had to survive it. I scraped their live site for the exact hex codes rather than sampling colours off screenshots. Fjalla One and Source Sans 3, self-hosted through Fontsource. Their own photography, downloaded and served from the build instead of pulled from wherever it was sitting before. Fourteen routes.
Then I measured the brand orange. #FE9700 comes in at 2.18:1 as text. The accepted floor for body copy is 4.5:1, so their own brand colour was unreadable in the place a brand colour gets used most. I split it into two tokens: #FE9700 stays as a fill — bars, icon shapes, where it is a shape and not a sentence — and a darker #AB6600 at 4.53:1 carries any orange word. On screen it still reads as their orange.
The WhatsApp enquiry buttons are WhatsApp green, not Solar DNA orange. The gallery opens in a lightbox. And going through the contact form I found an error box that could never appear: the script toggled a class on it but left the hidden attribute in place, and hidden wins. Anyone who mistyped a field got no error message back. A silent form is a lost enquiry.
The site is an Astro 5 static build with Tailwind CSS 4 and vanilla JavaScript. No UI framework. It ships as a container served by nginx on Google Cloud Run, europe-west1. Images go through astro:assets and sharp. I check the built output rather than the source: headless Chrome driven by Puppeteer, looking for horizontal overflow at 320, 390, 768 and 1440, and pixel-sampling the real rendered background behind text to get the actual contrast ratio instead of the one a design file promised.
Calls I made
- 01
Scraped the brand colours instead of eyeballing screenshots
Their orange is #FE9700. I took it from their live site, not from a screen grab. Their fonts are Fjalla One and Source Sans 3. A colour picked off a compressed image comes back a few values out, and a few values out is a brand colour that is almost right, which reads as wrong to the person who owns it.
- 02
Split the brand orange into a fill and a text colour
#FE9700 measures 2.18:1 as text. The minimum for body copy is 4.5:1, so the colour they lean on hardest was the one nobody could read. I kept #FE9700 as a fill-only token and derived #AB6600 at 4.53:1 for any orange word. Nothing about the brand changed, only the job each token is allowed to do.
- 03
WhatsApp green on the enquiry buttons, not brand orange
The enquiry buttons use WhatsApp's own brand green, which on paper fights an orange-and-white palette. It is worth it. A green WhatsApp button is recognised before it is read, and on a phone that is the whole decision. Matching the palette would have cost me that.
- 04
Fixed an error message that could never be seen
The contact form had an error box that was impossible to display. The script toggled a class on it but never removed the hidden attribute, and hidden wins. Anyone who mistyped a field got no error message back. I fixed it so the box can appear.
Outcome
A 14-route site live at https://solardna-u5rriq3m6q-ew.a.run.app, running as a container on Cloud Run in europe-west1. Same orange, same fonts, same photographs, now self-hosted and measured: #AB6600 at 4.53:1 for orange text. Checked for horizontal overflow at 320, 390, 768 and 1440. WhatsApp enquiry buttons on the pages that need them, a gallery lightbox, and a contact form that tells you when it fails.