BuildWithMatija
  1. Home
  2. Blog
  3. React
  4. Stop Starting From Scratch: How Vertical Slices Build Reusable Frontends

Stop Starting From Scratch: How Vertical Slices Build Reusable Frontends

Deliver faster by identifying the highest level of abstraction and building reusable vertical slices in your own…

21st September 2026·Updated on:23rd September 2026·MŽMatija Žiberna·
React
Stop Starting From Scratch: How Vertical Slices Build Reusable Frontends

⚛️ Advanced React Development Guides

Comprehensive React guides covering hooks, performance optimization, and React 19 features. Includes code examples and prompts to boost your workflow.

No spam. Unsubscribe anytime.

Related Posts:

  • •Headless UI Primitives: When to Own UI Behavior Today
  • •How to Take Over a Frontend: 4-Step Production Framework
  • •When to Use CSS Modules: A Practical Migration Guide
📄View markdown version
0

Comments

About the author

Matija Žiberna

Matija Žiberna

Full-stack developer, co-founder

AboutResume

Self-taught full-stack developer sharing lessons from building software and startups.

I'm Matija Žiberna, a self-taught full-stack developer and co-founder passionate about building products, writing clean code, and figuring out how to turn ideas into businesses. I write about web development with Next.js, lessons from entrepreneurship, and the journey of learning by doing. My goal is to provide value through code—whether it's through tools, content, or real-world software.

You might be interested in

Headless UI Primitives: When to Own UI Behavior Today
Headless UI Primitives: When to Own UI Behavior Today

9th September 2026

How to Take Over a Frontend: 4-Step Production Framework
How to Take Over a Frontend: 4-Step Production Framework

7th September 2026

When to Use CSS Modules: A Practical Migration Guide
When to Use CSS Modules: A Practical Migration Guide

8th September 2026

Contents

  • Every abstraction saves you from rebuilding something below it
  • Off the shelf doesn't have to mean a third-party library
  • A vertical slice turns building blocks into a working feature
  • The second feature should start higher up
  • Reuse the highest suitable abstraction, not the highest available one
  • A growing frontend should become easier to compose
  • Related Reading & Frontend Architecture
On this page:
  • Every abstraction saves you from rebuilding something below it
  • Off the shelf doesn't have to mean a third-party library
  • A vertical slice turns building blocks into a working feature
  • The second feature should start higher up
  • Reuse the highest suitable abstraction, not the highest available one
Build with Matija logotip

Build with Matija

Complex B2B websites, headless CMS platforms, AI workflows, and internal systems designed and built with Next.js and Payload CMS.

Services

  • B2B Website Development
  • CMS Architecture Review & Platform Blueprint
  • Next.js + Payload Advisory
  • AI Integration & Implementation

Resources

  • CMS Hub
  • B2B Website Strategy
  • E-commerce Hub
  • Blog
  • Case Studies
  • About Matija

Payload CMS

  • Payload CMS Developer
  • Payload CMS Migration
  • Payload CMS Demos
  • All Payload CMS Resources

Discuss your project

Planning a rebuild, migration, application, workflow change, or platform decision? Start with the business problem and the system behind it.

Book a discovery callContact me →
© 2026Build with Matija•Vse pravice pridržane•Politika zasebnosti•Pogoji uporabe
BuildWithMatija
Get In Touch

If you listen to a project manager, a frontend developer, and a product designer discuss building a new web feature, you will often hear three completely different vocabularies for the same screen.

The designer talks about design systems and visual consistency. The developer talks about utility classes, shadcn components, or headless primitives. The project manager just wants to know why building a product listing on the homepage took three weeks, and why building an almost identical listing on the category page is slated to take three more.

When teams start from scratch with every ticket, the confusion isn't caused by bad code. It's caused by a failure to agree on levels of abstraction:

  1. The Styling Layer (The Foundation): Where raw visual tokens live—custom CSS, CSS Modules, or atomic utility classes like Tailwind.
  2. The Component & Primitive Layer (The Machinery): Interactive elements like buttons, dialogs, sheets, and dropdowns that bundle headless interaction behavior with styling contracts (such as Radix or Base UI).
  3. The Section & Content Block Layer (The Composition): Structured, relational CMS blocks—such as Payload CMS layout blocks—that compose existing primitives into repeatable page sections without re-declaring their internal logic.

When technical leaders make these abstraction layers explicit, teams stop rebuilding components from scratch and start delivering features as cohesive, reusable vertical slices.

Every abstraction saves you from rebuilding something below it

At the lowest level, the browser already gives us HTML elements, CSS, JavaScript, and built-in interaction behavior.

We can work directly with those capabilities. We can write bespoke styles, implement custom controls, and arrange everything ourselves.

But we can also build—or adopt—abstractions that package recurring decisions.

A styling system gives us reusable tokens, typography, and layout conventions. A UI primitive handles difficult interaction behavior. A styled component combines behavior with a particular visual treatment. A section arranges components into something meaningful, such as a product grid. A page template composes sections into a repeatable page structure.

Each level potentially saves us from making the same lower-level decisions again.

Think of the available building blocks like this:

LevelExample
Browser capabilitiesHTML, CSS, JavaScript
Styling abstractionsTokens, Tailwind utilities, reusable CSS patterns
UI behavior primitivesSelect, Dialog, Combobox
Application componentsProductCard, ProductSearch
SectionsProductGrid, FilterPanel
Page templatesProduct listing, product detail
Complete featuresA working, data-connected product listing

For complex accessibility, focus management, and keyboard handling at the behavioral level, adopting Headless UI Primitives (such as Radix, Base UI, or Floating UI) allows teams to own presentation without reinventing intricate state machines.

This isn't a rigid technical hierarchy. Styling and interaction primitives, for example, address different concerns and can be combined in different ways.

It's a way to recognize how much functionality and how many decisions have already been packaged for reuse.

The higher-level building block isn't automatically better. A ready-made template that doesn't fit your requirements may be harder to adapt than a new page assembled from existing sections.

The useful question is: What's the largest existing building block that fits this job without forcing the wrong structure?

Off the shelf doesn't have to mean a third-party library

When developers hear “reuse,” they often think of installing another dependency.

That is one option. We can use a mature UI primitive instead of writing all the keyboard and focus behavior for a combobox. We can use an established styling system rather than inventing every spacing and typography convention.

But a project's own codebase should increasingly become its most relevant source of reusable building blocks.

After the first product listing is finished, the project may already have a ProductCard, ProductGrid, filter controls, and a listing template.

Those are now off-the-shelf options for the next feature in that project.

This is where abstraction and vertical slicing meet.

A vertical slice turns building blocks into a working feature

A vertical slice is not simply a collection of finished UI components.

It is a complete piece of functionality that works through the parts of the system it needs.

For our product listing, that means more than rendering a convincing mockup. A visitor should be able to open the page, search for a product, apply a filter, and see results supplied by the actual product data source.

To deliver that slice, we might:

  • Reuse the site's existing styling foundations.
  • Adopt a proven combobox primitive for search.
  • Adapt an existing ProductCard.
  • Compose a ProductGrid and filtering section.
  • Connect the listing template to Payload CMS.
  • Verify the result with real content, interaction tests, and responsive layouts.

In How to Take Over a Frontend: A 4-Step Production Framework, I detail how to integrate vertically with the data layer while preserving visual parity, rather than stalling delivery on speculative component rewrites. When developers understand that unfinished work is part of a deliberate architectural sequence rather than an unassigned gap, they avoid the coordination drag explored in When Helping Creates More Work.

Some pieces come from the ecosystem. Some come from the project. Some must be built specifically for this feature.

The goal isn't to maximize reuse at any cost. It's to deliver one complete experience without unnecessarily recreating capabilities that already exist.

And once that experience works, something important has changed.

The project now has more to reuse than it did before.

The second feature should start higher up

Now imagine building the related-products section on a product detail page.

We don't need to begin with CSS rules or product-card markup.

We may not even need to begin at the component level.

If the ProductGrid already supports the layout we need, we can reuse the entire section and supply a different set of products.

The original vertical slice has given the next slice a higher starting point.

Then we build a category landing page.

If its requirements match the existing listing template, we may be able to reuse that template, configure its filters and product source, and concentrate on the parts that are genuinely different.

The progression looks like this:

First feature: Assemble primitives and components into a new section and template.

Second feature: Reuse the section; implement only the missing integration or variation.

Third feature: Reuse the template if it fits; configure rather than reconstruct.

That is the compounding effect of a well-structured frontend.

The amount of work doesn't necessarily decrease with every feature—some features introduce entirely new problems. But the team no longer has to solve every old problem again.

Reuse the highest suitable abstraction, not the highest available one

There is a trap in this approach.

Once a team has created a reusable section, it can become tempting to make every future requirement fit that section. Soon, its API contains dozens of options, special cases, and conditional layouts.

The abstraction that was supposed to save time becomes difficult to understand.

So the rule needs a qualification:

Start at the highest abstraction that genuinely fits. Move down only as far as necessary.

If the template fits, use it.

If the template doesn't fit but its sections do, compose a different page from those sections.

If a section doesn't fit but its components do, reuse the components.

If the components don't fit, perhaps their UI primitives or styling foundations still will.

And if the requirement really is unique, build what it needs.

Balancing these layers objectively requires aligning technical tools with client business requirements rather than dogmatic tool bias, as discussed in Client Judgment vs. Preferred Technology.

This is also why not every piece of code needs to become reusable the moment it's written. Sometimes the right choice is to implement a feature clearly, then extract a shared abstraction when a second real use case reveals what the common contract should be.

Reuse should emerge from genuine shared requirements, not from trying to predict every future possibility.

A growing frontend should become easier to compose

The promise of vertical slicing is often framed around delivery: ship one working piece, validate it, then move to the next.

That's valuable, but there is a second benefit.

Each completed slice can expand the set of reliable abstractions available to the project.

The first feature may require substantial work at the component and section levels. The next may reuse an entire section. Another may be mostly template configuration and data integration.

Developers spend less time reconstructing familiar interface patterns and more time solving the requirements that make each feature different.

That's the frontend I want to build: not one where everything is forced into a universal component system, and not one where every new page starts with an empty file.

Then, for each new feature, we start as high up that ladder as the requirements allow—and deliver a complete vertical slice from there.


Related Reading & Frontend Architecture

For deeper guides on frontend design systems, UI behavior primitives, and delivery frameworks:

  • Headless UI Primitives: When to Own UI Behavior — When to use Radix, Base UI, or Floating UI instead of building custom state engines.
  • How to Take Over a Frontend: A 4-Step Production Framework — Preserving design parity, proving stability, and integrating vertically.
  • When CSS Modules Help: Migration Guide — Scoped styling vs utility-first CSS in component-driven applications.
  • When Helping Creates More Work — Why unfinished components aren't unclaimed tasks and how architectural sequencing prevents duplicated work.
  • Client Judgment vs. Preferred Technology — Separating tool bias from business outcomes when advising clients.
  • Technical Leadership Is More Than Having the Answer — Connecting technical decisions to business outcomes and leading teams effectively.

If you are structuring a modern Next.js or React application, explore my Next.js & Payload CMS Advisory or learn about my B2B Website Development process.

Comments