Deploying the QCD AI Agent
The project is a standard Next.js 15 App Router app. It runs on any Node.js 20+ host. The recommended approach for QCD is a Hetzner VPS with Docker, or a direct PM2 deployment.
1. Push to a repo
Create a private repo on GitHub and push the project.
2. Environment variables
Set these as environment variables on your server (via .env file, Docker env, or systemd environment):
| Variable | Example | Notes | | --- | --- | --- | | NEXT_PUBLIC_SITE_URL | https://agent.qcdauto.co.uk | Used by email links and the widget loader. | | NEXT_PUBLIC_WIDGET_ID | qcd-default | Identifies the widget configuration. | | WIDGET_ALLOWED_ORIGINS | qcdauto.co.uk,www.qcdauto.co.uk | CSV. localhost and 127.0.0.1 are in the default. | | NEXT_PUBLIC_SUPABASE_URL | from Supabase | | | NEXT_PUBLIC_SUPABASE_ANON_KEY | from Supabase | | | SUPABASE_SERVICE_ROLE_KEY | from Supabase | Server-side only. | | AI_PROVIDER | deepseek | Or openai, anthropic, google, openrouter, mock. | | AI_MODEL | deepseek-chat | Provider-appropriate model id. | | DEEPSEEK_API_KEY | from DeepSeek | Or the matching key for your chosen provider. | | EMAIL_PROVIDER | smtp | Or resend, mock. | | EMAIL_FROM | QCD Autocentre <info@qcdauto.co.uk> | | | EMAIL_TEAM_INBOX | info@qcdauto.co.uk | | | SMTP_HOST | smtp.ionos.co.uk | IONOS SMTP settings. | | SMTP_PORT | 587 | | | SMTP_USER | info@qcdauto.co.uk | | | SMTP_PASS | (password) | |
3. Deploy with Docker (recommended for Hetzner)
# Clone the repo
git clone <repo-url> qcd-ai-agent
cd qcd-ai-agent
# Create .env file with your variables
cp .env.example .env
# Edit .env with your real values
# Build and run
docker compose up -d --build
The app is served on port 3000. Point an Nginx reverse proxy at it with SSL (Let's Encrypt).
Nginx configuration
server {
listen 80;
server_name agent.qcdauto.co.uk;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name agent.qcdauto.co.uk;
ssl_certificate /etc/letsencrypt/live/agent.qcdauto.co.uk/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/agent.qcdauto.co.uk/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 120s;
}
}
Alternative: PM2 (without Docker)
npm ci --production=false
npm run build
npm ci --production
pm2 start node_modules/.bin/next --name qcd-ai-agent -- start -p 3000
pm2 save
pm2 startup
4. Verify
Visit:
https://your-domain/- public landing page.https://your-domain/admin- admin dashboard (mock-only data until Supabase is wired).https://your-domain/api/health- returns{ ok: true }.https://your-domain/embed/qcd-agent.js- widget loader script.
5. Domain allowlist
Update WIDGET_ALLOWED_ORIGINS whenever you embed the widget on a new domain. The /api/chat route returns 403 Origin not allowed otherwise. The same allowlist guards /api/bookings, /api/vehicle/lookup, /api/pricing/quote and /api/integrations/test.
6. DVSA and Motasoft env vars
The DVSA lookup, pricing engine and Motasoft handoff layer add optional environment variables:
DVSA_MOT_API_KEY=
DVSA_MOT_API_BASE_URL=https://history.mot.api.gov.uk/v1/trade/vehicles/registration
DVSA_MOT_API_MODE=disabled
GARAGE_SYSTEM=motasoft
GARAGE_INTEGRATION_MODE=manual_email
GARAGE_HANDOFF_EMAIL=info@qcdauto.co.uk
GARAGE_WEBHOOK_URL=
MOTASOFT_API_BASE_URL=
MOTASOFT_API_KEY=
See docs/garage-operations.md for what each one does.