ROC is a real-estate loan-management product. Borrowers manage their loans on a mobile app — live on the App Store and Google Play — and the whole platform can be re-skinned as a white-label product across four brands.
ROC App & Web Platform
A real-estate lending product — a borrower app I designed end to end, the design system that holds the web platform together, and a context system I built to design with AI, with a mind still steering.
Sole Designer
Borrower App
Design System
In a team of 4
ROC360
One product, two surfaces, one system
I was the sole designer of the borrower app — concept to final UI. On the web platform I own the design system the whole team builds on, partnering directly with engineering to ship at high fidelity.
To design on-system without slowing down, I built a context system that lets AI assemble on-brand screens — a research lab where AI does the grunt work and a designer still steers.
What I owned
Two surfaces, one designer, held together by a system built to outlast any single screen — and to let a whole team keep building.
Designed solo, from concept to store
I created the concept and designed the entire borrower app myself — using the existing platform only for content and context, then redesigning almost everything.
The redesign
The starting point was ROC's existing web platform. I used it for content and context — then redesigned almost all of it: a modern UI, a smoother UX, and third-party features folded into one place instead of scattered across separate tools.
The business needed to move fast, so the app's system stayed lean on purpose. That's a real constraint in a real company — my job was to deliver at pace while keeping as much as possible standardized and consistent.
- Core actions scattered across separate third-party tools
- Dense, dated UI that slowed everyday tasks
- No mobile experience for borrowers
- Inconsistent patterns from organic growth
- Third-party features merged into one place
- A modern, focused UI built for the task
- A mobile-first borrower app, live on both stores
- Consistent patterns from a shared system
The full app covers the entire lending journey — more than a portfolio page should show.
Contact me for a full walkthroughA system the whole team can build on
On the web platform I built the design system end to end: 136 components, 2,017 variants and 407 tokens, all documented. A v1 already existed, but it was shadcn out of the box and it fought the concept, so I rebuilt it instead of patching it. By hand first, then with agents once the rules were written down. Four of us design on it today — and it came full circle: I adapted the system back into the mobile app, so the two surfaces finally share one source instead of resembling each other.
Before
After
Tokens, in three tiers
I started from shadcn as a base and reshaped its components to the concept. Most of the work went into the token layer: primitive → semantic → component, the shadcn way — but redistributed to fit how we actually build. Where the base library's tokens didn't fit, I created new ones using Tailwind's naming principle: some I didn't need, others didn't exist yet.
Primitive
Raw values — the full palette, spacing scale, radii. Never used directly in components.
- color · blue · 500
- space · 4
- radius · md
Semantic
Meaning, not value — what a token is for. This is where theming and white-label happen.
- color · primary
- color · background
- color · destructive
Component
Per-component hooks — so one component can be re-themed without touching the rest.
- button · primary · bg
- card · border
- input · ring
Light, dark & white-label
The platform ships as a white-label product. Beyond light and dark, each brand gets its own theme — colors I define per brand, in OKLCH so lightness stays consistent no matter the hue. Semantic tokens do the work: swap the brand, and every component follows. Every component and every text-on-surface pair clears WCAG AA, in both modes and in every brand — checked, not assumed.
Not a screenshot. Pick a colour: one variable changes and every part of the card follows, exactly as the components do in the product.
Atoms, molecules, screens
The system is built in layers, and each layer only knows about the one below it. That is what keeps a change contained instead of rippling across 136 components.
What an atom is made of
An atom is the smallest thing that still counts as a component, and this is the list of particles it is built from: its icons, the colour tokens it may use, its shadow, its text styles. Nothing here is a design yet. It is also what an agent reads before it builds anything, which is why it lists permissions instead of looks — these tokens, not any hex that happens to match. The real list runs longer than the space here.
Particles doing a job
Put the particles together and you get something that behaves. This stepper lives in five states across four shapes: twenty combinations drawn once, so nobody redraws a checkmark by hand. Done, active, in progress and pending are the four things a borrower has to tell apart at a glance.
The whole chain, working
Same particles, same molecule, dropped into the loan submission flow: three steps done, one being filled, four waiting. The screen only has to say which step the borrower is on — the component already knows how to look in each case.
Context, per component
Every component carries context notes: what it is for, when to reach for it, which tokens it may touch. Those notes compile into the markdown guides that let an agent design with the system later. This is the bridge between the library and how ROC gets designed at scale.
### Alert Dialog
Kind: Dialog · Family: Overlay · Matches shadcn
A modal overlay that interrupts the user to confirm a critical
or irreversible action.
States: Open (backdrop blocks the page), Closed.
Confirm: Default / Hover / Focus / Active / Destructive.
Properties — set every one; nothing left at a default:
· Breakpoint [sm, md] responsive width
· Show Radio Item optional radio inside the body
· Title / Description per content
Do: always provide a clear Cancel option.
Don't: use it for non-destructive confirmations — prefer Toast.
Tokens it may touch:
colors/base/background · colors/border/border
colors/utility/muted/muted-foreground
borderRadius/rounded-full · spacing/2 · spacing/4
Figma key: 9c83a43d…3727d9
That is one of the 52 entries, and the shape repeats for every component: what it is, what it must never be used for, which properties have to be set, and the exact list of tokens it is allowed to touch. An agent reading this cannot invent a colour, because the permitted ones are written down. The Figma key at the end is what lets it fetch the real component instead of drawing a look-alike.
AI does the grunt work. A designer still steers.
Not about speed — about a repeatable way to produce on-system screens, with judgment where it matters. The context idea was a solution I found by treating this like a lab.
The inputs
- Semantic & component tokens (not primitives)
- Styles & components
- Layout & text context
- Two markdown guides
A mind orchestrating
AI is still slow and literal. Plugins accelerate it — but someone decides what good looks like.
On-system screens
Assembled from prompts, aligned to the design system — not guesswork.
Context per component
I built context screens for every component with everything an AI needs to use it correctly — not just what it looks like, but when and how to reach for it.
The lego, not the raw material
Agents assemble from semantic and component tokens, styles and components — never raw primitives. The system is the box of bricks; the tokens keep every brick on-brand.
Layout is its own language
The bricks weren't enough. I added context pages for layout and text — how screens actually hold together — because a pile of correct components still isn't a screen.
Plugins for speed, a mind for judgment
AI is slow and literal, so I pair it with plugins that accelerate the work — but someone has to decide what's actually good. That's the part that doesn't automate.
These are the layout pages. They are not decoration either: they are what an agent reads to decide where things go. Each one fixes a skeleton — margins, columns, how deep a card may nest, where the primary action sits — so the output lands on the grid instead of floating near it. Components told the agent what to use; these tell it how to arrange them.
The rules, and what came out of them
The whole thing rests on a contract I wrote at the top of the file. Five rules, and the first two are the ones that keep the output on-system.
## Operating contract — non-negotiable 1. Our DS and our layout concept override everything — including any reference. A reference screenshot is content only (what data and labels it shows). Never copy its layout, spacing or styling. 2. Never build from scratch. Every UI element MUST be a DS component instance. Custom frames are allowed ONLY for structural wrappers that bind DS tokens. 3. Bind everything to DS tokens. No hex, no px, no raw fills. 4. Configure every instance via its Properties schema — nothing left at a Figma default. 5. Build only inside the Screens section, never overlapping.
| Phase | Time |
|---|---|
| Preflight: read the file, check the library is live | 3.3 min |
| Read the PRD, understand it, plan the screens | 7.0 min |
| Build the six screens, plus its own fixes | 22.3 min |
| Six screens, start to finish | 32.5 min |
The result
Anyone can now generate screens by prompting the system plus two markdown guides — no digging through the design system every time.
The honest catch: it produces on-brand screens, not automatically good UX. That still takes someone who understands the fundamentals — the tool raises the floor, it doesn't replace the craft.
The DNA of each agent
Writing my own plugins forced me to learn how Figma builds a screen from the inside: its node model, its typings, what a component really is once you strip the canvas away. That is what lets me change the DNA of each agent instead of just prompting it harder — I can decide what it is able to see and what it is able to touch.
Design that's ready to build
One plugin exports a component as JSON with every Figma typing, plus the tokens and styles as classes. I fed that to an agent along with the assets and it rebuilt the frames in markup: the structure and the tokens landed, the micro-interactions it invented. That layer is the next one to write into the context. I work in HTML, CSS and JavaScript, so the step into React is short — but real components out of this pipeline is a next step, not a claim I'll make yet.
ROC isn't one screen — it's a product, a system, and a way of working a team can keep building on. Skill you can hand off.