united-tattoo/docs/brownfield-architecture-public.md

11 KiB
Raw Blame History

United Tattoo — Brownfield Architecture Document (Focused: Epic C — Public Website Experience)

This document captures the CURRENT STATE of the public-facing website (home/marketing pages, artist discovery, static content). It reflects actual behavior, patterns, and technical constraints to guide improvements.

Document Scope

Focused on: homepage sections (Hero, Artists, Services, Contact), navigation and scroll behaviors, artists discovery and profiles, static informational pages (aftercare, deposit, terms, privacy, specials, gift cards).

Change Log

Date Version Description Author
2025-09-18 1.0 Initial brownfield analysis (Public website) Architect Agent

Quick Reference — Key Files and Entry Points

Pages and Sections

  • app/page.tsx (Home) → renders in-page sections:
    • components/hero-section.tsx
    • components/artists-section.tsx
    • components/services-section.tsx
    • components/contact-section.tsx
  • app/artists/page.tsx → artists listing surface
  • app/artists/[id]/page.tsx → dynamic artist portfolio page via ArtistPortfolio
  • app/contact/page.tsx → contact page wrapper (components/contact-page.tsx)
  • app/aftercare/page.tsx → aftercare (components/aftercare-page.tsx)
  • app/deposit/page.tsx → deposit (components/deposit-page.tsx)
  • app/terms/page.tsx → terms (components/terms-page.tsx)
  • app/privacy/page.tsx → privacy (components/privacy-page.tsx)
  • app/specials/page.tsx → specials (components/specials-page.tsx)
  • app/gift-cards/page.tsx → gift cards (components/gift-cards-page.tsx)

Core Components (Public)

  • components/navigation.tsx → top nav with anchor-based section links (#home, #artists, #services, #contact)
  • components/scroll-progress.tsx, components/scroll-to-section.tsx → scroll UX affordances
  • components/mobile-booking-bar.tsx (present; not necessarily mounted globally)
  • components/artist-portfolio.tsx → artist detail content (on dynamic page)
  • components/artists-section.tsx → parallax artist grid on homepage (uses static data)
  • components/artists-page-section.tsx → listing page content
  • components/footer.tsx → global footer with site links

Data

  • data/artists.ts → static artist data (names, bios, images, styles, slugs)

High-Level Architecture (Public Website Reality)

  • Home uses App Router and is composed of client components with scroll-based effects (parallax, reveal-on-intersection).
  • Navigation uses hash anchor links to scroll to in-page sections. Active section highlighting is computed via window.scroll position.
  • Artist discovery is powered by a static file (data/artists.ts) rather than D1; the homepage and artists pages read directly from this file.
  • Artist detail pages are dynamic routes at /artists/[id] and render ArtistPortfolio with the id URL param (string).
  • Static informational pages (aftercare, deposit, terms, privacy) use ShadCN components for consistent typography and layout.
  • Visuals are image-forward; images are served from public/ (images unoptimized at Next level).

Implication: The public site is primarily static and visually rich. Dynamic content (artists, availability) is not sourced from DB for public surfaces yet.


Source Tree and Composition (Relevant Extract)

app/
├── page.tsx                      # Home (sections via components)
├── artists/page.tsx              # Artists listing wrapper
├── artists/[id]/page.tsx         # Artist profile
├── contact/page.tsx              # Contact wrapper
├── aftercare/page.tsx            # Aftercare content
├── deposit/page.tsx              # Deposit content
├── terms/page.tsx                # Terms
├── privacy/page.tsx              # Privacy
├── specials/page.tsx             # Specials
├── gift-cards/page.tsx           # Gift cards
components/
├── navigation.tsx                # Top navigation (anchors)
├── hero-section.tsx              # Landing hero w/ parallax
├── artists-section.tsx           # Home artists grid w/ parallax
├── services-section.tsx          # Home services section
├── contact-section.tsx           # Home contact section
├── artists-page-section.tsx      # Full artists page section
├── artist-portfolio.tsx          # Artist detail content
├── scroll-progress.tsx           # Scroll indicator
├── scroll-to-section.tsx         # Jump/scroll utility
├── footer.tsx                    # Global footer
data/
└── artists.ts                    # Static artist directory
public/
└── artists/                      # Artist images, work images

Behavior Details and UX Patterns

Navigation (components/navigation.tsx)

  • Client component with internal state: isOpen (mobile menu), isScrolled, activeSection.
  • On scroll: toggles header styling (opaque/transparent) and updates activeSection based on element positions for ids [home, artists, services, contact].
  • Links:
    • Large screens: anchor links with active underline animation.
    • Mobile: full-screen menu with section links and a prominent “Book Now” button (links to /book).
  • Note: Anchor links are only relevant on the homepage. When navigation is used on subpages (e.g., /artists), anchors may not exist, resulting in no-op or jump to missing sections.

Hero (components/hero-section.tsx)

  • Parallax background using united-logo-full.jpg; foreground elements translate subtly on scroll.
  • Animated reveal on mount.
  • Primary CTA button “Book Consultation” presently does not link to /book (no href provided in code).

Artists Section (components/artists-section.tsx)

  • Uses IntersectionObserver for reveal animations and requestAnimationFrame for parallax updates.
  • Distributes artists into left/center/right columns for visual balance.
  • Uses static data from data/artists.ts. Buttons:
    • PORTFOLIO → /artists/{artist.id} (numeric id)
    • BOOK → /book
  • Background and portrait layering with CSS masks; heavy imagery and parallax transforms.

Artists Listing and Profiles

  • app/artists/page.tsx wraps ArtistsPageSection.
  • app/artists/[id]/page.tsx passes params.id to ArtistPortfolio.
  • Static directory usage; no D1-driven content yet.

Static Pages (aftercare, deposit, terms, privacy, contact, specials, gift cards)

  • Each page wraps respective components using ShadCN primitives.
  • Deposit page is comprehensive policy content (no live payment integration).

Technical Debt and Known Issues (REALITY)

  1. Static artist source vs DB
  • Public site uses data/artists.ts for artist info and imagery. Admin uses D1 for artists and portfolio. These diverge and will drift.
  • The dynamic profile route takes numeric id; elsewhere in the codebase and future API plans prefer UUIDs. Slug vs id inconsistencies also exist (booking form uses slug for artist selection).
  1. Navigation anchors on non-home pages
  • Navigation links are section anchors (#home, #artists, etc.). On subpages (e.g., /artists), these anchors arent present, so links will not scroll to corresponding sections. Consider routing back to home with hash or using route segments with scroll to id.
  1. CTA link missing
  • “Book Consultation” in hero-section.tsx is a button without a link to /book, reducing conversion.
  1. Image optimization
  • next.config.mjs sets images.unoptimized: true. All images served as-is from public. Heavy images + parallax effects may impact LCP/INP. No Next/Image usage nor CDN transforms configured.
  1. Accessibility and SEO gaps
  • No explicit metadata/SEO (title/description per page), OG tags, or structured data for artists.
  • Animations and parallax may affect accessibility (motion sensitivity); no reduced-motion handling observed.
  • Color contrast appears high but isnt programmatically validated.
  1. Performance considerations
  • Many large images on the homepage; no lazy loading for offscreen images in custom sections (browser handles basic lazy if configured with loading attributes; not used in plain img tags).
  • Parallax and scroll handlers are on the main thread; may affect performance on low-end devices.
  1. Link consistency (artists)
  • Homepage PORTFOLIO links to /artists/{numeric id}. The site also uses slug elsewhere. Deep-link stability may suffer if numeric ids change.
  1. Content/UX duplication across pages
  • Contact information appears in multiple places; ensure single source to avoid drift (footer/contact/aftercare/deposit pages).

  • Unify artist data source

    • Replace data/artists.ts with DB-backed data fetched via a public /api/artists (sanitized fields).
    • Prefer slugs for stable URLs (/artists/christy-lumberg) and map to DB IDs internally.
  • Fix navigation behavior on subpages

    • For anchor targets, either:
      • Route to “/” with hash (e.g., “/ #artists”) and handle scroll on mount, or
      • Create dedicated routes (/artists, /services, /contact) and update nav links accordingly.
    • Ensure active section logic degrades cleanly on non-home pages.
  • Wire primary CTAs

    • Update the Hero “Book Consultation” button to link to /book.
  • Image strategy

    • Introduce Next/Image for key imagery or configure a Cloudflare image loader.
    • Add width/height to prevent CLS; add loading="lazy" and decoding="async" where appropriate.
    • Consider responsive sources and low-quality placeholders for hero and artist tiles.
  • Accessibility and SEO

    • Provide alt text for all decorative/semantic images (artist portraits/work).
    • Respect reduced motion prefers-reduced-motion to tone down parallax.
    • Add metadata per route (title/description), OG tags, and JSON-LD for artists.
  • Performance tuning

    • Throttle scroll work, and offload heavy effects where possible.
    • Lazy-render offscreen artist tiles (virtualization or intersection-based reveal) and defer heavy imagery.
  • Link stability for profiles

    • Adopt slug routes consistently; redirect old numeric routes to slug.

Gotchas and Practical Notes

  • If you switch to API-driven artists, adjust:
    • ArtistsSection and ArtistsPageSection to fetch via /api/artists (public variant).
    • ArtistPortfolio to fetch by slug (or translate slug→id server-side).
  • Ensure any new dynamic content is cache-aware; use ISR or tag revalidation patterns to keep public pages responsive.
  • Verify the mobile navigation overlay for keyboard and screen reader accessibility.

Appendix — Useful Commands

npm run dev            # Develop locally
npm run pages:build    # Build for Cloudflare (OpenNext)
npm run preview        # Preview Cloudflare worker locally
npm run deploy         # Deploy to Cloudflare Pages
npm run test           # Unit/component tests

This document reflects the real state of the public website. It identifies where static content should migrate to data services and highlights UX/accessibility/performance improvements for a robust Epic C delivery.