The problem
Tumblr’s interface had been accumulating visual inconsistency for years. Spacing values followed no pattern. A timestamp that added 39px of content made posts 108px taller, because uneven padding compounded through each element. The color situation was roughly 2,900 legacy palette variables spread across 985 SCSS files, maintained separately in three repositories, deprecated in spirit but thriving in practice.
There was never a formal initiative or a dedicated sprint. We built the design system in parallel with feature work, with key engineers from each platform, and got buy-in by shipping improvements. If it made the work faster and the product better, people used it.

Fig 01 Kicking off design systems work at a team meetup.
Tokens
Colors
Tumblr has 12 color palettes (True Blue, Dark Mode, Cement, and nine others), all available on web, with a subset on iOS and Android. Each palette defines a complete set of about 207 semantic-to-design-token mappings. The chrome token, for example, defines the app’s background color: navy-100 in True Blue, dark gray in the Dark palette. Change it once, and it updates everywhere.

Typography
Typography uses semantic tokens, divided between the interface and the post editor. The editor has custom options for users to play with when creating posts, but we kept interface type restricted.


Spacing
Every spacing value in the iOS feed seemed to be a different number, with no consistent pattern. We standardized to multiples of 8 (subdividing to 4 when needed), which improved readability and information density. A minor shortening of the post footer alone had resulted in a 2.5% increase in post impressions, so we knew even small consistency gains compounded.

Iconography
Icons had been added haphazardly over years. We redrew them all, unified their visual language, gave ourselves outlined and filled versions, and optimized for 16px, 20px, and 24px sizing.
![]()
![]()
![]()
![]()
![]()
![]()
Components
After defining tokens, we used them to build components.
Buttons
Primary, secondary, and icon variations, plus a custom “notes” button that appears on every post.






Avatar
The basic building block of identity on Tumblr, used widely and in many variations. We needed several sizes and states, but also needed to restrict implementation so it didn’t drift. We used this component to set the standard for documentation.
![]()
![]()
Menus
Menus appear throughout Tumblr: post overflow, publishing options, dashboard view selectors, ad reporting. We built a flexible menu component that handles icons, destructive actions, separators, submenus, and selection states.




Adoption
We still had 985 files using old variables.
We categorized the migration into three tiers: unambiguous replacements that could be automated, context-dependent ones where paletteBlack might map to $colorChromeFg or $colorContentFg depending on where the component sits in the hierarchy, and genuinely ambiguous cases that needed a human to look at the rendered UI and decide. I built internal tooling to speed up the second and third tiers, letting you click any element in the real UI, trace it back to its SCSS definition, and queue up replacements across files in a single pass.
Process
I set up a dedicated Friday session for design system work, open to designers, engineers, anyone contributing. The design team was already holding twice-weekly critique calls, which kept us aware of what was happening across product areas and surfaced opportunities to reuse components rather than build from scratch.
We tracked work on a GitHub project board across three lanes: design, engineering implementation (web, iOS, Android), and documentation (Storybook and Figma). We also introduced a requirement that a designer review all user-facing PRs. The team has reviewed about 200 since, and I’ve noticed fewer visual bugs as I use Tumblr outside of work.

