Overview
frontend/next.config.ts is essentially empty — no security headers, no image domain allowlist, no bundle size analysis, and no Content Security Policy. This issue hardens the Next.js configuration and addresses performance bottlenecks.
Technical Details
1. Security Headers (frontend/next.config.ts)
Add HTTP security headers via Next.js config:
const securityHeaders = [
{ key: 'X-DNS-Prefetch-Control', value: 'on' },
{ key: 'Strict-Transport-Security', value: 'max-age=63072000; includeSubDomains; preload' },
{ key: 'X-Frame-Options', value: 'SAMEORIGIN' },
{ key: 'X-Content-Type-Options', value: 'nosniff' },
{ key: 'Referrer-Policy', value: 'origin-when-cross-origin' },
{
key: 'Content-Security-Policy',
value: [
"default-src 'self'",
"script-src 'self' 'unsafe-eval' 'unsafe-inline'", // Next.js requires unsafe-eval in dev
"style-src 'self' 'unsafe-inline'",
"img-src 'self' data: https://res.cloudinary.com",
"connect-src 'self' wss://localhost:* https://horizon-testnet.stellar.org",
].join('; ')
},
];
const nextConfig = {
async headers() {
return [{ source: '/(.*)', headers: securityHeaders }];
}
};
2. Image Domain Configuration
Add all external image domains to next.config.ts:
images: {
remotePatterns: [
{ protocol: 'https', hostname: 'res.cloudinary.com' },
{ protocol: 'https', hostname: '*.amazonaws.com' }, // if S3
],
}
3. Bundle Analysis
Install @next/bundle-analyzer:
npm install -D @next/bundle-analyzer
Configure in next.config.ts:
const withBundleAnalyzer = require('@next/bundle-analyzer')({ enabled: process.env.ANALYZE === 'true' });
module.exports = withBundleAnalyzer(nextConfig);
Add to package.json: "analyze": "ANALYZE=true next build"
Run the analyzer (npm run analyze) and identify the top 3 largest bundle chunks. For each:
- If it is a large library used on only one page, convert to dynamic import:
const Heavy = dynamic(() => import('./Heavy'), { ssr: false })
- Document findings in a comment in
next.config.ts
4. Remove the Sandbox Page
frontend/app/sandbox/page.tsx is a developer component showcase accessible in production. Either:
- Delete the file entirely if it is not needed in production, OR
- Wrap it with a check:
if (process.env.NODE_ENV !== 'development') { notFound(); }
Either approach is acceptable — leave a comment explaining the choice.
5. Environment Variable Type Safety
Create frontend/lib/env.ts that uses a simple validation (manual checks since Zod v4 is available):
const env = {
NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL!,
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!,
NEXT_PUBLIC_STRIPE_VAPID_PUBLIC_KEY: process.env.NEXT_PUBLIC_WEB_PUSH_PUBLIC_KEY,
};
// Validate in development
if (process.env.NODE_ENV === 'development') {
Object.entries(env).forEach(([key, value]) => {
if (!value) console.warn(`Missing env var: ${key}`);
});
}
export default env;
Replace all direct process.env.NEXT_PUBLIC_* references with env.* imports.
Acceptance Criteria
Overview
frontend/next.config.tsis essentially empty — no security headers, no image domain allowlist, no bundle size analysis, and no Content Security Policy. This issue hardens the Next.js configuration and addresses performance bottlenecks.Technical Details
1. Security Headers (
frontend/next.config.ts)Add HTTP security headers via Next.js config:
2. Image Domain Configuration
Add all external image domains to
next.config.ts:3. Bundle Analysis
Install
@next/bundle-analyzer:Configure in
next.config.ts:Add to
package.json:"analyze": "ANALYZE=true next build"Run the analyzer (
npm run analyze) and identify the top 3 largest bundle chunks. For each:const Heavy = dynamic(() => import('./Heavy'), { ssr: false })next.config.ts4. Remove the Sandbox Page
frontend/app/sandbox/page.tsxis a developer component showcase accessible in production. Either:if (process.env.NODE_ENV !== 'development') { notFound(); }Either approach is acceptable — leave a comment explaining the choice.
5. Environment Variable Type Safety
Create
frontend/lib/env.tsthat uses a simple validation (manual checks since Zod v4 is available):Replace all direct
process.env.NEXT_PUBLIC_*references withenv.*imports.Acceptance Criteria
curl -I https://localhost:3000/includesX-Frame-Options: SAMEORIGINandX-Content-Type-Options: nosniffheadersremotePatternsconfignpm run analyzeruns without errors and opens the bundle analyzerNODE_ENV === 'development'checkfrontend/lib/env.tsexists and is used throughout the codebaseprocess.env.NEXT_PUBLIC_*references remain outside oflib/env.ts