feat: harden portfolio and add SEO foundations
This commit is contained in:
1 parent
b079afdd73
commit
62bcfbd8fa
121 files changed
+7769
-10469
No files matched your search
+19
-62
@@ -13,10 +13,27 @@ const nextConfig: NextConfig = {
|
||||
root: process.cwd(),
|
||||
},
|
||||
|
||||
// Headers de cache e segurança
|
||||
async headers(): Promise<
|
||||
Array<{ source: string; headers: Array<{ key: string; value: string }> }>
|
||||
> {
|
||||
const scriptSources = [
|
||||
"'self'",
|
||||
"'unsafe-inline'",
|
||||
...(process.env.NODE_ENV === "production" ? [] : ["'unsafe-eval'"]),
|
||||
"https://www.googletagmanager.com",
|
||||
].join(" ");
|
||||
const contentSecurityPolicy = [
|
||||
"default-src 'self'",
|
||||
`script-src ${scriptSources}`,
|
||||
"connect-src 'self' https://*.google-analytics.com https://*.analytics.google.com https://*.googletagmanager.com",
|
||||
"img-src 'self' data: blob: https://*.google-analytics.com https://www.googletagmanager.com",
|
||||
"style-src 'self' 'unsafe-inline'",
|
||||
"font-src 'self' data:",
|
||||
"frame-ancestors 'none'",
|
||||
"object-src 'none'",
|
||||
"base-uri 'self'",
|
||||
"form-action 'self'",
|
||||
].join("; ");
|
||||
const securityHeaders = [
|
||||
{
|
||||
key: "X-Frame-Options",
|
||||
@@ -36,12 +53,10 @@ const nextConfig: NextConfig = {
|
||||
},
|
||||
{
|
||||
key: "Content-Security-Policy-Report-Only",
|
||||
value:
|
||||
"script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.googletagmanager.com https://www.google-analytics.com; connect-src 'self' https://www.google-analytics.com https://analytics.google.com; img-src 'self' data: blob: https:; style-src 'self' 'unsafe-inline'; font-src 'self' data:; frame-ancestors 'none'; object-src 'none'; base-uri 'self'",
|
||||
value: contentSecurityPolicy,
|
||||
},
|
||||
];
|
||||
|
||||
// HSTS apenas em produção com HTTPS
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
securityHeaders.push({
|
||||
key: "Strict-Transport-Security",
|
||||
@@ -54,64 +69,6 @@ const nextConfig: NextConfig = {
|
||||
source: "/(.*)",
|
||||
headers: securityHeaders,
|
||||
},
|
||||
{
|
||||
source: "/static/(.*)",
|
||||
headers: [
|
||||
{
|
||||
key: "Cache-Control",
|
||||
value: "public, max-age=31536000, immutable",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
source: "/fonts/(.*)",
|
||||
headers: [
|
||||
{
|
||||
key: "Cache-Control",
|
||||
value: "public, max-age=31536000, immutable",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
source: "/assets/(.*)",
|
||||
headers: [
|
||||
{
|
||||
key: "Cache-Control",
|
||||
value: "public, max-age=31536000, immutable",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
source: "/logos/(.*)",
|
||||
headers: [
|
||||
{
|
||||
key: "Cache-Control",
|
||||
value: "public, max-age=31536000, immutable",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
},
|
||||
|
||||
// Proxy reverso para bypass de adblockers
|
||||
async rewrites() {
|
||||
return [
|
||||
// Rybbit Analytics
|
||||
{
|
||||
source: "/analytics/:match*",
|
||||
destination: "https://analytics.evandro.dev.br/:match*",
|
||||
},
|
||||
// Google Analytics - Script principal (camuflado como lib de sistema)
|
||||
{
|
||||
source: "/sys/libs/vendor-utils.js",
|
||||
destination: "https://www.googletagmanager.com/gtag/js?id=G-QTT9QT0T3S",
|
||||
},
|
||||
// Google Analytics - Endpoint de coleta (camuflado como API de vitals)
|
||||
// O gtag.js adiciona "/g/collect" automaticamente ao final da transport_url
|
||||
{
|
||||
source: "/sys/api/vitals/g/collect",
|
||||
destination: "https://www.google-analytics.com/g/collect",
|
||||
},
|
||||
];
|
||||
},
|
||||
|
||||
|
||||
Reference in new issue
Block a user