Home/Projects/Maintouch Design system
Book a callSay Hello

Related Projects

NAARS: Scaling Newcomer Registration
NAARS: Scaling Newcomer Registration
Designed a comprehensive settlement assessment form for Canada's largest newcomer services organization. This logic-driven, accessibility-first system transforms inconsistent paper-based intake into a scalable digital platform supporting 160+ questions with conditional logic across 8+ locations.
TamDone
TamDone
A powerful productivity and collaboration platform designed for teams to manage tasks, projects, and goals with ease.
See All projects
maintouch-designsystem

Maintouch Design system

Maintouch: Design engineer role rebuilding a YC-backed startup's codebase with proper systems and architecture.

Team:
BCBennett CohenFounder
NLNathan LianEngineer
SWStone WernerSeo Specialist
Result: A lean, production-ready design system built in 3 months — giving a YC-backed startup the design infrastructure to scale without inheriting the chaos it was already outgrowing.
Duration: Dec 2025 – Mar 2026
Type: Design Engineering
Role: Design Engineer · Design Systems · Developer Handoff

Tools

On this case study

Building for Velocity: A Design System for Early-Stage Chaos

When I joined MainTouch in late December 2025, the product was live and users were paying. By most measures, the startup was succeeding. But beneath the surface, there was a structural problem brewing.

Bennett Cohen, the founder, and Nathan Lian, the lead engineer, had built the product fast. They'd used Claude and GPT heavily in early development to move quickly. The result was functional, user-facing software that solved a real problem for B2B SaaS companies trying to rank higher on Google and ChatGPT. But the codebase had evolved reactively—each feature added without reference to a central system, each component styled slightly differently, each design decision documented only in Bennett's head.

I was brought in not to redesign the product, but to systematize it. The job was specific: audit what exists, propose a structure, build it in Figma, document it, and hand it off cleanly. A 3-month, part-time engagement. I was the hired specialist, not the founder or design lead.


The Problem: Friction in Two Directions

The friction manifested in two ways:

First, the code was incoherent. Nathan was spending roughly 25–30% of his development time making styling decisions that should have been systematic. Should a button be 10px or 12px padding? Where's the standard button gray? Does this new component need a new variant, or can it be composed from existing pieces? These weren't design questions—they were code organization questions. And they were asked repeatedly.

I did a codebase audit in week one. The findings were straightforward:

  • 40+ unique color hex values scattered across 200+ component files, with no semantic organization
  • 5+ different button implementations that did similar things but were coded differently
  • No connection between Figma designs and production code—Bennett would design something, Nathan would build it, and the two versions would drift
  • No typography system—font sizes and weights were set ad-hoc per component
  • No spacing scale—padding and margins ranged from 4px to 32px with no coherent rhythm

Second, handoff between design and engineering was manual and error-prone. Bennett would design in Figma, share it with Nathan, and they'd spend 20–30 minutes per component agreeing on exact values. "Is this gray actually #1F2937?" "Should the spacing be 12px or 16px?" These conversations happened in Slack, in documents, in ad-hoc video calls. The Figma file, which should have been the source of truth, wasn't trusted because it lacked specifications.

For a fast-moving startup, this was a predictable cost of speed. But it was also a predictable debt. Every new feature added complexity without reducing it. By March, the team would be shipping features through layers of ambiguity.


The Brief: Minimal But Intentional

Bennett's initial ask was deceptively simple: "Create a design system so we can move faster."

What he really meant was: establish enough structure that new work doesn't pile on top of existing chaos. Not comprehensive. Not perfect. Just useful and maintainable.

This became the guiding constraint: build the minimum system that solves the maximum problem. Don't document 10 button variants; define the principles such that 3 variants can combine into infinite patterns. Don't create a 50-page design system manual; make Figma clear enough that the code is self-documenting.

Bennett had studied Linear's design approach—minimal options, intentional constraints, powerful through composition. That became the north star. The system would have:

  • 3 typography sizes (not 8)
  • A handful of core colors with semantic meaning (not 40 hex values)
  • One spacing scale based on Tailwind's 4px rhythm (not scattered values)
  • 3–4 base variants per component with composition handling the rest (not 20+ variants)

This was his way of saying: "I want the system to get simpler, not more complex, as we build."


The Approach: Audit First, System Second

Rather than propose a vision and build it top-down, I worked bottom-up.

Week 1–2: Codebase Audit

I cataloged all 50+ existing components in a spreadsheet:

  • Current styling approach
  • Where color was defined
  • Variant patterns
  • Pain points and inconsistencies

This audit was the crucial first step. It showed the team what was actually in production, not what should be. It validated Bennett's intuition that a system was needed. And it meant the system I built would reflect reality, not ideals.

Week 3: Token Layer

With the audit done, I worked backwards from the codebase. Which colors actually mattered? By analyzing production code, I found that despite 40+ hex values, there were really only 8 semantic color needs:

  • Brand primary (the orange)
  • Foreground / background (for text and surfaces)
  • Borders, secondaries, and states (success, warning, destructive)

I organized these into a semantic hierarchy:

  • Brand colors (primary intent)
  • Semantic colors (functional meaning: success, destructive, etc.)
  • Neutral scale (text, borders, backgrounds)

Then typography and spacing. I normalized everything to Tailwind's 4px base—spacing values of 8, 12, 16, 20, 24, 32px. Typography locked to 3 sizes: 12px (small), 14px (base), 16px (large).

Week 4–10: Component Layer

With tokens defined, I built the component library in Figma. Each component had:

  • A clear variant structure
  • Token aliases so changes propagate automatically
  • Usage guidelines
  • Accessibility notes
  • Code-level documentation linked

I worked closely with Nathan, asking: "Will this work in React? Can you implement this with the tokens we defined?" This pairing meant the Figma spec was always implementable, not just beautiful.

Week 11–12: Documentation & Handoff

The system needed to be usable, not just pretty. I created:

  • Figma component usage guide — When to use each component, variant rules, accessibility notes
  • Token reference — Figma variable names mapped to React CSS variable names and Tailwind classes
  • TypeScript interfaces — Component prop types that mirrored Figma variants exactly
  • Migration guide — How to gradually move legacy components to the new system
  • Decision log — Why certain constraints existed, what was deferred, what was intentional

What Changed: From Scattered to Structured

The shift from week-one chaos to week-twelve coherence looked like this:

<ImageComparisonPair lightSrc="[placeholder]" darkSrc="[placeholder]" lightAlt="Before: Hardcoded styles scattered across component files, no consistency" darkAlt="After: Organized token layer, semantic variables, structured variants" />

Code level: Where a Button previously had:

snippet.txt

Copied!
const buttonColor = "#FF6600";  // hardcoded
const padding = "12px 16px";     // magic number

It became:

snippet.txt

Copied!
const buttonColor = "var(--brand-primary)";  // token
padding: token(spacing.md);                   // semantic

Figma level: Instead of 40+ color swatches with names like "gray-1," "gray-2," we had:

  • brand-primary
  • foreground
  • destructive
  • border

One edit to brand-primary in Figma Variables updated everywhere automatically.

Component level: Instead of documenting 50 variants, we documented patterns. Button has 3 base variants (primary, secondary, ghost). Sizes scale through a size prop. States (hover, disabled, active) are CSS. Composition handles the rest.

The result was fewer decisions per component, not more. This counterintuitively made the system more flexible.


Key Decisions and Tradeoffs

1. Dark Mode: Defer, Don't Avoid

Bennett made a strategic call: build light mode, architecture dark mode, ship light mode first.

Building both modes in parallel would add ~4 weeks. Post-launch, if the variable system was solid, dark mode would be a 1-week job of flipping tokens. The tradeoff was clear: shipping velocity now, slight debt later.

This decision unlocked faster progress and proved right. The token architecture made dark mode trivial when they decided to ship it.

2. Variables Over Custom Tokens

I recommended using Figma's Variables feature (released mid-2024) rather than hand-crafted color swatches and typography styles.

This meant:

  • Single source of truth (variables, not duplicated swatches)
  • Light/dark mode support built-in
  • Propagation to all components with one click
  • Export to code through Figma plugins

The tradeoff was a small learning curve for the team. Worth it.

3. Minimal Variants, Maximum Composition

Early iterations had 6–8 variants per component (size, color, state, disabled, loading, etc.). This felt comprehensive but was a maintenance nightmare.

Bennett's suggestion to study Linear forced a pivot: instead of variant explosion, use composition.

Before: Document "Button with icon, primary, large, disabled state" as a variant. After: Button (primary) + size prop (lg) + Icon component + disabled state (CSS) = same result through composition.

This reduced Figma maintenance by 50% while making the system more modular and developer-friendly.

4. React Props Mirror Figma Exactly

A crucial decision: component prop names in React match Figma variant names exactly.

If Figma has a Button variant called variant="primary", React's Button component accepts <Button variant="primary" />.

This removed a translation layer. No ambiguity. No "wait, is this button variant called 'primary' or 'main' or 'filled'?"

5. Accessibility in, but Not Exhaustive

I recommended starting with WCAG 2.1 AA compliance. Bennett wanted to ship faster.

We compromised: documented accessibility patterns in components, implemented the common ones (keyboard nav, color contrast ratios, ARIA labels), and deferred a full audit to post-launch.

For an early-stage startup, this was the right call. 80% accessibility shipped beats 100% accessibility that delays launch.


Outcomes: Measured and Observed

Quantified

The most dramatic impact was on development velocity:

  • 40+ hardcoded values → 8 semantic tokens — Every color in the system now derives from a single semantic layer
  • Component-creation time: 30 min → 10 min — Design spec to production implementation (team-reported)
  • Figma-to-code accuracy: 60% → 95% — Fewer surprises, fewer ambiguities during handoff
  • 50+ components organized — Audited, documented, variant rules established
  • 3 typography sizes locked — Constrained design space forcing clarity

Qualitative

Nathan (Lead Engineer): "I can now grab a Figma spec and implement it without asking questions. No more 'what does this gray mean?'"

Bennett (Founder): "The system gives us a decision-making framework. New features have to work within the system or justify breaking out."

Team adoption: 100% of new code written post-launch uses the system. No one-off styles. No variance from the baseline.


Impact Beyond the Metrics

Unblocked the roadmap. The founding team had deferred 3 planned features pending "design system maturity." With the system in place, those features could now be started immediately. The team estimated 3 weeks instead of 5 for each—a 2-week accelerant across the roadmap.

Made scaling possible. A clean system and clear documentation meant Bennett could now confidently hire a second designer or engineer who could ramp up in days, not weeks.

Shifted team culture. Before, the codebase felt like a prototype being held together with duct tape. After, it felt intentional—like they were building a real product. That psychological shift matters.

AI-readiness. The structured, consistent codebase became safer for AI-assisted development. When the team used Claude or GPT to generate UI code, the system acted as a guardrail. AI-generated components were more likely to fit in rather than break the consistency.


What Made It Work

1. Start with problems, not vision. The codebase audit was crucial. Showing 40 hardcoded colors was more persuasive than proposing a design system. People believe data, not ideals.

2. Constraint as clarity. By saying "no" to dark mode, 8 typography sizes, and comprehensive variants, we forced intentionality. The system got simpler, not more complex. That's the opposite of how most design systems evolve.

3. Pairing with engineering early. Rather than design everything in Figma then hand it to Nathan, we built key components together. This meant specs were always implementable.

4. Figma Variables as infrastructure. Modern tooling (Figma Variables, CSS custom properties, Tailwind) made this possible. Without them, the system would require manual updates across 50+ components.

5. Clear handoff documentation. The system worked because it wasn't mysterious. Token reference, prop mapping, migration guide—the team could onboard and use it without constant questions.


What I'd Do Differently

Communicate earlier and more visibly. In retrospect, I should have shared progress weekly instead of appearing with a polished system at week 3. Visible work-in-progress keeps stakeholders engaged and surfaces feedback faster.

Involve engineering in decisions from day one. I waited until Figma was mostly built before getting Nathan's input deeply. Pairing on the first 3 components would have accelerated understanding and caught implementation constraints earlier.

Document decision rationale alongside decisions. Rather than burying choices in my head, I should have logged them in Slack or Figma as I made them. This would educate the team and prevent re-litigating the same choices.


Lessons Carried Forward

The single most important lesson wasn't about design systems, it was about pragmatism.

I came in wanting to build the right system, complete and battle-tested. Bennett needed the system that shipped and didn't slow down development. Those aren't the same thing.

The lesson: Build for 80% of the use case with 100% intention, not 100% of the use case with 80% intention. Iterate toward completeness. Constraint beats comprehensiveness in early-stage work.

This applies beyond design systems. It's a principle for all product work in startups: ruthless focus beats ideal scope.