- FastAPI backend: PostGIS estimator + 3 scrapers (Avito/Cian/Yandex)
- Next.js 15 frontend: tradein.html mockup design, basePath=/trade-in
- WeasyPrint PDF (Брусника-style 4-page report)
- Address autocomplete с typo-tolerance + 6 EKB presets
- Изолированный docker stack gendesign-tradein (отдельная postgres БД)
- Caddy inline routes: gendsgn.ru/trade-in/* и /trade-in/api/v1/*
- Forgejo Actions: .forgejo/workflows/deploy-tradein.yml (shell-based GHCR login)
- Триггер только по paths: tradein-mvp/** (не пересекается с deploy.yml)
- Образы: ghcr.io/lekss361/gendesign-tradein-{backend,frontend}:latest
Первый запуск на сервере (вручную, один раз):
- создать /opt/gendesign/tradein-mvp/.env.runtime (postgres pwd, contact email)
- docker network create gendesign_shared (если нет)
- docker compose -p gendesign-tradein up -d
- docker compose -p gendesign exec caddy caddy reload
37 lines
1.5 KiB
TypeScript
37 lines
1.5 KiB
TypeScript
import type { NextConfig } from "next";
|
||
|
||
// basePath: пусто в dev / `/trade-in` в production когда сидим под gendsgn.ru/trade-in.
|
||
// Прокидывается через env при сборке Docker.
|
||
const BASE_PATH = process.env.NEXT_PUBLIC_BASE_PATH ?? "";
|
||
|
||
const nextConfig: NextConfig = {
|
||
reactStrictMode: true,
|
||
output: "standalone",
|
||
|
||
// basePath сдвигает ВСЕ routes на /trade-in/* — Next сам префиксит ассеты
|
||
// и navigation. Пустая строка = no-op.
|
||
basePath: BASE_PATH || undefined,
|
||
|
||
// assetPrefix — для CDN (мы не используем, оставляем пустым)
|
||
// trailingSlash — false (default), важно чтобы Caddy /trade-in без слэша
|
||
// редиректил на /trade-in/.
|
||
|
||
// В dev (без Caddy) Next.js сам проксирует /api/* и /health на backend
|
||
// так что браузер использует относительные same-origin URLs.
|
||
async rewrites() {
|
||
const backend = process.env.BACKEND_URL ?? "http://localhost:8000";
|
||
return [
|
||
{ source: "/api/:path*", destination: `${backend}/api/:path*` },
|
||
{ source: "/health", destination: `${backend}/health` },
|
||
];
|
||
},
|
||
|
||
async redirects() {
|
||
// basePath применяется автоматически к source — НЕ дублируем.
|
||
return [
|
||
{ source: "/", destination: "/trade-in", permanent: false },
|
||
];
|
||
},
|
||
};
|
||
|
||
export default nextConfig;
|