From 569b72f2f4016731ed212bbaab3c7263b5b26f1a Mon Sep 17 00:00:00 2001 From: Alexander Sullivan Date: Mon, 5 Jan 2026 20:15:15 -0500 Subject: [PATCH 1/2] update prompts --- .github/copilot-instructions.md | 156 ++++++++++ .github/prompts/audit-docs.md | 103 ------- .github/prompts/audit-docs.prompt.md | 176 +++++++++++ ...dit-quality.md => audit-quality.prompt.md} | 0 package-lock.json | 276 ++++++++++-------- package.json | 2 +- 6 files changed, 492 insertions(+), 221 deletions(-) create mode 100644 .github/copilot-instructions.md delete mode 100644 .github/prompts/audit-docs.md create mode 100644 .github/prompts/audit-docs.prompt.md rename .github/prompts/{audit-quality.md => audit-quality.prompt.md} (100%) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..5b9e54c --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,156 @@ +# AlexJSully Portfolio - AI Coding Agent Instructions + +## Architecture Overview + +This is a **Next.js portfolio website** using the **App Router** (not Pages Router), React, TypeScript, and Material-UI with Emotion. The project follows a modular structure with path aliases, comprehensive testing, and Progressive Web App (PWA) capabilities. + +### Key Technologies & Integrations +- **Framework**: Next.js App Router with React Server Components +- **Styling**: Material-UI (MUI) + Emotion (use `sx` prop, not CSS modules) +- **Testing**: Jest (unit tests), Cypress (E2E tests with accessibility via cypress-axe) +- **Monitoring**: Sentry error tracking, Firebase Analytics/Performance, Vercel Speed Insights +- **PWA**: Service Worker in `public/sw.js`, manifest via `src/app/manifest.ts` + +## Critical Workflows + +### Development Commands +```bash +npm run dev # Start dev server at localhost:3000 +npm run validate # Full CI check: prettier → eslint → tsc → jest → cypress → build → markdown +npm run test:jest # Unit tests only +npm run test:cypress:e2e # E2E tests headless +npm run build # Production build +``` + +**Always run `npm run validate` before committing.** This is the comprehensive quality gate used in CI/CD. + +### Testing Requirements +- **Unit tests**: Every component requires a `.test.tsx` file (see `src/components/banner/Banner.test.tsx`) +- **Test setup**: Uses `jest/setup.ts` with jsdom environment +- **E2E tests**: Located in `cypress/e2e/`, include accessibility tests (cypress-axe) +- **Coverage**: Run `npm run test:jest:coverage` for coverage reports + +## Project-Specific Conventions + +### Path Aliases (Critical!) +Always use TypeScript path aliases defined in `tsconfig.json`: +```typescript +import Avatar from '@components/banner/Avatar'; // NOT '../components/banner/Avatar' +import { DELAYS } from '@constants/index'; // NOT '../../constants' +import { isNetworkFast } from '@util/isNetworkFast'; +``` + +### Component Patterns + +#### Material-UI Styling +Use `sx` prop for styling, never inline styles or CSS modules: +```typescript + +``` + +#### SVG Icons Pattern +SVGs are imported as React components via `@svgr/webpack`. See `src/images/icons.tsx`: +```typescript +import Icon from './icons/example.svg'; +export const ExampleIcon = (props: SvgIconProps) => + ; +``` + +### Data Management +Static data lives in `src/data/`: +- `projects.ts`: Project portfolio with typed interface +- `publications.ts`: Academic publications +- `socials.ts`: Social media links +- `keywords.ts`: SEO keywords array + +### Constants Pattern +Centralized constants in `src/constants/index.ts` with `as const` for type safety: +```typescript +DELAYS.PROJECT_HOVER_VIDEO // 1000ms before video plays on hover +THRESHOLDS.SNEEZE_TRIGGER_INTERVAL // Easter egg triggers +NETWORK.SLOW_DOWNLINK_THRESHOLD // Network performance checks +``` + +## Code Style & Quality + +### Linting & Formatting +- **Indentation**: Tabs (not spaces) - enforced by ESLint +- **Line length**: No hard limit, use Prettier +- **Import sorting**: Handled by `@trivago/prettier-plugin-sort-imports` +- **Unused vars**: Prefix with `_` to ignore (e.g., `_unusedParam`) + +### ESLint Rules (see `eslint.config.js`) +- Tabs for indentation (indent: ['error', 'tab']) +- Console logs allowed (`no-console: off`) +- Unused vars with `_` prefix ignored +- React hooks exhaustive deps enforced + +### TypeScript +- **Strict mode**: Enabled in `tsconfig.json` +- **No implicit any**: All types must be explicit +- **React 19**: Uses new `react-jsx` transform +- Run `npm run tsc` to check types (no emit) + +## Next.js App Router Specifics + +### Metadata & SEO +All metadata configured in `src/app/layout.tsx`: +```typescript +export const metadata: Metadata = { + title: { template: `%s | ${metadataValues.title}`, default: metadataValues.title }, + keywords: seoKeywords, + openGraph: { ... }, + robots: { index: true, follow: true }, +}; +``` + +### Server Components vs Client Components +- Default: Server Components (no `'use client'`) +- Client-only: Components with hooks, event handlers, browser APIs +- Example client component: `src/components/ServiceWorkerRegister.tsx` + +### Security Headers +CSP and security headers configured in `next.config.js` headers() function. Includes: +- X-Content-Type-Options: nosniff +- X-Frame-Options: DENY +- Strict-Transport-Security (HSTS) +- Content Security Policy for service workers + +## Special Features + +### Network Performance Optimization +`src/util/isNetworkFast.ts` checks Network Information API to conditionally load heavy assets based on connection speed. + +### Easter Eggs +- `src/helpers/aaaahhhh.ts`: Fun image replacement logic triggered by avatar interactions +- `src/helpers/ascii.ts`: Console ASCII art + +### Service Worker +- Lives in `public/sw.js` and served via `src/app/sw.js/` +- Registration in `src/components/ServiceWorkerRegister.tsx` +- Used for PWA offline support + +## Firebase & Analytics +Initialize Firebase only client-side (see `src/configs/firebase.ts`): +```typescript +import { init, logAnalyticsEvent } from '@configs/firebase'; +init(); // Call once on client mount +logAnalyticsEvent('event_name', { params }); +``` + +## Documentation +Architecture docs in `docs/architecture/`: +- `index.md`: System overview +- Component-specific docs for Avatar, Projects, Publications, etc. + +## Common Gotchas +1. **Don't** import from relative paths - use path aliases +2. **Don't** forget to update tests when changing components +3. **Always** run `npm run validate` frequently when making changes diff --git a/.github/prompts/audit-docs.md b/.github/prompts/audit-docs.md deleted file mode 100644 index 9c7d72f..0000000 --- a/.github/prompts/audit-docs.md +++ /dev/null @@ -1,103 +0,0 @@ ---- -title: 'Audit and Update docs/ Directory' -scope: 'repo' -targets: - - 'docs/' - - 'codebase' -labels: - - 'documentation' - - 'audit' - - 'mermaid' ---- - -**Purpose:** -While reviewing this #activePullRequest #changes, analyze the entire #codebase and ensure the #file:docs directory is accurate, up to date, and fully aligned with the current implementation. - ---- - -## HARD RULES (Do Not Violate) - -1. **No forward-looking or speculative content.** - - Do NOT generate a `roadmap.md`. - - Do NOT document planned features, hypothetical designs, or imagined improvements. - - Document only what exists in the current codebase. - -2. **No invented code.** - - Only reference functions, hooks, classes, types, modules, files, directories, system architecture & design or packages that actually exist. - - Verify existence before describing or linking anything. - -3. **No placeholder text or TODOs.** - - Do not create empty sections or stubs. - - Every sentence must be grounded in verifiable code. - -4. **No unnecessary rewriting of the entire system.** - - Only update documentation that is outdated, incorrect, incomplete, or missing. - ---- - -## Execution Order (IMPORTANT) - -1. **Audit `docs/` first** -2. **Only if `docs/` is already accurate**, then: - - Audit markdown files elsewhere in the repository (root or subdirectories) - - Audit in-code documentation/comments where clarity or accuracy is lacking - -Do **not** skip ahead. - ---- - -## What to Do - -### 1. Audit the `docs/` directory - -- Identify inaccuracies, outdated content, missing explanations, or architectural mismatches. -- Cross-reference source files, comments, directory structure, and actual behavior. - -### 2. Update documentation strictly based on verified code - -- Correct outdated statements. -- Add missing explanations grounded in the current implementation. -- Include **small, accurate code snippets** whenever explaining behavior, usage, or examples. - - Snippets must reference real code that exists within the codebase. - - No invented identifiers. - -### 3. Use **Mermaid diagrams extensively** - -- Proactively identify any section where a diagram would improve clarity. -- Include diagrams for: - - data flows - - module interactions - - component relationships - - lifecycle steps - - architectural overviews - - system interactions -- Use only diagrams that reflect **actual, current code** (no hypothetical structures). -- Prefer `flowchart`, `sequenceDiagram`, `classDiagram`, and `stateDiagram` when appropriate. - -### 4. Reference real files frequently using markdown links - -- Whenever referencing a file or module, **link directly to the file using proper markdown**: `[Description](relative/path/to/file.ts)` -- Confirm the file exists before linking. -- Use file links liberally so readers can immediately navigate to source. - -### 5. Maintain clarity and conciseness - -- Keep explanations self-contained and clear. -- Highlight real architectural decisions, assumptions, and edge cases. -- Avoid verbosity or speculative commentary. - -### 6. Apply changes directly (docs only) - -- Modify existing documentation files. -- Add new markdown files only when supported by real code. -- If creating a **new directory**: - - **a. Always create an `index.md`** - - Must provide an overview of the directory’s purpose and contents. - - **b. Create only files that correspond directly to real, existing code.** -- No speculative or forward-looking directories or files. - ---- - -## Final Step - -After completing all changes, run `npm run validate` from #file:package.json and ensure markdown linting passes cleanly. diff --git a/.github/prompts/audit-docs.prompt.md b/.github/prompts/audit-docs.prompt.md new file mode 100644 index 0000000..8e23c59 --- /dev/null +++ b/.github/prompts/audit-docs.prompt.md @@ -0,0 +1,176 @@ +--- +title: 'Audit and Update docs/ Directory' +scope: 'repo' +targets: + - 'docs/' + - 'codebase' +labels: + - 'documentation' + - 'audit' + - 'mermaid' +--- + +## Purpose + +While reviewing this #activePullRequest #changes, analyze the entire #codebase and ensure the #file:docs directory is accurate, up to date, and fully aligned with the current implementation. + +Documentation produced by this prompt must serve **two audiences simultaneously**: + +1. **Internal developers / maintainers** + - To understand system internals, architectural decisions, constraints, and design intent + - To preserve *why* things were implemented the way they are and the *how* behind the *what* +2. **New or external developers** + - To understand how to use the system, APIs, and modules as tools + - To quickly navigate from documentation to implementation + +--- + +## HARD RULES (Do Not Violate) + +1. **No forward-looking or speculative content** + - Do NOT generate a `roadmap.md` + - Do NOT document planned features, hypothetical designs, or imagined improvements + - Document only what exists in the current codebase + +2. **No invented code** + - Only reference functions, hooks, classes, types, modules, files, directories, system architecture & design, or packages that actually exist + - Verify existence before describing or linking anything + +3. **No placeholder text or TODOs** + - Do not create empty sections or stubs + - Every sentence must be grounded in verifiable code + +4. **No unnecessary rewriting** + - Only update documentation that is outdated, incorrect, incomplete, or missing + - Preserve accurate documentation as-is + +--- + +## Execution Order (IMPORTANT) + +1. **Audit `docs/` first** +2. **Only if `docs/` is already accurate**, then: + - Audit markdown files elsewhere in the repository (root or subdirectories) + - Audit in-code documentation/comments where clarity or accuracy is lacking + +Do **not** skip ahead. + +--- + +## Documentation Style & Priorities (CRITICAL) + +### Description-first, Code-second + +When documenting behavior, architecture, or usage: + +1. **Start with a succinct natural-language explanation** + - Explain *what the component does*, *why it exists*, and *how it fits into the system* +2. **Link directly to the implementation** + - Prefer links to real source files over inline code + - Example: + > The request validation logic is centralized in `validateRequest`, which enforces schema constraints before execution. + > See implementation: [`src/api/validateRequest.ts`](src/api/validateRequest.ts) +3. **Use inline code blocks sparingly and intentionally** + - Include code snippets **only when they materially improve understanding**, such as: + - Public API usage examples + - Non-obvious control flow + - Critical invariants or edge cases + - Snippets must be: + - Small + - Accurate + - Directly copied or derived from real code + - Avoid restating large sections of implementation inline + +**Inline code should reinforce understanding — not replace navigation to source.** + +--- + +## What to Do + +### 1. Audit the `docs/` directory + +- Identify inaccuracies, outdated content, missing explanations, or architectural mismatches +- Cross-reference: + - Source files + - Directory structure + - In-code comments + - Actual runtime behavior + +--- + +### 2. Update documentation strictly based on verified code + +- Correct outdated or incorrect statements +- Add missing explanations grounded in the current implementation +- Clearly distinguish: + - **Conceptual behavior** (what/why) + - **Implementation details** (how) +- Prefer: + - **Explanation + file link** + - Over large inline code blocks + +--- + +### 3. Use Mermaid diagrams extensively + +Proactively identify any section where a diagram would improve clarity. + +Include diagrams for: + +- Data flows +- Module interactions +- Component relationships +- Lifecycle steps +- Architectural overviews +- System interactions + +Rules: + +- Diagrams must reflect **actual, current code** +- No hypothetical or idealized structures +- Prefer: + - `flowchart` + - `sequenceDiagram` + - `classDiagram` + - `stateDiagram` + +--- + +### 4. Reference real files frequently using markdown links + +- Whenever referencing a file, module, or subsystem: + - Link directly using relative paths + Example: `[Auth middleware](src/middleware/auth.ts)` +- Confirm the file exists before linking +- Use links liberally to encourage source exploration + +--- + +### 5. Maintain clarity and conciseness + +- Keep explanations focused and self-contained +- Explicitly document: + - Architectural decisions (use mermaid diagrams when applicable in addition to text) + - Constraints and limitations + - Trigger conditions + - Expected inputs and outputs + - Notable edge cases +- Avoid verbosity, repetition, or speculative commentary + +--- + +### 6. Apply changes directly (docs only) + +- Modify existing documentation files +- Add new markdown files **only when supported by real code** +- If creating a new directory: + - **Always include an `index.md`** + - Describe the directory’s purpose and contents + - Create files that map directly to existing code artifacts +- No speculative or forward-looking files or directories + +--- + +## Final Step + +After completing all changes, run `npm run validate` from #file:package.json and ensure markdown linting passes cleanly. diff --git a/.github/prompts/audit-quality.md b/.github/prompts/audit-quality.prompt.md similarity index 100% rename from .github/prompts/audit-quality.md rename to .github/prompts/audit-quality.prompt.md diff --git a/package-lock.json b/package-lock.json index 4f1af2c..2db6a74 100644 --- a/package-lock.json +++ b/package-lock.json @@ -51,7 +51,7 @@ "jest-transform-stub": "^2.0.0", "markdownlint-cli": "^0.47.0", "prettier": "^3.7.4", - "sass": "^1.97.1", + "sass": "^1.97.2", "start-server-and-test": "^2.1.3", "ts-jest": "^29.4.6", "typescript": "^5.9.3" @@ -2131,9 +2131,9 @@ } }, "node_modules/@cypress/request": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.9.tgz", - "integrity": "sha512-I3l7FdGRXluAS44/0NguwWlO83J18p0vlr2FYHrJkWdNYhgVoiYo61IXPqaOsL+vNxU1ZqMACzItGK3/KKDsdw==", + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.10.tgz", + "integrity": "sha512-hauBrOdvu08vOsagkZ/Aju5XuiZx6ldsLfByg1htFeldhex+PeMrYauANzFsMJeAA0+dyPLbDoX2OYuvVoLDkQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -2150,7 +2150,7 @@ "json-stringify-safe": "~5.0.1", "mime-types": "~2.1.19", "performance-now": "^2.1.0", - "qs": "6.14.0", + "qs": "~6.14.1", "safe-buffer": "^5.1.2", "tough-cookie": "^5.0.0", "tunnel-agent": "^0.6.0", @@ -2192,9 +2192,9 @@ } }, "node_modules/@emnapi/core": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.8.0.tgz", - "integrity": "sha512-ryJnSmj4UhrGLZZPJ6PKVb4wNPAIkW6iyLy+0TRwazd3L1u0wzMe8RfqevAh2HbcSkoeLiSYnOVDOys4JSGYyg==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.8.1.tgz", + "integrity": "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==", "dev": true, "license": "MIT", "optional": true, @@ -2204,9 +2204,9 @@ } }, "node_modules/@emnapi/runtime": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.0.tgz", - "integrity": "sha512-Z82FDl1ByxqPEPrAYYeTQVlx2FSHPe1qwX465c+96IRS3fTdSYRoJcRxg3g2fEG5I69z1dSEWQlNRRr0/677mg==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", + "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", "license": "MIT", "optional": true, "dependencies": { @@ -5823,9 +5823,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.54.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.54.0.tgz", - "integrity": "sha512-OywsdRHrFvCdvsewAInDKCNyR3laPA2mc9bRYJ6LBp5IyvF3fvXbbNR0bSzHlZVFtn6E0xw2oZlyjg4rKCVcng==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.55.1.tgz", + "integrity": "sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==", "cpu": [ "arm" ], @@ -5836,9 +5836,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.54.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.54.0.tgz", - "integrity": "sha512-Skx39Uv+u7H224Af+bDgNinitlmHyQX1K/atIA32JP3JQw6hVODX5tkbi2zof/E69M1qH2UoN3Xdxgs90mmNYw==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.55.1.tgz", + "integrity": "sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg==", "cpu": [ "arm64" ], @@ -5849,9 +5849,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.54.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.54.0.tgz", - "integrity": "sha512-k43D4qta/+6Fq+nCDhhv9yP2HdeKeP56QrUUTW7E6PhZP1US6NDqpJj4MY0jBHlJivVJD5P8NxrjuobZBJTCRw==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.55.1.tgz", + "integrity": "sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg==", "cpu": [ "arm64" ], @@ -5862,9 +5862,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.54.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.54.0.tgz", - "integrity": "sha512-cOo7biqwkpawslEfox5Vs8/qj83M/aZCSSNIWpVzfU2CYHa2G3P1UN5WF01RdTHSgCkri7XOlTdtk17BezlV3A==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.55.1.tgz", + "integrity": "sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ==", "cpu": [ "x64" ], @@ -5875,9 +5875,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.54.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.54.0.tgz", - "integrity": "sha512-miSvuFkmvFbgJ1BevMa4CPCFt5MPGw094knM64W9I0giUIMMmRYcGW/JWZDriaw/k1kOBtsWh1z6nIFV1vPNtA==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.55.1.tgz", + "integrity": "sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg==", "cpu": [ "arm64" ], @@ -5888,9 +5888,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.54.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.54.0.tgz", - "integrity": "sha512-KGXIs55+b/ZfZsq9aR026tmr/+7tq6VG6MsnrvF4H8VhwflTIuYh+LFUlIsRdQSgrgmtM3fVATzEAj4hBQlaqQ==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.55.1.tgz", + "integrity": "sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw==", "cpu": [ "x64" ], @@ -5901,9 +5901,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.54.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.54.0.tgz", - "integrity": "sha512-EHMUcDwhtdRGlXZsGSIuXSYwD5kOT9NVnx9sqzYiwAc91wfYOE1g1djOEDseZJKKqtHAHGwnGPQu3kytmfaXLQ==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.55.1.tgz", + "integrity": "sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==", "cpu": [ "arm" ], @@ -5914,9 +5914,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.54.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.54.0.tgz", - "integrity": "sha512-+pBrqEjaakN2ySv5RVrj/qLytYhPKEUwk+e3SFU5jTLHIcAtqh2rLrd/OkbNuHJpsBgxsD8ccJt5ga/SeG0JmA==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.55.1.tgz", + "integrity": "sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==", "cpu": [ "arm" ], @@ -5927,9 +5927,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.54.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.54.0.tgz", - "integrity": "sha512-NSqc7rE9wuUaRBsBp5ckQ5CVz5aIRKCwsoa6WMF7G01sX3/qHUw/z4pv+D+ahL1EIKy6Enpcnz1RY8pf7bjwng==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.55.1.tgz", + "integrity": "sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==", "cpu": [ "arm64" ], @@ -5940,9 +5940,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.54.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.54.0.tgz", - "integrity": "sha512-gr5vDbg3Bakga5kbdpqx81m2n9IX8M6gIMlQQIXiLTNeQW6CucvuInJ91EuCJ/JYvc+rcLLsDFcfAD1K7fMofg==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.55.1.tgz", + "integrity": "sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==", "cpu": [ "arm64" ], @@ -5953,9 +5953,22 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.54.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.54.0.tgz", - "integrity": "sha512-gsrtB1NA3ZYj2vq0Rzkylo9ylCtW/PhpLEivlgWe0bpgtX5+9j9EZa0wtZiCjgu6zmSeZWyI/e2YRX1URozpIw==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.55.1.tgz", + "integrity": "sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.55.1.tgz", + "integrity": "sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==", "cpu": [ "loong64" ], @@ -5966,9 +5979,22 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.54.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.54.0.tgz", - "integrity": "sha512-y3qNOfTBStmFNq+t4s7Tmc9hW2ENtPg8FeUD/VShI7rKxNW7O4fFeaYbMsd3tpFlIg1Q8IapFgy7Q9i2BqeBvA==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.55.1.tgz", + "integrity": "sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.55.1.tgz", + "integrity": "sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==", "cpu": [ "ppc64" ], @@ -5979,9 +6005,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.54.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.54.0.tgz", - "integrity": "sha512-89sepv7h2lIVPsFma8iwmccN7Yjjtgz0Rj/Ou6fEqg3HDhpCa+Et+YSufy27i6b0Wav69Qv4WBNl3Rs6pwhebQ==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.55.1.tgz", + "integrity": "sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==", "cpu": [ "riscv64" ], @@ -5992,9 +6018,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.54.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.54.0.tgz", - "integrity": "sha512-ZcU77ieh0M2Q8Ur7D5X7KvK+UxbXeDHwiOt/CPSBTI1fBmeDMivW0dPkdqkT4rOgDjrDDBUed9x4EgraIKoR2A==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.55.1.tgz", + "integrity": "sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==", "cpu": [ "riscv64" ], @@ -6005,9 +6031,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.54.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.54.0.tgz", - "integrity": "sha512-2AdWy5RdDF5+4YfG/YesGDDtbyJlC9LHmL6rZw6FurBJ5n4vFGupsOBGfwMRjBYH7qRQowT8D/U4LoSvVwOhSQ==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.55.1.tgz", + "integrity": "sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==", "cpu": [ "s390x" ], @@ -6018,9 +6044,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.54.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.54.0.tgz", - "integrity": "sha512-WGt5J8Ij/rvyqpFexxk3ffKqqbLf9AqrTBbWDk7ApGUzaIs6V+s2s84kAxklFwmMF/vBNGrVdYgbblCOFFezMQ==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.55.1.tgz", + "integrity": "sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==", "cpu": [ "x64" ], @@ -6031,9 +6057,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.54.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.54.0.tgz", - "integrity": "sha512-JzQmb38ATzHjxlPHuTH6tE7ojnMKM2kYNzt44LO/jJi8BpceEC8QuXYA908n8r3CNuG/B3BV8VR3Hi1rYtmPiw==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.55.1.tgz", + "integrity": "sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==", "cpu": [ "x64" ], @@ -6043,10 +6069,23 @@ "linux" ] }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.55.1.tgz", + "integrity": "sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.54.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.54.0.tgz", - "integrity": "sha512-huT3fd0iC7jigGh7n3q/+lfPcXxBi+om/Rs3yiFxjvSxbSB6aohDFXbWvlspaqjeOh+hx7DDHS+5Es5qRkWkZg==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.55.1.tgz", + "integrity": "sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw==", "cpu": [ "arm64" ], @@ -6057,9 +6096,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.54.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.54.0.tgz", - "integrity": "sha512-c2V0W1bsKIKfbLMBu/WGBz6Yci8nJ/ZJdheE0EwB73N3MvHYKiKGs3mVilX4Gs70eGeDaMqEob25Tw2Gb9Nqyw==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.55.1.tgz", + "integrity": "sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g==", "cpu": [ "arm64" ], @@ -6070,9 +6109,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.54.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.54.0.tgz", - "integrity": "sha512-woEHgqQqDCkAzrDhvDipnSirm5vxUXtSKDYTVpZG3nUdW/VVB5VdCYA2iReSj/u3yCZzXID4kuKG7OynPnB3WQ==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.55.1.tgz", + "integrity": "sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA==", "cpu": [ "ia32" ], @@ -6083,9 +6122,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.54.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.54.0.tgz", - "integrity": "sha512-dzAc53LOuFvHwbCEOS0rPbXp6SIhAf2txMP5p6mGyOXXw5mWY8NGGbPMPrs4P1WItkfApDathBj/NzMLUZ9rtQ==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.55.1.tgz", + "integrity": "sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg==", "cpu": [ "x64" ], @@ -6096,9 +6135,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.54.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.54.0.tgz", - "integrity": "sha512-hYT5d3YNdSh3mbCU1gwQyPgQd3T2ne0A3KG8KSBdav5TiBg6eInVmV+TeR5uHufiIgSFg0XsOWGW5/RhNcSvPg==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.55.1.tgz", + "integrity": "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==", "cpu": [ "x64" ], @@ -16011,9 +16050,9 @@ "license": "MIT" }, "node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", + "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -16322,9 +16361,9 @@ "license": "MIT" }, "node_modules/rollup": { - "version": "4.54.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.54.0.tgz", - "integrity": "sha512-3nk8Y3a9Ea8szgKhinMlGMhGMw89mqule3KWczxhIzqudyHdCIOHw8WJlj/r329fACjKLEh13ZSk7oE22kyeIw==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.55.1.tgz", + "integrity": "sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==", "license": "MIT", "peer": true, "dependencies": { @@ -16338,28 +16377,31 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.54.0", - "@rollup/rollup-android-arm64": "4.54.0", - "@rollup/rollup-darwin-arm64": "4.54.0", - "@rollup/rollup-darwin-x64": "4.54.0", - "@rollup/rollup-freebsd-arm64": "4.54.0", - "@rollup/rollup-freebsd-x64": "4.54.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.54.0", - "@rollup/rollup-linux-arm-musleabihf": "4.54.0", - "@rollup/rollup-linux-arm64-gnu": "4.54.0", - "@rollup/rollup-linux-arm64-musl": "4.54.0", - "@rollup/rollup-linux-loong64-gnu": "4.54.0", - "@rollup/rollup-linux-ppc64-gnu": "4.54.0", - "@rollup/rollup-linux-riscv64-gnu": "4.54.0", - "@rollup/rollup-linux-riscv64-musl": "4.54.0", - "@rollup/rollup-linux-s390x-gnu": "4.54.0", - "@rollup/rollup-linux-x64-gnu": "4.54.0", - "@rollup/rollup-linux-x64-musl": "4.54.0", - "@rollup/rollup-openharmony-arm64": "4.54.0", - "@rollup/rollup-win32-arm64-msvc": "4.54.0", - "@rollup/rollup-win32-ia32-msvc": "4.54.0", - "@rollup/rollup-win32-x64-gnu": "4.54.0", - "@rollup/rollup-win32-x64-msvc": "4.54.0", + "@rollup/rollup-android-arm-eabi": "4.55.1", + "@rollup/rollup-android-arm64": "4.55.1", + "@rollup/rollup-darwin-arm64": "4.55.1", + "@rollup/rollup-darwin-x64": "4.55.1", + "@rollup/rollup-freebsd-arm64": "4.55.1", + "@rollup/rollup-freebsd-x64": "4.55.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.55.1", + "@rollup/rollup-linux-arm-musleabihf": "4.55.1", + "@rollup/rollup-linux-arm64-gnu": "4.55.1", + "@rollup/rollup-linux-arm64-musl": "4.55.1", + "@rollup/rollup-linux-loong64-gnu": "4.55.1", + "@rollup/rollup-linux-loong64-musl": "4.55.1", + "@rollup/rollup-linux-ppc64-gnu": "4.55.1", + "@rollup/rollup-linux-ppc64-musl": "4.55.1", + "@rollup/rollup-linux-riscv64-gnu": "4.55.1", + "@rollup/rollup-linux-riscv64-musl": "4.55.1", + "@rollup/rollup-linux-s390x-gnu": "4.55.1", + "@rollup/rollup-linux-x64-gnu": "4.55.1", + "@rollup/rollup-linux-x64-musl": "4.55.1", + "@rollup/rollup-openbsd-x64": "4.55.1", + "@rollup/rollup-openharmony-arm64": "4.55.1", + "@rollup/rollup-win32-arm64-msvc": "4.55.1", + "@rollup/rollup-win32-ia32-msvc": "4.55.1", + "@rollup/rollup-win32-x64-gnu": "4.55.1", + "@rollup/rollup-win32-x64-msvc": "4.55.1", "fsevents": "~2.3.2" } }, @@ -16489,9 +16531,9 @@ "license": "MIT" }, "node_modules/sass": { - "version": "1.97.1", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.97.1.tgz", - "integrity": "sha512-uf6HoO8fy6ClsrShvMgaKUn14f2EHQLQRtpsZZLeU/Mv0Q1K5P0+x2uvH6Cub39TVVbWNSrraUhDAoFph6vh0A==", + "version": "1.97.2", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.97.2.tgz", + "integrity": "sha512-y5LWb0IlbO4e97Zr7c3mlpabcbBtS+ieiZ9iwDooShpFKWXf62zz5pEPdwrLYm+Bxn1fnbwFGzHuCLSA9tBmrw==", "devOptional": true, "license": "MIT", "peer": true, @@ -17441,9 +17483,9 @@ } }, "node_modules/systeminformation": { - "version": "5.28.10", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.28.10.tgz", - "integrity": "sha512-SBNOOYYKSL1NqgG8W+5pqb6654BEvR9JnM7qvWP4bgIXuCurvyZXpBMdweVKBpVPrpzUxrgl6PbZPxrmt4RpKw==", + "version": "5.29.1", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.29.1.tgz", + "integrity": "sha512-bBroZc2we1tpgTBKZL7JguBdObC1OY+eXAoEBdsTp3utfcCa8+jUf+Wq/intTCJmiKJcuLEPsjCU6uMye0qvsQ==", "dev": true, "license": "MIT", "os": [ @@ -18761,9 +18803,9 @@ } }, "node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", + "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", "dev": true, "license": "MIT", "engines": { @@ -18883,9 +18925,9 @@ } }, "node_modules/zod": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.4.tgz", - "integrity": "sha512-Zw/uYiiyF6pUT1qmKbZziChgNPRu+ZRneAsMUDU6IwmXdWt5JwcUfy2bvLOCUtz5UniaN/Zx5aFttZYbYc7O/A==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.5.tgz", + "integrity": "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==", "dev": true, "license": "MIT", "peer": true, diff --git a/package.json b/package.json index 8b393ed..b1bc4b2 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "jest-transform-stub": "^2.0.0", "markdownlint-cli": "^0.47.0", "prettier": "^3.7.4", - "sass": "^1.97.1", + "sass": "^1.97.2", "start-server-and-test": "^2.1.3", "ts-jest": "^29.4.6", "typescript": "^5.9.3" From d4cd552006b9d398a7097a118769be4887561aa8 Mon Sep 17 00:00:00 2001 From: Alexander Sullivan Date: Mon, 5 Jan 2026 21:10:36 -0500 Subject: [PATCH 2/2] update docs --- .github/copilot-instructions.md | 46 ++++++- .github/prompts/audit-docs.prompt.md | 8 +- docs/architecture/app-directory.md | 2 +- docs/architecture/components/index.md | 2 +- docs/architecture/data.md | 188 +++++++++++++++++--------- docs/architecture/helpers.md | 111 ++++++++++----- docs/architecture/layouts.md | 67 ++++++--- docs/architecture/pwa.md | 2 +- docs/architecture/utils.md | 97 +++++++++---- docs/index.md | 59 ++++---- docs/usage/index.md | 2 +- docs/usage/setup.md | 2 +- 12 files changed, 402 insertions(+), 184 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 5b9e54c..decdc51 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,10 +1,11 @@ -# AlexJSully Portfolio - AI Coding Agent Instructions +# Alexander Sullivan's Portfolio - AI Coding Agent Instructions ## Architecture Overview This is a **Next.js portfolio website** using the **App Router** (not Pages Router), React, TypeScript, and Material-UI with Emotion. The project follows a modular structure with path aliases, comprehensive testing, and Progressive Web App (PWA) capabilities. ### Key Technologies & Integrations + - **Framework**: Next.js App Router with React Server Components - **Styling**: Material-UI (MUI) + Emotion (use `sx` prop, not CSS modules) - **Testing**: Jest (unit tests), Cypress (E2E tests with accessibility via cypress-axe) @@ -14,6 +15,7 @@ This is a **Next.js portfolio website** using the **App Router** (not Pages Rout ## Critical Workflows ### Development Commands + ```bash npm run dev # Start dev server at localhost:3000 npm run validate # Full CI check: prettier → eslint → tsc → jest → cypress → build → markdown @@ -25,6 +27,7 @@ npm run build # Production build **Always run `npm run validate` before committing.** This is the comprehensive quality gate used in CI/CD. ### Testing Requirements + - **Unit tests**: Every component requires a `.test.tsx` file (see `src/components/banner/Banner.test.tsx`) - **Test setup**: Uses `jest/setup.ts` with jsdom environment - **E2E tests**: Located in `cypress/e2e/`, include accessibility tests (cypress-axe) @@ -33,17 +36,23 @@ npm run build # Production build ## Project-Specific Conventions ### Path Aliases (Critical!) + Always use TypeScript path aliases defined in `tsconfig.json`: + ```typescript -import Avatar from '@components/banner/Avatar'; // NOT '../components/banner/Avatar' -import { DELAYS } from '@constants/index'; // NOT '../../constants' +import Avatar from '@components/banner/Avatar'; +// NOT '../components/banner/Avatar' +import { DELAYS } from '@constants/index'; +// NOT '../../constants' import { isNetworkFast } from '@util/isNetworkFast'; ``` ### Component Patterns #### Material-UI Styling + Use `sx` prop for styling, never inline styles or CSS modules: + ```typescript @@ -64,35 +75,42 @@ export const ExampleIcon = (props: SvgIconProps) => ``` ### Data Management + Static data lives in `src/data/`: + - `projects.ts`: Project portfolio with typed interface - `publications.ts`: Academic publications - `socials.ts`: Social media links - `keywords.ts`: SEO keywords array ### Constants Pattern + Centralized constants in `src/constants/index.ts` with `as const` for type safety: + ```typescript -DELAYS.PROJECT_HOVER_VIDEO // 1000ms before video plays on hover -THRESHOLDS.SNEEZE_TRIGGER_INTERVAL // Easter egg triggers -NETWORK.SLOW_DOWNLINK_THRESHOLD // Network performance checks +DELAYS.PROJECT_HOVER_VIDEO; // 1000ms before video plays on hover +THRESHOLDS.SNEEZE_TRIGGER_INTERVAL; // Easter egg triggers +NETWORK.SLOW_DOWNLINK_THRESHOLD; // Network performance checks ``` ## Code Style & Quality ### Linting & Formatting + - **Indentation**: Tabs (not spaces) - enforced by ESLint - **Line length**: No hard limit, use Prettier - **Import sorting**: Handled by `@trivago/prettier-plugin-sort-imports` - **Unused vars**: Prefix with `_` to ignore (e.g., `_unusedParam`) ### ESLint Rules (see `eslint.config.js`) + - Tabs for indentation (indent: ['error', 'tab']) - Console logs allowed (`no-console: off`) - Unused vars with `_` prefix ignored - React hooks exhaustive deps enforced ### TypeScript + - **Strict mode**: Enabled in `tsconfig.json` - **No implicit any**: All types must be explicit - **React 19**: Uses new `react-jsx` transform @@ -101,7 +119,9 @@ NETWORK.SLOW_DOWNLINK_THRESHOLD // Network performance checks ## Next.js App Router Specifics ### Metadata & SEO + All metadata configured in `src/app/layout.tsx`: + ```typescript export const metadata: Metadata = { title: { template: `%s | ${metadataValues.title}`, default: metadataValues.title }, @@ -112,12 +132,15 @@ export const metadata: Metadata = { ``` ### Server Components vs Client Components + - Default: Server Components (no `'use client'`) - Client-only: Components with hooks, event handlers, browser APIs - Example client component: `src/components/ServiceWorkerRegister.tsx` ### Security Headers + CSP and security headers configured in `next.config.js` headers() function. Includes: + - X-Content-Type-Options: nosniff - X-Frame-Options: DENY - Strict-Transport-Security (HSTS) @@ -126,31 +149,40 @@ CSP and security headers configured in `next.config.js` headers() function. Incl ## Special Features ### Network Performance Optimization + `src/util/isNetworkFast.ts` checks Network Information API to conditionally load heavy assets based on connection speed. ### Easter Eggs + - `src/helpers/aaaahhhh.ts`: Fun image replacement logic triggered by avatar interactions - `src/helpers/ascii.ts`: Console ASCII art ### Service Worker + - Lives in `public/sw.js` and served via `src/app/sw.js/` - Registration in `src/components/ServiceWorkerRegister.tsx` - Used for PWA offline support ## Firebase & Analytics + Initialize Firebase only client-side (see `src/configs/firebase.ts`): + ```typescript import { init, logAnalyticsEvent } from '@configs/firebase'; -init(); // Call once on client mount + +init(); // Call once on client mount logAnalyticsEvent('event_name', { params }); ``` ## Documentation + Architecture docs in `docs/architecture/`: + - `index.md`: System overview - Component-specific docs for Avatar, Projects, Publications, etc. ## Common Gotchas + 1. **Don't** import from relative paths - use path aliases 2. **Don't** forget to update tests when changing components 3. **Always** run `npm run validate` frequently when making changes diff --git a/.github/prompts/audit-docs.prompt.md b/.github/prompts/audit-docs.prompt.md index 8e23c59..04532fd 100644 --- a/.github/prompts/audit-docs.prompt.md +++ b/.github/prompts/audit-docs.prompt.md @@ -18,7 +18,7 @@ Documentation produced by this prompt must serve **two audiences simultaneously* 1. **Internal developers / maintainers** - To understand system internals, architectural decisions, constraints, and design intent - - To preserve *why* things were implemented the way they are and the *how* behind the *what* + - To preserve _why_ things were implemented the way they are and the _how_ behind the _what_ 2. **New or external developers** - To understand how to use the system, APIs, and modules as tools - To quickly navigate from documentation to implementation @@ -64,12 +64,12 @@ Do **not** skip ahead. When documenting behavior, architecture, or usage: 1. **Start with a succinct natural-language explanation** - - Explain *what the component does*, *why it exists*, and *how it fits into the system* + - Explain _what the component does_, _why it exists_, and _how it fits into the system_ 2. **Link directly to the implementation** - Prefer links to real source files over inline code - Example: - > The request validation logic is centralized in `validateRequest`, which enforces schema constraints before execution. - > See implementation: [`src/api/validateRequest.ts`](src/api/validateRequest.ts) + > The request validation logic is centralized in `validateRequest`, which enforces schema constraints before execution. + > See implementation in the corresponding source file (for example under `src/components/` or `src/util/`), and always link to a real file that exists in this repository. 3. **Use inline code blocks sparingly and intentionally** - Include code snippets **only when they materially improve understanding**, such as: - Public API usage examples diff --git a/docs/architecture/app-directory.md b/docs/architecture/app-directory.md index abedc0b..e20424c 100644 --- a/docs/architecture/app-directory.md +++ b/docs/architecture/app-directory.md @@ -1,6 +1,6 @@ # App Directory (Next.js) -This document explains the Next.js App Router directory structure and implementation in the AlexJSully Portfolio project. +This document explains the Next.js App Router directory structure and implementation in the Alexander Sullivan's Portfolio project. ## Overview diff --git a/docs/architecture/components/index.md b/docs/architecture/components/index.md index 1757c2d..19cad3a 100644 --- a/docs/architecture/components/index.md +++ b/docs/architecture/components/index.md @@ -1,6 +1,6 @@ # Components Documentation -This document describes the internal architecture, relationships, and usage of major UI components in the AlexJSully Portfolio project. Components are modular, reusable, and styled with Material-UI and Emotion. +This document describes the internal architecture, relationships, and usage of major UI components in the Alexander Sullivan's Portfolio project. Components are modular, reusable, and styled with Material-UI and Emotion. ## Component List & Hierarchy diff --git a/docs/architecture/data.md b/docs/architecture/data.md index eea3926..bae2dea 100644 --- a/docs/architecture/data.md +++ b/docs/architecture/data.md @@ -1,85 +1,143 @@ # Data Architecture -This document explains how data is structured, managed, and integrated in the AlexJSully Portfolio project, with technical details and TypeScript interfaces. +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 +## Data Sources -### Static Data +All static data is centralized in [src/data/](../../src/data/) for consistency and maintainability: -- `src/data/projects.ts`: Project details (array of project objects) -- `src/data/publications.ts`: Publication details (array of publication objects) -- `src/data/socials.ts`: Social media links (array of social link objects) -- `src/data/keywords.ts`: SEO keywords (string array) +### 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 for real-time and remote data (see `src/configs/firebase.ts`) +- [Firebase integration](../../src/configs/firebase.ts) for analytics, performance monitoring, and real-time features (if configured) ## Data Flow ```mermaid sequenceDiagram - participant User - participant Page - participant Layout + participant Browser + participant NextJS[Next.js Server] participant Component - participant DataFile - User->>Page: Requests page - Page->>Layout: Loads layout - Layout->>Component: Renders components - Component->>DataFile: Imports data - DataFile-->>Component: Returns data - Component-->>Layout: Passes rendered output - Layout-->>Page: Passes rendered output - Page-->>User: Displays page + 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 ``` ## Data Usage in the Codebase -- Data files in `src/data/` provide static and dynamic content for components and pages. -- Components import data directly using TypeScript path aliases (e.g., `@data/projects`). -- Layouts and pages aggregate data from multiple sources for rendering. -- Dynamic data (e.g., from Firebase) is fetched in helper functions or via API routes, then passed to components as props. -- TypeScript interfaces ensure type safety and validation for all imported data. -- Data is used for: - - Rendering project lists, publication cards, and social links - - SEO metadata and keywords - - Navigation and page structure - - Analytics and user interaction tracking - -## 🧩 Data Structures & Interfaces - -- Data is exported as arrays/objects and imported into components using TypeScript path aliases. -- TypeScript interfaces define the structure and validation for each data type. - - Example: - - ```ts - // src/data/projects.ts - export interface Project { - id: string; - title: string; - description: string; - url: string; - tags: string[]; - } - export const projects: Project[] = [ ... ]; - ``` - -## 🔗 Integration & Usage - -- Components import data for rendering lists, cards, and details. -- Layouts use data for navigation and page structure. -- Data is tested and validated using TypeScript and Jest. - -## 🛠️ Extending Data - -- Add new data files in `src/data/`. -- Define TypeScript interfaces for new data types. -- Update components to consume new data as needed. - -## 🔗 Related Docs +- **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 Structures & Interfaces + +### Projects Interface + +Location: [src/data/projects.ts](../../src/data/projects.ts) + +```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 +} +``` -- [Component Documentation](./components/index.md) -- [System Architecture](./index.md) +### Publications Interface + +Location: [src/data/publications.ts](../../src/data/publications.ts) + +```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 +} +``` + +### 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 +} +``` -💡 **Tip:** Use TypeScript interfaces for all data structures to ensure type safety and maintainability. +## Extending Data + +### Adding a New Project + +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 + +### Adding a New Publication + +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 + +### Adding New Keywords + +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 + +## Related Docs + +- [Projects Component Documentation](./components/projects.md) +- [Publications Component Documentation](./components/publications.md) +- [System Architecture](./index.md) +- [Component Documentation](./components/index.md) diff --git a/docs/architecture/helpers.md b/docs/architecture/helpers.md index c18d2d3..0db7dd5 100644 --- a/docs/architecture/helpers.md +++ b/docs/architecture/helpers.md @@ -1,6 +1,6 @@ # Helpers Module Documentation -This document describes the purpose, architecture, and usage of helper functions in the AlexJSully Portfolio project, with technical details and integration patterns. +This document describes the purpose, architecture, and usage of helper functions in the Alexander Sullivan's Portfolio project, with technical details and integration patterns. ## Purpose @@ -8,19 +8,22 @@ Helpers provide reusable utility functions for formatting, logic, and data manip ## Structure -- Location: `src/helpers/` -- Example files: - - `ascii.ts`: Generates ASCII art for branding and fun UI elements. - - `aaaahhhh.ts`: Custom logic for playful UI interactions. -- Test files: - - `ascii.test.ts`: Unit tests for ASCII art generation. - - `aaaahhhh.test.ts`: Tests for custom logic. +**Location:** [src/helpers/](../../src/helpers/) + +### Available Helpers + +- [`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) ## Usage Examples ### ASCII Art Helper -```ts +**Location:** [src/helpers/ascii.ts](../../src/helpers/ascii.ts) + +Generates and logs ASCII art to the browser console on page load. + +```typescript import { consoleLogLogo, debounceConsoleLogLogo } from '@helpers/ascii'; // Print ASCII logo once @@ -30,7 +33,9 @@ consoleLogLogo(); debounceConsoleLogLogo(); ``` -The ASCII helper uses constants for timing: +**Implementation Details:** + +The ASCII helper uses constants for timing control: ```typescript import { DELAYS } from '@constants/index'; @@ -39,11 +44,18 @@ 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 -The `aaaahhhh` helper provides a playful page transformation triggered after multiple avatar sneezes: +**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! -```ts +```typescript import { aaaahhhh, convertAAAAHH, imageAAAAHHHH, textAAAAHHHH } from '@helpers/aaaahhhh'; // Trigger full page transformation @@ -63,49 +75,76 @@ imageAAAAHHHH(); ```mermaid flowchart TD - Trigger[aaaahhhh called] --> Text[textAAAAHHHH] - Trigger --> Images[imageAAAAHHHH] - Text --> Convert[convertAAAAHH] - Convert --> FirstHalf[First half → A] - Convert --> SecondHalf[Second half → H] - Images --> ReplaceImg[Replace all img src] - Images --> ReplaceBg[Replace backgrounds] + Trigger["Avatar sneezes
6 times"] --> AaaahhhhCall["aaaahhhh()"] + AaaahhhhCall --> Text["textAAAAHHHH()"] + AaaahhhhCall --> Images["imageAAAAHHHH()"] + + Text --> Convert["convertAAAAHH()"] + Convert --> FirstHalf["First half → A"] + Convert --> SecondHalf["Second half → H"] + + Images --> ReplaceImg["Replace img src"] + Images --> ReplaceBg["Replace bg images"] + + FirstHalf --> TextElements["Apply to: span, p, h1-h3, button"] + SecondHalf --> TextElements + + ReplaceImg --> ImageElements["All img & bg-image elements"] + ReplaceBg --> ImageElements + + TextElements --> Result["Aahh aaaaaahhhh!"] + ImageElements --> Result ``` **Text Conversion Logic:** - First half of word → 'A' (or 'a' if lowercase) - Second half of word → 'H' (or 'h' if lowercase) -- Spaces preserved -- Example: "Alexander" → "Aaaahhhhr", "SULLIVAN" → "AAAAHHHH" +- Spaces and special characters preserved **Image Transformation:** - Replaces all `` src and srcset attributes -- Replaces all background images in style attributes -- Updates the stars background (#sky) with cover image -- Uses `/images/aaaahhhh/aaaahhhh.webp` as replacement +- Replaces all CSS background images in style attributes +- Updates the stars background with cover image +- Uses `/images/aaaahhhh/aaaahhhh.webp` as replacement image **Target Elements:** -- Text: ``, `

`, `

`, `

`, `

`, `