Most portfolio and marketing pages hardcode their sections in a single, ever-growing component. It works — until you want to reorder things, hide one section for an A/B test, or reuse a block elsewhere. Every change means editing JSX.
There's a cleaner way: treat the page as data. This post walks through a small pattern I used to make a homepage fully config-driven.
The core idea
Instead of writing sections in order, describe them in a config object and render from it. Two pieces:
- A settings map — which sections are on, and in what order.
- A registry — mapping each section id to its component.
The page reads the settings, sorts, and renders. Reordering or hiding a section becomes a one-line config edit.
The settings map
export const sectionSettings = {
hero: { enabled: true, order: 10 },
projects: { enabled: true, order: 40 },
testimonials: { enabled: false, order: 70 },
} as const;
export function getOrderedSectionIds() {
return (Object.keys(sectionSettings) as SectionId[])
.filter((id) => sectionSettings[id].enabled)
.sort((a, b) => sectionSettings[a].order - sectionSettings[b].order);
}Because the keys are a typed union, TypeScript guarantees you can't reference a section that doesn't exist.
The registry
The registry maps ids to components. Marking it Partial lets configuration run ahead of implementation — a section can be enabled before its component exists, and the page just skips it.
export const sectionRegistry: Partial<Record<SectionId, ComponentType>> = {
hero: Hero,
projects: FeaturedProjects,
};Rendering the page
export default function HomePage() {
return (
<main>
{getOrderedSectionIds().map((id) => {
const Section = sectionRegistry[id];
return Section ? <Section key={id} /> : null;
})}
</main>
);
}That's the whole page. It never changes when content does.
Why this scales
This is the Open/Closed Principle in practice: the page is open to extension (add a section to config + registry) but closed to modification (you never edit the page itself). It also keeps layout decisions in one reviewable place, which is a gift when you come back six months later.
The same pattern generalizes to dashboards, settings screens, and any surface where the arrangement of blocks is itself a product decision.