Phase 1 cleanup of the personal-site revamp. Backend/architecture untouched; changes are limited to removing unused complexity and restoring feedback. Removals - Toast system: delete react-hot-toast, Toaster, QueryToastBridge, lib/toast, the toggle/easter-egg calls, related i18n keys and the dependency. - Contact protection: remove Turnstile + per-IP rate limiting (lib/contact-guard, lib/contact-protection, admin screen, form widget, app-config wiring, nav entry, test). - Speculative specs: delete orders, products, downloads, project-inquiry. Inline feedback (replaces toast, no new deps) - Add lib/admin-feedback (withFlash/readFlash) and components/admin/admin-flash, rendered centrally by AdminDashboardShell. - Emit success/error messages for media, site-settings, portfolio, smtp, marquee and maintenance actions; pages read them via searchParams. - Contact form shows validation/delivery errors inline; success still redirects to /success. Docs - Fix stale paths in frontend-system-* (components/root -> components/admin, lib/root-navigation -> lib/admin-navigation, drop phantom src/) and remove contact-protection references from docs and CLAUDE.md. - Add docs/PHASE0_DIAGNOSIS.md (diagnosis report). Note: proxy.ts self-fetch kept intentionally; it also drives maintenance mode.
15 KiB
Frontend System Audit
1. UI libraries actually used
nextApp Router is the app shell and routing layer.tailwindcssis the styling system.@radix-ui/react-*primitives are used through local wrappers in:components/ui/accordion.tsxcomponents/ui/checkbox.tsxcomponents/ui/dialog.tsxcomponents/ui/dropdown-menu.tsxcomponents/ui/select.tsxcomponents/ui/sheet.tsx
class-variance-authorityis used for variants in:components/ui/button.tsxcomponents/ui/badge.tsxcomponents/ui/app-card.tsxcomponents/layout/container.tsx
clsx+tailwind-mergeare used throughcn()inlib/utils.ts.next-themesis used for theme switching in:components/theme-provider.tsxcomponents/theme-toggle.tsx
framer-motionis used for custom motion in:components/motion-fade.tsxcomponents/layout/site-header.tsxcomponents/layout/site-logo.tsxcomponents/layout/hero-motion-backdrop.tsxcomponents/layout/hero-atmosphere.tsxcomponents/layout/site-ambient-backdrop.tsxcomponents/layout/ascii-water-ripple.tsxcomponents/layout/animated-logo.tsxcomponents/layout/stacked-marquee-section.tsx
tailwindcss-animateis enabled intailwind.config.tsand is used by state classes indialog,dropdown-menu,select,sheet, andaccordion.
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.jsonexists and points toapp/globals.css,tailwind.config.ts, and@/components/ui.- The local primitive structure matches the common shadcn pattern:
components/ui/button.tsxcomponents/ui/card.tsxcomponents/ui/dialog.tsxcomponents/ui/dropdown-menu.tsxcomponents/ui/select.tsxcomponents/ui/sheet.tsx
lib/utils.tsexposes the standardcn()helper.
Evidence that it is partial/customized rather than stock:
- There is no runtime
shadcn-uipackage inpackage.json. - Several components are customized to project tokens:
rounded-surfacerounded-nestedshadow-cardshadow-panel
components/ui/app-card.tsxis a project-specific wrapper overCard.components/ui/tabs.tsxis a custom React context implementation, not a Radix wrapper.- Usage is selective. Import counts in the current codebase show:
app-card:23card:26button:19dialog:1dropdown-menu:1sheet:1table:1tabs: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-layoutmax-w-narrowmax-w-widemax-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.tsxcomponents/layout/site-header.tsxcomponents/layout/home-hero.tsxcomponents/layout/page-hero.tsxapp/[locale]/(site)/contact/page.tsx
Patterns:
relative flex min-h-screen flex-col overflow-hiddenmax-w-[72rem] px-4 sm:px-6 lg:px-8- hero sections with:
pt-24sm:pt-28lg:pt-28pb-10lg:pb-12lg:pb-16
Admin layout pattern
Repeated in:
components/dashboard/dashboard-layout.tsxcomponents/admin/root-dashboard-shell.tsx- many
app/root/*/page.tsx
Patterns:
min-h-screen bg-muted/30grid 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.tsxcomponents/admin/portfolio-project-form.tsxapp/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-surfacerounded-nestedrounded-pill
Repeated radius class patterns
Most repeated token usage:
rounded-surfacecomponents/ui/card.tsxcomponents/ui/app-card.tsxcomponents/ui/accordion.tsxcomponents/ui/dropdown-menu.tsxcomponents/ui/select.tsxcomponents/ui/tabs.tsx
rounded-nestedcomponents/ui/button.tsxcomponents/ui/input.tsxcomponents/ui/textarea.tsxcomponents/ui/select.tsxcomponents/dashboard/sidebar.tsxcomponents/admin/contact-protection-form.tsx
rounded-[var(--radius-pill)]components/layout/site-header.tsxcomponents/layout/floating-preferences.tsx
rounded-full- used heavily for decorative circles and icon pills in site chrome:
components/layout/site-ambient-backdrop.tsxcomponents/layout/hero-atmosphere.tsxcomponents/layout/ascii-water-ripple.tsx
- used heavily for decorative circles and icon pills in site chrome:
Non-token radius values also present
rounded-md- several content blocks and previews
- examples:
app/root/page.tsxcomponents/admin/site-settings-form.tsxcomponents/admin/media-field-picker.tsx
rounded-lg- examples:
components/ui/dialog.tsxcomponents/dashboard/dashboard-layout.tsxcomponents/admin/portfolio-project-form.tsx
- examples:
6. Repeated spacing patterns found in code
Global repeated spacing
Most repeated stack and gap patterns:
space-y-6gap-6space-y-2space-y-3p-6p-4px-4 py-3px-4 py-4px-3 py-2
Core primitive spacing
CardHeader:flex flex-col gap-1.5 p-6components/ui/card.tsx
CardContent:p-6 pt-0components/ui/card.tsx
Buttonsizes:default:h-10 px-4 py-2sm:h-9 px-3lg:h-11 px-6icon:h-10 w-10components/ui/button.tsx
InputandTextarea:px-3 py-2components/ui/input.tsxcomponents/ui/textarea.tsx
SelectTrigger:px-3 py-2components/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-8components/layout/app-shell.tsx
- hero wrappers:
pt-24sm:pt-28lg: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:
backgroundforegroundcardpopoverprimarysecondarymutedaccentdestructiveborderborder-stronginputring
- custom semantic:
surface-1surface-2surface-3surface-inversebrand-primarybrand-secondarystatus-successstatus-success-softstatus-warningstatus-warning-softsidebar-*hero-*
Repeated utility combinations
Very common combinations:
border border-border/80 bg-card text-card-foreground shadow-cardcomponents/ui/card.tsx
border border-input bg-backgroundcomponents/ui/input.tsxcomponents/ui/select.tsxcomponents/admin/portfolio-categories-manager.tsxcomponents/admin/portfolio-projects-overview.tsx
bg-primary text-primary-foreground- active nav and badges/buttons:
components/ui/button.tsxcomponents/ui/badge.tsxcomponents/dashboard/sidebar.tsxcomponents/admin/portfolio-subnav.tsxapp/[locale]/(site)/portfolio/page.tsx
- active nav and badges/buttons:
text-muted-foreground- repeated throughout forms, cards, table headers, descriptions
hover:bg-accent- repeated in
button,dropdown-menu, select items, and selection cards
- repeated in
bg-muted/40andbg-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/6bg-white/24bg-white/32text-[hsl(var(--hero-ink)/0.76)]- custom shadow values with raw
rgba(...)
Examples:
components/layout/site-header.tsxcomponents/layout/floating-preferences.tsxapp/[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.tsxcomponents/layout/animated-logo.tsx
- ambient / backdrop motion:
components/layout/hero-motion-backdrop.tsxcomponents/layout/hero-atmosphere.tsxcomponents/layout/site-ambient-backdrop.tsxcomponents/layout/ascii-water-ripple.tsxcomponents/layout/stacked-marquee-section.tsx
tailwindcss-animate
Used through state classes for Radix-style overlays and disclosures:
data-[state=open]:animate-indata-[state=closed]:animate-outfade-in-0zoom-in-95slide-in-from-top-2animate-accordion-downanimate-accordion-up
Files:
components/ui/dialog.tsxcomponents/ui/dropdown-menu.tsxcomponents/ui/select.tsxcomponents/ui/sheet.tsxcomponents/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.tsxcomponents/layout/site-header.tsxcomponents/theme-toggle.tsxapp/root/page.tsxapp/[locale]/(site)/page.tsx
No second React icon library is present in package.json.
10. Component architecture currently used
Routing structure
appis the real route layer.- public site routes live under:
app/[locale]/(site)/*
- admin routes live under:
app/_admin/*(canonical source), mirrored toapp/admin-internal/*(rewrite target) andapp/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.tscn()
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
- wraps
components/theme-toggle.tsx- wraps
Button
- wraps
components/layout/locale-toggle.tsx- uses
ButtonandDropdownMenu
- uses
components/admin/form-save-button.tsx- uses
Button
- uses
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-cardbg-backgroundborder-inputshadow-cardrounded-surface
But public chrome often bypasses them with raw arbitrary values:
components/layout/site-header.tsxcomponents/layout/floating-preferences.tsxapp/[locale]/(site)/page.tsx
Examples:
bg-white/24border-black/6shadow-[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-mdrounded-lgrounded-full
Examples:
components/ui/dialog.tsxcomponents/dashboard/dashboard-layout.tsxcomponents/admin/site-settings-form.tsxcomponents/admin/portfolio-project-form.tsx
Some primitives follow the local system, some keep stock shadcn-style values
- tokenized:
components/ui/card.tsxcomponents/ui/button.tsxcomponents/ui/input.tsxcomponents/ui/select.tsx
- less tokenized:
components/ui/dialog.tsxsm:rounded-lgshadow-lg
- less tokenized:
components/ui/sheet.tsxshadow-lg
AppCard surface levels are not all visually distinct
In components/ui/app-card.tsx:
level: 1andlevel: 2both 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/uibefore introducing direct Radix usage. - Use
cn()fromlib/utils.tsfor class composition. - Use
cva()for reusable variant APIs where the project already does that:ButtonBadgeAppCardContainer
- For shared admin surfaces, prefer tokenized classes already present:
rounded-surfacerounded-nestedbg-cardbg-backgroundborder-inputborder-border/80shadow-cardshadow-panel
- For main width constraints, follow the existing container system:
Containermax-w-layoutmax-w-adminpx-4 sm:px-6 lg:px-8
- For admin pages and forms, the repeated layout rhythm is:
space-y-6gap-6space-y-2p-6p-4
- For public site hero/layout sections, the repeated shell is:
hero-surfacemax-w-[72rem]px-4 sm:px-6 lg:px-8pt-24 sm:pt-28
- Use
lucide-reactfor icons. - Use
framer-motionfor custom motion andtailwindcss-animatefor Radix state transitions. - Treat
shadcn/uiin this repo as a local customized base, not as a stock untouched library.