next.config.ts
Rama master · réplica de lectura del repositorio original.
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
async redirects() {
return [
{
// La doc développeurs vit désormais sur developers.cordsuite.app.
// Permanent (308) : les anciens liens et les moteurs de recherche suivent.
source: "/docs/technique/api-v2",
destination: "https://developers.cordsuite.app/api/drivecord",
permanent: true,
},
{
source: "/docs/technique/applications",
destination: "https://developers.cordsuite.app/auth",
permanent: true,
},
{
source: "/docs/technique/sdk",
destination: "https://developers.cordsuite.app/sdk",
permanent: true,
},
{
// Lien d'invitation « vanity » : on communique drivecord.app/discord
// partout, et il redirige vers l'invitation Discord réelle. Non
// permanent (307) exprès : si l'invitation change un jour, il suffit
// de modifier l'URL ci-dessous — aucun cache navigateur à purger.
source: "/discord",
destination: "https://discord.gg/drivecord",
permanent: false,
},
{
// Lien vanity vers le dashboard DriveBot (hébergé séparément). Non
// permanent (307) exprès pour pouvoir changer l'URL sans purge cache.
source: "/drivebot",
destination: "https://drivebot-dashboard.vercel.app/",
permanent: false,
},
{
// Lien vanity vers le dépôt GitHub : on communique drivecord.app/github
// et il redirige vers le dépôt réel. Non permanent (307) exprès pour
// pouvoir changer d'organisation ou de nom de dépôt sans purge cache.
source: "/github",
destination: "https://github.com/LeVraiLunatix/drivecord",
permanent: false,
},
{
// Lien vanity vers la page Patreon : on communique drivecord.app/patreon
// et il redirige vers la vraie page. Non permanent (307) pour pouvoir
// changer le slug sans purge cache.
source: "/patreon",
destination: "https://www.patreon.com/drivecord",
permanent: false,
},
];
},
async headers() {
return [
{
// Consent / developer / login screens must never be framed (clickjacking of an "Authorize" button).
source: "/:path(oauth|developers|login|settings)/:rest*",
headers: [
{ key: "Content-Security-Policy", value: "frame-ancestors 'none'" },
{ key: "X-Frame-Options", value: "DENY" },
],
},
{
// Baseline hardening for every response.
source: "/:path*",
headers: [
{ key: "X-Content-Type-Options", value: "nosniff" },
{ key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
{ key: "Permissions-Policy", value: "camera=(), microphone=(), geolocation=(), payment=()" },
{ key: "Strict-Transport-Security", value: "max-age=31536000; includeSubDomains" },
],
},
{
// The popup that mints an embed ticket is first-party only.
source: "/embed/connect",
headers: [
{ key: "Content-Security-Policy", value: "frame-ancestors 'none'" },
{ key: "X-Frame-Options", value: "DENY" },
],
},
{
// Never cache HTML documents / API responses, so the in-app WebView
// always loads the latest deploy on relaunch. Hashed static assets
// under /_next/ are excluded and stay immutably cached.
source: "/((?!_next/).*)",
headers: [
{ key: "Cache-Control", value: "no-store, must-revalidate" },
],
},
];
},
};
export default nextConfig;