mirror of
https://github.com/multica-ai/multica.git
synced 2026-06-17 11:48:42 +02:00
* feat(docs): mount docs site at /docs subpath via basePath + multi-zone Configure the Fumadocs site so it can be served at multica.ai/docs: - Add basePath: '/docs' to apps/docs/next.config.mjs - Flatten routes: drop standalone home, render content/docs/index.mdx at the root, move catch-all from app/docs/[[...slug]] to app/[...slug] - Wrap children with DocsLayout in the root layout (was a separate segment-level layout under app/docs/) - Set source loader baseUrl to '/' so URL slugs no longer carry the basePath (Next.js prepends it automatically) - Strip the now-redundant '/docs/' prefix from internal MDX links and drop the duplicate "Documentation" nav entry - Add app/not-found.tsx for App Router 404 handling Wire up multi-zone routing so apps/web proxies /docs/* to the docs app: - Add DOCS_URL env (default http://localhost:4000) and rewrites for /docs and /docs/:path* in apps/web/next.config.ts - Whitelist DOCS_URL in turbo.json globalEnv * fix(web): move /docs rewrite to beforeFiles so [workspaceSlug] doesn't shadow it The /docs rewrite was running in the default afterFiles slot, which is evaluated *after* file-system routing. apps/web/app/[workspaceSlug]/ matched /docs first as a workspace named "docs" (which doesn't exist) and returned 404 before the rewrite to the docs Vercel project ever fired. Splitting rewrites into beforeFiles/afterFiles puts /docs and /docs/:path* ahead of route resolution so they always proxy to the docs zone.
73 lines
2.0 KiB
TypeScript
73 lines
2.0 KiB
TypeScript
import type { NextConfig } from "next";
|
|
import { config } from "dotenv";
|
|
import { resolve } from "path";
|
|
|
|
// Load root .env so REMOTE_API_URL is available to next.config.ts
|
|
config({ path: resolve(__dirname, "../../.env") });
|
|
|
|
const remoteApiUrl = process.env.REMOTE_API_URL || "http://localhost:8080";
|
|
const docsUrl = process.env.DOCS_URL || "http://localhost:4000";
|
|
|
|
// Parse hostnames from CORS_ALLOWED_ORIGINS so that Next.js dev server
|
|
// allows cross-origin HMR / webpack requests (e.g. from Tailscale IPs).
|
|
const allowedDevOrigins = process.env.CORS_ALLOWED_ORIGINS
|
|
? process.env.CORS_ALLOWED_ORIGINS.split(",")
|
|
.map((origin) => {
|
|
try {
|
|
return new URL(origin.trim()).host;
|
|
} catch {
|
|
return origin.trim();
|
|
}
|
|
})
|
|
.filter(Boolean)
|
|
: undefined;
|
|
|
|
const nextConfig: NextConfig = {
|
|
...(process.env.STANDALONE === "true" ? { output: "standalone" as const } : {}),
|
|
transpilePackages: ["@multica/core", "@multica/ui", "@multica/views"],
|
|
...(allowedDevOrigins && allowedDevOrigins.length > 0
|
|
? { allowedDevOrigins }
|
|
: {}),
|
|
images: {
|
|
formats: ["image/avif", "image/webp"],
|
|
qualities: [75, 80, 85],
|
|
},
|
|
async rewrites() {
|
|
return {
|
|
// Run before file-system routes so /docs isn't shadowed by the
|
|
// [workspaceSlug] dynamic segment.
|
|
beforeFiles: [
|
|
{
|
|
source: "/docs",
|
|
destination: `${docsUrl}/docs`,
|
|
},
|
|
{
|
|
source: "/docs/:path*",
|
|
destination: `${docsUrl}/docs/:path*`,
|
|
},
|
|
],
|
|
afterFiles: [
|
|
{
|
|
source: "/api/:path*",
|
|
destination: `${remoteApiUrl}/api/:path*`,
|
|
},
|
|
{
|
|
source: "/ws",
|
|
destination: `${remoteApiUrl}/ws`,
|
|
},
|
|
{
|
|
source: "/auth/:path*",
|
|
destination: `${remoteApiUrl}/auth/:path*`,
|
|
},
|
|
{
|
|
source: "/uploads/:path*",
|
|
destination: `${remoteApiUrl}/uploads/:path*`,
|
|
},
|
|
],
|
|
fallback: [],
|
|
};
|
|
},
|
|
};
|
|
|
|
export default nextConfig;
|