Skip to content

E-commerce · Next.js App Router

Lappeland

A Norwegian custom-label store whose traffic doubled after a rendering rebuild.

Product
Lappeland — custom-label storefront for the Norwegian market
Role
Senior frontend engineer, contract
Scope
Next.js App Router build, SSR and ISR rendering architecture, Core Web Vitals tuning
Lappeland case study cover

The tension

Doubling traffic was a rendering problem before it was an interface problem.

What was happening

A custom-label storefront for the Norwegian market — name labels, mini labels, wall decor — built on Next.js App Router and TypeScript, with a configurator and a catalogue that changes constantly.

What changed the brief

Discoverability depended on what the server sent, not on what the client could assemble afterwards — so the rendering strategy became the lever, and the interface followed it.

Success looked like

More organic traffic reaching product pages, and Core Web Vitals inside budget on mobile rather than on a desktop test rig.

The constraint

A live catalogue could not wait on a full rebuild to publish a change, which ruled out static generation on its own.

traffic post-launch

Measured after the rendering rebuild shipped.

~95Lighthouse performance

Held on mobile, not on a desktop test rig.

The product story

The storefront, one rendering decision at a time.

Server-rendered

The first paint is the whole pitch.

The landing view ships from the server, so the product grid is content on arrival rather than a skeleton waiting on JavaScript.

Lappeland — landing view
Product cards arrive as HTML.Server Components render the grid, so it is indexable and visible before any client bundle has run.

Mobile-first

Built at the narrow width first.

Tailwind layouts start mobile and widen, verified across browsers and viewports against the Figma designs.

Lappeland — mobile view
The same markup, reflowed.Semantic structure and responsive utilities rather than a separate mobile template.

Incrementally static

Fresh pages without a rebuild.

ISR lets catalogue pages regenerate on their own schedule, so an edit publishes without redeploying the site.

Lappeland — full page
The long page stays cheap.Cached at the edge and revalidated in the background, so depth costs nothing at request time.

Walkthrough

The storefront in motion

Recorded from the live site.

The trust test

The happy path is only half the product.

Stock moves between regenerations

Anything reflecting live availability is server-rendered on request, so the incrementally regenerated page is never the one asked to be honest about stock.

The client bundle never arrives

The catalogue was rendered on the server, so it stays readable and indexable when the JavaScript that would have assembled it does not run.

There is no pointer

Keyboard navigation, focus management and screen-reader testing were scoped work rather than a pass at the end, so the storefront is operable without a mouse.

The decisions

Three moves carried the story.

Render on the server

SSR and ISR through the App Router, so pages are content when they arrive and stay fresh without a rebuild — the change that doubled traffic after launch.

Split what the browser has to parse

Code splitting and Core Web Vitals tuning, so the interactive weight of a page tracked what the page actually needed.

Treat accessibility as scope, not polish

WCAG 2.1 AA deliberately rather than incidentally: ARIA roles, keyboard navigation, focus management, contrast audits and screen-reader testing.

What I would test next

The revalidation window was tuned to the catalogue at launch. Whether it still matches how it changes now is worth measuring.