Why sections and not just primitives

Primitives are solved. Every library has a button, a card and a stack, and you can assemble anything from them given enough time. That 'given enough time' is the problem: assembling a pricing table from cards means making a dozen layout decisions that have already been made correctly a thousand times elsewhere.

Section components close that gap. `Pricing` is a component. `FAQ` is a component. `Hero`, `FeatureGrid`, `Testimonials`, `LogoCloud`, `Stats`, `Newsletter`, `CTA` and `Footer` are components. You pass data and you get a section that is responsive and accessible without a layout conversation.

The page skeleton

A landing page is a stack of sections inside a container. Import `Hero`, `FeatureGrid`, `Pricing`, `FAQ`, `CTA` and `Footer` from the package root and compose them in order. Because none of these require interactivity beyond what they declare internally, the page itself can remain a Server Component in the App Router.

That last point is worth pausing on. In many libraries a landing page ends up client-rendered because one section needed state and the directive propagated upward. Here the interactive parts declare their own boundary, so the surrounding page stays on the server and ships less JavaScript.

Hero and the fold

`Hero` takes a heading, supporting text and actions. The temptation with any hero component is to pass an image and move on; resist making it the largest contentful paint if you can avoid it, and if you cannot, make sure it is prioritised. This is a performance decision the component cannot make for you because it does not know what else is on the page.

Pair it with `Badge` for an eyebrow line and `Button` for the primary action. `ButtonGroup` handles the primary-plus-secondary pairing with correct spacing, which is one of those details that looks trivial and is annoying to get right by hand across breakpoints.

FeatureGrid, Pricing and Testimonials

`FeatureGrid` takes a list of features and lays them out responsively without you writing a single media query. The library's layout components are responsive by default rather than through props, which means you are not encoding breakpoints in your data.

`Pricing` is the section that saves the most hand-written markup. Pricing tables involve tier comparison, a highlighted plan, feature lists and calls to action, and they are fiddly to make accessible because the visual relationship between a column and its features has to survive being read linearly. `Testimonials` and `LogoCloud` follow the same pattern — pass data, get a correct section.

FAQ, built on native details

`FAQ` uses native `<details>` and `<summary>` rather than a JavaScript disclosure implementation. This matters for more than bundle size: native details is keyboard accessible with no code, works before hydration, and its content stays in the DOM when collapsed — which means search engines index the answers.

That last property is the one people miss. A JavaScript accordion that renders answers only when open can hide your best long-tail content from crawlers. If you are building a marketing page, the FAQ is often the part that ranks, so keeping it in the DOM is a real SEO decision.

What the whole thing costs

Measured with `size-limit`, minified and brotlied with React excluded, the six sections together come to 2.7 kB of JavaScript. That is the entire interactive cost of the page.

The honest addendum is the stylesheet: `styles.css` is 27 kB gzipped and is not split per component, so the page downloads all of it regardless of how few components you used. For a landing page that is usually an acceptable trade, since the CSS is cached across every subsequent page view. For a single-page micro-site with three components it is proportionally worse, and you should know that before choosing.

Key takeaways

  • Section components close the real gap: primitives are solved, assembling a pricing table repeatedly is not
  • Interactive sections declare their own client boundary, so the page itself stays a Server Component
  • Layout components are responsive by default, so breakpoints do not leak into your data
  • FAQ uses native <details>, so answers stay in the DOM when collapsed and remain indexable
  • Six sections total 2.7 kB of JavaScript, brotlied, React excluded
  • The 27 kB gzipped stylesheet is not split — fine for a site, proportionally worse for a three-component micro-page

Conclusion

The value of section components is not that they are hard to write once — it is that you write them once per project, forever, and each rewrite is a chance to get the accessibility slightly wrong. Passing data to a Pricing component and moving on is the correct amount of effort to spend on a pricing table.

Enjoyed this article?

Vivek Kumar Singh

Vivek Kumar Singh

Technical Expert · Full Stack Cloud Engineer · Tokyo, Japan