-
Notifications
You must be signed in to change notification settings - Fork 19
Expand file tree
/
Copy pathnext.config.ts
More file actions
99 lines (94 loc) · 3.25 KB
/
next.config.ts
File metadata and controls
99 lines (94 loc) · 3.25 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
import type { NextConfig } from "next";
import { getDirectTraceProviderPolicies } from "./src/lib/trails/providers";
const isDev = process.env.NODE_ENV === "development";
const directTraceConnectSrc = Array.from(
new Set(
getDirectTraceProviderPolicies().map(
(provider) => new URL(provider.baseUrl).origin,
),
),
).join(" ");
// Content Security Policy — allows only the external resources Aeris actually uses.
// https://nextjs.org/docs/app/guides/content-security-policy
//
// NOTE: planespotters.net, airport-data.com, and jetapi.dev are
// server-side only (accessed via /api/aircraft-photos proxy route). CSP does
// not apply to server-side fetches, so they are not listed in connect-src.
// adsbdb.com is used client-side for route lookups.
// hexdb.io is proxied via /api/hexdb (no CORS headers from hexdb.io).
const cspHeader = `
default-src 'self';
script-src 'self' 'unsafe-inline' https://www.googletagmanager.com${isDev ? " 'unsafe-eval'" : ""};
style-src 'self' 'unsafe-inline';
img-src 'self' blob: data: https: ;
font-src 'self';
connect-src 'self' data: https://opensky-network.org https://*.basemaps.cartocdn.com https://basemaps.cartocdn.com https://server.arcgisonline.com https://s3.amazonaws.com https://tile.opentopomap.org https://www.google-analytics.com https://www.googletagmanager.com https://api.github.com https://api.airplanes.live https://api.adsb.lol https://res.cloudinary.com https://api.rainviewer.com https://api.adsbdb.com ${directTraceConnectSrc};
worker-src 'self' blob:;
child-src blob:;
object-src 'none';
base-uri 'self';
form-action 'self';
frame-ancestors 'none';
upgrade-insecure-requests;
`;
const nextConfig: NextConfig = {
transpilePackages: [
"@deck.gl/core",
"@deck.gl/layers",
"@deck.gl/geo-layers",
"@deck.gl/mesh-layers",
"@deck.gl/mapbox",
"@deck.gl/react",
"@loaders.gl/core",
"@loaders.gl/gltf",
"@luma.gl/core",
"@luma.gl/webgl",
],
images: {
remotePatterns: [
{ hostname: "a.basemaps.cartocdn.com" },
{ hostname: "server.arcgisonline.com" },
{ hostname: "tile.opentopomap.org" },
],
},
async headers() {
return [
{
source: "/(.*)",
headers: [
{
key: "Content-Security-Policy",
value: cspHeader.replace(/\s{2,}/g, " ").trim(),
},
{
key: "Strict-Transport-Security",
value: "max-age=63072000; includeSubDomains; preload",
},
{ key: "X-Content-Type-Options", value: "nosniff" },
{ key: "X-Frame-Options", value: "DENY" },
{ key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
{ key: "X-DNS-Prefetch-Control", value: "on" },
{
key: "Permissions-Policy",
value:
"camera=(), microphone=(), geolocation=(self), interest-cohort=()",
},
],
},
{
source: "/api/:path*",
headers: [{ key: "Cache-Control", value: "no-store, max-age=0" }],
},
{
source: "/models/:path*",
headers: [
{
key: "Cache-Control",
value: "public, max-age=31536000, immutable",
},
],
},
];
},
};
export default nextConfig;