Compare commits

...

2 Commits

Author SHA1 Message Date
83190f1d00 fix: production stabilization (middleware routing + docker paths)
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 7s
Build & Deploy / 🏗️ Build (push) Successful in 12m46s
Build & Deploy / 🚀 Deploy (push) Successful in 20s
Build & Deploy / 🩺 Smoke Test (push) Failing after 3s
Build & Deploy / 🔔 Notify (push) Successful in 7s
Nightly QA / 🔍 Static Analysis (push) Successful in 2m36s
Nightly QA / 🔗 Links & Deps (push) Successful in 2m13s
Nightly QA / 🎭 Lighthouse (push) Successful in 3m47s
Nightly QA / 📝 E2E (push) Successful in 4m28s
Nightly QA / 🔔 Notify (push) Has been skipped
2026-04-12 23:28:05 +02:00
12848a4f23 fix: ensure rewrites are merged when config is a function (withPayload)
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 9s
Build & Deploy / 🏗️ Build (push) Successful in 14m52s
Build & Deploy / 🚀 Deploy (push) Successful in 31s
Build & Deploy / 🩺 Smoke Test (push) Failing after 3s
Build & Deploy / 🔔 Notify (push) Successful in 2s
2026-04-12 23:20:35 +02:00
3 changed files with 58 additions and 54 deletions

View File

@@ -75,7 +75,7 @@ WORKDIR /app
# Copy standalone output and static files (Monorepo paths)
# Note: Base image already handles the non-root user and basic env
COPY --from=builder --chown=1001:65533 /app/apps/web/public ./apps/web/public
COPY --from=builder --chown=1001:65533 /app/apps/web/public ./public
COPY --from=builder --chown=1001:65533 /app/apps/web/.next/standalone ./
COPY --from=builder --chown=1001:65533 /app/apps/web/.next/static ./apps/web/.next/static

View File

@@ -46,61 +46,12 @@ const nextConfig = {
},
];
},
// In Standalone mode, Next.js expects the tracing root to be the monorepo root
outputFileTracingRoot: path.join(dirname, '../../'),
};
const withMDX = createMDX({});
// Apply wrappers
const wrappedConfig = withPayload(withMintelConfig(withMDX(nextConfig)));
// HARDEN REWRITES: Manually merge showcase rules to prevent wrapper overwrites
const originalRewrites = wrappedConfig.rewrites;
wrappedConfig.rewrites = async () => {
const existing = await originalRewrites?.() || [];
// Normalize existing to object pattern (Next.js supports both Array and Object)
const normalized = Array.isArray(existing)
? { afterFiles: existing, beforeFiles: [], fallback: [] }
: existing;
return {
...normalized,
beforeFiles: [
...(normalized.beforeFiles || []),
// Diagnostic rule
{
source: '/robots-test',
destination: '/robots.txt',
},
// Assets requested from root
{
source: '/assets/:path*',
destination: '/showcase/klz-cables.com/assets/:path*',
},
{
source: '/wp-content/:path*',
destination: '/showcase/klz-cables.com/assets/klz-cables.com/wp-content/:path*',
},
{
source: '/wp-includes/:path*',
destination: '/showcase/klz-cables.com/assets/klz-cables.com/wp-includes/:path*',
},
// Assets requested relatively from case-studies/work/blog subpages
{
source: '/:folder(case-studies|work|blog)/assets/:path*',
destination: '/showcase/klz-cables.com/assets/:path*',
},
{
source: '/:folder(case-studies|work|blog)/wp-content/:path*',
destination: '/showcase/klz-cables.com/assets/klz-cables.com/wp-content/:path*',
},
{
source: '/:folder(case-studies|work|blog)/wp-includes/:path*',
destination: '/showcase/klz-cables.com/assets/klz-cables.com/wp-includes/:path*',
},
],
};
};
export default wrappedConfig;
// Clean, standard wrapper application
// Rewrites are now handled by src/middleware.ts for maximum robustness
export default withPayload(withMintelConfig(withMDX(nextConfig)));

View File

@@ -0,0 +1,53 @@
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
/**
* PRODUCTION STABILIZATION MIDDLEWARE
* This middleware handles legacy asset routing for the KLZ showcase,
* ensuring assets are correctly mapped regardless of Next.js config wrapper behavior.
*/
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
// 1. Diagnostic Rewrite
if (pathname === '/robots-test') {
return NextResponse.rewrite(new URL('/robots.txt', request.url));
}
// 2. Legacy Showcase Asset Mapping
// Matches: /wp-content/*, /wp-includes/*, /assets/*, and their relative subpaths
const showcaseAssetPattern = /^\/(?:wp-content|wp-includes|assets|(?:case-studies|work|blog)\/(?:wp-content|wp-includes|assets))\/(.*)/;
const match = pathname.match(showcaseAssetPattern);
if (match) {
const assetPath = match[0];
// Normalize path by stripping the case-studies/work/blog prefix if present
const normalizedPath = assetPath.replace(/^\/(?:case-studies|work|blog)/, '');
// Map to the literal directory in public/
// Destination: /showcase/klz-cables.com/...
return NextResponse.rewrite(new URL(`/showcase/klz-cables.com${normalizedPath}`, request.url));
}
return NextResponse.next();
}
// Optimization: Only run middleware for legacy asset paths to minimize overhead
export const config = {
matcher: [
'/robots-test',
'/wp-content/:path*',
'/wp-includes/:path*',
'/assets/:path*',
'/case-studies/wp-content/:path*',
'/case-studies/wp-includes/:path*',
'/case-studies/assets/:path*',
'/work/wp-content/:path*',
'/work/wp-includes/:path*',
'/work/assets/:path*',
'/blog/wp-content/:path*',
'/blog/wp-includes/:path*',
'/blog/assets/:path*',
],
};