Skip to content
Farhat Ullah.
Web

One design system, twelve frameworks — the TABSAP admin shells

Twelve admin dashboard starters, each built natively in a different framework, all implementing one shared design contract — nine CSS tokens and seven theme presets that behave identically across every stack.

Client
TABSAP internal platform, used across client projects
Sector
Web
Stack
Next.js · React · Vue · Angular · Nuxt · Laravel · React Native · Flutter · Tailwind
Year
2026
By Farhat UllahSenior Full Stack + AI EngineerUpdated

The problem

Every new project starts with the same argument: which stack. The answer is usually decided by what the client already runs, who maintains it afterwards, or whether it needs to be on a phone — and then the design gets re-decided from scratch to suit whatever won.

Porting one design across frameworks by hand produces twelve things that look roughly alike and diverge the moment anyone touches them. The sidebar behaves differently in Angular than in Blade. Dark mode works in three of them.

What I built

Twelve admin-panel shells — fully built dashboard starters — spanning Next.js, React, Vue, Angular, Nuxt, Laravel with both Blade and Inertia, React Native via Expo, Bootstrap, Tailwind and Flutter.

The point is not that there are twelve. It is that all twelve honour the same contract:

  • Nine CSS design tokens drive every piece of chrome — sidebar, header, primary accent.
  • Seven theme presets — TABSAP, Midnight, Graphite, Slate, Emerald, Rose — each with light and dark variants.
  • One storage and preview model, so theming behaves identically whether the underlying mechanism is React state, Vue reactivity, an Angular service, or Blade with Livewire.

Define a preset once and it lands the same way in all twelve. The collection behaves like a system rather than twelve lookalikes.

Selected engineering

A dark-mode bug that spanned the whole collection. Sidebars and headers stayed light in dark mode. The cause was CSS specificity, not logic: :where(.dark) contributes zero specificity, so the light-mode defaults silently outranked the dark overrides. It looked like a theming bug and was a cascade bug. Fixed across the affected shells, then audited all twelve for the same class of error.

Theme flash on client-side navigation. The boot script that applies the stored theme only runs on full page loads, so single-page navigations briefly dropped it. Fixed with framework-native re-apply listeners across eight shells — livewire:navigated, Inertia's inertia:finish, Next.js route effects, Nuxt router hooks, Angular's NavigationEnd, React Router location effects.

A modernisation pass. Vite 6 to 7, Tailwind v3 to v4 including the @theme inline-token migration and Angular's CSS pipeline, and Expo SDK 52 to 54 with React 19 and Reanimated 4.

Production hardening. Stripped non-functional comments from over two hundred source files using a proper AST parser per language — Babel for JS and TS, the Vue SFC compiler, the PHP tokenizer — rather than regex, so functional directives survived. Roughly 2,500 lines removed with no behaviour change, every shell verified building and type-checking clean.

Outcome

Twelve production-ready admin foundations that stay visually and behaviourally identical across the modern web and mobile stack. A new product can start on whichever framework fits the client, without re-deciding the design.

Why it mattered

The AST detail is the one worth dwelling on. Stripping comments with a regex across two hundred files is a ten-minute job that silently removes @ts-expect-error, Vue compiler hints and PHP annotations — and the damage surfaces weeks later in something unrelated. Doing it per-language with a real parser took far longer and is the reason the diff was 2,500 lines of pure noise removal rather than a bug hunt.

Framework implementations
12
Design tokens driving all chrome
9
Theme presets, light and dark
7

Have a system that needs to work in production?

Tell me what's breaking — or what you're building.

Chat on WhatsApp