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. Sentry keeps errors and traces only. Pages load only the @spoon/ui modules they import, and client code reads public env from publicEnv.ts so zod stays out of the browser. Both analytics integrations stay off until their env is set in Infisical prod.
105 lines
4.0 KiB
JavaScript
105 lines
4.0 KiB
JavaScript
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 '@spoon/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: ['@spoon/ui', 'radix-ui'],
|
|
},
|
|
/** Enables hot reloading for local packages without a build step */
|
|
transpilePackages: ['@spoon/backend', '@spoon/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(config, sentryConfig);
|