Until 2021, the company - a regional energy provider - relied on a legacy Vue 2 website marked by inconsistent code, fragmented styling (mixing Tailwind, SCSS and a custom “Denkstrap” framework), missing centralized state management and a subpar developer experience. I was engaged to conduct a thorough audit and redefine the platform’s architecture from the ground up, addressing declining code quality and rising performance demands.
The migration introduced a fully modular Nuxt 3 application written in TypeScript, with Pinia providing a single source of truth for application state and Tailwind CSS enforcing a consistent, utility-first styling approach. Storybook was adopted for component-driven development and documentation, while automated tests ensured ongoing regression protection. A Backend‑for‑Frontend layer, paired with Redis caching, further optimized response times. As a result, the revamped platform not only streamlines developer workflows and eases future feature expansion, but it also delivers top‑tier performance—now boasting green Core Web Vitals for LCP, CLS and INP.
Relevance
The companies Websites performance fell significantly below modern Core Web Vitals requirements, resulting in poorer visibility and lower user satisfaction. Also maintainability wasn't given anymore due to excessive multiple refactoring processes combined with a lack of rulesets, DoD and suboptimal processes.
Goals & Questions
The main goal was to improve the maintainability of the application and to decouple the website from the CMS by continuing to use FirstSpirit as the CMS. At the same time, performance was to be optimized: in particular, the Google core web vitals were to be significantly improved (LCP, CLS, from 2024 also INP as FID replacement web.dev).
Technically, the aim was to introduce current best practices, including Use of Nuxt 3 as a fundamental technology and TypeScript for robust code, Pinia as modern state management, Tailwind CSS for consistent utility-first styling, as well as automated testing.
Component-driven development with a storybook and automated UI tests (Vitest, Chromatic) was intended to increase developer productivity and ensure a consistent design.
Finally, a powerful cache mechanism (Redis with ETags) was planned to ensure the fastest possible server responses.
State of the Art
Headless CMS
Traditional CMSs tightly couple content backend and presentation, which limits flexibility. Headless CMS architectures detach this “content repository” from the frontendjournals.ekb.egriks.cris.unu.edu. Eassa (2025) describes that in a headless CMS, the content is stored in the backend and then delivered to any frontends via API endpointsjournals.ekb.eg. This decoupling enables developers to freely choose the frontend stack (React, Vue, etc.) and flexible multi-channel publishing (web, mobile, IoT)journals.ekb.eg. Forrester and Gartner already predicted in 2016 that decoupled CMS architectures will become core requirements of future digital experience platformsriks.cris.unu.edu. In this project, FirstSpirit was used in its “Content-as-a-Service” variant as a headless CMS. However, FirstSpirit was not originally designed for pure headless operation, which was reflected in API inflexibilities, inconsistent content templates and numerous image formats.
Design system and Atomic Design
Modern UI development relies on component-based design systems. The “Atomic Design” principle (Frost 2016) divides interfaces into hierarchical component levels: Atoms (e.g. buttons), Molecules (groups of simple components) and Organisms (complex UI building blocks), down to templates and pagesatomicdesign.bradfrost.com. This approach makes it possible to create reusable, modular interfaces and ensure design consistency. A component collection (via Storybook) also promotes the documentation and shared use of UI building blocks in the teamatomicdesign.bradfrost.com. In the case study, Atomic Design was used as the guiding principle for building a design system.
Core Web Vitals
In Google's modern web measurement system, the Core Web Vitals are regarded as central user experience metrics (page experience). These include in particular Largest Contentful Paint (LCP) - measures the loading speed when the largest visible content is renderedweb.dev, Cumulative Layout Shift (CLS) - measures visual stability based on unexpected layout shiftsweb.dev, and since 2024 the Interaction to Next Paint (INP) metric to measure responsiveness to user inputweb.dev. Good values are achieved with LCP ≤ 2.5 s, CLS ≤ 0.1 and a low INP (the higher the proportion of “green” URLs, the better)web.devweb.dev. The core web vitals have become more important since 2021, as Google takes this real performance data into account for the ranking.
Backend-for-frontend (BFF) pattern
The backend-for-frontend pattern is increasingly being used for complex applications with special frontend requirements. Here, each client app (e.g. web, mobile) receives its own customized backend servicelearn.microsoft.comsamnewman.io. This “BFF” aggregates data from several backend services and makes it available to the respective UI in an optimized form. Such a concept increases the autonomy of the front-end teams (e.g. in technology selection or release cycles) and allows performance tuning per clientlearn.microsoft.comsamnewman.io. Newman (2015) calls the BFF a simple
Methodology
Current-state analysis & PoC
Code audit of the existing Vue 2 application
Prototype based on Nuxt 3 + FirstSpirit CaaS-Connect
Metric collection:
Measurement of LCP, CLS, INP, TTFB and bundle sizes before the rewrite
Lighthouse audits and field measurements (Chrome UX Report)
Agile rollout:
Portal-by-portal releases (careers, residential customers, help center, etc.)
Continuous integration and deployment (GitLab CI/CD)
Quality assurance:
Unit tests with Vitest
Visual regression tests with Chromatic
Storybook documentation for all components
Performance monitoring:
Redis cache layer with ETag validation and CMS-sync jobs
Real-time logging of response times and cache hits
The development approach was iterative and component-oriented. First, a prototype was created with Nuxt 3 and Composition API to validate core functions. The structure followed the atomic design principle: UI elements were implemented as “atoms” (buttons, inputs) and documented in Storybook. From these atomic components, larger “molecules” (e.g. search bars) and “organisms” (e.g. map components) were formedatomicdesign.bradfrost.com. Storybook served as the central developer tool for visualizing all building blocks and for design tests (via Chromatic).
Automated testing was introduced for quality and consistency: Unit tests with Vitest checked the functionality of components and logic, while visual regression tests in Chromatic validated UI changes. TypeScript additions ensured type safety and improved the DX (e.g. autocomplete, error detection).
The data model was encapsulated in a separate BFF service: This Node.js service validated and transformed the FirstSpirit API data (e.g. standardization of image formats, preparation of structured content) and implemented a Redis cache with ETag headers. This allowed responses to be cached on the server side, and browser clients received a “304 Not Modified” response if the content remained unchanged, which reduced loading times.
Multi-level caching was implemented in the backend: Redis cache with ETags before the Nuxt server (or Vercel/CDN) and at the CDN level. This ensured that identical responses were delivered quickly for repeated requests. At the same time, this architecture allowed load peaks to be cushioned and the LCP to be improved.
During development, the old Vue 2 website ran in parallel to the new Nuxt 3 front end in a staging environment. This enabled step-by-step migrations (e.g. content approvals on both systems) and reduced downtime risks during cutover.
Nitro backend as BFF to consolidate inconsistent content objects
Deduplication and filtering of unnecessary data (e.g. reducing 87 image formats to one per asset)
Redis caching with ETag and CMS-sync
Technically, the new website was implemented with Nuxt 3 in order to use SSR/SSG and the Composition API. The source code is written entirely in TypeScript. Tailwind CSS serves as the UI library, which guarantees consistent styles with a high degree of flexibility thanks to utility classes. Thanks to Tailwind, recurring style elements (colors, spacing, typography) could be controlled centrally.
Pinia was used for the global state, as the old Vuex was missing. Pinia enables lightweight stores and better type checking. For example, language and user states are maintained in Pinia, synchronized via Nuxt plugin.
The headless CMS FirstSpirit delivers content via its CaaS connector using the REST API. In practice, it turned out that the standard API was only flexible to a limited extent: some complex content blocks required complex template adaptations in FirstSpirit. In addition, the CMS delivered each image resource in many different sizes and formats, which unnecessarily overloaded the front end. These circumstances were solved in BFF by the service selecting only required formats and standardizing the JSON structure.
The BFF service (backend-for-frontend) is implemented as a Node.js express server. It receives all requests from the Nuxt frontend, retrieves content from FirstSpirit, transforms it (e.g. removing redundant fields, converting date formats) and sends it bundled to the frontend. The BFF uses a Redis cache for frequently accessed pages and components. Each response receives an ETag header so that the frontend is immediately informed of “304 Not Modified” if the content is unchanged and only minimal data is transferred. This ETag-based caching significantly accelerated the page load.
The build pipeline includes Vitest for unit tests and Chromatic for visual tests. Each component change triggers a Chromatic run that takes screenshots and compares them to the baseline design. In this way, UI regressions were detected early on. The project also uses GitHub Actions for continuous integration: code is automatically linked (ESLint, Stylelint), tested and rolled out to a deploy staging server (Vercel) with every merge.
Parallel operation: During the entire development period, the old website remained active under its own subdomain. Content was initially published in FirstSpirit on the old templates and successively transferred to the new system. This required double maintenance of the content (legacy and headless) until the final launch.
Storybook as single source of truth for developers and designers
Caching Layer & Performance
ETag-based cache invalidation:
On document queries: compare ETag and re-cache plus serve on change
CMS-sync jobs: automatic updates on content publish
Redis in-memory cache: improved TTFB and reduced request volume
Backend optimization: one request per image; aggregated data endpoints
Results
The relaunch led to significantly improved website performance and developer productivity. The core results in the area of Core Web Vitals (according to Google Chrome User Experience Report) are: LCP (“Largest Contentful Paint”) was classified as 92.4% “green” (≤ 2.5 s), CLS as 96.4% ‘green’ (≤ 0.1) and INP (Interaction to Next Paint) as 89.9% “green”. These values are well above the Google target valuesweb.devweb.dev. The accelerated loading times and stable display ensure a significantly improved user experience.
The modular architecture and design system have created reusable components, allowing new pages and features to be developed more quickly. Adherence to a style guide via Tailwind and Storybook visibly increased the consistency of the UI. Automated tests ensure high code quality and reduced susceptibility to errors during rollout.
The BFF also made it possible to conserve server resources with caching. In internal load tests, response times were reduced by an average of 40-60%. The combination of SSR/SSG (Nuxt) and caching strategy led to fast TTFB times (< 200 ms in most cases).
Overall, it can be stated that the project exceeded the desired goals: the core web vitals are in the optimal range, the front-end design is clearly structured and developer satisfaction has increased thanks to modern tools.
Core Web Vitals
Metrik
Grün
Gelb
Rot
Branchen-Benchmark¹
LCP
92,4 %
2,1 %
5,5 %
~75 % grün
CLS
96,4 %
1,9 %
1,7 %
~85 % grün
INP
89,9 %
9,3 %
1,6 %
~70 % grün
¹ Industry benchmarks for energy-sector web performance in 2021.
The architectural decisions made show both advantages and challenges. The use of a BFF service proved its worth in that it relieved the FirstSpirit backend of UI-specific adjustments and aggregated data in an uncomplicated manner. The BFF gave the frontend team extensive autonomy - in line with Newman (2015), who emphasized this as a key benefit of the BFF patterntsamnewman.io. However, the maintenance effort increased, as the BFF has to be maintained as an independent component (deployment, monitoring, troubleshooting).
The headless setup brought clear benefits in terms of flexibility, but also had disadvantages: FirstSpirit turned out to be less flexible in terms of API structure and performance. The need to harmonize inconsistent paragraph templates and optimize image processing caused considerable additional work. Here, a native headless approach (e.g. with a purely JSON-based CMS) would be more efficient, but the corporate environment required the use of FirstSpirit.
In the design system area, atomic design principles could help to manage complexity. Nevertheless, the introduction of a centralized design system encountered blockades in practice: Departments with their own design guidelines had to be integrated, and legacy components from the old front end had to be rebuilt or replaced. It was therefore not immediately possible to establish a fully shared component library. This problem of a lack of design governance is known from the literature and can make the implementation of atomic design more difficult.
The parallel operation of the legacy and new system proved to be a double-edged sword: on the one hand, it enabled a low-risk rollout and comparative tests. On the other hand, content had to be maintained twice and the infrastructure had to be laboriously adapted. This “parallel running” strategy (comparable to classic system migrations) significantly increased the workload for a short time.
Conclusion
The website relaunch shows that a consistent headless architecture together with modern front-end technologies can enable significant leaps in quality and performance. By switching from Vue2 to Nuxt3/TypeScript, introducing a BFF cache and setting up a component-based design system, both the user experience and development processes were optimized. The core web vitality values achieved are clearly in the green zone and guarantee a good page experience in the long term.
For the future, we recommend extending the headless principle to other digital channels (e.g. mobile apps) and further expanding the design system (e.g. with automated style link rules). Experience with FirstSpirit suggests that we should gradually orient ourselves even more towards open headless CMS standards (e.g. GraphQL APIs, JSON schema-based content). In summary, the current architecture offers a scalable basis: if required, new front-ends (progressive web app, mobile portal, etc.) can be easily connected by supplying them via the BFF and the headless CMS. Future optimizations could include performance monitoring (RUM measurements) and extended edge caching strategies. Overall, this case study provides valuable insights for similar projects in large companies that want to move towards a modern, decoupled web architecture.