# 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`: ```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/admin/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/admin/site-settings-form.tsx` - `components/admin/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/admin/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/admin/site-settings-form.tsx` - `components/admin/media-field-picker.tsx` - `rounded-lg` - examples: - `components/ui/dialog.tsx` - `components/dashboard/dashboard-layout.tsx` - `components/admin/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/admin/portfolio-categories-manager.tsx` - `components/admin/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/admin/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/admin/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/_admin/*` (canonical source), mirrored to `app/admin-internal/*` (rewrite target) and `app/root/*` (dev alias) - there is no `src/` directory in the codebase. ### Component folders - `components/ui` - primitive and near-primitive reusable controls - `components/layout` - site shell, hero, header, footer, container, backdrops - `components/admin` - 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/admin-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/admin/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/admin/site-settings-form.tsx` - `components/admin/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` does not exist `tailwind.config.ts` includes: - `./src/**/*.{js,ts,jsx,tsx,mdx}` Current project state: - there is no `src/` directory; this glob matches nothing. ## 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.