Tailwind CSS 4 Design System: Building Consistent UI Across 6 Platforms
How Blossend uses Tailwind CSS 4 to maintain a consistent design system across OpenMyPro, Noizz.io, and four other platforms. @theme configuration, utility patterns, and mobile-first responsive design.
See this stack in production. 150K+ users. six-figure ARR.
Free forever. Upgrade only when you're ready.
150K+ users · Ex-Amazon Engineer · Healthcare Innovation
No card charged today · 150K+ users · $0 to start
Maintaining visual consistency across six platforms with one designer (me) required a design system that enforced rules without slowing development. Tailwind CSS 4 with the new @theme configuration is that system. Here is how we build and maintain UI across the entire Blossend ecosystem.
Why Tailwind CSS 4
Tailwind CSS 4 introduced three changes that transformed our workflow. First, the new @import "tailwindcss" directive replaced the old @tailwind directives, simplifying our CSS entry point. Second, the @theme block replaced tailwind.config.js for theme customization, keeping configuration in CSS where it belongs. Third, the new bg-linear-to-* syntax replaced the deprecated bg-gradient-to-* classes, which was a welcome modernization.
The utility-first approach eliminates context-switching between component files and stylesheets. Every visual property is expressed inline on the element it affects. When I need to adjust padding on a card component, I change a class on that element — not a CSS rule in a separate file that might affect other components.
The @theme Configuration
Our @theme block defines the design tokens that every platform shares. Brand colors, spacing scale, typography sizes, border radii, and shadow definitions live in a single CSS file imported by every application. When we update a color value, every platform picks it up on the next build.
We keep the theme minimal. The default Tailwind palette covers 95% of our color needs. We add only brand-specific tokens: our cyan-600 primary action color, the zinc scale for dark mode backgrounds, and healthcare-specific semantic colors for status indicators (confirmed, pending, cancelled). Fewer custom tokens means fewer decisions per component, which means faster development.
Mobile-First Responsive Patterns
Every component starts at mobile size and scales up using sm, md, lg, and xl breakpoints. This is not just a best practice — it is a business requirement. Over 60% of OpenMyPro's traffic comes from mobile devices. Patients search for healthcare providers from their phones while sitting in waiting rooms, commuting, or lying in bed after a rough day.
Our responsive patterns follow a consistent formula. Single-column stack on mobile, two-column grid on sm, three-column on lg. Text scales from text-base on mobile to text-lg on md. Padding grows from px-4 to px-6 to px-8. These patterns are so consistent that new pages practically design themselves.
Component Patterns
We use a small set of reusable visual patterns. Cards use rounded-xl border-2 border-zinc-400 bg-zinc-900/50 with hover:border-cyan-500 for interactive elements. Buttons follow a hierarchy: primary uses bg-cyan-600 text-white, secondary uses border-2 border-zinc-400 with explicit style={{ color: '#ffffff' }} for dark backgrounds, and ghost buttons use text-cyan-400 hover:text-cyan-300.
Dark mode is our default and only mode. Healthcare apps benefit from dark backgrounds that reduce eye strain during extended browsing. All text on dark backgrounds uses explicit style={{ color: '#ffffff' }} to guarantee contrast regardless of CSS specificity issues. The zinc palette provides the layering depth we need: zinc-950 for page backgrounds, zinc-900 for card backgrounds, zinc-800 for elevated surfaces.
Accessibility
WCAG compliance is built into our Tailwind patterns. Minimum border shade is 400 (never 300 or lower on dark backgrounds) for sufficient contrast. Interactive elements have visible focus rings using focus:ring-2 focus:ring-cyan-500. Text sizes never go below text-sm (14px). Color is never the only indicator of state — we always pair color with text labels or icons.
Performance Impact
Tailwind CSS 4's build produces remarkably small CSS files. Our production stylesheet for OpenMyPro is under 25KB gzipped, containing only the utility classes actually used in our components. Compare this to a traditional component library that might ship 200KB+ of CSS whether you use every component or not.
The elimination of runtime CSS-in-JS was a deliberate choice. Libraries like styled-components and Emotion add JavaScript overhead that slows page loads. Tailwind generates static CSS at build time, meaning zero runtime cost. For a healthcare platform where every 100ms of load time affects conversion rates, this matters.
Lessons From a Utility-First Design System
The biggest pushback against Tailwind is that class lists get long. They do. A complex card component might have 15-20 utility classes. But every one of those classes is explicit, readable, and local to the element. There is no mystery about where a style comes from. There is no cascade to debug. There is no !important war to fight. The tradeoff of longer class lists for complete style locality is overwhelmingly worth it at production scale.