├── .eslintrc.json ├── app ├── favicon.ico ├── components │ ├── About │ │ ├── SystemInfo.js │ │ ├── ScoreExplanation.js │ │ ├── TestProcedure.js │ │ └── About.js │ ├── Newsletter.js │ ├── StickyAnnouncement.js │ ├── DarkModeToggle.js │ ├── Footer.js │ ├── BrowserCard.js │ ├── Header.js │ └── BrowserBarChart.js ├── hooks │ └── useLocalStorage.js ├── globals.css ├── page.js ├── lib │ └── getBrowsers.js ├── layout.js └── privacy │ └── page.js ├── public ├── images │ ├── logo.png │ ├── BlueskyLogo.png │ ├── browser-logos │ │ ├── arc.png │ │ ├── ddg.jpg │ │ ├── dia.png │ │ ├── neo.jpg │ │ ├── ora.png │ │ ├── tor.png │ │ ├── via.png │ │ ├── web.png │ │ ├── brave.png │ │ ├── chrome.png │ │ ├── edge.png │ │ ├── fellou.jpg │ │ ├── floorp.png │ │ ├── helium.jpg │ │ ├── kito.png │ │ ├── kiwi.png │ │ ├── kosmik.jpg │ │ ├── meteor.jpg │ │ ├── mull.png │ │ ├── nook.jpg │ │ ├── opera.png │ │ ├── orion.png │ │ ├── quetta.png │ │ ├── safari.png │ │ ├── shift.jpg │ │ ├── soul.png │ │ ├── yandex.png │ │ ├── cromite.png │ │ ├── firefox.png │ │ ├── ghostery.png │ │ ├── iceraven.png │ │ ├── mullvad.png │ │ ├── opera-gx.png │ │ ├── sigmaos.png │ │ ├── thorium.webp │ │ ├── vivaldi.png │ │ ├── waterfox.png │ │ ├── bravebeta.webp │ │ ├── browseros.jpg │ │ ├── chromebeta.png │ │ ├── chromedev.webp │ │ ├── deta-surf.png │ │ ├── edge-beta.png │ │ ├── edge-canary.png │ │ ├── firefox-dev.png │ │ ├── opera-beta.webp │ │ ├── opera-mini.png │ │ ├── strawberry.png │ │ ├── bravenightly.webp │ │ ├── chrome-canary.png │ │ ├── firefox-beta.png │ │ ├── yandex-alpha.png │ │ ├── yandex-beta.webp │ │ ├── zen-twilight.png │ │ ├── firefox-nightly.png │ │ ├── samsung-internet.png │ │ ├── vivaldi-snapshot.png │ │ ├── samsung-internet-beta.png │ │ ├── zen.svg │ │ ├── librewolf.svg │ │ └── comet.svg │ ├── TelegramLogo.svg │ ├── TwitterLogo.svg │ └── RedditLogo.svg └── data │ ├── raw-data.xlsx │ ├── ipad.json │ ├── windows.json │ ├── browsers.json │ ├── android.json │ └── macos-intel.json ├── jsconfig.json ├── postcss.config.mjs ├── next.config.mjs ├── .gitignore ├── package.json ├── .github ├── FUNDING.yml └── dependabot.yml ├── tailwind.config.js └── README.md /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/app/favicon.ico -------------------------------------------------------------------------------- /public/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/logo.png -------------------------------------------------------------------------------- /public/data/raw-data.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/data/raw-data.xlsx -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "paths": { 4 | "@/*": ["./*"] 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /public/images/BlueskyLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/BlueskyLogo.png -------------------------------------------------------------------------------- /public/images/browser-logos/arc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/arc.png -------------------------------------------------------------------------------- /public/images/browser-logos/ddg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/ddg.jpg -------------------------------------------------------------------------------- /public/images/browser-logos/dia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/dia.png -------------------------------------------------------------------------------- /public/images/browser-logos/neo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/neo.jpg -------------------------------------------------------------------------------- /public/images/browser-logos/ora.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/ora.png -------------------------------------------------------------------------------- /public/images/browser-logos/tor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/tor.png -------------------------------------------------------------------------------- /public/images/browser-logos/via.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/via.png -------------------------------------------------------------------------------- /public/images/browser-logos/web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/web.png -------------------------------------------------------------------------------- /public/images/browser-logos/brave.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/brave.png -------------------------------------------------------------------------------- /public/images/browser-logos/chrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/chrome.png -------------------------------------------------------------------------------- /public/images/browser-logos/edge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/edge.png -------------------------------------------------------------------------------- /public/images/browser-logos/fellou.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/fellou.jpg -------------------------------------------------------------------------------- /public/images/browser-logos/floorp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/floorp.png -------------------------------------------------------------------------------- /public/images/browser-logos/helium.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/helium.jpg -------------------------------------------------------------------------------- /public/images/browser-logos/kito.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/kito.png -------------------------------------------------------------------------------- /public/images/browser-logos/kiwi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/kiwi.png -------------------------------------------------------------------------------- /public/images/browser-logos/kosmik.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/kosmik.jpg -------------------------------------------------------------------------------- /public/images/browser-logos/meteor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/meteor.jpg -------------------------------------------------------------------------------- /public/images/browser-logos/mull.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/mull.png -------------------------------------------------------------------------------- /public/images/browser-logos/nook.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/nook.jpg -------------------------------------------------------------------------------- /public/images/browser-logos/opera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/opera.png -------------------------------------------------------------------------------- /public/images/browser-logos/orion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/orion.png -------------------------------------------------------------------------------- /public/images/browser-logos/quetta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/quetta.png -------------------------------------------------------------------------------- /public/images/browser-logos/safari.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/safari.png -------------------------------------------------------------------------------- /public/images/browser-logos/shift.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/shift.jpg -------------------------------------------------------------------------------- /public/images/browser-logos/soul.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/soul.png -------------------------------------------------------------------------------- /public/images/browser-logos/yandex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/yandex.png -------------------------------------------------------------------------------- /public/images/browser-logos/cromite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/cromite.png -------------------------------------------------------------------------------- /public/images/browser-logos/firefox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/firefox.png -------------------------------------------------------------------------------- /public/images/browser-logos/ghostery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/ghostery.png -------------------------------------------------------------------------------- /public/images/browser-logos/iceraven.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/iceraven.png -------------------------------------------------------------------------------- /public/images/browser-logos/mullvad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/mullvad.png -------------------------------------------------------------------------------- /public/images/browser-logos/opera-gx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/opera-gx.png -------------------------------------------------------------------------------- /public/images/browser-logos/sigmaos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/sigmaos.png -------------------------------------------------------------------------------- /public/images/browser-logos/thorium.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/thorium.webp -------------------------------------------------------------------------------- /public/images/browser-logos/vivaldi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/vivaldi.png -------------------------------------------------------------------------------- /public/images/browser-logos/waterfox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/waterfox.png -------------------------------------------------------------------------------- /public/images/browser-logos/bravebeta.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/bravebeta.webp -------------------------------------------------------------------------------- /public/images/browser-logos/browseros.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/browseros.jpg -------------------------------------------------------------------------------- /public/images/browser-logos/chromebeta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/chromebeta.png -------------------------------------------------------------------------------- /public/images/browser-logos/chromedev.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/chromedev.webp -------------------------------------------------------------------------------- /public/images/browser-logos/deta-surf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/deta-surf.png -------------------------------------------------------------------------------- /public/images/browser-logos/edge-beta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/edge-beta.png -------------------------------------------------------------------------------- /public/images/browser-logos/edge-canary.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/edge-canary.png -------------------------------------------------------------------------------- /public/images/browser-logos/firefox-dev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/firefox-dev.png -------------------------------------------------------------------------------- /public/images/browser-logos/opera-beta.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/opera-beta.webp -------------------------------------------------------------------------------- /public/images/browser-logos/opera-mini.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/opera-mini.png -------------------------------------------------------------------------------- /public/images/browser-logos/strawberry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/strawberry.png -------------------------------------------------------------------------------- /public/images/browser-logos/bravenightly.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/bravenightly.webp -------------------------------------------------------------------------------- /public/images/browser-logos/chrome-canary.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/chrome-canary.png -------------------------------------------------------------------------------- /public/images/browser-logos/firefox-beta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/firefox-beta.png -------------------------------------------------------------------------------- /public/images/browser-logos/yandex-alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/yandex-alpha.png -------------------------------------------------------------------------------- /public/images/browser-logos/yandex-beta.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/yandex-beta.webp -------------------------------------------------------------------------------- /public/images/browser-logos/zen-twilight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/zen-twilight.png -------------------------------------------------------------------------------- /public/images/browser-logos/firefox-nightly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/firefox-nightly.png -------------------------------------------------------------------------------- /public/images/browser-logos/samsung-internet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/samsung-internet.png -------------------------------------------------------------------------------- /public/images/browser-logos/vivaldi-snapshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/vivaldi-snapshot.png -------------------------------------------------------------------------------- /public/images/browser-logos/samsung-internet-beta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kawaiier/browserating/HEAD/public/images/browser-logos/samsung-internet-beta.png -------------------------------------------------------------------------------- /postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | images: { 4 | domains: ["storage.ko-fi.com"], 5 | }, 6 | }; 7 | 8 | export default nextConfig; 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | .aider* 38 | .env 39 | .cursor/ 40 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "browserating", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@vercel/analytics": "^1.5.0", 13 | "chart.js": "^4.4.6", 14 | "lucide-react": "^0.556.0", 15 | "next": "16.0.8", 16 | "react": "^19", 17 | "react-chartjs-2": "^5.2.0", 18 | "react-dom": "^18" 19 | }, 20 | "devDependencies": { 21 | "eslint": "^9", 22 | "eslint-config-next": "16.0.8", 23 | "postcss": "^8", 24 | "tailwindcss": "^3.4.1" 25 | }, 26 | "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" 27 | } 28 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: kawaiier 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 12 | polar: # Replace with a single Polar username 13 | buy_me_a_coffee: # Replace with a single Buy Me a Coffee username 14 | thanks_dev: # Replace with a single thanks.dev username 15 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 16 | -------------------------------------------------------------------------------- /public/images/TelegramLogo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/components/About/SystemInfo.js: -------------------------------------------------------------------------------- 1 | export default function SystemInfo({ title, details }) { 2 | return ( 3 |
4 | 24 |
25 | {details} 26 |
27 |
28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /public/images/browser-logos/zen.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # .github/dependabot.yml 2 | # ------------------------------------------------- 3 | # Dependabot version‑update configuration 4 | # ------------------------------------------------- 5 | version: 2 6 | 7 | updates: 8 | # 1️⃣ npm (Node.js / TypeScript) dependencies 9 | - package-ecosystem: "npm" 10 | directory: "/" 11 | schedule: 12 | interval: "daily" 13 | time: "04:00" 14 | open-pull-requests-limit: 10 15 | labels: 16 | - "dependencies" 17 | - "npm" 18 | commit-message: 19 | prefix: "chore" 20 | prefix-development: "chore" 21 | include: "scope" 22 | 23 | # 2️⃣ Docker images referenced in Dockerfiles 24 | - package-ecosystem: "docker" 25 | directory: "/" 26 | schedule: 27 | interval: "weekly" 28 | day: "wednesday" 29 | time: "03:00" 30 | open-pull-requests-limit: 5 31 | labels: 32 | - "dependencies" 33 | - "docker" 34 | 35 | # 3️⃣ GitHub Actions workflow files 36 | - package-ecosystem: "github-actions" 37 | directory: "/.github/workflows" 38 | schedule: 39 | interval: "weekly" 40 | day: "friday" 41 | time: "02:00" 42 | open-pull-requests-limit: 5 43 | labels: 44 | - "dependencies" 45 | - "github-actions" 46 | -------------------------------------------------------------------------------- /public/images/TwitterLogo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | darkMode: "class", 4 | content: [ 5 | "./pages/**/*.{js,ts,jsx,tsx,mdx}", 6 | "./components/**/*.{js,ts,jsx,tsx,mdx}", 7 | "./app/**/*.{js,ts,jsx,tsx,mdx}", 8 | ], 9 | theme: { 10 | extend: { 11 | backgroundImage: { 12 | "gradient-radial": "radial-gradient(var(--tw-gradient-stops))", 13 | "gradient-conic": 14 | "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))", 15 | }, 16 | keyframes: { 17 | "fade-out": { 18 | "0%": { opacity: "1" }, 19 | "75%": { opacity: "1" }, 20 | "100%": { opacity: "0" }, 21 | }, 22 | "bounce-gentle": { 23 | "0%, 100%": { 24 | transform: "rotate(12deg) translateY(-5%)", 25 | animationTimingFunction: "cubic-bezier(0.8, 0, 1, 1)", 26 | }, 27 | "50%": { 28 | transform: "rotate(12deg) translateY(0)", 29 | animationTimingFunction: "cubic-bezier(0, 0, 0.2, 1)", 30 | }, 31 | }, 32 | }, 33 | animation: { 34 | "fade-out": "fade-out 2s ease-out forwards", 35 | "bounce-gentle": "bounce-gentle 2s infinite", 36 | }, 37 | }, 38 | }, 39 | plugins: [], 40 | }; 41 | -------------------------------------------------------------------------------- /app/hooks/useLocalStorage.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | 3 | export function useLocalStorage(key, defaultValue) { 4 | // Initialize state with default value 5 | const [storedValue, setStoredValue] = useState(defaultValue); 6 | const [isLoaded, setIsLoaded] = useState(false); 7 | 8 | // Load value from localStorage on mount (client-side only) 9 | useEffect(() => { 10 | try { 11 | if (typeof window !== "undefined") { 12 | const item = window.localStorage.getItem(key); 13 | if (item) { 14 | setStoredValue(JSON.parse(item)); 15 | } 16 | } 17 | } catch (error) { 18 | console.warn(`Error reading localStorage key "${key}":`, error); 19 | } finally { 20 | setIsLoaded(true); 21 | } 22 | }, [key]); 23 | 24 | // Return a wrapped version of useState's setter function that persists the new value to localStorage 25 | const setValue = (value) => { 26 | try { 27 | // Allow value to be a function so we have the same API as useState 28 | const valueToStore = 29 | value instanceof Function ? value(storedValue) : value; 30 | 31 | // Save state 32 | setStoredValue(valueToStore); 33 | 34 | // Save to localStorage (client-side only) 35 | if (typeof window !== "undefined") { 36 | window.localStorage.setItem(key, JSON.stringify(valueToStore)); 37 | } 38 | } catch (error) { 39 | console.warn(`Error setting localStorage key "${key}":`, error); 40 | } 41 | }; 42 | 43 | return [storedValue, setValue, isLoaded]; 44 | } 45 | -------------------------------------------------------------------------------- /app/components/About/ScoreExplanation.js: -------------------------------------------------------------------------------- 1 | export default function ScoreExplanation() { 2 | return ( 3 |
4 |

5 | 6 | The higher the score, the faster the browser. 7 | {" "} 8 | Speedometer 3.1 measures browser performance by simulating user 9 | interactions on various web applications. 10 |

11 | 12 |
13 |

14 | Score Interpretation: 15 |

16 | 30 |
31 | 32 |

33 | Note: Performance may vary based on your specific hardware, operating 34 | system version, and browser configuration. 35 |

36 |
37 | ); 38 | } 39 | -------------------------------------------------------------------------------- /app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | @keyframes fade-in { 6 | 0% { 7 | opacity: 0; 8 | transform: scale(0.95); /* Optional: Slightly scale down */ 9 | } 10 | 100% { 11 | opacity: 1; 12 | transform: scale(1); /* Return to normal scale */ 13 | } 14 | } 15 | 16 | .fade-in { 17 | animation: fade-in 0.4s ease-in-out forwards; /* Adjust duration and easing as needed */ 18 | } 19 | 20 | @keyframes twinkle { 21 | 0%, 22 | 100% { 23 | opacity: 1; 24 | } 25 | 50% { 26 | opacity: 0.3; 27 | } 28 | } 29 | 30 | .animate-twinkle { 31 | animation: twinkle 2s ease-in-out infinite; 32 | } 33 | 34 | @keyframes bounce-gentle { 35 | 0%, 36 | 100% { 37 | transform: translateY(0); 38 | } 39 | 50% { 40 | transform: translateY(-5px); 41 | } 42 | } 43 | 44 | .animate-bounce-gentle { 45 | animation: bounce-gentle 2s ease-in-out infinite; 46 | } 47 | 48 | /* Improved focus styles for better accessibility */ 49 | :focus-visible { 50 | outline: 2px solid #7853e0; 51 | outline-offset: 2px; 52 | border-radius: 0.25rem; 53 | } 54 | 55 | /* Ensure interactive elements have proper focus states */ 56 | a:focus-visible, 57 | button:focus-visible, 58 | input:focus-visible, 59 | select:focus-visible, 60 | textarea:focus-visible, 61 | [tabindex]:focus-visible { 62 | outline: 2px solid #7853e0; 63 | outline-offset: 2px; 64 | box-shadow: 0 0 0 4px rgba(120, 83, 224, 0.2); 65 | } 66 | 67 | /* Dark mode focus styles */ 68 | .dark a:focus-visible, 69 | .dark button:focus-visible, 70 | .dark input:focus-visible, 71 | .dark select:focus-visible, 72 | .dark textarea:focus-visible, 73 | .dark [tabindex]:focus-visible { 74 | outline-color: #9b7be8; 75 | box-shadow: 0 0 0 4px rgba(155, 123, 232, 0.2); 76 | } 77 | -------------------------------------------------------------------------------- /public/images/RedditLogo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/page.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useEffect, useState } from "react"; 4 | 5 | import About from "./components/About/About"; 6 | import BrowserRankingList from "./components/BrowserRankingList"; 7 | import Explanation from "./components/Explanation"; 8 | import Footer from "./components/Footer"; 9 | import Header from "./components/Header"; 10 | import Newsletter from "./components/Newsletter"; 11 | 12 | export default function Home() { 13 | const [darkMode, setDarkMode] = useState(false); 14 | const [mounted, setMounted] = useState(false); 15 | 16 | useEffect(() => { 17 | // Check initial theme preference 18 | const isDarkMode = 19 | localStorage?.getItem("darkMode") === "true" || 20 | (!("darkMode" in localStorage) && 21 | window?.matchMedia?.("(prefers-color-scheme: dark)")?.matches); 22 | 23 | setDarkMode(isDarkMode); 24 | if (isDarkMode) { 25 | document.documentElement.classList.add("dark"); 26 | } 27 | setMounted(true); 28 | }, []); 29 | 30 | const toggleDarkMode = () => { 31 | const newDarkMode = !darkMode; 32 | setDarkMode(newDarkMode); 33 | document.documentElement.classList.toggle("dark"); 34 | localStorage.setItem("darkMode", newDarkMode); 35 | }; 36 | 37 | // Prevent hydration mismatch by not rendering until mounted 38 | if (!mounted) { 39 | return null; 40 | } 41 | 42 | return ( 43 |
44 | 48 | Skip to content 49 | 50 |
51 |
52 | 53 | 54 | 55 | 56 |
57 |
59 | ); 60 | } 61 | -------------------------------------------------------------------------------- /app/components/Newsletter.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | 3 | export default function Newsletter() { 4 | const [subscriberCount, setSubscriberCount] = useState(7); // Dynamic count 5 | 6 | // Simulate growing subscriber count 7 | useEffect(() => { 8 | const interval = setInterval(() => { 9 | setSubscriberCount((prev) => prev + Math.floor(Math.random() * 3)); 10 | }, 30000); // Update every 30 seconds 11 | return () => clearInterval(interval); 12 | }, []); 13 | 14 | return ( 15 |
16 | {/* Background pattern */} 17 | 18 |
19 |
20 |