diff --git a/.github/prompts/audit-quality.prompt.md b/.github/prompts/audit-quality.prompt.md
index 4f589e3..10e125c 100644
--- a/.github/prompts/audit-quality.prompt.md
+++ b/.github/prompts/audit-quality.prompt.md
@@ -166,16 +166,22 @@ Act as a **Principal Code Reviewer, Security Auditor, and Refactoring Architect*
**Objective:** Ensure compliance with applicable data protection and privacy regulations.
+Not all regulations apply to every codebase. Determine which regulations are in scope based on the system's data subjects, geography, data types, and regulated activities. Only perform compliance checks for regulations that apply, and explicitly state why any listed regulation is out of scope.
+
Check compliance with:
- **United States:** HIPAA (Health Insurance Portability and Accountability Act)
+ - Applies when the system handles protected health information (PHI) for a covered entity or business associate.
- **European Union & Ireland:** GDPR (General Data Protection Regulation)
+ - Applies when the system processes personal data, especially if it profiles users, tracks behavior, or makes decisions that affect individuals.
- **Canada (Federal):** PIPEDA (Personal Information Protection and Electronic Documents Act)
+ - Applies when the system processes personal information for commercial activities in the private sector.
- **Canada - Ontario (Provincial):** PHIPA (Personal Health Information Protection Act)
+ - Applies when the system handles personal health information for a health information custodian or their agent.
- **South Korea:** PIPA (Personal Information Protection Act)
-- **Vietnam:** PDPL (Personal Data Protection Law)
+ - Applies when the system processes personal information, including identifiers, contact data, or behavioral data.
-Verify:
+For each applicable regulation, verify:
- Right to access, rectification, erasure, and data portability
- Breach notification procedures
diff --git a/docs/architecture/app-directory.md b/docs/architecture/app-directory.md
index e20424c..bc95328 100644
--- a/docs/architecture/app-directory.md
+++ b/docs/architecture/app-directory.md
@@ -1,28 +1,23 @@
# App Directory (Next.js)
-This document explains the Next.js App Router directory structure and implementation in the Alexander Sullivan's Portfolio project.
-
-## Overview
-
-The project uses Next.js 16+ with the App Router architecture located in [`src/app/`](../../src/app/). This modern routing system uses file-system based routing with server and client components.
-
-## Directory Structure
-
-```text
-src/app/
-├── layout.tsx # Root layout with metadata
-├── page.tsx # Home page component
-├── manifest.ts # PWA manifest configuration
-├── robots.ts # SEO robots.txt generator
-├── error.tsx # Error boundary
-├── global-error.tsx # Global error boundary
-├── loading.tsx # Loading UI
-├── not-found.tsx # 404 page
-├── favicon.ico # Site favicon
-└── sw.js/ # Service worker route handler
-```
+The portfolio uses Next.js App Router, where file names in [src/app/](../../src/app/) define routes and special behaviors. This follows Next.js convention-based routing rather than explicit route configuration.
+
+## App Router Conventions
+
+**File-Based Routing:** Next.js maps file names to functionality:
+
+- `layout.tsx` — Wraps all child routes with shared UI and metadata
+- `page.tsx` — Defines the `/` route content
+- `error.tsx` — Catches errors in route segments
+- `global-error.tsx` — Catches errors in root layout
+- `not-found.tsx` — Handles 404 pages
+- `loading.tsx` — Displays while routes load
+- `manifest.ts` — Generates PWA manifest `/manifest.webmanifest`
+- `robots.ts` — Generates `/robots.txt` for SEO
+
+**Server by Default:** Components in [src/app/](../../src/app/) are React Server Components unless marked with `'use client'`. This minimizes client JavaScript.
-## Architecture Pattern
+## Component Hierarchy
```mermaid
flowchart TD
@@ -36,276 +31,62 @@ flowchart TD
Page -->|Renders| Banner
Page -->|Renders| Projects[ProjectsGrid]
Page -->|Renders| Pubs[Publications]
- Page -->|Initializes| Firebase
- Page -->|Registers| SW[Service Worker]
-```
-
-## Root Layout
-
-Location: [`src/app/layout.tsx`](../../src/app/layout.tsx)
-
-The root layout defines metadata, global styles, and wraps all pages with the GeneralLayout component.
-
-### Key Features
-
-1. **Metadata Configuration:** SEO, OpenGraph, Twitter Cards, and PWA manifest
-2. **Global Styles:** Imports global SCSS styles
-3. **Analytics Integration:** Vercel Speed Insights
-4. **Service Worker Registration:** Client component for PWA support
-5. **Theme Configuration:** Viewport settings and theme color
-
-### Metadata Structure
-
-```typescript
-export const metadata: Metadata = {
- title: {
- template: `%s | ${metadataValues.title}`,
- default: metadataValues.title,
- },
- description: metadataValues.description,
- applicationName: metadataValues.title,
- referrer: 'origin',
- keywords: seoKeywords, // From src/data/keywords.ts
- category: 'technology',
- authors: [{ name: metadataValues.name, url: metadataValues.url }],
- creator: metadataValues.name,
- publisher: metadataValues.name,
- openGraph: {
- /* OpenGraph config */
- },
- twitter: {
- /* Twitter Card config */
- },
- manifest: '/manifest.webmanifest',
- // ... additional metadata
-};
-```
-
-### Viewport Configuration
-
-```typescript
-export const viewport: Viewport = {
- themeColor: '#131518',
- width: 'device-width',
- initialScale: 1,
- minimumScale: 1,
- maximumScale: 5,
- userScalable: true,
-};
-```
-
-## Home Page
-
-Location: [`src/app/page.tsx`](../../src/app/page.tsx)
-
-The home page is a client component that initializes services and renders main sections.
-
-### Initialization Flow
-
-```mermaid
-sequenceDiagram
- participant Page
- participant Firebase
- participant Console
- participant SW
- participant User
-
- Page->>Firebase: init()
- Page->>Console: debounceConsoleLogLogo()
- Page->>SW: navigator.serviceWorker.register('/sw.js')
- SW-->>Page: Registration complete
- Page->>User: Render Banner
- Page->>User: Render ProjectsGrid
- Page->>User: Render Publications
```
-### Component Structure
-
-```typescript
-'use client';
-
-export default function Home() {
- useEffect(() => {
- init(); // Initialize Firebase
- debounceConsoleLogLogo(); // Log ASCII art to console
-
- // Register service worker
- if (typeof navigator !== 'undefined' && 'serviceWorker' in navigator) {
- navigator.serviceWorker.register('/sw.js').catch(function (err) {
- console.error('Service Worker registration failed: ', err);
- });
- }
- }, []);
-
- return (
-
-
-
-
-
- );
-}
-```
+The root layout renders GeneralLayout which provides navigation, footer, background, and cookie consent for all pages.
-## Special Route Handlers
+## Root Layout
-### Manifest (`manifest.ts`)
-
-Generates the PWA manifest dynamically:
-
-```typescript
-import type { MetadataRoute } from 'next';
-
-export default function manifest(): MetadataRoute.Manifest {
- return {
- name: "Alexander Sullivan's Portfolio",
- short_name: "Alexander Sullivan's Portfolio",
- icons: [
- { src: '/icon/android-chrome-192x192.png', sizes: '192x192', type: 'image/png' },
- // ... more icons
- ],
- theme_color: '#131518',
- background_color: '#131518',
- display: 'standalone',
- start_url: '/',
- };
-}
-```
+**Metadata Configuration:** The layout exports a metadata object with SEO tags, OpenGraph, Twitter Cards, and PWA manifest path. Keywords are imported from [src/data/keywords.ts](../../src/data/keywords.ts).
-### Robots (`robots.ts`)
+**Viewport Setup:** Defines theme color (#131518), responsive scaling, and device width settings for mobile browsers.
-Generates robots.txt for SEO:
+**GeneralLayout:** Wraps children with [GeneralLayout](../../src/layouts/GeneralLayout.tsx) which provides navigation, footer, stars background, and cookie consent.
-```typescript
-import type { MetadataRoute } from 'next';
+**Global Styles:** Imports [globals.scss](../../src/styles/globals.scss) for application-wide CSS.
-export default function robots(): MetadataRoute.Robots {
- return {
- rules: {
- userAgent: '*',
- allow: '/',
- },
- sitemap: 'https://alexjsully.me/sitemap.xml',
- };
-}
-```
+**Analytics:** Includes Vercel SpeedInsights for performance tracking.
-## Error Handling
+Implementation: [src/app/layout.tsx](../../src/app/layout.tsx)
-### Error Boundary (`error.tsx`)
-
-Catches errors in the app and displays a fallback UI:
-
-```typescript
-'use client';
-
-export default function Error({
- error,
- reset,
-}: {
- error: Error & { digest?: string };
- reset: () => void;
-}) {
- return (
-
-
Something went wrong!
-
-
- );
-}
-```
+## Home Page
-### Global Error Boundary (`global-error.tsx`)
-
-Catches errors at the root level (even in layout):
-
-```typescript
-'use client';
-
-export default function GlobalError({
- error,
- reset,
-}: {
- error: Error & { digest?: string };
- reset: () => void;
-}) {
- return (
-
-
-
Something went wrong!
-
-
-
- );
-}
-```
+The home page ([src/app/page.tsx](../../src/app/page.tsx)) is a client component (`'use client'`) that initializes services on mount:
-## Loading States
+**Firebase Initialization:** Calls `init()` from [src/configs/firebase.ts](../../src/configs/firebase.ts) to start analytics and performance tracking.
-Location: [`src/app/loading.tsx`](../../src/app/loading.tsx)
+**Console Logo:** Debounced ASCII art logged to browser console via [ascii helper](../../src/helpers/ascii.ts).
-Displays a loading UI while the page is being rendered:
+**Service Worker Registration:** Registers `/sw.js` for PWA offline support. Registration runs once on page load.
-```typescript
-import { CircularProgress } from '@mui/material';
+**Content Rendering:** Displays Banner, ProjectsGrid, and Publications components in vertical stack.
-export default function Loading() {
- return (
-
-
-
- );
-}
-```
+Implementation: [src/app/page.tsx](../../src/app/page.tsx)
-The container uses inline styles with flexbox centering: `display: 'flex'`, `justifyContent: 'center'`, and `padding: '2rem'`.
+## Special Route Handlers
-## 404 Not Found
+**PWA Manifest** ([src/app/manifest.ts](../../src/app/manifest.ts)) — Generates `/manifest.webmanifest` with app name, icons, theme colors, and display mode. See [PWA Documentation](./pwa.md).
-Location: [`src/app/not-found.tsx`](../../src/app/not-found.tsx)
+**Robots.txt** ([src/app/robots.ts](../../src/app/robots.ts)) — Generates `/robots.txt` allowing all crawlers with sitemap URL for SEO.
-Custom 404 page with navigation back to home:
+## Error Handling
-```typescript
-export default function NotFound() {
- const pathname = usePathname();
+**Error Boundary** ([src/app/error.tsx](../../src/app/error.tsx)) — Catches errors in route segments and displays fallback UI with reset button.
- return (
-
- 404
- {pathname}?! What is that?!
-
-
-
-
- );
-}
-```
+**Global Error** ([src/app/global-error.tsx](../../src/app/global-error.tsx)) — Catches errors in root layout, including its own `` and `` tags since layout errors prevent normal rendering.
-## Best Practices
+Both error boundaries are client components that accept `error` and `reset` props.
-1. **Server vs Client Components:** Use server components by default, mark client components with `'use client'`
-2. **Metadata:** Define metadata in layout.tsx for SEO benefits
-3. **Error Boundaries:** Implement error.tsx for graceful error handling
-4. **Loading States:** Use loading.tsx for better UX during navigation
-5. **TypeScript:** Use Next.js types like `MetadataRoute`, `Metadata`, and `Viewport`
-6. **Accessibility:** Include proper ARIA labels on all components
+## Loading & 404
-## Testing
+**Loading UI** ([src/app/loading.tsx](../../src/app/loading.tsx)) — Shows MUI CircularProgress spinner centered on screen while routes load.
-Test files are located alongside their components:
+**Not Found** ([src/app/not-found.tsx](../../src/app/not-found.tsx)) — Custom 404 page displaying pathname and navigation button back to home.
-- `loading.test.tsx` - Tests loading component
-- `not-found.test.tsx` - Tests 404 page
+Implementation: [src/app/loading.tsx](../../src/app/loading.tsx), [src/app/not-found.tsx](../../src/app/not-found.tsx)
## Related Documentation
-- [Architecture Overview](./index.md)
-- [Layouts](./layouts.md)
-- [Components](./components/index.md)
-- [PWA Documentation](./pwa.md)
-- [Next.js App Router Documentation](https://nextjs.org/docs/app)
-
----
-
-💡 **Tip:** The App Router automatically handles routing based on the file structure. Any `page.tsx` file becomes a route, and `layout.tsx` files wrap their children routes.
+- [Architecture Overview](./index.md) — System architecture
+- [Layouts Documentation](./layouts.md) — GeneralLayout details
+- [PWA Documentation](./pwa.md) — Service worker and manifest
diff --git a/docs/architecture/components/avatar.md b/docs/architecture/components/avatar.md
index b1aea2c..0801d67 100644
--- a/docs/architecture/components/avatar.md
+++ b/docs/architecture/components/avatar.md
@@ -1,232 +1,91 @@
# Banner & Avatar Components
-This document details the Banner and Avatar components that create the introductory section of the portfolio.
-
-## Overview
-
-The Banner component displays the header section with profile information and an animated avatar that includes an Easter egg feature.
-
-## Component Structure
-
-```mermaid
-flowchart TD
- Banner[Banner Component] -->|Contains| Avatar[Avatar Component]
- Banner -->|Displays| Title[Title & Subtitle]
- Avatar -->|Hover| Sneeze[Sneeze Animation]
- Avatar -->|6x Sneeze| AAAAHHHH[Easter Egg Trigger]
- AAAAHHHH -->|Calls| Helper[aaaahhhh helper]
- Helper -->|Transforms| Page[Entire Page]
-```
+The Banner component displays the profile header with an animated avatar that includes interactive sneeze animations and a hidden Easter egg.
## Banner Component
-Location: [`src/components/banner/Banner.tsx`](../../src/components/banner/Banner.tsx)
+The Banner ([src/components/banner/Banner.tsx](../../src/components/banner/Banner.tsx)) is a container component that renders:
-**Purpose:** Displays the introductory section with profile image and text.
+- Avatar component with interactive animations
+- Name title split into hoverable characters (green glow on hover)
+- Subtitle displaying role ("Software Developer & Bioinformatician")
+- Responsive layout using MUI Stack for vertical alignment
-**Key Features:**
+The component is server-side rendered by default with no client-side state.
-- Responsive layout using MUI Grid/Stack
-- Profile avatar with animations
-- Title and subtitle text
-- Accessibility attributes
-
-**Usage Example:**
-
-```tsx
-import Banner from '@components/banner/Banner';
-
-;
-```
+Implementation: [src/components/banner/Banner.tsx](../../src/components/banner/Banner.tsx)
## Avatar Component
-Location: [`src/components/banner/Avatar.tsx`](../../src/components/banner/Avatar.tsx)
-
-**Purpose:** Displays an animated profile picture with an interactive sneeze animation and Easter egg.
+The Avatar ([src/components/banner/Avatar.tsx](../../src/components/banner/Avatar.tsx)) is a client component (`'use client'`) that displays an interactive profile image.
-### Key Features
+### Sneeze Animation Behavior
-1. **Sneeze Animation:** Triggered every 5 hovers (`THRESHOLDS.SNEEZE_TRIGGER_INTERVAL`)
-2. **Easter Egg:** After 6 sneezes (`THRESHOLDS.AAAAHHHH_TRIGGER_COUNT`), triggers the "AAAAHHHH" transformation
-3. **Analytics Tracking:** Logs user interactions
-4. **Image Optimization:** Uses Next.js Image component
-5. **Memory Management:** Proper cleanup of debounced functions
+The avatar triggers a multi-stage sneeze animation based on hover interactions:
-### State Management
+1. **Hover Counting:** Each hover/click increments a counter (debounced by 100ms)
+2. **Sneeze Trigger:** Every 5th hover triggers a 3-stage sneeze animation
+3. **Animation Lock:** While sneezing, additional hovers are ignored
+4. **Image Sequence:** Avatar cycles through 4 images (default → sneeze_1 → sneeze_2 → sneeze_3 → default)
+5. **Timing:** Stage transitions use constants (500ms → 300ms → 1000ms)
-```typescript
-const hoverProfilePic = useRef(0); // Hover count
-const totalSneeze = useRef(0); // Total sneezes
-const sneezing = useRef(false); // Animation lock
-const [image, setImage] = useState(imageList['default']); // Current image
-```
-
-### Image Assets
-
-```typescript
-const imageList = {
- default: '/images/drawn/profile_pic_drawn.webp',
- sneeze_1: '/images/drawn/profile_pic_drawn_2.webp',
- sneeze_2: '/images/drawn/profile_pic_drawn_3.webp',
- sneeze_3: '/images/drawn/profile_pic_drawn_4.webp',
-};
-```
-
-### Sneeze Animation Sequence
-
-The sneeze animation uses constants from `@constants/index` for timing:
+After each sneeze, the component logs a `trigger_sneeze` analytics event via Firebase.
-```typescript
-import { ANIMATIONS, THRESHOLDS } from '@constants/index';
+### Easter Egg: AAAAHHHH Transformation
-handleTriggerSneeze() {
- hoverProfilePic.current += 1;
+After the 6th sneeze, instead of animating, the avatar calls the [`aaaahhhh()`](../../src/helpers/aaaahhhh.ts) helper function which:
- if (hoverProfilePic.current % THRESHOLDS.SNEEZE_TRIGGER_INTERVAL === 0 && !sneezing.current) {
- totalSneeze.current += 1;
+- Transforms all text on the page to "AAAAHHHH" format (first half → 'A', second half → 'H')
+- Replaces all images with `/images/aaaahhhh/aaaahhhh.webp`
+- Changes background images including the stars
+- Sets page title to "Alexander Sullivan's AAAAHHHHH"
+- Logs a `trigger_aaaahhhh` analytics event
- if (totalSneeze.current >= THRESHOLDS.AAAAHHHH_TRIGGER_COUNT) {
- logAnalyticsEvent('trigger_aaaahhhh', {...});
- aaaahhhh(); // Transform entire page
- } else {
- sneezing.current = true;
-
- // Animate through sneeze sequence using constants
- setImage('sneeze_1');
- setTimeout(() => {
- setImage('sneeze_2');
-
- setTimeout(() => {
- setImage('sneeze_3');
-
- setTimeout(() => {
- setImage('default');
- sneezing.current = false;
- }, ANIMATIONS.SNEEZE_STAGE_3);
- }, ANIMATIONS.SNEEZE_STAGE_2);
- }, ANIMATIONS.SNEEZE_STAGE_1);
-
- logAnalyticsEvent('trigger_sneeze', {...});
- }
- }
-}
-```
+This creates a playful full-page transformation. See [AAAAHHHH Helper](../helpers.md#aaaahhhh-easter-egg-helper) for implementation details.
-**Animation Timing:**
+### State Management Strategy
-- Stage 1: 500ms (`ANIMATIONS.SNEEZE_STAGE_1`)
-- Stage 2: 300ms (`ANIMATIONS.SNEEZE_STAGE_2`)
-- Stage 3: 1000ms (`ANIMATIONS.SNEEZE_STAGE_3`)
+The component uses React refs for counters (hover count, sneeze count, animation lock) to avoid unnecessary re-renders. Only the current image is stored in React state, triggering re-renders for visual updates.
-### AAAAHHHH Easter Egg
+This pattern keeps the component performant by limiting state updates to what affects the DOM.
-When the avatar sneezes 6 times, it triggers [`aaaahhhh()`](../../src/helpers/aaaahhhh.ts) which:
+### Memory Management
-1. Converts all text to "AAAAHHHH" format
-2. Replaces all images with the AAAAHHHH image
-3. Changes background images
-4. Creates a playful page transformation
-
-See [AAAAHHHH Helper Documentation](../helpers.md#aaaahhhh-helper) for details.
-
-### Analytics Integration
-
-The component logs two event types:
-
-```typescript
-// Sneeze event
-logAnalyticsEvent('trigger_sneeze', {
- name: 'trigger_sneeze',
- type: 'hover',
-});
-
-// Easter egg event
-logAnalyticsEvent('trigger_aaaahhhh', {
- name: 'trigger_aaaahhhh',
- type: 'hover',
-});
-```
-
-### Usage Example
-
-```tsx
-import Avatar from '@components/banner/Avatar';
-
-; // No props required
-```
-
-### Performance Considerations
-
-- **Debounced Hover:** Uses `lodash.debounce` with `DELAYS.AVATAR_SNEEZE_DEBOUNCE` (100ms) to prevent rapid triggering
-- **Ref-based State:** Uses refs for counters to avoid unnecessary re-renders
-- **Animation Lock:** Prevents overlapping sneeze animations
-- **Image Preloading:** All sneeze images should be optimized as WebP
-- **Cleanup:** Cancels debounce on component unmount to prevent memory leaks
-
-```typescript
-import { DELAYS } from '@constants/index';
-
-const debounceSneeze = debounce(handleTriggerSneeze, DELAYS.AVATAR_SNEEZE_DEBOUNCE);
-
-// Cleanup debounce on unmount
-useEffect(() => {
- return () => {
- debounceSneeze.cancel();
- };
-}, [debounceSneeze]);
-```
+The component debounces hover interactions using `lodash.debounce` and cancels the debounce function on unmount via `useEffect` cleanup. This prevents memory leaks from pending callbacks after component removal.
### Accessibility
-The Avatar component uses the Next.js `Image` component with these accessibility attributes:
+The avatar uses Next.js `Image` component with:
-- `data-testid='profile_pic'` - Testing identifier
-- `aria-label='Profile Picture for Alexander Sullivan'` - Screen reader label
-- `alt='Alexander Sullivan head drawn and stylized'` - Descriptive alt text
-- `width={500}` and `height={500}` - Explicit dimensions for Next.js optimization
-- `priority` - Optimizes loading for above-the-fold content
-- `onClick={debounceSneeze}` - Click interaction handler (in addition to mouse enter)
-- `onMouseEnter={debounceSneeze}` - Hover interaction handler
-- `style` prop with `cursor: 'pointer'` via borderRadius and positioning
+- `priority` flag for above-the-fold loading
+- `alt` text describing the image
+- `aria-label` for screen readers
+- Explicit width/height for layout stability
+- Interactive `onClick` and `onMouseEnter` handlers
-## Component Interaction
+Implementation: [src/components/banner/Avatar.tsx](../../src/components/banner/Avatar.tsx)
+
+## Component Interaction Flow
```mermaid
sequenceDiagram
participant User
participant Avatar
- participant State
participant Helper
participant Analytics
User->>Avatar: Hover (5th time)
- Avatar->>State: Increment counter
- State->>Avatar: Trigger sneeze
- Avatar->>Avatar: Animate sneeze sequence
+ Avatar->>Avatar: Trigger sneeze animation
Avatar->>Analytics: Log sneeze event
- User->>Avatar: Hover (6th sneeze)
+ User->>Avatar: Hover (30th time, 6th sneeze)
Avatar->>Helper: Call aaaahhhh()
- Helper->>Helper: Transform page
+ Helper->>Helper: Transform entire page
Avatar->>Analytics: Log AAAAHHHH event
```
-## Testing
-
-Test file: [`src/components/banner/Avatar.test.tsx`](../../src/components/banner/Avatar.test.tsx)
-
-**Test Coverage:**
-
-- Component renders
-- Image changes on hover
-- Sneeze animation triggers
-- Easter egg activation
-- Analytics event logging
-
## Related Documentation
-- [Helpers: AAAAHHHH](../helpers.md#aaaahhhh-easter-egg-helper)
-- [Components Overview](./index.md)
-- [Firebase Analytics](../configs.md)
-- [Constants](../constants.md)
+- [Helpers: AAAAHHHH](../helpers.md#aaaahhhh-easter-egg-helper) — Easter egg implementation
+- [Constants](../constants.md) — Timing and threshold values
+- [Firebase Analytics](../configs.md) — Event tracking
diff --git a/docs/architecture/constants.md b/docs/architecture/constants.md
index e65b8e3..7b0c488 100644
--- a/docs/architecture/constants.md
+++ b/docs/architecture/constants.md
@@ -1,150 +1,62 @@
# Constants Module
-## Overview
+The constants module centralizes timing, thresholds, and configuration values used throughout the application. These values control interactive behaviors, network detection, and animations.
-The `constants` module provides centralized application-wide configuration values, thresholds, and magic numbers used throughout the codebase. This approach improves maintainability, testability, and makes it easier to tune application behavior.
+## Why Centralize Constants?
-## Location
+Using a single source of truth for magic numbers provides:
-**Path:** `src/constants/index.ts`
+- **Easier Tuning:** Change behavior across the app by editing one file
+- **Testability:** Constants can be imported and verified in tests
+- **Maintainability:** No hunting through components to find timing values
+- **Documentation:** Descriptive names make values self-explanatory
## Module Exports
-### `DELAYS`
-
-Time delays in milliseconds for various debounce and timing operations.
-
-```typescript
-export const DELAYS = {
- /** Debounce delay for console logo (1000ms) */
- CONSOLE_LOGO_DEBOUNCE: 1000,
-
- /** Delay before showing project video on hover (1000ms) */
- PROJECT_HOVER_VIDEO: 1000,
+The module exports four const objects, each grouping related values:
- /** Delay for avatar sneeze debounce (100ms) */
- AVATAR_SNEEZE_DEBOUNCE: 100,
-
- /** Initial delay for force star animation (1000ms) */
- STAR_ANIMATION_INITIAL: 1000,
-} as const;
-```
-
-**Usage Example:**
+### `DELAYS`
-```typescript
-import { DELAYS } from '@constants/index';
+Debounce delays and timing values in milliseconds:
-const debouncedFunc = debounce(handler, DELAYS.AVATAR_SNEEZE_DEBOUNCE);
-```
+- `CONSOLE_LOGO_DEBOUNCE` (1000ms) — Prevents duplicate ASCII logo prints in console
+- `PROJECT_HOVER_VIDEO` (1000ms) — Delay before showing video on project card hover
+- `AVATAR_SNEEZE_DEBOUNCE` (100ms) — Debounce for avatar hover interactions
+- `STAR_ANIMATION_INITIAL` (1000ms) — Initial delay for forced star shooting animations
----
+**Usage:** Import to control debouncing and timing in components.
### `THRESHOLDS`
-Trigger thresholds for interactive features and animations.
+Trigger thresholds for interactive features:
-```typescript
-export const THRESHOLDS = {
- /** Number of hovers before triggering sneeze (5) */
- SNEEZE_TRIGGER_INTERVAL: 5,
+- `SNEEZE_TRIGGER_INTERVAL` (5) — Number of hovers before avatar sneeze animation
+- `AAAAHHHH_TRIGGER_COUNT` (6) — Number of sneezes before Easter egg activation
+- `MIN_STARS_FOR_ANIMATION` (15) — Minimum stars required before forcing animation
- /** Total sneezes before triggering aaaahhhh easter egg (6) */
- AAAAHHHH_TRIGGER_COUNT: 6,
-
- /** Minimum number of stars before forcing animation (15) */
- MIN_STARS_FOR_ANIMATION: 15,
-} as const;
-```
-
-**Usage Example:**
-
-```typescript
-import { THRESHOLDS } from '@constants/index';
-
-if (hoverCount % THRESHOLDS.SNEEZE_TRIGGER_INTERVAL === 0) {
- triggerSneeze();
-}
-```
-
----
+**Usage:** Import to control when interactions trigger animations or Easter eggs.
### `NETWORK`
-Network performance thresholds used to detect slow connections and adapt behavior accordingly.
-
-```typescript
-export const NETWORK = {
- /** Maximum downlink speed (Mbps) to be considered slow (1.5) */
- SLOW_DOWNLINK_THRESHOLD: 1.5,
-
- /** Maximum RTT (ms) to be considered fast (100) */
- FAST_RTT_THRESHOLD: 100,
+Network performance thresholds for adaptive loading:
- /** Network types considered slow */
- SLOW_NETWORK_TYPES: ['slow-2g', '2g', '3g'] as const,
-} as const;
-```
+- `SLOW_DOWNLINK_THRESHOLD` (1.5 Mbps) — Maximum speed considered slow
+- `FAST_RTT_THRESHOLD` (100ms) — Maximum round-trip time considered fast
+- `SLOW_NETWORK_TYPES` (['slow-2g', '2g', '3g']) — Network types always considered slow
-**Usage Example:**
-
-```typescript
-import { NETWORK } from '@constants/index';
-
-const isSlow = connection.downlink < NETWORK.SLOW_DOWNLINK_THRESHOLD;
-```
-
----
+**Usage:** Import in [isNetworkFast()](../../src/util/isNetworkFast.ts) to determine whether to autoplay videos.
### `ANIMATIONS`
-Animation duration values in milliseconds for multi-stage animations.
-
-```typescript
-export const ANIMATIONS = {
- /** Avatar sneeze animation stage 1 (500ms) */
- SNEEZE_STAGE_1: 500,
-
- /** Avatar sneeze animation stage 2 (300ms) */
- SNEEZE_STAGE_2: 300,
-
- /** Avatar sneeze animation stage 3 (1000ms) */
- SNEEZE_STAGE_3: 1000,
-} as const;
-```
-
-**Usage Example:**
-
-```typescript
-import { ANIMATIONS } from '@constants/index';
-
-setTimeout(() => {
- setImage('sneeze_2');
-}, ANIMATIONS.SNEEZE_STAGE_1);
-```
-
----
-
-## Design Rationale
-
-### Why Centralize Constants?
-
-1. **Single Source of Truth:** All timing and threshold values are defined in one place
-2. **Easier Tuning:** Adjust application behavior by changing values in one file
-3. **Better Testing:** Constants can be imported and verified in tests
-4. **Type Safety:** Using `as const` provides literal type inference
-5. **Documentation:** Constants are self-documenting with descriptive names
-
-### Best Practices
+Multi-stage animation durations in milliseconds:
-- **Always use constants instead of magic numbers** in application code
-- **Document what each constant represents** using JSDoc comments
-- **Group related constants** under appropriate namespaces
-- **Use `as const`** for immutability and better type inference
+- `SNEEZE_STAGE_1` (500ms) — First frame of avatar sneeze
+- `SNEEZE_STAGE_2` (300ms) — Second frame of avatar sneeze
+- `SNEEZE_STAGE_3` (1000ms) — Final frame of avatar sneeze
----
+**Usage:** Import to sequence the avatar sneeze animation in [Avatar component](../../src/components/banner/Avatar.tsx).
-## See Also
+Implementation: [src/constants/index.ts](../../src/constants/index.ts)
- [Utils Documentation](./utils.md) - Utility functions that use these constants
- [Helpers Documentation](./helpers.md) - Helper functions that use these constants
diff --git a/docs/architecture/data.md b/docs/architecture/data.md
index bae2dea..e018a8e 100644
--- a/docs/architecture/data.md
+++ b/docs/architecture/data.md
@@ -1,143 +1,74 @@
# Data Architecture
-This document explains how data is structured, managed, and integrated in the Alexander Sullivan's Portfolio project, with technical details and TypeScript interfaces.
-
-## Data Sources
-
-All static data is centralized in [src/data/](../../src/data/) for consistency and maintainability:
-
-### Static Data Files
-
-- [**projects.ts**](../../src/data/projects.ts) — Project portfolio with employment history, personal projects, and showcase details
-- [**publications.ts**](../../src/data/publications.ts) — Academic publications with DOIs, abstracts, and authors
-- [**socials.ts**](../../src/data/socials.ts) — Social media links and contact information
-- [**keywords.ts**](../../src/data/keywords.ts) — SEO keywords for search engine optimization
-
-### Dynamic Data
-
-- [Firebase integration](../../src/configs/firebase.ts) for analytics, performance monitoring, and real-time features (if configured)
+The portfolio stores all content as TypeScript files in [src/data/](../../src/data/). This "data-as-code" approach provides compile-time type safety, eliminates database queries, and enables fast static builds.
## Data Flow
```mermaid
sequenceDiagram
- participant Browser
- participant NextJS[Next.js Server]
+ participant Build[Build Process]
+ participant Data[Data Files]
participant Component
- participant DataFile[Data Files]
-
- Browser->>NextJS: Request page
- NextJS->>Component: Render component
- Component->>DataFile: Import data (static)
- DataFile-->>Component: Return typed data
- Component->>Browser: Render with data
- Component->>Browser: Initialize Firebase (client-side)
- Browser->>Browser: Track user events
+ participant Browser
+
+ Build->>Data: Import at compile time
+ Data-->>Build: Type-checked data
+ Build->>Component: Pass as props
+ Component->>Browser: Render to HTML
+ Browser->>Browser: No data fetching
```
-## Data Usage in the Codebase
+1. Next.js build process imports data from [src/data/](../../src/data/)
+2. TypeScript validates data against interfaces
+3. Components receive type-safe data as imports
+4. Next.js pre-renders HTML with embedded data
+5. Browser displays content immediately (no loading states)
-- **Data Location:** All static data in [src/data/](../../src/data/) is imported directly into components
-- **Type Safety:** TypeScript interfaces define strict types for each data structure
-- **Path Aliases:** Components use aliases like `@data/projects` for clean imports (no relative paths)
-- **No Runtime Validation:** Data is validated at compile time via TypeScript
-- **Integration Points:**
- - [ProjectsGrid](../../src/components/projects/ProjectsGrid.tsx) imports [projects.ts](../../src/data/projects.ts)
- - [Publications](../../src/components/publications/Publications.tsx) imports [publications.ts](../../src/data/publications.ts)
- - [Footer](../../src/components/footer/Footer.tsx) imports [socials.ts](../../src/data/socials.ts)
- - [Root Layout](../../src/app/layout.tsx) imports [keywords.ts](../../src/data/keywords.ts) for SEO
+## Data Files
-## Data Structures & Interfaces
+**Projects** ([src/data/projects.ts](../../src/data/projects.ts)) — Employment history, personal projects, and portfolio items. Each project includes name, employer, dates, thumbnail path, optional YouTube URL, and action links.
-### Projects Interface
+**Publications** ([src/data/publications.ts](../../src/data/publications.ts)) — Academic publications with authors, abstracts, DOIs, and journal information. Publications can link to related projects.
-Location: [src/data/projects.ts](../../src/data/projects.ts)
+**Socials** ([src/data/socials.ts](../../src/data/socials.ts)) — Social media profiles with platform names, URLs, brand colors, and icon components.
-```typescript
-interface Projects {
- name: string; // Project name
- id: string; // Unique identifier
- description?: string; // Optional description
- employer?: string; // Company/organization name
- employerURL?: string; // Company website
- title: string; // Job/role title
- publication?: string; // Publication URL
- type?: string; // Employment, Personal Project, etc.
- url: string; // Project URL
- urls: Array<{
- // Links with icons and tooltips
- text: string;
- tooltip: string;
- icon: (props: SvgIconProps) => React.ReactElement;
- url: string;
- }>;
- color: string; // Hex color for card styling
- dates?: {
- // Optional date range
- startDate: string; // YYYY-MM format
- endDate: string; // YYYY-MM format
- };
- showcase?: boolean; // Display in featured section
- objectFit?: string; // Image fit (cover or contain)
- youtubeURL?: string; // Optional YouTube embed
-}
-```
+**Keywords** ([src/data/keywords.ts](../../src/data/keywords.ts)) — SEO keywords array used in page metadata for search engine optimization.
-### Publications Interface
+## How Components Use Data
-Location: [src/data/publications.ts](../../src/data/publications.ts)
+Components import data directly using TypeScript path aliases:
```typescript
-interface Publication {
- title: string; // Publication title
- authors: string[]; // List of author names
- abstract: string; // Publication abstract
- doi: string; // Digital Object Identifier
- journal: string; // Journal/conference name
- date: string; // Publication date (YYYY-MM-DD)
- 'related-project'?: string; // Link to related project ID
-}
+import projects from '@data/projects';
+import publications from '@data/publications';
```
-### Socials Interface
-
-Location: [src/data/socials.ts](../../src/data/socials.ts)
-
-```typescript
-interface Social {
- name: string; // Social platform name
- url: string; // Profile URL
- icon: (props: SvgIconProps) => React.ReactElement; // Icon component
- color: string; // Brand color
-}
-```
+- [ProjectsGrid](../../src/components/projects/ProjectsGrid.tsx) maps over projects array to render cards
+- [Publications](../../src/components/publications/Publications.tsx) displays publication list
+- [Footer](../../src/components/footer/Footer.tsx) renders social media links
+- [Root Layout](../../src/app/layout.tsx) uses keywords for SEO metadata
-## Extending Data
+No fetching, no loading states, no error handling. Data is guaranteed available at render time.
-### Adding a New Project
+## Data Validation
-1. Open [src/data/projects.ts](../../src/data/projects.ts)
-2. Add a new object to the `projects` array with required fields
-3. Create a thumbnail at `public/images/projects/{project-id}/thumbnail.webp`
-4. Ensure the `id` matches the folder name
-5. Run `npm run validate` to verify TypeScript types
+TypeScript interfaces enforce data structure. For project data, the interface requires:
-### Adding a New Publication
+- Unique `id` (string) — Must match thumbnail folder name
+- Project `name` (string)
+- Job/role `title` (string)
+- Project `url` (string)
+- `urls` array with link objects containing text, tooltip, icon, and url
+- Hex `color` (string) for card styling
-1. Open [src/data/publications.ts](../../src/data/publications.ts)
-2. Add a new object with title, authors, abstract, DOI, and date
-3. Optionally link to a related project using the `'related-project'` field
-4. Run `npm run validate` to verify types
+Optional fields include employer, dates, YouTube URL, and visibility flags.
-### Adding New Keywords
+See full interface definitions in [src/data/projects.ts](../../src/data/projects.ts), [src/data/publications.ts](../../src/data/publications.ts), and [src/data/socials.ts](../../src/data/socials.ts).
-1. Open [src/data/keywords.ts](../../src/data/keywords.ts)
-2. Add relevant SEO keywords to the array
-3. Keywords are used in [src/app/layout.tsx](../../src/app/layout.tsx) for metadata
+Implementation: [src/data/](../../src/data/)
-## Related Docs
+## Related Documentation
-- [Projects Component Documentation](./components/projects.md)
-- [Publications Component Documentation](./components/publications.md)
-- [System Architecture](./index.md)
-- [Component Documentation](./components/index.md)
+- [Projects Component](./components/projects.md) — How project data renders
+- [Publications Component](./components/publications.md) — How publication data renders
+- [System Architecture](./index.md) — Overall application flow
diff --git a/docs/architecture/helpers.md b/docs/architecture/helpers.md
index 3a5de37..cd7f178 100644
--- a/docs/architecture/helpers.md
+++ b/docs/architecture/helpers.md
@@ -1,150 +1,80 @@
-# Helpers Module Documentation
+# Helpers Module
-This document describes the purpose, architecture, and usage of helper functions in the Alexander Sullivan's Portfolio project, with technical details and integration patterns.
+Helper functions provide reusable logic for UI formatting, animations, and page transformations. These functions are pure utilities imported by components.
-## Purpose
+## ASCII Logo Helper
-Helpers provide reusable utility functions for formatting, logic, and data manipulation. They help keep components clean and focused on UI, separating business logic from presentation.
+The ASCII helper ([src/helpers/ascii.ts](../../src/helpers/ascii.ts)) generates styled ASCII art logged to the browser console when the page loads.
-## Structure
+**Functions:**
-**Location:** [src/helpers/](../../src/helpers/)
+- `consoleLogLogo()` — Immediately logs ASCII art
+- `debounceConsoleLogLogo()` — Debounced version using `DELAYS.CONSOLE_LOGO_DEBOUNCE` (1000ms)
-### Available Helpers
+The debounced version prevents duplicate logs during navigation or hot module replacement in development.
-- [`ascii.ts`](../../src/helpers/ascii.ts) — Generates ASCII art for branding and fun UI elements
-- [`aaaahhhh.ts`](../../src/helpers/aaaahhhh.ts) — Custom logic for playful UI interactions (Easter egg)
+Called by [src/app/page.tsx](../../src/app/page.tsx) in `useEffect` on mount.
-## Usage Examples
+Implementation: [src/helpers/ascii.ts](../../src/helpers/ascii.ts)
-### ASCII Art Helper
+## AAAAHHHH Easter Egg Helper
-**Location:** [src/helpers/ascii.ts](../../src/helpers/ascii.ts)
+The AAAAHHHH helper ([src/helpers/aaaahhhh.ts](../../src/helpers/aaaahhhh.ts)) transforms the entire page into a playful state after the avatar sneezes 6 times.
-Generates and logs ASCII art to the browser console on page load.
-
-```typescript
-import { consoleLogLogo, debounceConsoleLogLogo } from '@helpers/ascii';
-
-// Print ASCII logo once
-consoleLogLogo();
-
-// Debounced version for repeated calls (uses DELAYS.CONSOLE_LOGO_DEBOUNCE)
-debounceConsoleLogLogo();
-```
-
-**Implementation Details:**
-
-The ASCII helper uses constants for timing control:
-
-```typescript
-import { DELAYS } from '@constants/index';
-import { debounce } from 'lodash';
-
-export const debounceConsoleLogLogo = debounce(consoleLogLogo, DELAYS.CONSOLE_LOGO_DEBOUNCE);
-```
-
-**Integration:**
-
-- Called in [src/app/page.tsx](../../src/app/page.tsx) during `useEffect` initialization
-- Uses `DELAYS.CONSOLE_LOGO_DEBOUNCE` (1000ms) to prevent duplicate logs on navigation
-
-### AAAAHHHH Easter Egg Helper
-
-**Location:** [src/helpers/aaaahhhh.ts](../../src/helpers/aaaahhhh.ts)
-
-The `aaaahhhh` helper provides a playful page transformation triggered after multiple avatar sneezes (6 total). This is the ultimate Easter egg!
-
-```typescript
-import { aaaahhhh, convertAAAAHH, imageAAAAHHHH, textAAAAHHHH } from '@helpers/aaaahhhh';
-
-// Trigger full page transformation
-aaaahhhh();
-
-// Convert text to AAAAHHHH format
-const converted = convertAAAAHH('Hello World'); // Returns: 'Aaaaa HHHHHH'
-
-// Transform all text on page
-textAAAAHHHH();
-
-// Transform all images on page
-imageAAAAHHHH();
-```
-
-**How it Works:**
+### Transformation Behavior
```mermaid
flowchart TD
- Trigger["Avatar sneezes 6 times"] --> AaaahhhhCall["aaaahhhh()"]
- AaaahhhhCall --> Text["textAAAAHHHH()"]
- AaaahhhhCall --> Images["imageAAAAHHHH()"]
+ Trigger[Avatar sneezes 6 times] --> Call[aaaahhhh function]
+ Call --> Text[textAAAAHHHH]
+ Call --> Images[imageAAAAHHHH]
- Text --> Convert["convertAAAAHH()"]
- Convert --> FirstHalf["First half → A"]
- Convert --> SecondHalf["Second half → H"]
+ Text --> Convert[convertAAAAHH]
+ Convert --> FirstHalf[First half → 'A']
+ Convert --> SecondHalf[Second half → 'H']
- Images --> ReplaceImg["Replace img src"]
- Images --> ReplaceBg["Replace bg images"]
+ Images --> ImgReplace[Replace img src]
+ Images --> BgReplace[Replace bg images]
- FirstHalf --> TextElements["Apply to: span, p, h1-h3, button"]
- SecondHalf --> TextElements
+ FirstHalf --> Apply[Apply to text elements]
+ SecondHalf --> Apply
- ReplaceImg --> ImageElements["All img & bg-image elements"]
- ReplaceBg --> ImageElements
-
- TextElements --> Result["Aahh aaaaaahhhh!"]
- ImageElements --> Result
+ Apply --> Page[Transformed page]
+ ImgReplace --> Page
+ BgReplace --> Page
```
-**Text Conversion Logic:**
-
-- First half of word → 'A' (or 'a' if lowercase)
-- Second half of word → 'H' (or 'h' if lowercase)
-- Spaces and special characters preserved
-
-**Image Transformation:**
+**Text Transformation Logic:**
-- Replaces all `` src and srcset attributes
-- Replaces all CSS background images in style attributes
-- Updates the stars background with cover image
-- Uses `/images/aaaahhhh/aaaahhhh.webp` as replacement image
+The `convertAAAAHH()` function splits words in half:
-**Target Elements:**
+- First half characters → 'A' (lowercase → 'a')
+- Second half characters → 'H' (lowercase → 'h')
+- Spaces and special characters preserved
+- Example: "Hello World" → "Aaaaa HHHHHH"
-Text transformation applies to:
+Applied to: ``, `