Paper Production Management System
Paper Production Management System
Timeline
Feb 2025 - Aug 2025
Role
UI Designer (Design system Lead)
Deliverable
B2B SaaS Platform ERP for Paper manufacturing
Platform
Figma · Claude · shadcn/ui
Project Overview
The Paper Production Management System (PPMS) is a B2B SaaS platform built for mid-to-large paper manufacturing facilities. It centralises operations across the full production lifecycle — from raw material intake and production scheduling through to quality control and dispatch.
The platform is designed to serve multiple plant locations under a single product, with each client able to operate under their own brand and operational configuration. It is delivered as a modern web application, replacing a collection of separated, module-by-module tools that had accumulated inconsistency through years of independent development across different teams.
The system covers 14 functional modules across 4 operational clusters — Core Product, Productions, Operations, and Sales — all unified by a single design system built to bring consistency, scalability, and clarity across every module.
My Role as UI Designer
I worked as the sole UI designer within a small, focused team alongside a product owner and software developers. The team's approach was to build a core product first — Products Master — then bring it to clients and expand module by module based on each client's operational needs.
My responsibility was to establish the visual foundation of the platform: the design language, component system, and UI screens that the development team would build from. While the product owner defined business requirements and developers handled logic and technical architecture, I owned every design decision — from the token structure down to individual component states.
Design Process
🙋 Requirement
Brief & Challenges
The project brief came from the product owner with a clear goal — build a B2B SaaS ERP platform that could be sold to multiple paper manufacturing clients without rebuilding the UI for each one. That single requirement had significant design implications that shaped every decision in the system.
My responsibility was to focus on the visual layer of the system, without ownership of user flows or system logic those belonged to the product owner. That led me to approach this through a design system rather than designing screens one by one. Three core challenges shaped how I worked.
◆ Large-Scale system, One Designer: With 14 modules across four clusters, I was the only designer involved from the beginning. That meant I couldn't just design screens one by one — I needed to build a visual foundation and component system that developers and future designers could pick up and work from independently, without me having to explain every decision.
◆No existing design system foundation: When I joined the project, there was no shared design language — no color tokens, no typography scale, no component library. Each module had been approached individually, resulting in hardcoded values and visual inconsistency that grew harder to reconcile with every new screen added.
◆ Multi-client theming: The product owner required that the platform support multiple factory clients under the same codebase, each with their own brand color. This was not a cosmetic requirement — it had to work at the system level. The design system could not rely on hardcoded brand values. Every color needed to be token-driven and swappable at deployment, without touching component logic. This forced a semantic token architecture from the start — the foundation of everything that followed.
💡 Discovery
Shadcn/ui Foundation
In an early discussion with the product owner, I proposed using shadcn/ui as the UI foundation for the platform rather than building from scratch — choosing a proven base would save time, ensure accessibility, and give developers a familiar implementation path. Three reasons made it the right fit for this project's requirements:
◆ Clean UI: its clean, minimal black-and-white aesthetic made it easy to retheme per client without fighting an existing brand identity. For a multi-client platform, a neutral visual base is an advantage, not a limitation.
◆ Token-native architecture: Its component architecture exposes color and spacing values as CSS variables that can be swapped at the system level. This matched our multi-client theming requirement exactly — one palette swap, no component changes.
◆ Official Figma File: It ships with an official Figma file that mirrors the React component structure developers implement. This reduced interpretation gaps in handoff — what I designed in Figma had a direct counterpart in code.
🖥️ Prototype
High-Fidelity Prototype
The product owner drafted rough UI layouts in Google Sheets — outlining screen structure, navigation flow, and the data each module needed to display. These sketches were functional briefs, not design specs. My role was to take that structure and translate it into a high-fidelity interface using the shadcn/ui foundation.
Rather than designing all 14 modules upfront, I focused first on Paper Roll Management — the module with the widest range of component types: data tables, form inputs, dropdowns, status badges, and action buttons all in one view. Getting this module right would stress-test the component system and establish a visual pattern that the rest of the modules could follow.
📱 Design System
Design Tokens
Building on the shadcn/ui foundation, I created a design token system as the core deliverable of this project — a structured, documented set of tokens and components that gives the development team everything they need to build consistently across all 14 modules without requiring designer involvement on every decision. It unifies design and code into a single source of truth, while giving the product owner the flexibility to retheme per client at the token level.
The Pyramid of Design Token Structure
I structured design values into three layers of increasing specificity. Each layer references the one below — no component ever hardcodes a raw value:
◆ Primitive Values: The foundational layer — raw, immutable values. Every color, size, and spacing value in the system starts here as a literal hex or pixel value. These are the only tokens that contain hardcoded values. e.g. color/default/900 = #18181B.
◆ Semantic Tokens: The contextual layer — tokens named by role, not by value. e.g. surface-invert and text-primary reference primitive values and define what each value means in the interface.
◆ Component Tokens: The applied layer — tokens specific to individual components. button-surface-primary references a semantic token, not a primitive. This means a button's background color adapts across themes and modes without any change to the component itself.
Typography Tokens
Typography follows the same three-layer structure. Primitive values define the raw font properties — family, weight, size, and line height — as separate tokens that can be combined to form any text style. Semantic aliases then reference these primitives by role. All seven type levels in the system use Inter, with four size stops, four line height stops, and three weight stops covering the full scale. The separation means changing the base font family requires updating a single primitive token, not every text style individually.
Spacing and Radius Tokens
Spacing and radius follow a numbered primitive scale with semantic aliases covering all stops. Spacing uses a base unit of 8px, giving five stops from 8px to 40px — each with a semantic name from spacing-xs through spacing-xl. Radius follows the same five-stop structure, from radius-xs at 4px for subtle corner rounding up to radius-full at 360px — the pill radius used for badge and toggle components.
Both scales use a consistent two-layer naming convention: slash notation for primitives (spacing/3, radius/lg) and hyphen notation for semantic aliases (spacing-md, radius-md). This distinction makes it immediately clear to developers whether they are referencing a raw value or a semantic token, and ensures the system can be extended without naming collisions.
Components
With the token system in place, I built the core component library on top of shadcn/ui primitives. Each component references semantic tokens — never raw values — so every variant, state, and theme change flows from the token layer automatically. The library covers the full range of UI patterns used across all 14 modules: color application, typography scale, interactive controls, and form inputs.
Color
The slate scale forms the foundation — nine core stops from white to near-black, with an added 550 bridge stop to smooth the perceptual gap between 500 and 600. Semantic tokens reference these stops by role, not by value. Status colors are fixed across all client themes because they carry safety-critical meaning in a production environment.
Beyond the slate scale, two semantic color ramps handle feedback states across the interface — red for danger and errors, green for success and approval. Each ramp has five stops: a background tint, a border, a hover border, a dark mode stop, and a light mode stop. Because these colors carry domain-specific meaning, they are fixed across all client themes and are never part of a palette swap.
Tokens are grouped by role — text, surface, button, border, and icon — each with light and dark mode values defined in Figma Variables. The two-column Light / Dark structure means switching modes is a single variable collection change, not a component redesign. Every token references a primitive from the slate scale, never a hardcoded hex value.
Because every color in the system references a semantic token rather than a hardcoded value, light and dark mode required no component redesign — only the token values change. The same screen, the same component, the same layout — a different variable collection. This is also the proof-of-concept for per-client theming: the same mechanism that switches light to dark handles a full palette swap for each new client deployment. A new client brand color requires changing only the primitive layer — every component updates automatically.
Typography
The typography scale uses seven levels, all in Inter, defined through composable font primitives — family, weight, size, and line height — that combine to form each text style. From Display down to Data, every level references tokens rather than hardcoded values, meaning the entire type system can be updated at the token level without touching individual text styles across 14 modules.
The Data level is a purposeful addition beyond standard heading and body levels — using Inter Medium with font-variant-numeric: tabular-nums to ensure numeric values such as weights, batch IDs, and measurements align correctly in table columns without switching to a monospaced font.
Button
The button component is built on shadcn/ui and wired entirely to the token system — no hardcoded values. Every visual property, from background color and typography to spacing and corner radius, maps to a named token. This means any theme or mode change flows through automatically without touching the component itself.
The system uses a single size — 40px height — with four variants: Primary, Secondary, Ghost, and Danger. Each variant covers four interaction states: Default, Hover, Focus, and Disabled. Width hugs content by default; full-width is applied explicitly inside modals and single-column forms only. Ghost, Danger, and Loading states are designed and will be added to the component documentation in the next iteration.
Icons
Icons are sourced from Tabler Icons — an open-source library with a consistent stroke weight that matches the clean, minimal aesthetic of the shadcn/ui foundation. Each icon is sized at 18px and centered inside a fixed 40×40px container, keeping it visually consistent with the button height across the system
Like the button component, icon color is controlled through semantic tokens — each referencing the slate scale or support color ramps, never a hardcoded value.
Textbox
The text input is built on shadcn/ui and shares the same 40px height and radius-sm corner radius as the button component, ensuring vertical consistency when inputs and buttons appear on the same row. Like all components in the system, every visual property references a semantic token — never a hardcoded value.
The component covers five interaction states — Placeholder, Filled, Focus, Error, and Disabled. The focus state strengthens the border to signal active input without disrupting the surrounding layout. The error state pairs a red border from the danger color ramp with an inline message below the field, giving operators clear and immediate feedback without requiring a separate alert component.
Dropdown
The dropdown select shares the same 40px height, radius-sm corner radius, and token structure as the textbox — ensuring visual consistency across all form elements. The key difference is the open state: when triggered, a panel renders below with the selected option marked by a checkmark icon. Both the trigger and the open panel reference the same semantic tokens — border, background, icon, and text color — never hardcoded values.
Impact & Future
◆ Impact
Building a design system from zero for a 14-module B2B SaaS platform as a solo designer is not a small undertaking. The impact of this work is measured not just in what was delivered, but in what it enables going forward.
Consistency Across Modules: Every module now references the same tokens and components. Operators navigating between Paper Roll Management, Production Control, and Scheduling see the same patterns, states, and feedback language — regardless of which module they are in.
Faster Development: Developers no longer rebuild the same UI patterns per module. Buttons, inputs, dropdowns, and icon buttons are implemented once and reused — reducing development time and the risk of visual drift between modules.
Scalable Theming: The semantic token architecture directly solved the product owner's core requirement. Deploying for a new factory client now requires changing only the primitive color layer — every component updates automatically. No redesign, no additional development work.
Single Source of Truth: The Figma Variables file, token documentation, and component library give the entire team one place to reference design decisions — reducing ambiguity during development and giving new team members a foundation to onboard from independently.
◆ Future Improvements
The design system is a living document, not a finished deliverable. Four areas are planned for the next iteration:
Complete Button Variants: Ghost, Danger, and Loading states are designed but not yet fully documented. Icon button variants for edit, delete, and action triggers will be added alongside them.
Expand the Status Color System: The current system covers red and green. A full production environment needs amber (warning) and blue (info/calibrating) ramps — each with the same five-stop structure as the existing scales.
Additional Components: The next phase adds Table, Badge, Alert, Toast, Dialog, and Navigation — covering the full component range used across all 14 modules.
Multi-Client Palette Process: The token architecture supports per-client theming. The next step is a formal palette intake process — a structured way to onboard a new client's brand color and generate a primitive ramp that passes contrast requirements automatically.
◆ What this project taught me
Designing a system rather than individual screens requires a different mindset. Every decision has to answer two questions — does it work for this screen, and does it scale across 14 modules? The token architecture forced me to think structurally from the start, and the shadcn/ui foundation gave the development team a familiar implementation path that reduced friction during handoff. The biggest lesson: documentation is a design deliverable, not an afterthought.