ultisuite-client/next.config.mjs
R3D347HR4Y d6d18f911b
Some checks failed
E2E / Playwright e2e (push) Has been cancelled
Lots of stuff and mobile app
2026-06-17 00:13:28 +02:00

131 lines
3.3 KiB
JavaScript

/*
* Copyright (c) 2026 Eliott Guillaumin
* All rights reserved.
*/
import path from "node:path"
import { fileURLToPath } from "node:url"
/** @type {import('next').NextConfig} */
const projectRoot = path.dirname(fileURLToPath(import.meta.url))
const ultiProxyOrigin = process.env.ULTI_PROXY_ORIGIN ?? "http://127.0.0.1"
/** Hostnames allowed to load /_next/* in dev (tunnel, LAN, public dev domain). */
function allowedDevOrigins() {
const hosts = new Set([
"127.0.0.1",
"localhost",
"192.168.0.20",
"100.120.4.66",
"dev.ultispace.fr",
"dev.ultimail.fr",
])
const appUrl = process.env.NEXT_PUBLIC_APP_URL?.trim()
if (appUrl) {
try {
hosts.add(new URL(appUrl).hostname)
} catch {
/* ignore invalid NEXT_PUBLIC_APP_URL */
}
}
return [...hosts]
}
/**
* Mobile (Tauri) build: a fully static export with no server runtime. The
* server-only API route handlers are named `route.web.ts` and are excluded
* here by NOT registering the `web.ts` page extension (see `pageExtensions`),
* so they only compile for the web/standalone build.
*/
const isMobile = process.env.NEXT_PUBLIC_MOBILE === "1"
const webPageExtensions = ["web.tsx", "web.ts", "tsx", "ts", "jsx", "js"]
const mobilePageExtensions = ["tsx", "ts", "jsx", "js"]
/** @type {import('next').NextConfig} */
const baseConfig = {
outputFileTracingRoot: projectRoot,
allowedDevOrigins: allowedDevOrigins(),
typescript: {
ignoreBuildErrors: true,
},
images: {
unoptimized: true,
},
turbopack: {
resolveAlias: {
canvas: "./lib/empty-module.mjs",
},
},
webpack: (config) => {
config.resolve.alias = {
...config.resolve.alias,
canvas: false,
}
return config
},
}
const webConfig = {
...baseConfig,
output: "standalone",
// Docker standalone tracing only — do not set turbopack.root to projectRoot:
// breaks Tailwind @import resolution (resolves from parent /Users/red/workdev).
pageExtensions: webPageExtensions,
async redirects() {
return [
{
source: "/mail/settings",
destination: "/settings",
permanent: true,
},
{
source: "/mail/settings/:section*",
destination: "/settings/:section*",
permanent: true,
},
{
source: "/compte",
destination: "/account",
permanent: true,
},
{
source: "/compte/:section*",
destination: "/account/:section*",
permanent: true,
},
]
},
async rewrites() {
return [
{
source: "/api/v1/:path*",
destination: `${ultiProxyOrigin}/api/v1/:path*`,
},
{
source: "/ai/:path*",
destination: `${ultiProxyOrigin}/ai/:path*`,
},
{
source: "/ai",
destination: `${ultiProxyOrigin}/ai`,
},
]
},
}
const mobileConfig = {
...baseConfig,
output: "export",
// Mobile shells navigate client-side; the static export serves the start
// route (e.g. /mail) and Next's router + native deep-links handle the rest.
trailingSlash: true,
pageExtensions: mobilePageExtensions,
// No rewrites/redirects: the bundle calls an absolute backend URL chosen at
// runtime by the server picker, and path redirects run client-side.
}
const nextConfig = isMobile ? mobileConfig : webConfig
export default nextConfig