diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 970f5ec..483ef78 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -89,3 +89,31 @@ jobs: run: npm run build env: NEXT_TELEMETRY_DISABLED: 1 + + lighthouse: + name: Lighthouse + runs-on: ubuntu-latest + needs: [build] + steps: + - uses: actions/checkout@v4 + + - name: Use Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Build + run: npm run build + env: + NEXT_TELEMETRY_DISABLED: 1 + + - name: Run Lighthouse CI + uses: treosh/lighthouse-ci-action@v12 + with: + configPath: './lighthouserc.json' + uploadArtifacts: true + temporaryPublicStorage: true diff --git a/CLAUDE.md b/CLAUDE.md index 8d8663c..2f90b32 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,6 +6,8 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co Etags is a Next.js 16 application for product tagging and blockchain stamping. It manages brands, products, and tags with blockchain transaction tracking for authentication/verification purposes. +**Node.js requirement:** 20.x (LTS) + ## Commands - `npm run dev` - Start development server @@ -221,7 +223,14 @@ Solidity contracts are in `smartcontracts/` directory with separate Hardhat setu - `ETagRegistry.sol` - Main contract for tag lifecycle management (create, validate, update status, revoke) - `ETagCollectible.sol` - ERC721 NFT contract for collectibles (one NFT per tag) -See `smartcontracts/README.md` for contract development and testing. +Contract commands (run from `smartcontracts/` directory): + +- `npm run compile` - Compile contracts +- `npm run test` - Run contract tests +- `npm run deploy:local` - Deploy to local Hardhat node +- `npm run deploy:sepolia` - Deploy to Base Sepolia testnet + +See `smartcontracts/README.md` for full contract development documentation. ## Environment Variables diff --git a/lighthouserc.json b/lighthouserc.json new file mode 100644 index 0000000..c3208f8 --- /dev/null +++ b/lighthouserc.json @@ -0,0 +1,30 @@ +{ + "ci": { + "collect": { + "startServerCommand": "npm run start", + "startServerReadyPattern": "Ready", + "url": ["http://localhost:3000/"], + "numberOfRuns": 3, + "settings": { + "preset": "desktop", + "onlyCategories": [ + "performance", + "accessibility", + "best-practices", + "seo" + ] + } + }, + "assert": { + "assertions": { + "categories:performance": ["warn", { "minScore": 0.7 }], + "categories:accessibility": ["error", { "minScore": 0.9 }], + "categories:best-practices": ["warn", { "minScore": 0.8 }], + "categories:seo": ["warn", { "minScore": 0.8 }] + } + }, + "upload": { + "target": "temporary-public-storage" + } + } +} diff --git a/src/app/globals.css b/src/app/globals.css index 79da25f..7240d69 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -121,3 +121,24 @@ @apply bg-background text-foreground; } } + +/* Reduced motion support for older devices and accessibility */ +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + scroll-behavior: auto !important; + } +} + +/* GPU acceleration hints for smoother animations */ +.blur-xl, +.blur-2xl, +.blur-3xl, +.blur-\[80px\] { + will-change: auto; + transform: translateZ(0); +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index e373a4b..4ad0123 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -65,7 +65,6 @@ export const viewport = { themeColor: '#0c0a09', width: 'device-width', initialScale: 1, - maximumScale: 1, }; import { SessionProvider } from '@/components/providers/session-provider'; diff --git a/src/app/page.tsx b/src/app/page.tsx index be24b12..a6b7207 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,6 +1,3 @@ -'use client'; - -import { motion } from 'framer-motion'; import { Navbar } from '@/components/landing/Navbar'; import { Hero } from '@/components/landing/Hero'; import { Features } from '@/components/landing/Features'; @@ -9,37 +6,13 @@ import { FAQ } from '@/components/landing/FAQ'; import { CTA } from '@/components/landing/CTA'; import { Footer } from '@/components/landing/Footer'; -const MotionDiv = motion.div; - export default function Home() { return (
{item.a}
+{item.a}
+
Dapatkan visibilitas di mana produk Anda dipindai. Deteksi aktivitas mencurigakan secara real-time.
+
Scanner berbasis web kami bekerja langsung di browser, memastikan tingkat adopsi yang tinggi tanpa hambatan.
+
Setiap tag produk dicetak sebagai aset digital di blockchain, menciptakan catatan provenance yang tidak dapat dipalsukan.