diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8ac6cc8..f8827e6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,3 +36,46 @@ jobs: - name: Build run: pnpm build + + # Upload build artifacts for Lighthouse CI job + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: dist + path: dist + retention-days: 1 + + lighthouse: + runs-on: ubuntu-latest + needs: ci + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Download build artifacts + uses: actions/download-artifact@v4 + with: + name: dist + path: dist + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Install Lighthouse CI + run: npm install -g @lhci/cli@0.14.x + + - name: Run Lighthouse CI + run: lhci autorun + env: + LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }} + + - name: Upload Lighthouse report + uses: actions/upload-artifact@v4 + if: always() + with: + name: lighthouse-report + path: .lighthouseci + retention-days: 7 diff --git a/.gitignore b/.gitignore index 8a6fc6a..a3179f5 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,8 @@ pnpm-debug.log* # Test files test-*.html test-*.mjs +*-test.png +*-screenshot.png test-*.js preview-*.mjs launch-*.mjs @@ -35,6 +37,9 @@ test-results-*.md *.svg svg-preview.html +# Lighthouse CI +.lighthouseci/ + # Playwright playwright-report/ test-results/ diff --git a/SEO_CHECKLIST.md b/docs/SEO_CHECKLIST.md similarity index 100% rename from SEO_CHECKLIST.md rename to docs/SEO_CHECKLIST.md diff --git a/SEO_IMPLEMENTATION_REPORT.md b/docs/SEO_IMPLEMENTATION_REPORT.md similarity index 100% rename from SEO_IMPLEMENTATION_REPORT.md rename to docs/SEO_IMPLEMENTATION_REPORT.md diff --git a/SEO_SEMANTIC_HTML_GUIDE.md b/docs/SEO_SEMANTIC_HTML_GUIDE.md similarity index 100% rename from SEO_SEMANTIC_HTML_GUIDE.md rename to docs/SEO_SEMANTIC_HTML_GUIDE.md diff --git a/lighthouserc.json b/lighthouserc.json new file mode 100644 index 0000000..52f47bc --- /dev/null +++ b/lighthouserc.json @@ -0,0 +1,35 @@ +{ + "ci": { + "collect": { + "staticDistDir": "./dist", + "numberOfRuns": 3, + "url": ["http://localhost/"], + "settings": { + "preset": "desktop", + "skipAudits": ["uses-http2", "redirects-http"] + } + }, + "assert": { + "assertions": { + "first-contentful-paint": ["warn", { "maxNumericValue": 2000 }], + "largest-contentful-paint": ["error", { "maxNumericValue": 2500 }], + "cumulative-layout-shift": ["error", { "maxNumericValue": 0.1 }], + "total-blocking-time": ["warn", { "maxNumericValue": 300 }], + "speed-index": ["warn", { "maxNumericValue": 3400 }], + "categories:performance": ["warn", { "minScore": 0.9 }], + "categories:accessibility": ["error", { "minScore": 0.9 }], + "categories:best-practices": ["warn", { "minScore": 0.9 }], + "categories:seo": ["warn", { "minScore": 0.9 }], + "uses-text-compression": "off", + "uses-responsive-images": "warn", + "offscreen-images": "warn", + "unused-javascript": "warn", + "unused-css-rules": "warn", + "render-blocking-resources": "warn" + } + }, + "upload": { + "target": "temporary-public-storage" + } + } +} diff --git a/src/client/index.html b/src/client/index.html index 8a7e7b3..f245218 100644 --- a/src/client/index.html +++ b/src/client/index.html @@ -107,10 +107,26 @@ } - + + + + + + - + + + + + + + + diff --git a/ui-screenshot.png b/ui-screenshot.png deleted file mode 100644 index b7653eb..0000000 Binary files a/ui-screenshot.png and /dev/null differ diff --git a/visual-test.png b/visual-test.png deleted file mode 100644 index e1c3476..0000000 Binary files a/visual-test.png and /dev/null differ diff --git a/vite.config.ts b/vite.config.ts index 845adc6..be28eaa 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -9,13 +9,21 @@ export default defineConfig({ build: { outDir: '../../dist', emptyOutDir: true, + // Target modern browsers for smaller bundles + target: 'es2022', + // Enable CSS code splitting + cssCodeSplit: true, + // Optimize chunk size + chunkSizeWarningLimit: 500, rollupOptions: { output: { manualChunks: { // Core React runtime 'react-vendor': ['react', 'react-dom'], // Routing - 'router': ['react-router-dom'], + router: ['react-router-dom'], + // Icons (large library, lazy load when needed) + icons: ['lucide-react'], // UI primitives (Radix UI) 'radix-ui': [ '@radix-ui/react-checkbox', @@ -28,7 +36,9 @@ export default defineConfig({ '@radix-ui/react-tooltip', ], // Internationalization - 'i18n': ['i18next', 'react-i18next'], + i18n: ['i18next', 'react-i18next'], + // Utilities + utils: ['clsx', 'tailwind-merge', 'class-variance-authority'], }, }, },