-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathnext.config.mjs
More file actions
147 lines (143 loc) · 6.34 KB
/
next.config.mjs
File metadata and controls
147 lines (143 loc) · 6.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import { createRequire } from 'module';
import { fileURLToPath } from 'url'
import path from 'path'
const require = createRequire(import.meta.url);
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
})
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
// Next.js 16: Enable 'use cache' directive for explicit caching control
cacheComponents: true,
env: {
NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL,
NEXT_PUBLIC_FIREBASE_API_KEY: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
NEXT_PUBLIC_FIREBASE_APP_ID: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID,
AUTH_FIREBASE_PROJECT_ID: process.env.AUTH_FIREBASE_PROJECT_ID,
AUTH_FIREBASE_CLIENT_EMAIL: process.env.AUTH_FIREBASE_CLIENT_EMAIL,
AUTH_FIREBASE_PRIVATE_KEY: process.env.AUTH_FIREBASE_PRIVATE_KEY,
BLOB_READ_WRITE_TOKEN: process.env.BLOB_READ_WRITE_TOKEN,
AUTH_SECRET: process.env.AUTH_SECRET,
NEXTAUTH_URL: process.env.NEXTAUTH_URL || 'http://localhost:3000',
AUTH_APPLE_ID: process.env.AUTH_APPLE_ID,
AUTH_APPLE_SECRET: process.env.AUTH_APPLE_SECRET,
AUTH_GOOGLE_ID: process.env.AUTH_GOOGLE_ID,
AUTH_GOOGLE_SECRET: process.env.AUTH_GOOGLE_SECRET,
NEXT_PUBLIC_AUTH_GOOGLE_ID: process.env.NEXT_PUBLIC_AUTH_GOOGLE_ID || process.env.AUTH_GOOGLE_ID,
AUTH_RESEND_KEY: process.env.AUTH_RESEND_KEY,
},
async headers() {
// SECURITY FIX: Restrict CORS to specific origins only
const allowedOrigins = process.env.NODE_ENV === 'production'
? [process.env.NEXT_PUBLIC_API_URL || 'https://myri.ng'] // Replace with your production domain
: ['http://localhost:3000', 'http://localhost:3001']
return [
{
source: '/api/:path*',
headers: [
{ key: 'Access-Control-Allow-Credentials', value: 'true' },
// SECURITY: Dynamic origin based on environment - no wildcards!
{ key: 'Access-Control-Allow-Origin', value: allowedOrigins[0] }, // Next.js doesn't support dynamic headers, use middleware for multiple origins
{ key: 'Access-Control-Allow-Methods', value: 'GET,DELETE,PATCH,POST,PUT,OPTIONS' },
{ key: 'Access-Control-Allow-Headers', value: 'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version, Authorization' },
// Additional security headers
{ key: 'X-Content-Type-Options', value: 'nosniff' },
{ key: 'X-Frame-Options', value: 'DENY' },
{ key: 'X-XSS-Protection', value: '1; mode=block' },
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
],
},
]
},
staticPageGenerationTimeout: 180,
images: {
remotePatterns: [
{ protocol: 'https', hostname: 'lh3.googleusercontent.com' },
{ protocol: 'https', hostname: 'static.ring.ck.ua' },
{ protocol: 'https', hostname: 'x0kypqbqtr7wbl1a.public.blob.vercel-storage.com' },
{ protocol: 'https', hostname: 'fonts.googleapis.com' },
{ protocol: 'https', hostname: 'fonts.gstatic.com' },
{ protocol: 'https', hostname: 'example.com' },
{ protocol: 'https', hostname: 'cdn.ring-platform.org' }
],
// Configure image optimization behavior
dangerouslyAllowSVG: true,
contentDispositionType: 'attachment',
contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;",
// Disable image optimization for external domains to prevent infinite retries
unoptimized: false,
// Set loader to handle errors gracefully
loader: 'default',
// Configure image formats
formats: ['image/webp', 'image/avif'],
// Set device sizes for responsive images
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
},
// Next.js 16: Turbopack config (replaces webpack resolve.alias & resolve.fallback)
turbopack: {
resolveAlias: {
// Client-side polyfills for Web3 libs (replaces webpack resolve.fallback)
'crypto': { browser: 'crypto-browserify' },
'stream': { browser: 'stream-browserify' },
'util': { browser: 'util/' },
'process': { browser: 'process/browser' },
'events': { browser: 'events/' },
// Disable server-only modules on client (replaces resolve.fallback: false)
'fs': { browser: './lib/shims/empty.ts' },
'net': { browser: './lib/shims/empty.ts' },
'tls': { browser: './lib/shims/empty.ts' },
'http2': { browser: './lib/shims/empty.ts' },
'child_process': { browser: './lib/shims/empty.ts' },
// Node module protocol aliases
'node:events': 'events',
'node:stream': 'stream-browserify',
'node:util': 'util',
// Provide a stub for bert-js to allow builds without native dep
'bert-js': path.resolve(__dirname, 'lib/shims/bert-js.js'),
},
},
transpilePackages: [
'firebase',
'@firebase/auth',
'@firebase/firestore',
'next-auth',
'@auth/core',
'@auth/firebase-adapter'
],
// Note: serverRuntimeConfig removed in Next.js 16 - use process.env instead
output: 'standalone',
outputFileTracingRoot: path.join(__dirname, './'),
outputFileTracingIncludes: {
'**/*': ['./lib/**/*', './server.js']
},
// Packages that must NOT be bundled by Turbopack on the server —
// they rely on native Node.js HTTP/TLS for external API calls
serverExternalPackages: [
'google-auth-library',
'gaxios',
'gtoken',
],
experimental: {
serverActions: {
allowedOrigins: ['localhost:3000', 'ring.ck.ua', 'ring-platform.org', 'myri.ng'],
bodySizeLimit: '2mb'
}
},
// Exclude docs from build
pageExtensions: ['tsx', 'ts', 'jsx', 'js'].filter(extension => {
return !(extension.startsWith('my-docs/'));
}),
typescript: {
ignoreBuildErrors: false,
},
// Note: eslint config removed from next.config in Next.js 16 - use eslint CLI directly
}
export default withBundleAnalyzer(nextConfig);