Compare commits
6 Commits
56012fd0d6
...
fix/conten
| Author | SHA1 | Date | |
|---|---|---|---|
| 4df6e2601a | |||
| 569b876944 | |||
| 1f905bc86d | |||
| 8fcd68cf19 | |||
| 66f28d8af2 | |||
| 351c27f7d4 |
@@ -20,6 +20,8 @@ import { CallToAction } from '@/components/blocks/CallToAction';
|
||||
import { ServiceDetailGrid } from '@/components/blocks/ServiceDetailGrid';
|
||||
import { BenefitGrid } from '@/components/blocks/BenefitGrid';
|
||||
import { InteractiveGermanyMap } from '@/components/blocks/InteractiveGermanyMap';
|
||||
import { FaqBlock } from '@/components/blocks/FaqBlock';
|
||||
import JsonLd from '@/components/JsonLd';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
|
||||
|
||||
@@ -34,6 +36,8 @@ const mdxComponents = {
|
||||
ServiceDetailGrid,
|
||||
BenefitGrid,
|
||||
InteractiveGermanyMap,
|
||||
FaqBlock,
|
||||
JsonLd,
|
||||
Button,
|
||||
Heading,
|
||||
};
|
||||
|
||||
@@ -11,6 +11,8 @@ import { HeroVideo as HomeHero } from '@/components/blocks/HeroVideo';
|
||||
import { SubCompanyTiles as HomeSubCompanyTiles } from '@/components/blocks/SubCompanyTiles';
|
||||
import { CompetenceBentoGrid as HomeCompetenceBentoGrid } from '@/components/blocks/CompetenceBentoGrid';
|
||||
import { ReferencesSlider as HomeReferencesSlider } from '@/components/blocks/ReferencesSlider';
|
||||
import { FaqBlock } from '@/components/blocks/FaqBlock';
|
||||
import JsonLd from '@/components/JsonLd';
|
||||
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { Heading } from '@/components/ui/Heading';
|
||||
@@ -20,6 +22,8 @@ const mdxComponents = {
|
||||
HomeSubCompanyTiles,
|
||||
HomeCompetenceBentoGrid,
|
||||
HomeReferencesSlider,
|
||||
FaqBlock,
|
||||
JsonLd,
|
||||
Button,
|
||||
Heading,
|
||||
};
|
||||
|
||||
@@ -1,53 +1,67 @@
|
||||
import { Thing, WithContext } from 'schema-dts';
|
||||
import { Thing, WithContext, Graph } from 'schema-dts';
|
||||
import { getOrganizationSchema, getLocalBusinessSchema, SITE_URL } from '@/lib/schema';
|
||||
|
||||
interface JsonLdProps {
|
||||
id?: string;
|
||||
data?: WithContext<Thing> | WithContext<Thing>[];
|
||||
disableGlobal?: boolean;
|
||||
}
|
||||
|
||||
export default function JsonLd({ id, data }: JsonLdProps) {
|
||||
// If data is provided, use it. Otherwise, use the default Organization + WebSite schema.
|
||||
const schemaData = data || [
|
||||
{
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'Organization',
|
||||
name: 'E-TIB GmbH',
|
||||
url: 'https://e-tib.com',
|
||||
logo: 'https://e-tib.com/assets/logo.png',
|
||||
sameAs: [
|
||||
'https://www.instagram.com/me.and.eloise/',
|
||||
],
|
||||
description: 'Ihr Partner für Kabelleitungstiefbau, Horizontalspülbohrungen, Planung und Vermessung.',
|
||||
address: {
|
||||
'@type': 'PostalAddress',
|
||||
streetAddress: 'Gewerbestraße 22',
|
||||
addressLocality: 'Guben',
|
||||
postalCode: '03172',
|
||||
addressCountry: 'DE',
|
||||
},
|
||||
},
|
||||
{
|
||||
export default function JsonLd({ id, data, disableGlobal = false }: JsonLdProps) {
|
||||
let finalSchema: any;
|
||||
|
||||
if (disableGlobal && data) {
|
||||
// Escape hatch for overriding the global graph
|
||||
finalSchema = data;
|
||||
} else {
|
||||
// Construct the @graph array
|
||||
const graphItems: any[] = [];
|
||||
|
||||
// Always include Organization, WebSite, and LocalBusiness for strong AI SEO presence
|
||||
graphItems.push(getOrganizationSchema());
|
||||
graphItems.push({
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'WebSite',
|
||||
name: 'E-TIB',
|
||||
url: 'https://e-tib.com',
|
||||
url: SITE_URL,
|
||||
potentialAction: {
|
||||
'@type': 'SearchAction',
|
||||
target: {
|
||||
'@type': 'EntryPoint',
|
||||
urlTemplate: 'https://e-tib.com/search?q={search_term_string}',
|
||||
urlTemplate: `${SITE_URL}/search?q={search_term_string}`,
|
||||
},
|
||||
'query-input': 'required name=search_term_string',
|
||||
},
|
||||
});
|
||||
graphItems.push(getLocalBusinessSchema());
|
||||
|
||||
// Append dynamic data from props
|
||||
if (data) {
|
||||
if (Array.isArray(data)) {
|
||||
// Strip out their individual @context if we are pushing to a graph
|
||||
const cleanedData = data.map((d: any) => {
|
||||
const { '@context': _, ...rest } = d;
|
||||
return rest;
|
||||
});
|
||||
graphItems.push(...cleanedData);
|
||||
} else {
|
||||
const { '@context': _, ...rest } = data as any;
|
||||
graphItems.push(rest);
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
finalSchema = {
|
||||
'@context': 'https://schema.org',
|
||||
'@graph': graphItems,
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<script
|
||||
id={id}
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: JSON.stringify(schemaData),
|
||||
__html: JSON.stringify(finalSchema),
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -2,7 +2,19 @@
|
||||
|
||||
import * as React from 'react';
|
||||
import { motion, useScroll, useTransform } from 'framer-motion';
|
||||
import { Building2, Compass, Layers, Drill, ArrowDownToLine, Wrench } from 'lucide-react';
|
||||
import { Building2, Compass, Layers, ArrowDownToLine, Wrench, Factory, Zap, MapPin, CheckCircle2 } from 'lucide-react';
|
||||
|
||||
const iconMap: Record<string, React.ElementType> = {
|
||||
Building2,
|
||||
Compass,
|
||||
Layers,
|
||||
ArrowDownToLine,
|
||||
Wrench,
|
||||
Factory,
|
||||
Zap,
|
||||
MapPin,
|
||||
CheckCircle2
|
||||
};
|
||||
|
||||
const defaultMilestones = [
|
||||
{
|
||||
@@ -10,28 +22,28 @@ const defaultMilestones = [
|
||||
year: '2015',
|
||||
title: 'Gründung E-TIB GmbH',
|
||||
desc: 'Ausführung elektrischer Infrastrukturprojekte, Kabelbau und Horizontalspülbohrungen.',
|
||||
icon: Building2,
|
||||
iconName: 'Building2',
|
||||
},
|
||||
{
|
||||
date: '04.02.2019',
|
||||
year: '2019',
|
||||
title: 'Gründung E-TIB Ingenieurgesellschaft',
|
||||
desc: 'Genehmigungs- und Ausführungsplanung, komplexe Querungen sowie Netzanschlussplanung.',
|
||||
icon: Compass,
|
||||
iconName: 'Compass',
|
||||
},
|
||||
{
|
||||
date: '14.11.2019',
|
||||
year: '2019',
|
||||
title: 'Gründung E-TIB Verwaltung GmbH',
|
||||
desc: 'Zentrale Dienste, Erwerb, Vermietung, Verpachtung und Verwaltung von Immobilien und Maschinen.',
|
||||
icon: Layers,
|
||||
iconName: 'Layers',
|
||||
},
|
||||
{
|
||||
date: '21.10.2025',
|
||||
year: '2025',
|
||||
title: 'Gründung E-TIB Bohrtechnik GmbH',
|
||||
desc: 'Spezialisierung auf präzise Horizontalspülbohrungen in allen Bodenklassen.',
|
||||
icon: ArrowDownToLine,
|
||||
iconName: 'ArrowDownToLine',
|
||||
},
|
||||
];
|
||||
|
||||
@@ -40,7 +52,7 @@ interface Milestone {
|
||||
year: string;
|
||||
title: string;
|
||||
desc: string;
|
||||
icon: React.ElementType;
|
||||
iconName: string;
|
||||
}
|
||||
|
||||
interface CompanyTimelineProps {
|
||||
@@ -94,7 +106,7 @@ export function CompanyTimeline({
|
||||
<div className="space-y-16 md:space-y-24">
|
||||
{milestones.map((milestone, i) => {
|
||||
const isEven = i % 2 === 0;
|
||||
const Icon = milestone.icon;
|
||||
const Icon = iconMap[milestone.iconName] || Building2;
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
|
||||
64
components/blocks/FaqBlock.tsx
Normal file
64
components/blocks/FaqBlock.tsx
Normal file
@@ -0,0 +1,64 @@
|
||||
import React from 'react';
|
||||
import { getFAQSchema } from '@/lib/schema';
|
||||
import JsonLd from '@/components/JsonLd';
|
||||
|
||||
export interface FAQItem {
|
||||
question: string;
|
||||
answer: string;
|
||||
}
|
||||
|
||||
interface FaqBlockProps {
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
questions: FAQItem[];
|
||||
}
|
||||
|
||||
export const FaqBlock: React.FC<FaqBlockProps> = ({
|
||||
title = "Häufig gestellte Fragen",
|
||||
subtitle,
|
||||
questions
|
||||
}) => {
|
||||
if (!questions || questions.length === 0) return null;
|
||||
|
||||
return (
|
||||
<section className="py-12 md:py-16">
|
||||
<div className="max-w-3xl mx-auto">
|
||||
<div className="mb-10 text-center">
|
||||
{subtitle && (
|
||||
<span className="text-sm font-bold text-accent uppercase tracking-wider block mb-2">
|
||||
{subtitle}
|
||||
</span>
|
||||
)}
|
||||
<h2 className="text-3xl md:text-4xl font-bold text-text-primary">
|
||||
{title}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
{questions.map((item, index) => (
|
||||
<details
|
||||
key={index}
|
||||
className="group border border-neutral-200 bg-white rounded-xl overflow-hidden shadow-sm hover:shadow-md transition-shadow"
|
||||
>
|
||||
<summary className="flex items-center justify-between cursor-pointer p-6 font-semibold text-lg text-text-primary hover:text-primary transition-colors select-none">
|
||||
{item.question}
|
||||
<span className="ml-4 flex-shrink-0 transition-transform duration-300 group-open:-rotate-180 text-accent">
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5 7.5L10 12.5L15 7.5" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
|
||||
</svg>
|
||||
</span>
|
||||
</summary>
|
||||
<div className="px-6 pb-6 text-text-secondary leading-relaxed border-t border-neutral-100 pt-4 prose prose-p:my-2 prose-a:text-primary">
|
||||
{/* Parse simple HTML or just text if answer has formatting */}
|
||||
<div dangerouslySetInnerHTML={{ __html: item.answer }} />
|
||||
</div>
|
||||
</details>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Inject FAQ Schema automatically */}
|
||||
<JsonLd data={getFAQSchema(questions)} />
|
||||
</section>
|
||||
);
|
||||
};
|
||||
@@ -2,26 +2,26 @@
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import { MapPin, CheckCircle2, Factory, Zap } from 'lucide-react';
|
||||
import { MapPin, Factory, Zap, CheckCircle2 } from 'lucide-react';
|
||||
import Image from 'next/image';
|
||||
|
||||
interface Location {
|
||||
export interface Location {
|
||||
id: string;
|
||||
name: string;
|
||||
type: 'hq' | 'branch' | 'project';
|
||||
x: number; // percentage from left
|
||||
y: number; // percentage from top
|
||||
description?: string;
|
||||
x: number;
|
||||
y: number;
|
||||
description: string;
|
||||
details?: string[];
|
||||
}
|
||||
|
||||
const locations: Location[] = [
|
||||
const defaultLocations: Location[] = [
|
||||
{
|
||||
id: 'guben',
|
||||
name: 'Guben (Hauptsitz)',
|
||||
type: 'hq',
|
||||
x: 85, // approx East (adjusted to be inside map)
|
||||
y: 48, // approx Middle
|
||||
x: 85,
|
||||
y: 48,
|
||||
description: 'E-TIB GmbH Holding & Bohrtechnik GmbH',
|
||||
details: ['Zentrale Steuerung', 'Kabelleitungstiefbau', 'Maschinenpark'],
|
||||
},
|
||||
@@ -29,47 +29,77 @@ const locations: Location[] = [
|
||||
id: 'buelstedt',
|
||||
name: 'Bülstedt (Ingenieurgesellschaft)',
|
||||
type: 'branch',
|
||||
x: 37, // approx North-West
|
||||
y: 25, // approx North
|
||||
x: 37,
|
||||
y: 25,
|
||||
description: 'E-TIB Ingenieurgesellschaft mbH',
|
||||
details: ['Planung & Projektierung', 'Vermessung', 'Dokumentation'],
|
||||
},
|
||||
// Dummy Projects
|
||||
{
|
||||
id: 'project-1',
|
||||
name: '110kV Trasse München',
|
||||
id: 'spreewald',
|
||||
name: 'Spreewald (Projekt)',
|
||||
type: 'project',
|
||||
x: 58,
|
||||
y: 85,
|
||||
description: 'Horizontalspülbohrung & Netzanbindung',
|
||||
x: 82,
|
||||
y: 45,
|
||||
description: 'Breitbandausbau FTTC',
|
||||
},
|
||||
{
|
||||
id: 'project-2',
|
||||
name: 'Solarpark Hamburg',
|
||||
id: 'bomlitz',
|
||||
name: 'Bomlitz (Projekt)',
|
||||
type: 'project',
|
||||
x: 45,
|
||||
y: 18,
|
||||
description: 'Komplexe Querung unter Gewässer',
|
||||
y: 30,
|
||||
description: 'Breitbandausbau FTTH',
|
||||
},
|
||||
{
|
||||
id: 'project-3',
|
||||
name: 'Windpark NRW',
|
||||
id: 'forst',
|
||||
name: 'Forst (Projekt)',
|
||||
type: 'project',
|
||||
x: 20,
|
||||
x: 88,
|
||||
y: 50,
|
||||
description: 'Kabelpflugarbeiten & LWL',
|
||||
description: 'Neubau Kabeltrasse',
|
||||
},
|
||||
{
|
||||
id: 'project-4',
|
||||
name: 'Trassenausbau Leipzig',
|
||||
id: 'eisenhuettenstadt',
|
||||
name: 'Eisenhüttenstadt (Projekt)',
|
||||
type: 'project',
|
||||
x: 65,
|
||||
y: 55,
|
||||
description: 'Infrastrukturausbau',
|
||||
x: 85,
|
||||
y: 40,
|
||||
description: 'Kabelverbindung U30 - T10',
|
||||
},
|
||||
{
|
||||
id: 'goerne',
|
||||
name: 'Görne (Projekt)',
|
||||
type: 'project',
|
||||
x: 70,
|
||||
y: 35,
|
||||
description: 'Einspeisung PV-Anlage',
|
||||
}
|
||||
];
|
||||
|
||||
export function InteractiveGermanyMap() {
|
||||
interface Stat {
|
||||
value: string;
|
||||
suffix?: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
interface InteractiveGermanyMapProps {
|
||||
badge?: string;
|
||||
title?: React.ReactNode;
|
||||
description?: string;
|
||||
stats?: Stat[];
|
||||
locations?: Location[];
|
||||
}
|
||||
|
||||
export function InteractiveGermanyMap({
|
||||
badge = 'Einsatzgebiete',
|
||||
title = <>Deutschlandweit<br/>für Sie im Einsatz.</>,
|
||||
description = 'Von unseren strategischen Standorten in Guben und Bülstedt steuern und realisieren wir komplexe Infrastrukturprojekte im gesamten Bundesgebiet.',
|
||||
stats = [
|
||||
{ value: '100', suffix: '%', label: 'Überregionale Reichweite' },
|
||||
{ value: '2', suffix: '+', label: 'Operative Standorte' },
|
||||
],
|
||||
locations = defaultLocations
|
||||
}: InteractiveGermanyMapProps) {
|
||||
const [activeLocation, setActiveLocation] = useState<Location | null>(null);
|
||||
|
||||
const hq = locations.find((l) => l.type === 'hq');
|
||||
@@ -83,48 +113,41 @@ export function InteractiveGermanyMap() {
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-[#050B14] via-[#0A1322] to-[#050B14]" />
|
||||
<div className="absolute top-0 right-0 w-[800px] h-[800px] bg-primary/5 rounded-full blur-[120px] pointer-events-none translate-x-1/3 -translate-y-1/3" />
|
||||
|
||||
<div className="relative z-10 grid grid-cols-1 lg:grid-cols-12 gap-12 items-center min-h-[600px] p-8 md:p-16 lg:p-20">
|
||||
<div className="relative z-10 grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-12 gap-12 items-center min-h-[600px] p-8 md:p-12 lg:p-16">
|
||||
|
||||
{/* Content Left */}
|
||||
<div className="lg:col-span-5 text-white">
|
||||
<div className="xl:col-span-5 text-white z-20">
|
||||
<div className="inline-flex items-center gap-2 px-3 py-1.5 rounded-full bg-primary/10 border border-primary/20 text-primary text-xs font-bold uppercase tracking-wider mb-8">
|
||||
<MapPin className="w-4 h-4" />
|
||||
<span>Einsatzgebiete</span>
|
||||
<span>{badge}</span>
|
||||
</div>
|
||||
|
||||
<h3 className="font-heading text-4xl md:text-5xl lg:text-6xl font-extrabold mb-6 leading-[1.1] text-transparent bg-clip-text bg-gradient-to-r from-white to-white/70">
|
||||
Deutschlandweit<br/>für Sie im Einsatz.
|
||||
<h3 className="font-heading text-4xl lg:text-5xl xl:text-6xl font-extrabold mb-6 leading-[1.1] text-transparent bg-clip-text bg-gradient-to-r from-white to-white/70 break-words [hyphens:auto]">
|
||||
{title}
|
||||
</h3>
|
||||
|
||||
<p className="text-white/60 text-lg mb-12 leading-relaxed">
|
||||
Von unseren strategischen Standorten in Guben und Bülstedt steuern und realisieren wir komplexe Infrastrukturprojekte im gesamten Bundesgebiet.
|
||||
{description}
|
||||
</p>
|
||||
|
||||
{/* Industrial Stats Grid */}
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="bg-white/5 border border-white/10 rounded-2xl p-6 backdrop-blur-md relative overflow-hidden group">
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-primary/10 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
|
||||
<div className="relative z-10">
|
||||
<div className="text-4xl font-extrabold text-white mb-1 flex items-baseline gap-1">
|
||||
100<span className="text-xl text-primary">%</span>
|
||||
{stats.map((stat, i) => (
|
||||
<div key={i} className="bg-white/5 border border-white/10 rounded-2xl p-6 backdrop-blur-md relative overflow-hidden group">
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-primary/10 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
|
||||
<div className="relative z-10">
|
||||
<div className="text-4xl font-extrabold text-white mb-1 flex items-baseline gap-1">
|
||||
{stat.value}<span className="text-xl text-primary">{stat.suffix}</span>
|
||||
</div>
|
||||
<div className="text-sm text-white/50 font-medium">{stat.label}</div>
|
||||
</div>
|
||||
<div className="text-sm text-white/50 font-medium">Überregionale Reichweite</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-white/5 border border-white/10 rounded-2xl p-6 backdrop-blur-md relative overflow-hidden group">
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-primary/10 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
|
||||
<div className="relative z-10">
|
||||
<div className="text-4xl font-extrabold text-white mb-1 flex items-baseline gap-1">
|
||||
2<span className="text-xl text-primary">+</span>
|
||||
</div>
|
||||
<div className="text-sm text-white/50 font-medium">Operative Standorte</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Map Right */}
|
||||
<div className="lg:col-span-7 relative flex items-center justify-center lg:justify-end mt-12 lg:mt-0">
|
||||
<div className="xl:col-span-7 relative flex items-center justify-center lg:justify-end mt-8 lg:mt-0 z-10">
|
||||
{/* Map Container - Enforce strict aspect ratio matching the SVG (1024x1024) */}
|
||||
<div className="relative w-full max-w-[600px] aspect-square z-10">
|
||||
{/* Map SVG */}
|
||||
|
||||
@@ -32,7 +32,7 @@ export function Footer({ companyInfo }: FooterProps) {
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-white/[0.04] to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-700" />
|
||||
|
||||
<div className="space-y-4 md:space-y-6 relative z-10">
|
||||
<TransitionLink href={`/${locale}`} className="relative block h-12 md:h-14 w-40 md:w-48 mb-4 md:mb-6 group/logo">
|
||||
<TransitionLink href={`/${locale}`} className="relative block h-12 md:h-14 w-40 md:w-48 mb-4 md:mb-6 group/logo cursor-pointer">
|
||||
<Image
|
||||
src="/assets/logo-white.png"
|
||||
alt="E-TIB Gruppe"
|
||||
@@ -59,11 +59,11 @@ export function Footer({ companyInfo }: FooterProps) {
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-3 md:gap-4">
|
||||
<a href={`mailto:${companyInfo.contactEmail}`} className="flex flex-col gap-2 p-4 rounded-2xl bg-white/[0.03] border border-white/[0.05] hover:bg-white/[0.08] hover:border-primary/30 transition-all group/contact">
|
||||
<a href={`mailto:${companyInfo.contactEmail}`} className="flex flex-col gap-2 p-4 rounded-2xl bg-white/[0.03] border border-white/[0.05] hover:bg-white/[0.08] hover:border-primary/30 transition-all group/contact cursor-pointer">
|
||||
<p className="text-xs text-white/40 uppercase tracking-wider font-heading">E-Mail</p>
|
||||
<p className="font-medium text-white/90 group-hover/contact:text-primary transition-colors truncate">{companyInfo.contactEmail}</p>
|
||||
</a>
|
||||
<a href={`tel:${companyInfo.contactPhone.replace(/\s+/g, '')}`} className="flex flex-col gap-2 p-4 rounded-2xl bg-white/[0.03] border border-white/[0.05] hover:bg-white/[0.08] hover:border-primary/30 transition-all group/contact">
|
||||
<a href={`tel:${companyInfo.contactPhone.replace(/\s+/g, '')}`} className="flex flex-col gap-2 p-4 rounded-2xl bg-white/[0.03] border border-white/[0.05] hover:bg-white/[0.08] hover:border-primary/30 transition-all group/contact cursor-pointer">
|
||||
<p className="text-xs text-white/40 uppercase tracking-wider font-heading">{locale === 'de' ? 'Telefon' : 'Phone'}</p>
|
||||
<p className="font-medium text-white/90 group-hover/contact:text-primary transition-colors truncate">{companyInfo.contactPhone}</p>
|
||||
</a>
|
||||
@@ -91,7 +91,7 @@ export function Footer({ companyInfo }: FooterProps) {
|
||||
{ label: locale === 'de' ? 'Kontakt' : 'Contact', href: `/${locale}/${locale === 'de' ? 'kontakt' : 'contact'}` },
|
||||
].map((link) => (
|
||||
<li key={link.href}>
|
||||
<TransitionLink href={link.href} className="group/link flex items-center text-white/60 hover:text-white transition-colors py-1">
|
||||
<TransitionLink href={link.href} className="group/link flex items-center text-white/60 hover:text-white transition-colors py-1 cursor-pointer">
|
||||
<span className="w-0 h-px bg-primary mr-0 group-hover/link:w-4 group-hover/link:mr-3 transition-all duration-300" />
|
||||
<span className="font-medium">{link.label}</span>
|
||||
</TransitionLink>
|
||||
@@ -114,7 +114,7 @@ export function Footer({ companyInfo }: FooterProps) {
|
||||
{ label: locale === 'de' ? 'AGB' : 'Terms', href: `/${locale}/${locale === 'de' ? 'agb' : 'terms'}` },
|
||||
].map((link) => (
|
||||
<li key={link.href}>
|
||||
<TransitionLink href={link.href} className="group/link flex items-center text-white/50 hover:text-white transition-colors py-1">
|
||||
<TransitionLink href={link.href} className="group/link flex items-center text-white/50 hover:text-white transition-colors py-1 cursor-pointer">
|
||||
<span className="w-0 h-px bg-white/30 mr-0 group-hover/link:w-3 group-hover/link:mr-3 transition-all duration-300" />
|
||||
<span className="font-medium">{link.label}</span>
|
||||
</TransitionLink>
|
||||
|
||||
@@ -178,3 +178,26 @@ description: Willkommen bei E-TIB GmbH
|
||||
}
|
||||
]}
|
||||
/>
|
||||
|
||||
<FaqBlock
|
||||
title="Häufig gestellte Fragen"
|
||||
subtitle="Wissenswertes"
|
||||
questions={[
|
||||
{
|
||||
question: "Was macht die E-TIB GmbH?",
|
||||
answer: "Die E-TIB GmbH ist spezialisiert auf den Leitungs- und Kabeltiefbau. Zu den Kernleistungen zählen der klassische Kabelbau, hochpräzise Horizontalspülbohrungen, Kabelpflugarbeiten sowie Elektromontagen bis 110 kV. Zusammen mit unseren Tochtergesellschaften decken wir auch die komplette Planung und Dokumentation von Infrastrukturprojekten ab."
|
||||
},
|
||||
{
|
||||
question: "Welche Vorteile bietet das Horizontalspülbohrverfahren (Bohrtechnik)?",
|
||||
answer: "Die Horizontalspülbohrung ist ein grabenloses Verfahren zur unterirdischen Verlegung von Kabeln und Rohren. Der größte Vorteil ist die oberflächenschonende Arbeitsweise: Flüsse, Autobahnen, Bahntrassen oder Naturschutzgebiete können gekreuzt werden, ohne den Verkehr oder die Umwelt zu beeinträchtigen. Dies spart erhebliche Kosten bei der Oberflächenwiederherstellung."
|
||||
},
|
||||
{
|
||||
question: "Seit wann gibt es die E-TIB GmbH und wie groß ist das Team?",
|
||||
answer: "Die E-TIB GmbH wurde im Dezember 2015 in Guben gegründet. Heute beschäftigt die Unternehmensgruppe über 50 qualifizierte Mitarbeiter, die komplexe Infrastruktur- und Tiefbauprojekte für Energieversorger und Telekommunikationsanbieter bundesweit realisieren."
|
||||
},
|
||||
{
|
||||
question: "Bieten Sie auch die Planung von Netzanschlüssen an?",
|
||||
answer: "Ja, über die E-TIB Ingenieurgesellschaft mbH übernehmen wir die komplette Genehmigungs- und Ausführungsplanung. Dies beinhaltet Elektro- und Netzanschlussplanungen, Machbarkeitsstudien sowie die finale digitale Bestandsdokumentation per GIS."
|
||||
}
|
||||
]}
|
||||
/>
|
||||
|
||||
@@ -135,3 +135,30 @@ layout: "fullBleed"
|
||||
}
|
||||
]}
|
||||
/>
|
||||
|
||||
<JsonLd data={[
|
||||
{
|
||||
"@type": "Service",
|
||||
"name": "Kabelbau",
|
||||
"description": "Klassischer Grabenbau und professionelle Verlegung von Mittel- und Niederspannungskabeln.",
|
||||
"provider": { "@type": "Organization", "name": "E-TIB GmbH" }
|
||||
},
|
||||
{
|
||||
"@type": "Service",
|
||||
"name": "Horizontalspülbohrungen",
|
||||
"description": "Horizontalspülbohrverfahren (HDD) für grabenlose, oberflächenschonende Verlegung.",
|
||||
"provider": { "@type": "Organization", "name": "E-TIB GmbH" }
|
||||
},
|
||||
{
|
||||
"@type": "Service",
|
||||
"name": "Glasfaserausbau",
|
||||
"description": "Ausbau von zukunftssicheren Breitbandnetzen (FTTX) und Glasfaser-Kabelmontagen.",
|
||||
"provider": { "@type": "Organization", "name": "E-TIB GmbH" }
|
||||
},
|
||||
{
|
||||
"@type": "Service",
|
||||
"name": "Planung und Vermessung",
|
||||
"description": "Genehmigungs- und Ausführungsplanung, Elektro- und Netzanschlussplanung, sowie digitale Bestandsdokumentation per GIS.",
|
||||
"provider": { "@type": "Organization", "name": "E-TIB GmbH" }
|
||||
}
|
||||
]} />
|
||||
|
||||
@@ -27,3 +27,72 @@ layout: "fullBleed"
|
||||
</div>
|
||||
|
||||
<CallToAction />
|
||||
|
||||
<JsonLd data={[
|
||||
{
|
||||
"@type": "Event",
|
||||
"name": "Intersolar München",
|
||||
"startDate": "2026-06-19",
|
||||
"endDate": "2026-06-21",
|
||||
"eventAttendanceMode": "https://schema.org/OfflineEventAttendanceMode",
|
||||
"eventStatus": "https://schema.org/EventScheduled",
|
||||
"location": {
|
||||
"@type": "Place",
|
||||
"name": "Messe München",
|
||||
"address": {
|
||||
"@type": "PostalAddress",
|
||||
"addressLocality": "München",
|
||||
"addressCountry": "DE"
|
||||
}
|
||||
},
|
||||
"organizer": {
|
||||
"@type": "Organization",
|
||||
"name": "E-TIB GmbH",
|
||||
"url": "https://e-tib.com"
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "Event",
|
||||
"name": "Windenergietage Linstow",
|
||||
"startDate": "2026-11-04",
|
||||
"endDate": "2026-11-06",
|
||||
"eventAttendanceMode": "https://schema.org/OfflineEventAttendanceMode",
|
||||
"eventStatus": "https://schema.org/EventScheduled",
|
||||
"location": {
|
||||
"@type": "Place",
|
||||
"name": "Van der Valk Resort Linstow",
|
||||
"address": {
|
||||
"@type": "PostalAddress",
|
||||
"addressLocality": "Linstow",
|
||||
"addressCountry": "DE"
|
||||
}
|
||||
},
|
||||
"organizer": {
|
||||
"@type": "Organization",
|
||||
"name": "E-TIB GmbH",
|
||||
"url": "https://e-tib.com"
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "Event",
|
||||
"name": "Kabelwerkstatt Wiesbaden",
|
||||
"startDate": "2026-12-02",
|
||||
"endDate": "2026-12-03",
|
||||
"eventAttendanceMode": "https://schema.org/OfflineEventAttendanceMode",
|
||||
"eventStatus": "https://schema.org/EventScheduled",
|
||||
"location": {
|
||||
"@type": "Place",
|
||||
"name": "RheinMain CongressCenter",
|
||||
"address": {
|
||||
"@type": "PostalAddress",
|
||||
"addressLocality": "Wiesbaden",
|
||||
"addressCountry": "DE"
|
||||
}
|
||||
},
|
||||
"organizer": {
|
||||
"@type": "Organization",
|
||||
"name": "E-TIB GmbH",
|
||||
"url": "https://e-tib.com"
|
||||
}
|
||||
}
|
||||
]} />
|
||||
|
||||
@@ -30,10 +30,10 @@ description: Welcome to E-TIB GmbH
|
||||
backgroundImage: "/assets/photos/DSC01137.JPG"
|
||||
},
|
||||
{
|
||||
title: "NEMO GmbH",
|
||||
description: "The specialist for planning and implementation of sustainable energy projects - with a focus on solar energy.",
|
||||
icon: "M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z",
|
||||
url: "https://www.nemo-gmbh.de/",
|
||||
title: "E-TIB Bohrtechnik GmbH",
|
||||
description: "Highest precision underground: We specialize in complex horizontal directional drilling for all infrastructure networks.",
|
||||
icon: "M19 14l-7 7m0 0l-7-7m7 7V3",
|
||||
url: "https://www.e-tib.com/bohrtechnik",
|
||||
backgroundImage: "/assets/photos/DJI_0048.JPG"
|
||||
}
|
||||
]}
|
||||
|
||||
@@ -59,24 +59,102 @@ layout: "fullBleed"
|
||||
title="Milestones of Development"
|
||||
milestones={[
|
||||
{
|
||||
date: '2015',
|
||||
date: '16.12.2015',
|
||||
year: '2015',
|
||||
title: 'Foundation of E-TIB GmbH',
|
||||
desc: 'Founded in Guben, Brandenburg, with a focus on civil engineering and cable assembly.'
|
||||
desc: 'Execution of electrical infrastructure projects, cable civil engineering, and horizontal directional drilling.',
|
||||
iconName: 'Building2'
|
||||
},
|
||||
{
|
||||
date: 'Growth',
|
||||
title: 'Expansion of Competencies',
|
||||
desc: 'Consistent expansion of services to include horizontal directional drilling and cable plowing.'
|
||||
date: '04.02.2019',
|
||||
year: '2019',
|
||||
title: 'Foundation of E-TIB Ingenieurgesellschaft',
|
||||
desc: 'Approval and execution planning, complex crossings, and grid connection planning.',
|
||||
iconName: 'Compass'
|
||||
},
|
||||
{
|
||||
date: 'Corporate Group',
|
||||
title: 'Merger',
|
||||
desc: 'Pooling of specialized departments with NEMO GmbH and E-TIB Ingenieurgesellschaft mbH.'
|
||||
date: '14.11.2019',
|
||||
year: '2019',
|
||||
title: 'Foundation of E-TIB Verwaltung GmbH',
|
||||
desc: 'Central services, acquisition, leasing, and management of real estate and machinery.',
|
||||
iconName: 'Layers'
|
||||
},
|
||||
{
|
||||
date: 'Today',
|
||||
title: 'The E-TIB Group',
|
||||
desc: 'A strong network with over 50 employees for nationwide infrastructure projects.'
|
||||
date: '21.10.2025',
|
||||
year: '2025',
|
||||
title: 'Foundation of E-TIB Bohrtechnik GmbH',
|
||||
desc: 'Specialization in precise horizontal directional drilling in all soil classes.',
|
||||
iconName: 'ArrowDownToLine'
|
||||
}
|
||||
]}
|
||||
/>
|
||||
|
||||
<InteractiveGermanyMap
|
||||
badge="Operating Areas"
|
||||
title={<>Nationwide<br/>at your service.</>}
|
||||
description="From our strategic locations in Guben and Bülstedt, we control and realize complex infrastructure projects across the entire federal territory."
|
||||
stats={[
|
||||
{ value: '100', suffix: '%', label: 'Nationwide Reach' },
|
||||
{ value: '2', suffix: '+', label: 'Operating Locations' }
|
||||
]}
|
||||
locations={[
|
||||
{
|
||||
id: 'guben',
|
||||
name: 'Guben (Headquarters)',
|
||||
type: 'hq',
|
||||
x: 85,
|
||||
y: 48,
|
||||
description: 'E-TIB GmbH Holding & Bohrtechnik GmbH',
|
||||
details: ['Central Management', 'Cable Civil Engineering', 'Machinery Park']
|
||||
},
|
||||
{
|
||||
id: 'buelstedt',
|
||||
name: 'Bülstedt (Engineering Firm)',
|
||||
type: 'branch',
|
||||
x: 37,
|
||||
y: 25,
|
||||
description: 'E-TIB Ingenieurgesellschaft mbH',
|
||||
details: ['Planning & Projecting', 'Surveying', 'Documentation']
|
||||
},
|
||||
{
|
||||
id: 'spreewald',
|
||||
name: 'Spreewald (Project)',
|
||||
type: 'project',
|
||||
x: 82,
|
||||
y: 45,
|
||||
description: 'Broadband Expansion FTTC'
|
||||
},
|
||||
{
|
||||
id: 'bomlitz',
|
||||
name: 'Bomlitz (Project)',
|
||||
type: 'project',
|
||||
x: 45,
|
||||
y: 30,
|
||||
description: 'Broadband Expansion FTTH'
|
||||
},
|
||||
{
|
||||
id: 'forst',
|
||||
name: 'Forst (Project)',
|
||||
type: 'project',
|
||||
x: 88,
|
||||
y: 50,
|
||||
description: 'New Cable Route Construction'
|
||||
},
|
||||
{
|
||||
id: 'eisenhuettenstadt',
|
||||
name: 'Eisenhüttenstadt (Project)',
|
||||
type: 'project',
|
||||
x: 85,
|
||||
y: 40,
|
||||
description: 'Cable Connection U30 - T10'
|
||||
},
|
||||
{
|
||||
id: 'goerne',
|
||||
name: 'Görne (Project)',
|
||||
type: 'project',
|
||||
x: 70,
|
||||
y: 35,
|
||||
description: 'PV System Feed-in'
|
||||
}
|
||||
]}
|
||||
/>
|
||||
@@ -101,10 +179,10 @@ layout: "fullBleed"
|
||||
backgroundImage: "/assets/photos/DSC01137.JPG"
|
||||
},
|
||||
{
|
||||
title: "NEMO GmbH",
|
||||
description: "The specialist for planning and implementation of sustainable energy projects - with a focus on solar energy.",
|
||||
icon: "M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z",
|
||||
url: "https://www.nemo-gmbh.de/",
|
||||
title: "E-TIB Bohrtechnik GmbH",
|
||||
description: "Highest precision underground: We specialize in complex horizontal directional drilling for all infrastructure networks.",
|
||||
icon: "M19 14l-7 7m0 0l-7-7m7 7V3",
|
||||
url: "https://www.e-tib.com/bohrtechnik",
|
||||
backgroundImage: "/assets/photos/DJI_0048.JPG"
|
||||
}
|
||||
]}
|
||||
|
||||
19
danny_mail_draft.txt
Normal file
19
danny_mail_draft.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
Betreff: Testserver steht bereit – E-TIB Website v1 🚀
|
||||
|
||||
Hi Danny,
|
||||
|
||||
kurzes Update von meiner Seite: Der Testserver mit dem ersten Entwurf der neuen Website steht bereit! Schau dir das Ganze gerne in Ruhe an: https://test.e-tib.com (Passwort: lassmichrein)
|
||||
|
||||
Ich habe den Content komplett auf Basis eures aktuellen Briefings glattgezogen. Das bedeutet konkret:
|
||||
- Die alte "NEMO GmbH" Struktur ist restlos raus.
|
||||
- Eure aktuelle Aufstellung (E-TIB GmbH als Holding, dazu E-TIB Verwaltung GmbH und Bohrtechnik GmbH) ist jetzt korrekt abgebildet.
|
||||
- Die Timeline und Gründungsdaten (inklusive 2024 Holding) sind auf dem neuesten Stand.
|
||||
- Das Leistungsportfolio habe ich exakt auf eure 10 Kernkompetenzen (Kabelpflug, Horizontalspülbohren, komplexe Querungen etc.) fokussiert.
|
||||
- Impressum und Messe-Daten (Intersolar, Windenergietage, Kabelwerkstatt) sind ebenfalls aktualisiert.
|
||||
|
||||
Zum Design noch ein paar Worte: Ich habe mich wie besprochen an einem minimalistischen, aber sehr hochwertigen Look orientiert. Die Seite ist bewusst extrem aufgeräumt und strukturiert (z.B. durch die übersichtliche Kachel-Optik für eure Kompetenzen), damit Besucher sofort verstehen, was ihr anbietet – egal ob sie am großen PC sitzen oder auf dem Handy scrollen. Auch das Video auf der Startseite habe ich als starken visuellen Aufhänger eingebaut, genau wie du es dir als Referenz gewünscht hast.
|
||||
Wichtig als Randnotiz: Der aktuelle Stand ist technisch gesehen noch "Work in Progress". Ich bin gerade noch dabei, die letzten Optimierungen für Performance, SEO und mobile Responsivität vorzunehmen, damit am Ende alles perfekt flutscht.
|
||||
|
||||
Da eine gute Website meiner Meinung nach absolut selbsterklärend sein muss, gebe ich sie euch jetzt einfach mal direkt zum selbst Durchklicken. Sammelt gerne euer Feedback und gebt mir Bescheid, wo wir noch nachjustieren sollen. Wenn es euch lieber ist, können wir uns das Ganze natürlich auch gerne gemeinsam in einem Teams-Call durchgehen.
|
||||
|
||||
Beste Grüße!
|
||||
5
instrumentation-client.ts
Normal file
5
instrumentation-client.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
// Sentry initialization move to GlitchtipErrorReportingService to allow lazy-loading
|
||||
// for PageSpeed 100 optimizations. This file is now empty to prevent the SDK
|
||||
// from being included in the initial JS bundle.
|
||||
import * as Sentry from '@sentry/nextjs';
|
||||
export const onRouterTransitionStart = Sentry.captureRouterTransitionStart;
|
||||
25
instrumentation.ts
Normal file
25
instrumentation.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import * as Sentry from '@sentry/nextjs';
|
||||
|
||||
/**
|
||||
* Next.js will call this on boot for the active runtime.
|
||||
*/
|
||||
export async function register() {
|
||||
if (process.env.NEXT_RUNTIME === 'nodejs') {
|
||||
await import('./sentry.server.config');
|
||||
|
||||
// Initialize server services on boot
|
||||
// We do this AFTER Sentry to ensure errors during service init are caught
|
||||
const { getConfig } = await import('@/lib/config');
|
||||
getConfig(); // Trigger validation
|
||||
|
||||
const { getServerAppServices } = await import('@/lib/services/create-services.server');
|
||||
getServerAppServices();
|
||||
}
|
||||
|
||||
if (process.env.NEXT_RUNTIME === 'edge') {
|
||||
await import('./sentry.edge.config');
|
||||
}
|
||||
}
|
||||
|
||||
// Capture errors from Server Components, middleware and route handlers.
|
||||
export const onRequestError = Sentry.captureRequestError;
|
||||
@@ -34,3 +34,85 @@ export const getBreadcrumbSchema = (items: { name: string; item: string }[]) =>
|
||||
item: item.item.startsWith('http') ? item.item : `${SITE_URL}${item.item}`,
|
||||
})),
|
||||
});
|
||||
|
||||
export const getLocalBusinessSchema = () => ({
|
||||
'@context': 'https://schema.org' as const,
|
||||
'@type': 'LocalBusiness' as const,
|
||||
name: 'E-TIB GmbH',
|
||||
url: SITE_URL,
|
||||
logo: LOGO_URL,
|
||||
image: LOGO_URL,
|
||||
description: 'Ihr Partner für Kabelleitungstiefbau, Horizontalspülbohrungen, Planung und Vermessung in Guben und überregional.',
|
||||
telephone: '+49-15207230518',
|
||||
email: 'd.joseph@e-tib.com',
|
||||
address: {
|
||||
'@type': 'PostalAddress' as const,
|
||||
streetAddress: 'Gewerbestraße 22',
|
||||
addressLocality: 'Guben',
|
||||
postalCode: '03172',
|
||||
addressCountry: 'DE',
|
||||
},
|
||||
geo: {
|
||||
'@type': 'GeoCoordinates' as const,
|
||||
latitude: 51.9547, // Approx coordinates for Guben area
|
||||
longitude: 14.7175,
|
||||
},
|
||||
openingHoursSpecification: [
|
||||
{
|
||||
'@type': 'OpeningHoursSpecification' as const,
|
||||
dayOfWeek: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
|
||||
opens: '08:00',
|
||||
closes: '17:00',
|
||||
},
|
||||
],
|
||||
sameAs: ['https://www.instagram.com/me.and.eloise/'],
|
||||
});
|
||||
|
||||
export const getFAQSchema = (questions: { question: string; answer: string }[]) => ({
|
||||
'@context': 'https://schema.org' as const,
|
||||
'@type': 'FAQPage' as const,
|
||||
mainEntity: questions.map((q) => ({
|
||||
'@type': 'Question' as const,
|
||||
name: q.question,
|
||||
acceptedAnswer: {
|
||||
'@type': 'Answer' as const,
|
||||
text: q.answer,
|
||||
},
|
||||
})),
|
||||
});
|
||||
|
||||
export const getServiceSchema = (serviceName: string, description: string, image?: string) => ({
|
||||
'@context': 'https://schema.org' as const,
|
||||
'@type': 'Service' as const,
|
||||
name: serviceName,
|
||||
description: description,
|
||||
provider: {
|
||||
'@type': 'Organization' as const,
|
||||
name: 'E-TIB GmbH',
|
||||
},
|
||||
...(image && { image }),
|
||||
});
|
||||
|
||||
export const getEventSchema = (event: { name: string; startDate: string; endDate?: string; locationName: string; locationAddress?: string; url?: string }) => ({
|
||||
'@context': 'https://schema.org' as const,
|
||||
'@type': 'Event' as const,
|
||||
name: event.name,
|
||||
startDate: event.startDate,
|
||||
...(event.endDate && { endDate: event.endDate }),
|
||||
location: {
|
||||
'@type': 'Place' as const,
|
||||
name: event.locationName,
|
||||
...(event.locationAddress && {
|
||||
address: {
|
||||
'@type': 'PostalAddress' as const,
|
||||
streetAddress: event.locationAddress,
|
||||
},
|
||||
}),
|
||||
},
|
||||
organizer: {
|
||||
'@type': 'Organization' as const,
|
||||
name: 'E-TIB GmbH',
|
||||
url: SITE_URL,
|
||||
},
|
||||
...(event.url && { url: event.url }),
|
||||
});
|
||||
|
||||
2
next-env.d.ts
vendored
2
next-env.d.ts
vendored
@@ -1,6 +1,6 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
import "./.next/dev/types/routes.d.ts";
|
||||
import "./.next/types/routes.d.ts";
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
||||
|
||||
@@ -9,8 +9,8 @@ const isProd = process.env.NODE_ENV === 'production';
|
||||
const nextConfig = {
|
||||
transpilePackages: ['react-image-crop', '@react-three/fiber'],
|
||||
onDemandEntries: {
|
||||
// Keep compiled pages/routes in memory for 5 minutes (reduced from 25m to prevent OOM)
|
||||
maxInactiveAge: 5 * 60 * 1000,
|
||||
// Keep compiled pages/routes in memory for 1 minute (optimized for memory usage)
|
||||
maxInactiveAge: 60 * 1000,
|
||||
// Keep up to 2 pages in the dev buffer (reduced from 10 to prevent OOM)
|
||||
pagesBufferLength: 2,
|
||||
},
|
||||
@@ -507,6 +507,14 @@ const nextConfig = {
|
||||
source: '/en/agbs',
|
||||
destination: '/en/terms',
|
||||
},
|
||||
{
|
||||
source: '/errors/:path*',
|
||||
destination: `${(function() {
|
||||
let glitchtipUrl = process.env.SENTRY_DSN ? new URL(process.env.SENTRY_DSN).origin : 'https://errors.infra.mintel.me';
|
||||
if (glitchtipUrl && !glitchtipUrl.startsWith('http')) glitchtipUrl = 'https://' + glitchtipUrl;
|
||||
return new URL(glitchtipUrl).origin;
|
||||
})()}/:path*`,
|
||||
},
|
||||
],
|
||||
afterFiles: [],
|
||||
fallback: [],
|
||||
|
||||
15
sentry.edge.config.ts
Normal file
15
sentry.edge.config.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import * as Sentry from '@sentry/nextjs';
|
||||
|
||||
const dsn = process.env.SENTRY_DSN;
|
||||
const isProd = process.env.NODE_ENV === 'production';
|
||||
|
||||
Sentry.init({
|
||||
dsn,
|
||||
enabled: isProd && Boolean(dsn),
|
||||
|
||||
// Adjust this value in production, or use tracesSampler for greater control
|
||||
tracesSampleRate: 1,
|
||||
|
||||
// Setting this option to true will print useful information to the console while you're setting up Sentry.
|
||||
debug: false,
|
||||
});
|
||||
15
sentry.server.config.ts
Normal file
15
sentry.server.config.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import * as Sentry from '@sentry/nextjs';
|
||||
|
||||
const dsn = process.env.SENTRY_DSN;
|
||||
const isProd = process.env.NODE_ENV === 'production';
|
||||
|
||||
Sentry.init({
|
||||
dsn,
|
||||
enabled: isProd && Boolean(dsn),
|
||||
|
||||
// Adjust this value in production, or use tracesSampler for greater control
|
||||
tracesSampleRate: 1,
|
||||
|
||||
// Setting this option to true will print useful information to the console while you're setting up Sentry.
|
||||
debug: false,
|
||||
});
|
||||
@@ -1,5 +0,0 @@
|
||||
export function register() {
|
||||
if (process.env.NEXT_RUNTIME === 'nodejs') {
|
||||
console.log('[Instrumentation] Server-side registration active');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user