Files
sass-mohfarawati/docs/frontend-system-audit.md
T

15 KiB

Frontend System Audit

1. UI libraries actually used

  • next App Router is the app shell and routing layer.
  • tailwindcss is the styling system.
  • @radix-ui/react-* primitives are used through local wrappers in:
    • components/ui/accordion.tsx
    • components/ui/checkbox.tsx
    • components/ui/dialog.tsx
    • components/ui/dropdown-menu.tsx
    • components/ui/select.tsx
    • components/ui/sheet.tsx
  • class-variance-authority is used for variants in:
    • components/ui/button.tsx
    • components/ui/badge.tsx
    • components/ui/app-card.tsx
    • components/layout/container.tsx
  • clsx + tailwind-merge are used through cn() in lib/utils.ts.
  • next-themes is used for theme switching in:
    • components/theme-provider.tsx
    • components/theme-toggle.tsx
  • framer-motion is used for custom motion in:
    • components/motion-fade.tsx
    • components/layout/site-header.tsx
    • components/layout/site-logo.tsx
    • components/layout/hero-motion-backdrop.tsx
    • components/layout/hero-atmosphere.tsx
    • components/layout/site-ambient-backdrop.tsx
    • components/layout/ascii-water-ripple.tsx
    • components/layout/animated-logo.tsx
    • components/layout/stacked-marquee-section.tsx
  • tailwindcss-animate is enabled in tailwind.config.ts and is used by state classes in dialog, dropdown-menu, select, sheet, and accordion.

2. Which library is the primary source of UI primitives

The primary primitive source is the local components/ui layer.

That layer is mostly built on top of @radix-ui/react-* plus Tailwind classes.

The app code imports local primitives like:

  • @/components/ui/button
  • @/components/ui/card
  • @/components/ui/input
  • @/components/ui/dialog
  • @/components/ui/select

It does not import Radix primitives directly from route files and feature components.

3. Whether shadcn/ui is really used or only partially used

shadcn/ui is present, but partially.

Evidence that it is present:

  • components.json exists and points to app/globals.css, tailwind.config.ts, and @/components/ui.
  • The local primitive structure matches the common shadcn pattern:
    • components/ui/button.tsx
    • components/ui/card.tsx
    • components/ui/dialog.tsx
    • components/ui/dropdown-menu.tsx
    • components/ui/select.tsx
    • components/ui/sheet.tsx
  • lib/utils.ts exposes the standard cn() helper.

Evidence that it is partial/customized rather than stock:

  • There is no runtime shadcn-ui package in package.json.
  • Several components are customized to project tokens:
    • rounded-surface
    • rounded-nested
    • shadow-card
    • shadow-panel
  • components/ui/app-card.tsx is a project-specific wrapper over Card.
  • components/ui/tabs.tsx is a custom React context implementation, not a Radix wrapper.
  • Usage is selective. Import counts in the current codebase show:
    • app-card: 23
    • card: 26
    • button: 19
    • dialog: 1
    • dropdown-menu: 1
    • sheet: 1
    • table: 1
    • tabs: 1

4. Repeated layout/container patterns found in code

Global container pattern

The main reusable container is components/layout/container.tsx:

mx-auto w-full px-4 sm:px-6 lg:px-8

Container sizes come from Tailwind extensions:

  • max-w-layout
  • max-w-narrow
  • max-w-wide
  • max-w-admin

These map to CSS vars in app/globals.css:

  • --container-narrow: 48rem
  • --container-default: 72rem
  • --container-wide: 80rem
  • --container-admin: 88rem

Public site shell pattern

Repeated in:

  • app/[locale]/(site)/layout.tsx
  • components/layout/site-header.tsx
  • components/layout/home-hero.tsx
  • components/layout/page-hero.tsx
  • app/[locale]/(site)/contact/page.tsx

Patterns:

  • relative flex min-h-screen flex-col overflow-hidden
  • max-w-[72rem] px-4 sm:px-6 lg:px-8
  • hero sections with:
    • pt-24
    • sm:pt-28
    • lg:pt-28
    • pb-10
    • lg:pb-12
    • lg:pb-16

Admin layout pattern

Repeated in:

  • components/dashboard/dashboard-layout.tsx
  • components/root/root-dashboard-shell.tsx
  • many app/root/*/page.tsx

Patterns:

  • min-h-screen bg-muted/30
  • grid min-h-screen lg:grid-cols-[280px_minmax(0,1fr)]
  • sticky sidebar:
    • lg:sticky lg:top-0 lg:h-screen
  • sticky header:
    • sticky top-0 z-30 ... bg-background/95 ... backdrop-blur
  • main content spacing:
    • p-4 lg:p-6
  • page stack wrapper:
    • space-y-6

Editor / split workspace pattern

Repeated in:

  • components/root/site-settings-form.tsx
  • components/root/portfolio-project-form.tsx
  • app/root/page.tsx

Patterns:

  • grid gap-6 xl:grid-cols-[minmax(0,3fr)_minmax(320px,1fr)]
  • grid gap-6 xl:grid-cols-[280px_minmax(0,1fr)]
  • sticky side panel:
    • xl:sticky xl:top-6 xl:self-start

5. Repeated radius values found in code

Tokenized radius values

Defined in app/globals.css:

  • --radius-surface: 24px
  • --radius-nested: 16px
  • --radius-pill: 9999px

Mapped in tailwind.config.ts:

  • rounded-surface
  • rounded-nested
  • rounded-pill

Repeated radius class patterns

Most repeated token usage:

  • rounded-surface
    • components/ui/card.tsx
    • components/ui/app-card.tsx
    • components/ui/accordion.tsx
    • components/ui/dropdown-menu.tsx
    • components/ui/select.tsx
    • components/ui/tabs.tsx
  • rounded-nested
    • components/ui/button.tsx
    • components/ui/input.tsx
    • components/ui/textarea.tsx
    • components/ui/select.tsx
    • components/dashboard/sidebar.tsx
    • components/root/contact-protection-form.tsx
  • rounded-[var(--radius-pill)]
    • components/layout/site-header.tsx
    • components/layout/floating-preferences.tsx
  • rounded-full
    • used heavily for decorative circles and icon pills in site chrome:
      • components/layout/site-ambient-backdrop.tsx
      • components/layout/hero-atmosphere.tsx
      • components/layout/ascii-water-ripple.tsx

Non-token radius values also present

  • rounded-md
    • several content blocks and previews
    • examples:
      • app/root/page.tsx
      • components/root/site-settings-form.tsx
      • components/root/media-field-picker.tsx
  • rounded-lg
    • examples:
      • components/ui/dialog.tsx
      • components/dashboard/dashboard-layout.tsx
      • components/root/portfolio-project-form.tsx

6. Repeated spacing patterns found in code

Global repeated spacing

Most repeated stack and gap patterns:

  • space-y-6
  • gap-6
  • space-y-2
  • space-y-3
  • p-6
  • p-4
  • px-4 py-3
  • px-4 py-4
  • px-3 py-2

Core primitive spacing

  • CardHeader: flex flex-col gap-1.5 p-6
    • components/ui/card.tsx
  • CardContent: p-6 pt-0
    • components/ui/card.tsx
  • Button sizes:
    • default: h-10 px-4 py-2
    • sm: h-9 px-3
    • lg: h-11 px-6
    • icon: h-10 w-10
    • components/ui/button.tsx
  • Input and Textarea:
    • px-3 py-2
    • components/ui/input.tsx
    • components/ui/textarea.tsx
  • SelectTrigger:
    • px-3 py-2
    • components/ui/select.tsx

Layout spacing

  • container padding:
    • px-4 sm:px-6 lg:px-8
  • admin page wrapper:
    • p-4 lg:p-6
  • admin section wrapper:
    • py-6 lg:py-8
    • components/layout/app-shell.tsx
  • hero wrappers:
    • pt-24
    • sm:pt-28
    • lg:pt-28

7. Repeated color/token usage found in code

Semantic tokens defined

Defined in app/globals.css and exposed in tailwind.config.ts:

  • base semantic:
    • background
    • foreground
    • card
    • popover
    • primary
    • secondary
    • muted
    • accent
    • destructive
    • border
    • border-strong
    • input
    • ring
  • custom semantic:
    • surface-1
    • surface-2
    • surface-3
    • surface-inverse
    • brand-primary
    • brand-secondary
    • status-success
    • status-success-soft
    • status-warning
    • status-warning-soft
    • sidebar-*
    • hero-*

Repeated utility combinations

Very common combinations:

  • border border-border/80 bg-card text-card-foreground shadow-card
    • components/ui/card.tsx
  • border border-input bg-background
    • components/ui/input.tsx
    • components/ui/select.tsx
    • components/root/portfolio-categories-manager.tsx
    • components/root/portfolio-projects-overview.tsx
  • bg-primary text-primary-foreground
    • active nav and badges/buttons:
      • components/ui/button.tsx
      • components/ui/badge.tsx
      • components/dashboard/sidebar.tsx
      • components/root/portfolio-subnav.tsx
      • app/[locale]/(site)/portfolio/page.tsx
  • text-muted-foreground
    • repeated throughout forms, cards, table headers, descriptions
  • hover:bg-accent
    • repeated in button, dropdown-menu, select items, and selection cards
  • bg-muted/40 and bg-muted/50
    • repeated in admin surfaces and tables

Site-specific color usage outside semantic surface tokens

Public-facing chrome also uses many arbitrary values:

  • border-black/6
  • bg-white/24
  • bg-white/32
  • text-[hsl(var(--hero-ink)/0.76)]
  • custom shadow values with raw rgba(...)

Examples:

  • components/layout/site-header.tsx
  • components/layout/floating-preferences.tsx
  • app/[locale]/(site)/page.tsx

8. Motion/animation approach actually used

There are two real motion layers.

framer-motion

Used for custom movement and page chrome:

  • reveal-on-scroll wrapper:
    • components/motion-fade.tsx
  • header nav active pill and mobile menu:
    • components/layout/site-header.tsx
  • logo animation:
    • components/layout/site-logo.tsx
    • components/layout/animated-logo.tsx
  • ambient / backdrop motion:
    • components/layout/hero-motion-backdrop.tsx
    • components/layout/hero-atmosphere.tsx
    • components/layout/site-ambient-backdrop.tsx
    • components/layout/ascii-water-ripple.tsx
    • components/layout/stacked-marquee-section.tsx

tailwindcss-animate

Used through state classes for Radix-style overlays and disclosures:

  • data-[state=open]:animate-in
  • data-[state=closed]:animate-out
  • fade-in-0
  • zoom-in-95
  • slide-in-from-top-2
  • animate-accordion-down
  • animate-accordion-up

Files:

  • components/ui/dialog.tsx
  • components/ui/dropdown-menu.tsx
  • components/ui/select.tsx
  • components/ui/sheet.tsx
  • components/ui/accordion.tsx

9. Icon system actually used

The icon system is lucide-react .

Evidence:

  • dependency in package.json
  • broad usage across app and components
  • examples:
    • components/root/root-dashboard-shell.tsx
    • components/layout/site-header.tsx
    • components/theme-toggle.tsx
    • app/root/page.tsx
    • app/[locale]/(site)/page.tsx

No second React icon library is present in package.json.

10. Component architecture currently used

Routing structure

  • app is the real route layer.
  • public site routes live under:
    • app/[locale]/(site)/*
  • admin routes live under:
    • app/root/*
  • src exists but is empty in the current codebase.

Component folders

  • components/ui
    • primitive and near-primitive reusable controls
  • components/layout
    • site shell, hero, header, footer, container, backdrops
  • components/root
    • admin feature components and forms
  • components/dashboard
    • admin navigation and dashboard layout shell
  • components/site
    • site feature forms such as contact form

Helper layer

  • lib/utils.ts
    • cn()
  • lib/root-navigation.ts
    • navigation config for admin shell
  • other lib/*
    • app settings, metadata, locale, media, portfolio, auth

Wrappers around primitives

Confirmed custom wrappers around local primitive layer:

  • components/ui/app-card.tsx
    • wraps Card
  • components/theme-toggle.tsx
    • wraps Button
  • components/layout/locale-toggle.tsx
    • uses Button and DropdownMenu
  • components/root/form-save-button.tsx
    • uses Button

11. Violations or inconsistencies found in the current codebase

These are current inconsistencies visible in the implementation.

Token system is mixed with raw one-off styling

Admin and primitive components strongly use semantic tokens:

  • bg-card
  • bg-background
  • border-input
  • shadow-card
  • rounded-surface

But public chrome often bypasses them with raw arbitrary values:

  • components/layout/site-header.tsx
  • components/layout/floating-preferences.tsx
  • app/[locale]/(site)/page.tsx

Examples:

  • bg-white/24
  • border-black/6
  • shadow-[0_14px_34px_-24px_rgba(15,23,42,0.18)]

Radius usage is not fully normalized

Tokenized radius classes exist, but these also appear:

  • rounded-md
  • rounded-lg
  • rounded-full

Examples:

  • components/ui/dialog.tsx
  • components/dashboard/dashboard-layout.tsx
  • components/root/site-settings-form.tsx
  • components/root/portfolio-project-form.tsx

Some primitives follow the local system, some keep stock shadcn-style values

  • tokenized:
    • components/ui/card.tsx
    • components/ui/button.tsx
    • components/ui/input.tsx
    • components/ui/select.tsx
  • less tokenized:
    • components/ui/dialog.tsx
      • sm:rounded-lg
      • shadow-lg
  • less tokenized:
    • components/ui/sheet.tsx
      • shadow-lg

AppCard surface levels are not all visually distinct

In components/ui/app-card.tsx:

  • level: 1 and level: 2 both use:
    • border border-border/80 bg-card text-card-foreground shadow-card

So the file defines multiple levels, but two of them are currently identical.

Primitive implementation style is not uniform

Most interactive primitives use Radix wrappers, but components/ui/tabs.tsx is a custom React context implementation instead.

Tailwind scans src, but src is empty

tailwind.config.ts includes:

  • ./src/**/*.{js,ts,jsx,tsx,mdx}

Current project state:

  • src contains no files.

12. Codex rules derived from the existing system

These rules are derived from what the codebase already does.

  • Use local primitives from components/ui before introducing direct Radix usage.
  • Use cn() from lib/utils.ts for class composition.
  • Use cva() for reusable variant APIs where the project already does that:
    • Button
    • Badge
    • AppCard
    • Container
  • For shared admin surfaces, prefer tokenized classes already present:
    • rounded-surface
    • rounded-nested
    • bg-card
    • bg-background
    • border-input
    • border-border/80
    • shadow-card
    • shadow-panel
  • For main width constraints, follow the existing container system:
    • Container
    • max-w-layout
    • max-w-admin
    • px-4 sm:px-6 lg:px-8
  • For admin pages and forms, the repeated layout rhythm is:
    • space-y-6
    • gap-6
    • space-y-2
    • p-6
    • p-4
  • For public site hero/layout sections, the repeated shell is:
    • hero-surface
    • max-w-[72rem]
    • px-4 sm:px-6 lg:px-8
    • pt-24 sm:pt-28
  • Use lucide-react for icons.
  • Use framer-motion for custom motion and tailwindcss-animate for Radix state transitions.
  • Treat shadcn/ui in this repo as a local customized base, not as a stock untouched library.