Aimpress_site/server/nginx.conf
Vadym Samoilenko 6c1956585a Add SEO, structured data, AI indexing, and Google Reviews integration
- Add react-helmet-async with SEO component for dynamic meta tags on all pages
- Add JSON-LD structured data (Organization, WebSite, ProfessionalService) to index.html
- Add fallback OG/Twitter Card meta tags in index.html for non-JS crawlers
- Add robots.txt allowing all crawlers including AI bots (GPTBot, Claude-Web, etc.)
- Add sitemap.xml with all routes
- Add llms.txt for AI crawler discovery
- Add X-Robots-Tag header and reviews.json cache rule to nginx.conf
- Replace fake testimonials with Google Reviews (fetch /reviews.json)
- Add star ratings, Google badge, and "Leave us a review" button to testimonials
- Add server/sync-reviews.mjs for daily Google Places API review sync

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 14:26:05 +00:00

58 lines
2.4 KiB
Nginx Configuration File

server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
# Enable gzip compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json;
# Cache static assets (Vite hashed filenames)
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Blog JSON/images - short cache for frequent updates
location /blog/ {
expires 10m;
add_header Cache-Control "public, must-revalidate";
}
# API proxy to email service (resolver allows nginx to start even if email-api is down)
location /api/ {
resolver 127.0.0.11 valid=30s;
set $email_api http://aimpress-email-api:3001;
proxy_pass $email_api;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Content-Type $http_content_type;
}
# SEO headers
add_header X-Robots-Tag "index, follow" always;
# Reviews JSON - short cache
location = /reviews.json {
expires 1h;
add_header Cache-Control "public, must-revalidate";
}
# Security headers
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://www.googletagmanager.com https://cdn.mxpnl.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https://lh3.googleusercontent.com https://www.googletagmanager.com; connect-src 'self' https://www.google-analytics.com https://analytics.google.com https://*.google-analytics.com https://*.analytics.google.com https://api-js.mixpanel.com https://api.mixpanel.com https://*.mixpanel.com https://*.mxpnl.com https://*.amplitude.com; frame-src https://www.youtube.com; media-src 'self'; worker-src 'self' blob:;" always;
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
# SPA fallback
location / {
try_files $uri $uri/ /index.html;
}
error_page 404 /index.html;
}