From 3fa6d54866388b9eca794e326bb50ffa4075ca2d Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sat, 23 Aug 2025 23:01:03 +0100 Subject: [PATCH 01/12] homepage styling --- website/static/css/chart-stuff.css | 15 +++++---------- website/static/css/homepage.css | 7 ++++++- website/static/js/framework-table.js | 7 ++----- website/templates/base.html | 2 +- 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/website/static/css/chart-stuff.css b/website/static/css/chart-stuff.css index 5c823f47..938fbccc 100644 --- a/website/static/css/chart-stuff.css +++ b/website/static/css/chart-stuff.css @@ -1,12 +1,9 @@ .charts-section { - padding: 1rem 2rem; - border-radius: 12px; -} - -.charts-section h2 { - text-align: center; - margin-bottom: 2rem; - color: var(--text-primary, #2c3e50); + h2 { + text-align: center; + margin-bottom: 2rem; + color: var(--text-primary, #2c3e50); + } } /* Framework Toggle Styles */ @@ -15,7 +12,6 @@ border: 1px solid rgba(0, 0, 0, 0.1); border-radius: 8px; padding: 1rem; - max-width: 87.5rem; margin: 0 auto 1.5rem; .toggle-header { @@ -107,7 +103,6 @@ display: grid; grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); gap: 1.5rem; - max-width: 1400px; margin: 0 auto; } diff --git a/website/static/css/homepage.css b/website/static/css/homepage.css index eaa0bc32..218f939e 100644 --- a/website/static/css/homepage.css +++ b/website/static/css/homepage.css @@ -24,6 +24,12 @@ flex-wrap: wrap; padding: 1rem; align-items: end; + @media (min-width: 768px) { + margin: 5rem auto; + } + @media (min-width: 1200px) { + transform: scale(1.1); + } .subtitle { font-size: 1.2em; margin-top: 0.5rem; @@ -88,7 +94,6 @@ h2 { font-weight: 500; margin-top: 1rem; margin: 1rem auto 0 auto; - padding-left: 2rem; } diff --git a/website/static/js/framework-table.js b/website/static/js/framework-table.js index 0b59cf4e..cca26a0b 100644 --- a/website/static/js/framework-table.js +++ b/website/static/js/framework-table.js @@ -136,10 +136,7 @@ class FrameworkTable { type: 'numericColumn', cellRenderer: (params) => { const open = params.value || 0; - const closed = params.data.closed_issues || 0; - const total = open + closed; - const openPct = total > 0 ? (open / total) * 100 : 0; - const color = openPct > 20 ? '#f44336' : openPct > 10 ? '#ff9800' : '#4caf50'; + const color = open > 400 ? '#f44336' : open > 200 ? '#ff9800' : '#4caf50'; return `${open}`; }, sortable: true, @@ -257,4 +254,4 @@ if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initFrameworkTable); } else { initFrameworkTable(); -} \ No newline at end of file +} diff --git a/website/templates/base.html b/website/templates/base.html index 72f0d80a..0c20e1f1 100644 --- a/website/templates/base.html +++ b/website/templates/base.html @@ -58,7 +58,7 @@

{{ config.website.title }}

Free and open source, forever

lissy93/weather-front - Licensed under + is licensed under MIT โ€ข © 2025 Alicia Sykes

From 588714b28df243ac17c511f33670697ae85f61cc Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sat, 23 Aug 2025 23:12:04 +0100 Subject: [PATCH 02/12] Redesigned homepage --- website/static/css/homepage.css | 420 +++++++++++++++++++++++--------- website/static/css/main.css | 75 ++++-- website/templates/base.html | 5 + 3 files changed, 366 insertions(+), 134 deletions(-) diff --git a/website/static/css/homepage.css b/website/static/css/homepage.css index 218f939e..102dfdea 100644 --- a/website/static/css/homepage.css +++ b/website/static/css/homepage.css @@ -1,186 +1,299 @@ - .homepage-container { margin: 0 auto; max-width: 87.5rem; + padding: 0 1rem; } - .navigation { display: none !important; } +/* Hero Section */ .hero { - display: flex; - border: 2px solid var(--card-border); - border-radius: 12px; - transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1); - background: var(--card-bg); + background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%); + border: 1px solid rgba(102, 126, 234, 0.2); + border-radius: var(--border-radius); + margin: 2rem auto 4rem; + padding: 3rem 2rem; + position: relative; + overflow: hidden; + + &::before { + content: ''; + position: absolute; + top: -50%; + left: -50%; + width: 200%; + height: 200%; + background: radial-gradient(circle, rgba(102, 126, 234, 0.05) 0%, transparent 50%); + animation: pulse 4s ease-in-out infinite; + } + display: flex; align-items: center; - box-shadow: var(--shadow); - max-width: 64rem; - margin: 0 auto; - gap: 1rem; + gap: 3rem; flex-wrap: wrap; - padding: 1rem; - align-items: end; - @media (min-width: 768px) { - margin: 5rem auto; - } - @media (min-width: 1200px) { - transform: scale(1.1); - } - .subtitle { - font-size: 1.2em; - margin-top: 0.5rem; + + .hero-left { + flex: 1; + min-width: 300px; + z-index: 2; + + h1 { + font-size: clamp(2.5rem, 5vw, 4rem); + font-weight: 800; + margin-bottom: 1rem; + background: var(--gradient); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + line-height: 1.1; + } + + .subtitle { + font-size: 1.25rem; + color: var(--text-muted); + margin-bottom: 2rem; + line-height: 1.6; + } } + .hero-buttons { display: flex; - gap: 0.8rem; + gap: 1rem; flex-wrap: wrap; + margin-top: 1rem; } + .primary-cta, .secondary-cta { - text-decoration: none; - border: 2px solid var(--card-border); - text-align: center; - transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1); - position: relative; - overflow: hidden; - display: flex; - align-items: center; - box-shadow: var(--shadow); - width: fit-content; - padding: 0.25rem 0.5rem; - font-size: 1.1rem; - font-weight: 600; - border-radius: 8px; - color: var(--text-color, #2c3e50); - min-width: 80px; - text-align: center; - display: flex; - justify-content: center; - flex: 1; + padding: 0.5rem 1.25rem; + border-radius: 0.5rem; + font-weight: 600; + font-size: 1rem; + transition: var(--transition); + text-decoration: none; + position: relative; + overflow: hidden; + + &::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent); + transition: left 0.6s; + } + + &:hover::before { + left: 100%; + } } - + .primary-cta { - color: var(--bg-color); - background: #6762ff; + background: var(--gradient); + color: white; + border: none; + box-shadow: var(--shadow-lg); + transform: translateY(0); + + &:hover { + transform: translateY(-2px); + box-shadow: 0 25px 50px -12px rgba(102, 126, 234, 0.25); + } } - .hero-left, .lil-grid { - flex: 1; - min-width: 340px; + + .secondary-cta { + background: rgba(255, 255, 255, 0.8); + border: 1px solid var(--card-border); + color: var(--text-color); + + &:hover { + background: white; + border-color: var(--primary-color); + transform: translateY(-1px); + box-shadow: var(--shadow); + } } + .lil-grid { + flex: 1; + min-width: 300px; + max-width: 500px; display: grid; - grid-template-columns: repeat(auto-fit, minmax(64px, 1fr)); + grid-template-columns: repeat(auto-fit, minmax(60px, 1fr)); gap: 1rem; - margin-top: 1rem; + .framework-card { - background: var(--secondary-bg, #f8f9fa); - border-radius: 0.5rem; - padding: 0; - text-align: center; - transition: all 0.3s ease; + aspect-ratio: 1; + background: rgba(255, 255, 255, 0.8); + border-radius: 0.75rem; + border: 1px solid rgba(255, 255, 255, 0.3); + display: flex; + align-items: center; + justify-content: center; + transition: var(--transition); + backdrop-filter: blur(10px); + position: relative; + + &::before { + content: ''; + position: absolute; + inset: 0; + border-radius: inherit; + background: linear-gradient(135deg, var(--fw-color, var(--primary-color)) 0%, transparent 100%); + opacity: 0; + transition: opacity 0.3s; + } + + &:hover { + transform: translateY(-4px) scale(1.05); + background: white; + border-color: var(--fw-color, var(--primary-color)); + box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 0 0 1px var(--fw-color, var(--primary-color)); + + &::before { + opacity: 0.1; + } + } + img { width: 32px; - margin: 0 auto; + height: 32px; + z-index: 2; + filter: drop-shadow(0 2px 4px rgba(0,0,0,0.1)); } } } } +@keyframes pulse { + 0%, 100% { opacity: 0.3; transform: scale(1); } + 50% { opacity: 0.8; transform: scale(1.05); } +} + h2 { - opacity: 0.7; - font-weight: 500; - margin-top: 1rem; - margin: 1rem auto 0 auto; + font-size: 2.5rem; + font-weight: 700; + text-align: center; + margin: 4rem auto 2rem; + background: var(--gradient); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + position: relative; + + &::after { + content: ''; + position: absolute; + bottom: -0.5rem; + left: 50%; + transform: translateX(-50%); + width: 60px; + height: 4px; + background: var(--gradient); + border-radius: 2px; + } } .framework-card { - border: 2px solid var(--card-border); - border-radius: 12px; - padding: 1.5rem 1rem 0.5rem; + background: white; + border: 1px solid var(--card-border); + border-radius: var(--border-radius); + padding: 2rem 1rem 1rem; text-align: center; - transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1); - background: var(--card-bg); + transition: var(--transition); position: relative; overflow: hidden; display: flex; flex-direction: column; align-items: center; box-shadow: var(--shadow); -} - -.framework-card:hover { - border-color: var(--fw-color, #3498db); - transform: translateY(-4px); - box-shadow: 0 12px 30px rgba(0,0,0,0.15), 0 4px 12px color-mix(in srgb, var(--fw-color, #3498db) 25%, transparent); -} - -.framework-card::before { - content: ''; - position: absolute; - top: 0; - left: 0; - right: 0; - height: 4px; - background: linear-gradient(90deg, var(--fw-color, #3498db), color-mix(in srgb, var(--fw-color, #3498db) 80%, white)); - transform: scaleX(0); - transform-origin: center; - transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1); -} - -.framework-card:hover::before { - transform: scaleX(1); + + &::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 3px; + background: var(--fw-color, var(--primary-color)); + transform: scaleX(0); + transition: transform 0.4s ease; + } + + &:hover { + transform: translateY(-8px); + box-shadow: var(--shadow-lg), 0 4px 12px color-mix(in srgb, var(--fw-color, #3498db) 25%, transparent); + border-color: color-mix(in srgb, var(--fw-color, var(--primary-color)) 50%, transparent); + + &::before { + transform: scaleX(1); + } + + .framework-icon { + transform: scale(1.1); + } + + .framework-name { + color: var(--fw-color, var(--primary-color)); + } + } } .framework-icon { width: 64px; height: 64px; - margin: 0 auto 16px auto; + margin: 0 auto 1rem; display: block; + transition: var(--transition); + filter: drop-shadow(0 4px 8px rgba(0,0,0,0.1)); } .framework-name { - font-size: 1.3em; - font-weight: bold; - margin-bottom: 8px; - color: #2c3e50; + font-size: 1.2rem; + font-weight: 600; + color: var(--text-color); + transition: var(--transition); } .info-section { - border: 2px solid var(--card-border); - border-radius: 12px; - padding: 1.5rem 1rem 0.5rem; - transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1); - background: var(--card-bg); - display: flex; - flex-direction: column; - align-items: center; + background: white; + border: 1px solid var(--card-border); + border-radius: var(--border-radius); + padding: 3rem 2rem; + margin: 3rem auto; + max-width: 70rem; box-shadow: var(--shadow); - width: 100%; - max-width: 64rem; - margin: 1rem auto; - + text-align: center; + + h3 { + font-size: 1.5rem; + margin-bottom: 1rem; + color: var(--text-color); + } + + p { + font-size: 1.1rem; + margin-bottom: 2rem; + color: var(--text-muted); + } } -.info-section h3 { - margin-top: 0; - color: #2c3e50; -} .url-list { list-style: none; padding: 0; display: grid; - grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 1rem; - width: 100%; + margin-top: 2rem; } .url-list li { @@ -203,11 +316,84 @@ h2 { .health-link { display: inline-block; - margin-top: 16px; - color: #27ae60; - font-weight: 500; + margin-top: 2rem; + color: var(--primary-color); + font-weight: 600; + padding: 0.75rem 1.5rem; + background: rgba(255, 255, 255, 0.8); + border: 1px solid var(--primary-color); + border-radius: 0.5rem; + transition: var(--transition); + text-decoration: none; + + &:hover { + background: var(--primary-color); + color: white; + transform: translateY(-2px); + box-shadow: var(--shadow); + } } -.health-link:hover { - text-decoration: underline; + +/* Responsive Design */ +@media (max-width: 768px) { + .hero { + margin: 1rem auto 2rem; + padding: 2rem 1rem; + gap: 2rem; + + .hero-left h1 { + font-size: clamp(2rem, 8vw, 3rem); + } + + .hero-buttons { + justify-content: center; + } + + .lil-grid { + grid-template-columns: repeat(auto-fit, minmax(50px, 1fr)); + gap: 0.75rem; + + .framework-card img { + width: 24px; + height: 24px; + } + } + } + + .url-list { + grid-template-columns: 1fr; + } +} + +@media (max-width: 480px) { + .homepage-container { + padding: 0 0.5rem; + } + + .hero { + padding: 1.5rem 1rem; + + .hero-buttons { + flex-direction: column; + + .primary-cta, .secondary-cta { + width: 100%; + justify-content: center; + } + } + } + + .framework-card { + padding: 1.5rem 0.75rem 0.75rem; + + .framework-icon { + width: 48px; + height: 48px; + } + + .framework-name { + font-size: 1rem; + } + } } diff --git a/website/static/css/main.css b/website/static/css/main.css index 5905f35e..7090678a 100644 --- a/website/static/css/main.css +++ b/website/static/css/main.css @@ -1,13 +1,17 @@ :root { - --text-color: #333; - --text-muted: #7f8c8d; - --bg-color: #f5f5f5; + --text-color: #1a202c; + --text-muted: #718096; + --bg-color: #f7fafc; --card-bg: white; - --card-border: #e5e5e5; - --font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + --card-border: #e2e8f0; + --font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; --max-width: 1200px; - --shadow: 0 4px 12px rgba(0,0,0,0.1); - --primary-color: #6762ff; + --shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + --shadow-lg: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); + --primary-color: #667eea; + --gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + --border-radius: 0.75rem; + --transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); } ::selection { @@ -24,12 +28,14 @@ body { margin: 0; padding: 0; font-family: var(--font-family); - line-height: 1.5; + line-height: 1.6; color: var(--text-color); background: var(--bg-color); min-height: 100vh; display: flex; flex-direction: column; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } h1, h2, h3 { @@ -66,28 +72,40 @@ a { /* Header */ header { - background: var(--card-bg); + background: rgba(255, 255, 255, 0.95); + backdrop-filter: blur(10px); box-shadow: var(--shadow); position: sticky; top: 0; - z-index: 9; + z-index: 100; + border-bottom: 1px solid var(--card-border); + .site-name { display: flex; flex-direction: column; + p { margin: 0; font-style: italic; + font-size: 0.85rem; + opacity: 0.8; } + h1 { font-size: 1.5rem; margin: 0; - color: var(--primary-color); + background: var(--gradient); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + font-weight: 700; } } + .navigation { max-width: var(--max-width); margin: 0 auto; - padding: 0.25rem; + padding: 1rem; display: flex; justify-content: space-between; align-items: center; @@ -156,21 +174,44 @@ footer { .grid { display: grid; - gap: 24px; - grid-template-columns: repeat(auto-fit, minmax(225px, 1fr)); - margin: 2rem auto; - max-width: 64rem; + gap: 2rem; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + margin: 3rem auto; + max-width: 70rem; + padding: 0 1rem; } /* Responsive */ @media (max-width: 768px) { - .navigation, .footer-content { + .navigation { flex-direction: column; gap: 1rem; text-align: center; + padding: 0.5rem; + } + + .grid { + grid-template-columns: 1fr; + gap: 1.5rem; + padding: 0 0.5rem; + } + + h2 { + font-size: 2rem; + margin: 2rem auto 1rem; } .main-content { padding: 1rem; } } + +@media (max-width: 480px) { + .main-content { + padding: 0.5rem; + } + + h2 { + font-size: 1.75rem; + } +} diff --git a/website/templates/base.html b/website/templates/base.html index 0c20e1f1..a03bf4dd 100644 --- a/website/templates/base.html +++ b/website/templates/base.html @@ -7,6 +7,11 @@ + + + + + {% block extra_css %}{% endblock %} From 0758aaf22cc4404f588af0e9d6d3aced9ef372f2 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sat, 23 Aug 2025 23:12:06 +0100 Subject: [PATCH 03/12] Hide community stats on mobile, cba to make responsive --- website/static/css/framework-table.css | 49 ++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/website/static/css/framework-table.css b/website/static/css/framework-table.css index 1db1eed1..a72fd9e7 100644 --- a/website/static/css/framework-table.css +++ b/website/static/css/framework-table.css @@ -62,7 +62,7 @@ .framework-name { font-weight: 600; - font-size: 15px; + font-size: 18px; } /* Number formatting */ @@ -188,4 +188,49 @@ /* Header tooltips */ .ag-header-cell-text { font-weight: 600; -} \ No newline at end of file +} + +@media (max-width: 640px) { + .framework-stats { + margin: 2rem auto; + padding: 0; + overflow-x: auto; + } + + .stats-table-container { + height: 400px; + min-width: 800px; + border-radius: 0; + } + + .ag-theme-alpine, + .ag-theme-alpine-dark { + --ag-font-size: 11px; + --ag-header-height: 36px; + --ag-row-height: 40px; + } +} + +@media (max-width: 480px) { + .framework-stats { + position: relative; + } + + .stats-table-container { + display: none; + } + + .framework-stats::after { + content: '๐Ÿ“ฑ Community stats table is hidden on mobile devices. View on desktop or tablet for full statistics.'; + display: block; + text-align: center; + padding: 2rem 1rem; + background: var(--card-bg, white); + border: 1px solid var(--card-border, #e2e8f0); + border-radius: var(--border-radius, 0.75rem); + color: var(--text-muted, #718096); + font-size: 0.9rem; + margin: 0 1rem; + line-height: 1.5; + } +} From bf3d660b53dfbaf238a918c005c16cecf8cb408f Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sat, 23 Aug 2025 23:19:02 +0100 Subject: [PATCH 04/12] Rename repo, from weather-front to framework-benchmarks --- .github/CONTRIBUTING.md | 2 +- .github/README.md | 56 +++++++++++++------------- .github/docs/testing.md | 4 +- .github/docs/troubleshooting.md | 3 +- apps/alpine/README.md | 14 +++---- apps/angular/README.md | 14 +++---- apps/jquery/README.md | 14 +++---- apps/lit/README.md | 14 +++---- apps/preact/README.md | 14 +++---- apps/qwik/README.md | 14 +++---- apps/react/README.md | 14 +++---- apps/solid/README.md | 14 +++---- apps/svelte/README.md | 14 +++---- apps/vanilla/README.md | 14 +++---- apps/vanjs/README.md | 14 +++---- apps/vue/README.md | 14 +++---- package-lock.json | 4 +- package.json | 17 ++++---- scripts/pyproject.toml | 4 +- scripts/run/build_website.py | 6 +-- scripts/run/serve.py | 4 +- scripts/transform/build_app_readme.py | 14 +++---- scripts/transform/insert_statuses.py | 8 ++-- website/static/css/framework-table.css | 6 ++- website/static/js/framework-table.js | 3 +- website/templates/base.html | 6 +-- website/templates/framework.html | 20 ++++----- website/templates/homepage.html | 2 +- 28 files changed, 166 insertions(+), 161 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 67e9cc73..4103c4f0 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,2 +1,2 @@ -> See [Project Usage](https://github.com/Lissy93/weather-front?tab=readme-ov-file#usage) for setup and contribution instructions. +> See [Project Usage](https://github.com/lissy93/framework-benchmarks?tab=readme-ov-file#usage) for setup and contribution instructions. diff --git a/.github/README.md b/.github/README.md index 28e95a86..cd9f18f4 100644 --- a/.github/README.md +++ b/.github/README.md @@ -67,8 +67,8 @@ Git, Node (LTS or v22+), Python (3.10) and uv installed ### Setup ```bash -git clone git@github.com:Lissy93/weather-front.git -cd weather-front +git clone git@github.com:lissy93/framework-benchmarks.git +cd framework-benchmarks npm install pip install -r scripts/requirements.txt npm run setup @@ -80,7 +80,7 @@ Or, you can: `cd ./apps/[app-name]` then `npm i` and `npm run dev` ### Testing All apps are tested with the same shared test suite, to ensure they all conform to the same requirements, and are fully functional. -Tests are dome with [Playwright](https://playwright.dev/docs/intro) and can be found in the [`tests/`](https://github.com/Lissy93/weather-front/tree/main/tests) directory. +Tests are dome with [Playwright](https://playwright.dev/docs/intro) and can be found in the [`tests/`](https://github.com/lissy93/framework-benchmarks/tree/main/tests) directory. Either execute tests for all implementations with `npm test`, or just for a specific app with `npm run test:[app]` (e.g. `npm run test:react`).
You should also verify the lint checks pass, with `npm run lint` or `npm run lint:[app]`. @@ -92,7 +92,7 @@ Then upload `./apps/[app-name]/dist/` to any web server, CDN or static hosting p ### Adding a Framework 1. Create app directory: `apps/your-framework/` with `package.json`, `vite.config.js`, and a `src/` dir 2. Build your app (ensuring it meets the [requirements spec](#requirement-spec) above) -3. Update [`frameworks.json`](https://github.com/Lissy93/weather-front/blob/main/frameworks.json) +3. Update [`frameworks.json`](https://github.com/lissy93/framework-benchmarks/blob/main/frameworks.json) 4. Add a test config file in `tests/config/` 6. Them run `node scripts/setup/generate-scripts.js` and `node scripts/setup/sync-assets.js` @@ -104,7 +104,7 @@ Then upload `./apps/[app-name]/dist/` to any web server, CDN or static hosting p ### Directory Structure ``` -weather-front +framework-benchmarks โ”œโ”€โ”€ scripts # Scripts for managing the app (syncing assets, generating mocks, etc) โ”œโ”€โ”€ assets # These are shared across all apps for consistency โ”‚ โ”œโ”€โ”€ icons # SVG icons, used by all apps @@ -119,7 +119,7 @@ weather-front ``` ### Scripts -The **[`scripts/`](https://github.com/Lissy93/weather-front/tree/main/scripts)** directory contains +The **[`scripts/`](https://github.com/lissy93/framework-benchmarks/tree/main/scripts)** directory contains everything for managing the project (setup, testing, benchmarking, reporting, etc). You can view a list of scripts by running `npm run help`. @@ -127,9 +127,9 @@ You can view a list of scripts by running `npm run help`. ### Shared Assets To keep things uniform, all apps will share certain assets -- **[`tests/`](https://github.com/Lissy93/weather-front/tree/main/tests)** - Same test suit used for all apps. To ensure each app conforms to the spec and is fully functional -- **[`assets/`](https://github.com/Lissy93/weather-front/tree/main/assets)** - Same static assets (icons, fonts, styles, meta, etc) -- **[`assets/styles/`](https://github.com/Lissy93/weather-front/tree/main/assets/styles)** - Same styles for all apps, and theming is done with CSS variables +- **[`tests/`](https://github.com/lissy93/framework-benchmarks/tree/main/tests)** - Same test suit used for all apps. To ensure each app conforms to the spec and is fully functional +- **[`assets/`](https://github.com/lissy93/framework-benchmarks/tree/main/assets)** - Same static assets (icons, fonts, styles, meta, etc) +- **[`assets/styles/`](https://github.com/lissy93/framework-benchmarks/tree/main/assets/styles)** - Same styles for all apps, and theming is done with CSS variables ### Third Parties - **Dependencies**: Beyond their framework code, none of the apps use any additional dependencies, libraries or third-party "stuff" @@ -146,9 +146,9 @@ To keep things uniform, all apps will share certain assets - `npm run start` - Starts the demo server, which serves up all built apps - `npm run help` - Displays a list of all available commands -See the [`package.json`](https://github.com/Lissy93/weather-front/blob/main/package.json) for all commands +See the [`package.json`](https://github.com/lissy93/framework-benchmarks/blob/main/package.json) for all commands -Note that the project commands get generated automatically by the [`generate_scripts.py`](https://github.com/Lissy93/weather-front/blob/main/scripts/setup/generate_scripts.py) script, based on the contents of [`frameworks.json`](https://github.com/Lissy93/weather-front/blob/main/frameworks.json) and [`config.json`](https://github.com/Lissy93/weather-front/blob/main/config.json). +Note that the project commands get generated automatically by the [`generate_scripts.py`](https://github.com/lissy93/framework-benchmarks/blob/main/scripts/setup/generate_scripts.py) script, based on the contents of [`frameworks.json`](https://github.com/lissy93/framework-benchmarks/blob/main/frameworks.json) and [`config.json`](https://github.com/lissy93/framework-benchmarks/blob/main/config.json). --- @@ -201,7 +201,7 @@ To compare the frameworks, we need to measure: The interface is simple, but must be identical arcorss all apps. As validated by the snapshots in the tests.
The screenshots will all look like this: - + --- @@ -211,24 +211,24 @@ The screenshots will all look like this: ## Status -Each app gets built and tested to ensure that it is functional, compliant with the spec, and (reasonably) well coded. Below is the current status of each, but for complete details you can see the [Workflow Logs](https://github.com/Lissy93/weather-front/actions) via GitHub Actions. +Each app gets built and tested to ensure that it is functional, compliant with the spec, and (reasonably) well coded. Below is the current status of each, but for complete details you can see the [Workflow Logs](https://github.com/lissy93/framework-benchmarks/actions) via GitHub Actions. | App | Build | Test | Lint | |---|---|---|---| -| React | ![React Build Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/build-react.svg) | ![React Test Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/test-react.svg) | ![React Lint Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/lint-react.svg) | -| Angular | ![Angular Build Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/build-angular.svg) | ![Angular Test Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/test-angular.svg) | ![Angular Lint Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/lint-angular.svg) | -| Svelte | ![Svelte Build Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/build-svelte.svg) | ![Svelte Test Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/test-svelte.svg) | ![Svelte Lint Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/lint-svelte.svg) | -| Preact | ![Preact Build Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/build-preact.svg) | ![Preact Test Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/test-preact.svg) | ![Preact Lint Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/lint-preact.svg) | -| Solid.js | ![Solid.js Build Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/build-solid.svg) | ![Solid.js Test Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/test-solid.svg) | ![Solid.js Lint Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/lint-solid.svg) | -| Qwik | ![Qwik Build Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/build-qwik.svg) | ![Qwik Test Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/test-qwik.svg) | ![Qwik Lint Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/lint-qwik.svg) | -| Vue 3 | ![Vue 3 Build Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/build-vue.svg) | ![Vue 3 Test Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/test-vue.svg) | ![Vue 3 Lint Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/lint-vue.svg) | -| jQuery | ![jQuery Build Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/build-jquery.svg) | ![jQuery Test Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/test-jquery.svg) | ![jQuery Lint Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/lint-jquery.svg) | -| Alpine.js | ![Alpine.js Build Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/build-alpine.svg) | ![Alpine.js Test Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/test-alpine.svg) | ![Alpine.js Lint Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/lint-alpine.svg) | -| Lit | ![Lit Build Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/build-lit.svg) | ![Lit Test Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/test-lit.svg) | ![Lit Lint Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/lint-lit.svg) | -| VanJS | ![VanJS Build Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/build-vanjs.svg) | ![VanJS Test Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/test-vanjs.svg) | ![VanJS Lint Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/lint-vanjs.svg) | -| Vanilla JavaScript | ![Vanilla JavaScript Build Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/build-vanilla.svg) | ![Vanilla JavaScript Test Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/test-vanilla.svg) | ![Vanilla JavaScript Lint Status](https://raw.githubusercontent.com/Lissy93/weather-front/badges/lint-vanilla.svg) | +| React | ![React Build Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/build-react.svg) | ![React Test Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/test-react.svg) | ![React Lint Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/lint-react.svg) | +| Angular | ![Angular Build Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/build-angular.svg) | ![Angular Test Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/test-angular.svg) | ![Angular Lint Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/lint-angular.svg) | +| Svelte | ![Svelte Build Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/build-svelte.svg) | ![Svelte Test Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/test-svelte.svg) | ![Svelte Lint Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/lint-svelte.svg) | +| Preact | ![Preact Build Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/build-preact.svg) | ![Preact Test Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/test-preact.svg) | ![Preact Lint Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/lint-preact.svg) | +| Solid.js | ![Solid.js Build Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/build-solid.svg) | ![Solid.js Test Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/test-solid.svg) | ![Solid.js Lint Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/lint-solid.svg) | +| Qwik | ![Qwik Build Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/build-qwik.svg) | ![Qwik Test Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/test-qwik.svg) | ![Qwik Lint Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/lint-qwik.svg) | +| Vue 3 | ![Vue 3 Build Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/build-vue.svg) | ![Vue 3 Test Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/test-vue.svg) | ![Vue 3 Lint Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/lint-vue.svg) | +| jQuery | ![jQuery Build Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/build-jquery.svg) | ![jQuery Test Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/test-jquery.svg) | ![jQuery Lint Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/lint-jquery.svg) | +| Alpine.js | ![Alpine.js Build Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/build-alpine.svg) | ![Alpine.js Test Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/test-alpine.svg) | ![Alpine.js Lint Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/lint-alpine.svg) | +| Lit | ![Lit Build Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/build-lit.svg) | ![Lit Test Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/test-lit.svg) | ![Lit Lint Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/lint-lit.svg) | +| VanJS | ![VanJS Build Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/build-vanjs.svg) | ![VanJS Test Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/test-vanjs.svg) | ![VanJS Lint Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/lint-vanjs.svg) | +| Vanilla JavaScript | ![Vanilla JavaScript Build Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/build-vanilla.svg) | ![Vanilla JavaScript Test Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/test-vanilla.svg) | ![Vanilla JavaScript Lint Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/badges/lint-vanilla.svg) | --- @@ -285,19 +285,19 @@ So, in order to let each one shine, I have I have built real-world apps in each ### Contributors -![Contributors](https://readme-contribs.as93.net/contributors/lissy93/weather-front?avatarSize=80&perRow=10) +![Contributors](https://readme-contribs.as93.net/contributors/lissy93/framework-benchmarks?avatarSize=80&perRow=10) ### Stargzers -![Stargazers](https://readme-contribs.as93.net/stargazers/lissy93/weather-front?perRow=16&limit=64) +![Stargazers](https://readme-contribs.as93.net/stargazers/lissy93/framework-benchmarks?perRow=16&limit=64) --- ## License -> _**[Lissy93/Weather-Front](https://github.com/Lissy93/weather-front)** is licensed under [MIT](https://github.com/Lissy93/weather-front/blob/HEAD/LICENSE) ยฉ [Alicia Sykes](https://aliciasykes.com) 2025._
+> _**[lissy93/framework-benchmarks](https://github.com/lissy93/framework-benchmarks)** is licensed under [MIT](https://github.com/lissy93/framework-benchmarks/blob/HEAD/LICENSE) ยฉ [Alicia Sykes](https://aliciasykes.com) 2025._
> For information, see TLDR Legal > MIT
diff --git a/.github/docs/testing.md b/.github/docs/testing.md index 7df25323..24164d83 100644 --- a/.github/docs/testing.md +++ b/.github/docs/testing.md @@ -241,6 +241,6 @@ If tests fail or you need help: 1. Check this README 2. Review test output and screenshots 3. Run tests in debug mode -4. Check [GitHub Issues](https://github.com/Lissy93/weather-front/issues) +4. Check [GitHub Issues](https://github.com/lissy93/framework-benchmarks/issues) -**Happy Testing! ๐ŸŽ‰** \ No newline at end of file +**Happy Testing! ๐ŸŽ‰** diff --git a/.github/docs/troubleshooting.md b/.github/docs/troubleshooting.md index 87e6b6c7..d83620e8 100644 --- a/.github/docs/troubleshooting.md +++ b/.github/docs/troubleshooting.md @@ -1,5 +1,4 @@ - - +# Troubleshooting ### "Unable to connect to Chrome" - Ensure Chrome/Chromium is installed diff --git a/apps/alpine/README.md b/apps/alpine/README.md index ee0b8531..0dce6a41 100644 --- a/apps/alpine/README.md +++ b/apps/alpine/README.md @@ -2,7 +2,7 @@

๐Ÿ”๏ธ Weather Front - Alpine.js

-
+
A tiny weather app
๐Ÿš€ Demo โ— ๐Ÿ“Š Results @@ -40,9 +40,9 @@ This is a simple weather app, built in [Alpine.js](https://alpinejs.dev/) (as we | Task | Status | |---|---| -| **Test** - Executes all e2e and unit tests | [![Test Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/test-alpine.svg)](https://github.com/Lissy93/weather-front/actions/workflows/test.yml) | -| **Lint** - Verifies code style and quality | [![Lint Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/lint-alpine.svg)](https://github.com/Lissy93/weather-front/actions/workflows/lint.yml) | -| **Build** - Builds and deploys the app | [![Build Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/build-alpine.svg)](https://github.com/Lissy93/weather-front/actions/workflows/build.yml) | +| **Test** - Executes all e2e and unit tests | [![Test Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/test-alpine.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/test.yml) | +| **Lint** - Verifies code style and quality | [![Lint Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/lint-alpine.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/lint.yml) | +| **Build** - Builds and deploys the app | [![Build Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/build-alpine.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/build.yml) | @@ -50,7 +50,7 @@ This is a simple weather app, built in [Alpine.js](https://alpinejs.dev/) (as we ## Usage -First, follow the [repo setup instructions](https://github.com/Lissy93/weather-front?tab=readme-ov-file#usage). Then `cd apps/alpine` and use the following commands: +First, follow the [repo setup instructions](https://github.com/lissy93/framework-benchmarks?tab=readme-ov-file#usage). Then `cd apps/alpine` and use the following commands: ```bash npm run dev # Start dev server (python3 -m http.server 3000 || python -m http.server 3000) @@ -93,7 +93,7 @@ Since the weather app is very simple, it may be helpful to see a more practical ## License -Weather-Front is licensed under [MIT](https://github.com/Lissy93/weather-front/blob/main/LICENSE) ยฉ Alicia Sykes 2025.
-View [Attributions](https://github.com/Lissy93/weather-front?tab=readme-ov-file#attributions) for credits, thanks and contributors. +Weather-Front is licensed under [MIT](https://github.com/lissy93/framework-benchmarks/blob/main/LICENSE) ยฉ Alicia Sykes 2025.
+View [Attributions](https://github.com/lissy93/framework-benchmarks?tab=readme-ov-file#attributions) for credits, thanks and contributors. diff --git a/apps/angular/README.md b/apps/angular/README.md index 4fe8f420..c93c47de 100644 --- a/apps/angular/README.md +++ b/apps/angular/README.md @@ -2,7 +2,7 @@

๐Ÿ…ฐ๏ธ Weather Front - Angular

-
+
A tiny weather app
๐Ÿš€ Demo โ— ๐Ÿ“Š Results @@ -40,9 +40,9 @@ This is a simple weather app, built in [Angular](https://angular.io/) (as well a | Task | Status | |---|---| -| **Test** - Executes all e2e and unit tests | [![Test Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/test-angular.svg)](https://github.com/Lissy93/weather-front/actions/workflows/test.yml) | -| **Lint** - Verifies code style and quality | [![Lint Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/lint-angular.svg)](https://github.com/Lissy93/weather-front/actions/workflows/lint.yml) | -| **Build** - Builds and deploys the app | [![Build Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/build-angular.svg)](https://github.com/Lissy93/weather-front/actions/workflows/build.yml) | +| **Test** - Executes all e2e and unit tests | [![Test Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/test-angular.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/test.yml) | +| **Lint** - Verifies code style and quality | [![Lint Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/lint-angular.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/lint.yml) | +| **Build** - Builds and deploys the app | [![Build Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/build-angular.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/build.yml) | @@ -50,7 +50,7 @@ This is a simple weather app, built in [Angular](https://angular.io/) (as well a ## Usage -First, follow the [repo setup instructions](https://github.com/Lissy93/weather-front?tab=readme-ov-file#usage). Then `cd apps/angular` and use the following commands: +First, follow the [repo setup instructions](https://github.com/lissy93/framework-benchmarks?tab=readme-ov-file#usage). Then `cd apps/angular` and use the following commands: ```bash npm run dev # Start dev server (ng serve --port 3000) @@ -94,7 +94,7 @@ Since the weather app is very simple, it may be helpful to see a more practical ## License -Weather-Front is licensed under [MIT](https://github.com/Lissy93/weather-front/blob/main/LICENSE) ยฉ Alicia Sykes 2025.
-View [Attributions](https://github.com/Lissy93/weather-front?tab=readme-ov-file#attributions) for credits, thanks and contributors. +Weather-Front is licensed under [MIT](https://github.com/lissy93/framework-benchmarks/blob/main/LICENSE) ยฉ Alicia Sykes 2025.
+View [Attributions](https://github.com/lissy93/framework-benchmarks?tab=readme-ov-file#attributions) for credits, thanks and contributors. diff --git a/apps/jquery/README.md b/apps/jquery/README.md index b60e1445..a8533f26 100644 --- a/apps/jquery/README.md +++ b/apps/jquery/README.md @@ -2,7 +2,7 @@

๐Ÿ’™ Weather Front - jQuery

-
+
A tiny weather app
๐Ÿš€ Demo โ— ๐Ÿ“Š Results @@ -40,9 +40,9 @@ This is a simple weather app, built in [jQuery](https://jquery.com/) (as well as | Task | Status | |---|---| -| **Test** - Executes all e2e and unit tests | [![Test Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/test-jquery.svg)](https://github.com/Lissy93/weather-front/actions/workflows/test.yml) | -| **Lint** - Verifies code style and quality | [![Lint Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/lint-jquery.svg)](https://github.com/Lissy93/weather-front/actions/workflows/lint.yml) | -| **Build** - Builds and deploys the app | [![Build Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/build-jquery.svg)](https://github.com/Lissy93/weather-front/actions/workflows/build.yml) | +| **Test** - Executes all e2e and unit tests | [![Test Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/test-jquery.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/test.yml) | +| **Lint** - Verifies code style and quality | [![Lint Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/lint-jquery.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/lint.yml) | +| **Build** - Builds and deploys the app | [![Build Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/build-jquery.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/build.yml) | @@ -50,7 +50,7 @@ This is a simple weather app, built in [jQuery](https://jquery.com/) (as well as ## Usage -First, follow the [repo setup instructions](https://github.com/Lissy93/weather-front?tab=readme-ov-file#usage). Then `cd apps/jquery` and use the following commands: +First, follow the [repo setup instructions](https://github.com/lissy93/framework-benchmarks?tab=readme-ov-file#usage). Then `cd apps/jquery` and use the following commands: ```bash npm run dev # Start dev server (vite --port 3000) @@ -82,7 +82,7 @@ For troubleshooting, use `npm run verify` from the root of the project. ## License -Weather-Front is licensed under [MIT](https://github.com/Lissy93/weather-front/blob/main/LICENSE) ยฉ Alicia Sykes 2025.
-View [Attributions](https://github.com/Lissy93/weather-front?tab=readme-ov-file#attributions) for credits, thanks and contributors. +Weather-Front is licensed under [MIT](https://github.com/lissy93/framework-benchmarks/blob/main/LICENSE) ยฉ Alicia Sykes 2025.
+View [Attributions](https://github.com/lissy93/framework-benchmarks?tab=readme-ov-file#attributions) for credits, thanks and contributors. diff --git a/apps/lit/README.md b/apps/lit/README.md index b891b6f2..751cc2b9 100644 --- a/apps/lit/README.md +++ b/apps/lit/README.md @@ -2,7 +2,7 @@

๐Ÿ”ฅ Weather Front - Lit

-
+
A tiny weather app
๐Ÿš€ Demo โ— ๐Ÿ“Š Results @@ -40,9 +40,9 @@ This is a simple weather app, built in [Lit](https://lit.dev/) (as well as also | Task | Status | |---|---| -| **Test** - Executes all e2e and unit tests | [![Test Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/test-lit.svg)](https://github.com/Lissy93/weather-front/actions/workflows/test.yml) | -| **Lint** - Verifies code style and quality | [![Lint Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/lint-lit.svg)](https://github.com/Lissy93/weather-front/actions/workflows/lint.yml) | -| **Build** - Builds and deploys the app | [![Build Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/build-lit.svg)](https://github.com/Lissy93/weather-front/actions/workflows/build.yml) | +| **Test** - Executes all e2e and unit tests | [![Test Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/test-lit.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/test.yml) | +| **Lint** - Verifies code style and quality | [![Lint Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/lint-lit.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/lint.yml) | +| **Build** - Builds and deploys the app | [![Build Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/build-lit.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/build.yml) | @@ -50,7 +50,7 @@ This is a simple weather app, built in [Lit](https://lit.dev/) (as well as also ## Usage -First, follow the [repo setup instructions](https://github.com/Lissy93/weather-front?tab=readme-ov-file#usage). Then `cd apps/lit` and use the following commands: +First, follow the [repo setup instructions](https://github.com/lissy93/framework-benchmarks?tab=readme-ov-file#usage). Then `cd apps/lit` and use the following commands: ```bash npm run dev # Start dev server (vite --port 3000) @@ -92,7 +92,7 @@ Since the weather app is very simple, it may be helpful to see a more practical ## License -Weather-Front is licensed under [MIT](https://github.com/Lissy93/weather-front/blob/main/LICENSE) ยฉ Alicia Sykes 2025.
-View [Attributions](https://github.com/Lissy93/weather-front?tab=readme-ov-file#attributions) for credits, thanks and contributors. +Weather-Front is licensed under [MIT](https://github.com/lissy93/framework-benchmarks/blob/main/LICENSE) ยฉ Alicia Sykes 2025.
+View [Attributions](https://github.com/lissy93/framework-benchmarks?tab=readme-ov-file#attributions) for credits, thanks and contributors. diff --git a/apps/preact/README.md b/apps/preact/README.md index d529e4a2..24f05a26 100644 --- a/apps/preact/README.md +++ b/apps/preact/README.md @@ -2,7 +2,7 @@

๐Ÿ’œ Weather Front - Preact

-
+
A tiny weather app
๐Ÿš€ Demo โ— ๐Ÿ“Š Results @@ -40,9 +40,9 @@ This is a simple weather app, built in [Preact](https://preactjs.com/) (as well | Task | Status | |---|---| -| **Test** - Executes all e2e and unit tests | [![Test Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/test-preact.svg)](https://github.com/Lissy93/weather-front/actions/workflows/test.yml) | -| **Lint** - Verifies code style and quality | [![Lint Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/lint-preact.svg)](https://github.com/Lissy93/weather-front/actions/workflows/lint.yml) | -| **Build** - Builds and deploys the app | [![Build Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/build-preact.svg)](https://github.com/Lissy93/weather-front/actions/workflows/build.yml) | +| **Test** - Executes all e2e and unit tests | [![Test Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/test-preact.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/test.yml) | +| **Lint** - Verifies code style and quality | [![Lint Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/lint-preact.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/lint.yml) | +| **Build** - Builds and deploys the app | [![Build Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/build-preact.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/build.yml) | @@ -50,7 +50,7 @@ This is a simple weather app, built in [Preact](https://preactjs.com/) (as well ## Usage -First, follow the [repo setup instructions](https://github.com/Lissy93/weather-front?tab=readme-ov-file#usage). Then `cd apps/preact` and use the following commands: +First, follow the [repo setup instructions](https://github.com/lissy93/framework-benchmarks?tab=readme-ov-file#usage). Then `cd apps/preact` and use the following commands: ```bash npm run dev # Start dev server (vite) @@ -92,7 +92,7 @@ Since the weather app is very simple, it may be helpful to see a more practical ## License -Weather-Front is licensed under [MIT](https://github.com/Lissy93/weather-front/blob/main/LICENSE) ยฉ Alicia Sykes 2025.
-View [Attributions](https://github.com/Lissy93/weather-front?tab=readme-ov-file#attributions) for credits, thanks and contributors. +Weather-Front is licensed under [MIT](https://github.com/lissy93/framework-benchmarks/blob/main/LICENSE) ยฉ Alicia Sykes 2025.
+View [Attributions](https://github.com/lissy93/framework-benchmarks?tab=readme-ov-file#attributions) for credits, thanks and contributors. diff --git a/apps/qwik/README.md b/apps/qwik/README.md index 76bf3357..8eeb0b84 100644 --- a/apps/qwik/README.md +++ b/apps/qwik/README.md @@ -2,7 +2,7 @@

โšก Weather Front - Qwik

-
+
A tiny weather app
๐Ÿš€ Demo โ— ๐Ÿ“Š Results @@ -40,9 +40,9 @@ This is a simple weather app, built in [Qwik](https://qwik.builder.io/) (as well | Task | Status | |---|---| -| **Test** - Executes all e2e and unit tests | [![Test Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/test-qwik.svg)](https://github.com/Lissy93/weather-front/actions/workflows/test.yml) | -| **Lint** - Verifies code style and quality | [![Lint Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/lint-qwik.svg)](https://github.com/Lissy93/weather-front/actions/workflows/lint.yml) | -| **Build** - Builds and deploys the app | [![Build Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/build-qwik.svg)](https://github.com/Lissy93/weather-front/actions/workflows/build.yml) | +| **Test** - Executes all e2e and unit tests | [![Test Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/test-qwik.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/test.yml) | +| **Lint** - Verifies code style and quality | [![Lint Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/lint-qwik.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/lint.yml) | +| **Build** - Builds and deploys the app | [![Build Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/build-qwik.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/build.yml) | @@ -50,7 +50,7 @@ This is a simple weather app, built in [Qwik](https://qwik.builder.io/) (as well ## Usage -First, follow the [repo setup instructions](https://github.com/Lissy93/weather-front?tab=readme-ov-file#usage). Then `cd apps/qwik` and use the following commands: +First, follow the [repo setup instructions](https://github.com/lissy93/framework-benchmarks?tab=readme-ov-file#usage). Then `cd apps/qwik` and use the following commands: ```bash npm run dev # Start dev server (vite --port 3000) @@ -92,7 +92,7 @@ Since the weather app is very simple, it may be helpful to see a more practical ## License -Weather-Front is licensed under [MIT](https://github.com/Lissy93/weather-front/blob/main/LICENSE) ยฉ Alicia Sykes 2025.
-View [Attributions](https://github.com/Lissy93/weather-front?tab=readme-ov-file#attributions) for credits, thanks and contributors. +Weather-Front is licensed under [MIT](https://github.com/lissy93/framework-benchmarks/blob/main/LICENSE) ยฉ Alicia Sykes 2025.
+View [Attributions](https://github.com/lissy93/framework-benchmarks?tab=readme-ov-file#attributions) for credits, thanks and contributors. diff --git a/apps/react/README.md b/apps/react/README.md index 93a40738..31262038 100644 --- a/apps/react/README.md +++ b/apps/react/README.md @@ -2,7 +2,7 @@

โš›๏ธ Weather Front - React

-
+
A tiny weather app
๐Ÿš€ Demo โ— ๐Ÿ“Š Results @@ -40,9 +40,9 @@ This is a simple weather app, built in [React](https://react.dev/) (as well as a | Task | Status | |---|---| -| **Test** - Executes all e2e and unit tests | [![Test Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/test-react.svg)](https://github.com/Lissy93/weather-front/actions/workflows/test.yml) | -| **Lint** - Verifies code style and quality | [![Lint Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/lint-react.svg)](https://github.com/Lissy93/weather-front/actions/workflows/lint.yml) | -| **Build** - Builds and deploys the app | [![Build Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/build-react.svg)](https://github.com/Lissy93/weather-front/actions/workflows/build.yml) | +| **Test** - Executes all e2e and unit tests | [![Test Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/test-react.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/test.yml) | +| **Lint** - Verifies code style and quality | [![Lint Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/lint-react.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/lint.yml) | +| **Build** - Builds and deploys the app | [![Build Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/build-react.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/build.yml) | @@ -50,7 +50,7 @@ This is a simple weather app, built in [React](https://react.dev/) (as well as a ## Usage -First, follow the [repo setup instructions](https://github.com/Lissy93/weather-front?tab=readme-ov-file#usage). Then `cd apps/react` and use the following commands: +First, follow the [repo setup instructions](https://github.com/lissy93/framework-benchmarks?tab=readme-ov-file#usage). Then `cd apps/react` and use the following commands: ```bash npm run dev # Start dev server (vite) @@ -92,7 +92,7 @@ Since the weather app is very simple, it may be helpful to see a more practical ## License -Weather-Front is licensed under [MIT](https://github.com/Lissy93/weather-front/blob/main/LICENSE) ยฉ Alicia Sykes 2025.
-View [Attributions](https://github.com/Lissy93/weather-front?tab=readme-ov-file#attributions) for credits, thanks and contributors. +Weather-Front is licensed under [MIT](https://github.com/lissy93/framework-benchmarks/blob/main/LICENSE) ยฉ Alicia Sykes 2025.
+View [Attributions](https://github.com/lissy93/framework-benchmarks?tab=readme-ov-file#attributions) for credits, thanks and contributors. diff --git a/apps/solid/README.md b/apps/solid/README.md index c369b4e0..da75e351 100644 --- a/apps/solid/README.md +++ b/apps/solid/README.md @@ -2,7 +2,7 @@

๐Ÿš€ Weather Front - Solid.js

-
+
A tiny weather app
๐Ÿš€ Demo โ— ๐Ÿ“Š Results @@ -40,9 +40,9 @@ This is a simple weather app, built in [Solid.js](https://www.solidjs.com/) (as | Task | Status | |---|---| -| **Test** - Executes all e2e and unit tests | [![Test Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/test-solid.svg)](https://github.com/Lissy93/weather-front/actions/workflows/test.yml) | -| **Lint** - Verifies code style and quality | [![Lint Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/lint-solid.svg)](https://github.com/Lissy93/weather-front/actions/workflows/lint.yml) | -| **Build** - Builds and deploys the app | [![Build Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/build-solid.svg)](https://github.com/Lissy93/weather-front/actions/workflows/build.yml) | +| **Test** - Executes all e2e and unit tests | [![Test Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/test-solid.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/test.yml) | +| **Lint** - Verifies code style and quality | [![Lint Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/lint-solid.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/lint.yml) | +| **Build** - Builds and deploys the app | [![Build Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/build-solid.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/build.yml) | @@ -50,7 +50,7 @@ This is a simple weather app, built in [Solid.js](https://www.solidjs.com/) (as ## Usage -First, follow the [repo setup instructions](https://github.com/Lissy93/weather-front?tab=readme-ov-file#usage). Then `cd apps/solid` and use the following commands: +First, follow the [repo setup instructions](https://github.com/lissy93/framework-benchmarks?tab=readme-ov-file#usage). Then `cd apps/solid` and use the following commands: ```bash npm run dev # Start dev server (vite) @@ -93,7 +93,7 @@ Since the weather app is very simple, it may be helpful to see a more practical ## License -Weather-Front is licensed under [MIT](https://github.com/Lissy93/weather-front/blob/main/LICENSE) ยฉ Alicia Sykes 2025.
-View [Attributions](https://github.com/Lissy93/weather-front?tab=readme-ov-file#attributions) for credits, thanks and contributors. +Weather-Front is licensed under [MIT](https://github.com/lissy93/framework-benchmarks/blob/main/LICENSE) ยฉ Alicia Sykes 2025.
+View [Attributions](https://github.com/lissy93/framework-benchmarks?tab=readme-ov-file#attributions) for credits, thanks and contributors. diff --git a/apps/svelte/README.md b/apps/svelte/README.md index 8639499e..978991c7 100644 --- a/apps/svelte/README.md +++ b/apps/svelte/README.md @@ -2,7 +2,7 @@

๐Ÿ”ฅ Weather Front - Svelte

-
+
A tiny weather app
๐Ÿš€ Demo โ— ๐Ÿ“Š Results @@ -40,9 +40,9 @@ This is a simple weather app, built in [Svelte](https://svelte.dev/) (as well as | Task | Status | |---|---| -| **Test** - Executes all e2e and unit tests | [![Test Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/test-svelte.svg)](https://github.com/Lissy93/weather-front/actions/workflows/test.yml) | -| **Lint** - Verifies code style and quality | [![Lint Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/lint-svelte.svg)](https://github.com/Lissy93/weather-front/actions/workflows/lint.yml) | -| **Build** - Builds and deploys the app | [![Build Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/build-svelte.svg)](https://github.com/Lissy93/weather-front/actions/workflows/build.yml) | +| **Test** - Executes all e2e and unit tests | [![Test Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/test-svelte.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/test.yml) | +| **Lint** - Verifies code style and quality | [![Lint Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/lint-svelte.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/lint.yml) | +| **Build** - Builds and deploys the app | [![Build Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/build-svelte.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/build.yml) | @@ -50,7 +50,7 @@ This is a simple weather app, built in [Svelte](https://svelte.dev/) (as well as ## Usage -First, follow the [repo setup instructions](https://github.com/Lissy93/weather-front?tab=readme-ov-file#usage). Then `cd apps/svelte` and use the following commands: +First, follow the [repo setup instructions](https://github.com/lissy93/framework-benchmarks?tab=readme-ov-file#usage). Then `cd apps/svelte` and use the following commands: ```bash npm run dev # Start dev server (vite dev --port 3000) @@ -92,7 +92,7 @@ Since the weather app is very simple, it may be helpful to see a more practical ## License -Weather-Front is licensed under [MIT](https://github.com/Lissy93/weather-front/blob/main/LICENSE) ยฉ Alicia Sykes 2025.
-View [Attributions](https://github.com/Lissy93/weather-front?tab=readme-ov-file#attributions) for credits, thanks and contributors. +Weather-Front is licensed under [MIT](https://github.com/lissy93/framework-benchmarks/blob/main/LICENSE) ยฉ Alicia Sykes 2025.
+View [Attributions](https://github.com/lissy93/framework-benchmarks?tab=readme-ov-file#attributions) for credits, thanks and contributors. diff --git a/apps/vanilla/README.md b/apps/vanilla/README.md index 4bb99b08..dfdb47b2 100644 --- a/apps/vanilla/README.md +++ b/apps/vanilla/README.md @@ -2,7 +2,7 @@

๐Ÿงช Weather Front - Vanilla JavaScript

-
+
A tiny weather app
๐Ÿš€ Demo โ— ๐Ÿ“Š Results @@ -40,9 +40,9 @@ This is a simple weather app, built in [Vanilla JavaScript](https://developer.mo | Task | Status | |---|---| -| **Test** - Executes all e2e and unit tests | [![Test Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/test-vanilla.svg)](https://github.com/Lissy93/weather-front/actions/workflows/test.yml) | -| **Lint** - Verifies code style and quality | [![Lint Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/lint-vanilla.svg)](https://github.com/Lissy93/weather-front/actions/workflows/lint.yml) | -| **Build** - Builds and deploys the app | [![Build Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/build-vanilla.svg)](https://github.com/Lissy93/weather-front/actions/workflows/build.yml) | +| **Test** - Executes all e2e and unit tests | [![Test Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/test-vanilla.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/test.yml) | +| **Lint** - Verifies code style and quality | [![Lint Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/lint-vanilla.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/lint.yml) | +| **Build** - Builds and deploys the app | [![Build Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/build-vanilla.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/build.yml) | @@ -50,7 +50,7 @@ This is a simple weather app, built in [Vanilla JavaScript](https://developer.mo ## Usage -First, follow the [repo setup instructions](https://github.com/Lissy93/weather-front?tab=readme-ov-file#usage). Then `cd apps/vanilla` and use the following commands: +First, follow the [repo setup instructions](https://github.com/lissy93/framework-benchmarks?tab=readme-ov-file#usage). Then `cd apps/vanilla` and use the following commands: ```bash npm run dev # Start dev server (python3 -m http.server 3000 || python -m http.server 3000) @@ -93,7 +93,7 @@ Since the weather app is very simple, it may be helpful to see a more practical ## License -Weather-Front is licensed under [MIT](https://github.com/Lissy93/weather-front/blob/main/LICENSE) ยฉ Alicia Sykes 2025.
-View [Attributions](https://github.com/Lissy93/weather-front?tab=readme-ov-file#attributions) for credits, thanks and contributors. +Weather-Front is licensed under [MIT](https://github.com/lissy93/framework-benchmarks/blob/main/LICENSE) ยฉ Alicia Sykes 2025.
+View [Attributions](https://github.com/lissy93/framework-benchmarks?tab=readme-ov-file#attributions) for credits, thanks and contributors. diff --git a/apps/vanjs/README.md b/apps/vanjs/README.md index d5f679a7..08965fe6 100644 --- a/apps/vanjs/README.md +++ b/apps/vanjs/README.md @@ -2,7 +2,7 @@

๐Ÿš Weather Front - VanJS

-
+
A tiny weather app
๐Ÿš€ Demo โ— ๐Ÿ“Š Results @@ -40,9 +40,9 @@ This is a simple weather app, built in [VanJS](https://vanjs.org/) (as well as a | Task | Status | |---|---| -| **Test** - Executes all e2e and unit tests | [![Test Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/test-vanjs.svg)](https://github.com/Lissy93/weather-front/actions/workflows/test.yml) | -| **Lint** - Verifies code style and quality | [![Lint Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/lint-vanjs.svg)](https://github.com/Lissy93/weather-front/actions/workflows/lint.yml) | -| **Build** - Builds and deploys the app | [![Build Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/build-vanjs.svg)](https://github.com/Lissy93/weather-front/actions/workflows/build.yml) | +| **Test** - Executes all e2e and unit tests | [![Test Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/test-vanjs.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/test.yml) | +| **Lint** - Verifies code style and quality | [![Lint Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/lint-vanjs.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/lint.yml) | +| **Build** - Builds and deploys the app | [![Build Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/build-vanjs.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/build.yml) | @@ -50,7 +50,7 @@ This is a simple weather app, built in [VanJS](https://vanjs.org/) (as well as a ## Usage -First, follow the [repo setup instructions](https://github.com/Lissy93/weather-front?tab=readme-ov-file#usage). Then `cd apps/vanjs` and use the following commands: +First, follow the [repo setup instructions](https://github.com/lissy93/framework-benchmarks?tab=readme-ov-file#usage). Then `cd apps/vanjs` and use the following commands: ```bash npm run dev # Start dev server (vite --port 3000) @@ -92,7 +92,7 @@ Since the weather app is very simple, it may be helpful to see a more practical ## License -Weather-Front is licensed under [MIT](https://github.com/Lissy93/weather-front/blob/main/LICENSE) ยฉ Alicia Sykes 2025.
-View [Attributions](https://github.com/Lissy93/weather-front?tab=readme-ov-file#attributions) for credits, thanks and contributors. +Weather-Front is licensed under [MIT](https://github.com/lissy93/framework-benchmarks/blob/main/LICENSE) ยฉ Alicia Sykes 2025.
+View [Attributions](https://github.com/lissy93/framework-benchmarks?tab=readme-ov-file#attributions) for credits, thanks and contributors. diff --git a/apps/vue/README.md b/apps/vue/README.md index 4c2364c9..a0c17b28 100644 --- a/apps/vue/README.md +++ b/apps/vue/README.md @@ -2,7 +2,7 @@

๐Ÿ’š Weather Front - Vue 3

-
+
A tiny weather app
๐Ÿš€ Demo โ— ๐Ÿ“Š Results @@ -40,9 +40,9 @@ This is a simple weather app, built in [Vue 3](https://vuejs.org/) (as well as a | Task | Status | |---|---| -| **Test** - Executes all e2e and unit tests | [![Test Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/test-vue.svg)](https://github.com/Lissy93/weather-front/actions/workflows/test.yml) | -| **Lint** - Verifies code style and quality | [![Lint Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/lint-vue.svg)](https://github.com/Lissy93/weather-front/actions/workflows/lint.yml) | -| **Build** - Builds and deploys the app | [![Build Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/build-vue.svg)](https://github.com/Lissy93/weather-front/actions/workflows/build.yml) | +| **Test** - Executes all e2e and unit tests | [![Test Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/test-vue.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/test.yml) | +| **Lint** - Verifies code style and quality | [![Lint Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/lint-vue.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/lint.yml) | +| **Build** - Builds and deploys the app | [![Build Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/build-vue.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/build.yml) | @@ -50,7 +50,7 @@ This is a simple weather app, built in [Vue 3](https://vuejs.org/) (as well as a ## Usage -First, follow the [repo setup instructions](https://github.com/Lissy93/weather-front?tab=readme-ov-file#usage). Then `cd apps/vue` and use the following commands: +First, follow the [repo setup instructions](https://github.com/lissy93/framework-benchmarks?tab=readme-ov-file#usage). Then `cd apps/vue` and use the following commands: ```bash npm run dev # Start dev server (vite --port 3000) @@ -93,7 +93,7 @@ Since the weather app is very simple, it may be helpful to see a more practical ## License -Weather-Front is licensed under [MIT](https://github.com/Lissy93/weather-front/blob/main/LICENSE) ยฉ Alicia Sykes 2025.
-View [Attributions](https://github.com/Lissy93/weather-front?tab=readme-ov-file#attributions) for credits, thanks and contributors. +Weather-Front is licensed under [MIT](https://github.com/lissy93/framework-benchmarks/blob/main/LICENSE) ยฉ Alicia Sykes 2025.
+View [Attributions](https://github.com/lissy93/framework-benchmarks?tab=readme-ov-file#attributions) for credits, thanks and contributors. diff --git a/package-lock.json b/package-lock.json index fc611767..afada34f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "weather-front", + "name": "framework-benchmarks", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "weather-front", + "name": "framework-benchmarks", "version": "1.0.0", "license": "MIT", "devDependencies": { diff --git a/package.json b/package.json index 796f39af..5beb793a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,13 @@ { - "name": "weather-front", + "name": "framework-benchmarks", "version": "1.0.0", "description": "Cross-framework weather app comparison project", + "author": "Alicia Sykes", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/lissy93/framework-benchmarks" + }, "scripts": { "setup": "python scripts/setup/main.py", "test": "python scripts/verify/test.py", @@ -82,6 +88,9 @@ "serve:production": "node scripts/performance/production-server.js", "serve:single": "node scripts/performance/serve-single.js", "verify": "cd scripts && python verify/main.py" + }, + "dependencies": { + }, "devDependencies": { "@angular-eslint/eslint-plugin": "^20.1.1", @@ -113,11 +122,5 @@ "svelte", "angular" ], - "author": "Alicia Sykes", - "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/Lissy93/weather-front" - }, "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" } diff --git a/scripts/pyproject.toml b/scripts/pyproject.toml index 4f774dd9..82e274f8 100644 --- a/scripts/pyproject.toml +++ b/scripts/pyproject.toml @@ -3,7 +3,7 @@ requires = ["hatchling"] build-backend = "hatchling.build" [project] -name = "weather-front-scripts" +name = "framework-benchmarks-scripts" version = "1.0.0" description = "Python scripts for Weather Front benchmarking project" readme = "README.txt" @@ -58,4 +58,4 @@ exclude = [ ".git", ".venv", "venv", -] \ No newline at end of file +] diff --git a/scripts/run/build_website.py b/scripts/run/build_website.py index ade50698..4fc345a4 100644 --- a/scripts/run/build_website.py +++ b/scripts/run/build_website.py @@ -351,7 +351,7 @@ def generate_deployment_files(base_url: str, frameworks: List[Dict], output_dir: f.write(sitemap_content) # Generate _redirects for Netlify - redirects_content = "# Netlify redirects\n/*/source https://github.com/anthropics/weather-front/tree/main/apps/:splat 302\n/* /404/ 404\n" + redirects_content = "# Netlify redirects\n/*/source https://github.com/anthropics/framework-benchmarks/tree/main/apps/:splat 302\n/* /404/ 404\n" with open(output_dir / "_redirects", "w") as f: f.write(redirects_content) @@ -360,7 +360,7 @@ def generate_deployment_files(base_url: str, frameworks: List[Dict], output_dir: RewriteEngine On # Redirect source code requests to GitHub -RewriteRule ^([^/]+)/source/?$ https://github.com/anthropics/weather-front/tree/main/apps/$1 [R=302,L] +RewriteRule ^([^/]+)/source/?$ https://github.com/anthropics/framework-benchmarks/tree/main/apps/$1 [R=302,L] # Handle 404s ErrorDocument 404 /404/index.html @@ -465,4 +465,4 @@ def build_website(base_url: str, output: str, no_clean: bool, verbose: bool): if __name__ == "__main__": - build_website() \ No newline at end of file + build_website() diff --git a/scripts/run/serve.py b/scripts/run/serve.py index 97f15322..8e985006 100644 --- a/scripts/run/serve.py +++ b/scripts/run/serve.py @@ -161,7 +161,7 @@ def framework_app(framework_id: str, subpath: str = ''): def framework_source(framework_id: str): if framework_id not in self.frameworks: return self.website_generator.render_404(), 404 - github_url = f"https://github.com/anthropics/weather-front/tree/main/apps/{framework_id}" + github_url = f"https://github.com/anthropics/framework-benchmarks/tree/main/apps/{framework_id}" return redirect(github_url) def _setup_asset_routes(self) -> None: @@ -349,4 +349,4 @@ def serve(port: int, host: str, debug: bool) -> None: if __name__ == "__main__": - serve() \ No newline at end of file + serve() diff --git a/scripts/transform/build_app_readme.py b/scripts/transform/build_app_readme.py index 3b027fb0..5deb134b 100644 --- a/scripts/transform/build_app_readme.py +++ b/scripts/transform/build_app_readme.py @@ -32,7 +32,7 @@ def generate_section_header(framework: Dict) -> str:

{meta['emoji']} Weather Front - {fw_name}

-
+
A tiny weather app
๐Ÿš€ Demo โ— ๐Ÿ“Š Results @@ -77,9 +77,9 @@ def generate_section_status(framework: Dict) -> str: | Task | Status | |---|---| -| **Test** - Executes all e2e and unit tests | [![Test Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/test-{fw_id}.svg)](https://github.com/Lissy93/weather-front/actions/workflows/test.yml) | -| **Lint** - Verifies code style and quality | [![Lint Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/lint-{fw_id}.svg)](https://github.com/Lissy93/weather-front/actions/workflows/lint.yml) | -| **Build** - Builds and deploys the app | [![Build Status](https://raw.githubusercontent.com/Lissy93/weather-front/refs/heads/badges/build-{fw_id}.svg)](https://github.com/Lissy93/weather-front/actions/workflows/build.yml) | +| **Test** - Executes all e2e and unit tests | [![Test Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/test-{fw_id}.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/test.yml) | +| **Lint** - Verifies code style and quality | [![Lint Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/lint-{fw_id}.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/lint.yml) | +| **Build** - Builds and deploys the app | [![Build Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/refs/heads/badges/build-{fw_id}.svg)](https://github.com/lissy93/framework-benchmarks/actions/workflows/build.yml) | """ @@ -91,7 +91,7 @@ def generate_section_usage(framework: Dict) -> str: ## Usage -First, follow the [repo setup instructions](https://github.com/Lissy93/weather-front?tab=readme-ov-file#usage). Then `cd apps/{fw_dir}` and use the following commands: +First, follow the [repo setup instructions](https://github.com/lissy93/framework-benchmarks?tab=readme-ov-file#usage). Then `cd apps/{fw_dir}` and use the following commands: ```bash npm run dev # Start dev server ({build['devCommand']}) @@ -134,8 +134,8 @@ def generate_section_license() -> str: ## License -Weather-Front is licensed under [MIT](https://github.com/Lissy93/weather-front/blob/main/LICENSE) ยฉ Alicia Sykes 2025.
-View [Attributions](https://github.com/Lissy93/weather-front?tab=readme-ov-file#attributions) for credits, thanks and contributors. +Weather-Front is licensed under [MIT](https://github.com/lissy93/framework-benchmarks/blob/main/LICENSE) ยฉ Alicia Sykes 2025.
+View [Attributions](https://github.com/lissy93/framework-benchmarks?tab=readme-ov-file#attributions) for credits, thanks and contributors. """ diff --git a/scripts/transform/insert_statuses.py b/scripts/transform/insert_statuses.py index 49ea9002..cd35d3ee 100644 --- a/scripts/transform/insert_statuses.py +++ b/scripts/transform/insert_statuses.py @@ -6,7 +6,7 @@ from rich.progress import Progress, SpinnerColumn, TextColumn # Constants -REPO_URL = "https://github.com/Lissy93/weather-front" +REPO_URL = "https://github.com/lissy93/framework-benchmarks" BADGES_BRANCH = "badges" README_PATH = Path(".github/README.md") FRAMEWORKS_JSON = "frameworks.json" @@ -40,9 +40,9 @@ def generate_status_table(frameworks: List[Dict]) -> str: app_link = f'{icon} {fw_name}' # Badge URLs - build_badge = f"![{fw_name} Build Status](https://raw.githubusercontent.com/Lissy93/weather-front/{BADGES_BRANCH}/build-{fw_id}.svg)" - test_badge = f"![{fw_name} Test Status](https://raw.githubusercontent.com/Lissy93/weather-front/{BADGES_BRANCH}/test-{fw_id}.svg)" - lint_badge = f"![{fw_name} Lint Status](https://raw.githubusercontent.com/Lissy93/weather-front/{BADGES_BRANCH}/lint-{fw_id}.svg)" + build_badge = f"![{fw_name} Build Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/{BADGES_BRANCH}/build-{fw_id}.svg)" + test_badge = f"![{fw_name} Test Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/{BADGES_BRANCH}/test-{fw_id}.svg)" + lint_badge = f"![{fw_name} Lint Status](https://raw.githubusercontent.com/lissy93/framework-benchmarks/{BADGES_BRANCH}/lint-{fw_id}.svg)" table += f"| {app_link} | {build_badge} | {test_badge} | {lint_badge} |\n" diff --git a/website/static/css/framework-table.css b/website/static/css/framework-table.css index a72fd9e7..d3881f37 100644 --- a/website/static/css/framework-table.css +++ b/website/static/css/framework-table.css @@ -5,7 +5,7 @@ } .stats-table-container { - height: 600px; + height: 640px; width: 100%; border-radius: 8px; overflow: hidden; @@ -55,7 +55,6 @@ .framework-logo-cell img { width: 24px; - height: 24px; border-radius: 4px; flex-shrink: 0; } @@ -97,6 +96,9 @@ background: rgba(0, 0, 0, 0.1); border-radius: 3px; position: relative; + @media (max-width: 1024px) { + display: none; + } } .progress-text { diff --git a/website/static/js/framework-table.js b/website/static/js/framework-table.js index cca26a0b..5d9d1c57 100644 --- a/website/static/js/framework-table.js +++ b/website/static/js/framework-table.js @@ -5,6 +5,7 @@ class FrameworkTable { this.frameworksData = frameworksData; this.gridApi = null; this.isDark = document.documentElement.classList.contains('dark-theme'); + this.frameworksData = this.frameworksData.filter(fw => fw?.id !== 'vanilla'); } formatNumber(value, type = 'default') { @@ -61,7 +62,7 @@ class FrameworkTable { pinned: 'left', cellRenderer: (params) => { const framework = params.data; - const iconUrl = `https://cdn.simpleicons.org/${framework.id}`; + const iconUrl = `https://storage.googleapis.com/as93-screenshots/frontend-benchmarks/framework-logos/${framework.id}.png`; return `

${framework.name} diff --git a/website/templates/base.html b/website/templates/base.html index a03bf4dd..69fcc282 100644 --- a/website/templates/base.html +++ b/website/templates/base.html @@ -50,7 +50,7 @@

{{ config.website.title }}

@@ -62,9 +62,9 @@

{{ config.website.title }}

diff --git a/website/templates/framework.html b/website/templates/framework.html index fac9323d..94428c81 100644 --- a/website/templates/framework.html +++ b/website/templates/framework.html @@ -46,7 +46,7 @@

Demo

View {{framework.name}} Weather App - + @@ -195,15 +195,15 @@

Status

  • Lint - +
  • Build - +
  • Test - +
@@ -211,11 +211,11 @@

Status

@@ -224,7 +224,7 @@

Links

Usage Instructions

- First, follow the repo setup instructions + First, follow the repo setup instructions Then cd into 'apps/{{framework.id}}' and and use the following commands:

@@ -290,7 +290,7 @@

Feature Requirements

  • ๐ŸŒ Internationalized
  • - +
    diff --git a/website/templates/homepage.html b/website/templates/homepage.html index 52e22c84..cf7468d5 100644 --- a/website/templates/homepage.html +++ b/website/templates/homepage.html @@ -10,7 +10,7 @@

    Framework Benchmarks

    The same app, built in every frontend web framework, and then benchmarked

    - GitHub + GitHub Results Stats Apps From 2a5c7a0c2e7a92758a6f99fc0955b0a258861823 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sat, 23 Aug 2025 23:25:02 +0100 Subject: [PATCH 05/12] Implemenmt chart image generation using quickcharts, and insert into readme --- .github/README.md | 10 ++ .github/workflows/transform-results.yml | 4 +- scripts/transform/build_charts.py | 160 ++++++++++++++++++++++-- 3 files changed, 161 insertions(+), 13 deletions(-) mode change 100755 => 100644 scripts/transform/build_charts.py diff --git a/.github/README.md b/.github/README.md index cd9f18f4..dbf28507 100644 --- a/.github/README.md +++ b/.github/README.md @@ -235,6 +235,16 @@ Each app gets built and tested to ensure that it is functional, compliant with t ## Results +A summary of results can be viewed in [`summary.tsv`](https://github.com/Lissy93/framework-benchmarks/blob/main/results/summary.tsv).
    +Full, detailed results can be found in the [`results`](https://github.com/Lissy93/framework-benchmarks/tree/results) branch, +or attached as an artifact in the GitHub Actions benchmarking workflow runs. +For slightly more interactive reports, you can view the website at [framework-benchmarks.as93.net](https://framework-benchmarks.as93.net), +and also view a stats on a per-framework basis. + +### Summary + + + ### Community Info diff --git a/.github/workflows/transform-results.yml b/.github/workflows/transform-results.yml index 5063baf4..1af223ec 100644 --- a/.github/workflows/transform-results.yml +++ b/.github/workflows/transform-results.yml @@ -102,7 +102,7 @@ jobs: run: | echo "๐Ÿ“Š Generating Chart.js configurations..." python scripts/transform/build_charts.py - echo "โœ… Chart configurations generated" + echo "โœ… Chart configurations and README charts generated" - name: ๐Ÿ“Š Generate Results Summary run: | @@ -119,7 +119,7 @@ jobs: git config user.email "alicia-gh-bot@mail.as93.net" # Only commit if there are changes - git add results/ website/static/chart*.json website/static/charts/ || true + git add results/ website/static/chart*.json website/static/charts/ .github/README.md || true if git diff --cached --quiet; then echo "โ„น๏ธ No changes to commit." echo "skip_commit=true" >> $GITHUB_ENV diff --git a/scripts/transform/build_charts.py b/scripts/transform/build_charts.py old mode 100755 new mode 100644 index 44b18f93..a35a9510 --- a/scripts/transform/build_charts.py +++ b/scripts/transform/build_charts.py @@ -7,6 +7,8 @@ import json import math import os +import urllib.parse +import requests from pathlib import Path from typing import Dict, List, Any, Optional @@ -69,6 +71,16 @@ 'large': 500 } +# QuickChart.io configuration +QUICKCHART_DEFAULT_WIDTH = 400 +QUICKCHART_DEFAULT_HEIGHT = 400 +QUICKCHART_CREATE_URL = 'https://quickchart.io/chart/create' +QUICKCHART_BASE_URL = 'https://quickchart.io/chart' + +# Chart scale configuration +LIGHTHOUSE_MIN_SCALE = 80 # Start Lighthouse charts at 80 instead of 0 +PERFORMANCE_MIN_SCALE = 80 # Start performance charts at 80 instead of 0 + # ============================================================================= # UTILITY FUNCTIONS # ============================================================================= @@ -512,7 +524,7 @@ def create_lighthouse_radial_chart(data: Dict[str, Any]) -> Dict[str, Any]: config['options']['scales'] = { 'r': { 'beginAtZero': False, - 'min': 80, + 'min': LIGHTHOUSE_MIN_SCALE, 'max': 100, 'ticks': { 'stepSize': 5 @@ -526,16 +538,35 @@ def create_source_analysis_chart(data: Dict[str, Any]) -> Dict[str, Any]: """Generate horizontal stacked bar chart for source analysis metrics.""" config = get_base_chart_config('bar') config['options']['indexAxis'] = 'y' # Make it horizontal - config['options']['scales'] = get_categorical_scales_config() - # Swap x and y for horizontal orientation - config['options']['scales']['y']['stacked'] = True - config['options']['scales']['x']['stacked'] = True - config['options']['scales']['y']['type'] = 'category' - config['options']['scales']['y']['grid'] = {'display': False} - config['options']['scales']['x']['type'] = 'linear' - config['options']['scales']['x']['beginAtZero'] = True - config['options']['scales']['x']['grid'] = {'color': 'rgba(0, 0, 0, 0.1)', 'drawOnChartArea': True} + # Configure horizontal scales + config['options']['scales'] = { + 'x': { + 'type': 'linear', + 'beginAtZero': True, + 'stacked': True, + 'grid': { + 'color': GRID_COLOR, + 'drawOnChartArea': True + }, + 'title': { + 'display': True, + 'text': 'Count', + 'font': { + 'family': FONT_FAMILY, + 'size': FONT_SIZE_LABEL, + 'weight': 'bold' + } + } + }, + 'y': { + 'type': 'category', + 'stacked': True, + 'grid': { + 'display': False + } + } + } # Collect and sort frameworks by total size (logical lines + files*10 + complexity) framework_data_list = [] @@ -725,8 +756,15 @@ def create_performance_quadrant_chart(data: Dict[str, Any]) -> Dict[str, Any]: # Override interaction mode for scatter plot config['options']['interaction']['mode'] = 'point' + # Calculate min/max values for better scaling + performance_scores = [fw_data['lighthouse']['scores']['performance'] for fw_data in data['frameworks'].values()] + min_performance = min(performance_scores) + y_axis_min = max(PERFORMANCE_MIN_SCALE, min_performance - 5) + config['options']['scales']['x']['title']['text'] = 'Bundle Size (KB, gzipped)' config['options']['scales']['y']['title']['text'] = 'Performance Score' + config['options']['scales']['y']['min'] = y_axis_min + config['options']['scales']['y']['max'] = 100 datasets = [] for framework_id, framework_data in data['frameworks'].items(): @@ -983,6 +1021,81 @@ def generate_all_charts(results_dir: Path) -> Dict[str, Dict[str, Any]]: return charts +# ============================================================================= +# QUICKCHART.IO URL GENERATION +# ============================================================================= + +def create_quickchart_url(chart_config, width=QUICKCHART_DEFAULT_WIDTH, height=QUICKCHART_DEFAULT_HEIGHT, use_short_url=True): + payload = {'chart': chart_config, 'v': '3', 'width': width, 'height': height, 'backgroundColor': 'white'} + if use_short_url: + try: + r = requests.post(QUICKCHART_CREATE_URL, json=payload, timeout=10) + if r.ok and 'url' in r.json(): + return r.json()['url'] + except Exception as e: + print(f"Warning: Short URL generation failed, using regular URL: {e}") + config_json = json.dumps(chart_config, separators=(',', ':')) + encoded = urllib.parse.quote(config_json) + return f"{QUICKCHART_BASE_URL}?v=3&c={encoded}&w={width}&h={height}&bkg=white" + + +def get_summary_charts(charts): + cfgs = [ + ('performance_radar', 'Performance Overview'), + ('performance_quadrant', 'Performance vs Bundle Size'), + ('source_analysis', 'Source Code Analysis'), + ('bundle_size_comparison', 'Bundle Size and Comparison'), + ('lighthouse_radial', 'Lighthouse Performance Scores'), + ('load_timeline', 'Loading Performance'), + ('project_size_pie', 'Project Size Distribution'), + ('dev_server_performance', 'Development Server Performance'), + ('build_time_donut', 'Build Time Distribution'), + ] + return [ + {'title': t, 'url': create_quickchart_url(charts[cid]), 'chart_id': cid} + for cid, t in cfgs if cid in charts + ] + +def generate_readme_charts_markdown(summary_charts): + """Generate markdown content for README chart section.""" + imgs = '\n'.join(f' {c[' for c in summary_charts) + return f'

    \n{imgs}\n

    ' + +def update_readme_with_charts(readme_path: Path, summary_charts: List[Dict[str, str]]) -> None: + """Update README.md with generated chart URLs.""" + if not readme_path.exists(): + print(f"README not found at {readme_path}") + return + + with open(readme_path, 'r') as f: + content = f.read() + + # Generate new chart content + chart_markdown = generate_readme_charts_markdown(summary_charts) + print(f" Generated chart markdown: {len(chart_markdown)} characters") + + # Replace content between markers + start_marker = "" + end_marker = "" + + start_idx = content.find(start_marker) + end_idx = content.find(end_marker) + print(f" Searching for markers: start_idx={start_idx}, end_idx={end_idx}") + + if start_idx != -1 and end_idx != -1: + new_content = ( + content[:start_idx + len(start_marker)] + + "\n" + chart_markdown + "\n" + + content[end_idx:] + ) + + with open(readme_path, 'w') as f: + f.write(new_content) + + print(f" Updated README with {len(summary_charts)} chart images") + else: + print(" Warning: Chart markers not found in README") + def main(): """Main function to generate and save chart configurations.""" script_dir = Path(__file__).parent @@ -1016,7 +1129,32 @@ def main(): json.dump(combined_config, f, indent=2) print(f" All chart configurations saved to {output_dir}") - print(f"=๏ฟฝ Generated {len(charts)} chart types") + print(f"=๐Ÿ“Š Generated {len(charts)} chart types") + + # Now run QuickChart.io integration + try: + print(" Running QuickChart.io integration...") + readme_path = script_dir.parent.parent / ".github" / "README.md" + summary_charts = get_summary_charts(charts) + + # Save chart URLs to a file + chart_urls_file = output_dir / "chart-urls.json" + chart_urls_data = { + "generated_at": "2025-08-19T23:55:00Z", + "summary_charts": summary_charts + } + + with open(chart_urls_file, "w") as f: + json.dump(chart_urls_data, f, indent=2) + + # Update README with chart images + update_readme_with_charts(readme_path, summary_charts) + + print(f" Generated {len(summary_charts)} QuickChart.io URLs") + except Exception as e: + print(f" Error in QuickChart.io integration: {e}") + import traceback + traceback.print_exc() if __name__ == '__main__': main() From 96c0810f69521149ada1efcd3b93a5e27611cef6 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sat, 23 Aug 2025 23:59:02 +0100 Subject: [PATCH 06/12] Update per-app readmes, and insert content into per-app webpage --- .github/README.md | 11 +++++++++++ apps/alpine/README.md | 18 +++++++++++++++++- apps/angular/README.md | 19 +++++++++++++++++-- apps/jquery/README.md | 17 ++++++++++++++++- apps/lit/README.md | 17 ++++++++++++++++- apps/preact/README.md | 19 ++++++++++++++++++- apps/qwik/README.md | 18 +++++++++++++++++- apps/react/README.md | 18 +++++++++++++++++- apps/solid/README.md | 17 ++++++++++++++++- apps/svelte/README.md | 18 +++++++++++++++++- apps/vanilla/README.md | 18 +++++++++++++++++- apps/vanjs/README.md | 18 +++++++++++++++++- apps/vue/README.md | 21 ++++++++++++++++++++- scripts/run/build_website.py | 30 ++++++++++++++++++++++++++++-- scripts/run/generator.py | 6 ++++++ website/static/css/framework.css | 4 ++++ website/templates/framework.html | 15 +++++++++++++-- 17 files changed, 267 insertions(+), 17 deletions(-) diff --git a/.github/README.md b/.github/README.md index dbf28507..ac141c01 100644 --- a/.github/README.md +++ b/.github/README.md @@ -243,6 +243,17 @@ and also view a stats on a per-framework basis. ### Summary +

    + Performance Overview + Performance vs Bundle Size + Source Code Analysis + Bundle Size and Comparison + Lighthouse Performance Scores + Loading Performance + Project Size Distribution + Development Server Performance + Build Time Distribution +

    ### Community Info diff --git a/apps/alpine/README.md b/apps/alpine/README.md index 0dce6a41..14f412eb 100644 --- a/apps/alpine/README.md +++ b/apps/alpine/README.md @@ -67,13 +67,29 @@ For troubleshooting, use `npm run verify` from the root of the project. ## Alpine Implementation -### Notable files - `index.html` - Main HTML with Alpine directives sprinkled in - `js/weather-app.js` - Alpine data and methods for weather logic - `js/weather-service.js` - API calls integrated with Alpine reactivity - `js/weather-utils.js` - Utility functions for data formatting +## About Alpine + + + +## My Thoughts on Alpine + + +Alpine.js is like jQuery had a baby with Vue and decided to live directly in your HTML. It's refreshingly simple - you sprinkle a few `x-` attributes into your markup and suddenly you have reactive behavior. No build tools, no bundlers, no complexity. Just add a script tag and start building. + +The approach feels intuitive once you get it. `x-data` sets up your reactive state, `x-show` handles conditional rendering, and `x-for` loops through arrays. Our weather app's forecast list is just `
    ` - no components, no imports, no ceremony. + +What's clever is how Alpine stays out of your way. The HTML is still readable, the JavaScript is minimal, and everything degrades gracefully if Alpine doesn't load. It's progressive enhancement done right - the page works without JavaScript, but becomes interactive when it loads. + +The syntax reads naturally: `x-on:click="searchWeather()"`, `x-text="temperature"`, `x-bind:class="{'active': isExpanded}"`. It's declarative like Vue templates but lives right in the HTML. The reactive updates happen automatically when you modify the data. + +For simple interactive websites, Alpine hits the sweet spot. You get modern reactivity without the complexity of a full framework. But for anything complex, you'll miss proper component organization and tooling. Alpine works great for [my whois lookup API](https://github.com/Lissy93/who-dat), because I just needed sprinkles of interactivity to update results, not a full SPA experience. + diff --git a/apps/angular/README.md b/apps/angular/README.md index c93c47de..66e97482 100644 --- a/apps/angular/README.md +++ b/apps/angular/README.md @@ -64,10 +64,12 @@ For troubleshooting, use `npm run verify` from the root of the project. -## Angular Implementation +## About Angular + + +## Angular Implementation -### Notable files - `src/app/app.component.ts` - Root component with weather state management - `src/app/services/weather.service.ts` - Injectable service using Angular's HttpClient - `src/app/services/weather-state.service.ts` - Centralized state with RxJS observables @@ -75,6 +77,19 @@ For troubleshooting, use `npm run verify` from the root of the project. - `src/app/types/weather.types.ts` - TypeScript interfaces for type safety +## My Thoughts on Angular + +Angular isn't the cool kid anymore, but it's incredibly solid and ships with absolutely everything you need. TypeScript from day one, dependency injection, forms, HTTP client, routing, testing utilities - it's all there, officially maintained and deeply integrated. No need to cobble together a stack from random npm packages. + +For our weather app, Angular did kinda feel like using a sledgehammer to crack a nut. Using the newer standalone components (no more `NgModule` boilerplate!) made things cleaner, but I was still writing a lot more code than I needed in Svelte or Vue. That said, everything does just works, and the TypeScript integration is phenomenal. + +The dependency injection system was quite nice for having `WeatherService` automatically injected into components. And RxJS observables handle all the async weather data very nicley, though they do add a learning curve if you're not familiar with reactive programming. + +Angular's template syntax with `*ngIf`, `*ngFor`, and `(click)` feels natural once you get used to it. Change detection just works without thinking about it (unlike React where you're constantly memoizing things). + +For a simple weather app, we really didn't need any of Angular's big or flagship features (like guards, resolvers, or lazy loading). But I recently build [Domain Locker](https://github.com/lissy93/domain-locker) using Angular, and it was a great fit for the complexity of that project, As the structure, type safety, and tooling made it easy to manage a large codebase with multiple features. + + diff --git a/apps/jquery/README.md b/apps/jquery/README.md index a8533f26..564cfccc 100644 --- a/apps/jquery/README.md +++ b/apps/jquery/README.md @@ -67,13 +67,28 @@ For troubleshooting, use `npm run verify` from the root of the project. ## jQuery Implementation -### Notable files - `src/main.js` - Application initialization and jQuery setup - `src/components/weather-ui.js` - Manual DOM management and event handling - `src/services/weather-service.js` - API calls with `$.ajax()` - `index.html` - Plain HTML structure with jQuery CDN +## About jQuery + + + +## My Thoughts on jQuery + +Let's be honest - building a modern app with jQuery in 2024 feels like showing up to a Formula 1 race with a vintage car. It'll get you there, but everyone will wonder what the f*ck you are on. Still, jQuery powered the web for over a decade, and is still actually very widley used (thanks WordPress), so it's worth understanding what made it so dominant. Nowadays pertty much everything jQuery could do, is implemented into ES6+ natively, so there's little point in jQuery (unless u r supporting IE11). + +The TL;DR of jQuery's magic was always in the simplicity. `$('#weather-display').html(weatherHtml)` just *works*. No virtual DOM, no component lifecycle, no build process - just select elements and manipulate them. The method chaining is genuinely elegant: `$('.forecast-item').addClass('active').fadeIn(300)` reads like English. + +For our weather app, jQuery actually handles the basic functionality fine. Event delegation with `$(document).on('click', '.forecast-toggle', handler)` works perfectly, and `$.ajax()` fetches weather data without fuss. But you quickly realize you're manually managing everything React or Vue handles automatically - state updates, DOM synchronization, component organization. + +The imperative style becomes tedious fast. Want to update the temperature display? Manually find the element and change its text. Need to show/hide loading states? Manually toggle CSS classes. It works, but you'll write 3x more code than you would in Svelte. + +jQuery still has its place for simple enhancements to static sites, but for anything interactive, modern frameworks or even vanilla JS, are just better. The ecosystem and community have largely moved on, and you'll spend more time fighting against jQuery's limitations than building features. + diff --git a/apps/lit/README.md b/apps/lit/README.md index 751cc2b9..41c61752 100644 --- a/apps/lit/README.md +++ b/apps/lit/README.md @@ -66,13 +66,28 @@ For troubleshooting, use `npm run verify` from the root of the project. ## Lit Implementation -### Notable files - `src/weather-app.js` - Main application as a custom element - `src/weather-display.js` - Weather data display component - `src/weather-forecast.js` - Forecast list with lit-html templates - `src/weather-search.js` - Search form component with event binding +## About Lit + + + +## My Thoughts on Lit + +Lit can feel like stepping back into the old React class component days, but actually the cohesion to web standards makes Lit pretty... lit. It's built around Web Components, which is both its greatest strength and biggest frustration. Everything is properly encapsulated and framework-agnostic, but the developer experience feels surprisingly verbose for 2025. + +The weird expression syntax has caught me out a lot. Want to bind a property? Use `.value="${this.temp}"`. A boolean attribute? `?disabled="${this.loading}"`. An event listener? `@click="${this.handleClick}"`. It's functional once you memorize the symbols, but it breaks the flow when you're trying to think about business logic. + +Class-based components can feel outdated after years of hooks and functional patterns. Creating a simple weather display requires extending `LitElement`, defining `@property` decorators, implementing `render()`, and handling lifecycle methods manually. It works, but feels like unnecessary ceremony. + +The shadow DOM isolation is cool in theory - your styles can't leak, global CSS can't interfere. But in practice, it creates more problems than it solves. Want to style components consistently? Good luck getting your design system to work across shadow boundaries. Because of this, I really struggled to get the shared weather styles working across the Lit app. If you want to submit a PR to fix this, please do! + +But Lit really does shine for design systems and component libraries where you need true framework-agnostic components. I did build [Email Comparison](https://email-comparison.as93.net/) in Lit, but in heindsite, I think that was a mistake! + diff --git a/apps/preact/README.md b/apps/preact/README.md index 24f05a26..2c3e0866 100644 --- a/apps/preact/README.md +++ b/apps/preact/README.md @@ -66,7 +66,6 @@ For troubleshooting, use `npm run verify` from the root of the project. ## Preact Implementation -### Notable files - `src/App.jsx` - Main component with familiar React-style hooks - `src/hooks/useWeatherData.js` - Custom hook for weather state and API calls - `src/components/` - Standard functional components with hooks @@ -74,6 +73,24 @@ For troubleshooting, use `npm run verify` from the root of the project. +## About Preact + + + +## My Thoughts on Preact + +If you love React but hate the bundle size, Preact is your best friend. It's essentially React, but 3KB instead of 40KB. Same hooks, same JSX, same mental model - just way more efficient. You can literally take a React component, change the import from `react` to `preact`, and it'll work. + +For our weather app, switching from React to Preact required basically zero changes. The `useWeatherData` custom hook works identically, functional components behave the same, and `useState` does exactly what you'd expect. But the compiled bundle is drastically smaller and noticeably faster. + +Preact's secret sauce is smart optimizations under the hood. It skips unnecessary work that React's virtual DOM usually does, and includes automatic component memoization that you'd have to add manually in React with `memo()`. The reconciliation algorithm is also more direct, making updates snappier. + +The developer experience is identical to React. Hot refresh works perfectly, the dev tools are solid, and you can use most React libraries via `preact/compat`. Really, the only difference is your bundle analyzer will make you smile. + +I didn't need Preact's router or state management libraries for this simple app, but they follow the same lightweight philosophy. For anything bigger, you'd probably reach for the React ecosystem anyway via the compat layer. + + + ## Real-World App diff --git a/apps/qwik/README.md b/apps/qwik/README.md index 8eeb0b84..1f9fcbfd 100644 --- a/apps/qwik/README.md +++ b/apps/qwik/README.md @@ -66,13 +66,29 @@ For troubleshooting, use `npm run verify` from the root of the project. ## Qwik Implementation -### Notable files - `src/App.tsx` - Main component with resumable state - `src/stores/weatherStore.ts` - Qwik stores that serialize automatically - `src/services/WeatherService.ts` - API calls with progressive loading - `src/components/` - Components that wake up on demand +## About Qwik + + + +## My Thoughts on Qwik + +Qwik is kinda wild. It completely rethinks how web apps work by doing something called "resumability" - your page loads instantly with zero JavaScript, then individual components wake up only when you interact with them. It's like having a webpage that's asleep until you poke it. + +The secret is those `$` symbols everywhere. `component$()`, `useTask$()`, `onClick$()` - these aren't just weird syntax, they're lazy loading boundaries. Each `$` tells Qwik "this code can be loaded later when needed." So clicking a button doesn't load the entire app, it just loads that specific button's handler. + +For our weather app, this means the initial page render is lightning fast - just HTML and CSS. Search for a city, and only *then* does the search logic get loaded. Click to expand a forecast day, and only the expansion code gets fetched. It's incremental interactivity taken to its logical extreme. + +The state management feels familiar but with superpowers. Qwik stores automatically serialize to HTML, so when components resume, they pick up exactly where they left off. No hydration mismatch, no loading spinners, just seamless continuation. For that reason, I used Qwik to build the interactive stuff on my [Digital Defense](https://digital-defense.io/) website. + +The trade-off is developer complexity - all those `$` symbols take getting used to, and debugging can be tricky when code loads on-demand. But for performance-critical apps, especially content-heavy sites, Qwik's approach is genuinely revolutionary. Your Core Web Vitals scores will thank you. + + diff --git a/apps/react/README.md b/apps/react/README.md index 31262038..92d69a4e 100644 --- a/apps/react/README.md +++ b/apps/react/README.md @@ -66,13 +66,29 @@ For troubleshooting, use `npm run verify` from the root of the project. ## React Implementation -### Notable files - `src/App.jsx` - Main component with hooks-based state management - `src/hooks/useWeatherData.js` - Custom hook for weather logic and API calls - `src/components/ErrorBoundary.jsx` - Error boundary for crash protection - `src/components/` - Modular functional components +## About React + + + +## My Thoughts on React + +React is everywhere, powering millions of websites and used by every major tech company. It's been around for over 12 years, and both React and its tooling are incredibly mature. There's a reason it became the default choice for so many teams - the ecosystem is massive, jobs are plentiful, and you can build basically anything. + +But it's not perfect. Our weather app showcases both React's strengths and frustrations. The component model is elegant, `useState` and `useEffect` work fine for simple state, and the custom `useWeatherData` hook abstracts the weather logic nicely. But you're constantly thinking about re-renders, dependency arrays, and manual memoization. + +The virtual DOM adds overhead that other frameworks avoid entirely. Need to optimize performance? Time to sprinkle `React.memo`, `useCallback`, and `useMemo` everywhere. Coming from Svelte or Solid, all this manual work feels tedious. But the developer tooling is exceptional and the community support is unmatched. + +The JSX syntax is familiar once you get used to the quirks - `className` instead of `class`, self-closing tags, and JavaScript expressions in curly braces. Controlled components with `value` and `onChange` work well for forms, though they're more verbose than Vue's `v-model`. + +React really shines for complex applications where the ecosystem matters. We didn't need Redux, React Query, or code splitting for this simple weather app, but for something like [Web Check](https://github.com/lissy93/web-check), these tools become essential. The flexibility to choose your own architecture is both React's blessing and curse. + + diff --git a/apps/solid/README.md b/apps/solid/README.md index da75e351..b660e84b 100644 --- a/apps/solid/README.md +++ b/apps/solid/README.md @@ -67,13 +67,28 @@ For troubleshooting, use `npm run verify` from the root of the project. ## Solid Implementation -### Notable files - `src/App.jsx` - Main component using Solid's reactive primitives - `src/stores/weatherStore.js` - Global state with `createStore` - `src/services/WeatherService.js` - API integration with `createResource` - `src/components/` - Reactive components that update precisely +## About Solid + + + +## My Thoughts on Solid + +Solid feels like React, but *actually* reactive. It looks like JSX, but underneath it's magic. While React re-renders entire component trees, Solid surgically updates only the exact DOM nodes that need to change. The result is performance that makes other frameworks look sluggish. + +The mental shift from React is subtle but profound. Instead of thinking about re-renders and memoization, you think about signals and reactivity. `createSignal` returns a getter and setter - call `temperature()` to read, `setTemperature(25)` to update, and everything that depends on it automatically updates. + +Our weather app showcases this, as the temperature display, the weather icon, the styling - they all react independently when the weather data changes. No `useEffect`, no dependency arrays, no `useMemo` - just pure reactive programming that actually works. + +The JSX looks familiar, but `` and `` components replace your typical `{condition &&
    }` patterns. These aren't just syntactic sugar - they're compiled into efficient conditional rendering that only updates when necessary. + +`createResource` handles async data elegantly, giving you loading states, error handling, and refetching without the usual ceremony. For our simple weather app, we didn't need Solid's more advanced features like stores or effects, but for something complex, the fine-grained reactivity becomes essential. + diff --git a/apps/svelte/README.md b/apps/svelte/README.md index 978991c7..f959539b 100644 --- a/apps/svelte/README.md +++ b/apps/svelte/README.md @@ -66,13 +66,29 @@ For troubleshooting, use `npm run verify` from the root of the project. ## Svelte Implementation -### Notable files - `src/routes/+page.svelte` - Main page using SvelteKit's file-based routing - `src/lib/stores/weather-store.js` - Global state with Svelte writable stores - `src/lib/services/weather-service.js` - API calls integrated with stores - `src/lib/components/` - Single-file components with scoped styles +## About Svelte + + + +## My Thoughts on Svelte + +Svelte is just *fun*. There's something magical about writing `count += 1` and having the UI automatically update. No `useState`, no `useEffect`, no `ref()` - just assign to a variable and it reacts. This is how UI frameworks should work. + +Unlike React or Vue, Svelte doesn't ship a runtime. Your components get compiled into highly optimized vanilla JavaScript at build time. The result? Tiny bundles, blazing fast performance, and surprisingly readable compiled output. Our weather app compiles down to around 15KB, which is frankly ridiculous for a full-featured application. + +The `$:` reactive statements are brilliant for computed values - `$: tempDisplay = `${temp}ยฐC`` just works and updates whenever `temp` changes. Svelte stores handle global state beautifully, and the automatic subscription cleanup means you never have to worry about memory leaks. + +The template syntax feels natural - `{#if}`, `{#each}`, and `{#await}` blocks handle conditional rendering and async data elegantly. Two-way binding with `bind:value` eliminates the usual form boilerplate you'd write in React. + +For our simple weather app, we didn't need Svelte's built-in animations or transitions. But Svelte is my go to choice for nearly all my personal projects, as these features become incredibly powerful. The `transition:` and `animate:` directives can make your UI feel incredibly polished with minimal code. + + diff --git a/apps/vanilla/README.md b/apps/vanilla/README.md index dfdb47b2..f03123d8 100644 --- a/apps/vanilla/README.md +++ b/apps/vanilla/README.md @@ -67,13 +67,29 @@ For troubleshooting, use `npm run verify` from the root of the project. ## Vanilla JavaScript Implementation -### Notable files - `src/main.js` - Application initialization and DOM manipulation - `src/weather-service.js` - API calls using native fetch - `src/weather-utils.js` - Utility functions for data processing - `index.html` - Pure HTML structure without framework dependencies +## About JavaScript + + + +## My Thoughts on JavaScript + +Sometimes the best framework is no framework. Vanilla JavaScript forces you to understand what's actually happening under the hood of all those fancy abstractions. No magic, no build steps, no dependency hell - just the web platform as intended. + +For our weather app, vanilla JS is surprisingly capable. `fetch()` handles API calls, `document.querySelector()` finds elements, and `addEventListener()` manages interactions. Modern browser APIs like `localStorage`, `geolocation`, and CSS custom properties give you most of what you need without any external dependencies. + +The challenge is organization and state management. Without a framework's structure, you're responsible for everything - keeping the DOM in sync with data, organizing code sensibly, and avoiding spaghetti. Our weather app uses a simple pub/sub pattern and functional organization, but it requires discipline. + +The performance is excellent since there's no framework overhead, and the bundle size is minimal. Everything loads fast, and you're not shipping someone else's code to your users. For simple applications or when performance is critical, vanilla JS can be the right choice. + +But you'll miss the conveniences of modern frameworks - automatic updates, component organization, and developer experience. What takes one line in React might take ten in vanilla JS. It's a trade-off between control and convenience. + + diff --git a/apps/vanjs/README.md b/apps/vanjs/README.md index 08965fe6..bfe936cc 100644 --- a/apps/vanjs/README.md +++ b/apps/vanjs/README.md @@ -66,13 +66,29 @@ For troubleshooting, use `npm run verify` from the root of the project. ## VanJS Implementation -### Notable files - `src/main.js` - Application logic with VanJS state and DOM creation - `src/weather-service.js` - API calls that update VanJS reactive state - `src/weather-utils.js` - Utility functions for data processing - `index.html` - Minimal HTML with VanJS script tag +## About Van + + + +## My Thoughts on Van + +VanJS is impressively tiny - just 1KB of runtime with zero dependencies. It's basically "what if we took the reactive parts of modern frameworks and stripped away everything else?" The result is surprisingly elegant for simple applications, but you'll quickly bump into its limitations. + +The functional approach is refreshing after dealing with classes and complex component lifecycles. `van.state(initialValue)` creates reactive state, `van.tags.div()` creates DOM elements, and everything just works. Our weather app's temperature display is literally `van.tags.span(temperature)` - when `temperature` changes, the DOM updates automatically. + +But the simplicity comes with trade-offs. There's no component abstraction beyond functions, no templating system, no event system. You're essentially building a reactive version of vanilla DOM manipulation. It works for basic interactivity but gets unwieldy fast. + +The DOM creation syntax is functional but verbose: `van.tags.div({class: "weather-card"}, van.tags.h2("Weather"))`. Coming from JSX or template languages, it feels like writing assembly code. You'll miss the declarative nature of modern frameworks. + +VanJS works well for simple enhancements where you need just a touch of reactivity without the framework overhead. I've used it for mini apps, like [raid-calculator](https://github.com/lissy93/raid-calculator). But for anything substantial, you'll spend more time fighting the limitations than building features. It's an interesting experiment in minimalism, but modern frameworks exist for good reasons. + + diff --git a/apps/vue/README.md b/apps/vue/README.md index a0c17b28..cf6f8730 100644 --- a/apps/vue/README.md +++ b/apps/vue/README.md @@ -67,13 +67,32 @@ For troubleshooting, use `npm run verify` from the root of the project. ## Vue Implementation -### Notable files - `src/App.vue` - Main component using Vue's Composition API - `src/services/weatherService.js` - API integration with Vue's reactive patterns - `src/components/` - Single File Components with scoped styles - `src/utils/weatherUtils.js` - Utility functions for data processing +## About Vue + +TEST123 + + +## My Thoughts on Vue + +Vue sits in the Goldilocks zone - not as minimal as Alpine, not as opinionated as Angular, just right for most projects. It feels like the framework that actually learned from React's mistakes while keeping the good parts. Single File Components are brilliant, the template syntax is intuitive, and reactivity just works without the mental gymnastics of `useEffect`. + +For our weather app, Vue felt natural and productive. The `v-if`, `v-for`, and `v-model` directives handle conditional rendering, lists, and form inputs elegantly. No weird JSX quirks, no manual event handling - just HTML that does what you expect. The Composition API gives you React-style logic organization when you need it, but Options API is still there for simpler components. + +The reactivity system using Proxies is genuinely impressive. Change a data property and everything dependent on it updates automatically. No `useState`, no memoization hell, no stale closures. Vue tracks dependencies behind the scenes and updates only what needs to change. + +The Single File Component format is perfect - template, script, and styles all in one file with proper scoping. `