Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e9ea253021 | |||
| 237bd46593 | |||
| 40ebdb31d9 | |||
| 8f39ec3d35 | |||
| 7734440b90 | |||
| 42295c3c41 | |||
| 1e00690dd8 |
@@ -51,7 +51,8 @@ COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
|||||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||||
|
|
||||||
# Ensure the cache directory specifically is writeable (Mintel Standard #16)
|
# Ensure the cache directory specifically is writeable (Mintel Standard #16)
|
||||||
RUN mkdir -p .next/cache && chown -R nextjs:nodejs .next/cache
|
# We copy a small directory or just create it via COPY to avoid RUN chown permission issues
|
||||||
|
COPY --from=builder --chown=nextjs:nodejs /app/.next/cache ./.next/cache
|
||||||
|
|
||||||
USER nextjs
|
USER nextjs
|
||||||
|
|
||||||
|
|||||||
@@ -114,6 +114,20 @@ export default async function RootLayout({
|
|||||||
await import("@/lib/services/create-services.server")
|
await import("@/lib/services/create-services.server")
|
||||||
).getServerAppServices();
|
).getServerAppServices();
|
||||||
|
|
||||||
|
// Populate analytics context with headers for high-fidelity server-side tracking
|
||||||
|
const { headers } = await import("next/headers");
|
||||||
|
const requestHeaders = await headers();
|
||||||
|
|
||||||
|
if (serverServices.analytics.setServerContext) {
|
||||||
|
serverServices.analytics.setServerContext({
|
||||||
|
userAgent: requestHeaders.get("user-agent") || undefined,
|
||||||
|
language:
|
||||||
|
requestHeaders.get("accept-language")?.split(",")[0] || undefined,
|
||||||
|
referrer: requestHeaders.get("referer") || undefined,
|
||||||
|
ip: requestHeaders.get("x-forwarded-for")?.split(",")[0] || undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Track server-side (initial load)
|
// Track server-side (initial load)
|
||||||
serverServices.analytics.trackPageview("/");
|
serverServices.analytics.trackPageview("/");
|
||||||
|
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ export default async function Image() {
|
|||||||
letterSpacing: "0.1em",
|
letterSpacing: "0.1em",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Engineering Excellence
|
Technische Beratung
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ export default async function Image() {
|
|||||||
letterSpacing: "0.1em",
|
letterSpacing: "0.1em",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Engineering Excellence
|
Technische Beratung
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,23 @@ export async function POST(req: Request) {
|
|||||||
const services = getServerAppServices();
|
const services = getServerAppServices();
|
||||||
const logger = services.logger.child({ action: "contact_submission" });
|
const logger = services.logger.child({ action: "contact_submission" });
|
||||||
|
|
||||||
|
// Set analytics context from request headers for high-fidelity server-side tracking
|
||||||
|
// This fulfills the "server-side via nextjs proxy" requirement
|
||||||
|
if (services.analytics.setServerContext) {
|
||||||
|
services.analytics.setServerContext({
|
||||||
|
userAgent: req.headers.get("user-agent") || undefined,
|
||||||
|
language: req.headers.get("accept-language")?.split(",")[0] || undefined,
|
||||||
|
referrer: req.headers.get("referer") || undefined,
|
||||||
|
ip: req.headers.get("x-forwarded-for")?.split(",")[0] || undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { name, email, company, message, website } = await req.json();
|
const { name, email, company, message, website } = await req.json();
|
||||||
|
|
||||||
|
// Track attempt
|
||||||
|
services.analytics.track("contact-form-attempt");
|
||||||
|
|
||||||
// Honeypot check
|
// Honeypot check
|
||||||
if (website) {
|
if (website) {
|
||||||
logger.info("Spam detected (honeypot)");
|
logger.info("Spam detected (honeypot)");
|
||||||
@@ -118,6 +132,11 @@ ${message}
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Track success
|
||||||
|
services.analytics.track("contact-form-success", {
|
||||||
|
has_company: Boolean(company),
|
||||||
|
});
|
||||||
|
|
||||||
return NextResponse.json({ message: "Ok" });
|
return NextResponse.json({ message: "Ok" });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error("Global API Error", { error });
|
logger.error("Global API Error", { error });
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ export default function Home() {
|
|||||||
<div className="absolute inset-0 bg-accent/10 opacity-0 group-hover:opacity-100 transition-opacity duration-500 z-10 pointer-events-none" />
|
<div className="absolute inset-0 bg-accent/10 opacity-0 group-hover:opacity-100 transition-opacity duration-500 z-10 pointer-events-none" />
|
||||||
<Image
|
<Image
|
||||||
src="/media/cables/hs-kabel.png"
|
src="/media/cables/hs-kabel.png"
|
||||||
alt="Technical Engineering"
|
alt="Technische Beratung"
|
||||||
width={800}
|
width={800}
|
||||||
height={600}
|
height={600}
|
||||||
className="w-full h-[400px] md:h-[500px] object-cover hover:scale-105 transition-transform duration-700"
|
className="w-full h-[400px] md:h-[500px] object-cover hover:scale-105 transition-transform duration-700"
|
||||||
|
|||||||
@@ -275,7 +275,7 @@ const Layout = ({ children }: { children: React.ReactNode }) => {
|
|||||||
<div className="bg-slate-950 py-6 border-t border-white/5">
|
<div className="bg-slate-950 py-6 border-t border-white/5">
|
||||||
<div className="container-custom">
|
<div className="container-custom">
|
||||||
<p className="text-[10px] uppercase tracking-[0.2em] text-slate-600 text-center md:text-left">
|
<p className="text-[10px] uppercase tracking-[0.2em] text-slate-600 text-center md:text-left">
|
||||||
Website developed by{" "}
|
Website entwickelt von{" "}
|
||||||
<a
|
<a
|
||||||
href="https://mintel.me"
|
href="https://mintel.me"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
|||||||
@@ -73,4 +73,15 @@ export interface AnalyticsService {
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
trackPageview(url?: string): void;
|
trackPageview(url?: string): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the server-side context for the current request.
|
||||||
|
* This is used for server-side tracking (e.g. from Next.js proxy).
|
||||||
|
*/
|
||||||
|
setServerContext?(context: {
|
||||||
|
userAgent?: string;
|
||||||
|
language?: string;
|
||||||
|
referrer?: string;
|
||||||
|
ip?: string;
|
||||||
|
}): void;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,4 +68,16 @@ export class NoopAnalyticsService implements AnalyticsService {
|
|||||||
trackPageview(_url?: string) {
|
trackPageview(_url?: string) {
|
||||||
// intentionally noop - analytics are disabled
|
// intentionally noop - analytics are disabled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No-op implementation of setServerContext.
|
||||||
|
*/
|
||||||
|
setServerContext(_context: {
|
||||||
|
userAgent?: string;
|
||||||
|
language?: string;
|
||||||
|
referrer?: string;
|
||||||
|
ip?: string;
|
||||||
|
}) {
|
||||||
|
// intentionally noop - analytics are disabled
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,12 @@ export type UmamiAnalyticsServiceOptions = {
|
|||||||
export class UmamiAnalyticsService implements AnalyticsService {
|
export class UmamiAnalyticsService implements AnalyticsService {
|
||||||
private websiteId?: string;
|
private websiteId?: string;
|
||||||
private endpoint: string;
|
private endpoint: string;
|
||||||
|
private serverContext?: {
|
||||||
|
userAgent?: string;
|
||||||
|
language?: string;
|
||||||
|
referrer?: string;
|
||||||
|
ip?: string;
|
||||||
|
};
|
||||||
|
|
||||||
constructor(private readonly options: UmamiAnalyticsServiceOptions) {
|
constructor(private readonly options: UmamiAnalyticsServiceOptions) {
|
||||||
this.websiteId = config.analytics.umami.websiteId;
|
this.websiteId = config.analytics.umami.websiteId;
|
||||||
@@ -36,6 +42,19 @@ export class UmamiAnalyticsService implements AnalyticsService {
|
|||||||
: "/stats";
|
: "/stats";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the server-side context for the current request.
|
||||||
|
* This allows the service to use real request headers for tracking.
|
||||||
|
*/
|
||||||
|
setServerContext(context: {
|
||||||
|
userAgent?: string;
|
||||||
|
language?: string;
|
||||||
|
referrer?: string;
|
||||||
|
ip?: string;
|
||||||
|
}) {
|
||||||
|
this.serverContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal method to send the payload to Umami API.
|
* Internal method to send the payload to Umami API.
|
||||||
*/
|
*/
|
||||||
@@ -47,24 +66,47 @@ export class UmamiAnalyticsService implements AnalyticsService {
|
|||||||
const payload = {
|
const payload = {
|
||||||
website: this.websiteId,
|
website: this.websiteId,
|
||||||
hostname:
|
hostname:
|
||||||
typeof window !== "undefined" ? window.location.hostname : "server",
|
typeof window !== "undefined"
|
||||||
|
? window.location.hostname
|
||||||
|
: this.serverContext?.referrer
|
||||||
|
? new URL(this.serverContext.referrer).hostname
|
||||||
|
: "server",
|
||||||
screen:
|
screen:
|
||||||
typeof window !== "undefined"
|
typeof window !== "undefined"
|
||||||
? `${window.screen.width}x${window.screen.height}`
|
? `${window.screen.width}x${window.screen.height}`
|
||||||
: undefined,
|
: undefined,
|
||||||
language:
|
language:
|
||||||
typeof window !== "undefined" ? navigator.language : undefined,
|
typeof window !== "undefined"
|
||||||
referrer: typeof window !== "undefined" ? document.referrer : undefined,
|
? navigator.language
|
||||||
|
: this.serverContext?.language,
|
||||||
|
referrer:
|
||||||
|
typeof window !== "undefined"
|
||||||
|
? document.referrer
|
||||||
|
: this.serverContext?.referrer,
|
||||||
...data,
|
...data,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const headers: Record<string, string> = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set User-Agent
|
||||||
|
if (typeof window !== "undefined") {
|
||||||
|
headers["User-Agent"] = navigator.userAgent;
|
||||||
|
} else if (this.serverContext?.userAgent) {
|
||||||
|
headers["User-Agent"] = this.serverContext.userAgent;
|
||||||
|
} else {
|
||||||
|
headers["User-Agent"] = "Mintel-Server-Proxy";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forward client IP if available (Umami must be configured to trust this)
|
||||||
|
if (this.serverContext?.ip) {
|
||||||
|
headers["X-Forwarded-For"] = this.serverContext.ip;
|
||||||
|
}
|
||||||
|
|
||||||
const response = await fetch(`${this.endpoint}/api/send`, {
|
const response = await fetch(`${this.endpoint}/api/send`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers,
|
||||||
"Content-Type": "application/json",
|
|
||||||
"User-Agent":
|
|
||||||
typeof window === "undefined" ? "KLZ-Server" : navigator.userAgent,
|
|
||||||
},
|
|
||||||
body: JSON.stringify({ type, payload }),
|
body: JSON.stringify({ type, payload }),
|
||||||
keepalive: true,
|
keepalive: true,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
@@ -93,7 +135,9 @@ export class UmamiAnalyticsService implements AnalyticsService {
|
|||||||
url:
|
url:
|
||||||
typeof window !== "undefined"
|
typeof window !== "undefined"
|
||||||
? window.location.pathname + window.location.search
|
? window.location.pathname + window.location.search
|
||||||
: undefined,
|
: this.serverContext?.referrer
|
||||||
|
? new URL(this.serverContext.referrer).pathname
|
||||||
|
: "/",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +150,9 @@ export class UmamiAnalyticsService implements AnalyticsService {
|
|||||||
url ||
|
url ||
|
||||||
(typeof window !== "undefined"
|
(typeof window !== "undefined"
|
||||||
? window.location.pathname + window.location.search
|
? window.location.pathname + window.location.search
|
||||||
: undefined),
|
: this.serverContext?.referrer
|
||||||
|
? new URL(this.serverContext.referrer).pathname
|
||||||
|
: "/"),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,33 +31,63 @@ export class PinoLoggerService implements LoggerService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
trace(msg: string, ...args: unknown[]) {
|
trace(msg: string, ...args: unknown[]) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
if (args.length > 0 && typeof args[0] === "object" && args[0] !== null) {
|
||||||
this.logger.trace(msg, ...(args as any));
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
(this.logger as any).trace(args[0] as object, msg, ...args.slice(1));
|
||||||
|
} else {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
(this.logger as any).trace(msg, ...args);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debug(msg: string, ...args: unknown[]) {
|
debug(msg: string, ...args: unknown[]) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
if (args.length > 0 && typeof args[0] === "object" && args[0] !== null) {
|
||||||
this.logger.debug(msg, ...(args as any));
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
(this.logger as any).debug(args[0] as object, msg, ...args.slice(1));
|
||||||
|
} else {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
(this.logger as any).debug(msg, ...args);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
info(msg: string, ...args: unknown[]) {
|
info(msg: string, ...args: unknown[]) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
if (args.length > 0 && typeof args[0] === "object" && args[0] !== null) {
|
||||||
this.logger.info(msg, ...(args as any));
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
(this.logger as any).info(args[0] as object, msg, ...args.slice(1));
|
||||||
|
} else {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
(this.logger as any).info(msg, ...args);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
warn(msg: string, ...args: unknown[]) {
|
warn(msg: string, ...args: unknown[]) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
if (args.length > 0 && typeof args[0] === "object" && args[0] !== null) {
|
||||||
this.logger.warn(msg, ...(args as any));
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
(this.logger as any).warn(args[0] as object, msg, ...args.slice(1));
|
||||||
|
} else {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
(this.logger as any).warn(msg, ...args);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
error(msg: string, ...args: unknown[]) {
|
error(msg: string, ...args: unknown[]) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
if (args.length > 0 && typeof args[0] === "object" && args[0] !== null) {
|
||||||
this.logger.error(msg, ...(args as any));
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
(this.logger as any).error(args[0] as object, msg, ...args.slice(1));
|
||||||
|
} else {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
(this.logger as any).error(msg, ...args);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fatal(msg: string, ...args: unknown[]) {
|
fatal(msg: string, ...args: unknown[]) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
if (args.length > 0 && typeof args[0] === "object" && args[0] !== null) {
|
||||||
this.logger.fatal(msg, ...(args as any));
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
(this.logger as any).fatal(args[0] as object, msg, ...args.slice(1));
|
||||||
|
} else {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
(this.logger as any).fatal(msg, ...args);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
child(bindings: Record<string, unknown>): LoggerService {
|
child(bindings: Record<string, unknown>): LoggerService {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"Index": {
|
"Index": {
|
||||||
"hero": {
|
"hero": {
|
||||||
"tag": "Engineering Excellence",
|
"tag": "Technische Beratung",
|
||||||
"title": "Spezialisierter Partner für Energiekabelprojekte",
|
"title": "Spezialisierter Partner für Energiekabelprojekte",
|
||||||
"titleHighlight": "Energiekabelprojekte",
|
"titleHighlight": "Energiekabelprojekte",
|
||||||
"subtitle": "Herstellerneutrale technische Beratung für Ihre Projekte in Mittel- und Hochspannungsnetzen bis zu 110 kV.",
|
"subtitle": "Herstellerneutrale technische Beratung für Ihre Projekte in Mittel- und Hochspannungsnetzen bis zu 110 kV.",
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
"expertise": {
|
"expertise": {
|
||||||
"tag": "Expertise",
|
"tag": "Expertise",
|
||||||
"title": "Anwendungen & Zielgruppen",
|
"title": "Anwendungen & Zielgruppen",
|
||||||
"description": "Wir unterstützen Akteure der Energiewende bei der Realisierung komplexer Kabelprojekte mit höchster Präzision.",
|
"description": "Wir unterstützen Sie bei der Realisierung Ihrer Kabelprojekte.",
|
||||||
"groups": [
|
"groups": [
|
||||||
"Energieversorger",
|
"Energieversorger",
|
||||||
"Ingenieurbüros",
|
"Ingenieurbüros",
|
||||||
@@ -83,16 +83,16 @@
|
|||||||
"datenschutz": "Datenschutz",
|
"datenschutz": "Datenschutz",
|
||||||
"agb": "AGB",
|
"agb": "AGB",
|
||||||
"rights": "Alle Rechte vorbehalten.",
|
"rights": "Alle Rechte vorbehalten.",
|
||||||
"madeWith": "Made with",
|
"madeWith": "Entwickelt mit",
|
||||||
"precision": "precision",
|
"precision": "Präzision",
|
||||||
"inGermany": "in Germany"
|
"inGermany": "in Deutschland"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"About": {
|
"About": {
|
||||||
"hero": {
|
"hero": {
|
||||||
"tagline": "Über uns",
|
"tagline": "Über uns",
|
||||||
"title": "Wir gestalten die Infrastructure der Zukunft",
|
"title": "Zuverlässige Begleitung für Ihre Netzinfrastruktur",
|
||||||
"subtitle": "MB Grid Solution steht für technische Exzellenz in der Energiekabeltechnologie. Wir verstehen uns als Ihr technischer Lotse."
|
"subtitle": "Herstellerneutrale Beratung in der Energiekabeltechnologie. Wir verstehen uns als Ihr technischer Lotse."
|
||||||
},
|
},
|
||||||
"intro": {
|
"intro": {
|
||||||
"p1": "Unsere Wurzeln liegen in der tiefen praktischen Erfahrung unserer technischen Berater und unserer Netzwerke im globalem Kabelmarkt. Wir vereinen Tradition mit modernster Innovation, um zuverlässige Energielösungen für Projekte bis 110 kV zu realisieren.",
|
"p1": "Unsere Wurzeln liegen in der tiefen praktischen Erfahrung unserer technischen Berater und unserer Netzwerke im globalem Kabelmarkt. Wir vereinen Tradition mit modernster Innovation, um zuverlässige Energielösungen für Projekte bis 110 kV zu realisieren.",
|
||||||
|
|||||||
@@ -17,10 +17,18 @@ const nextConfig = {
|
|||||||
source: "/stats/:path*",
|
source: "/stats/:path*",
|
||||||
destination: `${umamiUrl}/:path*`,
|
destination: `${umamiUrl}/:path*`,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
source: "/:locale(de)/stats/:path*",
|
||||||
|
destination: `${umamiUrl}/:path*`,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
source: "/errors/:path*",
|
source: "/errors/:path*",
|
||||||
destination: `${glitchtipUrl}/:path*`,
|
destination: `${glitchtipUrl}/:path*`,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
source: "/:locale(de)/errors/:path*",
|
||||||
|
destination: `${glitchtipUrl}/:path*`,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
13
sentry.client.config.ts
Normal file
13
sentry.client.config.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import * as Sentry from "@sentry/nextjs";
|
||||||
|
import { config } from "./lib/config";
|
||||||
|
|
||||||
|
if (config.errors.glitchtip.enabled) {
|
||||||
|
Sentry.init({
|
||||||
|
dsn: config.errors.glitchtip.dsn,
|
||||||
|
tracesSampleRate: 1.0,
|
||||||
|
debug: config.isDevelopment,
|
||||||
|
environment: config.target || "production",
|
||||||
|
// Use the proxy path defined in config
|
||||||
|
tunnel: config.errors.glitchtip.proxyPath,
|
||||||
|
});
|
||||||
|
}
|
||||||
11
sentry.edge.config.ts
Normal file
11
sentry.edge.config.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import * as Sentry from "@sentry/nextjs";
|
||||||
|
import { config } from "./lib/config";
|
||||||
|
|
||||||
|
if (config.errors.glitchtip.enabled) {
|
||||||
|
Sentry.init({
|
||||||
|
dsn: config.errors.glitchtip.dsn,
|
||||||
|
tracesSampleRate: 1.0,
|
||||||
|
debug: config.isDevelopment,
|
||||||
|
environment: config.target || "production",
|
||||||
|
});
|
||||||
|
}
|
||||||
11
sentry.server.config.ts
Normal file
11
sentry.server.config.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import * as Sentry from "@sentry/nextjs";
|
||||||
|
import { config } from "./lib/config";
|
||||||
|
|
||||||
|
if (config.errors.glitchtip.enabled) {
|
||||||
|
Sentry.init({
|
||||||
|
dsn: config.errors.glitchtip.dsn,
|
||||||
|
tracesSampleRate: 1.0,
|
||||||
|
debug: config.isDevelopment,
|
||||||
|
environment: config.target || "production",
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user