feat: Integrate Directus CMS, add i18n with next-intl, and configure project tooling with pnpm, husky, and commitlint.**
This commit is contained in:
108
app/[locale]/agb/page.tsx
Normal file
108
app/[locale]/agb/page.tsx
Normal file
@@ -0,0 +1,108 @@
|
||||
import { Download } from "lucide-react";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
export default function AGB() {
|
||||
const filePath = path.join(process.cwd(), "context/agbs.md");
|
||||
const fileContent = fs.readFileSync(filePath, "utf8");
|
||||
|
||||
// Split by double newlines to get major blocks (headers + their first paragraphs, or subsequent paragraphs)
|
||||
const blocks = fileContent
|
||||
.split(/\n\s*\n/)
|
||||
.map((b) => b.trim())
|
||||
.filter((b) => b !== "");
|
||||
|
||||
const title = blocks[0] || "Liefer- und Zahlungsbedingungen";
|
||||
const stand = blocks[1] || "Stand Januar 2026";
|
||||
|
||||
const sections: { title: string; content: string[] }[] = [];
|
||||
let currentSection: { title: string; content: string[] } | null = null;
|
||||
|
||||
// Skip title and stand
|
||||
blocks.slice(2).forEach((block) => {
|
||||
const lines = block
|
||||
.split("\n")
|
||||
.map((l) => l.trim())
|
||||
.filter((l) => l !== "");
|
||||
if (lines.length === 0) return;
|
||||
|
||||
const firstLine = lines[0];
|
||||
|
||||
if (/^\d+\./.test(firstLine)) {
|
||||
// New section
|
||||
if (currentSection) sections.push(currentSection);
|
||||
|
||||
currentSection = { title: firstLine, content: [] };
|
||||
|
||||
// If there are more lines in this block, they form the first paragraph(s)
|
||||
if (lines.length > 1) {
|
||||
// Join subsequent lines as they might be part of the same paragraph
|
||||
// In this MD, we'll assume lines in the same block belong together
|
||||
// unless they are clearly separate paragraphs (but we already split by double newline)
|
||||
const remainingText = lines.slice(1).join(" ");
|
||||
if (remainingText) currentSection.content.push(remainingText);
|
||||
}
|
||||
} else if (currentSection) {
|
||||
// Continuation of current section
|
||||
const blockText = lines.join(" ");
|
||||
if (blockText) currentSection.content.push(blockText);
|
||||
}
|
||||
});
|
||||
if (currentSection) sections.push(currentSection);
|
||||
|
||||
// The last block is the footer
|
||||
const footer = blocks[blocks.length - 1];
|
||||
if (sections.length > 0) {
|
||||
const lastSection = sections[sections.length - 1];
|
||||
if (lastSection.content.includes(footer) || lastSection.title === footer) {
|
||||
lastSection.content = lastSection.content.filter((c) => c !== footer);
|
||||
if (sections[sections.length - 1].title === footer) {
|
||||
sections.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="bg-slate-50 min-h-screen pt-40 pb-20">
|
||||
<div className="container-custom">
|
||||
<div className="max-w-4xl mx-auto bg-white p-8 md:p-12 rounded-[2.5rem] shadow-sm border border-slate-100">
|
||||
<div className="flex flex-col md:flex-row md:items-center justify-between gap-6 mb-8">
|
||||
<div>
|
||||
<h1 className="text-4xl font-extrabold text-primary mb-2">
|
||||
{title}
|
||||
</h1>
|
||||
<p className="text-slate-500 font-medium">{stand}</p>
|
||||
</div>
|
||||
<a
|
||||
href="/assets/AGB MB Grid 1-2026.pdf"
|
||||
download
|
||||
className="btn-primary !py-3 !px-6 flex items-center gap-2"
|
||||
>
|
||||
<Download size={18} />
|
||||
Als PDF herunterladen
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div className="space-y-8 text-slate-600 leading-relaxed">
|
||||
{sections.map((section, index) => (
|
||||
<div key={index}>
|
||||
<h2 className="text-2xl font-bold text-primary mb-4">
|
||||
{section.title}
|
||||
</h2>
|
||||
<div className="space-y-4">
|
||||
{section.content.map((paragraph, pIndex) => (
|
||||
<p key={pIndex}>{paragraph}</p>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
<div className="pt-8 border-t border-slate-100">
|
||||
<p className="font-bold text-primary">{footer}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
66
app/[locale]/datenschutz/page.tsx
Normal file
66
app/[locale]/datenschutz/page.tsx
Normal file
@@ -0,0 +1,66 @@
|
||||
export default function Privacy() {
|
||||
return (
|
||||
<div className="bg-slate-50 min-h-screen pt-40 pb-20">
|
||||
<div className="container-custom">
|
||||
<div className="max-w-4xl mx-auto bg-white p-8 md:p-12 rounded-[2.5rem] shadow-sm border border-slate-100">
|
||||
<h1 className="text-4xl font-extrabold text-primary mb-8">
|
||||
Datenschutzerklärung
|
||||
</h1>
|
||||
|
||||
<div className="space-y-8 text-slate-600 leading-relaxed">
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold text-primary mb-4">
|
||||
1. Datenschutz auf einen Blick
|
||||
</h2>
|
||||
<p>
|
||||
Wir nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir
|
||||
behandeln Ihre personenbezogenen Daten vertraulich und
|
||||
entsprechend der gesetzlichen Datenschutzvorschriften sowie
|
||||
dieser Datenschutzerklärung.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold text-primary mb-4">
|
||||
2. Hosting
|
||||
</h2>
|
||||
<p>
|
||||
Unsere Website wird bei Hetzner Online GmbH gehostet. Der
|
||||
Serverstandort ist Deutschland. Wir haben einen Vertrag über
|
||||
Auftragsverarbeitung (AVV) mit Hetzner geschlossen.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold text-primary mb-4">
|
||||
3. Kontaktformular
|
||||
</h2>
|
||||
<p>
|
||||
Wenn Sie uns per Kontaktformular Anfragen zukommen lassen,
|
||||
werden Ihre Angaben aus dem Anfrageformular inklusive der von
|
||||
Ihnen dort angegebenen Kontaktdaten zwecks Bearbeitung der
|
||||
Anfrage und für den Fall von Anschlussfragen bei uns
|
||||
gespeichert. Diese Daten geben wir nicht ohne Ihre Einwilligung
|
||||
weiter.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold text-primary mb-4">
|
||||
4. Server-Log-Dateien
|
||||
</h2>
|
||||
<p>
|
||||
Der Provider der Seiten erhebt und speichert automatisch
|
||||
Informationen in sogenannten Server-Log-Dateien, die Ihr Browser
|
||||
automatisch an uns übermittelt. Dies sind: Browsertyp und
|
||||
Browserversion, verwendetes Betriebssystem, Referrer URL,
|
||||
Hostname des zugreifenden Rechners, Uhrzeit der Serveranfrage,
|
||||
IP-Adresse.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
63
app/[locale]/error.tsx
Normal file
63
app/[locale]/error.tsx
Normal file
@@ -0,0 +1,63 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect } from "react";
|
||||
import { motion } from "framer-motion";
|
||||
import { RefreshCcw, Home } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
|
||||
export default function Error({
|
||||
error,
|
||||
reset,
|
||||
}: {
|
||||
error: Error & { digest?: string };
|
||||
reset: () => void;
|
||||
}) {
|
||||
useEffect(() => {
|
||||
console.error(error);
|
||||
}, [error]);
|
||||
|
||||
return (
|
||||
<div className="min-h-[80vh] flex items-center justify-center px-4">
|
||||
<div className="text-center">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scale: 0.5 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
className="text-9xl font-extrabold text-slate-200 mb-8"
|
||||
>
|
||||
500
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: 0.2, duration: 0.5 }}
|
||||
>
|
||||
<h1 className="text-4xl font-bold text-primary mb-4">
|
||||
Etwas ist schiefgelaufen
|
||||
</h1>
|
||||
<p className="text-slate-600 text-lg mb-12 max-w-md mx-auto">
|
||||
Es gab ein technisches Problem. Wir arbeiten bereits an der Lösung.
|
||||
</p>
|
||||
|
||||
<div className="flex flex-col sm:flex-row items-center justify-center gap-4">
|
||||
<button
|
||||
onClick={() => reset()}
|
||||
className="btn-accent flex items-center gap-2"
|
||||
>
|
||||
<RefreshCcw size={18} />
|
||||
Erneut versuchen
|
||||
</button>
|
||||
<Link
|
||||
href="/"
|
||||
className="btn-primary bg-slate-100 !text-primary hover:bg-slate-200 flex items-center gap-2"
|
||||
>
|
||||
<Home size={18} />
|
||||
Zur Startseite
|
||||
</Link>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
101
app/[locale]/impressum/page.tsx
Normal file
101
app/[locale]/impressum/page.tsx
Normal file
@@ -0,0 +1,101 @@
|
||||
"use client";
|
||||
|
||||
import { motion } from "framer-motion";
|
||||
import { TechBackground } from "@/components/TechBackground";
|
||||
|
||||
export default function Legal() {
|
||||
return (
|
||||
<div className="bg-slate-50 min-h-screen pt-40 pb-20 relative overflow-hidden">
|
||||
<TechBackground />
|
||||
<div className="container-custom relative z-10">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ type: "spring", stiffness: 50, damping: 20 }}
|
||||
className="max-w-4xl mx-auto bg-white p-8 md:p-12 rounded-[2.5rem] shadow-sm border border-slate-100 relative overflow-hidden group"
|
||||
>
|
||||
<div className="tech-corner top-8 left-8 border-t-2 border-l-2 opacity-20" />
|
||||
<div className="tech-corner bottom-8 right-8 border-b-2 border-r-2 opacity-20" />
|
||||
|
||||
<h1 className="text-4xl font-extrabold text-primary mb-8 relative z-10">
|
||||
Impressum
|
||||
</h1>
|
||||
|
||||
<div className="space-y-8 text-slate-600 leading-relaxed relative z-10">
|
||||
<div>
|
||||
<h2 className="text-xl font-bold text-primary mb-4">
|
||||
Angaben gemäß § 5 TMG
|
||||
</h2>
|
||||
<p>
|
||||
MB Grid Solutions & Services GmbH
|
||||
<br />
|
||||
Raiffeisenstraße 22
|
||||
<br />
|
||||
73630 Remshalden
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="text-xl font-bold text-primary mb-4">
|
||||
Vertreten durch
|
||||
</h2>
|
||||
<p>
|
||||
Michael Bodemer
|
||||
<br />
|
||||
Klaus Mintel
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="text-xl font-bold text-primary mb-4">Kontakt</h2>
|
||||
<p>
|
||||
E-Mail:{" "}
|
||||
<a
|
||||
href="mailto:info@mb-grid-solutions.com"
|
||||
className="text-accent hover:underline"
|
||||
>
|
||||
info@mb-grid-solutions.com
|
||||
</a>
|
||||
<br />
|
||||
Web:{" "}
|
||||
<a
|
||||
href="https://www.mb-grid-solutions.com"
|
||||
className="text-accent hover:underline"
|
||||
>
|
||||
www.mb-grid-solutions.com
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="text-xl font-bold text-primary mb-4">
|
||||
Registereintrag
|
||||
</h2>
|
||||
<p>
|
||||
Eintragung im Handelsregister.
|
||||
<br />
|
||||
Registergericht: Amtsgericht Stuttgart
|
||||
<br />
|
||||
Registernummer: HRB 803379
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 className="text-xl font-bold text-primary mb-4">
|
||||
Urheberrecht
|
||||
</h2>
|
||||
<p>
|
||||
Alle auf der Website veröffentlichten Texte, Bilder und
|
||||
sonstigen Informationen unterliegen – sofern nicht anders
|
||||
gekennzeichnet – dem Urheberrecht. Jede Vervielfältigung,
|
||||
Verbreitung, Speicherung, Übermittlung, Wiedergabe bzw.
|
||||
Weitergabe der Inhalte ohne schriftliche Genehmigung ist
|
||||
ausdrücklich untersagt.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
12
app/[locale]/kontakt/page.tsx
Normal file
12
app/[locale]/kontakt/page.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Metadata } from "next";
|
||||
import ContactContent from "@/components/ContactContent";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Kontakt",
|
||||
description:
|
||||
"Haben Sie Fragen zu einem Projekt oder benötigen Sie technische Beratung? Wir freuen uns auf Ihre Nachricht.",
|
||||
};
|
||||
|
||||
export default function Page() {
|
||||
return <ContactContent />;
|
||||
}
|
||||
123
app/[locale]/layout.tsx
Normal file
123
app/[locale]/layout.tsx
Normal file
@@ -0,0 +1,123 @@
|
||||
import Layout from "@/components/Layout";
|
||||
import type { Metadata } from "next";
|
||||
import { Inter } from "next/font/google";
|
||||
import "../globals.css";
|
||||
import { NextIntlClientProvider } from "next-intl";
|
||||
import { getMessages } from "next-intl/server";
|
||||
import { notFound } from "next/navigation";
|
||||
|
||||
const inter = Inter({
|
||||
subsets: ["latin"],
|
||||
display: "swap",
|
||||
variable: "--font-inter",
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
metadataBase: new URL("https://www.mb-grid-solutions.com"),
|
||||
title: {
|
||||
default: "MB Grid Solutions | Energiekabelprojekte & Technische Beratung",
|
||||
template: "%s | MB Grid Solutions",
|
||||
},
|
||||
description:
|
||||
"Ihr spezialisierter Partner für herstellerneutrale technische Beratung und Projektbegleitung bei Energiekabelprojekten bis 110 kV. Expertise in Mittel- und Hochspannungsnetzen.",
|
||||
keywords: [
|
||||
"Energiekabel",
|
||||
"Hochspannung",
|
||||
"Mittelspannung",
|
||||
"Kabelprojekte",
|
||||
"Technische Beratung",
|
||||
"Engineering",
|
||||
"Energiewende",
|
||||
"110 kV",
|
||||
],
|
||||
authors: [{ name: "MB Grid Solutions & Services GmbH" }],
|
||||
creator: "MB Grid Solutions & Services GmbH",
|
||||
publisher: "MB Grid Solutions & Services GmbH",
|
||||
formatDetection: {
|
||||
email: false,
|
||||
address: false,
|
||||
telephone: false,
|
||||
},
|
||||
openGraph: {
|
||||
type: "website",
|
||||
locale: "de_DE",
|
||||
url: "https://www.mb-grid-solutions.com",
|
||||
siteName: "MB Grid Solutions",
|
||||
title: "MB Grid Solutions | Energiekabelprojekte & Technische Beratung",
|
||||
description:
|
||||
"Spezialisierter Partner für Energiekabelprojekte bis 110 kV. Herstellerneutrale technische Beratung und Projektbegleitung.",
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
title: "MB Grid Solutions | Energiekabelprojekte & Technische Beratung",
|
||||
description: "Spezialisierter Partner für Energiekabelprojekte bis 110 kV.",
|
||||
},
|
||||
robots: {
|
||||
index: true,
|
||||
follow: true,
|
||||
googleBot: {
|
||||
index: true,
|
||||
follow: true,
|
||||
"max-video-preview": -1,
|
||||
"max-image-preview": "large",
|
||||
"max-snippet": -1,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default async function RootLayout({
|
||||
children,
|
||||
params,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
params: Promise<{ locale: string }>;
|
||||
}) {
|
||||
const { locale } = await params;
|
||||
|
||||
// Validate that the incoming `locale` is supported
|
||||
if (locale !== "de") {
|
||||
notFound();
|
||||
}
|
||||
|
||||
// Providing all messages to the client
|
||||
// side is the easiest way to get started
|
||||
const messages = await getMessages();
|
||||
|
||||
const jsonLd = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Organization",
|
||||
name: "MB Grid Solutions & Services GmbH",
|
||||
url: "https://www.mb-grid-solutions.com",
|
||||
logo: "https://www.mb-grid-solutions.com/assets/logo.png",
|
||||
description:
|
||||
"Ihr spezialisierter Partner für herstellerneutrale technische Beratung und Projektbegleitung bei Energiekabelprojekten bis 110 kV.",
|
||||
address: {
|
||||
"@type": "PostalAddress",
|
||||
streetAddress: "Raiffeisenstraße 22",
|
||||
addressLocality: "Remshalden",
|
||||
postalCode: "73630",
|
||||
addressCountry: "DE",
|
||||
},
|
||||
contactPoint: {
|
||||
"@type": "ContactPoint",
|
||||
email: "info@mb-grid-solutions.com",
|
||||
contactType: "customer service",
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<html lang={locale} className={`${inter.variable}`}>
|
||||
<head>
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||
/>
|
||||
</head>
|
||||
<body className="antialiased">
|
||||
<NextIntlClientProvider messages={messages}>
|
||||
<Layout>{children}</Layout>
|
||||
</NextIntlClientProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
50
app/[locale]/not-found.tsx
Normal file
50
app/[locale]/not-found.tsx
Normal file
@@ -0,0 +1,50 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { motion } from "framer-motion";
|
||||
import { Home, ArrowLeft } from "lucide-react";
|
||||
|
||||
export default function NotFound() {
|
||||
return (
|
||||
<div className="min-h-[80vh] flex items-center justify-center px-4">
|
||||
<div className="text-center">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scale: 0.5 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
className="text-9xl font-extrabold text-slate-200 mb-8"
|
||||
>
|
||||
404
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: 0.2, duration: 0.5 }}
|
||||
>
|
||||
<h1 className="text-4xl font-bold text-primary mb-4">
|
||||
Seite nicht gefunden
|
||||
</h1>
|
||||
<p className="text-slate-600 text-lg mb-12 max-w-md mx-auto">
|
||||
Die von Ihnen gesuchte Seite scheint nicht zu existieren oder wurde
|
||||
verschoben.
|
||||
</p>
|
||||
|
||||
<div className="flex flex-col sm:flex-row items-center justify-center gap-4">
|
||||
<Link href="/" className="btn-primary flex items-center gap-2">
|
||||
<Home size={18} />
|
||||
Zur Startseite
|
||||
</Link>
|
||||
<button
|
||||
onClick={() => window.history.back()}
|
||||
className="btn-primary bg-slate-100 !text-primary hover:bg-slate-200 flex items-center gap-2"
|
||||
>
|
||||
<ArrowLeft size={18} />
|
||||
Zurück
|
||||
</button>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
175
app/[locale]/opengraph-image.tsx
Normal file
175
app/[locale]/opengraph-image.tsx
Normal file
@@ -0,0 +1,175 @@
|
||||
import { ImageResponse } from "next/og";
|
||||
|
||||
export const runtime = "edge";
|
||||
|
||||
export const alt =
|
||||
"MB Grid Solutions | Energiekabelprojekte & Technische Beratung";
|
||||
export const size = {
|
||||
width: 1200,
|
||||
height: 630,
|
||||
};
|
||||
|
||||
export const contentType = "image/png";
|
||||
|
||||
export default async function Image() {
|
||||
return new ImageResponse(
|
||||
<div
|
||||
style={{
|
||||
background: "#ffffff",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
position: "relative",
|
||||
fontFamily: "sans-serif",
|
||||
}}
|
||||
>
|
||||
{/* Grid Pattern Background - matching .grid-pattern in globals.css */}
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
backgroundImage:
|
||||
"radial-gradient(circle, #e2e8f0 1.5px, transparent 1.5px)",
|
||||
backgroundSize: "40px 40px",
|
||||
zIndex: 0,
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Content Container - matching .card-modern / .glass-panel style */}
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
backgroundColor: "rgba(255, 255, 255, 0.95)",
|
||||
padding: "60px 80px",
|
||||
borderRadius: "48px",
|
||||
border: "1px solid #e2e8f0",
|
||||
boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.1)",
|
||||
zIndex: 1,
|
||||
position: "relative",
|
||||
}}
|
||||
>
|
||||
{/* Engineering Excellence Badge */}
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "12px",
|
||||
padding: "8px 20px",
|
||||
backgroundColor: "rgba(16, 185, 129, 0.1)",
|
||||
borderRadius: "100px",
|
||||
marginBottom: "32px",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
width: "10px",
|
||||
height: "10px",
|
||||
backgroundColor: "#10b981",
|
||||
borderRadius: "50%",
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
style={{
|
||||
fontSize: "14px",
|
||||
fontWeight: "bold",
|
||||
color: "#10b981",
|
||||
textTransform: "uppercase",
|
||||
letterSpacing: "0.1em",
|
||||
}}
|
||||
>
|
||||
Engineering Excellence
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Brand Mark */}
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
width: "100px",
|
||||
height: "100px",
|
||||
backgroundColor: "#0f172a",
|
||||
borderRadius: "24px",
|
||||
marginBottom: "32px",
|
||||
boxShadow: "0 10px 15px -3px rgba(15, 23, 42, 0.3)",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
fontSize: "48px",
|
||||
fontWeight: "bold",
|
||||
color: "#10b981",
|
||||
}}
|
||||
>
|
||||
MB
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Title */}
|
||||
<div
|
||||
style={{
|
||||
fontSize: "72px",
|
||||
fontWeight: "900",
|
||||
color: "#0f172a",
|
||||
marginBottom: "16px",
|
||||
textAlign: "center",
|
||||
letterSpacing: "-0.02em",
|
||||
}}
|
||||
>
|
||||
MB Grid <span style={{ color: "#10b981" }}>Solutions</span>
|
||||
</div>
|
||||
|
||||
{/* Subtitle */}
|
||||
<div
|
||||
style={{
|
||||
fontSize: "32px",
|
||||
fontWeight: "500",
|
||||
color: "#64748b",
|
||||
textAlign: "center",
|
||||
maxWidth: "800px",
|
||||
lineHeight: 1.4,
|
||||
}}
|
||||
>
|
||||
Energiekabelprojekte & Technische Beratung
|
||||
<br />
|
||||
bis 110 kV
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Tech Lines - matching .tech-line style */}
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: "10%",
|
||||
left: 0,
|
||||
width: "200px",
|
||||
height: "1px",
|
||||
backgroundColor: "rgba(16, 185, 129, 0.2)",
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
bottom: "15%",
|
||||
right: 0,
|
||||
width: "300px",
|
||||
height: "1px",
|
||||
backgroundColor: "rgba(16, 185, 129, 0.2)",
|
||||
}}
|
||||
/>
|
||||
</div>,
|
||||
{
|
||||
...size,
|
||||
},
|
||||
);
|
||||
}
|
||||
12
app/[locale]/page.tsx
Normal file
12
app/[locale]/page.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Metadata } from "next";
|
||||
import HomeContent from "@/components/HomeContent";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "MB Grid Solutions | Energiekabelprojekte & Technische Beratung",
|
||||
description:
|
||||
"Ihr spezialisierter Partner für herstellerneutrale technische Beratung und Projektbegleitung bei Energiekabelprojekten bis 110 kV.",
|
||||
};
|
||||
|
||||
export default function Page() {
|
||||
return <HomeContent />;
|
||||
}
|
||||
175
app/[locale]/twitter-image.tsx
Normal file
175
app/[locale]/twitter-image.tsx
Normal file
@@ -0,0 +1,175 @@
|
||||
import { ImageResponse } from "next/og";
|
||||
|
||||
export const runtime = "edge";
|
||||
|
||||
export const alt =
|
||||
"MB Grid Solutions | Energiekabelprojekte & Technische Beratung";
|
||||
export const size = {
|
||||
width: 1200,
|
||||
height: 630,
|
||||
};
|
||||
|
||||
export const contentType = "image/png";
|
||||
|
||||
export default async function Image() {
|
||||
return new ImageResponse(
|
||||
<div
|
||||
style={{
|
||||
background: "#ffffff",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
position: "relative",
|
||||
fontFamily: "sans-serif",
|
||||
}}
|
||||
>
|
||||
{/* Grid Pattern Background */}
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
backgroundImage:
|
||||
"radial-gradient(circle, #e2e8f0 1.5px, transparent 1.5px)",
|
||||
backgroundSize: "40px 40px",
|
||||
zIndex: 0,
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Content Container */}
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
backgroundColor: "rgba(255, 255, 255, 0.95)",
|
||||
padding: "60px 80px",
|
||||
borderRadius: "48px",
|
||||
border: "1px solid #e2e8f0",
|
||||
boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.1)",
|
||||
zIndex: 1,
|
||||
position: "relative",
|
||||
}}
|
||||
>
|
||||
{/* Engineering Excellence Badge */}
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "12px",
|
||||
padding: "8px 20px",
|
||||
backgroundColor: "rgba(16, 185, 129, 0.1)",
|
||||
borderRadius: "100px",
|
||||
marginBottom: "32px",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
width: "10px",
|
||||
height: "10px",
|
||||
backgroundColor: "#10b981",
|
||||
borderRadius: "50%",
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
style={{
|
||||
fontSize: "14px",
|
||||
fontWeight: "bold",
|
||||
color: "#10b981",
|
||||
textTransform: "uppercase",
|
||||
letterSpacing: "0.1em",
|
||||
}}
|
||||
>
|
||||
Engineering Excellence
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Brand Mark */}
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
width: "100px",
|
||||
height: "100px",
|
||||
backgroundColor: "#0f172a",
|
||||
borderRadius: "24px",
|
||||
marginBottom: "32px",
|
||||
boxShadow: "0 10px 15px -3px rgba(15, 23, 42, 0.3)",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
fontSize: "48px",
|
||||
fontWeight: "bold",
|
||||
color: "#10b981",
|
||||
}}
|
||||
>
|
||||
MB
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Title */}
|
||||
<div
|
||||
style={{
|
||||
fontSize: "72px",
|
||||
fontWeight: "900",
|
||||
color: "#0f172a",
|
||||
marginBottom: "16px",
|
||||
textAlign: "center",
|
||||
letterSpacing: "-0.02em",
|
||||
}}
|
||||
>
|
||||
MB Grid <span style={{ color: "#10b981" }}>Solutions</span>
|
||||
</div>
|
||||
|
||||
{/* Subtitle */}
|
||||
<div
|
||||
style={{
|
||||
fontSize: "32px",
|
||||
fontWeight: "500",
|
||||
color: "#64748b",
|
||||
textAlign: "center",
|
||||
maxWidth: "800px",
|
||||
lineHeight: 1.4,
|
||||
}}
|
||||
>
|
||||
Energiekabelprojekte & Technische Beratung
|
||||
<br />
|
||||
bis 110 kV
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Tech Lines */}
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: "10%",
|
||||
left: 0,
|
||||
width: "200px",
|
||||
height: "1px",
|
||||
backgroundColor: "rgba(16, 185, 129, 0.2)",
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
bottom: "15%",
|
||||
right: 0,
|
||||
width: "300px",
|
||||
height: "1px",
|
||||
backgroundColor: "rgba(16, 185, 129, 0.2)",
|
||||
}}
|
||||
/>
|
||||
</div>,
|
||||
{
|
||||
...size,
|
||||
},
|
||||
);
|
||||
}
|
||||
12
app/[locale]/ueber-uns/page.tsx
Normal file
12
app/[locale]/ueber-uns/page.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Metadata } from "next";
|
||||
import AboutContent from "@/components/AboutContent";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Über uns",
|
||||
description:
|
||||
"Erfahren Sie mehr über MB Grid Solutions, unsere Expertise und unser Manifest für technische Exzellenz.",
|
||||
};
|
||||
|
||||
export default function Page() {
|
||||
return <AboutContent />;
|
||||
}
|
||||
Reference in New Issue
Block a user