{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreif3ltz7tphzrw4tfnhjy6x2gc5gpjheux6ldlfyibuuupfvwgqxqa",
    "uri": "at://did:plc:25rdn5elo5izoxrmtis34zuk/app.bsky.feed.post/3mon2epwc2zg2"
  },
  "coverImage": {
    "$type": "blob",
    "ref": {
      "$link": "bafkreiayiw3nn4oxvif2nmk3brx6mp76k4p2kg35xdyxgayapblkwiazz4"
    },
    "mimeType": "image/webp",
    "size": 83784
  },
  "path": "/cathylai/real-world-tailwind-css-the-gatekeeper-architecture-a-senior-developers-guide-part-12-m36",
  "publishedAt": "2026-06-19T09:25:12.000Z",
  "site": "https://dev.to",
  "tags": [
    "tailwindcss",
    "buildinpublic",
    "css",
    "frontend"
  ],
  "textContent": "So, armed with the knowledge of Tailwind and what it has to offer, how should we actually start our next large-scale project? To answer that question, it helps to look at how mature design-system teams structure frontend development in large organizations.\n\n##  The Blueprint: Component Authors vs. Feature Developers\n\nAfter a quick research, I've found that many successful design systems, including examples such as Shopify Polaris, are built around a simple idea: not everyone on the team is responsible for styling decisions.\n\nInstead, styling responsibilities are often separated into two distinct roles:\n\n  1. **The Component Authors (The Gatekeepers):** This core team builds foundational UI primitives. They write the Tailwind classes, manage accessibility, dark mode, component states, and design-token compliance.\n  2. **The Feature Developers (The Assemblers):** This team builds product features, workflows, and dashboards. Their primary focus is business logic and page composition rather than choosing colors, typography, or spacing scales.\n\n\n\nMany organizations reinforce this boundary through a combination of lint rules, code review standards, internal tooling, and shared team conventions.\n\n✔ Allowed: layout and composition utilities (`flex`, `grid`, `gap-4`)\n\n❌ Discouraged: introducing new visual styles such as `bg-indigo-600` or `text-lg` directly inside feature pages when an approved component already exists\n\n##  Code Example: The Standard Corporate Button\n\nTo see this boundary in practice, let's look at how a standard corporate button might be built and consumed.\n\n###  1. What the Component Author Builds\n\nThe Component Authors create a reusable primitive inside `@/components/ui/button.tsx`. The visual styling is centralized behind a clean TypeScript API:\n\n\n\n    // Managed by the Design System Team (@/components/ui/button.tsx)\n    import React from 'react';\n\n    interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n      variant?: 'primary' | 'secondary';\n      className?: string; // Intended for layout adjustments when needed\n    }\n\n    export function Button({\n      variant = 'primary',\n      className = '',\n      children,\n      ...props\n    }: ButtonProps) {\n      const baseStyles =\n        \"px-4 py-2 rounded-lg font-medium text-sm transition-all focus:outline-none focus:ring-2 focus:ring-offset-2\";\n\n      const variants = {\n        primary: \"bg-indigo-600 text-white hover:bg-indigo-700 focus:ring-indigo-500\",\n        secondary: \"bg-slate-100 text-slate-700 hover:bg-slate-200 focus:ring-slate-500\"\n      };\n\n      return (\n        <button className={`${baseStyles} ${variants[variant]} ${className}`} {...props}>\n          {children}\n        </button>\n      );\n    }\n\n\n###  2. How the Feature Developer Uses It\n\nWhen a Feature Developer builds a dashboard page, they primarily assemble existing building blocks and focus on feature logic:\n\n\n\n    // Inside @/app/dashboard/page.tsx\n    import { Button } from \"@/components/ui/button\";\n\n    export default function Dashboard() {\n      return (\n        <div>\n          ...\n\n          <Button variant=\"primary\" className=\"mt-4\">\n            Save Changes\n          </Button>\n        </div>\n      );\n    }\n\n\nThe visual design remains centralized in the component, while the page controls placement and composition.\n\n##  Scenarios\n\n###  Deleting a Button\n\nThe developer who originally created a page has moved on, and another developer needs to remove a button.\n\nBecause the visual styling is already encapsulated inside a shared component, there is no need to search through multiple CSS files looking for button-specific styles. The page simply stops using the component.\n\nThis reduces the risk of obsolete styling logic lingering in the codebase and makes long-term maintenance easier.\n\n###  Colour or Theme Change\n\nSuppose the company decides to move from Indigo to Violet as its primary brand color.\n\nIn many design-system architectures, the update happens in a single shared location (or design-token layer). The change then propagates consistently across the application without requiring developers to update individual pages.\n\n##  A Bigger Lesson\n\nThe important idea is not Tailwind itself. The key architectural concept is the boundary between **component authors** and **feature developers**. Tailwind is simply one effective tool for implementing that separation while keeping styles close to the components that own them.\n\n##  In the Next Article...\n\nThis approach covers most day-to-day product development. But what happens when the marketing team wants a one-off campaign page with a glowing, animated gradient button that doesn't fit the design system? Do we extend the component library? Create a special exception? Relax the rules?\n\nIn Part 2, we'll explore practical ways to handle architectural exceptions without turning the codebase into a free-for-all.",
  "title": "Real World Tailwind CSS: The \"Gatekeeper\" Architecture: A Senior Developer's Guide (Part 1/2)"
}