Templiox
Back to blog

Blocks vs Components: What Survives a Rebrand

The core architectural split in this SaaS foundation — disposable blocks read i18n and wire content, durable components render anything you feed them.

May 28, 2026Templiox TeamTempliox Team

Every template promises "easy customization," then makes you grep through twelve files to change a headline. This foundation avoids that with one rule:

A file that reads translations is a block. A file that takes all content via props is a component.

Blocks are disposable

Blocks live in src/blocks/ and are zero-config page sections — <Hero />, <Pricing />, <Footer />. Each one reads i18n messages, builds a content config, and passes it to a component. They're the demo material: when you start a real project, you delete them and write your own.

// src/blocks/header.tsx — a block: reads i18n, wires a component
import { m } from '@/paraglide/messages.js';
import { SiteHeader } from '@/components/site-header';

export function Header() {
  const navLinks = [{ href: '/#features', label: m['landing.nav.features']() }];
  return <SiteHeader navLinks={navLinks} />;
}

Components are durable

The design rule for reusable components in src/components/ is to receive content through props. Marketing shells such as SiteHeader and AppSidebar illustrate this direction. PricingTable now receives checkout callbacks and translated labels through props. Some other components, including user menus, still read translations or initiate business requests; separating those concerns is ongoing architectural work. Audit each component's imports before treating it as a product-independent primitive.

Why the split matters

When you rebrand or start a new project from the template:

  1. Keep src/components/* — the chassis.
  2. Rewrite src/blocks/* — the content wiring.
  3. Rewrite the translation JSON files that feed the blocks.

The page files themselves stay tiny — src/routes/index.tsx is pure composition, a stack of blocks. A content-only rebrand should normally touch blocks and JSON. Changes to layout or interactions can also require extending the primitives. The split is not cosmetic; it's what makes customization a rewrite of intent instead of a fight with someone else's design decisions.