compose.prod.yml only whitelisted DB/redis/storage/auth/VAPID/Google/
OpenRouter vars in web.environment — Portainer stack env alone doesn't
reach the container unless the compose file declares the ${VAR} ref, so
SMTP_HOST etc were set in Portainer but silently ignored. Add the full
set from .env.example (SMTP, GitHub/Discord/Authentik OAuth + their
NEXT_PUBLIC_*_ENABLED flags, Stripe, remaining AI provider keys).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
login page referenced auth.continueWithGithub/Discord/Authentik keys that
didn't exist in en/fr message files, crashing the login page. Also remap
docker/compose.yml redis to 6380 since 6379 collides with an unrelated
local container on this machine.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Add a migrator Dockerfile target (drizzle-kit migrate + tier-definitions
seed, both idempotent) and wire it as a one-shot compose service that web
waits on via service_completed_successfully. No more manual exec step
after first deploy — runs safely on every redeploy.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Add root Dockerfile (standalone Next output, multi-stage pnpm build), drop
in-stack caddy in favor of publishing web's port for an external traefik
LXC (file-provider dynamic config included), and document the portainer
deploy flow.
Also fixes issues that blocked any production build: a bad auth-client
type cast, the ai SDK's mimeType->mediaType rename, an implicit-any
callback param, and push.ts eagerly calling webpush.setVapidDetails at
module import time (which crashed page-data collection whenever VAPID
env vars weren't present at build) — now lazily configured on first send.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>