chore: initial commit before website expansion
This commit is contained in:
commit
8267ae3e8c
|
|
@ -0,0 +1,5 @@
|
||||||
|
node_modules/
|
||||||
|
.next/
|
||||||
|
.superpowers/
|
||||||
|
.agents/
|
||||||
|
.claude/
|
||||||
|
|
@ -0,0 +1,321 @@
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
import LegalLayout from "@/components/LegalLayout";
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: "Datenschutzerklaerung | MBO-Tech-IT",
|
||||||
|
description: "Datenschutzerklaerung gemaess DSGVO / DS-GVO",
|
||||||
|
robots: "noindex, nofollow",
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function DatenschutzPage() {
|
||||||
|
return (
|
||||||
|
<LegalLayout title="Datenschutzerklaerung">
|
||||||
|
<section>
|
||||||
|
<h2>1. Datenschutz auf einen Blick</h2>
|
||||||
|
<h3>Allgemeine Hinweise</h3>
|
||||||
|
<p>
|
||||||
|
Die folgenden Hinweise geben einen einfachen Ueberblick darueber, was mit Ihren
|
||||||
|
personenbezogenen Daten passiert, wenn Sie diese Website besuchen. Personenbezogene
|
||||||
|
Daten sind alle Daten, mit denen Sie persoenlich identifiziert werden koennen.
|
||||||
|
Ausfuehrliche Informationen zum Thema Datenschutz entnehmen Sie unserer unter diesem
|
||||||
|
Text aufgefuehrten Datenschutzerklaerung.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Datenerfassung auf dieser Website</h3>
|
||||||
|
<p>
|
||||||
|
<strong>Wer ist verantwortlich fuer die Datenerfassung auf dieser Website?</strong><br />
|
||||||
|
Die Datenverarbeitung auf dieser Website erfolgt durch den Websitebetreiber. Dessen
|
||||||
|
Kontaktdaten koennen Sie dem Abschnitt „Hinweis zur Verantwortlichen Stelle“
|
||||||
|
in dieser Datenschutzerklaerung entnehmen.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>Wie erfassen wir Ihre Daten?</strong><br />
|
||||||
|
Ihre Daten werden zum einen dadurch erhoben, dass Sie uns diese mitteilen, z. B. durch
|
||||||
|
Eingabe in unser Kontaktformular. Andere Daten werden automatisch oder nach Ihrer
|
||||||
|
Einwilligung beim Besuch der Website durch unsere IT-Systeme erfasst. Das sind vor
|
||||||
|
allem technische Daten (z. B. Internetbrowser, Betriebssystem oder Uhrzeit des
|
||||||
|
Seitenaufrufs).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>Wofuer nutzen wir Ihre Daten?</strong><br />
|
||||||
|
Ein Teil der Daten wird erhoben, um eine fehlerfreie Bereitstellung der Website zu
|
||||||
|
gewaehrleisten. Andere Daten koennen zur Analyse Ihres Nutzerverhaltens verwendet
|
||||||
|
werden. Sofern ueber die Website Vertraege geschlossen oder angebahnt werden koennen,
|
||||||
|
werden die uebermittelten Daten auch fuer Vertragsangebote, Bestellungen oder sonstige
|
||||||
|
Auftragsanfragen verarbeitet.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>Welche Rechte haben Sie bezueglich Ihrer Daten?</strong><br />
|
||||||
|
Sie haben jederzeit das Recht, unentgeltlich Auskunft ueber Herkunft, Emfpaenger und
|
||||||
|
Zweck Ihrer gespeicherten personenbezogenen Daten zu erhalten. Sie haben ausserdem ein
|
||||||
|
Recht, die Berichtigung oder Loeschung dieser Daten zu verlangen. Wenn Sie eine
|
||||||
|
Einwilligung zur Datenverarbeitung erteilt haben, koennen Sie diese Einwilligung
|
||||||
|
jederzeit fuer die Zukunft widerrufen. Ausserdem haben Sie das Recht, unter bestimmten
|
||||||
|
Umstaenden die Einschraenkung der Verarbeitung Ihrer personenbezogenen Daten zu
|
||||||
|
verlangen.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>2. Hosting</h2>
|
||||||
|
<p>
|
||||||
|
Wir hosten die Inhalte unserer Website bei folgendem Anbieter:
|
||||||
|
</p>
|
||||||
|
<h3>Externes Hosting</h3>
|
||||||
|
<p>
|
||||||
|
Diese Website wird extern gehostet. Die personenbezogenen Daten, die auf dieser
|
||||||
|
Website erfasst werden, werden auf den Servern des Hosters / der Hoster gespeichert.
|
||||||
|
Hierbei kann es sich v. a. um IP-Adressen, Kontaktanfragen, Meta- und
|
||||||
|
Kommunikationsdaten, Vertragsdaten, Kontaktdaten, Namen, Websitezugriffe und sonstige
|
||||||
|
Daten, die ueber eine Website generiert werden, handeln.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Das externe Hosting erfolgt zum Zwecke der Vertragserfullung gegenueber unseren
|
||||||
|
potenziellen und bestehenden Kunden (Art. 6 Abs. 1 lit. b DSGVO) und im Interesse
|
||||||
|
einer sicheren, schnellen und effizienten Bereitstellung unseres Online-Angebots
|
||||||
|
durch einen professionellen Anbieter (Art. 6 Abs. 1 lit. f DSGVO).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Unser(e) Hoster wird bzw. werden Ihre Daten nur insoweit verarbeiten, wie dies zur
|
||||||
|
Erfuellung seiner Leistungspflichten erforderlich ist und unsere Weisungen in Bezug
|
||||||
|
auf diese Daten befolgen.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Wir setzen folgende(n) Hoster ein:<br />
|
||||||
|
<strong>[HOSTING-ANBIETER, z.B. Hetzner Online GmbH, Industriestr. 25, 91710 Gunzenhausen]</strong>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>3. Allgemeine Hinweise und Pflichtinformationen</h2>
|
||||||
|
|
||||||
|
<h3>Datenschutz</h3>
|
||||||
|
<p>
|
||||||
|
Die Betreiber dieser Seiten nehmen den Schutz Ihrer persoenlichen Daten sehr ernst.
|
||||||
|
Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend den
|
||||||
|
gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklaerung.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Wenn Sie diese Website benutzen, werden verschiedene personenbezogene Daten erhoben.
|
||||||
|
Personenbezogene Daten sind Daten, mit denen Sie persoenlich identifiziert werden
|
||||||
|
koennen. Die vorliegende Datenschutzerklaerung erlaeutert, welche Daten wir erheben
|
||||||
|
und wofuer wir sie nutzen. Sie erlaeutert auch, wie und zu welchem Zweck das geschieht.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Hinweis zur verantwortlichen Stelle</h3>
|
||||||
|
<p>
|
||||||
|
Die verantwortliche Stelle fuer die Datenverarbeitung auf dieser Website ist:
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>Markus Butz</strong><br />
|
||||||
|
MBO-Tech-IT<br />
|
||||||
|
Mörikestr. 2<br />
|
||||||
|
74564 Crailsheim<br /><br />
|
||||||
|
Telefon: <a href="tel:+4917193451093">+49 171 9345193</a><br />
|
||||||
|
E-Mail: <a href="mailto:kontakt@mbo-tech-it.de">kontakt@mbo-tech-it.de</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Verantwortliche Stelle ist die natuerliche oder juristische Person, die allein oder
|
||||||
|
gemeinsam mit anderen ueber die Zwecke und Mittel der Verarbeitung von
|
||||||
|
personenbezogenen Daten entscheidet.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Speicherdauer</h3>
|
||||||
|
<p>
|
||||||
|
Soweit innerhalb dieser Datenschutzerklaerung keine speziellere Speicherdauer genannt
|
||||||
|
wurde, verbleiben Ihre personenbezogenen Daten bei uns, bis der Zweck fuer die
|
||||||
|
Datenverarbeitung entfaellt. Wenn Sie ein berechtigtes Loeschersuchen geltend machen
|
||||||
|
oder eine Einwilligung zur Datenverarbeitung widerrufen, werden Ihre Daten geloescht,
|
||||||
|
sofern wir keine anderen rechtlich zulaessigen Gruende fuer die Speicherung Ihrer
|
||||||
|
personenbezogenen Daten haben (z. B. steuer- oder handelsrechtliche
|
||||||
|
Aufbewahrungsfristen); im letztgenannten Fall erfolgt die Loeschung nach Fortfall
|
||||||
|
dieser Gruende.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>SSL- bzw. TLS-Verschluesselung</h3>
|
||||||
|
<p>
|
||||||
|
Diese Seite nutzt aus Sicherheitsgruenden und zum Schutz der Uebertragung
|
||||||
|
vertraulicher Inhalte, wie zum Beispiel Bestellungen oder Anfragen, die Sie an uns
|
||||||
|
als Seitenbetreiber senden, eine SSL- bzw. TLS-Verschluesselung. Eine verschluesselte
|
||||||
|
Verbindung erkennen Sie daran, dass die Adresszeile des Browsers von „http://“
|
||||||
|
auf „https://“ wechselt und an dem Schloss-Symbol in Ihrer Browserzeile.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Wenn die SSL- bzw. TLS-Verschluesselung aktiviert ist, koennen die Daten, die Sie an
|
||||||
|
uns uebermitteln, nicht von Dritten mitgelesen werden.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Ihre Rechte als betroffene Person</h3>
|
||||||
|
<p>Gemaess DSGVO haben Sie folgende Rechte:</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<strong>Auskunftsrecht (Art. 15 DSGVO):</strong> Sie haben das Recht zu erfahren,
|
||||||
|
ob und welche Daten wir ueber Sie verarbeiten.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Recht auf Berichtigung (Art. 16 DSGVO):</strong> Sie koennen die
|
||||||
|
Berichtigung unrichtiger oder die Vervollstaendigung unvollstaendiger Daten verlangen.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Recht auf Loeschung (Art. 17 DSGVO):</strong> Sie koennen die Loeschung
|
||||||
|
Ihrer Daten verlangen, sofern keine gesetzliche Aufbewahrungspflicht entgegensteht.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Recht auf Einschraenkung (Art. 18 DSGVO):</strong> Sie koennen die
|
||||||
|
Einschraenkung der Verarbeitung Ihrer Daten verlangen.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Recht auf Datenuebertragbarkeit (Art. 20 DSGVO):</strong> Sie koennen Ihre
|
||||||
|
Daten in einem maschinenlesbaren Format erhalten oder an einen anderen
|
||||||
|
Verantwortlichen uebertragen lassen.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Widerspruchsrecht (Art. 21 DSGVO):</strong> Sie koennen der Verarbeitung
|
||||||
|
Ihrer Daten widersprechen, sofern diese auf Art. 6 Abs. 1 lit. e oder f DSGVO
|
||||||
|
beruht.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Widerrufsrecht:</strong> Erteilte Einwilligungen koennen Sie jederzeit mit
|
||||||
|
Wirkung fuer die Zukunft widerrufen.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Beschwerderecht (Art. 77 DSGVO):</strong> Sie haben das Recht, sich bei
|
||||||
|
einer Datenschutzaufsichtsbehoerde zu beschweren, insbesondere in dem
|
||||||
|
EU-Mitgliedstaat Ihres gewoehnlichen Aufenthalts, Ihres Arbeitsplatzes oder des
|
||||||
|
Orts des mutmaßlichen Verstosses.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
Fuer Anfragen zu Ihren Rechten wenden Sie sich bitte an:{" "}
|
||||||
|
<a href="mailto:kontakt@mbo-tech-it.de">kontakt@mbo-tech-it.de</a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>4. Datenerfassung auf dieser Website</h2>
|
||||||
|
|
||||||
|
<h3>Server-Log-Dateien</h3>
|
||||||
|
<p>
|
||||||
|
Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten
|
||||||
|
Server-Log-Dateien, die Ihr Browser automatisch an uns uebermittelt. Dies sind:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>Browsertyp und Browserversion</li>
|
||||||
|
<li>Verwendetes Betriebssystem</li>
|
||||||
|
<li>Referrer URL</li>
|
||||||
|
<li>Hostname des zugreifenden Rechners</li>
|
||||||
|
<li>Uhrzeit der Serveranfrage</li>
|
||||||
|
<li>IP-Adresse (anonymisiert)</li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
Eine Zusammenfuehrung dieser Daten mit anderen Datenquellen wird nicht vorgenommen.
|
||||||
|
Die Erfassung dieser Daten erfolgt auf Grundlage von Art. 6 Abs. 1 lit. f DSGVO.
|
||||||
|
Der Websitebetreiber hat ein berechtigtes Interesse an der technisch fehlerfreien
|
||||||
|
Darstellung und der Optimierung seiner Website – hierzu muessen die Server-Log-Files
|
||||||
|
erfasst werden.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Kontaktformular</h3>
|
||||||
|
<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 fuer den Fall von Anschlussfragen bei uns gespeichert.
|
||||||
|
Diese Daten geben wir nicht ohne Ihre Einwilligung weiter.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Die Verarbeitung dieser Daten erfolgt auf Grundlage von Art. 6 Abs. 1 lit. b DSGVO,
|
||||||
|
sofern Ihre Anfrage mit der Erfuellung eines Vertrags zusammenhaengt oder zur
|
||||||
|
Durchfuehrung vorvertraglicher Massnahmen erforderlich ist. In allen uebrigen Faellen
|
||||||
|
beruht die Verarbeitung auf unserem berechtigten Interesse an der effektiven
|
||||||
|
Bearbeitung der an uns gerichteten Anfragen (Art. 6 Abs. 1 lit. f DSGVO) oder auf
|
||||||
|
Ihrer Einwilligung (Art. 6 Abs. 1 lit. a DSGVO), sofern diese abgefragt wurde.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Die von Ihnen im Kontaktformular eingegebenen Daten verbleiben bei uns, bis Sie uns
|
||||||
|
zur Loeschung auffordern, Ihre Einwilligung zur Speicherung widerrufen oder der Zweck
|
||||||
|
fuer die Datenspeicherung entfaellt (z. B. nach abgeschlossener Bearbeitung Ihrer
|
||||||
|
Anfrage). Zwingende gesetzliche Bestimmungen – insbesondere Aufbewahrungsfristen
|
||||||
|
– bleiben unberuehrt.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Anfrage per E-Mail oder Telefon</h3>
|
||||||
|
<p>
|
||||||
|
Wenn Sie uns per E-Mail oder Telefon kontaktieren, wird Ihre Anfrage inklusive aller
|
||||||
|
daraus hervorgehenden personenbezogenen Daten (Name, Anfrage) zum Zwecke der
|
||||||
|
Bearbeitung Ihres Anliegens bei uns gespeichert und verarbeitet. Diese Daten geben
|
||||||
|
wir nicht ohne Ihre Einwilligung weiter.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Die Verarbeitung dieser Daten erfolgt auf Grundlage von Art. 6 Abs. 1 lit. b DSGVO,
|
||||||
|
sofern Ihre Anfrage mit der Erfuellung eines Vertrags zusammenhaengt oder zur
|
||||||
|
Durchfuehrung vorvertraglicher Massnahmen erforderlich ist. In allen uebrigen Faellen
|
||||||
|
beruht die Verarbeitung auf unserem berechtigten Interesse an der effektiven
|
||||||
|
Bearbeitung der an uns gerichteten Anfragen (Art. 6 Abs. 1 lit. f DSGVO).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Die von Ihnen an uns per Kontaktanfragen uebersandten Daten verbleiben bei uns, bis
|
||||||
|
Sie uns zur Loeschung auffordern, Ihre Einwilligung zur Speicherung widerrufen oder
|
||||||
|
der Zweck fuer die Datenspeicherung entfaellt. Zwingende gesetzliche Bestimmungen
|
||||||
|
– insbesondere gesetzliche Aufbewahrungsfristen – bleiben unveraendert.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>5. Analyse-Tools und Werbung</h2>
|
||||||
|
<p>
|
||||||
|
Auf dieser Website werden <strong>keine</strong> Analyse-Tools (wie z. B. Google
|
||||||
|
Analytics, Matomo o. ae.) eingesetzt. Es werden keine Tracking-Cookies gesetzt und
|
||||||
|
keine Nutzerprofile erstellt. Es findet kein Retargeting und keine Weitergabe Ihrer
|
||||||
|
Daten an Werbenetzwerke statt.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>6. Plugins und Tools</h2>
|
||||||
|
<h3>Google Fonts (lokales Einbinden)</h3>
|
||||||
|
<p>
|
||||||
|
Diese Seite nutzt zur einheitlichen Darstellung von Schriftarten so genannte Google
|
||||||
|
Fonts, die von Google bereitgestellt werden. Die Google Fonts sind lokal installiert
|
||||||
|
bzw. werden ueber den CDN-Dienst von Google eingebunden. Eine Verbindung zu Servern
|
||||||
|
von Google findet dabei statt.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Weitere Informationen zu Google Fonts finden Sie unter{" "}
|
||||||
|
<a
|
||||||
|
href="https://developers.google.com/fonts/faq"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
https://developers.google.com/fonts/faq
|
||||||
|
</a>{" "}
|
||||||
|
und in der Datenschutzerklaerung von Google:{" "}
|
||||||
|
<a
|
||||||
|
href="https://policies.google.com/privacy"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
https://policies.google.com/privacy
|
||||||
|
</a>
|
||||||
|
.
|
||||||
|
</p>
|
||||||
|
<p className="note">
|
||||||
|
<strong>Empfehlung:</strong> Um den Datenschutz zu maximieren, koennen die Schriftarten
|
||||||
|
lokal eingebunden werden, sodass keine Verbindung zu Google-Servern aufgebaut wird.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>7. Aenderungen dieser Datenschutzerklaerung</h2>
|
||||||
|
<p>
|
||||||
|
Wir behalten uns vor, diese Datenschutzerklaerung anzupassen, damit sie stets den
|
||||||
|
aktuellen rechtlichen Anforderungen entspricht oder um Aenderungen unserer Leistungen
|
||||||
|
in der Datenschutzerklaerung umzusetzen, z. B. bei der Einfuehrung neuer Services.
|
||||||
|
Fuer Ihren erneuten Besuch gilt dann die neue Datenschutzerklaerung.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>Stand: {new Date().toLocaleDateString("de-DE", { month: "long", year: "numeric" })}</strong>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</LegalLayout>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,196 @@
|
||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500&display=swap');
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--color-orange: #f97316;
|
||||||
|
--color-orange-light: #fb923c;
|
||||||
|
--color-blue: #2563eb;
|
||||||
|
--color-blue-light: #60a5fa;
|
||||||
|
--color-dark: #18212f;
|
||||||
|
--color-darker: #111925;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background-color: #18212f;
|
||||||
|
color: #f1f5f9;
|
||||||
|
font-family: 'Inter', system-ui, sans-serif;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer components {
|
||||||
|
/* Primary button – orange, darkens on hover */
|
||||||
|
.btn-primary {
|
||||||
|
@apply inline-flex items-center justify-center rounded-xl
|
||||||
|
bg-orange-500 text-white font-bold
|
||||||
|
transition-all duration-200
|
||||||
|
hover:bg-orange-600 hover:scale-[1.03]
|
||||||
|
hover:shadow-lg hover:shadow-orange-900/40
|
||||||
|
active:scale-[0.98];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Secondary button – outlined, fills subtly on hover */
|
||||||
|
.btn-secondary {
|
||||||
|
@apply inline-flex items-center justify-center rounded-xl
|
||||||
|
border border-gray-600 text-slate-300 font-semibold
|
||||||
|
transition-all duration-200
|
||||||
|
hover:bg-white/5 hover:border-gray-400 hover:text-white
|
||||||
|
active:scale-[0.98];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Small nav button */
|
||||||
|
.btn-nav {
|
||||||
|
@apply px-4 py-2 rounded-lg bg-orange-500 text-white text-sm font-bold
|
||||||
|
transition-all duration-200
|
||||||
|
hover:bg-orange-600 hover:shadow-md hover:shadow-orange-900/30
|
||||||
|
active:scale-[0.97];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer utilities {
|
||||||
|
.text-gradient {
|
||||||
|
@apply bg-gradient-to-r from-blue-400 to-blue-600 bg-clip-text text-transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-gradient-orange {
|
||||||
|
@apply bg-gradient-to-r from-orange-400 to-orange-500 bg-clip-text text-transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dot matrix – default background pattern */
|
||||||
|
.bg-grid {
|
||||||
|
background-image: radial-gradient(rgba(249, 115, 22, 0.15) 1px, transparent 1px);
|
||||||
|
background-size: 28px 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Alt: subtle line grid */
|
||||||
|
.bg-grid-lines {
|
||||||
|
background-image: linear-gradient(rgba(249, 115, 22, 0.05) 1px, transparent 1px),
|
||||||
|
linear-gradient(90deg, rgba(249, 115, 22, 0.05) 1px, transparent 1px);
|
||||||
|
background-size: 60px 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Alt: diagonal hatching */
|
||||||
|
.bg-diagonal {
|
||||||
|
background-image: repeating-linear-gradient(
|
||||||
|
-45deg,
|
||||||
|
rgba(249, 115, 22, 0.04) 0px,
|
||||||
|
rgba(249, 115, 22, 0.04) 1px,
|
||||||
|
transparent 1px,
|
||||||
|
transparent 14px
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-hover {
|
||||||
|
@apply transition-all duration-300 hover:-translate-y-1 hover:shadow-lg hover:shadow-orange-500/10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tagline ticker animation */
|
||||||
|
@keyframes ticker-scroll {
|
||||||
|
0% { transform: translateX(0); }
|
||||||
|
100% { transform: translateX(-50%); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-ticker {
|
||||||
|
animation: ticker-scroll 25s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Legal pages content styling */
|
||||||
|
.legal-content section {
|
||||||
|
margin-bottom: 2.5rem;
|
||||||
|
}
|
||||||
|
.legal-content h2 {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #f1f5f9;
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
margin-top: 2rem;
|
||||||
|
padding-bottom: 0.5rem;
|
||||||
|
border-bottom: 1px solid #2d3748;
|
||||||
|
}
|
||||||
|
.legal-content h3 {
|
||||||
|
font-size: 0.95rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #fb923c;
|
||||||
|
margin-top: 1.25rem;
|
||||||
|
margin-bottom: 0.4rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
}
|
||||||
|
.legal-content p {
|
||||||
|
color: #94a3b8;
|
||||||
|
line-height: 1.8;
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
font-size: 0.925rem;
|
||||||
|
}
|
||||||
|
.legal-content ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0.75rem 0 1rem 0;
|
||||||
|
}
|
||||||
|
.legal-content ul li {
|
||||||
|
color: #94a3b8;
|
||||||
|
font-size: 0.925rem;
|
||||||
|
line-height: 1.75;
|
||||||
|
padding-left: 1.25rem;
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
.legal-content ul li::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0.65rem;
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #f97316;
|
||||||
|
}
|
||||||
|
.legal-content a {
|
||||||
|
color: #60a5fa;
|
||||||
|
text-decoration: underline;
|
||||||
|
text-underline-offset: 3px;
|
||||||
|
}
|
||||||
|
.legal-content a:hover {
|
||||||
|
color: #fb923c;
|
||||||
|
}
|
||||||
|
.legal-content strong {
|
||||||
|
color: #e2e8f0;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.legal-content .note {
|
||||||
|
background: #1e2a3d;
|
||||||
|
border-left: 3px solid #f97316;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
border-radius: 0 0.5rem 0.5rem 0;
|
||||||
|
margin: 0.75rem 0;
|
||||||
|
}
|
||||||
|
.legal-content .note p {
|
||||||
|
margin-bottom: 0;
|
||||||
|
font-size: 0.875rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scrollbar */
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
}
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
background: #18212f;
|
||||||
|
}
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: #2d3748;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: #f97316;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,124 @@
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
import LegalLayout from "@/components/LegalLayout";
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: "Impressum | MBO-Tech-IT",
|
||||||
|
description: "Impressum und Anbieterkennzeichnung gemäß §5 TMG",
|
||||||
|
robots: "noindex, nofollow",
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function ImpressumPage() {
|
||||||
|
return (
|
||||||
|
<LegalLayout title="Impressum">
|
||||||
|
<section>
|
||||||
|
<h2>Angaben gemäß §5 TMG</h2>
|
||||||
|
<p>
|
||||||
|
<strong>Markus Butz</strong><br />
|
||||||
|
MBO-Tech-IT<br />
|
||||||
|
Mörikestr. 2<br />
|
||||||
|
74564 Crailsheim<br />
|
||||||
|
Deutschland
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>Kontakt</h2>
|
||||||
|
<p>
|
||||||
|
Telefon: <a href="tel:+4917193451093">+49 171 9345193</a><br />
|
||||||
|
E-Mail: <a href="mailto:kontakt@mbo-tech-it.de">kontakt@mbo-tech-it.de</a>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>Umsatzsteuer-ID</h2>
|
||||||
|
<p>
|
||||||
|
Umsatzsteuer-Identifikationsnummer gemäß §27a Umsatzsteuergesetz:<br />
|
||||||
|
<strong>DE417140014</strong>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>Verantwortlich für den Inhalt nach §55 Abs. 2 RStV</h2>
|
||||||
|
<p>
|
||||||
|
<strong>Markus Butz</strong><br />
|
||||||
|
Mörikestr. 2<br />
|
||||||
|
74564 Crailsheim
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>EU-Streitschlichtung</h2>
|
||||||
|
<p>
|
||||||
|
Die Europäische Kommission stellt eine Plattform zur Online-Streitbeilegung (OS)
|
||||||
|
bereit:{" "}
|
||||||
|
<a
|
||||||
|
href="https://ec.europa.eu/consumers/odr/"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
https://ec.europa.eu/consumers/odr/
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Unsere E-Mail-Adresse finden Sie oben im Impressum. Wir sind nicht bereit oder
|
||||||
|
verpflichtet, an Streitbeilegungsverfahren vor einer Verbraucherschlichtungsstelle
|
||||||
|
teilzunehmen.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>Haftung für Inhalte</h2>
|
||||||
|
<p>
|
||||||
|
Als Diensteanbieter sind wir gemäß §7 Abs. 1 TMG für eigene Inhalte auf diesen
|
||||||
|
Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§8 bis 10 TMG sind wir
|
||||||
|
als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte
|
||||||
|
fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine
|
||||||
|
rechtswidrige Tätigkeit hinweisen.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den
|
||||||
|
allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist
|
||||||
|
jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich.
|
||||||
|
Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte
|
||||||
|
umgehend entfernen.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>Haftung für Links</h2>
|
||||||
|
<p>
|
||||||
|
Unser Angebot enthält Links zu externen Websites Dritter, auf deren Inhalte wir
|
||||||
|
keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine
|
||||||
|
Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige
|
||||||
|
Anbieter oder Betreiber der Seiten verantwortlich.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche
|
||||||
|
Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der
|
||||||
|
Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten
|
||||||
|
Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar.
|
||||||
|
Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>Urheberrecht</h2>
|
||||||
|
<p>
|
||||||
|
Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten
|
||||||
|
unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung,
|
||||||
|
Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes
|
||||||
|
bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers.
|
||||||
|
Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen
|
||||||
|
Gebrauch gestattet.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die
|
||||||
|
Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche
|
||||||
|
gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam
|
||||||
|
werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von
|
||||||
|
Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</LegalLayout>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
import "./globals.css";
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: "MBO-Tech-IT | Docker, Kubernetes & Cloud-Infrastruktur",
|
||||||
|
description:
|
||||||
|
"Ihr Experte fur Docker-Installationen, Kubernetes-Orchestrierung, Proxmox-Virtualisierung und Hetzner Cloud-Infrastruktur. IT-Losungen fur Hard- und Software.",
|
||||||
|
keywords: [
|
||||||
|
"Docker",
|
||||||
|
"Kubernetes",
|
||||||
|
"Proxmox",
|
||||||
|
"Hetzner",
|
||||||
|
"Cloud",
|
||||||
|
"IT",
|
||||||
|
"Virtualisierung",
|
||||||
|
"Container",
|
||||||
|
"DevOps",
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function RootLayout({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<html lang="de" className="scroll-smooth">
|
||||||
|
<body>{children}</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
import Header from "@/components/Header";
|
||||||
|
import Hero from "@/components/Hero";
|
||||||
|
import TaglineBanner from "@/components/TaglineBanner";
|
||||||
|
import Services from "@/components/Services";
|
||||||
|
import Technologies from "@/components/Technologies";
|
||||||
|
import DataSovereignty from "@/components/DataSovereignty";
|
||||||
|
import About from "@/components/About";
|
||||||
|
import Contact from "@/components/Contact";
|
||||||
|
import Footer from "@/components/Footer";
|
||||||
|
|
||||||
|
export default function Home() {
|
||||||
|
return (
|
||||||
|
<main className="min-h-screen bg-[#18212f]">
|
||||||
|
<Header />
|
||||||
|
<Hero />
|
||||||
|
<TaglineBanner />
|
||||||
|
<Services />
|
||||||
|
<TaglineBanner />
|
||||||
|
<Technologies />
|
||||||
|
<DataSovereignty />
|
||||||
|
<TaglineBanner />
|
||||||
|
<About />
|
||||||
|
<TaglineBanner />
|
||||||
|
<Contact />
|
||||||
|
<Footer />
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,358 @@
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
import Link from "next/link";
|
||||||
|
import Logo from "@/components/Logo";
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: "Pakete & Preise | MBO-Tech-IT",
|
||||||
|
description:
|
||||||
|
"Konkrete IT-Pakete: Nextcloud + Paperless-ngx auf Docker/Kubernetes/Proxmox – inkl. Preise für Installation, Hosting und Wartung.",
|
||||||
|
};
|
||||||
|
|
||||||
|
const packages = [
|
||||||
|
{
|
||||||
|
name: "Starter",
|
||||||
|
subtitle: "Nextcloud + Paperless",
|
||||||
|
tag: "Docker auf Hetzner CX22",
|
||||||
|
price: "174",
|
||||||
|
setup: "Einmalig",
|
||||||
|
monthly: "ab 12",
|
||||||
|
highlight: false,
|
||||||
|
specs: {
|
||||||
|
server: "Hetzner CX22 (2 vCPU, 4 GB RAM)",
|
||||||
|
storage: "40 GB SSD + optionale Storage Box",
|
||||||
|
os: "Ubuntu 24.04 LTS",
|
||||||
|
stack: "Docker + Docker Compose",
|
||||||
|
},
|
||||||
|
includes: [
|
||||||
|
"Nextcloud Installation & Konfiguration",
|
||||||
|
"Paperless-ngx Dokumentenmanagement",
|
||||||
|
"PostgreSQL Datenbank (Docker)",
|
||||||
|
"Redis Cache (Docker)",
|
||||||
|
"Traefik Reverse Proxy + SSL (Let's Encrypt)",
|
||||||
|
"Automatische Backups (Hetzner Snapshot)",
|
||||||
|
"Basis-Monitoring",
|
||||||
|
"1 Monat Support inklusive",
|
||||||
|
],
|
||||||
|
monthly_costs: [
|
||||||
|
{ label: "Hetzner CX22 Server", price: "4,35 €" },
|
||||||
|
{ label: "20 GB Snapshot-Backup", price: "0,60 €" },
|
||||||
|
{ label: "Gesamt Serverkosten", price: "~5 €" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Professional",
|
||||||
|
subtitle: "Nextcloud + Paperless",
|
||||||
|
tag: "Docker + Traefik auf Hetzner CAX21",
|
||||||
|
price: "384",
|
||||||
|
setup: "Einmalig",
|
||||||
|
monthly: "ab 22",
|
||||||
|
highlight: true,
|
||||||
|
specs: {
|
||||||
|
server: "Hetzner CAX21 ARM64 (4 vCPU, 8 GB RAM)",
|
||||||
|
storage: "80 GB SSD + BX21 Storage Box (1 TB)",
|
||||||
|
os: "Ubuntu 24.04 LTS",
|
||||||
|
stack: "Docker Compose + Watchtower (Auto-Updates)",
|
||||||
|
},
|
||||||
|
includes: [
|
||||||
|
"Alles aus Starter-Paket",
|
||||||
|
"Nextcloud All-in-One Instanz",
|
||||||
|
"Nextcloud Office (Collabora/OnlyOffice)",
|
||||||
|
"Paperless-ngx mit OCR (deutsch & englisch)",
|
||||||
|
"Nextcloud Talk (Videokommunikation)",
|
||||||
|
"Externe Storage Box für Dokumente (1 TB)",
|
||||||
|
"Automatische Nextcloud-Updates via Watchtower",
|
||||||
|
"E-Mail-Benachrichtigungen bei Systemereignissen",
|
||||||
|
"SMTP-Integration für Nextcloud",
|
||||||
|
"3 Monate Support inklusive",
|
||||||
|
],
|
||||||
|
monthly_costs: [
|
||||||
|
{ label: "Hetzner CAX21 Server", price: "7,69 €" },
|
||||||
|
{ label: "BX21 Storage Box (1 TB)", price: "3,20 €" },
|
||||||
|
{ label: "Backup-Snapshot", price: "0,80 €" },
|
||||||
|
{ label: "Gesamt Serverkosten", price: "~12 €" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Enterprise",
|
||||||
|
subtitle: "Nextcloud + Paperless Cluster",
|
||||||
|
tag: "Kubernetes auf Proxmox / Hetzner CAX41",
|
||||||
|
price: "1.049",
|
||||||
|
setup: "Einmalig",
|
||||||
|
monthly: "ab 55",
|
||||||
|
highlight: false,
|
||||||
|
specs: {
|
||||||
|
server: "Hetzner CAX41 (16 vCPU, 32 GB RAM) oder Proxmox Cluster",
|
||||||
|
storage: "160 GB SSD + BX31 Storage Box (5 TB)",
|
||||||
|
os: "Ubuntu 24.04 LTS / Proxmox VE 8",
|
||||||
|
stack: "Kubernetes (k3s) + Helm Charts + Longhorn Storage",
|
||||||
|
},
|
||||||
|
includes: [
|
||||||
|
"Alles aus Professional-Paket",
|
||||||
|
"Kubernetes Cluster (k3s) Setup",
|
||||||
|
"Helm-basiertes Nextcloud-Deployment",
|
||||||
|
"Horizontal Pod Autoscaling",
|
||||||
|
"Longhorn Distributed Storage",
|
||||||
|
"Grafana + Prometheus Monitoring",
|
||||||
|
"Zentrales Logging (Loki)",
|
||||||
|
"GitLab CI/CD Pipeline für Updates",
|
||||||
|
"Hochverfügbarkeit (HA) Konfiguration",
|
||||||
|
"SLA: 99,9% Uptime-Garantie",
|
||||||
|
"12 Monate Priority-Support inklusive",
|
||||||
|
],
|
||||||
|
monthly_costs: [
|
||||||
|
{ label: "Hetzner CAX41 Server", price: "30,99 €" },
|
||||||
|
{ label: "BX31 Storage Box (5 TB)", price: "10,90 €" },
|
||||||
|
{ label: "Load Balancer", price: "5,54 €" },
|
||||||
|
{ label: "Monitoring-Stack", price: "~8 €" },
|
||||||
|
{ label: "Gesamt Serverkosten", price: "~55 €" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const maintenancePlans = [
|
||||||
|
{
|
||||||
|
name: "Basic Wartung",
|
||||||
|
price: "27",
|
||||||
|
interval: "/ Monat",
|
||||||
|
features: [
|
||||||
|
"Monatliche System-Updates",
|
||||||
|
"Docker-Image Updates",
|
||||||
|
"Backup-Kontrolle",
|
||||||
|
"E-Mail-Support (5 Werktage Reaktionszeit)",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Standard Wartung",
|
||||||
|
price: "62",
|
||||||
|
interval: "/ Monat",
|
||||||
|
features: [
|
||||||
|
"Wöchentliche Updates & Patches",
|
||||||
|
"Sicherheits-Monitoring 24/7",
|
||||||
|
"Performance-Checks",
|
||||||
|
"Telefon- & E-Mail-Support (2 Werktage)",
|
||||||
|
"Monatlicher Status-Report",
|
||||||
|
"1 Std. Anpassungen inklusive",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Premium Wartung",
|
||||||
|
price: "132",
|
||||||
|
interval: "/ Monat",
|
||||||
|
features: [
|
||||||
|
"Tägliche Updates & Monitoring",
|
||||||
|
"Sofortiger Incident-Response",
|
||||||
|
"Proaktive Performance-Optimierung",
|
||||||
|
"Priority-Support (4 Std. Reaktionszeit)",
|
||||||
|
"Wöchentlicher Status-Report",
|
||||||
|
"3 Std. Anpassungen inklusive",
|
||||||
|
"Quartalsweise Sicherheits-Audits",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function PaketePage() {
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-[#18212f]">
|
||||||
|
{/* Header */}
|
||||||
|
<header className="bg-[#111925] border-b border-gray-800">
|
||||||
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4 flex items-center justify-between">
|
||||||
|
<Link href="/" className="flex items-center gap-3 group">
|
||||||
|
<Logo className="h-8 w-auto" />
|
||||||
|
<div className="flex flex-col leading-tight">
|
||||||
|
<span className="font-black text-white text-base tracking-wider uppercase">
|
||||||
|
MBO-<span className="bg-gradient-to-r from-blue-400 to-blue-600 bg-clip-text text-transparent">TECH-IT</span>
|
||||||
|
</span>
|
||||||
|
<span className="text-[9px] font-semibold tracking-[0.2em] text-orange-400/70 uppercase hidden sm:block">
|
||||||
|
Digital Denken. Lokal Handeln.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
href="/"
|
||||||
|
className="flex items-center gap-2 text-slate-400 hover:text-orange-400 transition-colors text-sm font-medium"
|
||||||
|
>
|
||||||
|
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 19l-7-7m0 0l7-7m-7 7h18" />
|
||||||
|
</svg>
|
||||||
|
Zurück
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
|
||||||
|
|
||||||
|
{/* Hero */}
|
||||||
|
<div className="text-center mb-16">
|
||||||
|
<span className="text-orange-400 font-mono text-xs font-bold tracking-[0.25em] uppercase">
|
||||||
|
Beispiel-Paket
|
||||||
|
</span>
|
||||||
|
<h1 className="text-4xl sm:text-5xl font-black text-white mt-3 mb-4">
|
||||||
|
Nextcloud + Paperless-ngx
|
||||||
|
</h1>
|
||||||
|
<p className="text-slate-400 text-lg max-w-2xl mx-auto">
|
||||||
|
Ihr persönliches Cloud-Büro: Datei-Management mit Nextcloud und
|
||||||
|
digitales Dokumentenarchiv mit Paperless-ngx – sicher selbst gehostet
|
||||||
|
auf Hetzner Cloud.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* What is it */}
|
||||||
|
<div className="grid md:grid-cols-2 gap-6 mb-16">
|
||||||
|
<div className="p-6 rounded-2xl bg-gray-900 border border-gray-800">
|
||||||
|
<div className="w-12 h-12 rounded-xl bg-blue-500/10 text-blue-400 flex items-center justify-center mb-4">
|
||||||
|
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 15a4 4 0 004 4h9a5 5 0 10-.1-9.999 5.002 5.002 0 10-9.78 2.096A4.001 4.001 0 003 15z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<h3 className="text-white font-bold text-lg mb-2">Nextcloud</h3>
|
||||||
|
<p className="text-slate-400 text-sm leading-relaxed">
|
||||||
|
Die freie Alternative zu Dropbox & Google Drive. Dateien, Kalender,
|
||||||
|
Kontakte, Videokonferenzen und Office-Dokumente – alles auf Ihrem
|
||||||
|
eigenen Server. Volle DSGVO-Konformität, keine Drittanbieter.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="p-6 rounded-2xl bg-gray-900 border border-gray-800">
|
||||||
|
<div className="w-12 h-12 rounded-xl bg-orange-500/10 text-orange-400 flex items-center justify-center mb-4">
|
||||||
|
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<h3 className="text-white font-bold text-lg mb-2">Paperless-ngx</h3>
|
||||||
|
<p className="text-slate-400 text-sm leading-relaxed">
|
||||||
|
Digitales Dokumentenmanagementsystem mit OCR-Texterkennung. Rechnungen,
|
||||||
|
Verträge, Briefe – alles durchsuchbar archiviert. Automatische
|
||||||
|
Klassifizierung und Tagging von Dokumenten.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Packages */}
|
||||||
|
<h2 className="text-3xl font-black text-white mb-8 text-center">
|
||||||
|
Installations-Pakete
|
||||||
|
</h2>
|
||||||
|
<div className="grid lg:grid-cols-3 gap-6 mb-20">
|
||||||
|
{packages.map((pkg) => (
|
||||||
|
<div
|
||||||
|
key={pkg.name}
|
||||||
|
className={`relative rounded-2xl p-6 border transition-all duration-300 ${
|
||||||
|
pkg.highlight
|
||||||
|
? "bg-orange-500/5 border-orange-500/50 shadow-lg shadow-orange-500/10"
|
||||||
|
: "bg-gray-900 border-gray-800"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{pkg.highlight && (
|
||||||
|
<div className="absolute -top-3 left-1/2 -translate-x-1/2 px-4 py-1 bg-orange-500 rounded-full text-white text-xs font-black tracking-wider">
|
||||||
|
EMPFOHLEN
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="mb-5">
|
||||||
|
<span className="text-orange-400 text-xs font-bold tracking-widest uppercase">{pkg.tag}</span>
|
||||||
|
<h3 className="text-2xl font-black text-white mt-1">{pkg.name}</h3>
|
||||||
|
<p className="text-slate-400 text-sm">{pkg.subtitle}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Setup price */}
|
||||||
|
<div className="mb-2 flex items-baseline gap-1.5">
|
||||||
|
<span className="text-xs text-slate-500 font-semibold tracking-wide">ab</span>
|
||||||
|
<span className="text-4xl font-black text-white">{pkg.price} €</span>
|
||||||
|
<span className="text-slate-400 text-sm">{pkg.setup}</span>
|
||||||
|
</div>
|
||||||
|
<p className="text-slate-500 text-xs mb-6">
|
||||||
|
+ Serverkosten {pkg.monthly} €/Monat (Hetzner direkt)
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* Server specs */}
|
||||||
|
<div className="p-3 rounded-xl bg-[#111925] mb-5 space-y-1">
|
||||||
|
<p className="text-xs text-slate-500 font-mono"># Server-Konfiguration</p>
|
||||||
|
<p className="text-xs text-slate-400 font-mono">{pkg.specs.server}</p>
|
||||||
|
<p className="text-xs text-slate-400 font-mono">Storage: {pkg.specs.storage}</p>
|
||||||
|
<p className="text-xs text-slate-400 font-mono">Stack: {pkg.specs.stack}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Monthly costs breakdown */}
|
||||||
|
<div className="mb-5">
|
||||||
|
<p className="text-xs font-bold text-slate-500 uppercase tracking-widest mb-2">Laufende Serverkosten</p>
|
||||||
|
{pkg.monthly_costs.map((c) => (
|
||||||
|
<div key={c.label} className="flex justify-between text-xs py-1 border-b border-gray-800">
|
||||||
|
<span className="text-slate-400">{c.label}</span>
|
||||||
|
<span className={c.label.startsWith("Gesamt") ? "text-orange-400 font-bold" : "text-slate-400"}>
|
||||||
|
{c.price}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Includes */}
|
||||||
|
<ul className="space-y-2 mb-6">
|
||||||
|
{pkg.includes.map((item) => (
|
||||||
|
<li key={item} className="flex items-start gap-2 text-sm text-slate-300">
|
||||||
|
<span className="w-4 h-4 rounded-full bg-orange-500 flex items-center justify-center flex-shrink-0 mt-0.5">
|
||||||
|
<svg className="w-2.5 h-2.5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={3} d="M5 13l4 4L19 7" />
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
{item}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<Link
|
||||||
|
href="/#contact"
|
||||||
|
className={`block w-full py-3 rounded-xl text-center font-bold text-sm transition-colors ${
|
||||||
|
pkg.highlight
|
||||||
|
? "bg-orange-500 hover:bg-orange-600 text-white"
|
||||||
|
: "bg-gray-800 hover:bg-gray-700 text-white border border-gray-700"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
Paket anfragen
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Maintenance */}
|
||||||
|
<h2 className="text-3xl font-black text-white mb-3 text-center">Wartungsvertrag</h2>
|
||||||
|
<p className="text-slate-400 text-center mb-10 max-w-xl mx-auto">
|
||||||
|
Nach der Installation können Sie optional einen Wartungsvertrag abschließen.
|
||||||
|
Wir kümmern uns um Updates, Sicherheit und Betrieb.
|
||||||
|
</p>
|
||||||
|
<div className="grid md:grid-cols-3 gap-6 mb-16">
|
||||||
|
{maintenancePlans.map((plan) => (
|
||||||
|
<div key={plan.name} className="p-6 rounded-2xl bg-gray-900 border border-gray-800 hover:border-orange-500/30 transition-all">
|
||||||
|
<h3 className="text-white font-bold text-lg mb-1">{plan.name}</h3>
|
||||||
|
<div className="mb-4 flex items-baseline gap-1.5">
|
||||||
|
<span className="text-xs text-slate-500 font-semibold tracking-wide">ab</span>
|
||||||
|
<span className="text-3xl font-black text-orange-400">{plan.price} €</span>
|
||||||
|
<span className="text-slate-400 text-sm">{plan.interval}</span>
|
||||||
|
</div>
|
||||||
|
<ul className="space-y-2">
|
||||||
|
{plan.features.map((f) => (
|
||||||
|
<li key={f} className="flex items-start gap-2 text-sm text-slate-400">
|
||||||
|
<span className="w-1.5 h-1.5 rounded-full bg-orange-400 flex-shrink-0 mt-1.5" />
|
||||||
|
{f}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Note */}
|
||||||
|
<div className="p-6 rounded-2xl border border-blue-500/20 bg-blue-500/5 text-center">
|
||||||
|
<p className="text-slate-400 text-sm">
|
||||||
|
<strong className="text-white">Hinweis:</strong> Die Serverkosten bei Hetzner werden
|
||||||
|
direkt von Ihnen bezahlt – wir installieren und warten, Sie behalten die volle
|
||||||
|
Kontrolle. Alle Preise zzgl. gesetzl. MwSt. Individuelle Angebote auf Anfrage.
|
||||||
|
</p>
|
||||||
|
<Link
|
||||||
|
href="/#contact"
|
||||||
|
className="inline-block mt-4 px-6 py-3 bg-orange-500 hover:bg-orange-600 text-white font-bold rounded-xl text-sm transition-colors"
|
||||||
|
>
|
||||||
|
Kostenloses Erstgespräch anfragen
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,102 @@
|
||||||
|
const highlights = [
|
||||||
|
{
|
||||||
|
icon: "01",
|
||||||
|
title: "Analyse & Planung",
|
||||||
|
description:
|
||||||
|
"Wir analysieren Ihre bestehende Infrastruktur und planen die optimale Lösung für Ihre Anforderungen.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: "02",
|
||||||
|
title: "Implementierung",
|
||||||
|
description:
|
||||||
|
"Professionelle Umsetzung mit bewährten technischen Methoden und modernsten Tools.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: "03",
|
||||||
|
title: "Betrieb & Support",
|
||||||
|
description:
|
||||||
|
"Zuverlässiger Betrieb, Monitoring und Support – damit Ihre Systeme immer laufen.",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function About() {
|
||||||
|
return (
|
||||||
|
<section id="about" className="py-24 px-4 sm:px-6 lg:px-8 relative">
|
||||||
|
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_bottom_right,rgba(37,99,235,0.06)_0%,transparent_60%)]" />
|
||||||
|
|
||||||
|
<div className="max-w-7xl mx-auto relative">
|
||||||
|
<div className="grid lg:grid-cols-2 gap-16 items-center">
|
||||||
|
{/* Left: Text */}
|
||||||
|
<div>
|
||||||
|
<span className="text-orange-400 font-mono text-xs font-bold tracking-[0.25em] uppercase">
|
||||||
|
Über uns
|
||||||
|
</span>
|
||||||
|
<h2 className="text-4xl sm:text-5xl font-black text-white mt-3 mb-6 leading-tight">
|
||||||
|
IT-Expertise,{" "}
|
||||||
|
<span className="text-gradient">die Sie weiterbringt</span>
|
||||||
|
</h2>
|
||||||
|
<p className="text-slate-400 text-lg leading-relaxed mb-6">
|
||||||
|
MBO-Tech-IT steht für über <strong className="text-white">30 Jahre IT-Erfahrung</strong> —
|
||||||
|
angefangen bei der einfachen Hardware-Wartung, über den Aufbau großer
|
||||||
|
Client-Server-Netzwerke, bis hin zu mehr als 20 Jahren Spezialisierung
|
||||||
|
in der <strong className="text-white">IT-Security</strong>.
|
||||||
|
</p>
|
||||||
|
<p className="text-slate-400 text-lg leading-relaxed mb-8">
|
||||||
|
Heute liegt der Fokus auf modernen Container-Technologien, Cloud-nativer
|
||||||
|
Infrastruktur und Virtualisierung. Dieses breite Fundament ermöglicht es,
|
||||||
|
Lösungen zu entwickeln, die nicht nur funktionieren — sondern auch
|
||||||
|
sicher und langfristig tragfähig sind.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* Tagline callout */}
|
||||||
|
<div className="mb-8 px-5 py-4 rounded-xl border-l-4 border-orange-500 bg-orange-500/5">
|
||||||
|
<p className="text-orange-400 font-black text-sm tracking-[0.2em] uppercase">
|
||||||
|
Digital Denken. Lokal Handeln.
|
||||||
|
</p>
|
||||||
|
<p className="text-slate-400 text-sm mt-1">
|
||||||
|
Globales Know-how — persönlicher Service.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Key points */}
|
||||||
|
<div className="space-y-3">
|
||||||
|
{[
|
||||||
|
"30+ Jahre IT-Erfahrung – von Hardware bis Cloud",
|
||||||
|
"20+ Jahre IT-Security & Netzwerk-Expertise",
|
||||||
|
"Spezialisiert auf Docker, Kubernetes & Proxmox",
|
||||||
|
"Transparente Kommunikation & faire Preise",
|
||||||
|
].map((point) => (
|
||||||
|
<div key={point} className="flex items-center gap-3">
|
||||||
|
<div className="w-5 h-5 rounded-full bg-orange-500 flex items-center justify-center flex-shrink-0">
|
||||||
|
<svg className="w-3 h-3 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={3} d="M5 13l4 4L19 7" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<span className="text-slate-300 text-sm">{point}</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Right: Process steps */}
|
||||||
|
<div className="space-y-6">
|
||||||
|
{highlights.map((item) => (
|
||||||
|
<div
|
||||||
|
key={item.title}
|
||||||
|
className="flex gap-5 p-6 rounded-2xl bg-gray-900 border border-gray-800 hover:border-orange-500/30 transition-all duration-300"
|
||||||
|
>
|
||||||
|
<div className="flex-shrink-0 w-12 h-12 rounded-xl bg-orange-500/10 border border-orange-500/20 flex items-center justify-center">
|
||||||
|
<span className="font-mono text-orange-400 font-black text-sm">{item.icon}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 className="text-white font-bold text-lg mb-2">{item.title}</h3>
|
||||||
|
<p className="text-slate-400 text-sm leading-relaxed">{item.description}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,124 @@
|
||||||
|
const contactItems = [
|
||||||
|
{
|
||||||
|
icon: (
|
||||||
|
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
label: "Telefon",
|
||||||
|
value: "+49 171 9345193",
|
||||||
|
href: "tel:+4917193451093",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: (
|
||||||
|
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
label: "E-Mail",
|
||||||
|
value: "kontakt@mbo-tech-it.de",
|
||||||
|
href: "mailto:kontakt@mbo-tech-it.de",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function Contact() {
|
||||||
|
return (
|
||||||
|
<section id="contact" className="py-24 px-4 sm:px-6 lg:px-8 relative">
|
||||||
|
<div className="absolute inset-0 bg-[#111925]" />
|
||||||
|
<div className="absolute inset-0 bg-grid opacity-40" />
|
||||||
|
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_center,rgba(249,115,22,0.07)_0%,transparent_70%)]" />
|
||||||
|
|
||||||
|
<div className="max-w-4xl mx-auto relative">
|
||||||
|
{/* Header */}
|
||||||
|
<div className="text-center mb-12">
|
||||||
|
<span className="text-orange-400 font-mono text-xs font-bold tracking-[0.25em] uppercase">
|
||||||
|
Kontakt
|
||||||
|
</span>
|
||||||
|
<h2 className="text-4xl sm:text-5xl font-black text-white mt-3 mb-4">
|
||||||
|
Projekt anfragen
|
||||||
|
</h2>
|
||||||
|
<p className="text-slate-400 text-lg max-w-xl mx-auto">
|
||||||
|
Sie haben ein IT-Projekt oder eine Frage? Schreiben Sie uns —
|
||||||
|
wir melden uns schnellstmöglich bei Ihnen.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Contact form */}
|
||||||
|
<div className="bg-gray-900 border border-gray-800 rounded-3xl p-8 sm:p-10">
|
||||||
|
<form className="space-y-6">
|
||||||
|
<div className="grid sm:grid-cols-2 gap-6">
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-slate-300 mb-2">Name</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Max Mustermann"
|
||||||
|
className="w-full px-4 py-3 rounded-xl bg-[#111925] border border-gray-700 text-white placeholder-slate-600 focus:outline-none focus:border-orange-500/60 focus:ring-1 focus:ring-orange-500/20 transition-colors"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-slate-300 mb-2">E-Mail</label>
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
placeholder="max@beispiel.de"
|
||||||
|
className="w-full px-4 py-3 rounded-xl bg-[#111925] border border-gray-700 text-white placeholder-slate-600 focus:outline-none focus:border-orange-500/60 focus:ring-1 focus:ring-orange-500/20 transition-colors"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-slate-300 mb-2">Betreff</label>
|
||||||
|
<select className="w-full px-4 py-3 rounded-xl bg-[#111925] border border-gray-700 text-white focus:outline-none focus:border-orange-500/60 focus:ring-1 focus:ring-orange-500/20 transition-colors appearance-none">
|
||||||
|
<option value="">Thema auswählen...</option>
|
||||||
|
<option value="docker">Docker Installation</option>
|
||||||
|
<option value="kubernetes">Kubernetes Setup</option>
|
||||||
|
<option value="proxmox">Proxmox Virtualisierung</option>
|
||||||
|
<option value="hetzner">Hetzner Cloud Infrastruktur</option>
|
||||||
|
<option value="hardware">Hardware & Software</option>
|
||||||
|
<option value="other">Sonstiges</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-slate-300 mb-2">Nachricht</label>
|
||||||
|
<textarea
|
||||||
|
rows={5}
|
||||||
|
placeholder="Beschreiben Sie Ihr Projekt oder Ihre Anfrage..."
|
||||||
|
className="w-full px-4 py-3 rounded-xl bg-[#111925] border border-gray-700 text-white placeholder-slate-600 focus:outline-none focus:border-orange-500/60 focus:ring-1 focus:ring-orange-500/20 transition-colors resize-none"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" className="btn-primary w-full py-4 text-lg">
|
||||||
|
Nachricht senden
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{/* Divider */}
|
||||||
|
<div className="flex items-center gap-4 my-8">
|
||||||
|
<div className="flex-1 h-px bg-gray-800" />
|
||||||
|
<span className="text-slate-600 text-sm">oder direkt</span>
|
||||||
|
<div className="flex-1 h-px bg-gray-800" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Contact info */}
|
||||||
|
<div className="flex flex-col sm:flex-row items-center justify-center gap-6">
|
||||||
|
{contactItems.map((item) => (
|
||||||
|
<a
|
||||||
|
key={item.label}
|
||||||
|
href={item.href}
|
||||||
|
className="flex items-center gap-3 text-slate-300 hover:text-orange-400 transition-colors duration-200 group"
|
||||||
|
>
|
||||||
|
<span className="w-10 h-10 rounded-lg bg-orange-500/10 border border-orange-500/20 flex items-center justify-center text-orange-400 group-hover:bg-orange-500/20 transition-colors duration-200">
|
||||||
|
{item.icon}
|
||||||
|
</span>
|
||||||
|
<div>
|
||||||
|
<div className="text-xs text-slate-500">{item.label}</div>
|
||||||
|
<div className="font-medium">{item.value}</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,168 @@
|
||||||
|
const risks = [
|
||||||
|
{
|
||||||
|
title: "US Cloud Act (2018)",
|
||||||
|
accent: "red",
|
||||||
|
text:
|
||||||
|
"Der Clarifying Lawful Overseas Use of Data Act verpflichtet US-amerikanische Unternehmen, gespeicherte Daten auf Anordnung US-amerikanischer Behoerden herauszugeben - unabhaengig davon, ob die Daten in Europa oder anderswo gespeichert sind. Microsoft, Google, Amazon und alle weiteren US-Konzerne unterliegen diesem Gesetz. Ein europaeischer Serverstandort allein genuegt daher nicht, wenn der Betreiber ein US-Unternehmen ist.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "DSGVO-Konflikt",
|
||||||
|
accent: "red",
|
||||||
|
text:
|
||||||
|
"Die Datenschutz-Grundverordnung (DSGVO) verbietet die Weitergabe personenbezogener Daten an Drittlaender ohne angemessenes Schutzniveau. Der US Cloud Act und die DSGVO stehen damit in direktem Widerspruch: US-Unternehmen koennen bei Herausgabeanordnungen nicht gleichzeitig DSGVO-konform handeln. Dieses Spannungsfeld ist bis heute rechtlich ungeloest.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Wirtschaftsspionage & Datenabfluss",
|
||||||
|
accent: "red",
|
||||||
|
text:
|
||||||
|
"Betriebsgeheimnisse, Kundendaten, Vertraege und strategische Plaene - all das kann durch den Cloud Act fuer US-Behoerden zugreifbar werden. Betroffen sind nicht nur grosse Konzerne: Jedes Unternehmen, das Daten bei US-Anbietern speichert, ist potenziell exponiert. Laut einer Studie des Bitkom haben 75 % der deutschen Unternehmen innerhalb von 3 Jahren Cyberattacken oder Datendiebstahl erlebt.",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const solutions = [
|
||||||
|
{
|
||||||
|
title: "Europaeische Cloud - Hetzner",
|
||||||
|
icon: "shield",
|
||||||
|
text: "Hetzner ist ein deutsches Unternehmen mit Rechenzentren in Deutschland und Finnland. Als europaischer Anbieter unterliegt Hetzner nicht dem US Cloud Act. Ihre Daten bleiben in deutschen Rechenzentren - rechtssicher und DSGVO-konform.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Self-Hosting auf eigenem Server",
|
||||||
|
icon: "server",
|
||||||
|
text: "Mit Docker, Kubernetes oder Proxmox betreiben Sie Ihre Anwendungen auf Infrastruktur, die vollstaendig unter Ihrer Kontrolle liegt. Kein Drittanbieter hat Zugriff - kein Cloud Act, keine versteckten Klauseln, volle Datensouveraenitaet.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Nextcloud statt Google Drive",
|
||||||
|
icon: "cloud",
|
||||||
|
text: "Dateien, Kalender, Kontakte und Office-Dokumente auf Ihrem eigenen Server statt bei Google oder Microsoft. Funktionsgleich, aber ohne Abhaengigkeit von US-Konzernen. Ideal fuer Unternehmen, Arztpraxen, Kanzleien und Behoerden.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Verschluesselung & Datensouveraenitaet",
|
||||||
|
icon: "lock",
|
||||||
|
text: "Ende-zu-Ende-Verschluesselung, SSL/TLS und Festplattenver-schluesselung auf Serverebene. Kombiniert mit europaeischer Infrastruktur ergibt sich ein Schutzniveau, das Cloud-Angeboten grosser US-Konzerne deutlich ueberlegen ist.",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const icons: Record<string, JSX.Element> = {
|
||||||
|
shield: (
|
||||||
|
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
server: (
|
||||||
|
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 12h14M5 12a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v4a2 2 0 01-2 2M5 12a2 2 0 00-2 2v4a2 2 0 002 2h14a2 2 0 002-2v-4a2 2 0 00-2-2m-2-4h.01M17 16h.01" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
cloud: (
|
||||||
|
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 15a4 4 0 004 4h9a5 5 0 10-.1-9.999 5.002 5.002 0 10-9.78 2.096A4.001 4.001 0 003 15z" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
lock: (
|
||||||
|
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function DataSovereignty() {
|
||||||
|
return (
|
||||||
|
<section id="datensouveraenitaet" className="py-24 px-4 sm:px-6 lg:px-8 relative">
|
||||||
|
<div className="absolute inset-0 bg-[#111925]" />
|
||||||
|
<div className="absolute inset-0 bg-grid opacity-30" />
|
||||||
|
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_bottom_left,rgba(239,68,68,0.04)_0%,transparent_60%)]" />
|
||||||
|
|
||||||
|
<div className="max-w-7xl mx-auto relative">
|
||||||
|
|
||||||
|
{/* Header */}
|
||||||
|
<div className="text-center mb-16">
|
||||||
|
<span className="text-orange-400 font-mono text-xs font-bold tracking-[0.25em] uppercase">
|
||||||
|
Datenschutz & Souveraenitaet
|
||||||
|
</span>
|
||||||
|
<h2 className="text-4xl sm:text-5xl font-black text-white mt-3 mb-4">
|
||||||
|
Ihre Daten gehoeren{" "}
|
||||||
|
<span className="text-gradient">Ihnen</span>
|
||||||
|
</h2>
|
||||||
|
<p className="text-slate-400 text-lg max-w-2xl mx-auto">
|
||||||
|
US Cloud Act, DSGVO und Datensouveraenitaet — warum die Wahl
|
||||||
|
Ihrer IT-Infrastruktur ueber mehr als Kosten entscheidet.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Warning banner */}
|
||||||
|
<div className="mb-12 p-5 rounded-2xl border border-red-500/30 bg-red-500/5 flex items-start gap-4">
|
||||||
|
<div className="flex-shrink-0 w-10 h-10 rounded-xl bg-red-500/10 text-red-400 flex items-center justify-center mt-0.5">
|
||||||
|
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-red-400 font-bold text-sm mb-1">Wichtig fuer deutsche Unternehmen</p>
|
||||||
|
<p className="text-slate-400 text-sm leading-relaxed">
|
||||||
|
Wer Daten bei US-amerikanischen Anbietern wie Microsoft Azure, Google Cloud oder AWS speichert, kann sich nicht sicher sein, dass diese Daten nicht auf Anordnung US-amerikanischer Behoerden herausgegeben werden — auch wenn die Server physisch in Deutschland stehen. Der <strong className="text-white">US Cloud Act</strong> hebelt den geografischen Serverstandort als Schutzargument vollstaendig aus.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Risks */}
|
||||||
|
<div className="grid md:grid-cols-3 gap-6 mb-16">
|
||||||
|
{risks.map((risk) => (
|
||||||
|
<div key={risk.title} className="p-6 rounded-2xl bg-gray-900 border border-red-500/20 hover:border-red-500/40 transition-all duration-300">
|
||||||
|
<div className="flex items-center gap-3 mb-4">
|
||||||
|
<div className="w-2 h-2 rounded-full bg-red-400 flex-shrink-0" />
|
||||||
|
<h3 className="text-white font-bold text-base">{risk.title}</h3>
|
||||||
|
</div>
|
||||||
|
<p className="text-slate-400 text-sm leading-relaxed">{risk.text}</p>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Divider with CTA */}
|
||||||
|
<div className="flex items-center gap-6 mb-16">
|
||||||
|
<div className="flex-1 h-px bg-gradient-to-r from-transparent via-gray-700 to-transparent" />
|
||||||
|
<div className="px-6 py-2 rounded-full border border-orange-500/40 bg-orange-500/5 text-orange-400 text-sm font-black tracking-wider whitespace-nowrap">
|
||||||
|
Unsere Loesung
|
||||||
|
</div>
|
||||||
|
<div className="flex-1 h-px bg-gradient-to-r from-transparent via-gray-700 to-transparent" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Solutions */}
|
||||||
|
<div className="grid md:grid-cols-2 gap-6 mb-16">
|
||||||
|
{solutions.map((sol) => (
|
||||||
|
<div key={sol.title} className="flex gap-5 p-6 rounded-2xl bg-gray-900 border border-orange-500/20 hover:border-orange-500/40 transition-all duration-300 hover:-translate-y-0.5">
|
||||||
|
<div className="flex-shrink-0 w-12 h-12 rounded-xl bg-orange-500/10 text-orange-400 flex items-center justify-center">
|
||||||
|
{icons[sol.icon]}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 className="text-white font-bold text-base mb-2">{sol.title}</h3>
|
||||||
|
<p className="text-slate-400 text-sm leading-relaxed">{sol.text}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Bottom callout */}
|
||||||
|
<div className="p-8 rounded-2xl border border-orange-500/30 bg-orange-500/5 text-center">
|
||||||
|
<p className="text-orange-400 font-black text-sm tracking-[0.2em] uppercase mb-2">
|
||||||
|
Digital Denken. Lokal Handeln.
|
||||||
|
</p>
|
||||||
|
<p className="text-white text-xl font-bold mb-2">
|
||||||
|
Europaeische Infrastruktur. Volle Kontrolle. Echter Datenschutz.
|
||||||
|
</p>
|
||||||
|
<p className="text-slate-400 text-sm max-w-xl mx-auto mb-6">
|
||||||
|
Mit MBO-Tech-IT erhalten Sie IT-Infrastruktur, die nicht nur
|
||||||
|
funktioniert, sondern auch rechtssicher und souveraen ist. Keine
|
||||||
|
Abhaengigkeit von US-Konzernen, kein Cloud Act-Risiko.
|
||||||
|
</p>
|
||||||
|
<a
|
||||||
|
href="#contact"
|
||||||
|
className="btn-primary inline-flex px-8 py-3 text-sm"
|
||||||
|
>
|
||||||
|
Beratungsgespraech vereinbaren
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,111 @@
|
||||||
|
import Link from "next/link";
|
||||||
|
import Logo from "./Logo";
|
||||||
|
|
||||||
|
const footerLinks = [
|
||||||
|
{
|
||||||
|
title: "Services",
|
||||||
|
links: [
|
||||||
|
{ label: "Docker Installationen", href: "/#services" },
|
||||||
|
{ label: "Kubernetes", href: "/#services" },
|
||||||
|
{ label: "Proxmox", href: "/#services" },
|
||||||
|
{ label: "Hetzner Cloud", href: "/#services" },
|
||||||
|
{ label: "Hardware & Software", href: "/#services" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Unternehmen",
|
||||||
|
links: [
|
||||||
|
{ label: "Über uns", href: "/#about" },
|
||||||
|
{ label: "Technologien", href: "/#technologies" },
|
||||||
|
{ label: "Kontakt", href: "/#contact" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Rechtliches",
|
||||||
|
links: [
|
||||||
|
{ label: "Impressum", href: "/impressum" },
|
||||||
|
{ label: "Datenschutz", href: "/datenschutz" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function Footer() {
|
||||||
|
const year = new Date().getFullYear();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<footer className="bg-[#111925] border-t border-gray-800">
|
||||||
|
{/* Tagline strip */}
|
||||||
|
<div className="border-b border-gray-800 py-6 px-4">
|
||||||
|
<div className="max-w-7xl mx-auto flex flex-col sm:flex-row items-center justify-between gap-4">
|
||||||
|
<p className="text-2xl sm:text-3xl font-black text-white tracking-tight">
|
||||||
|
<span className="text-orange-400">DIGITAL DENKEN.</span>{" "}
|
||||||
|
<span className="bg-gradient-to-r from-blue-400 to-blue-600 bg-clip-text text-transparent">LOKAL HANDELN.</span>
|
||||||
|
</p>
|
||||||
|
<a
|
||||||
|
href="/#contact"
|
||||||
|
className="btn-primary flex-shrink-0 px-6 py-3 text-sm tracking-wide"
|
||||||
|
>
|
||||||
|
Jetzt starten
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-10 mb-12">
|
||||||
|
{/* Brand */}
|
||||||
|
<div className="lg:col-span-1">
|
||||||
|
<div className="flex items-center gap-3 mb-4">
|
||||||
|
<Logo className="h-8 w-auto" />
|
||||||
|
<div className="flex flex-col leading-tight">
|
||||||
|
<span className="font-black text-white text-base tracking-wider uppercase">
|
||||||
|
MBO-<span className="bg-gradient-to-r from-blue-400 to-blue-600 bg-clip-text text-transparent">TECH-IT</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p className="text-slate-500 text-sm leading-relaxed mb-4">
|
||||||
|
Ihr Spezialist für Docker, Kubernetes, Proxmox und Hetzner Cloud —
|
||||||
|
professionelle IT-Infrastruktur für Ihr Business.
|
||||||
|
</p>
|
||||||
|
<p className="text-orange-500/60 text-xs font-bold tracking-[0.2em] uppercase">
|
||||||
|
Digital Denken. Lokal Handeln.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Links */}
|
||||||
|
{footerLinks.map((group) => (
|
||||||
|
<div key={group.title}>
|
||||||
|
<h4 className="text-white font-bold text-sm mb-4 tracking-wide">{group.title}</h4>
|
||||||
|
<ul className="space-y-2">
|
||||||
|
{group.links.map((link) => (
|
||||||
|
<li key={link.label}>
|
||||||
|
<Link
|
||||||
|
href={link.href}
|
||||||
|
className="text-slate-500 hover:text-orange-400 transition-colors text-sm"
|
||||||
|
>
|
||||||
|
{link.label}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Bottom bar */}
|
||||||
|
<div className="pt-8 border-t border-gray-800 flex flex-col sm:flex-row items-center justify-between gap-4">
|
||||||
|
<p className="text-slate-600 text-sm">
|
||||||
|
© {year} MBO-Tech-IT. Alle Rechte vorbehalten.
|
||||||
|
</p>
|
||||||
|
<div className="flex items-center gap-4 text-slate-600 text-sm">
|
||||||
|
<Link href="/impressum" className="hover:text-orange-400 transition-colors">Impressum</Link>
|
||||||
|
<Link href="/datenschutz" className="hover:text-orange-400 transition-colors">Datenschutz</Link>
|
||||||
|
<span className="flex items-center gap-2">
|
||||||
|
<span className="w-2 h-2 bg-green-500 rounded-full animate-pulse" />
|
||||||
|
Alle Systeme betriebsbereit
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
export default function GearPattern({ opacity = 0.06 }: { opacity?: number }) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="absolute inset-0 overflow-hidden pointer-events-none"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
className="absolute inset-0 w-full h-full"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<defs>
|
||||||
|
{/* Single gear shape as a pattern tile */}
|
||||||
|
<symbol id="gear" viewBox="0 0 60 60">
|
||||||
|
<g transform="translate(30,30)">
|
||||||
|
{/* Outer teeth */}
|
||||||
|
{[0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330].map((angle) => (
|
||||||
|
<rect
|
||||||
|
key={angle}
|
||||||
|
x="-3.5"
|
||||||
|
y="-26"
|
||||||
|
width="7"
|
||||||
|
height="7"
|
||||||
|
rx="1"
|
||||||
|
fill="#f97316"
|
||||||
|
transform={`rotate(${angle})`}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
{/* Outer ring */}
|
||||||
|
<circle cx="0" cy="0" r="18" fill="none" stroke="#f97316" strokeWidth="4" />
|
||||||
|
{/* Inner spokes */}
|
||||||
|
{[0, 60, 120, 180, 240, 300].map((angle) => (
|
||||||
|
<line
|
||||||
|
key={angle}
|
||||||
|
x1="0"
|
||||||
|
y1="0"
|
||||||
|
x2="0"
|
||||||
|
y2="-14"
|
||||||
|
stroke="#f97316"
|
||||||
|
strokeWidth="2.5"
|
||||||
|
transform={`rotate(${angle})`}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
{/* Center hole */}
|
||||||
|
<circle cx="0" cy="0" r="5" fill="none" stroke="#f97316" strokeWidth="3" />
|
||||||
|
</g>
|
||||||
|
</symbol>
|
||||||
|
|
||||||
|
{/* Small gear */}
|
||||||
|
<symbol id="gear-sm" viewBox="0 0 34 34">
|
||||||
|
<g transform="translate(17,17)">
|
||||||
|
{[0, 45, 90, 135, 180, 225, 270, 315].map((angle) => (
|
||||||
|
<rect
|
||||||
|
key={angle}
|
||||||
|
x="-2.5"
|
||||||
|
y="-14.5"
|
||||||
|
width="5"
|
||||||
|
height="5"
|
||||||
|
rx="0.8"
|
||||||
|
fill="#f97316"
|
||||||
|
transform={`rotate(${angle})`}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
<circle cx="0" cy="0" r="9" fill="none" stroke="#f97316" strokeWidth="3" />
|
||||||
|
{[0, 90, 180, 270].map((angle) => (
|
||||||
|
<line
|
||||||
|
key={angle}
|
||||||
|
x1="0"
|
||||||
|
y1="0"
|
||||||
|
x2="0"
|
||||||
|
y2="-7"
|
||||||
|
stroke="#f97316"
|
||||||
|
strokeWidth="2"
|
||||||
|
transform={`rotate(${angle})`}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
<circle cx="0" cy="0" r="3" fill="none" stroke="#f97316" strokeWidth="2" />
|
||||||
|
</g>
|
||||||
|
</symbol>
|
||||||
|
|
||||||
|
{/* Repeating pattern */}
|
||||||
|
<pattern id="gearPattern" x="0" y="0" width="160" height="160" patternUnits="userSpaceOnUse">
|
||||||
|
{/* Large gear top-left */}
|
||||||
|
<use href="#gear" x="10" y="10" width="60" height="60" />
|
||||||
|
{/* Small gear top-right, meshing */}
|
||||||
|
<use href="#gear-sm" x="68" y="22" width="34" height="34" />
|
||||||
|
{/* Large gear bottom-right */}
|
||||||
|
<use href="#gear" x="90" y="90" width="60" height="60" />
|
||||||
|
{/* Small gear bottom-left */}
|
||||||
|
<use href="#gear-sm" x="18" y="104" width="34" height="34" />
|
||||||
|
{/* Tiny center connector dots */}
|
||||||
|
<circle cx="80" cy="56" r="2" fill="#f97316" />
|
||||||
|
<circle cx="56" cy="80" r="2" fill="#f97316" />
|
||||||
|
</pattern>
|
||||||
|
</defs>
|
||||||
|
<rect
|
||||||
|
width="100%"
|
||||||
|
height="100%"
|
||||||
|
fill="url(#gearPattern)"
|
||||||
|
opacity={opacity}
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,111 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useState, useEffect } from "react";
|
||||||
|
import Link from "next/link";
|
||||||
|
import Logo from "./Logo";
|
||||||
|
|
||||||
|
const navLinks = [
|
||||||
|
{ label: "Services", href: "/#services" },
|
||||||
|
{ label: "Pakete & Preise", href: "/pakete" },
|
||||||
|
{ label: "Technologien", href: "/#technologies" },
|
||||||
|
{ label: "Datenschutz", href: "/#datensouveraenitaet" },
|
||||||
|
{ label: "Über uns", href: "/#about" },
|
||||||
|
{ label: "Kontakt", href: "/#contact" },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function Header() {
|
||||||
|
const [scrolled, setScrolled] = useState(false);
|
||||||
|
const [menuOpen, setMenuOpen] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const onScroll = () => setScrolled(window.scrollY > 20);
|
||||||
|
window.addEventListener("scroll", onScroll);
|
||||||
|
return () => window.removeEventListener("scroll", onScroll);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<header
|
||||||
|
className={`fixed top-0 left-0 right-0 z-50 transition-all duration-300 ${
|
||||||
|
scrolled
|
||||||
|
? "bg-[#111925]/95 backdrop-blur-md border-b border-gray-800"
|
||||||
|
: "bg-transparent"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<div className="flex items-center justify-between h-16">
|
||||||
|
{/* Logo */}
|
||||||
|
<Link href="/" className="flex items-center gap-3 group">
|
||||||
|
<Logo className="h-8 w-auto" />
|
||||||
|
<div className="flex flex-col leading-tight">
|
||||||
|
<span className="font-black text-white text-base tracking-wider uppercase">
|
||||||
|
MBO-<span className="text-gradient">TECH-IT</span>
|
||||||
|
</span>
|
||||||
|
<span className="text-[9px] font-semibold tracking-[0.2em] text-orange-400/70 uppercase hidden sm:block">
|
||||||
|
Digital Denken. Lokal Handeln.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
{/* Desktop Nav */}
|
||||||
|
<nav className="hidden md:flex items-center gap-6">
|
||||||
|
{navLinks.map((link) => (
|
||||||
|
<Link
|
||||||
|
key={link.href}
|
||||||
|
href={link.href}
|
||||||
|
className="text-slate-400 hover:text-blue-400 transition-colors text-sm font-medium"
|
||||||
|
>
|
||||||
|
{link.label}
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
<Link
|
||||||
|
href="/#contact"
|
||||||
|
className="btn-nav"
|
||||||
|
>
|
||||||
|
Jetzt anfragen
|
||||||
|
</Link>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{/* Mobile Menu Button */}
|
||||||
|
<button
|
||||||
|
className="md:hidden text-slate-400 hover:text-white transition-colors"
|
||||||
|
onClick={() => setMenuOpen(!menuOpen)}
|
||||||
|
aria-label="Menu"
|
||||||
|
>
|
||||||
|
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
{menuOpen ? (
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
||||||
|
) : (
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
|
||||||
|
)}
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Mobile Menu */}
|
||||||
|
{menuOpen && (
|
||||||
|
<div className="md:hidden bg-[#111925]/98 backdrop-blur-md border-t border-gray-800">
|
||||||
|
<nav className="px-4 py-4 flex flex-col gap-4">
|
||||||
|
{navLinks.map((link) => (
|
||||||
|
<Link
|
||||||
|
key={link.href}
|
||||||
|
href={link.href}
|
||||||
|
className="text-slate-400 hover:text-blue-400 transition-colors text-sm font-medium py-1"
|
||||||
|
onClick={() => setMenuOpen(false)}
|
||||||
|
>
|
||||||
|
{link.label}
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
<Link
|
||||||
|
href="/#contact"
|
||||||
|
className="px-4 py-2 rounded-lg bg-orange-500 hover:bg-orange-400 text-white text-sm font-bold text-center mt-2 transition-colors"
|
||||||
|
onClick={() => setMenuOpen(false)}
|
||||||
|
>
|
||||||
|
Jetzt anfragen
|
||||||
|
</Link>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</header>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
export default function Hero() {
|
||||||
|
return (
|
||||||
|
<section className="relative min-h-screen flex items-center justify-center overflow-hidden">
|
||||||
|
{/* Background grid */}
|
||||||
|
<div className="absolute inset-0 bg-grid opacity-50" />
|
||||||
|
|
||||||
|
{/* Radial gradient glow */}
|
||||||
|
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_center,rgba(249,115,22,0.10)_0%,transparent_65%)]" />
|
||||||
|
|
||||||
|
{/* Floating orbs */}
|
||||||
|
<div className="absolute top-1/4 left-1/4 w-72 h-72 bg-orange-500/5 rounded-full blur-3xl animate-pulse-slow" />
|
||||||
|
<div className="absolute bottom-1/4 right-1/4 w-80 h-80 bg-blue-600/5 rounded-full blur-3xl animate-pulse-slow" />
|
||||||
|
|
||||||
|
<div className="relative z-10 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||||
|
{/* Tagline badge */}
|
||||||
|
<div className="inline-flex items-center gap-2 px-5 py-2 rounded-full border border-orange-500/40 bg-orange-500/10 text-orange-400 text-xs font-black tracking-[0.3em] uppercase mb-8">
|
||||||
|
<span className="w-1.5 h-1.5 bg-orange-400 rounded-full animate-pulse" />
|
||||||
|
Digital Denken. Lokal Handeln.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Headline */}
|
||||||
|
<h1 className="text-5xl sm:text-6xl lg:text-7xl font-black text-white leading-tight mb-6 tracking-tight">
|
||||||
|
Ihre IT-Infrastruktur.{" "}
|
||||||
|
<span className="text-gradient">Professionell.</span>
|
||||||
|
<br />
|
||||||
|
Skalierbar. Zuverlässig.
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
{/* Subheadline */}
|
||||||
|
<p className="text-xl sm:text-2xl text-slate-400 max-w-3xl mx-auto mb-4 leading-relaxed">
|
||||||
|
Von Docker-Containern über Kubernetes-Cluster bis hin zu
|
||||||
|
Proxmox-Virtualisierung auf Hetzner Cloud — wir bringen Ihre
|
||||||
|
IT auf das nächste Level.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* Tech pills */}
|
||||||
|
<div className="flex flex-wrap items-center justify-center gap-3 mb-10">
|
||||||
|
{["Docker", "Kubernetes", "Proxmox", "Hetzner Cloud", "Linux"].map((tech) => (
|
||||||
|
<span
|
||||||
|
key={tech}
|
||||||
|
className="px-3 py-1 rounded-md bg-gray-900 border border-gray-700 text-slate-300 text-sm font-mono"
|
||||||
|
>
|
||||||
|
{tech}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* CTAs */}
|
||||||
|
<div className="flex flex-col sm:flex-row items-center justify-center gap-4">
|
||||||
|
<a
|
||||||
|
href="#contact"
|
||||||
|
className="btn-primary w-full sm:w-auto px-8 py-4 text-lg"
|
||||||
|
>
|
||||||
|
Projekt anfragen
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="#services"
|
||||||
|
className="btn-secondary w-full sm:w-auto px-8 py-4 text-lg"
|
||||||
|
>
|
||||||
|
Services ansehen
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Scroll indicator */}
|
||||||
|
<div className="absolute bottom-8 left-1/2 -translate-x-1/2 flex flex-col items-center gap-2 text-slate-600">
|
||||||
|
<span className="text-xs font-bold tracking-[0.3em] uppercase">Scroll</span>
|
||||||
|
<div className="w-px h-12 bg-gradient-to-b from-slate-600 to-transparent" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,135 @@
|
||||||
|
import type { ReactNode } from "react";
|
||||||
|
import Link from "next/link";
|
||||||
|
import Logo from "./Logo";
|
||||||
|
|
||||||
|
interface LegalLayoutProps {
|
||||||
|
title: string;
|
||||||
|
children: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function LegalLayout({ title, children }: LegalLayoutProps) {
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-[#18212f]">
|
||||||
|
{/* Top tagline bar */}
|
||||||
|
<div className="bg-orange-500 py-2 px-4 text-center">
|
||||||
|
<span className="text-white text-xs font-black tracking-[0.2em] uppercase">
|
||||||
|
Digital Denken. Lokal Handeln.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Header – matches main site */}
|
||||||
|
<header className="bg-[#111925] border-b border-gray-800 sticky top-0 z-50">
|
||||||
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<div className="flex items-center justify-between h-16">
|
||||||
|
<Link href="/" className="flex items-center gap-3 group">
|
||||||
|
<Logo className="h-8 w-auto" />
|
||||||
|
<div className="flex flex-col leading-tight">
|
||||||
|
<span className="font-black text-white text-base tracking-wider uppercase">
|
||||||
|
MBO-
|
||||||
|
<span className="bg-gradient-to-r from-blue-400 to-blue-600 bg-clip-text text-transparent">
|
||||||
|
TECH-IT
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span className="text-[9px] font-semibold tracking-[0.2em] text-orange-400/70 uppercase hidden sm:block">
|
||||||
|
Digital Denken. Lokal Handeln.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<div className="flex items-center gap-6">
|
||||||
|
<Link href="/pakete" className="text-slate-400 hover:text-blue-400 transition-colors text-sm font-medium hidden sm:block">
|
||||||
|
Pakete & Preise
|
||||||
|
</Link>
|
||||||
|
<Link href="/#contact" className="btn-nav">
|
||||||
|
Anfragen
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
href="/"
|
||||||
|
className="flex items-center gap-1.5 text-slate-500 hover:text-orange-400 transition-colors text-sm"
|
||||||
|
>
|
||||||
|
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 19l-7-7m0 0l7-7m-7 7h18" />
|
||||||
|
</svg>
|
||||||
|
Startseite
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
{/* Page hero */}
|
||||||
|
<div className="relative bg-[#111925] border-b border-gray-800 overflow-hidden">
|
||||||
|
<div className="absolute inset-0 bg-grid opacity-40" />
|
||||||
|
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_top_left,rgba(249,115,22,0.08)_0%,transparent_60%)]" />
|
||||||
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12 relative">
|
||||||
|
<div className="flex items-center gap-2 text-xs text-slate-500 mb-4 font-mono">
|
||||||
|
<Link href="/" className="hover:text-orange-400 transition-colors">Home</Link>
|
||||||
|
<span>/</span>
|
||||||
|
<span className="text-orange-400">{title}</span>
|
||||||
|
</div>
|
||||||
|
<h1 className="text-4xl sm:text-5xl font-black text-white">{title}</h1>
|
||||||
|
<div className="w-16 h-1 bg-orange-500 rounded mt-4" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Content */}
|
||||||
|
<main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
|
||||||
|
<div className="grid lg:grid-cols-4 gap-10">
|
||||||
|
{/* Sidebar */}
|
||||||
|
<aside className="lg:col-span-1">
|
||||||
|
<div className="sticky top-24 space-y-2">
|
||||||
|
<p className="text-xs font-bold text-slate-500 uppercase tracking-widest mb-4">Rechtliches</p>
|
||||||
|
<Link
|
||||||
|
href="/impressum"
|
||||||
|
className="flex items-center gap-2 px-4 py-3 rounded-xl bg-gray-900 border border-gray-800 hover:border-orange-500/40 text-slate-300 hover:text-orange-400 transition-all text-sm font-medium group"
|
||||||
|
>
|
||||||
|
<svg className="w-4 h-4 text-orange-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
|
||||||
|
</svg>
|
||||||
|
Impressum
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
href="/datenschutz"
|
||||||
|
className="flex items-center gap-2 px-4 py-3 rounded-xl bg-gray-900 border border-gray-800 hover:border-orange-500/40 text-slate-300 hover:text-orange-400 transition-all text-sm font-medium group"
|
||||||
|
>
|
||||||
|
<svg className="w-4 h-4 text-orange-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
|
||||||
|
</svg>
|
||||||
|
Datenschutz
|
||||||
|
</Link>
|
||||||
|
<div className="mt-6 p-4 rounded-xl bg-orange-500/5 border border-orange-500/20">
|
||||||
|
<p className="text-xs text-slate-400 leading-relaxed">
|
||||||
|
Fragen zu Datenschutz oder rechtlichen Themen?
|
||||||
|
</p>
|
||||||
|
<Link href="/#contact" className="text-xs text-orange-400 font-bold mt-2 block hover:text-orange-300 transition-colors">
|
||||||
|
Kontakt aufnehmen →
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
{/* Main content */}
|
||||||
|
<div className="lg:col-span-3">
|
||||||
|
<div className="bg-gray-900 border border-gray-800 rounded-2xl p-8 sm:p-10 legal-content">
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
{/* Footer */}
|
||||||
|
<footer className="bg-[#111925] border-t border-gray-800 mt-8">
|
||||||
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8 flex flex-col sm:flex-row items-center justify-between gap-4">
|
||||||
|
<p className="text-slate-600 text-sm">
|
||||||
|
© {new Date().getFullYear()} MBO-Tech-IT — Digital Denken. Lokal Handeln.
|
||||||
|
</p>
|
||||||
|
<div className="flex gap-6 text-sm text-slate-600">
|
||||||
|
<Link href="/impressum" className="hover:text-orange-400 transition-colors">Impressum</Link>
|
||||||
|
<Link href="/datenschutz" className="hover:text-orange-400 transition-colors">Datenschutz</Link>
|
||||||
|
<Link href="/" className="hover:text-orange-400 transition-colors">Startseite</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,87 @@
|
||||||
|
"use client";
|
||||||
|
import { useId } from "react";
|
||||||
|
|
||||||
|
type GearDef = {
|
||||||
|
id: string;
|
||||||
|
cx: number;
|
||||||
|
cy: number;
|
||||||
|
r: number;
|
||||||
|
hr: number;
|
||||||
|
tc: number;
|
||||||
|
tw: number;
|
||||||
|
th: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function Logo({ className = "" }: { className?: string }) {
|
||||||
|
const uid = useId();
|
||||||
|
const col = "#f97316";
|
||||||
|
|
||||||
|
// 4 gears in a horizontal chain, two pairs slightly offset vertically
|
||||||
|
// Connector nodes sit between gears
|
||||||
|
const gears: GearDef[] = [
|
||||||
|
// left-outer: small
|
||||||
|
{ id: "g1", cx: 28, cy: 50, r: 12, hr: 4, tc: 8, tw: 4.5, th: 4.5 },
|
||||||
|
// left-inner: large
|
||||||
|
{ id: "g2", cx: 68, cy: 50, r: 18, hr: 6, tc: 12, tw: 5.5, th: 5.5 },
|
||||||
|
// right-inner: large
|
||||||
|
{ id: "g3", cx: 112, cy: 50, r: 18, hr: 6, tc: 12, tw: 5.5, th: 5.5 },
|
||||||
|
// right-outer: small
|
||||||
|
{ id: "g4", cx: 152, cy: 50, r: 12, hr: 4, tc: 8, tw: 4.5, th: 4.5 },
|
||||||
|
];
|
||||||
|
|
||||||
|
// Connector nodes between gears
|
||||||
|
const nodes = [
|
||||||
|
{ cx: 48, cy: 50 }, // between g1 and g2
|
||||||
|
{ cx: 90, cy: 50 }, // between g2 and g3
|
||||||
|
{ cx: 132, cy: 50 }, // between g3 and g4
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 180 100"
|
||||||
|
className={className}
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
aria-label="MBO-Tech-IT Logo"
|
||||||
|
>
|
||||||
|
<defs>
|
||||||
|
{gears.map((g) => (
|
||||||
|
<mask key={g.id} id={`${uid}-${g.id}`}>
|
||||||
|
<rect width="200" height="200" fill="black" />
|
||||||
|
<circle cx={g.cx} cy={g.cy} r={g.r + g.th + 1} fill="white" />
|
||||||
|
<circle cx={g.cx} cy={g.cy} r={g.hr} fill="black" />
|
||||||
|
</mask>
|
||||||
|
))}
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
{/* Gears */}
|
||||||
|
{gears.map((g) => {
|
||||||
|
const angles = Array.from({ length: g.tc }, (_, i) => (360 / g.tc) * i);
|
||||||
|
return (
|
||||||
|
<g key={g.id} mask={`url(#${uid}-${g.id})`}>
|
||||||
|
{angles.map((a) => (
|
||||||
|
<rect
|
||||||
|
key={a}
|
||||||
|
x={g.cx - g.tw / 2}
|
||||||
|
y={g.cy - g.r - g.th}
|
||||||
|
width={g.tw}
|
||||||
|
height={g.th + 1}
|
||||||
|
rx="0.8"
|
||||||
|
fill={col}
|
||||||
|
transform={`rotate(${a}, ${g.cx}, ${g.cy})`}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
<circle cx={g.cx} cy={g.cy} r={g.r} fill={col} />
|
||||||
|
</g>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
|
||||||
|
{/* Connector nodes */}
|
||||||
|
{nodes.map(({ cx, cy }) => (
|
||||||
|
<g key={`n-${cx}`}>
|
||||||
|
<circle cx={cx} cy={cy} r={5} fill={col} />
|
||||||
|
<circle cx={cx} cy={cy} r={2.5} fill="white" fillOpacity="0.3" />
|
||||||
|
</g>
|
||||||
|
))}
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,142 @@
|
||||||
|
const services = [
|
||||||
|
{
|
||||||
|
icon: (
|
||||||
|
<svg viewBox="0 0 24 24" className="w-8 h-8" fill="currentColor">
|
||||||
|
<path d="M19 3H5C3.9 3 3 3.9 3 5v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 14l-5-5 1.41-1.41L12 14.17l7.59-7.59L21 8l-9 9z" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
title: "Hardware & Software",
|
||||||
|
description:
|
||||||
|
"Beratung, Beschaffung und Konfiguration von Hardware sowie Software-Lösungen. Von der Auswahl bis zur Inbetriebnahme alles aus einer Hand.",
|
||||||
|
features: ["Hardware-Beratung", "Software-Lizenzierung", "System-Konfiguration", "IT-Support"],
|
||||||
|
accent: "orange",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: (
|
||||||
|
<svg viewBox="0 0 24 24" className="w-8 h-8" fill="currentColor">
|
||||||
|
<path d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 10.99h7c-.53 4.12-3.28 7.79-7 8.94V12H5V6.3l7-3.11v8.8z" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
title: "Netzwerk & Sicherheit",
|
||||||
|
description:
|
||||||
|
"Sichere Netzwerkinfrastruktur und IT-Sicherheitslösungen. Firewall-Konfiguration, VPN-Setups und Hardening für Ihre Server und Dienste.",
|
||||||
|
features: ["Firewall & VPN", "SSL/TLS Management", "Server Hardening", "Monitoring"],
|
||||||
|
accent: "blue",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: (
|
||||||
|
<svg viewBox="0 0 24 24" className="w-8 h-8" fill="currentColor">
|
||||||
|
<path d="M4 1h16a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1zm0 8h16a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1v-4a1 1 0 0 1 1-1zm0 8h16a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1v-4a1 1 0 0 1 1-1z" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
title: "Cloud Infrastruktur",
|
||||||
|
description:
|
||||||
|
"Kosteneffiziente und skalierbare Cloud-Server-Setups. Netzwerkkonfiguration, automatisiertes Deployment und Infrastruktur als Code für Ihre Workloads.",
|
||||||
|
features: ["Server-Provisionierung", "Netzwerk & Firewall", "Load Balancer", "Terraform/Ansible"],
|
||||||
|
accent: "orange",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: (
|
||||||
|
<svg viewBox="0 0 24 24" className="w-8 h-8" fill="currentColor">
|
||||||
|
<path d="M13.5 2c-5.629 0-10.212 4.436-10.475 10h-3.025l4 5.917 4-5.917h-2.516c.26-4.068 3.647-7.333 7.516-7.333 4.136 0 7.5 3.364 7.5 7.5s-3.364 7.5-7.5 7.5c-2.136 0-4.065-.888-5.464-2.318l-1.44 2.133c1.799 1.722 4.257 2.785 6.904 2.785 5.514 0 10-4.486 10-10s-4.486-10-10-10z" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
title: "Docker Installationen",
|
||||||
|
description:
|
||||||
|
"Professionelle Einrichtung und Verwaltung von Docker-Umgebungen. Von der ersten Containerisierung bis hin zu komplexen Multi-Container-Setups mit Docker Compose.",
|
||||||
|
features: ["Docker Engine Setup", "Docker Compose", "Registry Management", "Container-Optimierung"],
|
||||||
|
accent: "blue",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: (
|
||||||
|
<svg viewBox="0 0 24 24" className="w-8 h-8" fill="currentColor">
|
||||||
|
<path d="M20 3H4a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h16a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1zm-9 14H5v-2h6v2zm0-4H5v-2h6v2zm0-4H5V7h6v2zm8 8h-6v-2h6v2zm0-4h-6v-2h6v2zm0-4h-6V7h6v2z" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
title: "Proxmox Virtualisierung",
|
||||||
|
description:
|
||||||
|
"Enterprise-Virtualisierung mit Proxmox VE. Aufbau von Hypervisor-Clustern, VM- und LXC-Management sowie Hochverfügbarkeits-Konfigurationen.",
|
||||||
|
features: ["Proxmox VE Setup", "VM & LXC Management", "HA-Cluster", "Backup-Strategien"],
|
||||||
|
accent: "orange",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: (
|
||||||
|
<svg viewBox="0 0 24 24" className="w-8 h-8" fill="currentColor">
|
||||||
|
<path d="M10.204 14.35l.007.01-.999 2.413a5.171 5.171 0 0 1-2.075-2.597l2.578-.437.49.61zm.022-4.6l.499.611-.997 2.413-2.578-.437a5.171 5.171 0 0 1 2.076-2.587zm.73 1.879l1.249-.417-.003-2.619-1.249-.416a3.6 3.6 0 0 0-.713.833l.716 1.396-.716 1.39a3.6 3.6 0 0 0 .716.833zm4.103 4.348l-2.578.437-.998-2.413.007-.01.49-.61 2.578.437a5.171 5.171 0 0 1-1.499 2.159zm.02-7.028l-2.578.437-1.001 2.413.007.01.49.61 2.578-.437a5.171 5.171 0 0 0-1.496-3.033zm-1.502 5.516l.999-2.413-.499-.611-1.001.334.001 2.286.5.404zm2.998-2.413l-2.578-.437.499.611-.001 2.619 1.25.417a3.6 3.6 0 0 0 .83-3.21zM12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2z" />
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
title: "Kubernetes Orchestrierung",
|
||||||
|
description:
|
||||||
|
"Skalierbare Container-Orchestrierung mit Kubernetes. Aufbau und Verwaltung von K8s-Clustern für hochverfügbare, produktionsreife Anwendungen.",
|
||||||
|
features: ["Cluster-Setup", "Helm Charts", "Auto-Scaling", "Monitoring & Logging"],
|
||||||
|
accent: "blue",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const colorMap = {
|
||||||
|
orange: {
|
||||||
|
border: "border-orange-500/20 hover:border-orange-500/50",
|
||||||
|
icon: "text-orange-400",
|
||||||
|
iconBg: "bg-orange-500/10",
|
||||||
|
dot: "bg-orange-400",
|
||||||
|
shadow: "hover:shadow-orange-500/10",
|
||||||
|
},
|
||||||
|
blue: {
|
||||||
|
border: "border-blue-500/20 hover:border-blue-500/50",
|
||||||
|
icon: "text-blue-400",
|
||||||
|
iconBg: "bg-blue-500/10",
|
||||||
|
dot: "bg-blue-400",
|
||||||
|
shadow: "hover:shadow-blue-500/10",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function Services() {
|
||||||
|
return (
|
||||||
|
<section id="services" className="py-24 px-4 sm:px-6 lg:px-8 relative">
|
||||||
|
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_top,rgba(37,99,235,0.05)_0%,transparent_60%)]" />
|
||||||
|
|
||||||
|
<div className="max-w-7xl mx-auto relative">
|
||||||
|
{/* Section header */}
|
||||||
|
<div className="text-center mb-16">
|
||||||
|
<span className="text-orange-400 font-mono text-xs font-bold tracking-[0.25em] uppercase">
|
||||||
|
Leistungen
|
||||||
|
</span>
|
||||||
|
<h2 className="text-4xl sm:text-5xl font-black text-white mt-3 mb-4">
|
||||||
|
Unsere Services
|
||||||
|
</h2>
|
||||||
|
<p className="text-slate-400 text-lg max-w-2xl mx-auto">
|
||||||
|
Professionelle IT-Lösungen für moderne Infrastruktur — von
|
||||||
|
der Containerisierung bis zur vollständigen Cloud-Migration.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Services grid */}
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
|
{services.map((service) => {
|
||||||
|
const c = colorMap[service.accent as keyof typeof colorMap];
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={service.title}
|
||||||
|
className={`group p-6 rounded-2xl bg-gray-900 border ${c.border} transition-all duration-300 hover:-translate-y-1 hover:shadow-xl ${c.shadow}`}
|
||||||
|
>
|
||||||
|
<div className={`w-14 h-14 rounded-xl ${c.iconBg} ${c.icon} flex items-center justify-center mb-5`}>
|
||||||
|
{service.icon}
|
||||||
|
</div>
|
||||||
|
<h3 className="text-xl font-bold text-white mb-3">{service.title}</h3>
|
||||||
|
<p className="text-slate-400 text-sm leading-relaxed mb-5">{service.description}</p>
|
||||||
|
<ul className="space-y-2">
|
||||||
|
{service.features.map((feature) => (
|
||||||
|
<li key={feature} className="flex items-center gap-2 text-sm text-slate-300">
|
||||||
|
<span className={`w-1.5 h-1.5 rounded-full ${c.dot} flex-shrink-0`} />
|
||||||
|
{feature}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
export default function TaglineBanner() {
|
||||||
|
const phrase = "DIGITAL DENKEN. LOKAL HANDELN.";
|
||||||
|
const items = Array(12).fill(phrase);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="relative overflow-hidden bg-orange-500 py-3 select-none">
|
||||||
|
<div className="flex animate-ticker whitespace-nowrap">
|
||||||
|
{items.map((text, i) => (
|
||||||
|
<span
|
||||||
|
key={i}
|
||||||
|
className="inline-flex items-center gap-6 px-6 text-white font-black text-sm tracking-[0.2em]"
|
||||||
|
>
|
||||||
|
{text}
|
||||||
|
<span className="text-orange-200 opacity-60">●</span>
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,201 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
const techStack = [
|
||||||
|
{
|
||||||
|
name: "Docker",
|
||||||
|
category: "Container",
|
||||||
|
color: "text-blue-400",
|
||||||
|
description:
|
||||||
|
"Stellen Sie sich Docker wie eine standardisierte Versandbox vor: Ihre Anwendung und alles, was sie zum Laufen braucht, wird in eine einheitliche Box verpackt. Diese Box funktioniert auf jedem Rechner identisch - egal ob auf Ihrem Laptop, dem Firmenserver oder in der Cloud. Schluss mit 'Bei mir lauft es doch!'. Docker macht Software-Installationen zuverlassig und reproduzierbar.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Kubernetes",
|
||||||
|
category: "Orchestrierung",
|
||||||
|
color: "text-blue-400",
|
||||||
|
description:
|
||||||
|
"Kubernetes ist der Dirigent Ihres Container-Orchesters. Wenn Sie viele Docker-Anwendungen gleichzeitig betreiben, sorgt Kubernetes dafur, dass immer genug davon laufen, startet automatisch neue, wenn eine ausfallt, und verteilt die Last gleichmaessig. Das Ergebnis: Ihre Anwendung bleibt immer erreichbar - auch wenn einzelne Server ausfallen oder die Nutzerzahl plotzlich steigt.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Proxmox VE",
|
||||||
|
category: "Virtualisierung",
|
||||||
|
color: "text-orange-400",
|
||||||
|
description:
|
||||||
|
"Proxmox verwandelt einen einzigen leistungsstarken Server in viele virtuelle Computer. Statt funf separate Maschinen zu kaufen, nutzen Sie eine - und teilen sie in funf logische Bereiche auf. Das spart Strom, Platz und Geld. Jeder virtuelle Computer lauft vollstandig isoliert, als ware er ein echter eigener Server. Ideal fur Homelab-Setups oder kleine Unternehmen.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Hetzner Cloud",
|
||||||
|
category: "Cloud",
|
||||||
|
color: "text-orange-400",
|
||||||
|
description:
|
||||||
|
"Hetzner ist ein deutsches Rechenzentrum, das Server auf Abruf vermietet - zu einem Bruchteil der Kosten von Amazon oder Google. Sie zahlen nur, was Sie nutzen, und Ihre Daten liegen in Deutschland (DSGVO-konform). Wir nutzen Hetzner, um Ihnen professionelle Cloud-Infrastruktur zu fairen Preisen anzubieten: zuverlassig, schnell und datenschutzfreundlich.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Terraform",
|
||||||
|
category: "Infrastruktur als Code",
|
||||||
|
color: "text-purple-400",
|
||||||
|
description:
|
||||||
|
"Terraform ist wie ein Bauplan fur Ihre IT-Infrastruktur. Statt Server manuell anzuklicken und einzurichten, wird alles als Code aufgeschrieben. Dieser Code lasst sich in Sekunden ausfuhren - und baut Ihre gesamte Infrastruktur automatisch auf. Anderungen sind nachvollziehbar, wiederholbar und sicher ruckgangig zu machen.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Ansible",
|
||||||
|
category: "Automatisierung",
|
||||||
|
color: "text-purple-400",
|
||||||
|
description:
|
||||||
|
"Ansible ist Ihr digitaler Hausmeister: Es erledigt wiederkehrende Aufgaben auf Servern automatisch. Updates einspielen, Konfigurationen angleichen, Software installieren - auf einem oder hundert Servern gleichzeitig, ohne manuelle Eingriffe. Das spart Zeit, verhindert Fehler und sorgt dafur, dass alle Systeme immer in einem definierten, sicheren Zustand sind.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Linux",
|
||||||
|
category: "Betriebssystem",
|
||||||
|
color: "text-green-400",
|
||||||
|
description:
|
||||||
|
"Linux ist das meistgenutzte Serverbetriebssystem der Welt - kostenlos, stabil und sicher. Anders als Windows lauft Linux auf Servern oft jahrelang ohne Neustart. Es ist die Grundlage fur fast alles im Internet: Webseiten, Apps, Cloud-Dienste. Wir setzen auf Linux, weil es uns maximale Kontrolle, Stabilitat und Sicherheit fur Ihre Infrastruktur bietet.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Nginx",
|
||||||
|
category: "Webserver",
|
||||||
|
color: "text-green-400",
|
||||||
|
description:
|
||||||
|
"Nginx (ausgesprochen 'Engine-X') ist der Turksteher Ihrer Webserver-Infrastruktur. Wenn jemand Ihre Webseite aufruft, nimmt Nginx die Anfrage entgegen und leitet sie an den richtigen Dienst weiter - blitzschnell und fur Tausende gleichzeitige Besucher ausgelegt. Er kann auch SSL-Verschlusselung (das 'https://') bereitstellen und als Sicherheitsschicht dienen.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Traefik",
|
||||||
|
category: "Reverse Proxy",
|
||||||
|
color: "text-cyan-400",
|
||||||
|
description:
|
||||||
|
"Traefik ist ein intelligenter Verkehrsregler fur Ihre Anwendungen. Wenn Sie viele Dienste auf einem Server betreiben - z.B. Nextcloud, Paperless, eine Webseite - erkennt Traefik automatisch, welcher Dienst unter welcher Adresse erreichbar sein soll, und stellt SSL-Zertifikate gleich kostenlos dazu. Kein manuelles Konfigurieren mehr: Traefik lernt selbst, was wo lauft.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Grafana",
|
||||||
|
category: "Monitoring",
|
||||||
|
color: "text-yellow-400",
|
||||||
|
description:
|
||||||
|
"Grafana verwandelt trockene Serverdaten in ubersichtliche, bunte Dashboards. Sie sehen auf einen Blick: Wie viel CPU nutzt mein Server? Wie viel Speicher ist frei? Gibt es Fehler? Wir richten Grafana so ein, dass Sie jederzeit den Gesundheitszustand Ihrer Infrastruktur uberblicken - wie ein Cockpit fur Ihre IT.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Prometheus",
|
||||||
|
category: "Monitoring",
|
||||||
|
color: "text-yellow-400",
|
||||||
|
description:
|
||||||
|
"Prometheus ist der fleissige Datensammler hinter Grafana. Er fragt alle paar Sekunden Ihre Server ab und speichert diese Messwerte fur Grafana. Prometheus kann auch Alarm schlagen, wenn etwas nicht stimmt - zum Beispiel wenn ein Server zu voll wird oder ein Dienst nicht mehr antwortet. So erfahren wir Probleme, bevor Sie sie uberhaupt bemerken.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "GitLab CI",
|
||||||
|
category: "CI/CD",
|
||||||
|
color: "text-orange-400",
|
||||||
|
description:
|
||||||
|
"GitLab CI automatisiert den Weg vom geschriebenen Code bis zum laufenden Programm. Jedes Mal, wenn Code geandert wird, startet GitLab automatisch Tests, pruft die Qualitat und spielt die Anderung auf den Server aus - alles ohne manuellen Aufwand. Das Ergebnis: Neue Funktionen und Sicherheitsupdates kommen schneller und zuverlassiger bei Ihnen an.",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const stats = [
|
||||||
|
{ value: "99.9%", label: "Uptime-Garantie" },
|
||||||
|
{ value: "24/7", label: "Support & Monitoring" },
|
||||||
|
{ value: "100+", label: "Deployments" },
|
||||||
|
{ value: "5+", label: "Jahre Erfahrung" },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function Technologies() {
|
||||||
|
const [active, setActive] = useState<string | null>(null);
|
||||||
|
const activeTech = techStack.find((t) => t.name === active);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section id="technologies" className="py-24 px-4 sm:px-6 lg:px-8 relative">
|
||||||
|
<div className="absolute inset-0 bg-[#111925]" />
|
||||||
|
<div className="absolute inset-0 bg-grid opacity-40" />
|
||||||
|
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_center,rgba(249,115,22,0.06)_0%,transparent_70%)]" />
|
||||||
|
|
||||||
|
<div className="max-w-7xl mx-auto relative">
|
||||||
|
{/* Section header */}
|
||||||
|
<div className="text-center mb-16">
|
||||||
|
<span className="text-orange-400 font-mono text-xs font-bold tracking-[0.25em] uppercase">
|
||||||
|
Tech-Stack
|
||||||
|
</span>
|
||||||
|
<h2 className="text-4xl sm:text-5xl font-black text-white mt-3 mb-4">
|
||||||
|
Unsere Technologien
|
||||||
|
</h2>
|
||||||
|
<p className="text-slate-400 text-lg max-w-2xl mx-auto">
|
||||||
|
Klicken Sie auf eine Technologie und erhalten Sie eine
|
||||||
|
verstandliche Erklarung - ganz ohne Fachwissen.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Tech grid */}
|
||||||
|
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 gap-4 mb-20">
|
||||||
|
{techStack.map((tech) => (
|
||||||
|
<button
|
||||||
|
key={tech.name}
|
||||||
|
onClick={() => setActive(tech.name)}
|
||||||
|
className="group flex flex-col items-center gap-2 p-4 rounded-xl border bg-gray-900 border-gray-800 hover:border-orange-500/50 hover:-translate-y-1 transition-all duration-300 w-full"
|
||||||
|
>
|
||||||
|
<span className="text-xs text-orange-500/70 font-mono">{tech.category}</span>
|
||||||
|
<span className="font-semibold text-sm text-center text-white group-hover:text-orange-400 transition-colors">
|
||||||
|
{tech.name}
|
||||||
|
</span>
|
||||||
|
<span className="text-[10px] text-slate-600 font-medium mt-0.5">Details</span>
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Stats */}
|
||||||
|
<div className="grid grid-cols-2 lg:grid-cols-4 gap-6">
|
||||||
|
{stats.map((stat) => (
|
||||||
|
<div
|
||||||
|
key={stat.label}
|
||||||
|
className="text-center p-6 rounded-2xl bg-gray-900 border border-gray-800"
|
||||||
|
>
|
||||||
|
<div className="text-4xl font-black text-orange-400 mb-2">{stat.value}</div>
|
||||||
|
<div className="text-slate-400 text-sm">{stat.label}</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Modal overlay */}
|
||||||
|
{activeTech && (
|
||||||
|
<div
|
||||||
|
className="fixed inset-0 z-50 flex items-center justify-center p-4"
|
||||||
|
onClick={() => setActive(null)}
|
||||||
|
>
|
||||||
|
{/* Backdrop */}
|
||||||
|
<div className="absolute inset-0 bg-black/70 backdrop-blur-sm" />
|
||||||
|
|
||||||
|
{/* Modal */}
|
||||||
|
<div
|
||||||
|
className="relative z-10 w-full max-w-lg bg-[#1a2535] border border-orange-500/30 rounded-2xl shadow-2xl shadow-black/60 p-8"
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
{/* Close button */}
|
||||||
|
<button
|
||||||
|
onClick={() => setActive(null)}
|
||||||
|
className="absolute top-4 right-4 w-8 h-8 rounded-lg bg-gray-800 hover:bg-gray-700 text-slate-400 hover:text-white transition-all flex items-center justify-center text-sm font-bold"
|
||||||
|
aria-label="Schliessen"
|
||||||
|
>
|
||||||
|
x
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{/* Header */}
|
||||||
|
<div className="mb-5 pr-8">
|
||||||
|
<span className="text-orange-400 font-mono text-xs tracking-widest uppercase">
|
||||||
|
{activeTech.category}
|
||||||
|
</span>
|
||||||
|
<h3 className="text-2xl font-black text-white mt-1">{activeTech.name}</h3>
|
||||||
|
<div className="w-10 h-0.5 bg-orange-500 rounded mt-3" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Description */}
|
||||||
|
<p className="text-slate-300 text-base leading-relaxed">
|
||||||
|
{activeTech.description}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* Footer hint */}
|
||||||
|
<p className="text-slate-600 text-xs mt-6 text-center">
|
||||||
|
Klick ausserhalb oder x zum Schliessen
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,763 @@
|
||||||
|
# Website-Erweiterung Implementation Plan
|
||||||
|
|
||||||
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||||
|
|
||||||
|
**Goal:** Zwei neue Service-Karten, eine DSGVO/GoBD/Paperless-Sektion und drei Spezialeffekte (Scroll-Reveal, Typewriter, Counter) zur bestehenden MBO-Tech-IT Next.js Website hinzufügen.
|
||||||
|
|
||||||
|
**Architecture:** Alle Effekte werden mit nativen Web-APIs (Intersection Observer, requestAnimationFrame) ohne externe Packages implementiert. Neue Komponenten folgen dem bestehenden Muster (Tailwind, dark theme, orange/blau Akzente). `"use client"` nur wo Browser-APIs benötigt werden.
|
||||||
|
|
||||||
|
**Tech Stack:** Next.js 14 (App Router), TypeScript, Tailwind CSS, Intersection Observer API
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Dateiübersicht
|
||||||
|
|
||||||
|
| Aktion | Datei | Zweck |
|
||||||
|
|--------|-------|-------|
|
||||||
|
| Create | `components/ScrollReveal.tsx` | Wiederverwendbarer Wrapper mit Intersection Observer |
|
||||||
|
| Create | `hooks/useTypewriter.ts` | Hook für Typewriter-Effekt |
|
||||||
|
| Create | `components/StatsBar.tsx` | Animierte Statistik-Leiste mit Counter |
|
||||||
|
| Create | `components/PaperlessSection.tsx` | DSGVO & GoBD mit Paperless Sektion |
|
||||||
|
| Modify | `components/Services.tsx` | 2 neue Karten (WLAN, WebApps) + ScrollReveal |
|
||||||
|
| Modify | `components/Hero.tsx` | Typewriter-Effekt integrieren |
|
||||||
|
| Modify | `app/page.tsx` | StatsBar + PaperlessSection einbinden |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Task 1: ScrollReveal-Komponente
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Create: `components/ScrollReveal.tsx`
|
||||||
|
|
||||||
|
- [ ] **Step 1: Komponente erstellen**
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// components/ScrollReveal.tsx
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useEffect, useRef, useState } from "react";
|
||||||
|
|
||||||
|
interface ScrollRevealProps {
|
||||||
|
children: React.ReactNode;
|
||||||
|
delay?: number;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ScrollReveal({ children, delay = 0, className = "" }: ScrollRevealProps) {
|
||||||
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const el = ref.current;
|
||||||
|
if (!el) return;
|
||||||
|
|
||||||
|
const observer = new IntersectionObserver(
|
||||||
|
([entry]) => {
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
setVisible(true);
|
||||||
|
observer.disconnect();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ threshold: 0.1 }
|
||||||
|
);
|
||||||
|
|
||||||
|
observer.observe(el);
|
||||||
|
return () => observer.disconnect();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={ref}
|
||||||
|
className={className}
|
||||||
|
style={{
|
||||||
|
opacity: visible ? 1 : 0,
|
||||||
|
transform: visible ? "translateY(0)" : "translateY(24px)",
|
||||||
|
transition: `opacity 500ms ease-out ${delay}ms, transform 500ms ease-out ${delay}ms`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 2: Dev-Server starten und Datei prüfen**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Öffne http://localhost:3000 — Seite soll unverändert aussehen (Komponente noch nicht eingebunden).
|
||||||
|
|
||||||
|
- [ ] **Step 3: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add components/ScrollReveal.tsx
|
||||||
|
git commit -m "feat: add ScrollReveal component with Intersection Observer"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Task 2: useTypewriter Hook
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Create: `hooks/useTypewriter.ts`
|
||||||
|
|
||||||
|
- [ ] **Step 1: `hooks/` Ordner anlegen und Hook erstellen**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p hooks
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// hooks/useTypewriter.ts
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
export function useTypewriter(words: string[], typingSpeed = 80, deletingSpeed = 40, pauseMs = 2000) {
|
||||||
|
const [displayed, setDisplayed] = useState("");
|
||||||
|
const [wordIndex, setWordIndex] = useState(0);
|
||||||
|
const [isDeleting, setIsDeleting] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const current = words[wordIndex % words.length];
|
||||||
|
|
||||||
|
const timeout = setTimeout(() => {
|
||||||
|
if (!isDeleting) {
|
||||||
|
setDisplayed(current.slice(0, displayed.length + 1));
|
||||||
|
if (displayed.length + 1 === current.length) {
|
||||||
|
setTimeout(() => setIsDeleting(true), pauseMs);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setDisplayed(current.slice(0, displayed.length - 1));
|
||||||
|
if (displayed.length - 1 === 0) {
|
||||||
|
setIsDeleting(false);
|
||||||
|
setWordIndex((i) => i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, isDeleting ? deletingSpeed : typingSpeed);
|
||||||
|
|
||||||
|
return () => clearTimeout(timeout);
|
||||||
|
}, [displayed, isDeleting, wordIndex, words, typingSpeed, deletingSpeed, pauseMs]);
|
||||||
|
|
||||||
|
return displayed;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 2: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add hooks/useTypewriter.ts
|
||||||
|
git commit -m "feat: add useTypewriter hook"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Task 3: Hero — Typewriter-Effekt integrieren
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `components/Hero.tsx`
|
||||||
|
|
||||||
|
- [ ] **Step 1: Hero.tsx anpassen**
|
||||||
|
|
||||||
|
Ersetze die gesamte Datei `components/Hero.tsx` mit folgendem Inhalt:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// components/Hero.tsx
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useTypewriter } from "@/hooks/useTypewriter";
|
||||||
|
|
||||||
|
export default function Hero() {
|
||||||
|
const typed = useTypewriter(["Professionell.", "DSGVO-konform.", "Zuverlässig.", "Skalierbar."]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="relative min-h-screen flex items-center justify-center overflow-hidden">
|
||||||
|
{/* Background grid */}
|
||||||
|
<div className="absolute inset-0 bg-grid opacity-50" />
|
||||||
|
|
||||||
|
{/* Radial gradient glow */}
|
||||||
|
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_center,rgba(249,115,22,0.10)_0%,transparent_65%)]" />
|
||||||
|
|
||||||
|
{/* Floating orbs */}
|
||||||
|
<div className="absolute top-1/4 left-1/4 w-72 h-72 bg-orange-500/5 rounded-full blur-3xl animate-pulse-slow" />
|
||||||
|
<div className="absolute bottom-1/4 right-1/4 w-80 h-80 bg-blue-600/5 rounded-full blur-3xl animate-pulse-slow" />
|
||||||
|
|
||||||
|
<div className="relative z-10 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||||
|
{/* Tagline badge */}
|
||||||
|
<div className="inline-flex items-center gap-2 px-5 py-2 rounded-full border border-orange-500/40 bg-orange-500/10 text-orange-400 text-xs font-black tracking-[0.3em] uppercase mb-8">
|
||||||
|
<span className="w-1.5 h-1.5 bg-orange-400 rounded-full animate-pulse" />
|
||||||
|
Digital Denken. Lokal Handeln.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Headline */}
|
||||||
|
<h1 className="text-5xl sm:text-6xl lg:text-7xl font-black text-white leading-tight mb-6 tracking-tight">
|
||||||
|
Ihre IT-Infrastruktur.{" "}
|
||||||
|
<span className="text-gradient">
|
||||||
|
{typed}
|
||||||
|
<span className="animate-pulse">|</span>
|
||||||
|
</span>
|
||||||
|
<br />
|
||||||
|
Skalierbar. Zuverlässig.
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
{/* Subheadline */}
|
||||||
|
<p className="text-xl sm:text-2xl text-slate-400 max-w-3xl mx-auto mb-4 leading-relaxed">
|
||||||
|
Von Docker-Containern über Kubernetes-Cluster bis hin zu
|
||||||
|
Proxmox-Virtualisierung auf Hetzner Cloud — wir bringen Ihre
|
||||||
|
IT auf das nächste Level.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* Tech pills */}
|
||||||
|
<div className="flex flex-wrap items-center justify-center gap-3 mb-10">
|
||||||
|
{["Docker", "Kubernetes", "Proxmox", "Hetzner Cloud", "Linux"].map((tech) => (
|
||||||
|
<span
|
||||||
|
key={tech}
|
||||||
|
className="px-3 py-1 rounded-md bg-gray-900 border border-gray-700 text-slate-300 text-sm font-mono"
|
||||||
|
>
|
||||||
|
{tech}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* CTAs */}
|
||||||
|
<div className="flex flex-col sm:flex-row items-center justify-center gap-4">
|
||||||
|
<a href="#contact" className="btn-primary w-full sm:w-auto px-8 py-4 text-lg">
|
||||||
|
Projekt anfragen
|
||||||
|
</a>
|
||||||
|
<a href="#services" className="btn-secondary w-full sm:w-auto px-8 py-4 text-lg">
|
||||||
|
Services ansehen
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Scroll indicator */}
|
||||||
|
<div className="absolute bottom-8 left-1/2 -translate-x-1/2 flex flex-col items-center gap-2 text-slate-600">
|
||||||
|
<span className="text-xs font-bold tracking-[0.3em] uppercase">Scroll</span>
|
||||||
|
<div className="w-px h-12 bg-gradient-to-b from-slate-600 to-transparent" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 2: Im Browser prüfen**
|
||||||
|
|
||||||
|
Öffne http://localhost:3000 — der Hero-Text soll zwischen "Professionell.", "DSGVO-konform.", "Zuverlässig.", "Skalierbar." wechseln mit Cursor `|`.
|
||||||
|
|
||||||
|
- [ ] **Step 3: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add components/Hero.tsx hooks/useTypewriter.ts
|
||||||
|
git commit -m "feat: add typewriter effect to Hero headline"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Task 4: StatsBar — Animierte Statistiken
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Create: `components/StatsBar.tsx`
|
||||||
|
|
||||||
|
- [ ] **Step 1: Komponente erstellen**
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// components/StatsBar.tsx
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useEffect, useRef, useState } from "react";
|
||||||
|
|
||||||
|
const stats = [
|
||||||
|
{ value: 30, suffix: "+", label: "Jahre IT-Erfahrung", accent: "orange" },
|
||||||
|
{ value: 99, suffix: "%", label: "Server-Uptime", accent: "blue" },
|
||||||
|
{ value: 50, suffix: "+", label: "Abgeschlossene Projekte", accent: "orange" },
|
||||||
|
{ value: 24, suffix: "h", label: "Support-Reaktionszeit", accent: "blue" },
|
||||||
|
];
|
||||||
|
|
||||||
|
function Counter({ value, suffix, accent }: { value: number; suffix: string; accent: string }) {
|
||||||
|
const [count, setCount] = useState(0);
|
||||||
|
const ref = useRef<HTMLSpanElement>(null);
|
||||||
|
const started = useRef(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const el = ref.current;
|
||||||
|
if (!el) return;
|
||||||
|
|
||||||
|
const observer = new IntersectionObserver(
|
||||||
|
([entry]) => {
|
||||||
|
if (entry.isIntersecting && !started.current) {
|
||||||
|
started.current = true;
|
||||||
|
const duration = 1500;
|
||||||
|
const start = performance.now();
|
||||||
|
|
||||||
|
const tick = (now: number) => {
|
||||||
|
const progress = Math.min((now - start) / duration, 1);
|
||||||
|
const eased = 1 - Math.pow(1 - progress, 3);
|
||||||
|
setCount(Math.floor(eased * value));
|
||||||
|
if (progress < 1) requestAnimationFrame(tick);
|
||||||
|
};
|
||||||
|
|
||||||
|
requestAnimationFrame(tick);
|
||||||
|
observer.disconnect();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ threshold: 0.3 }
|
||||||
|
);
|
||||||
|
|
||||||
|
observer.observe(el);
|
||||||
|
return () => observer.disconnect();
|
||||||
|
}, [value]);
|
||||||
|
|
||||||
|
const color = accent === "orange" ? "text-orange-400" : "text-blue-400";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span ref={ref} className={`text-4xl sm:text-5xl font-black ${color}`}>
|
||||||
|
{count}{suffix}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function StatsBar() {
|
||||||
|
return (
|
||||||
|
<section className="py-12 px-4 sm:px-6 lg:px-8 relative">
|
||||||
|
<div className="absolute inset-0 bg-[#111925]" />
|
||||||
|
<div className="max-w-7xl mx-auto relative">
|
||||||
|
<div className="grid grid-cols-2 lg:grid-cols-4 gap-8">
|
||||||
|
{stats.map((stat) => (
|
||||||
|
<div key={stat.label} className="text-center">
|
||||||
|
<Counter value={stat.value} suffix={stat.suffix} accent={stat.accent} />
|
||||||
|
<p className="text-slate-500 text-sm mt-1">{stat.label}</p>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 2: StatsBar in `app/page.tsx` einbinden**
|
||||||
|
|
||||||
|
Füge den Import und die Komponente in `app/page.tsx` ein. Die Datei soll danach so aussehen:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// app/page.tsx
|
||||||
|
import Header from "@/components/Header";
|
||||||
|
import Hero from "@/components/Hero";
|
||||||
|
import TaglineBanner from "@/components/TaglineBanner";
|
||||||
|
import StatsBar from "@/components/StatsBar";
|
||||||
|
import Services from "@/components/Services";
|
||||||
|
import Technologies from "@/components/Technologies";
|
||||||
|
import DataSovereignty from "@/components/DataSovereignty";
|
||||||
|
import PaperlessSection from "@/components/PaperlessSection";
|
||||||
|
import About from "@/components/About";
|
||||||
|
import Contact from "@/components/Contact";
|
||||||
|
import Footer from "@/components/Footer";
|
||||||
|
|
||||||
|
export default function Home() {
|
||||||
|
return (
|
||||||
|
<main className="min-h-screen bg-[#18212f]">
|
||||||
|
<Header />
|
||||||
|
<Hero />
|
||||||
|
<TaglineBanner />
|
||||||
|
<StatsBar />
|
||||||
|
<Services />
|
||||||
|
<TaglineBanner />
|
||||||
|
<PaperlessSection />
|
||||||
|
<DataSovereignty />
|
||||||
|
<TaglineBanner />
|
||||||
|
<Technologies />
|
||||||
|
<About />
|
||||||
|
<TaglineBanner />
|
||||||
|
<Contact />
|
||||||
|
<Footer />
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Hinweis:** `PaperlessSection` existiert noch nicht — TypeScript wird einen Fehler werfen. Das ist normal, wir erstellen sie in Task 6.
|
||||||
|
|
||||||
|
- [ ] **Step 3: Im Browser prüfen**
|
||||||
|
|
||||||
|
Öffne http://localhost:3000 — nach dem Hero soll die dunkle StatsBar erscheinen. Beim Scrollen dazu zählen die Zahlen hoch.
|
||||||
|
|
||||||
|
- [ ] **Step 4: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add components/StatsBar.tsx app/page.tsx
|
||||||
|
git commit -m "feat: add animated StatsBar with counter effect"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Task 5: Services — 2 neue Karten + ScrollReveal
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `components/Services.tsx`
|
||||||
|
|
||||||
|
- [ ] **Step 1: `services`-Array in `Services.tsx` um 2 Einträge erweitern**
|
||||||
|
|
||||||
|
Füge am Ende des `services`-Arrays (nach dem Kubernetes-Eintrag, vor der schließenden `]`) folgende zwei Objekte ein:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
{
|
||||||
|
icon: (
|
||||||
|
<svg viewBox="0 0 24 24" className="w-8 h-8" fill="currentColor">
|
||||||
|
<path d="M1 6l5 4-5 4V6zm7 0h14v2H8V6zm0 5h14v2H8v-2zm0 5h14v2H8v-2z" />
|
||||||
|
<path d="M5.828 7l-1.414 1.414L6.586 10.6 4.414 12.8l1.414 1.4L10 10.6 5.828 7z" opacity=".6"/>
|
||||||
|
<path d="M19 3H5a2 2 0 00-2 2v1h2V5h14v14H5v-1H3v1a2 2 0 002 2h14a2 2 0 002-2V5a2 2 0 00-2-2z"/>
|
||||||
|
<circle cx="4" cy="12" r="3"/>
|
||||||
|
<path d="M4 10.5A1.5 1.5 0 115.5 12 1.5 1.5 0 014 10.5z" fill="#18212f"/>
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
title: "WLAN & Netzwerk",
|
||||||
|
description:
|
||||||
|
"Professionelle WLAN-Planung, Installation und Troubleshooting für Privat- und Gewerbekunden. Mesh-Netzwerke, Access Points und hartnäckige Netzwerkprobleme — auch in schwierigen Gebäuden.",
|
||||||
|
features: ["WLAN-Planung & Installation", "Mesh-Netzwerke", "Netzwerk-Troubleshooting", "Privat- & Gewerbekunden"],
|
||||||
|
accent: "orange",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: (
|
||||||
|
<svg viewBox="0 0 24 24" className="w-8 h-8" fill="currentColor">
|
||||||
|
<path d="M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0l4.6-4.6-4.6-4.6L16 6l6 6-6 6-1.4-1.4z"/>
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
title: "Individuelle Webanwendungen",
|
||||||
|
description:
|
||||||
|
"Maßgeschneiderte Web-Apps für spezielle Geschäftsanforderungen. Von Kundenportalen über interne Tools bis zu Buchungssystemen — entwickelt auf Ihre Prozesse zugeschnitten.",
|
||||||
|
features: ["Maßgeschneiderte Entwicklung", "Kundenportale & Tools", "API-Integrationen", "Moderner Tech-Stack"],
|
||||||
|
accent: "blue",
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 2: ScrollReveal in die Karten-Schleife integrieren**
|
||||||
|
|
||||||
|
Füge am Anfang der Datei den Import hinzu:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import ScrollReveal from "@/components/ScrollReveal";
|
||||||
|
```
|
||||||
|
|
||||||
|
Ändere dann die Karten-Schleife in der `return`-Anweisung von:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
|
{services.map((service) => {
|
||||||
|
const c = colorMap[service.accent as keyof typeof colorMap];
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={service.title}
|
||||||
|
className={`group p-6 rounded-2xl bg-gray-900 border ${c.border} transition-all duration-300 hover:-translate-y-1 hover:shadow-xl ${c.shadow}`}
|
||||||
|
>
|
||||||
|
```
|
||||||
|
|
||||||
|
zu:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
|
{services.map((service, index) => {
|
||||||
|
const c = colorMap[service.accent as keyof typeof colorMap];
|
||||||
|
return (
|
||||||
|
<ScrollReveal key={service.title} delay={index * 75}>
|
||||||
|
<div
|
||||||
|
className={`group p-6 rounded-2xl bg-gray-900 border ${c.border} transition-all duration-300 hover:-translate-y-1 hover:shadow-xl ${c.shadow}`}
|
||||||
|
>
|
||||||
|
```
|
||||||
|
|
||||||
|
Und die schließende `</div>` der Karte wird zu `</div></ScrollReveal>`. Die vollständige `return`-Schleife sieht dann so aus:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
{services.map((service, index) => {
|
||||||
|
const c = colorMap[service.accent as keyof typeof colorMap];
|
||||||
|
return (
|
||||||
|
<ScrollReveal key={service.title} delay={index * 75}>
|
||||||
|
<div
|
||||||
|
className={`group p-6 rounded-2xl bg-gray-900 border ${c.border} transition-all duration-300 hover:-translate-y-1 hover:shadow-xl ${c.shadow}`}
|
||||||
|
>
|
||||||
|
<div className={`w-14 h-14 rounded-xl ${c.iconBg} ${c.icon} flex items-center justify-center mb-5`}>
|
||||||
|
{service.icon}
|
||||||
|
</div>
|
||||||
|
<h3 className="text-xl font-bold text-white mb-3">{service.title}</h3>
|
||||||
|
<p className="text-slate-400 text-sm leading-relaxed mb-5">{service.description}</p>
|
||||||
|
<ul className="space-y-2">
|
||||||
|
{service.features.map((feature) => (
|
||||||
|
<li key={feature} className="flex items-center gap-2 text-sm text-slate-300">
|
||||||
|
<span className={`w-1.5 h-1.5 rounded-full ${c.dot} flex-shrink-0`} />
|
||||||
|
{feature}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</ScrollReveal>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 3: Im Browser prüfen**
|
||||||
|
|
||||||
|
http://localhost:3000 → Services-Bereich soll 8 Karten zeigen, die beim Scrollen gestaffelt einfahren.
|
||||||
|
|
||||||
|
- [ ] **Step 4: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add components/Services.tsx
|
||||||
|
git commit -m "feat: add WLAN and WebApps service cards with scroll-reveal"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Task 6: PaperlessSection — DSGVO & GoBD
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Create: `components/PaperlessSection.tsx`
|
||||||
|
|
||||||
|
- [ ] **Step 1: Komponente erstellen**
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// components/PaperlessSection.tsx
|
||||||
|
import ScrollReveal from "@/components/ScrollReveal";
|
||||||
|
|
||||||
|
const requirements = [
|
||||||
|
{
|
||||||
|
accent: "orange",
|
||||||
|
title: "DSGVO-konforme Archivierung",
|
||||||
|
text: "Alle Dokumente bleiben auf Ihrer eigenen Infrastruktur — in Deutschland oder bei Hetzner. Kein Zugriff durch Drittanbieter, keine US-Cloud. Vollständig DSGVO-konform.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accent: "blue",
|
||||||
|
title: "GoBD-Anforderungen erfüllt",
|
||||||
|
text: "Revisionssichere, unveränderliche Ablage steuerrelevanter Belege. Paperless-ngx protokolliert alle Änderungen und erfüllt die Anforderungen der GoBD an die digitale Buchführung.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accent: "orange",
|
||||||
|
title: "Selbstgehostet & unter Kontrolle",
|
||||||
|
text: "Betrieb auf Ihrem eigenen Server oder auf einem deutschen Hetzner-VPS. Sie haben die volle Kontrolle über Ihre Daten — heute, morgen und in 10 Jahren.",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const services = [
|
||||||
|
"Installation & Konfiguration von Paperless-ngx",
|
||||||
|
"Einrichtung automatischer Dokumentenerkennung (OCR)",
|
||||||
|
"Migration bestehender Dokumentenarchive",
|
||||||
|
"Schulung & Dokumentation für Ihr Team",
|
||||||
|
];
|
||||||
|
|
||||||
|
const colorMap = {
|
||||||
|
orange: {
|
||||||
|
border: "border-orange-500/20 hover:border-orange-500/50",
|
||||||
|
dot: "bg-orange-400",
|
||||||
|
dotBg: "bg-orange-500/10",
|
||||||
|
},
|
||||||
|
blue: {
|
||||||
|
border: "border-blue-500/20 hover:border-blue-500/50",
|
||||||
|
dot: "bg-blue-400",
|
||||||
|
dotBg: "bg-blue-500/10",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function PaperlessSection() {
|
||||||
|
return (
|
||||||
|
<section id="paperless" className="py-24 px-4 sm:px-6 lg:px-8 relative">
|
||||||
|
<div className="absolute inset-0 bg-[#111925]" />
|
||||||
|
<div className="absolute inset-0 bg-grid opacity-20" />
|
||||||
|
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_top_right,rgba(34,197,94,0.04)_0%,transparent_60%)]" />
|
||||||
|
|
||||||
|
<div className="max-w-7xl mx-auto relative">
|
||||||
|
|
||||||
|
{/* Header */}
|
||||||
|
<ScrollReveal>
|
||||||
|
<div className="text-center mb-16">
|
||||||
|
<span className="text-orange-400 font-mono text-xs font-bold tracking-[0.25em] uppercase">
|
||||||
|
Compliance & Dokumentenmanagement
|
||||||
|
</span>
|
||||||
|
<h2 className="text-4xl sm:text-5xl font-black text-white mt-3 mb-4">
|
||||||
|
DSGVO & GoBD mit{" "}
|
||||||
|
<span className="text-gradient-orange">Paperless-ngx</span>
|
||||||
|
</h2>
|
||||||
|
<p className="text-slate-400 text-lg max-w-2xl mx-auto">
|
||||||
|
Digitale Dokumentenverwaltung, die rechtssicher ist — DSGVO-konform,
|
||||||
|
GoBD-tauglich, selbstgehostet. Kein Abo, keine US-Cloud, volle Kontrolle.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</ScrollReveal>
|
||||||
|
|
||||||
|
{/* What is Paperless */}
|
||||||
|
<ScrollReveal delay={100}>
|
||||||
|
<div className="mb-12 p-6 rounded-2xl bg-gray-900 border border-orange-500/20 flex flex-col md:flex-row gap-6 items-start">
|
||||||
|
<div className="flex-shrink-0 w-14 h-14 rounded-xl bg-orange-500/10 text-orange-400 flex items-center justify-center">
|
||||||
|
<svg className="w-7 h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 className="text-white font-bold text-lg mb-2">Was ist Paperless-ngx?</h3>
|
||||||
|
<p className="text-slate-400 text-sm leading-relaxed">
|
||||||
|
Paperless-ngx ist ein Open-Source Dokumentenmanagementsystem (DMS), das Ihre Papierflut digitalisiert
|
||||||
|
und durchsuchbar macht. Rechnungen, Verträge, Briefe — automatisch per OCR erkannt, kategorisiert und
|
||||||
|
archiviert. Betrieben auf Ihrer eigenen Infrastruktur, ohne Abhängigkeit von Cloud-Anbietern.
|
||||||
|
</p>
|
||||||
|
<div className="flex flex-wrap gap-2 mt-3">
|
||||||
|
{["Open Source", "Self-Hosted", "OCR", "Volltextsuche", "Automatische Tags"].map((tag) => (
|
||||||
|
<span key={tag} className="px-3 py-1 rounded-full bg-orange-500/10 border border-orange-500/20 text-orange-400 text-xs font-mono">
|
||||||
|
{tag}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ScrollReveal>
|
||||||
|
|
||||||
|
{/* Requirements grid */}
|
||||||
|
<div className="grid md:grid-cols-3 gap-6 mb-16">
|
||||||
|
{requirements.map((req, index) => {
|
||||||
|
const c = colorMap[req.accent as keyof typeof colorMap];
|
||||||
|
return (
|
||||||
|
<ScrollReveal key={req.title} delay={index * 100}>
|
||||||
|
<div className={`p-6 rounded-2xl bg-gray-900 border ${c.border} transition-all duration-300 h-full`}>
|
||||||
|
<div className={`w-2 h-2 rounded-full ${c.dot} mb-4`} />
|
||||||
|
<h3 className="text-white font-bold text-base mb-3">{req.title}</h3>
|
||||||
|
<p className="text-slate-400 text-sm leading-relaxed">{req.text}</p>
|
||||||
|
</div>
|
||||||
|
</ScrollReveal>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Divider */}
|
||||||
|
<div className="flex items-center gap-6 mb-12">
|
||||||
|
<div className="flex-1 h-px bg-gradient-to-r from-transparent via-gray-700 to-transparent" />
|
||||||
|
<div className="px-6 py-2 rounded-full border border-orange-500/40 bg-orange-500/5 text-orange-400 text-sm font-black tracking-wider whitespace-nowrap">
|
||||||
|
Unser Leistungsumfang
|
||||||
|
</div>
|
||||||
|
<div className="flex-1 h-px bg-gradient-to-r from-transparent via-gray-700 to-transparent" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Services list */}
|
||||||
|
<ScrollReveal delay={100}>
|
||||||
|
<div className="grid sm:grid-cols-2 gap-4 mb-16">
|
||||||
|
{services.map((item) => (
|
||||||
|
<div key={item} className="flex items-center gap-3 p-4 rounded-xl bg-gray-900 border border-gray-800">
|
||||||
|
<div className="w-5 h-5 rounded-full bg-orange-500 flex items-center justify-center flex-shrink-0">
|
||||||
|
<svg className="w-3 h-3 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={3} d="M5 13l4 4L19 7" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<span className="text-slate-300 text-sm">{item}</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</ScrollReveal>
|
||||||
|
|
||||||
|
{/* CTA */}
|
||||||
|
<ScrollReveal delay={150}>
|
||||||
|
<div className="p-8 rounded-2xl border border-orange-500/30 bg-orange-500/5 text-center">
|
||||||
|
<p className="text-orange-400 font-black text-sm tracking-[0.2em] uppercase mb-2">
|
||||||
|
Compliance leicht gemacht
|
||||||
|
</p>
|
||||||
|
<p className="text-white text-xl font-bold mb-2">
|
||||||
|
DSGVO & GoBD — ohne Kompromisse.
|
||||||
|
</p>
|
||||||
|
<p className="text-slate-400 text-sm max-w-xl mx-auto mb-6">
|
||||||
|
Wir richten Paperless-ngx auf Ihrer Infrastruktur ein, migrieren
|
||||||
|
Ihre bestehenden Dokumente und schulen Ihr Team. Rechtssicher,
|
||||||
|
selbstgehostet, dauerhaft unter Ihrer Kontrolle.
|
||||||
|
</p>
|
||||||
|
<a href="#contact" className="btn-primary inline-flex px-8 py-3 text-sm">
|
||||||
|
Jetzt Beratung anfragen
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</ScrollReveal>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 2: Im Browser prüfen**
|
||||||
|
|
||||||
|
http://localhost:3000 → Zwischen Services und DataSovereignty soll die neue Paperless-Sektion erscheinen mit dunkelgrauem Hintergrund, 3 Anforderungskarten und CTA.
|
||||||
|
|
||||||
|
- [ ] **Step 3: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add components/PaperlessSection.tsx
|
||||||
|
git commit -m "feat: add PaperlessSection with DSGVO/GoBD content"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Task 7: page.tsx — PaperlessSection finalisieren
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `app/page.tsx`
|
||||||
|
|
||||||
|
Nach Task 4 wurde `PaperlessSection` bereits in `page.tsx` importiert. In Task 6 wurde die Komponente erstellt.
|
||||||
|
|
||||||
|
- [ ] **Step 1: Prüfen dass page.tsx korrekt ist**
|
||||||
|
|
||||||
|
`app/page.tsx` soll exakt so aussehen (wurde bereits in Task 4 geschrieben):
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import Header from "@/components/Header";
|
||||||
|
import Hero from "@/components/Hero";
|
||||||
|
import TaglineBanner from "@/components/TaglineBanner";
|
||||||
|
import StatsBar from "@/components/StatsBar";
|
||||||
|
import Services from "@/components/Services";
|
||||||
|
import Technologies from "@/components/Technologies";
|
||||||
|
import DataSovereignty from "@/components/DataSovereignty";
|
||||||
|
import PaperlessSection from "@/components/PaperlessSection";
|
||||||
|
import About from "@/components/About";
|
||||||
|
import Contact from "@/components/Contact";
|
||||||
|
import Footer from "@/components/Footer";
|
||||||
|
|
||||||
|
export default function Home() {
|
||||||
|
return (
|
||||||
|
<main className="min-h-screen bg-[#18212f]">
|
||||||
|
<Header />
|
||||||
|
<Hero />
|
||||||
|
<TaglineBanner />
|
||||||
|
<StatsBar />
|
||||||
|
<Services />
|
||||||
|
<TaglineBanner />
|
||||||
|
<PaperlessSection />
|
||||||
|
<DataSovereignty />
|
||||||
|
<TaglineBanner />
|
||||||
|
<Technologies />
|
||||||
|
<About />
|
||||||
|
<TaglineBanner />
|
||||||
|
<Contact />
|
||||||
|
<Footer />
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Falls noch nicht so, jetzt anpassen.
|
||||||
|
|
||||||
|
- [ ] **Step 2: Finaler Check im Browser**
|
||||||
|
|
||||||
|
http://localhost:3000 — vollständige Seite prüfen:
|
||||||
|
- Hero: Typewriter läuft ✓
|
||||||
|
- StatsBar: Zahlen zählen hoch beim Scrollen ✓
|
||||||
|
- Services: 8 Karten, gleiten beim Scrollen ein ✓
|
||||||
|
- PaperlessSection: erscheint nach Services ✓
|
||||||
|
- Keine TypeScript/Console-Fehler ✓
|
||||||
|
|
||||||
|
- [ ] **Step 3: Finaler Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add app/page.tsx
|
||||||
|
git commit -m "feat: wire up all new sections in page layout"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Self-Review Ergebnis
|
||||||
|
|
||||||
|
- **Spec-Abdeckung:** Alle 7 Anforderungen (2 Karten, 1 Sektion, 3 Effekte, page.tsx) haben Tasks ✓
|
||||||
|
- **Keine Platzhalter:** Alle Code-Blöcke sind vollständig ✓
|
||||||
|
- **Typ-Konsistenz:** `ScrollReveal` wird in Tasks 5 und 6 identisch verwendet ✓
|
||||||
|
- **useTypewriter:** Hook gibt `string` zurück, wird in Hero als `{typed}` eingesetzt ✓
|
||||||
|
|
@ -0,0 +1,135 @@
|
||||||
|
# Website-Erweiterung: Neue Services & Spezialeffekte
|
||||||
|
|
||||||
|
**Datum:** 2026-04-02
|
||||||
|
**Status:** Genehmigt
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Überblick
|
||||||
|
|
||||||
|
Die bestehende MBO-Tech-IT-Website (Next.js + Tailwind CSS, dunkles Design) wird um drei neue Leistungsbereiche und drei Spezialeffekte erweitert. Zwei neue Services kommen als Karten ins bestehende Grid; DSGVO/GoBD mit Paperless erhält eine eigene Sektion.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Neue Service-Karten im Grid
|
||||||
|
|
||||||
|
Das Services-Grid wächst von 6 auf 8 Karten. Die zwei neuen Karten werden am Ende des Arrays in `components/Services.tsx` hinzugefügt.
|
||||||
|
|
||||||
|
### Karte 1: WLAN & Netzwerk
|
||||||
|
- **Accent:** orange
|
||||||
|
- **Titel:** WLAN & Netzwerk
|
||||||
|
- **Beschreibung:** Professionelle WLAN-Planung, Installation und Troubleshooting für Privat- und Gewerbekunden. Mesh-Netzwerke, Access Points und Netzwerkprobleme — auch in schwierigen Gebäuden.
|
||||||
|
- **Features:** WLAN-Planung & Installation, Mesh-Netzwerke, Netzwerk-Troubleshooting, Privat- & Gewerbekunden
|
||||||
|
- **Icon:** WiFi-Symbol (SVG)
|
||||||
|
|
||||||
|
### Karte 2: Individuelle Webanwendungen
|
||||||
|
- **Accent:** blue
|
||||||
|
- **Titel:** Individuelle Webanwendungen
|
||||||
|
- **Beschreibung:** Maßgeschneiderte Web-Apps für spezielle Geschäftsanforderungen. Von Kundenportalen über interne Tools bis zu Buchungssystemen — entwickelt auf Ihre Prozesse zugeschnitten.
|
||||||
|
- **Features:** Maßgeschneiderte Entwicklung, Kundenportale & Tools, API-Integrationen, Moderne Tech-Stack
|
||||||
|
- **Icon:** Code/Browser-Symbol (SVG)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Neue Sektion: DSGVO & GoBD mit Paperless
|
||||||
|
|
||||||
|
**Datei:** `components/PaperlessSection.tsx` (neu)
|
||||||
|
**Position in `app/page.tsx`:** Nach `<Services />`, vor `<DataSovereignty />`
|
||||||
|
|
||||||
|
### Struktur
|
||||||
|
1. **Header** — Label "Compliance & Dokumentenmanagement", Überschrift mit Gradient, Untertitel
|
||||||
|
2. **Was ist Paperless-ngx?** — Erklärungsblock: Open-Source DMS, DSGVO-konform, GoBD-tauglich, kein US-Cloud-Risiko
|
||||||
|
3. **Anforderungen-Grid** (3 Karten):
|
||||||
|
- DSGVO-konforme Archivierung (Daten bleiben lokal/EU)
|
||||||
|
- GoBD-Anforderungen (revisionssichere, unveränderliche Ablage)
|
||||||
|
- Selbstgehostet auf eigenem Server oder Hetzner
|
||||||
|
4. **Leistungsumfang** (4 Punkte als horizontale Feature-Liste):
|
||||||
|
- Installation & Konfiguration von Paperless-ngx
|
||||||
|
- Einrichtung automatischer Dokumentenerkennung (OCR)
|
||||||
|
- Migration bestehender Dokumentenarchive
|
||||||
|
- Schulung & Dokumentation für Ihr Team
|
||||||
|
5. **CTA-Banner** — "Jetzt Compliance-Beratung anfragen" → `#contact`
|
||||||
|
|
||||||
|
### Design
|
||||||
|
- Hintergrund: `#111925` (wie DataSovereignty)
|
||||||
|
- Akzentfarbe: orange (Anforderungen) + grün (#22c55e) für "DSGVO-konform"-Badges
|
||||||
|
- Gleiche Card-Styles wie bestehende Sektionen
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Spezialeffekte
|
||||||
|
|
||||||
|
### A: Scroll-Reveal
|
||||||
|
**Implementierung:** Intersection Observer API (kein externes Package)
|
||||||
|
**Datei:** `components/ScrollReveal.tsx` — wiederverwendbare Wrapper-Komponente
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// Verwendung:
|
||||||
|
<ScrollReveal>
|
||||||
|
<ServiceCard ... />
|
||||||
|
</ScrollReveal>
|
||||||
|
```
|
||||||
|
|
||||||
|
- Animation: `opacity: 0 → 1` + `translateY(24px → 0)`, Dauer 500ms, ease-out
|
||||||
|
- Delay-Prop für gestaffelte Karten: `delay={index * 75}ms`
|
||||||
|
- Kein Re-Trigger nach erstem Einblenden (`once: true`)
|
||||||
|
- Angewendet auf: alle Service-Karten, PaperlessSection-Blöcke, DataSovereignty-Karten, About-Bereich
|
||||||
|
|
||||||
|
### B: Typewriter im Hero
|
||||||
|
**Implementierung:** Custom Hook `useTypewriter` in `hooks/useTypewriter.ts`
|
||||||
|
**Datei:** Änderung in `components/Hero.tsx`
|
||||||
|
|
||||||
|
- Wörter-Rotation: `["Professionell.", "DSGVO-konform.", "Zuverlässig.", "Skalierbar."]`
|
||||||
|
- Tipp-Geschwindigkeit: 80ms pro Zeichen
|
||||||
|
- Lösch-Geschwindigkeit: 40ms pro Zeichen
|
||||||
|
- Pause nach vollständigem Wort: 2000ms
|
||||||
|
- Cursor: blinkender `|` via CSS-Animation (bereits in globals.css vorhanden)
|
||||||
|
- Ersetzt den statischen `<span className="text-gradient">Professionell.</span>` im Hero
|
||||||
|
|
||||||
|
### D: Counter-Statistiken
|
||||||
|
**Implementierung:** Intersection Observer + `requestAnimationFrame` in `components/StatsBar.tsx` (neu)
|
||||||
|
**Position in `app/page.tsx`:** Zwischen `<TaglineBanner />` und `<Services />`
|
||||||
|
|
||||||
|
Statistiken:
|
||||||
|
| Wert | Label |
|
||||||
|
|------|-------|
|
||||||
|
| 50+ | Abgeschlossene Projekte |
|
||||||
|
| 99% | Server-Uptime |
|
||||||
|
| 5+ | Jahre Erfahrung |
|
||||||
|
| 24h | Support-Reaktionszeit |
|
||||||
|
|
||||||
|
> **Hinweis:** Diese Zahlen sind Vorschläge — bitte vor der Umsetzung bestätigen oder anpassen.
|
||||||
|
|
||||||
|
- Zählt von 0 auf Zielwert wenn ins Viewport gescrollt
|
||||||
|
- Suffix (`+`, `%`, `h`) wird statisch nach dem Zähler angezeigt
|
||||||
|
- Design: 4 Blöcke horizontal, orange/blaue Akzente, dunkel-grauer Hintergrund
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Seitenstruktur nach Umsetzung
|
||||||
|
|
||||||
|
```
|
||||||
|
<Header />
|
||||||
|
<Hero /> ← Typewriter-Effekt
|
||||||
|
<TaglineBanner />
|
||||||
|
<StatsBar /> ← NEU (Counter)
|
||||||
|
<Services /> ← 8 Karten (+ WLAN, + WebApps) + ScrollReveal
|
||||||
|
<TaglineBanner />
|
||||||
|
<PaperlessSection /> ← NEU (DSGVO & GoBD)
|
||||||
|
<DataSovereignty /> ← ScrollReveal
|
||||||
|
<TaglineBanner />
|
||||||
|
<Technologies />
|
||||||
|
<About /> ← ScrollReveal
|
||||||
|
<TaglineBanner />
|
||||||
|
<Contact />
|
||||||
|
<Footer />
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Technische Randbedingungen
|
||||||
|
|
||||||
|
- Kein externes Animations-Package (Framer Motion o.ä.) — alles mit Web APIs & CSS
|
||||||
|
- `"use client"` nur wo nötig (Hooks, Intersection Observer)
|
||||||
|
- Bestehende Farbpalette beibehalten: orange `#f97316`, blau `#2563eb`, dark `#18212f`
|
||||||
|
- Alle neuen Komponenten folgen dem bestehenden Muster (Tailwind, keine inline styles)
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
/// <reference types="next" />
|
||||||
|
/// <reference types="next/image-types/global" />
|
||||||
|
/// <reference path="./.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.
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
import type { NextConfig } from "next";
|
||||||
|
|
||||||
|
const nextConfig: NextConfig = {};
|
||||||
|
|
||||||
|
export default nextConfig;
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"name": "mbo-tech-it",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "node --max-old-space-size=4096 node_modules/.bin/next dev",
|
||||||
|
"build": "next build",
|
||||||
|
"start": "next start",
|
||||||
|
"lint": "next lint"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"next": "^15.2.0",
|
||||||
|
"react": "^19.0.0",
|
||||||
|
"react-dom": "^19.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^22",
|
||||||
|
"@types/react": "^19",
|
||||||
|
"@types/react-dom": "^19",
|
||||||
|
"typescript": "^5",
|
||||||
|
"tailwindcss": "^3.4.0",
|
||||||
|
"postcss": "^8",
|
||||||
|
"autoprefixer": "^10"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
/** @type {import('postcss').Config} */
|
||||||
|
const config = {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
autoprefixer: {},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
||||||
|
|
@ -0,0 +1,120 @@
|
||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"skills": {
|
||||||
|
"access": {
|
||||||
|
"source": "anthropics/claude-plugins-official",
|
||||||
|
"sourceType": "github",
|
||||||
|
"computedHash": "709982b08e4d9b4665e4b33c2ed7e5a91b7c2548fd00b636507d9d8e0b6e9ded"
|
||||||
|
},
|
||||||
|
"agent-development": {
|
||||||
|
"source": "anthropics/claude-plugins-official",
|
||||||
|
"sourceType": "github",
|
||||||
|
"computedHash": "ffed02054e8df93cad2ba9b959a412bfcb0c6e42528cdaae8b0202f288f86bce"
|
||||||
|
},
|
||||||
|
"build-mcp-app": {
|
||||||
|
"source": "anthropics/claude-plugins-official",
|
||||||
|
"sourceType": "github",
|
||||||
|
"computedHash": "2ec4705e327b323e78091fedabafaa29ae0fa0303df66e0022824eae11e62201"
|
||||||
|
},
|
||||||
|
"build-mcp-server": {
|
||||||
|
"source": "anthropics/claude-plugins-official",
|
||||||
|
"sourceType": "github",
|
||||||
|
"computedHash": "f347c2ac3187cefbb0061120635464244cede550cb42b233c105abb23615c520"
|
||||||
|
},
|
||||||
|
"build-mcpb": {
|
||||||
|
"source": "anthropics/claude-plugins-official",
|
||||||
|
"sourceType": "github",
|
||||||
|
"computedHash": "d7ed192ab12c1ffb5441ec568d7cde37644b11c77351f18f58c1f0d647492507"
|
||||||
|
},
|
||||||
|
"claude-automation-recommender": {
|
||||||
|
"source": "anthropics/claude-plugins-official",
|
||||||
|
"sourceType": "github",
|
||||||
|
"computedHash": "af42a0323713f62407eacc09510649d18a3df32725c4f125909ccc7309a8102d"
|
||||||
|
},
|
||||||
|
"claude-md-improver": {
|
||||||
|
"source": "anthropics/claude-plugins-official",
|
||||||
|
"sourceType": "github",
|
||||||
|
"computedHash": "7b765125563b4e1490c925f72da35dcd004151e1469b9b680b3af7fa5f0b94e6"
|
||||||
|
},
|
||||||
|
"command-development": {
|
||||||
|
"source": "anthropics/claude-plugins-official",
|
||||||
|
"sourceType": "github",
|
||||||
|
"computedHash": "9df69c3a9f233f5345d99b6a3beebc0e578da8d120434d3108a2fd78328174f0"
|
||||||
|
},
|
||||||
|
"configure": {
|
||||||
|
"source": "anthropics/claude-plugins-official",
|
||||||
|
"sourceType": "github",
|
||||||
|
"computedHash": "24dd10994a7130dd5bdf8cffc4e69d56031441285df48a97a1124bd189fcedba"
|
||||||
|
},
|
||||||
|
"frontend-design": {
|
||||||
|
"source": "anthropics/claude-plugins-official",
|
||||||
|
"sourceType": "github",
|
||||||
|
"computedHash": "739fdfda7f74445ad6b300d6eeba31a82aed276664242580206cd564e6fee3f6"
|
||||||
|
},
|
||||||
|
"hook-development": {
|
||||||
|
"source": "anthropics/claude-plugins-official",
|
||||||
|
"sourceType": "github",
|
||||||
|
"computedHash": "eb506a65ffcb49aff37e3404040d274131e3a84edb708293f9696e40f29da0f6"
|
||||||
|
},
|
||||||
|
"math-olympiad": {
|
||||||
|
"source": "anthropics/claude-plugins-official",
|
||||||
|
"sourceType": "github",
|
||||||
|
"computedHash": "298af26317bec42b379fc00f10f51cee9bdefa62b1d6a07363da24e11ed4c69e"
|
||||||
|
},
|
||||||
|
"mcp-integration": {
|
||||||
|
"source": "anthropics/claude-plugins-official",
|
||||||
|
"sourceType": "github",
|
||||||
|
"computedHash": "5cc0d1ad88fa7ce8cac005c9187171a32fa989b4c553bb2d66649eb49f68fbca"
|
||||||
|
},
|
||||||
|
"pdf": {
|
||||||
|
"source": "anthropics/skills",
|
||||||
|
"sourceType": "github",
|
||||||
|
"computedHash": "37226d4220d844377e6b2a386c51a011df4cd130855ff0b80bcc22f9c28abd57"
|
||||||
|
},
|
||||||
|
"playground": {
|
||||||
|
"source": "anthropics/claude-plugins-official",
|
||||||
|
"sourceType": "github",
|
||||||
|
"computedHash": "ebeaf44264e6346e224ffb83d18aa07c2b25646f4f83438e36f393b34be2d73f"
|
||||||
|
},
|
||||||
|
"playwright-best-practices": {
|
||||||
|
"source": "currents-dev/playwright-best-practices-skill",
|
||||||
|
"sourceType": "github",
|
||||||
|
"computedHash": "6db654e753257e642d6507d59b4fc633a2382e93429748ba0fb6817c23ef5216"
|
||||||
|
},
|
||||||
|
"playwright-cli": {
|
||||||
|
"source": "microsoft/playwright-cli",
|
||||||
|
"sourceType": "github",
|
||||||
|
"computedHash": "1308eb2ce02f818cf7292a9c9ba6da7ea54cfc04d49dc1eb729d4fb84e4a19b1"
|
||||||
|
},
|
||||||
|
"playwright-generate-test": {
|
||||||
|
"source": "github/awesome-copilot",
|
||||||
|
"sourceType": "github",
|
||||||
|
"computedHash": "8f963da3e25f705ff39755b8b990f20da0c0320cb86ac83fcc4d2d4eca91f6e4"
|
||||||
|
},
|
||||||
|
"plugin-settings": {
|
||||||
|
"source": "anthropics/claude-plugins-official",
|
||||||
|
"sourceType": "github",
|
||||||
|
"computedHash": "f2ce926014bfb6e9742be2b4fd90ee09ee2a0eb7041bdf12d3641d76046aca2e"
|
||||||
|
},
|
||||||
|
"plugin-structure": {
|
||||||
|
"source": "anthropics/claude-plugins-official",
|
||||||
|
"sourceType": "github",
|
||||||
|
"computedHash": "ba7cd10f4e2140cc99ba887beb8e496e3d2118d05d7beed41a76a203ba855c33"
|
||||||
|
},
|
||||||
|
"skill-creator": {
|
||||||
|
"source": "anthropics/claude-plugins-official",
|
||||||
|
"sourceType": "github",
|
||||||
|
"computedHash": "e513e29a52533c4dd0aff72964c80d2d43c6fe9619ecb8766aabcd117e2b1acd"
|
||||||
|
},
|
||||||
|
"skill-development": {
|
||||||
|
"source": "anthropics/claude-plugins-official",
|
||||||
|
"sourceType": "github",
|
||||||
|
"computedHash": "0f91d445e350793549a8ed7b450ef3777a5a82c800b71523961c042eb65cca27"
|
||||||
|
},
|
||||||
|
"writing-hookify-rules": {
|
||||||
|
"source": "anthropics/claude-plugins-official",
|
||||||
|
"sourceType": "github",
|
||||||
|
"computedHash": "e940c5a85723aec360e8d00088ec59e8d16af42c3fc75486e592a57cc45f2845"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
import type { Config } from "tailwindcss";
|
||||||
|
|
||||||
|
const config: Config = {
|
||||||
|
content: [
|
||||||
|
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
||||||
|
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
||||||
|
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
||||||
|
],
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
colors: {
|
||||||
|
brand: {
|
||||||
|
orange: "#f97316",
|
||||||
|
"orange-light": "#fb923c",
|
||||||
|
"orange-dark": "#ea6c00",
|
||||||
|
blue: "#2563eb",
|
||||||
|
"blue-light": "#60a5fa",
|
||||||
|
"blue-dark": "#1d4ed8",
|
||||||
|
dark: "#0d1117",
|
||||||
|
darker: "#080d12",
|
||||||
|
card: "#111827",
|
||||||
|
border: "#1f2937",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fontFamily: {
|
||||||
|
sans: ["Inter", "system-ui", "sans-serif"],
|
||||||
|
mono: ["JetBrains Mono", "Fira Code", "monospace"],
|
||||||
|
},
|
||||||
|
animation: {
|
||||||
|
"fade-in": "fadeIn 0.6s ease-out forwards",
|
||||||
|
"slide-up": "slideUp 0.6s ease-out forwards",
|
||||||
|
"pulse-slow": "pulse 3s ease-in-out infinite",
|
||||||
|
"spin-slow": "spin 8s linear infinite",
|
||||||
|
},
|
||||||
|
keyframes: {
|
||||||
|
fadeIn: {
|
||||||
|
"0%": { opacity: "0" },
|
||||||
|
"100%": { opacity: "1" },
|
||||||
|
},
|
||||||
|
slideUp: {
|
||||||
|
"0%": { opacity: "0", transform: "translateY(20px)" },
|
||||||
|
"100%": { opacity: "1", transform: "translateY(0)" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2017",
|
||||||
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"incremental": true,
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "next"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue