One Design Language for Every Page
The homepage redesign left five subpages looking like a different website. The fix was not restyling each page by hand but extracting shared components.
TL;DR
Shipping a polished homepage exposed inconsistent spacing, heroes and buttons across other pages. Instead of patching each page, the fix extended two components, page-hero.tsx and page-cta.tsx, plus a borderless card pattern using layered gradients, CSS variable tokens and consistent pill buttons. Pages now share the same visual language through props while keeping unique content, so updates happen in one place.
I Just Finished the Homepage and Every Other Page Looked Wrong
I shipped the new homepage. Gradient mesh on top, dotted grid behind it, soft accent glow on the side. Looked exactly how I wanted.
Then I opened `/about`. Then `/services`. Instant whiplash. Different spacing, different hero treatment, buttons with slightly different radius. It felt like three different websites stitched together.
My first instinct was to go page by page and make them match the homepage by hand. Copy the background, tweak the padding, fix the button. I almost did it too. It would have worked for a week, then the next redesign would break it all again.
Fixing pages one by one is a trap
That approach does not scale. Each page drifts. You forget one radius value somewhere and suddenly you have four slightly different pills. Change the primary color and you have to grep through every file.
Commit `b0a1e5f` touches 20 files, so it looks massive at first. But the core is small. I didn't restyle every page manually. I extended two components that already existed: `page-hero.tsx` and `page-cta.tsx`. Plus one shared card idiom. Everything else is just pages consuming them.
That's the whole trick. Instead of making pages look alike, make them inherit the same language.
The shared hero handles the layered background. The CTA handles the closing section. Cards handle the middle. Pages just pass props and children, so they keep their own personality without inventing new styles.
Two components that carry the whole language
`page-hero.tsx` is where the homepage look lives now. It stacks two layers in one `background-image`: a radial gradient mesh and a dotted grid. `radial-gradient()` is technically an image data type [3], so you can layer it with other images like this.
No magic there. Colors are not hardcoded. They are design tokens: name/value pairs that store design decisions [1], expressed as CSS custom properties. So `var(--accent-glow)` or `var(--dot-color)` is the single source. Change the variable once, it propagates everywhere [2]. I personally wouldn't do it any other way now, even though hardcoding hex codes feels faster at first.
`page-cta.tsx` does the same at the bottom of every page. Same background language, same pill button.
That `rounded-full` is intentional. Every primary action across the site is a pill now. Same padding, same radius. No more `rounded-md` on one page and `rounded-lg` on another.
Cards follow the same rule. I went borderless: a flat surface with a hairline divider between sections. Too many borders make the UI feel busy and heavy [4], and I felt it instantly when I compared the old boxed cards side by side. Cleaner without them.
For icons inside those cards I use Lucide `Check`. I like that Lucide is tree-shakable [5]: you import only the icons you use, the rest gets shaken out of the bundle. No extra weight for a simple checkmark.
Why this actually holds
This works because the components take `props` and `children`. The hero doesn't decide what the page says, it decides how any page says it. About can pass a longer subtitle, Services can inject an extra badge, but both render through the same mesh and grid and glow.
And because tokens live as custom properties, a color tweak is a one-line change in `globals.css`, not a hunt through 20 files.
I used to think consistency meant being disciplined and remembering the right values. It does not. Consistency means you don't have to remember.
I kept the pages distinct where it matters, copy, structure, the specific content, but they all speak the same visual language now because they literally share the same two files.