E-commerce · 2019

Nature.House

Five years leading the full modernisation of a major European vacation rental platform — from raw script tags and a 27 MB JS payload to 0.7s mobile load times, 150 Storybook components, and a deploy on every MR

Nature.House vacation rental booking platform
Role
Senior Software Engineer
Type
E-commerce
Year
2019
Client
Nature.House
Skills
  • Agile
  • Atomic Design
  • AWS
  • BEM
  • Bootstrap
  • CI/CD
  • Confluence
  • Convert.com
  • CSS
  • Cypress
  • Design System
  • DevOps
  • Docker
  • E2E Testing
  • Elasticsearch
  • Figma
  • Git
  • GitHub
  • GitHub Actions
  • Google Analytics
  • Google Cloud Platform
  • Google Optimize
  • Headless CMS
  • HTML
  • JavaScript
  • Jest
  • Jira
  • jQuery
  • JSON
  • Micro Frontend
  • MongoDB
  • MySQL
  • Node.js
  • NPM
  • Nunjucks
  • PHP
  • Playwright
  • PostCSS
  • PWA
  • React
  • Redux
  • Responsive Design
  • REST
  • SASS
  • Scrum
  • Sketch
  • Storyblok
  • Storybook
  • Symfony
  • Twig
  • TypeScript
  • Unit Testing
  • Vite
  • Vitest
  • Web Components
  • Webpack
  • YAML
  • Yarn

I spent five years at Nature.House as the sole front-end engineer and later the lead of a team of five, owning every significant front-end initiative on a large custom Symfony booking platform. We went from jQuery, no build tooling, zero tests, and a 12–14 second mobile load time to a 150-component Web Component design system, 95%+ front-end code coverage, GitLab CI deploying on every MR, and a 0.7 second mobile load time.

Five years, one platform, rebuilt from the inside — and I was there for all of it.

When I joined Nature.House in 2019 as the only front-end developer, the codebase was a collection of raw JavaScript files loaded as sequential script tags with no bundler, no transpilation, and no asset pipeline. Symfony translations were made available to JavaScript by dumping the entire dictionary into the page: 27 MB of translation files on every request, regardless of what the page needed. On mobile, the site took 12–14 seconds before anything was usable.

From zero to Webpack to Vite — and eliminating 27 MB of JS My first task was introducing Webpack, the project's first ever build system. Beyond bundling, I solved the translation problem at its root: translations are now injected at build time — only the keys a specific page actually uses — bringing the 27 MB payload to zero entirely. Combined with image optimisation and general front-end cleanup, mobile load time dropped from 12–14 seconds to 0.7 seconds. In 2023 we migrated from Webpack to Vite, significantly improving build speed and the daily developer experience.

150-component Storybook design system The core multi-year project was replacing a bespoke jQuery stack with native HTML Web Components in TypeScript. Each component was designed and built in complete isolation inside Storybook — unit tested, integration tested, visually documented — then imported into the Symfony application as a standalone package. By the time I left, the design system contained around 150 components. Every component was verifiably correct before reaching production, and the library shipped independently of the host application.

Storyblok headless CMS — marketing autonomy at scale I integrated Storyblok as a headless CMS across all search landing pages and the full homepage structure. Every section is a drag-and-drop block in the Storyblok editor, backed by a live preview integration. The marketing team can build, rearrange, and publish pages entirely without developer involvement — managing SEO content and page layout on their own schedule.

Continuous framework upgrades — Symfony 2 to 8, PHP 5.6 to 8.3 The platform started on Symfony 2 and PHP 5.6. In 2020, we completed the first major leap to Symfony 4 — a migration that required rewriting approximately 50% of the application. That wasn't a one-off: the team has continued upgrading to stay current, reaching Symfony 8.0 and PHP 8.3. I coordinated the front-end side of these migrations while keeping the product continuously running.

From zero tests to 95%+ code coverage When I joined, there was no automated test suite anywhere in the front-end codebase — no unit tests, no end-to-end tests, nothing. I initiated and led the transition to a full testing culture: E2E tests covering all core booking flows, smoke tests across all major pages, and unit tests for every feature. By the time I left, front-end code coverage was above 95% across all repositories.

Monthly releases to deploy-on-every-MR When I started, a production release happened once a month: code frozen, manually QA'd on staging, then deployed. We moved the infrastructure to Google Cloud Platform and built a GitLab CI pipeline that takes a merged MR straight to production automatically. The release cycle went from monthly to every single merge request.

Solr to Elasticsearch, and a complete rebrand Search was migrated from Solr to Elasticsearch, which resolved serious performance issues Solr was experiencing at the scale of Nature.House's inventory. Alongside all of this, Nature.House underwent a full rebrand — new logo, a completely new color palette, and new typography — which I led on the front-end, rolling out the new identity through the design system and into the live platform simultaneously.

Growing a team from scratch I joined as the only front-end developer, paired with a backend team of two. Over five years I helped grow the organisation to four additional front-end engineers, four backend developers, a UI designer, a product owner, and a QA engineer. I led hiring, conducted interviews, mentored junior and mid-level developers, and collaborated directly with the product owner on roadmap priorities.

Nature.House homepage
Homepage
Nature.House vacation homes overview
Vacation homes
Nature.House cottages in the Netherlands
Netherlands
List your vacation home on Nature.House
Renting out
Nature.House mission — protecting local biodiversity
Our mission
Goals(4)
  • Bring mobile load time under 1 second

    The site took 12–14 seconds to load on mobile. The root causes were uncompressed images and 27 MB of Symfony translation files loaded on every page request, regardless of content. Getting this to a usable state was the first and most urgent priority.

  • Replace the inherited jQuery codebase with a scalable architecture

    The front-end was a bespoke jQuery system built by an external agency, with no documentation, no standards, and no separation of concerns. The goal was a fully modern, maintainable architecture that could support a growing team and years of product development.

  • Establish a testing culture from zero

    There were no automated tests anywhere in the front-end codebase — no unit tests, no E2E tests, no smoke tests. Building a testing culture and reaching meaningful coverage was both a quality goal and a prerequisite for safe continuous deployment.

  • Give the marketing team full content autonomy

    Developers were the bottleneck for any change to landing pages and SEO content. The goal was a content infrastructure where the marketing team could create, rearrange, and publish pages entirely on their own schedule.

Responsibilities(3)
  • Front-end architecture across all repositories

    Owned every significant architectural decision on the front-end — tooling choices, component library structure, testing strategy, CI/CD pipeline design, and the standards the team coded to. As the team grew, these decisions shaped how five engineers worked day to day.

  • Technical roadmap collaboration with the Product Owner

    Actively participated in planning and prioritising the product backlog alongside the Product Owner — translating technical debt, refactor work, and infrastructure needs into roadmap items with real business impact. Bridged the gap between what engineering needed and what the product team could prioritise.

  • Grew the front-end team from 1 to 5

    Joined as the sole front-end developer alongside a two-person backend team. Over five years I helped grow and shape the front-end team to five engineers, while the wider organisation expanded to include a UI designer, product owner, and dedicated QA engineer. Led hiring, interviews, and ongoing mentorship.

Key Features(3)
  • Storyblok headless CMS — marketing without developers

    Integrated Storyblok as a headless CMS across all search landing pages and the homepage. Every section is a drag-and-drop block in the Storyblok editor with a live preview integration. The marketing team manages SEO content and page layouts entirely independently, on their own schedule.

  • Progressive Web App

    Implemented PWA capabilities across the platform — offline support, installability, and service worker caching — so the site works reliably on poor mobile connections, which matters for travellers browsing accommodations from remote areas.

  • A/B testing with Convert.com and Google Optimize

    Set up and ran conversion experiments across key booking funnel pages using Convert.com and Google Optimize. Tested layouts, CTAs, and search interaction patterns to make data-driven decisions rather than opinions — directly informing roadmap priorities.

Challenges(4)
  • A live platform that could never go down

    Every major refactor — the jQuery replacement, the Symfony migrations, the infrastructure move to GCP, the full rebrand — had to happen while the booking platform was live and generating revenue. There was no freeze window, no big-bang cutover option.

  • Symfony 2 end-of-life with 50% of the app coupled to it

    Symfony 2 reached end-of-life with no security support. Migrating to Symfony 4 required rewriting approximately half the application due to deep architectural differences between the two versions — a year-long effort on top of regular product work.

  • Running a complex platform as the only front-end developer

    For the first two years I was the sole front-end engineer on a large, complex booking system. Every decision — architecture, tooling, standards, hiring criteria — was mine to own without a front-end team to consult or distribute work to.

  • Rebuilding the foundation while shipping new features

    The refactor ran in parallel with continuous product development. Components couldn't be rewritten in isolation on a separate branch — the jQuery system and the Web Component system had to coexist in production for the duration of the migration, with no regression in functionality.

Solutions(4)
  • Build-time translation injection — 27 MB to zero

    Instead of shipping the entire Symfony translation dictionary to the browser at runtime, translations are now injected at build time — only the specific keys each page actually uses. This eliminated 27 MB of JavaScript from every page request and was the single largest driver of the performance improvement.

  • Storybook as the source of truth for every component

    Each Web Component was built, tested, and documented in complete isolation inside Storybook before it was ever imported into the Symfony application. Storybook became the single source of truth for the design system — the library shipped as a standalone package, independently of the host application.

  • Incremental migration — jQuery and Web Components in parallel

    Rather than attempting a full rewrite, the jQuery components were replaced one by one with native Web Components while both systems ran in production simultaneously. This allowed the team to ship new features and fix bugs throughout the migration without a feature freeze.

  • CI/CD as the quality gate

    With 95%+ code coverage in place, the GitLab CI pipeline became a genuine quality gate rather than just an automation convenience. Every MR triggers the full test suite before deployment. The combination of high coverage and automated deployment made it safe to ship multiple times a day.

Measurable outcomes

  • 12–14sBefore
    0.7sAfter

    Mobile load time

    Root causes: uncompressed images and 27 MB of Symfony translation files loaded on every page

  • 27MBBefore
    0MBAfter

    Front-end JS translation payload

    Solved by injecting only the required translation keys at build time — eliminating runtime delivery entirely

  • monthlyBefore
    per MRAfter

    Release cadence

    GitLab CI pipeline deploys automatically on every merged merge request

  • 150

    Storybook components

    Native Web Components in TypeScript, each individually built, tested, and documented in Storybook before use in the application

  • 0%Before
    95+%After

    Front-end code coverage

    Built from nothing — E2E tests for all core flows, smoke tests across major pages, unit tests for all features

  • 1Before
    5After

    Front-end team size

    Grew from sole front-end developer to a team of five over five years

Colour palette

  • PlumPrimary action color — CTAs, borders, text highlights#5a125b
  • VioletHover and accent states#a458a5
  • ForestPrimary text, headings, and dark surfaces#2f3808
  • OliveSecondary actions and accents#627e16
  • SageAlternate backgrounds and secondary surfaces#ddefae
  • CreamPrimary background#fcfcfb

Typography

  • Let nature wake you up.
    Frauncesheading'Fraunces', serif
  • Find your cottage in nature.
    Work Sansbody'Work Sans', sans-serif