Skip to content

Case Study · Nova Rock Tools

Building
Without a Brief.

How I turned a four-word brief into a static, bilingual, WhatsApp-first website for a mining tools company — without a designer, mockups, or a brand guide.

2025 B2B · Industrial SvelteKit · Cloudflare novarocktools.com ↗

The result: a static, bilingual, WhatsApp-first product site that went from ~4.2 MB per load to under 400 KB, shipped correct Open Graph previews for every product page, and looked like it belonged in industrial procurement — not a template marketplace.

Concept (WordPress) Perf 57
216.222.198.80/~luxor430/novarocktools
WordPress concept site — navy theme, large text, minimal product content
Production (SvelteKit) Perf 100
novarocktools.com
SvelteKit production site — product-first hero with DTH hammer specs
Metric Concept Production Delta
Performance 57 100 +43
Best Practices 76 92 +16
LCP 7.7 s 0.8 s −6.9 s
FCP 6.1 s 0.5 s −5.6 s
Speed Index 11.0 s 0.6 s −10.4 s
Page weight 549 KB 248 KB −55%
Lighthouse desktop audit — concept site at IP, production at novarocktools.com. Same test conditions, same categories.

The brief was four words: "We need a website."

No designer. No brand guide. No mockups. A logo, a handful of product photos, and a client — a Lima-based mining equipment company called Nova Rock Tools — who knew exactly what they needed their customers to feel, but couldn't sketch it for you.

This wasn't a redesign from a Figma file. It was a business translation exercise: turn a vague need into a site that felt credible to mining procurement teams. That's the most common brief a solo developer gets, and it's the one nobody really talks about.

The client: B2B, industrial, bilingual

Nova Rock Tools makes DTH hammers, drill bits and tricones for underground mining operations. Their customers are procurement engineers at Peruvian mining companies — people who need to trust a supplier before they'll put their number on a quote request. There's no impulse buy. There's no "add to cart." There is: does this company look like they know what they're doing?

DTH hammer — Nova Rock Tools flagship product
DTH Hammer
Tricone drill bits
Tricones
DTH drill bits
Drill Bits

The site also had to speak two languages. Spanish is the language of the business, but ISO certifications and export inquiries increasingly come from English-speaking engineers. One codebase, two audiences — and no brief for either.

What "no designer" actually means

When there's no designer, you don't get a blank canvas — you get a harder constraint. You have to derive the design from the content, not the other way around.

That means asking different questions at the start:

  • What does this customer already trust? (Heavy industry, precision — think Bosch, Atlas Copco. Not playful. Not loud.)
  • What's the single thing a visitor should believe after 10 seconds? (These people know their product.)
  • Where does the customer go when they're convinced? (WhatsApp — not a contact form. WhatsApp.)

The Design Rule

Every decision ran through the same three filters.

01 Does it increase trust?
02 Does it make the product easier to understand?
03 Does it move the buyer closer to WhatsApp?

Those three filters produced most of the design decisions: dark, high-contrast type; clean product photography with no noise around it; a floating WhatsApp CTA pre-filled with the product name, because that's how deals actually happen in Lima in 2025. The goal was not to make it exciting. The goal was to make it credible.

Why static — and why it mattered

The original site was a hand-rolled Svelte SPA — a blank <div id="app"> until ~110 KB of JavaScript had downloaded, parsed, and run. For a business that lives on WhatsApp link previews and Google, that's not a performance problem. It's a trust problem.

WhatsApp scrapers don't execute JavaScript. Share a product page link and your customers see the homepage thumbnail, every time, for every product. The fix was migrating to SvelteKit with static prerendering — all ten routes built to real HTML at deploy time, served from Cloudflare's edge. Correct Open Graph tags on every page. A real 404. No JavaScript required for first paint.

Before → After: WhatsApp link preview

SPA — every page looks like this

novarocktools.com

Nova Rock Tools

Herramientas de perforación DTH para minería…

Static — correct per page

Correct Open Graph preview showing the DTH hammer product

novarocktools.com

Martillo DTH NRT45DH — Nova Rock Tools

Martillo de alta eficiencia para perforación…

The SPA returned a blank image + generic title for every URL — because scrapers never executed the JS that set per-page og:* tags. After prerendering, each product page ships its own correct title, description, and product photo in the initial HTML.

The Image Problem

4.2 MB per page load — mostly images no one audited.

AssetBeforeAfter (WebP)Reduction
Hero hammer1.78 MB77 KB96%
Drill bits1.39 MB214 KB85%
Tricones1.33 MB230 KB83%
Hammer (small)749 KB92 KB88%

Converted with cwebp -q 82 at three widths (480/960/1440 px). The hero was hidden on mobile with display:none in the original — which doesn't stop the download. Phones were paying 1.78 MB for a picture they never saw.

DTH hammer — the site's LCP element, before and after optimisation
The hero. 1.78 MB as a PNG. 77 KB as a responsive WebP. Same hammer, 23× smaller.

The Fix

A <Picture> component emits a proper <picture> element with srcset + sizes, explicit dimensions to kill CLS, fetchpriority="high" on the LCP image, and a mobileSkip prop that emits an empty source on small screens — so the hero is genuinely never downloaded on mobile, not just hidden.

Picture.svelte — usage Svelte 5
<!-- Hero — preloaded, never downloaded on mobile -->
<Picture
  src="/img/dth-hammer.png"
  alt="DTH hammer NRT45DH"
  widths={[480, 960, 1440]}
  sizes="(min-width: 1024px) 50vw, 100vw"
  mobileSkip
  fetchpriority="high"
/>

<!-- Below-fold product — lazy, no mobile skip -->
<Picture
  src="/img/triconos.png"
  alt="Tricone drill bits"
  widths={[480, 960]}
  sizes="(min-width: 768px) 400px, 100vw"
  loading="lazy"
/>
mobileSkip emits <source media="(max-width: 639px)" srcset=""> as the first source — browsers stop at the first matching source, so mobile never requests the file. display:none doesn't do this.

Making design decisions without a design education

This is where most developer-as-designer writing gets dishonest. The honest version: you lean on constraints.

When you're building for a Peruvian mining-tools company:

  • The palette is dark, slate, industrial — because the product is.
  • The typography is clean and readable at small sizes — because engineers read specs, not copy.
  • The layout puts the product image and CTA first — because the goal is a WhatsApp message, not time-on-site.
  • The bilingual toggle is visible and persistent — because switching languages mid-visit is a real behaviour.

None of those are especially creative decisions. They're correct ones. Consumer brands need to delight; industrial B2B needs to not scare people off. The goal was not to make it exciting. The goal was to make it credible.

The part AI actually helped with

The audit that surfaced the image problem, the font-loading issue, the injection-prone contact form, the buttons masquerading as links — that was done by pairing with an AI agent that read the entire codebase and ran real measurements. Not "you should probably optimise images" but "dth-hammer.png is 1.78 MB; at 960w WebP it's 77 KB; here's the cwebp command."

What AI can't do: tell you what the site should feel like. It can't know that a floating WhatsApp button is the most important UI element on the page. It doesn't know that ISO certification badges are a trust signal, not decoration. It can't decide the design should signal "precision" rather than "friendly."

Those are design decisions, and they come from understanding the client's world. That's still the part that requires a human in the room.

What changed

Before and after, in plain numbers.

Page weight (home) ~4.2 MB < 400 KB
Largest asset 1.78 MB 77 KB
Rendering Client-side SPA Static HTML
Crawlable links 0 All routes
WhatsApp / social previews Homepage only Correct per page
Contact form Injection-prone, no validation Escaped + bot-filtered

The live site at novarocktools.com is a fully static SvelteKit build on Cloudflare Pages — ten prerendered routes, WebP images, self-hosted fonts, a Cloudflare Workers contact function wired to Resend with escaping, validation, and a honeypot, and a floating WhatsApp CTA on every product page.

The final site is not trying to be flashy. It is static, fast, bilingual, crawlable, shareable on WhatsApp, and clear about what Nova Rock Tools sells. For this kind of business, that is the design win: not delight, but confidence.

That was the brief.

What I'd improve next

  • Add product structured data (JSON-LD) for each tool — drilling equipment queries are specific and long-tail.
  • Downloadable PDF spec sheets per product, gated behind the WhatsApp CTA.
  • Track WhatsApp CTA clicks by product to understand which tools drive the most inquiries.
  • Spanish-first SEO landing pages targeting specific drill types and mining regions.
  • A small FAQ section answering "¿Hacen envíos a mina?" and "¿Tiempos de entrega?" — those questions earn rich results.

Next up

7 min · 2019–23

Four Years, Two Frameworks, One Mission

Case Study · SAUT