Xây dựng Design SystemBuilding a Design System
Thuộc bộ kiến thức Design System Roadmap.
Tổng quan
Xây dựng một design system thực chất là một bài toán quản lý thay đổi (change management) được ngụy trang dưới hình hài một bài toán thiết kế. Các thư viện Figma, token, và code component là phần đầu ra hữu hình, nhưng phần khó nhất — phần thực sự quyết định hệ thống có sống sót qua năm đầu tiên hay không — nằm ở khía cạnh tổ chức: làm sao để một nhóm designer và engineer vốn đã có thói quen làm việc, deadline, và quan điểm riêng của mình, đồng thuận trên một bộ building block chung, mà không phá vỡ những gì đang chạy trong sản xuất. Phần lớn tài liệu về design system bắt đầu từ token và component, như thể xây một hệ thống cũng giống xây một ngôi nhà — móng, rồi tường, rồi mái. Trên thực tế, quyết định thật sự đầu tiên xảy ra sớm hơn thế nhiều: hệ thống này bắt đầu từ đâu, và nó cần thuyết phục ai?
Có đúng hai điểm khởi đầu, và mỗi điểm đòi hỏi một chiến lược gần như trái ngược nhau. Xây greenfield nghĩa là bắt đầu từ một khung canvas trống — một sản phẩm hoàn toàn mới, hoặc một lần “reset” toàn công ty khi ban lãnh đạo quyết định xây lại ngôn ngữ thiết kế từ con số 0. Xây theo hướng retrofit (hay brownfield) nghĩa là bắt đầu từ một sản phẩm đang chạy thật, đã có sẵn button, form, và màu sắc trong production — chỉ là chúng không nhất quán. Trường hợp greenfield khá hiếm và, thẳng thắn mà nói, dễ viết bài về nó hơn nhiều, đó là lý do nó xuất hiện dày đặc trong các buổi conference talk và bài blog. Trường hợp retrofit mới là thứ hầu hết mọi người thực sự đối mặt: một sản phẩm đã phát triển qua nhiều năm, tích lũy technical debt lẫn design debt, và giờ cần được hệ thống hóa mà không cần viết lại từ đầu. Bài viết này tập trung vào quy trình thực tế cho cả hai hướng, nhưng nghiêng nhiều hơn về hướng retrofit vì đó là nơi phần lớn các nỗ lực design system thực sự ra đời.
Kiến thức nền tảng
Hai điểm khởi đầu: greenfield vs. retrofit
Điểm khởi đầu thay đổi gần như mọi quyết định tiếp theo — cần nghiên cứu bao nhiêu, bộ token đầu tiên có thể ra mắt nhanh đến đâu, và cần bao nhiêu “vốn chính trị” (political capital) trước khi component đầu tiên chạm tới production.
| Khía cạnh | Greenfield | Retrofit (sản phẩm đã tồn tại) |
|---|---|---|
| Nguyên liệu ban đầu | Chưa có gì được ship; một canvas trắng | Một sản phẩm đang chạy với component thật, sự không nhất quán thật, người dùng thật |
| Rủi ro lớn nhất | Thiết kế trong chân không, tách rời khỏi ràng buộc sử dụng thực tế | Thiết kế xoay quanh các quyết định cũ vốn chưa bao giờ được đưa ra một cách có chủ đích |
| Hoạt động đầu tiên | Xác định nguyên tắc và một bộ token nhỏ trước khi bất kỳ màn hình nào tồn tại | Kiểm toán (audit) những gì đang tồn tại trước khi định nghĩa bất cứ điều gì mới |
| Tốc độ “trông như xong” | Nhanh — không có gì để đối chiếu, không có CSS legacy xung đột với token mới | Chậm — mỗi token mới đều phải được đối chiếu với hàng chục giá trị cũ, chưa từng được tài liệu hóa |
| Độ khó về mặt chính trị | Thấp hơn — không ai có màn hình cũ cần bảo vệ | Cao hơn — mỗi điểm không nhất quán được phát hiện đều có một chủ nhân đã xây nó với thiện chí |
| Nguyên nhân kích hoạt điển hình | Một dòng sản phẩm mới, lần đầu công ty startup tuyển design lead, hoặc một đợt rebrand toàn công ty | Sản phẩm đã phát triển vượt quá điểm mà sự nhất quán không chính thức (“cứ copy màn hình trước”) còn hiệu quả |
Xây greenfield hiếm gặp trên thực tế vì nó đòi hỏi một sản phẩm thực sự mới hoặc một lần reset do lãnh đạo chỉ đạo — những tình huống mà hầu hết designer chỉ gặp một hoặc hai lần trong cả sự nghiệp, nếu có. Trường hợp retrofit mới là mặc định, và về bản chất đây là một bài toán đối chiếu (reconciliation): hệ thống phải mô tả một trạng thái đích mạch lạc, đồng thời thừa nhận rằng trạng thái hiện tại là một mớ hỗn độn của những quyết định hợp lý một cách độc lập, được đưa ra dưới áp lực deadline bởi những người chưa bao giờ sai khi đưa ra quyết định đó vào thời điểm ấy.
Xác định quy trình thiết kế hiện có
Trước khi đề xuất bất kỳ token nào, hãy dành thời gian tìm hiểu cách designer và engineer hiện đang làm việc — không phải cách một bài blog về design system nói rằng họ nên làm việc. Điều này nghĩa là ngồi dự các buổi design review, đọc code component hiện có, hỏi engineer xem họ copy-paste UI từ đâu, và hỏi designer xem họ duplicate file Figma nào khi bắt đầu một màn hình mới. Mục tiêu là tìm ra hệ thống không chính thức vốn đã tồn tại, bởi vì bất kỳ sản phẩm nào đã ship nhiều hơn một vài màn hình đều có một hệ thống nào đó, dù nó chưa được tài liệu hóa và không nhất quán — một file Figma chung mà mọi người copy từ đó, một thư mục components/ mà mọi người import từ đó, kiến thức truyền miệng (tribal knowledge) về “chúng ta làm modal như thế nào ở đây.”
Bước này rất dễ bị bỏ qua vì nó không tạo ra đầu ra hữu hình nào — không có token, không có component, không có screenshot để show trong buổi status update. Nhưng bỏ qua nó lại là lý do phổ biến nhất khiến design system bị âm thầm phớt lờ: một hệ thống áp đặt lên trên một quy trình làm việc chưa được tìm hiểu, đối với những người phải dùng nó hàng ngày, trông giống như thêm một lớp process chồng lên process hiện có của họ, thay vì thay thế nó. Nếu engineer hiện đang import UI từ một thư mục ui/ dùng chung trong repository chính, việc bắt họ di chuyển sang một package hoàn toàn tách biệt với build pipeline và cơ chế versioning khác là một yêu cầu lớn hơn nhiều so với việc tiến hóa thư mục đó ngay tại chỗ. Hiểu quy trình hiện có trước tiên nghĩa là hệ thống mới có thể được giới thiệu như một sự tiến hóa tự nhiên của những gì mọi người đã làm, thay vì một cấu trúc song song mà họ bị yêu cầu áp dụng thêm lên trên quy trình thật của mình.
Khái niệm chính
Phân tích thiết kế hiện có và visual audit
Sau khi hiểu quy trình không chính thức, bước tiếp theo là đo lường quy mô thực sự của sự không nhất quán, và công cụ tiêu chuẩn cho việc này là visual audit: chụp màn hình, phân loại, và so sánh một cách có hệ thống mọi thực thể của một loại UI element nhất định — mỗi button, mỗi giá trị màu, mỗi khoảng cách (spacing) — đang thực sự tồn tại trong production. Đây là công việc tẻ nhạt, không hào nhoáng, và chính vì thế nó lại thuyết phục đến vậy: nó thay thế một tuyên bố mơ hồ, dễ tranh cãi (“UI của chúng ta cảm giác không nhất quán”) bằng một sự thật cụ thể, đếm được.
Một visual audit thực tế sẽ đi qua từng màn hình của sản phẩm (hoặc một mẫu đại diện, với các sản phẩm rất lớn) và ghi lại, cho từng danh mục UI lặp lại:
| Đối tượng audit | Ghi lại điều gì | Thường phát hiện ra điều gì |
|---|---|---|
| Màu sắc | Mọi giá trị hex/RGB riêng biệt đang được dùng, nhóm theo mục đích rõ ràng (hành động chính, lỗi, trạng thái disabled) | Hàng chục giá trị gần giống nhau vốn được dự định là “cùng một màu xanh” nhưng lệch dần qua copy-paste và nhập hex thủ công |
| Typography | Mọi kích thước font, độ đậm (weight), và line-height đang dùng | Một vài text style dự định ban đầu đã âm thầm nhân lên thành mười lăm, hai mươi tổ hợp gần giống nhau |
| Spacing | Mọi giá trị margin/padding dùng giữa và bên trong component | Các giá trị spacing không theo một thang đo (scale) rõ ràng nào — 6px, 9px, 13px, 14px, 16px được dùng lẫn lộn ở nơi mà một thang đo dựa trên 8px là đủ |
| Button | Mọi biến thể hình ảnh của button (hình dạng, chiều cao, border radius, trạng thái hover) | Nhiều cách hiện thực “primary button” khác nhau, mỗi cái do một team khác nhau xây, không ai biết về nhau |
| Form input | Mọi input, label, và cách xử lý trạng thái lỗi | Trạng thái focus và cách hiển thị lỗi không nhất quán giữa các form, thường là một vấn đề accessibility thực sự, không chỉ là thẩm mỹ |
Kết quả nổi tiếng của việc thực hiện bài tập này một cách trung thực là phát hiện ra kiểu như “47 sắc thái xanh dương” (47 shades of blue) trong production — một hiện tượng có thật, thường được trích dẫn, khi một sản phẩm dự định chỉ dùng một hoặc hai màu xanh thương hiệu, nhưng qua nhiều năm hiện thực độc lập, cuối cùng lại có hàng chục giá trị gần trùng nhau mà không ai từng chủ đích chọn ra. Loại phát hiện này không chỉ là một chi tiết thú vị của bài audit; nó là lập luận mạnh nhất cho việc tại sao hệ thống cần tồn tại. Những stakeholder hoài nghi rằng “lại thêm một sáng kiến nữa” có đáng đầu tư hay không thường trở nên bớt hoài nghi đi rất nhiều khi được cho xem một slide với 47 mẫu màu xanh gần như giống hệt nhau đặt cạnh nhau, mỗi mẫu đều đang thực sự chạy trong sản phẩm họ ship. Bài audit biến một lời phàn nàn về thẩm mỹ thành một business case có con số đi kèm.
Các stakeholder tham gia xây dựng design system
Design system về bản chất là liên phòng ban (cross-functional), và xây dựng nó một cách cô lập — kể cả một hệ thống xuất sắc về mặt kỹ thuật — là một trong những cách phổ biến nhất khiến nỗ lực này thất bại. Những người cần được tham gia, và lý do tại sao, vượt xa team design vốn thường là bên khởi xướng nỗ lực này.
| Stakeholder | Tại sao họ quan trọng |
|---|---|
| Design | Sở hữu ngôn ngữ thị giác, quyết định về token, và thiết kế component; thường là bên khởi xướng, nhưng không nên là tiếng nói duy nhất |
| Engineering | Xây dựng và duy trì thư viện component ở dạng code; nếu không tham gia sớm, designer sẽ đặc tả những thứ tốn kém hoặc bất khả thi để hiện thực một cách nhất quán trên tech stack thực tế |
| Product management | Quyết định điều gì được ưu tiên và cấp nhân lực; một hệ thống cạnh tranh cùng sprint capacity với công việc feature cần một đồng minh PM hiểu được lợi ích dài hạn của nó |
| Content / UX writing | Định nghĩa voice, tone, và các mẫu microcopy gắn với component (thông báo lỗi, empty state, nhãn button); nếu thiếu điều này, hệ thống chuẩn hóa được phần thị giác nhưng để lại phần chữ vẫn không nhất quán như trước |
| Chuyên gia accessibility | Đảm bảo component đúng chuẩn ngay từ đầu (quản lý focus, ngữ nghĩa ARIA, độ tương phản màu sắc) thay vì bắt mỗi team tiêu dùng phải tự giải quyết accessibility riêng cho từng màn hình |
| Leadership / executive sponsorship | Cung cấp nguồn lực và ủy quyền tổ chức giúp hệ thống sống sót qua vài tháng đầu tiên |
Trong số này, executive sponsorship xứng đáng được nhấn mạnh đặc biệt vì sự vắng mặt của nó là một kẻ giết chóc chậm rãi, âm thầm chứ không kịch tính. Một design system thường ra mắt với sự hào hứng thật sự — một buổi kickoff meeting, một kênh Slack, một vài early adopter phấn khích vì không phải xây lại một cái button từ đầu. Sự hào hứng đó không tự duy trì được. Sáu tháng sau, khi hệ thống cần thời gian của một engineer chuyên trách để sửa một breaking change, hoặc cần một product team hoãn một feature đi một sprint để áp dụng component Input mới thay vì ship một cái tự chế riêng, ai đó có thẩm quyền tổ chức phải quyết định rằng công việc này đủ quan trọng để bảo vệ. Nếu không có một người lãnh đạo đã nói rõ ràng “đây là ưu tiên” và hậu thuẫn bằng headcount hoặc thời gian được bảo vệ, design system sẽ âm thầm thua trong mọi cuộc tranh giành nguồn lực với công việc feature có deadline rõ ràng, và nó cạn kiệt dần — không phải qua một quyết định duy nhất để khai tử nó, mà qua hàng trăm quyết định nhỏ hạ thấp mức ưu tiên của nó.
Bắt đầu với một pilot
Ngay cả khi đã có đúng các stakeholder đồng thuận, việc triển khai một hệ thống mới cho toàn bộ các team cùng lúc là một sai lầm phổ biến và có thể tránh được. Cách tiếp cận tốt hơn là chọn một pilot: một team, một khu vực sản phẩm, hoặc một luồng (flow), áp dụng hệ thống trước tiên, từ đầu đến cuối, trước khi bất kỳ ai nói về việc triển khai toàn công ty.
Lý do gần như hoàn toàn liên quan đến momentum. Một hệ thống được giới thiệu ở mọi nơi cùng lúc thường không được áp dụng đầy đủ ở bất kỳ đâu: mỗi team có ưu tiên và deadline hơi khác nhau, nên mỗi team chỉ tích hợp token và component mới một phần, ở rìa của những gì họ đang làm, và không team nào thực sự hoàn thành việc di chuyển. Sáu tháng sau, hệ thống tồn tại trên danh nghĩa — một thư viện Figma, một component package trên registry nội bộ — nhưng không có màn hình thật nào trong production được xây hoàn toàn từ nó, và tổ chức kết luận, không hẳn là vô lý, rằng “dự án design system chẳng đi tới đâu cả.”
Một pilot tránh được điều này bằng cách tập trung nỗ lực. Một team, lý tưởng là một team cởi mở, có nhu cầu thật trong ngắn hạn mà hệ thống có thể giải quyết, và không nằm trên đường găng (critical path) của lần ra mắt quan trọng nhất công ty, sẽ áp dụng đầy đủ bộ token và bộ component nhỏ đầu tiên. Điều này tạo ra một thứ mà một đợt rollout diện rộng thường không thể: một ví dụ thật, đã được ship, mà một stakeholder hoài nghi có thể click qua và nói “đây chính là việc áp dụng hệ thống trông như thế nào, và đây là team đã làm điều đó.” Bằng chứng cụ thể đó thuyết phục hơn nhiều — và cũng hữu ích hơn nhiều trong việc tìm ra những góc cạnh thô ráp của chính hệ thống — so với một thư viện trừu tượng mà chưa màn hình production nào thực sự dùng tới.
Trình tự xây dựng: token trước, rồi core component, rồi mở rộng độ phủ
Sau khi chọn được pilot, quá trình xây dựng thực tế theo một trình tự khá nhất quán qua các hệ thống thành công, bởi vì mỗi giai đoạn phụ thuộc vào giai đoạn trước đó đã tương đối ổn định.
- Design token trước tiên. Token (màu sắc, spacing, typography, radius, elevation — được trình bày chi tiết trong
./03-design-tokens-and-visual-foundations.md) là nền móng vì mọi component xây sau đó đều tham chiếu tới chúng. Xây component trước token nghĩa là sau này phải xây lại phần bên trong của các component đó, khi lớp token cuối cùng cũng xuất hiện — quyết định về token rẻ để thay đổi trước khi có gì tiêu thụ nó, và đắt để thay đổi sau khi hàng chục component đã hard-code các giá trị mà token đáng lẽ phải thay thế. - Một bộ nhỏ các component được dùng nhiều nhất. Trong hầu hết mọi sản phẩm được audit, một vài component — thường là Button, Input, và Card — chiếm một tỷ lệ không cân xứng trong tổng số thực thể UI. Xây những component này trước, và xây cho tốt (đầy đủ mọi trạng thái: mặc định, hover, focus, disabled, lỗi, loading), mang lại tỷ suất lợi nhuận trên công sức cao nhất trong toàn bộ hệ thống, vì chúng là thứ mà phần lớn màn hình thực sự được tạo nên từ đó.
- Mở rộng dựa trên yêu cầu thật, không dựa trên phỏng đoán. Sau khi bộ core được ship và team pilot đang sử dụng nó, những component tiếp theo cần xây nên đến từ nhu cầu thật, được quan sát, từ các team tiêu dùng — không phải từ một roadmap ai đó viết ra một cách cô lập, tưởng tượng “một design system hoàn chỉnh” nên chứa những gì. Một nhật ký yêu cầu (request log) hoặc quy trình tiếp nhận (intake process) — một form, một kênh Slack, một backlog — ghi lại “team X cần một component Y cho feature Z” là một tín hiệu ưu tiên đáng tin cậy hơn nhiều so với trực giác.
”Quy tắc số ba” (rule of three)
Một heuristic hữu ích, cụ thể cho bước 3 ở trên là quy tắc số ba: một component không được đưa vào hệ thống dùng chung cho đến khi có nhu cầu thật, được chứng minh, ở ít nhất ba nơi riêng biệt. Nếu chỉ một team cần một pattern cụ thể nào đó, gần như chắc chắn nó thuộc về codebase riêng của team đó, không phải thư viện dùng chung — xây nó ở trung tâm sẽ tạo thêm bề mặt bảo trì, gánh nặng tài liệu hóa, và chi phí versioning cho một thứ có thể chẳng bao giờ được tái sử dụng. Khi một team thứ hai độc lập yêu cầu cùng một thứ, đó là một tín hiệu hữu ích nhưng vẫn còn yếu — có thể là trùng hợp, hoặc hai team đang giải quyết các vấn đề lân cận nhưng khác nhau lại trông giống nhau trên bề mặt. Một yêu cầu độc lập thứ ba mới là điểm mà mô hình về nhu cầu thật, lặp lại trở nên khó bác bỏ, và đó là lúc khoản đầu tư thiết kế, xây dựng, tài liệu hóa, và cam kết duy trì một component dùng chung thực sự đáng giá.
Quy tắc số ba cũng là một kỷ luật để nói “chưa phải lúc” nhiều như để nói “được.” Nó trực tiếp ngăn chặn một trong những kiểu thất bại phổ biến nhất của design system: xây các component mang tính suy đoán mà không ai yêu cầu, dựa trên những gì người duy trì hệ thống cho rằng một thư viện “hoàn chỉnh” nên có. Mỗi component trong một hệ thống dùng chung mang theo chi phí bảo trì liên tục — nó cần được đồng bộ với hệ thống token, được kiểm thử về accessibility, được tài liệu hóa, và được versioning — và một hệ thống chất đầy các component ít được dùng sẽ khó điều hướng hơn và tiến hóa chậm hơn so với một hệ thống nhỏ gọn, được chọn lọc kỹ càng, ánh xạ trực tiếp vào nhu cầu sản phẩm thật, lặp lại.
Các kiểu thất bại thường gặp
Một số mô hình thất bại lặp lại đủ thường xuyên qua nhiều tổ chức đến mức đáng để nêu tên rõ ràng, chính xác vì mỗi kiểu đều có thể tránh được nhờ những thực hành ở trên.
| Kiểu thất bại | Trông như thế nào | Tại sao nó xảy ra |
|---|---|---|
| Xây dựng cô lập | Một team trung tâm nhỏ thiết kế và ship component mà không có sự tham gia thường xuyên từ các product team đáng lẽ sẽ dùng chúng | Bỏ qua bước “xác định quy trình hiện có” và bước pilot; hệ thống được thiết kế cho một người tiêu dùng lý tưởng hóa thay vì người dùng thật |
| Over-engineering token trước khi ship bất cứ thứ gì | Nhiều tuần hoặc nhiều tháng tranh luận về cách đặt tên token, cấu trúc alias nhiều tầng, hoặc kiến trúc theming trước khi có một component nào tồn tại | Xem lớp token là phần thú vị, ít rủi ro của công việc, trong khi phần khó hơn, dễ bị soi hơn — component thật, sự áp dụng thật — bị trì hoãn |
| Xem v1 là “xong” | Hệ thống ship một bộ component ban đầu, momentum dừng lại, và không có kế hoạch đầu tư thêm | Cấp vốn và nhân lực cho hệ thống như một hạng mục dự án một lần, thay vì như một sản phẩm đang tiếp diễn với roadmap, backlog, và chỉ số adoption riêng (xem ./13-adoption-community-and-support.md) |
| Bỏ qua audit | Token và component mới được định nghĩa dựa trên nguyên tắc hoặc gu thẩm mỹ, không tham chiếu tới những gì thực sự đang chạy trong production | Cảm giác nhanh hơn trong ngắn hạn, nhưng tạo ra một hệ thống không ánh xạ vào màn hình thật, khiến công sức di chuyển sau này phình to |
| Không có executive sponsor | Hệ thống thua trong mọi xung đột ưu tiên với công việc feature sau vài tháng đầu | Sự hào hứng từ team sáng lập bị nhầm lẫn với cam kết của tổ chức |
Tổng quan cách tiếp cận xây dựng
| Cách tiếp cận | Bước đầu tiên điển hình | Rủi ro điển hình |
|---|---|---|
| Greenfield (sản phẩm mới hoặc reset toàn công ty) | Xác định nguyên tắc thiết kế → thiết lập một bộ token nhỏ → thiết kế và xây core component song song với những màn hình thật đầu tiên | Thiết kế trong chân không, tách rời khỏi nội dung thật, dữ liệu thật, và ràng buộc engineering thật, vì không có sản phẩm hiện có nào để đối chiếu |
| Retrofit (sản phẩm đang chạy) | Xác định quy trình không chính thức hiện có → chạy visual audit → đối chiếu phát hiện thành một bộ token → pilot với một team → mở rộng theo yêu cầu | Đầu tư chưa đủ vào audit và sự đồng thuận stakeholder, sau đó áp đặt một hệ thống phớt lờ cách tổ chức đã vận hành, dẫn tới sự phớt lờ âm thầm |
Best Practices
- Audit trước khi thiết kế bất cứ thứ gì mới. Một visual audit về màu sắc, typography, spacing, và component trong production biến “UI của chúng ta không nhất quán” từ một ý kiến thành một sự thật đo lường được, và cho phiên bản đầu tiên của hệ thống một thứ cụ thể để đối chiếu thay vì một giả định.
- Đảm bảo executive sponsorship trước buổi kickoff meeting, không phải sau khi sự hào hứng đã tan. Có được cam kết rõ ràng về headcount hoặc thời gian được bảo vệ từ ai đó có thẩm quyền tổ chức; nếu không, hệ thống sẽ cạn kiệt nguồn lực ngay khi cạnh tranh với một deadline feature.
- Pilot với một team trước khi triển khai diện rộng. Một hệ thống được áp dụng đầy đủ ở một khu vực sản phẩm là một bằng chứng mạnh hơn — và một nguồn feedback thật tốt hơn — so với một hệ thống được áp dụng một phần ở khắp mọi nơi.
- Sắp xếp trình tự token, rồi core component, rồi độ phủ — theo đúng thứ tự đó. Đừng xây component trước khi nền tảng token tương đối ổn định, và đừng mở rộng độ phủ component nhanh hơn tốc độ các team thật đang yêu cầu.
- Áp dụng quy tắc số ba trước khi đưa bất cứ thứ gì vào hệ thống dùng chung. Một component chỉ cần ở một hoặc hai nơi thuộc về codebase riêng của team đó, không phải một thư viện mà ai cũng phải bảo trì.
- Xem hệ thống là một sản phẩm đang tiếp diễn, không phải một hạng mục v1. Cấp cho nó một backlog, một quy trình tiếp nhận yêu cầu, và một chỉ số adoption, giống như bất kỳ sản phẩm nội bộ nào khác có người dùng thật.
- Đưa engineering, content, và accessibility vào ngay từ đầu, không phải tới lúc review. Retrofit accessibility hoặc content guideline lên một component đã ship rồi tốn kém hơn nhiều so với thiết kế chúng vào ngay từ phiên bản đầu tiên.
- Đưa các product team thật vào làm đối tác thiết kế, không chỉ là người tiêu dùng. Một hệ thống xây hoàn toàn bởi một team trung tâm, tách rời khỏi các team đáng lẽ sẽ áp dụng nó, có xu hướng giải quyết những vấn đề mà các team đó không thực sự gặp phải.
Tài liệu tham khảo
- roadmap.sh/design-system
- Design Systems Handbook — InVision/DesignBetter
- Building and Scaling a Design System — Nathan Curtis
- Design Systems Repo — danh sách tuyển chọn design system và tài nguyên
- Atlassian: How we structure our design system team
- Audit UI Inconsistencies — Smashing Magazine on design system foundations
./01-introduction-to-design-systems.md./03-design-tokens-and-visual-foundations.md./13-adoption-community-and-support.md
Part of the Design System Roadmap knowledge base.
Overview
Building a design system is a change-management problem disguised as a design problem. The Figma libraries, tokens, and component code are the visible output, but the hard part — the part that actually determines whether the system survives its first year — is organizational: getting a group of designers and engineers who already have working habits, deadlines, and opinions to converge on a shared set of building blocks, without breaking what currently ships. Most write-ups of design systems start from the tokens and components, as if a system is built the way a house is built — foundation, then walls, then roof. In practice, the first real decision happens earlier than any of that: where is this system coming from, and who does it have to win over?
There are exactly two starting points, and they call for almost opposite strategies. A greenfield build starts from an empty canvas — a brand-new product, or a company-wide reset where leadership has decided to rebuild the design language from zero. A retrofit (or brownfield) build starts from a live product that already has buttons, forms, and colors in production — just inconsistent ones. The greenfield case is rare and, frankly, the easier of the two to write about, which is why it dominates conference talks and blog posts. The retrofit case is what almost everyone actually faces: a product that has grown for years, accumulated technical and design debt, and now needs to be systematized without a rewrite. This note focuses on the practical process for both, with more weight on the retrofit path because that is where most design system efforts are actually born.
Fundamentals
Two starting points: greenfield vs. retrofit
The starting point changes almost every subsequent decision — how much research is needed, how fast a first token set can ship, and how much political capital is required before the first component reaches production.
| Dimension | Greenfield | Retrofit (existing product) |
|---|---|---|
| Starting material | Nothing shipped yet; a blank canvas | A live product with real components, real inconsistencies, real users |
| Biggest risk | Designing in a vacuum, disconnected from real usage constraints | Designing around legacy decisions that were never intentional in the first place |
| First activity | Define principles and a small token set before any screen exists | Audit what already exists before defining anything new |
| Speed to “looks done” | Fast — nothing to reconcile, no legacy CSS fighting the new tokens | Slow — every new token has to be reconciled against dozens of existing, undocumented values |
| Political difficulty | Lower — no one has an existing screen to defend | Higher — every inconsistency found has an owner who built it in good faith |
| Typical trigger | A new product line, a startup’s first hire of a design lead, or a company-wide rebrand | A product has grown past the point where informal consistency (“just copy the last screen”) still works |
Greenfield builds are rare in practice because they require a genuinely new product or a leadership-mandated reset — situations most designers encounter once or twice in a career, if that. The retrofit case is the default, and it is fundamentally a reconciliation exercise: the system has to describe a coherent target state while acknowledging that the current state is a mess of independently reasonable decisions made under deadline pressure by people who were never wrong to make them at the time.
Identifying the existing design process
Before proposing a single token, spend time understanding how designers and engineers currently work — not how a design-systems blog says they should work. This means sitting in on design reviews, reading existing component code, asking engineers where they copy-paste UI from, and asking designers which Figma file they duplicate when starting a new screen. The goal is to find the informal system that already exists, because every product that has shipped more than a handful of screens has some system, even if it’s undocumented and inconsistent — a shared Figma file everyone copies from, a components/ folder everyone imports from, tribal knowledge about “how we do modals here.”
This step is easy to skip because it produces no visible deliverable — no token, no component, no screenshot to show in a status update. But skipping it is the single most common reason design systems get quietly ignored: a system imposed on top of an unexamined workflow looks, to the people who have to use it daily, like extra process bolted onto their existing process, rather than a replacement for it. If engineers currently import UI from a shared ui/ folder in the main app repository, migrating them to an entirely separate package with a different build pipeline and versioning scheme is a much bigger ask than evolving that existing folder in place. Understanding the existing process first means the system can be introduced as a natural evolution of what people already do, rather than a parallel structure they are asked to adopt on top of their real workflow.
Key Concepts
Existing design analysis and the visual audit
Once the informal process is understood, the next step is to measure the actual scope of inconsistency, and the standard tool for this is the visual audit: systematically screenshotting, cataloguing, and comparing every instance of a given UI element — every button, every color value, every spacing measurement — currently live in production. This is tedious, unglamorous work, and that is precisely why it is so persuasive: it replaces a vague, arguable claim (“our UI feels inconsistent”) with a concrete, countable fact.
A practical visual audit walks every screen of the product (or a representative sample, for very large products) and records, for each recurring UI category:
| Audit target | What to capture | What it typically reveals |
|---|---|---|
| Colors | Every distinct hex/RGB value in use, grouped by apparent intent (primary action, error, disabled state) | Dozens of near-identical values that were meant to be “the same blue” but drifted through copy-paste and manual hex entry |
| Typography | Every font size, weight, and line-height combination in use | A handful of intended text styles that has silently multiplied into fifteen or twenty slightly different combinations |
| Spacing | Every margin/padding value used between and within components | Spacing values with no discernible scale — 6px, 9px, 13px, 14px, 16px used interchangeably where a single 8px-based scale would suffice |
| Buttons | Every visual variant of button (shape, height, border radius, hover state) | Multiple “primary button” implementations, each built by a different team, none aware of the others |
| Form inputs | Every input, label, and error-state treatment | Inconsistent focus states and error messaging patterns across forms, often a genuine accessibility problem, not just a cosmetic one |
The now-famous result of doing this exercise honestly is discovering something like “47 shades of blue” in production — a real, oft-cited pattern where a product intended to use one or two brand blues and, through years of independent implementation, ended up with dozens of near-duplicate values that no single person chose deliberately. This kind of finding is not just an interesting artifact of the audit; it is the single strongest argument for why the system needs to exist at all. Stakeholders who are skeptical that “yet another initiative” is worth funding tend to become considerably less skeptical when shown a slide with 47 nearly identical blue swatches side by side, each one currently live in the product they ship. The audit converts an aesthetic complaint into an business case with a number attached to it.
Stakeholders involved in building a design system
A design system is cross-functional by nature, and building one in isolation — even a technically excellent one — is one of the most common ways these efforts fail. The people who need to be involved, and why, extend beyond the design team that typically initiates the effort.
| Stakeholder | Why they matter |
|---|---|
| Design | Owns the visual language, token decisions, and component design; usually the initiator, but should not be the only voice |
| Engineering | Builds and maintains the coded component library; without early involvement, designers will specify things that are expensive or impossible to implement consistently across the actual tech stack |
| Product management | Decides what gets prioritized and staffed; a system that competes for the same sprint capacity as feature work needs a PM ally who understands its long-term payoff |
| Content / UX writing | Defines voice, tone, and microcopy patterns tied to components (error messages, empty states, button labels); without this, a system standardizes visuals but leaves text as inconsistent as before |
| Accessibility specialists | Ensure components are correct by default (focus management, ARIA semantics, color contrast) rather than requiring every consuming team to re-solve accessibility per screen |
| Leadership / executive sponsorship | Provides the resourcing and organizational mandate that lets the system survive past its first few months |
Of these, executive sponsorship deserves special emphasis because its absence is a slow, quiet killer rather than a dramatic one. A design system usually launches with real enthusiasm — a kickoff meeting, a Slack channel, a handful of early adopters excited about not having to build another button from scratch. That enthusiasm is not self-sustaining. Six months in, when the system needs a dedicated engineer’s time to fix a breaking change, or needs a product team to delay a feature by a sprint to adopt the new Input component instead of shipping a one-off, someone with organizational authority has to decide that this work matters enough to protect. Without a leader who has explicitly said “this is a priority” and backed it with headcount or protected time, the design system quietly loses every resourcing fight against feature work with a visible deadline, and it starves — not through any single decision to kill it, but through a hundred small decisions to deprioritize it.
Starting with a pilot
Even with the right stakeholders aligned, rolling a new system out to every team simultaneously is a common and avoidable mistake. The better approach is choosing a pilot: one team, one product area, or one flow, that adopts the system first, end to end, before anyone talks about a company-wide rollout.
The reasoning is almost entirely about momentum. A system introduced everywhere at once tends to be adopted nowhere fully: every team has slightly different priorities and deadlines, so each one integrates the new tokens and components partially, around the edges of whatever they were already doing, and none of them actually finishes migrating. Six months later, the system exists in name — a Figma library, a component package on the internal registry — but no real screen in production is built entirely from it, and the org concludes, not unreasonably, that “the design system project didn’t really go anywhere.”
A pilot avoids this by concentrating effort. One team, ideally one that is receptive, has a real near-term need the system can address, and is not on the critical path for the company’s highest-stakes launch, adopts the token set and the first small component set completely. This produces something a broad rollout usually cannot: a real, shipped example that a skeptical stakeholder can click through and say “this is what adopting the system actually looks like, and here is the team that did it.” That concrete proof is far more persuasive — and far more useful for finding the rough edges in the system itself — than an abstract library that no production screen actually uses yet.
Sequencing the build: tokens, then core components, then coverage
Once a pilot is chosen, the build itself follows a fairly consistent sequence across successful systems, because each stage depends on the one before it being reasonably stable.
- Design tokens first. Tokens (color, spacing, typography, radius, elevation — covered in depth in
./03-design-tokens-and-visual-foundations.md) are the foundation because every component that gets built afterward references them. Building components before tokens means rebuilding those components’ internals later, once the token layer finally arrives — token decisions are cheap to change before anything consumes them, and expensive to change after dozens of components hard-code values the tokens were meant to replace. - A small set of the highest-usage components. In almost every audited product, a small handful of components — typically Button, Input, and Card — account for a disproportionate share of all UI instances. Building these first, and building them well (all states: default, hover, focus, disabled, error, loading), delivers the highest return on effort of anything in the system, because they are what most screens are actually made of.
- Expand based on real requests, not guesses. After the core set ships and the pilot team is using it, the next components to build should come from actual, observed demand from consuming teams — not from a roadmap someone wrote in isolation, imagining what “a complete design system” ought to contain. A request log or intake process (a form, a Slack channel, a backlog) that captures “team X needs a Y component for feature Z” is a far more reliable prioritization signal than intuition.
The “rule of three”
A useful, concrete heuristic for step 3 above is the rule of three: a component does not get promoted into the shared system until there is a real, demonstrated need for it in at least three separate places. If only one team needs a particular pattern, it almost certainly belongs in that team’s own codebase, not in the shared library — building it centrally adds maintenance surface, documentation burden, and versioning overhead for something that may never be reused. Once a second team independently asks for the same thing, that is a useful signal but still weak evidence — it could be coincidence, or two teams solving adjacent-but-different problems that happen to look similar on the surface. A third independent request is where the pattern of genuine, recurring need becomes hard to dismiss, and that is the point at which the investment of designing, building, documenting, and committing to maintain a shared component actually pays off.
The rule of three is as much a discipline for saying “not yet” as it is for saying “yes.” It directly prevents one of the most common design-system failure modes: building speculative components that nobody asked for, based on what the system’s maintainers assume a “complete” library should contain. Every component in a shared system carries an ongoing maintenance cost — it needs to be kept in sync with the token system, tested for accessibility, documented, and versioned — and a system cluttered with rarely used components is harder to navigate and slower to evolve than a smaller, tightly curated one that maps directly onto real, recurring product needs.
Common failure modes
Several failure patterns recur often enough across organizations that they are worth naming explicitly, precisely because each one is avoidable with the practices above.
| Failure mode | What it looks like | Why it happens |
|---|---|---|
| Building in isolation | A small central team designs and ships components without regular involvement from the product teams meant to use them | Skipping the “identify the existing process” step and the pilot; the system is designed for an idealized consumer instead of a real one |
| Over-engineering tokens before shipping anything | Weeks or months spent debating a token naming taxonomy, multi-tier alias structures, or theming architecture before a single component exists | Treating the token layer as the interesting, low-risk part of the work, while the harder, more exposed work — real components, real adoption — gets deferred |
| Treating v1 as “done” | The system ships an initial component set, momentum stops, and no further investment is planned | Funding and staffing the system as a one-time project deliverable rather than as an ongoing product with its own roadmap, backlog, and adoption metrics (see ./13-adoption-community-and-support.md) |
| Skipping the audit | New tokens and components are defined from principle or taste, without reference to what is actually live in production | Feels faster in the short term, but produces a system that doesn’t map onto real screens, so migration effort balloons later |
| No executive sponsor | The system loses every prioritization conflict with feature work after the first few months | Enthusiasm from the founding team is mistaken for organizational commitment |
Build approach at a glance
| Build approach | Typical first steps | Typical risk |
|---|---|---|
| Greenfield (new product or company-wide reset) | Define design principles → establish a small token set → design and build core components alongside the first real screens | Designing in a vacuum, disconnected from real content, real data, and real engineering constraints, because there is no existing product to validate against |
| Retrofit (existing, live product) | Identify the existing informal process → run a visual audit → reconcile findings into a token set → pilot with one team → expand by request | Under-investing in the audit and stakeholder alignment, then imposing a system that ignores how the org actually already works, leading to quiet rejection |
Best Practices
- Audit before you design anything new. A visual audit of colors, type, spacing, and components in production turns “our UI is inconsistent” from an opinion into a measurable fact, and gives the system’s first version something concrete to reconcile against instead of an assumption.
- Secure executive sponsorship before the kickoff meeting, not after the enthusiasm fades. Get an explicit commitment of headcount or protected time from someone with organizational authority; without it, the system starves for resourcing the moment it competes with a feature deadline.
- Pilot with one team before rolling out broadly. A fully adopted system in one product area is a stronger proof point — and a better source of real feedback — than a partially adopted system everywhere.
- Sequence tokens, then core components, then coverage — in that order. Don’t build components before the token foundation is reasonably stable, and don’t expand component coverage faster than real teams are asking for it.
- Apply the rule of three before promoting anything to the shared system. A component needed in only one or two places belongs in that team’s own codebase, not in a library everyone has to maintain.
- Treat the system as an ongoing product, not a v1 deliverable. Staff it with a backlog, a request intake process, and an adoption metric, the same way you would any other internal product with real users.
- Bring engineering, content, and accessibility in from the start, not at review time. Retrofitting accessibility or content guidelines onto an already-shipped component is far more expensive than designing them in from the first version.
- Involve real product teams as design partners, not just as consumers. A system built entirely by a central team, disconnected from the teams meant to adopt it, tends to solve problems those teams don’t actually have.
References
- roadmap.sh/design-system
- Design Systems Handbook — InVision/DesignBetter
- Building and Scaling a Design System — Nathan Curtis
- Design Systems Repo — a curated list of design systems and resources
- Atlassian: How we structure our design system team
- Audit UI Inconsistencies — Smashing Magazine on design system foundations
./01-introduction-to-design-systems.md./03-design-tokens-and-visual-foundations.md./13-adoption-community-and-support.md