Back to blog

Blocks vs Components: What Survives a Rebrand

How VocAny keeps translated page content separate from durable interface components.

May 28, 2026VocAny TeamVocAny Team

VocAny keeps translated page content separate from reusable interface components 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 such as <Hero />, <Pricing />, and <Footer />. Each one reads i18n messages, builds a content config, and passes it to a component.

// src/blocks/header.tsx: reads i18n, wires a component
export function Header() {
  const navLinks = [{ href: '/#features', label: m['landing.nav.features']() }];
  return <SiteHeader navLinks={navLinks} />;
}

Components are durable

Components live in src/components/ and never read translations. SiteHeader, PricingTable, and AppSidebar receive all content through props. They do not know the product name, copy, or active locale, which is why they survive every rebrand.

Why the split matters

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

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

The page files stay small because each one composes a stack of blocks. Changing the landing page touches blocks and translation JSON, not the durable primitives. The split turns a rebrand into a focused rewrite of content and intent.