- Initialize Git repository with main branch - Create comprehensive .gitignore for Node.js, React, and environment files - Set up directory structure (frontend/, backend/, docs/) - Create detailed README.md with project overview and setup instructions - Add .env.example with all required environment variables - Configure Prettier for consistent code formatting All acceptance criteria met: ✅ Git repository initialized with appropriate .gitignore ✅ Directory structure matches Technical Assumptions ✅ README.md created with project overview and setup docs ✅ .env.example file with all required environment variables ✅ Prettier config files added for code formatting consistency 🤖 Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2.1 KiB
2.1 KiB
Monitoring and Observability
Monitoring Stack
- Frontend Monitoring: Browser console errors (dev), future: Sentry for production error tracking
- Backend Monitoring: Winston structured logging, health check endpoint for uptime
- Error Tracking: Console logs (dev), future: Sentry or LogRocket
- Performance Monitoring: Lighthouse audits (manual), future: Web Vitals reporting
Key Metrics
Frontend Metrics:
- Core Web Vitals:
- LCP (Largest Contentful Paint): <2.5s
- FID (First Input Delay): <100ms
- CLS (Cumulative Layout Shift): <0.1
- JavaScript errors: Track with Error Boundaries
- API response times: Log slow requests (>1s)
- User interactions: Button clicks, form submissions
Backend Metrics:
- Request rate: Requests per second
- Error rate: 4xx/5xx responses per minute
- Response time: P50, P95, P99 latency
- Database query performance: Slow queries (>100ms)
- Open Library API: Success rate, response times
Health Check Endpoint:
// GET /api/health
app.get('/api/health', async (req, res) => {
try {
// Check database connection
await prisma.$queryRaw`SELECT 1`;
res.json({
status: 'ok',
timestamp: new Date().toISOString(),
uptime: process.uptime(),
database: 'connected',
});
} catch (error) {
res.status(503).json({
status: 'error',
timestamp: new Date().toISOString(),
database: 'disconnected',
});
}
});
Logging (Winston):
// utils/logger.js
const winston = require('winston');
const logger = winston.createLogger({
level: process.env.LOG_LEVEL || 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
transports: [
new winston.transports.Console({
format: winston.format.simple(),
}),
// Add file transport for production
// new winston.transports.File({ filename: 'error.log', level: 'error' }),
],
});
module.exports = logger;
// Usage:
logger.info('Book created', { bookId: 123, title: 'Test Book' });
logger.error('API error', { error: err.message, stack: err.stack });