Template
PostHog loads after the page is idle through a same-origin /ingest proxy and follows the signed-in Convex user. Plausible uses the per-site script through a /pa proxy, clear of Payload's /api routes. Sentry keeps errors and traces only. Pages load only the @gib/ui modules they import, and client code reads public env from publicEnv.ts so zod stays out of the browser.
106 lines
4.0 KiB
JavaScript
106 lines
4.0 KiB
JavaScript
import { withPayload } from '@payloadcms/next/withPayload';
|
|
import { withSentryConfig } from '@sentry/nextjs';
|
|
import { createJiti } from 'jiti';
|
|
import { withPlausibleProxy } from 'next-plausible';
|
|
|
|
const jiti = createJiti(import.meta.url);
|
|
const { env } = /** @type {typeof import('./src/env')} */ (
|
|
await jiti.import('./src/env')
|
|
);
|
|
const { posthogScriptAliases } =
|
|
/** @type {typeof import('./src/lib/posthog-scripts')} */ (
|
|
await jiti.import('./src/lib/posthog-scripts')
|
|
);
|
|
|
|
/** @type {import("next").NextConfig} */
|
|
const baseConfig = {
|
|
output: 'standalone',
|
|
images: {
|
|
remotePatterns: [
|
|
{
|
|
protocol: 'https',
|
|
hostname: '*.gbrown.org',
|
|
},
|
|
],
|
|
},
|
|
serverExternalPackages: ['require-in-the-middle'],
|
|
experimental: {
|
|
serverActions: {
|
|
bodySizeLimit: '10mb',
|
|
},
|
|
// Resolves `import { Button } from '@gib/ui'` to the button module alone,
|
|
// so marketing pages never pull in admin-only Radix widgets or Recharts.
|
|
// radix-ui is the umbrella package the shadcn components import from.
|
|
// lucide-react, date-fns and @tabler/icons-react are on Next's default list.
|
|
optimizePackageImports: ['@gib/ui', 'radix-ui'],
|
|
},
|
|
/** Enables hot reloading for local packages without a build step */
|
|
transpilePackages: ['@gib/backend', '@gib/ui'],
|
|
typescript: { ignoreBuildErrors: true },
|
|
// PostHog's capture paths end in a slash (/e/, /i/v0/e/), and Next's
|
|
// built-in trailing-slash redirect would answer those proxied POSTs with a
|
|
// redirect. It is turned off here and replaced by the redirect below, which
|
|
// strips trailing slashes everywhere except /ingest.
|
|
skipTrailingSlashRedirect: true,
|
|
redirects: async () => [
|
|
{
|
|
source: '/:path((?!ingest(?:/|$)).+)/',
|
|
destination: '/:path',
|
|
permanent: true,
|
|
},
|
|
],
|
|
// Same-origin proxy for PostHog, so blocklists that match the PostHog host
|
|
// never see the request. The aliased extension scripts (blocked by file
|
|
// name, see src/lib/posthog-scripts.ts) map back to their real files first.
|
|
rewrites: async () => {
|
|
const host = env.NEXT_PUBLIC_POSTHOG_HOST;
|
|
if (!host) return [];
|
|
return [
|
|
...Object.entries(posthogScriptAliases).map(([name, alias]) => ({
|
|
source: `/ingest/static/${alias}.js`,
|
|
destination: `${host}/static/${name}.js`,
|
|
})),
|
|
{ source: '/ingest/:path*', destination: `${host}/:path*` },
|
|
];
|
|
},
|
|
};
|
|
|
|
// Serves Plausible's per-site script from this origin so ad blockers see a
|
|
// first-party request. next-plausible 4 takes the full script URL. Its default
|
|
// event path is /api/event, which sits inside Payload's /api routes, so both
|
|
// paths move under /pa.
|
|
const config = env.NEXT_PUBLIC_PLAUSIBLE_SRC
|
|
? withPlausibleProxy({
|
|
src: env.NEXT_PUBLIC_PLAUSIBLE_SRC,
|
|
scriptPath: '/pa/script.js',
|
|
apiPath: '/pa/event',
|
|
})(baseConfig)
|
|
: baseConfig;
|
|
|
|
const sentryConfig = {
|
|
// For all available options, see:
|
|
// https://www.npmjs.com/package/@sentry/webpack-plugin#options
|
|
org: process.env.NEXT_PUBLIC_SENTRY_ORG,
|
|
project: process.env.NEXT_PUBLIC_SENTRY_PROJECT_NAME,
|
|
sentryUrl: process.env.NEXT_PUBLIC_SENTRY_URL,
|
|
authToken: process.env.SENTRY_AUTH_TOKEN,
|
|
// Only print logs for uploading source maps in CI
|
|
silent: !process.env.CI,
|
|
// For all available options, see:
|
|
// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/
|
|
// Upload a larger set of source maps for prettier stack traces (increases build time)
|
|
widenClientFileUpload: true,
|
|
// Route browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers.
|
|
// This can increase your server load as well as your hosting bill.
|
|
// Note: Check that the configured route will not match with your Next.js middleware, otherwise reporting of client-
|
|
// side errors will fail.
|
|
tunnelRoute: '/monitoring',
|
|
// Automatically tree-shake Sentry logger statements to reduce bundle size
|
|
disableLogger: true,
|
|
// Capture React Component Names
|
|
reactComponentAnnotation: {
|
|
enabled: true,
|
|
},
|
|
};
|
|
export default withSentryConfig(withPayload(config), sentryConfig);
|