Ctrl K
ComunidadGuías…

dashboard/next.config.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import type { NextConfig } from 'next';
import { HTML_LIMITED_BOT_UA_RE } from 'next/dist/shared/lib/router/utils/html-bots';
import * as fs from 'fs';
import * as path from 'path';
import dotenv from 'dotenv';
import createNextIntlPlugin from 'next-intl/plugin';
import { SUPPORTED_LANGUAGES } from './src/constants/i18n';

// Load environment variables from the root directory
const rootDir = path.resolve(process.cwd(), '..');
const envPath = path.join(rootDir, '.env');
const result = dotenv.config({ path: envPath });

if (result.error) {
  console.warn('Could not load .env file from root:', result.error.message);
}

const BLOG_POST_SLUGS = fs
  .readdirSync(path.join(process.cwd(), 'src/content/blog/posts'))
  .filter((file) => file.endsWith('.mdx'))
  .map((file) => file.slice(0, -'.mdx'.length));

const nextConfig: NextConfig = {
  output: 'standalone',
  // Next's list omits Googlebot and AI crawlers; Google ignores canonical and hreflang streamed into <body>
  htmlLimitedBots: new RegExp(
    `${HTML_LIMITED_BOT_UA_RE.source}|Googlebot|GPTBot|OAI-SearchBot|PerplexityBot|ClaudeBot`,
    'i',
  ),
  experimental: {
    // app and landing have separate root layouts, so unmatched URLs need a global 404
    globalNotFound: true,
    webpackMemoryOptimizations: true,
    serverSourceMaps: true,
  },
  // the daily re-render reads posts from disk, which the standalone trace can't follow on its own
  outputFileTracingIncludes: {
    '/blog/**': ['./src/content/blog/posts/**/*'],
  },
  async redirects() {
    return [
      { source: '/login', destination: '/signin', permanent: true },
      { source: '/register', destination: '/signup', permanent: true },
      { source: '/:locale/login', destination: '/:locale/signin', permanent: true },
      { source: '/:locale/register', destination: '/:locale/signup', permanent: true },
      {
        source: `/:locale(${SUPPORTED_LANGUAGES.join('|')})/blog/:path*`,
        destination: '/blog/:path*',
        permanent: true,
      },
    ];
  },
  async rewrites() {
    return {
      beforeFiles: [],
      // Dotted segments the middleware skips (/wp-login.php) would each cache a 404 as a landing locale
      afterFiles: [
        {
          source: `/:segment((?!(?:${SUPPORTED_LANGUAGES.join('|')})$)[^/]+)`,
          destination: `/${process.env.NEXT_PUBLIC_DEFAULT_LANGUAGE ?? 'en'}/:segment`,
        },
        // Likewise every unknown blog URL would cache its own 404, so they share one prerendered page
        {
          source: `/blog/:path((?!(?:${BLOG_POST_SLUGS.join('|')})$).+)`,
          destination: '/blog/not_found',
        },
      ],
      fallback: [],
    };
  },
  async headers() {
    return [
      {
        source: '/dashboard/:path*',
        headers: [{ key: 'X-Accel-Buffering', value: 'no' }],
      },
      {
        source: '/:dir(browser-icons|os-icons)/:file*',
        headers: [{ key: 'Cache-Control', value: 'public, max-age=86400, stale-while-revalidate=604800' }],
      },
    ];
  },
  productionBrowserSourceMaps: false,
};

export default createNextIntlPlugin()(nextConfig);