-
Notifications
You must be signed in to change notification settings - Fork 1
Fix Firefox performance #61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
fa442da
Add CLAUDE.md with project guidance for Claude Code
ThomasJButler 4f715fa
Fix Firefox performance: disable expensive CSS effects, throttle canv…
ThomasJButler bea38af
Revert "Add CLAUDE.md with project guidance for Claude Code"
ThomasJButler 52603d0
Reapply "Add CLAUDE.md with project guidance for Claude Code"
ThomasJButler d5251b5
remove claude.md
ThomasJButler File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| # CLAUDE.md | ||
|
|
||
| This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. | ||
|
|
||
| ## Project Overview | ||
|
|
||
| Personal portfolio website for Thomas J Butler — a React 19 + TypeScript SPA with a Matrix-themed aesthetic (green terminal effects, CRT overlays, particle backgrounds). Deployed to GitHub Pages at thomasjbutler.github.io. | ||
|
|
||
| ## Commands | ||
|
|
||
| | Command | Purpose | | ||
| |---------|---------| | ||
| | `npm run dev` | Dev server on port 3000 (opens /react.html) | | ||
| | `npm run build` | Production build to dist/ | | ||
| | `npm run preview` | Preview production build | | ||
| | `npm run lint` | ESLint on src/**/*.{js,ts} | | ||
| | `npm run format` | Prettier on src/**/*.{js,ts,css,html} | | ||
| | `npm run type-check` | TypeScript check (no emit) | | ||
| | `npm run test` | Vitest | | ||
| | `npm run test:ui` | Vitest with UI | | ||
| | `npm run test:coverage` | Vitest with coverage | | ||
| | `npm run deploy` | Build + deploy to GitHub Pages via gh-pages | | ||
|
|
||
| ## Architecture | ||
|
|
||
| **Stack:** React 19, TypeScript (strict), Vite 7, React Router v7 (BrowserRouter) | ||
|
|
||
| **Entry flow:** `index.html` redirects to `react.html`, which loads `src/main.tsx` -> `App.tsx`. A third entry `blog.html` exists for legacy blog URL compatibility. | ||
|
|
||
| **Routing:** All pages are lazy-loaded via `React.lazy()` + `Suspense` in `App.tsx`. Blog routes are currently commented out. Legacy `.html` routes redirect to clean paths. The `/skills` route redirects to `/services`. | ||
|
|
||
| **CSS architecture:** `src/css/main.css` is the master import file. Styles are organized into `base/`, `components/`, `pages/`, and `utilities/` subdirectories using partial files (prefixed with `_`). Theme variables live in `themes.css` with light/dark mode via CSS custom properties and React Context (`ThemeContext`). | ||
|
|
||
| **Animation libraries:** GSAP, Anime.js (v4), Framer Motion, AOS (Animate On Scroll), ScrollMagic. Matrix rain, CRT effects, and particle backgrounds are custom implementations. | ||
|
|
||
| **Path aliases:** `@/` -> `src/`, plus `@components/`, `@pages/`, `@hooks/`, `@utils/`, `@css/`, `@js/`, `@images/` (configured in both tsconfig.json and vite.config.mjs). | ||
|
|
||
| **Key directories:** | ||
| - `src/pages/` — Route-level page components | ||
| - `src/components/` — Reusable UI components | ||
| - `src/hooks/` — Custom hooks (scroll animation, lazy loading, SEO, performance) | ||
| - `src/utils/` — Utilities (keyboard nav, performance optimizer, animations) | ||
| - `src/contexts/` — React Context (ThemeContext for light/dark mode) | ||
| - `src/css/` — Organized stylesheet modules | ||
| - `src/content/blog/` — Markdown blog posts (copied to dist on build) | ||
|
|
||
| ## Code Style | ||
|
|
||
| - Prettier: single quotes, semicolons, 100 char width, trailing commas (es5) | ||
| - ESLint: TypeScript strict, React hooks rules, no-var, no-require | ||
| - Components use named exports (not default), except where lazy loading requires `.then(m => ({ default: m.ComponentName }))` | ||
| - Global animation libs (anime, gsap, ScrollMagic, AOS) are declared as ESLint globals | ||
|
|
||
| ## Deployment | ||
|
|
||
| GitHub Actions workflow (`.github/workflows/deploy.yml`) auto-deploys on push to main. Manual deploys via `npm run deploy` use the `gh-pages` package to push `dist/` to the gh-pages branch. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,130 @@ | ||
| /* ========================================================================== | ||
| Firefox Performance Overrides | ||
| Reduces expensive CSS effects that Firefox renders less efficiently | ||
| than Chromium browsers. Applied via .is-firefox class on <html>. | ||
| ========================================================================== */ | ||
|
|
||
| /* ========================================================================== | ||
| Backdrop Filter Reduction | ||
| Firefox supports backdrop-filter but renders it expensively. | ||
| Replace blur effects with solid semi-transparent backgrounds. | ||
| ========================================================================== */ | ||
|
|
||
| .is-firefox header, | ||
| .is-firefox footer, | ||
| .is-firefox .footer, | ||
| .is-firefox section, | ||
| .is-firefox form, | ||
| .is-firefox .form-container, | ||
| .is-firefox .matrix-spinner-overlay, | ||
| .is-firefox nav ul, | ||
| .is-firefox nav ul.mobile-open, | ||
| .is-firefox header.scrolled, | ||
| .is-firefox .backdrop-performance { | ||
| backdrop-filter: none !important; | ||
| -webkit-backdrop-filter: none !important; | ||
| } | ||
|
|
||
| /* Compensate for lost blur with slightly more opaque backgrounds */ | ||
| .is-firefox header { | ||
| background: rgba(26, 26, 26, 0.98) !important; | ||
| } | ||
|
|
||
| .is-firefox footer, | ||
| .is-firefox .footer { | ||
| background: rgba(26, 26, 26, 0.95) !important; | ||
| } | ||
|
|
||
| .is-firefox section { | ||
| background-color: var(--matrix-darker) !important; | ||
| } | ||
|
|
||
| .is-firefox nav ul { | ||
| background: rgba(0, 20, 0, 0.98) !important; | ||
| } | ||
|
|
||
| .is-firefox form, | ||
| .is-firefox .form-container { | ||
| background: rgba(0, 20, 0, 0.85) !important; | ||
| } | ||
|
|
||
| /* ========================================================================== | ||
| Will-Change Cleanup | ||
| Firefox doesn't release will-change layers efficiently. | ||
| Remove persistent will-change; let the browser optimize naturally. | ||
| ========================================================================== */ | ||
|
|
||
| .is-firefox .mainContent, | ||
| .is-firefox header, | ||
| .is-firefox footer, | ||
| .is-firefox .back-to-top { | ||
| will-change: auto !important; | ||
| } | ||
|
|
||
| .is-firefox .will-change-transform, | ||
| .is-firefox .will-change-opacity, | ||
| .is-firefox .will-change-filter, | ||
| .is-firefox .will-change-contents, | ||
| .is-firefox .interactive, | ||
| .is-firefox .gpu-accelerated { | ||
| will-change: auto !important; | ||
| } | ||
|
|
||
| /* ========================================================================== | ||
| Filter Animation Reduction | ||
| CSS filter animations (hue-rotate, brightness, blur) are not | ||
| GPU-accelerated in Firefox. Simplify or disable them. | ||
| ========================================================================== */ | ||
|
|
||
| .is-firefox .glitch-text:hover { | ||
| animation: none !important; | ||
| } | ||
|
|
||
| .is-firefox .matrix-rain-background { | ||
| filter: none !important; | ||
| } | ||
|
|
||
| /* ========================================================================== | ||
| Scanline Overlay Optimization | ||
| The full-screen repeating-gradient scanline is expensive in Firefox. | ||
| Reduce opacity to minimize compositing cost. | ||
| ========================================================================== */ | ||
|
|
||
| .is-firefox [data-theme="matrix"] body::after { | ||
| opacity: 0.2; | ||
| } | ||
|
|
||
| /* ========================================================================== | ||
| Text Shadow / Glow Reduction | ||
| Firefox renders multi-layer text-shadow less efficiently. | ||
| Simplify to single-layer glows. | ||
| ========================================================================== */ | ||
|
|
||
| .is-firefox [data-theme="matrix"] h1, | ||
| .is-firefox [data-theme="matrix"] h2, | ||
| .is-firefox [data-theme="matrix"] .section-title, | ||
| .is-firefox [data-theme="matrix"] .page-heading { | ||
| text-shadow: 0 0 10px var(--glow-color-primary) !important; | ||
| } | ||
|
|
||
| /* ========================================================================== | ||
| Transition Simplification | ||
| Reduce the global wildcard transition on theme changes. | ||
| ========================================================================== */ | ||
|
|
||
| .is-firefox * { | ||
| transition-property: none !important; | ||
| } | ||
|
|
||
| .is-firefox a, | ||
| .is-firefox button, | ||
| .is-firefox input, | ||
| .is-firefox textarea, | ||
| .is-firefox header, | ||
| .is-firefox [class*="card"], | ||
| .is-firefox [class*="btn"], | ||
| .is-firefox .menu-toggle, | ||
| .is-firefox nav ul { | ||
| transition-property: color, background-color, border-color, opacity, transform, box-shadow !important; | ||
| transition-duration: 0.2s !important; | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: ThomasJButler/thomasjbutler.github.io
Length of output: 164
🏁 Script executed:
Repository: ThomasJButler/thomasjbutler.github.io
Length of output: 4195
Fix unreachable CSS selector for scanline opacity override.
Line 93 (
.is-firefox [data-theme="matrix"] body::after) is unreachable becausedata-themeis applied to the html element itself (viadocument.documentElement.setAttribute('data-theme', theme)in ThemeContext.tsx), not to a descendant. The current selector tries to match[data-theme="matrix"]as a descendant of.is-firefox(which is the html element), making it impossible to match.Proposed fix
Combine the
.is-firefoxand[data-theme="matrix"]selectors on the same element (html) since both conditions are applied to it.📝 Committable suggestion
🤖 Prompt for AI Agents