A web-based tool for analyzing website performance metrics, including Core Web Vitals, resource loading timelines, and actionable performance suggestions.
- Core Web Vitals Analysis: Measure LCP, FID, and CLS with color-coded ratings
- Detailed Performance Metrics: TTFB, DOM Content Loaded, Full Page Load, and more
- Resource Waterfall Visualization: View resource loading timeline in chart or table format
- Performance Suggestions: Get actionable recommendations based on your site's metrics
- Easy to Use: Simply enter a URL and get comprehensive analysis in seconds
- Frontend: React 18 + Vite
- Backend: Node.js + Express
- Analysis Engine: Puppeteer (headless Chrome)
- Deployment: Docker + Docker Compose
Choose one based on your preferred setup method:
- Node.js 18 or higher
- npm or yarn
- Docker
- Docker Compose
The easiest way to run the application is using Docker Compose:
# Clone or navigate to the project directory
cd siteperformance
# Start the application
docker-compose up -d
# The application will be available at http://localhostTo stop the application:
docker-compose down# Navigate to backend directory
cd backend
# Install dependencies
npm install
# Create environment file
cp .env.example .env
# Start development server
npm run devThe backend will run on http://localhost:3001
In a separate terminal:
# Navigate to frontend directory
cd frontend
# Install dependencies
npm install
# Start development serve
npm run devThe frontend will run on http://localhost:5173
- Open the application in your browser (http://localhost or http://localhost:5173 for dev)
- Enter the URL you want to analyze (must start with http:// or https://)
- Click "Analyze Performance"
- Wait 10-30 seconds for the analysis to complete
- Review the results:
- Core Web Vitals with color-coded ratings
- Navigation timing metrics
- Resource summary and breakdown
- Resource waterfall (chart or table view)
- Performance suggestions
PORT=3001
FRONTEND_URL=http://localhost:5173
NODE_ENV=development
For production builds, you can set:
VITE_API_URL=https://your-backend-url.com
In development, the Vite proxy handles API routing automatically.
- Create a new project on Railway
- Add two services:
- Backend Service:
- Root directory:
/backend - Build command: (Docker will be detected automatically)
- Environment variables:
PORT=3001,FRONTEND_URL=https://your-frontend-url.com
- Root directory:
- Frontend Service:
- Root directory:
/frontend - Build command: (Docker will be detected automatically)
- Root directory:
- Backend Service:
- Deploy both services
- Create a new Web Service for backend:
- Build command:
cd backend && npm install - Start command:
cd backend && npm start - Or use Docker (select Dockerfile:
backend/Dockerfile)
- Build command:
- Create a Static Site for frontend:
- Build command:
cd frontend && npm install && npm run build - Publish directory:
frontend/dist - Or use Docker
- Build command:
- Set environment variables appropriately
# Install flyctl
curl -L https://fly.io/install.sh | sh
# Deploy backend
cd backend
fly launch
fly deploy
# Deploy frontend
cd ../frontend
fly launch
fly deploy- Backend requires ~1GB RAM for Puppeteer/Chromium
- Set appropriate CORS origins in backend environment
- Frontend should proxy
/apirequests to backend URL - Consider adding rate limiting for production use
siteperformance/
├── backend/
│ ├── src/
│ │ ├── index.js # Express server entry point
│ │ ├── routes/
│ │ │ └── analyze.js # API endpoint
│ │ ├── services/
│ │ │ ├── analyzer.js # Puppeteer analysis
│ │ │ └── suggestions.js # Performance suggestions
│ │ └── utils/
│ │ ├── validators.js # URL validation
│ │ └── metrics.js # Metric calculations
│ ├── package.json
│ ├── Dockerfile
│ └── .env.example
├── frontend/
│ ├── src/
│ │ ├── App.jsx # Main app with routing
│ │ ├── main.jsx # React entry point
│ │ ├── pages/
│ │ │ ├── Home.jsx # URL input page
│ │ │ └── Results.jsx # Results display
│ │ ├── components/
│ │ │ ├── MetricCard.jsx
│ │ │ ├── MetricsGrid.jsx
│ │ │ ├── Waterfall.jsx
│ │ │ ├── WaterfallTable.jsx
│ │ │ ├── Suggestions.jsx
│ │ │ ├── LoadingSpinner.jsx
│ │ │ └── ErrorMessage.jsx
│ │ ├── services/
│ │ │ └── api.js # Backend API calls
│ │ ├── hooks/
│ │ │ └── useAnalysis.js # Analysis state hook
│ │ └── styles/
│ │ └── index.css # Global styles
│ ├── index.html
│ ├── package.json
│ ├── vite.config.js
│ ├── Dockerfile
│ └── nginx.conf
├── docker-compose.yml
└── README.md
Analyze performance of a given URL.
Request Body:
{
"url": "https://example.com"
}Response (200 OK):
{
"url": "https://example.com",
"timestamp": "2025-12-04T10:30:00.000Z",
"metrics": {
"coreWebVitals": {
"lcp": { "value": 2400, "rating": "good" },
"fid": { "value": null, "rating": "unknown" },
"cls": { "value": 0.12, "rating": "needs-improvement" }
},
"navigationTiming": {
"ttfb": 320,
"domContentLoaded": 1800,
"loadComplete": 3200,
"domInteractive": 1600
},
"additionalMetrics": {
"fcp": 1200,
"tti": 3400,
"tbt": 450,
"speedIndex": 2100
},
"resourceSummary": {
"totalRequests": 47,
"totalSize": 2457600,
"byType": {
"script": { "count": 12, "size": 892000 },
"stylesheet": { "count": 5, "size": 145000 },
"image": { "count": 18, "size": 1200000 },
"font": { "count": 4, "size": 180000 },
"other": { "count": 8, "size": 40600 }
}
}
},
"resources": [ /* array of resource objects */ ],
"suggestions": [ /* array of suggestion objects */ ]
}Error Response (400/500):
{
"error": "Error message"
}- Verify the target URL is publicly accessible
- Some sites with bot protection (Cloudflare, etc.) may block automated browsers
- Increase timeout if analyzing very large/slow sites
- Check
FRONTEND_URLenvironment variable in backend matches your frontend URL - In development, ensure Vite proxy is configured correctly
- Puppeteer/Chromium requires ~1GB RAM
- Increase Docker memory limit:
docker-compose.ymlalready sets 1GB limit for backend - On Docker Desktop, ensure you've allocated sufficient resources
- Verify the URL is correct and publicly accessible
- Check your internet connection
- Some sites may block automated access
- Ensure Node.js 18+ is installed
- Clear node_modules and reinstall:
rm -rf node_modules && npm install - For Docker builds, ensure Docker has sufficient disk space
- FID cannot be accurately measured without real user interaction - value will be null
- CLS may be incomplete for content loaded beyond initial viewport
- Desktop-only analysis - viewport fixed at 1920x1080 (mobile analysis not included)
- No authentication support - cannot analyze pages behind login walls
- No historical data - each analysis is fresh, results are not cached
- Resource intensive - each analysis launches a full Chrome browser instance
- Rate limiting not included - consider adding rate limiting for production
- Bot protection - sites with Cloudflare or similar may block analysis
- Analysis typically takes 10-30 seconds depending on target site
- Backend requires approximately 1GB RAM for Puppeteer
- Results are not cached - each request performs fresh analysis
- Concurrent analyses will spawn separate browser instances
- Mobile viewport analysis with network throttling
- Historical data tracking and comparison
- Scheduled monitoring with email alerts
- PDF report generation
- Lighthouse integration for additional insights
- Multi-region analysis
- API key access for programmatic use
- User authentication and saved history
MIT
For issues and feature requests, please open an issue in the repository.