Read Aloud
Text Size
Website • Next.js • React • TypeScript • Docker

There is a particular kind of frustration that comes from maintaining a website you have outgrown. You know every awkward corner of it. You know which updates require a developer to touch a config file, which layouts will break if someone adds an extra paragraph, and which performance issues you have been quietly apologizing for in client calls. That was where we found ourselves with our old site.
The problems were not mysterious. The design had aged out, content updates required developer involvement for even minor changes, and the site structure made it genuinely difficult to add new sections or run marketing experiments without significant rework. Performance was affecting both user experience and search rankings, and we had no content approval workflow and no way to preview changes before they went live. For a software development company whose job is to solve exactly these kinds of problems for clients, it was time to stop tolerating them ourselves.
We decided to rebuild from scratch, not just the visuals, but the underlying architecture. The goal was a platform where editors had real autonomy, developers were freed from content support work, and the site could grow with the business without requiring structural surgery every time we wanted to add something new.
The fundamental tension in any CMS project is between flexibility and control. Give editors too much freedom and layouts collapse; lock things down too tightly and the content team is back to raising tickets for every change. We needed a block-based system where editors could compose pages from reusable components: hero sections, testimonials, CTAs, galleries, without being able to accidentally break things.
We also needed to solve the preview problem. Publishing blind, then checking the live site, then fixing, then republishing is a workflow that sounds manageable until you are dealing with a complex marketing page where visual accuracy actually matters. A proper live preview, one that reflects changes in real time before anything goes public, was non-negotiable.
On the frontend side, we had to balance performance against content freshness. Key landing pages needed to load fast, which pointed toward static generation. But blogs, job listings, and case studies change regularly and need to be current for SEO. Getting the rendering strategy right for each content type, rather than applying one approach to everything, was a meaningful technical decision rather than a default.
And threading through all of it: security and permissions. Sensitive submissions, job applications, contact forms, needed to be visible only to the right people, with role-based access enforced at the data layer, not just the UI.
We split the project into two distinct parts: a headless CMS built on Payload CMS, and a modern frontend built with Next.js, which sits on top of React. Decoupling them was a deliberate choice, it means we can evolve either side independently, and the frontend communicates with the CMS through versioned APIs rather than being tightly entangled with it.
For the CMS, we evaluated several options before landing on Payload. What made it the right choice was its developer-first approach and its block system. We defined a library of reusable content blocks, each one typed, validated, and visually predictable, that editors can combine to build any page layout they need without writing a line of code. The block architecture also means new block types can be added as needs evolve without re-architecting anything. We mapped out all the content types we needed upfront: pages, blog posts, case studies, careers listings, navigation, and more, then built flexible collections for each with custom fields and validators to prevent editors from accidentally publishing broken or incomplete content.
The live preview integration was one of the more satisfying things to get right. As editors build or modify a page in Payload's admin panel, they can open a live preview in a parallel tab that reflects changes in real time. No publishing required, no guesswork about how something will look in context. For complex layouts or time-sensitive marketing pages, this alone has changed how the content team works.
On the frontend, we used Next.js's hybrid rendering model deliberately rather than uniformly. Landing pages are statically generated for fast load times; dynamic content like blog posts and job listings is server-rendered for freshness and SEO. Tailwind CSS powers the design system, keeping styling consistent and responsive without a lot of bespoke CSS to maintain. We also built custom features into the frontend: a contact form with backend validation and email notifications, a CV upload flow for careers applications, error boundaries, and accessible components tested against keyboard navigation, color contrast, and screen reader standards.
For DevOps, we containerized both the CMS and frontend with Docker, wrote automated scripts for building, migrating, and seeding both applications, and set up separate staging and production environments with isolated configs and secrets. Every pull request runs through CI before anything reaches the main branch. Monitoring and logging mean we know about issues before users do, and rollbacks are fast when they are needed.
We also built seeding scripts to populate the database with representative sample data, something that made onboarding new developers and testing new features significantly faster, since every environment starts from the same consistent baseline rather than an empty state or a manual setup process.
The new site is a meaningful step forward in how we operate. Editors can launch campaigns or update pages in minutes rather than raising developer tickets. Developers spend their time on features rather than content support. Load times are down by more than half compared to the old site, with corresponding improvements in user experience and search rankings.
More than the specific metrics, though, the site is now something we can point to. It demonstrates the same thinking we bring to client projects: clear architectural decisions made for real reasons, a workflow that respects both technical and non-technical contributors, and a foundation that will scale with the business rather than constrain it.