Files
route-commerce/next.config.ts
T
openclaw c86e97e816
Deploy to route.crispygoat.com / deploy (push) Failing after 7s
feat(storage): MinIO object storage, Neon Auth, Supabase removal
- Add MinIO/S3-compatible storage client (src/lib/storage.ts) with uploadObject,
  deleteObject, presigned URL helpers, and BUCKETS constant
- Wire product images, brand logos, and water log photos to MinIO via the
  new storage client
- Migrate forgot-password to Neon Auth (remove Supabase /auth/v1/recover call)
- Migrate send-scheduled cron to direct Postgres + Resend (remove Supabase Edge
  Function proxy)
- Add logoUrl to email types (OrderReceipt, Welcome, PasswordReset) and pass
  brand_settings.logo_url from all call sites
- Update email templates to use dynamic logoUrl instead of hardcoded Supabase
  bucket URLs
- Remove hardcoded Supabase URLs from TuxedoVideoHero, TuxedoAboutPage,
  TimeTrackingFieldClient; use brand_settings props + local public/ fallback
- Download brand logos (3) and tuxedo-hero.mp4 (36MB) from Supabase bucket to
  public/ for local development
- Add MinIO env vars to .env.example (endpoint, access key, secret, buckets)
- Fix TimeTrackingFieldClient to destructure logoUrl and brandAccent props
- Fix admin/users.ts logoUrl type (null → undefined for optional string)
- Remove stale sb- cookie from wholesale-auth
- Migrate tuxedo/about page to remove supabase import and use pool query for
  wholesale_settings lookup
2026-06-09 12:21:57 -06:00

132 lines
3.2 KiB
TypeScript

import type { NextConfig } from "next";
const nextConfig: NextConfig = {
// Enable standalone output for Docker/PM2 deployment
output: "standalone",
// Lock the file-tracing root to the project directory. Without this,
// Next.js 16 walks up from package.json looking for a lockfile, finds
// the homelab runner's stale `act` cache at
// /home/tyler/.cache/act/.../package-lock.json, and warns:
// "We detected multiple lockfiles and selected the directory of
// /home/tyler/package-lock.json as the root directory."
// The deploy runner's APP_DIR is /home/tyler/route-commerce, so
// resolving relative to the project root is correct both locally and
// in CI.
outputFileTracingRoot: ".",
// Enable strict mode
reactStrictMode: true,
// Optimize images
images: {
remotePatterns: [
{
protocol: "https",
hostname: "*.supabase.co",
},
{
protocol: "https",
hostname: "images.unsplash.com",
},
{
protocol: "https",
hostname: "picsum.photos",
},
],
formats: ["image/avif", "image/webp"],
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
},
// Security headers
async headers() {
return [
{
source: "/:path*",
headers: [
{
key: "X-Content-Type-Options",
value: "nosniff",
},
{
key: "X-Frame-Options",
value: "DENY",
},
{
key: "X-XSS-Protection",
value: "1; mode=block",
},
{
key: "Referrer-Policy",
value: "strict-origin-when-cross-origin",
},
{
key: "Permissions-Policy",
value: "camera=(), microphone=(), geolocation=()",
},
],
},
{
// API routes - more restrictive
source: "/api/:path*",
headers: [
{
key: "Access-Control-Allow-Methods",
value: "GET, POST, PUT, DELETE, OPTIONS",
},
{
key: "Access-Control-Allow-Headers",
value: "Content-Type, Authorization, X-API-Key",
},
{
key: "Access-Control-Max-Age",
value: "86400",
},
],
},
];
},
// Redirects
async redirects() {
return [
// Redirect old paths if needed
// {
// source: '/old-path',
// destination: '/new-path',
// permanent: true,
// },
];
},
// Rewrites for API proxy
async rewrites() {
return [
// Add any necessary rewrites here
];
},
// Experimental features
experimental: {
// Enable optimizePackageImports for better bundle size
optimizePackageImports: ["lucide-react", "@radix-ui/react-icons", "framer-motion"],
},
// Compiler options
compiler: {
// Remove console.log in production
removeConsole: process.env.NODE_ENV === "production"
? { exclude: ["error", "warn"] }
: false,
},
// Logging
logging: {
fetches: {
fullUrl: process.env.NODE_ENV === "development",
},
},
};
export default nextConfig;