diff --git a/app/about/page.tsx b/app/about/page.tsx index 9c10008..5d411a4 100644 --- a/app/about/page.tsx +++ b/app/about/page.tsx @@ -10,28 +10,24 @@ import { ConceptSystem, ConceptTarget, ContactIllustration, - ConnectorBranch, - ConnectorStart, - ConnectorEnd, - ConnectorSplit, HeroLines, ParticleNetwork, GridLines } from '../../src/components/Landing'; -import { Check, ArrowRight } from 'lucide-react'; +import { Check } from 'lucide-react'; +import { H3, H4, LeadText, BodyText, Label, MonoLabel } from '../../src/components/Typography'; +import { BackgroundGrid, Card, Container } from '../../src/components/Layout'; +import { Button } from '../../src/components/Button'; export default function AboutPage() { return (
{/* Background Elements */} -
+ {/* Hero Section */} -
+
@@ -39,41 +35,42 @@ export default function AboutPage() {
-
+
{/* Structural rings around avatar */} -
-
+
+
-
+
Marc Mintel
-
+
-
+
- Digital Architect + Digital Architect
Über mich.} - description="(oder: Warum das hier kein Agentur-Zirkus ist)" + title={<>Über mich.} + description="Warum ich tue, was ich tue – und wie Sie davon profitieren." + className="pt-0 md:pt-0" />
-
+ {/* Connector to first section */}
@@ -84,48 +81,47 @@ export default function AboutPage() { number="01" title="Erfahrung" borderTop - connector={} - illustration={} + illustration={} >
-

- Ich baue Websites und Systeme seit über 15 Jahren.
- Weil ich es hasse, wenn Dinge nicht funktionieren. -

+

+ 15 Jahre Web-Entwicklung.
+ Vom Designer zum Architekten. +

-
+
-
-

- In diesen 15 Jahren habe ich Agenturen von innen gesehen, Konzerne erlebt und Startups aufgebaut. -

+
+ + Ich habe Agenturen, Konzerne und Startups von innen gesehen. Dabei habe ich gelernt, what really counts: Ergebnisse, nicht Prozesse. +
    {[ - 'Marketingversprechen zerlegt', - 'Systeme repariert, die „fertig“ waren', - 'Gelernt, wie man Dinge baut, die einfach laufen' + 'Komplexe Systeme vereinfacht', + 'Performance-Probleme gelöst', + 'Nachhaltige Software-Architekturen gebaut' ].map((item, i) => ( -
  • -
    - {item} +
  • +
    + {item}
  • ))}
-
-

Heute mache ich das ohne Agentur-Zwischenschichten.

-
- {['Direkt', 'Sauber', 'Verantwortlich'].map((tag, i) => ( - - {tag} + +

Mein Fokus heute: Direkte Zusammenarbeit ohne Reibungsverluste.

+
+ {['Effizient', 'Pragmatisch', 'Verlässlich'].map((tag, i) => ( + + ))}
-
+
@@ -137,31 +133,30 @@ export default function AboutPage() { title="Verantwortung" variant="gray" borderTop - connector={} - illustration={} + illustration={} >
-

- Ich habe fast alle Fehler schon für Sie gemacht.
- (Damit Sie sie nicht machen müssen) -

+

+ Ich stehe für meine
+ Arbeit gerade. +

-
+
-

- Ich habe als Designer angefangen, bin dann Entwickler geworden, und habe irgendwann gemerkt: Das Problem ist selten Technik. Es ist immer Zuständigkeit. -

+ + In der klassischen Agenturwelt verschwindet Verantwortung oft hinter Hierarchien. Bei mir gibt es nur einen Ansprechpartner: Mich. +
-
-
!
-

- Wenn keiner verantwortlich ist, passiert nichts. Also habe ich mir angewöhnt, Verantwortung zu übernehmen. -

-
+ +
!
+ + Ich übernehme die volle Verantwortung für die technische Umsetzung und Qualität Ihres Projekts. Ohne Ausreden. + +
@@ -173,129 +168,94 @@ export default function AboutPage() { number="03" title="Philosophie" borderTop - connector={} - illustration={} + illustration={} >
-

- Warum ich Websites wie Systeme baue. -

+

+ Nachhaltigkeit durch
+ sauberen Code. +

-

- Ich war viele Jahre Senior Developer in Firmen, in denen Millionenumsätze dranhingen, Fehler teuer waren und Performance nicht optional war. -

+ + Ich baue keine Wegwerf-Produkte. Meine Systeme sind so konzipiert, dass sie mit Ihrem Unternehmen wachsen können. +
- {['Schnell', 'Stabil', 'Boring', 'Erweiterbar', 'Wartungsarm', 'Unabhängig'].map((item, i) => ( + {['Skalierbar', 'Wartbar', 'Performant', 'Sicher', 'Unabhängig', 'Zukunftssicher'].map((item, i) => ( -
- - {item} +
+
+ +
+
))}
-
-
-

Das prägt.

-

- Meine Websites sind nicht abhängig von Plugins oder Agenturen. Sie sind gebaut, um zu bleiben. -

-
+ +
+

Kein Vendor Lock-in.

+ + Sie behalten die volle Kontrolle über Ihren Code und Ihre Daten. Keine Abhängigkeit von proprietären Systemen. + +
- {/* Section 04: Roles */} + {/* Section 04: Result */}
} - illustration={} - > -
- -

- Ich habe beide Seiten gesehen. -

-
- -
- {[ - 'Webdesigner', 'Entwickler', 'Marketing', 'Vertrieb', - 'Agentur', 'Inhouse', 'Dienstleister', 'Unternehmer' - ].map((role, i) => ( - -
- {role} -
-
- ))} -
- - -

- Ich weiß, was Unternehmen brauchen – und was sie nicht brauchen. (Meetings, Tickets, Workshops, PowerPoint.) -

-
-
-
- - {/* Section 05: Result */} -
} - illustration={} + illustration={} >
-

- Was Kunden davon haben. -

+

+ Was Sie von mir
+ erwarten können. +

-
+
-
- Sie bekommen kein: +
+
- {['Projektmanager', 'Prozess', 'Team', 'Ticket', 'CMS-Drama'].map((item, i) => ( - - {item} + {['Agentur-Zirkus', 'Meeting-Marathon', 'Ticket-Wahnsinn', 'CMS-Frust'].map((item, i) => ( + + {item} ))}
-
- Sie bekommen: -
+
+ +
{[ - { label: 'Eine Person', desc: 'Direkter Kontakt, keine Stille Post.' }, - { label: 'Eine Verantwortung', desc: 'Ich stehe für das Ergebnis gerade.' }, - { label: 'Ein Ergebnis', desc: 'Funktionierende Systeme, keine Ausreden.' } + { label: 'Direkte Kommunikation', desc: 'Kurze Wege, schnelle Entscheidungen.' }, + { label: 'Echte Expertise', desc: 'Fundiertes Wissen aus 15 Jahren Praxis.' }, + { label: 'Messbare Qualität', desc: 'Code, der hält, was er verspricht.' } ].map((item, i) => ( -
-
- +
+
+
-
-
{item.label}
-
{item.desc}
+
+

{item.label}

+ {item.desc}
@@ -307,41 +267,37 @@ export default function AboutPage() {
- {/* Section 06: Today */} + {/* Section 05: Today */}
} - illustration={} + illustration={} >
-

- Heute baue ich Websites für Unternehmen, die keine Lust mehr auf Chaos haben. -

+

+ Bereit für eine
+ Zusammenarbeit? +

-
-
+ +
-

- Ich übernehme das Thema komplett – damit es für Sie kein Thema mehr ist. -

+ + Lassen Sie uns gemeinsam etwas bauen, das wirklich funktioniert. + - -
+
diff --git a/app/globals.css b/app/globals.css index 90a6bd8..ba80275 100644 --- a/app/globals.css +++ b/app/globals.css @@ -10,28 +10,28 @@ body { @apply bg-white text-slate-800 font-serif antialiased selection:bg-slate-900 selection:text-white; - line-height: 1.8; + line-height: 1.6; } /* Typography */ h1, h2, h3, h4, h5, h6 { - @apply font-sans font-bold text-slate-900; + @apply font-sans font-bold text-slate-900 tracking-tighter; } h1 { - @apply text-4xl md:text-5xl leading-[1.1] mb-8 tracking-tight; + @apply text-6xl md:text-8xl leading-[0.95] mb-12; } h2 { - @apply text-3xl md:text-4xl leading-[1.2] mb-6 mt-12 tracking-tight; + @apply text-4xl md:text-6xl leading-tight mb-8 mt-16; } h3 { - @apply text-2xl md:text-3xl leading-[1.3] mb-4 mt-8 tracking-tight; + @apply text-3xl md:text-5xl leading-tight mb-6 mt-12; } h4 { - @apply text-xl md:text-2xl leading-[1.4] mb-3 mt-6 tracking-tight; + @apply text-2xl md:text-3xl leading-tight mb-4 mt-8; } p { diff --git a/app/page.tsx b/app/page.tsx index d90b85d..c0074bd 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,6 +1,4 @@ -import { ArrowRight } from 'lucide-react'; import { - CirclePattern, ComparisonRow, ConceptAutomation, ConceptCode, @@ -10,80 +8,61 @@ import { ConceptPrototyping, ConceptSystem, ConceptWebsite, - ConnectorBranch, - ConnectorEnd, - ConnectorSplit, - ConnectorStart, - ContactIllustration, DifferenceIllustration, - FlowLines, - GridLines, HeroArchitecture, - HeroMainIllustration, - ServicesFlow + HeroMainIllustration } from '../src/components/Landing'; import { Reveal } from '../src/components/Reveal'; import { Section } from '../src/components/Section'; +import { H1, H3, LeadText, BodyText, MonoLabel, Label } from '../src/components/Typography'; +import { BackgroundGrid, Card, Container } from '../src/components/Layout'; +import { Button } from '../src/components/Button'; export default function LandingPage() { return (
- {/* Subtle Grid Pattern Overlay */} -
+ - {/* Hero Section - Split Layout */} -
-
- {/* Connector Start for Hero */} -
- -
- -
- {/* Left Column: Brand & Number */} -
+ {/* Hero Section */} +
+ +
+ {/* Left Column */} +
-
- - Digital Architect +
+
+ Digital Architect
-

+

Websites
- ohne
Overhead.
-

-
- {/* Right Column: Visual & Context */} -
- {/* Hero Architecture Illustration - Background Layer */} -
+ {/* Right Column */} +
+
- +
-
+
{/* Section 02: The Promise */} @@ -91,41 +70,33 @@ export default function LandingPage() { number="02" title="Das Versprechen" borderTop - connector={} >
-
- -
- -

+

Schluss mit aufgeblähten Prozessen.
- Ich reduziere auf das Wesentliche. -

+ Ich reduziere auf das Wesentliche. +
-
+
-
-
- -
- Was ich biete +
+
-
    +
      {[ - { text: 'Direkte Kommunikation ohne Account Manager', icon: }, - { text: 'Schnelle Prototypen statt langer Konzepte', icon: }, - { text: 'Sauberer Code, der auch morgen noch läuft', icon: }, - { text: 'Fixpreise für klare Budgetsicherheit', icon: } + { text: 'Direkte Kommunikation ohne Umwege', icon: }, + { text: 'Schnelle Prototypen statt langer Konzepte', icon: }, + { text: 'Sauberer Code, der auch morgen noch läuft', icon: }, + { text: 'Fixpreise für volle Budgetsicherheit', icon: } ].map((item, i) => ( -
    • -
      +
    • +
      {item.icon}
      - {item.text} + {item.text}
    • ))}
    @@ -133,12 +104,9 @@ export default function LandingPage() { -
    -
    -
    - -
    - Was ich nicht mache +
    +
    +
      {[ @@ -147,9 +115,9 @@ export default function LandingPage() { 'Outsourcing an Billig-Anbieter', 'Wartungsverträge mit versteckten Kosten' ].map((item, i) => ( -
    • - - {item} +
    • + + {item}
    • ))}
    @@ -165,43 +133,37 @@ export default function LandingPage() { title="Der Unterschied" variant="white" borderTop - connector={} > -
    +
    -

    - Der klassische Agentur-Weg ist oft langsam und teuer. Mein Ansatz ist radikal anders: Ich baue zuerst, dann reden wir über Details. -

    + + Ich arbeite nicht gegen die Zeit, sondern für das Ergebnis. Mein Fokus liegt auf der Umsetzung, nicht auf der Verwaltung von Prozessen. +
    - - + +
    + +
    -
    +
    -
@@ -211,103 +173,97 @@ export default function LandingPage() { number="04" title="Zielgruppe" borderTop - connector={} > -
-
- -
-
- -
-
-
- -
-

Unternehmer &
Geschäftsführer

-

- "Ich brauche eine Lösung, die funktioniert. Ich habe keine Zeit für technische Details oder lange Meetings." -

-
-
- Perfekt für Sie +
+ + +
+
+
+

Unternehmer &
Geschäftsführer

+ + "Ich brauche eine Lösung, die funktioniert. Ich habe keine Zeit für technische Details." +
-
- -
-
-
- -
-

Marketing &
Vertrieb

-

- "Wir brauchen Landingpages, Tools und Automatisierungen, um unsere Ziele zu erreichen. Schnell und zuverlässig." -

-
-
- Perfekt für Sie -
+
+
- -
+ +
+ + +
+
+ +
+

Marketing &
Vertrieb

+ + "Wir brauchen Landingpages und Tools, um unsere Ziele zu erreichen. Schnell und zuverlässig." + +
+
+ +
+
+
- {/* Section 05: Services - Visual Flow */} + {/* Section 05: Services */}
} > -
- {/* Connecting Line Illustration */} -
- -
- -
- -
-
- -
-

Websites

-

- High-Performance Websites. Kein Baukasten, sondern maßgeschneiderte Architektur. -

- - Preise ansehen +
+ + +
+ +
+
- + + - -
-
- -
-

Systeme

-

- Web-Applikationen, Kundenportale, interne Tools. Wenn Standard-Software an ihre Grenzen stößt. -

+ + +
+
-
+
+

Systeme

+ + Web-Applikationen, Portale, interne Tools. Wenn Standard an Grenzen stößt. + +
+ + - -
-
- -
-

Automatisierung

-

- Verbindung von Tools, automatische PDF-Erstellung, Daten-Synchronisation. -

+ + +
+
-
-
+
+

Automatisierung

+ + Verbindung von Tools, automatische Prozesse, Daten-Synchronisation. + +
+ +
@@ -316,43 +272,38 @@ export default function LandingPage() { number="06" title="Kontakt" borderTop - connector={} >
-
- -
-
- -
-
-

+
+

Lassen Sie uns
- starten. -

+ starten. +

-
-
-

- Schreiben Sie mir kurz, worum es geht. Ich melde mich innerhalb von 24 Stunden mit einer ersten Einschätzung. -

- - Projekt anfragen - +
+
+ + Schreiben Sie mir kurz, worum es geht. Ich melde mich innerhalb von 24 Stunden. + +
-
-
+
+
- Verfügbar für neue Projekte +
-

- Aktuell nehme ich Projekte für Q2 2026 an. -

+ + Aktuell nehme ich Projekte für Q2 2026 an. +
diff --git a/app/websites/page.tsx b/app/websites/page.tsx index b228d37..b81860e 100644 --- a/app/websites/page.tsx +++ b/app/websites/page.tsx @@ -1,6 +1,5 @@ 'use client'; -import { Info, Check, Zap, Shield, Code, MessageSquare, RefreshCw, Layout, ArrowRight } from 'lucide-react'; import { PageHeader } from '../../src/components/PageHeader'; import { Reveal } from '../../src/components/Reveal'; import { Section } from '../../src/components/Section'; @@ -10,23 +9,28 @@ import { SolidFoundation, LayerSeparation, DirectService, - AgencyChaos, - TaskDone -} from '../../src/components/Landing/Illustrations/WebsitesDescriptive'; -import { motion } from 'framer-motion'; + TaskDone, + ConceptAutomation, + ConceptCode, + ConceptCommunication, + ConceptPrototyping, + ConceptSystem, + ConceptTarget +} from '../../src/components/Landing'; +import { Check } from 'lucide-react'; +import { H2, H3, H4, LeadText, BodyText, Label } from '../../src/components/Typography'; +import { BackgroundGrid, Card } from '../../src/components/Layout'; +import { MotionButton } from '../../src/components/Button'; export default function WebsitesPage() { return (
- {/* Subtle Grid Pattern Overlay */} -
+ + Websites, die
einfach funktionieren.} - description="Die meisten Websites funktionieren. Bis jemand sie anfasst. Ich baue Websites so, dass das alles egal ist." + title={<>Websites, die
einfach funktionieren.} + description="Keine Baukästen, keine Plugins, kein Overhead. Nur sauberer Code und maximale Performance." backLink={{ href: '/', label: 'Zurück' }} backgroundSymbol="W" /> @@ -36,32 +40,34 @@ export default function WebsitesPage() { number="01" title="Der Ansatz" borderTop - illustration={} + illustration={} >
-

+

Ich baue Websites wie Systeme –
- nicht wie Broschüren. -

+ nicht wie Broschüren. +
-

- Eine Website ist kein Flyer. Sie ist ein System, das jeden Tag arbeitet. - Deshalb baue ich sie stabil, schnell und vorhersehbar. -

+ + Eine Website ist kein Flyer. Sie ist ein Werkzeug, das jeden Tag arbeitet. + Deshalb baue ich sie stabil, schnell und wartungsfrei. +
{[ - { label: 'Stabil', icon: Shield }, - { label: 'Schnell', icon: Zap }, - { label: 'Vorhersehbar', icon: Layout }, - { label: 'Sicher', icon: Info }, + { label: 'Stabil', icon: ConceptSystem }, + { label: 'Schnell', icon: ConceptAutomation }, + { label: 'Wartungsfrei', icon: ConceptCode }, + { label: 'Sicher', icon: ConceptTarget }, ].map((item, i) => ( -
- - {item.label} +
+
+ +
+
))}
@@ -74,42 +80,47 @@ export default function WebsitesPage() { number="02" title="Performance" borderTop - illustration={} + variant="gray" + illustration={} >
-

+

Geschwindigkeit ist
- kein Extra. Sie ist Standard. -

+ kein Extra. Sie ist Standard. +
- -

- Viele Websites sind langsam, weil sie zusammengeklickt sind. Meine sind schnell, weil sie gebaut sind. -

-
-
- -
    - {[ - 'Seiten laden sofort', - 'Google mag sie (SEO)', - 'Besucher bleiben länger', - 'Bessere Sichtbarkeit', - ].map((item, i) => ( -
  • -
    - {item} -
  • - ))} -
-
- -
-
90+
-
Pagespeed Normalzustand
-
-
+
+
+ + + Viele Websites sind langsam, weil sie zusammengeklickt sind. Meine sind schnell, weil sie von Grund auf entwickelt wurden. + + + +
    + {[ + 'Seiten laden ohne Verzögerung', + 'Optimiert für Suchmaschinen (SEO)', + 'Bessere Nutzererfahrung', + 'Höhere Conversion-Rates', + ].map((item, i) => ( +
  • +
    + {item} +
  • + ))} +
+
+
+
+ + +
90+
+ +
+
+
@@ -117,33 +128,39 @@ export default function WebsitesPage() { {/* No Maintenance */}
} + illustration={} >
-

+

Keine Plugins.
- Keine Wartungshölle. -

+ Keine Abhängigkeiten. +
-

- Ich nutze keine Baukästen oder Plugin-Sammlungen, die sich selbst zerstören. - Ihre Website besteht aus sauberem Code und einer klaren Struktur. -

+ + Ich nutze keine Baukästen, die sich selbst zerstören. + Ihre Website besteht aus sauberem Code, der Ihnen gehört. +
-
-
Technik
-

Sauberer Code & feste Bausteine.

-
-
-
Sicherheit
-

Wenn etwas geändert wird, geht nichts kaputt.

-
+ +
+ +

Langlebigkeit

+ Modernste Web-Technologien für maximale Performance und Wartbarkeit. +
+
+ +
+ +

Resilienz

+ Minimale Angriffsfläche durch Verzicht auf unnötige Drittanbieter-Software. +
+
@@ -154,40 +171,48 @@ export default function WebsitesPage() { number="04" title="Inhalte" borderTop - illustration={} + variant="gray" + illustration={} >
-

- Inhalte & Technik
- sind getrennt. Absichtlich. -

+

+ Inhalte pflegen
+ ohne Angst. +

- -

- Sie können Inhalte selbst pflegen, ohne das Design oder die Technik zu gefährden. - Sie können nichts kaputt machen. Ich verspreche es. -

-
- -
-
-
Was Sie tun
-
- - Inhalte pflegen -
-
-
-
Was Sie ignorieren
-
-
Design
-
Struktur
-
Technik
-
-
+
+
+ + + Sie können Texte und Bilder selbst anpassen, ohne das Design oder die Technik zu gefährden. + Ein intuitives System sorgt dafür, dass alles an seinem Platz bleibt. + +
- +
+ + +
+ +
+
+ +
+ Inhalte flexibel verwalten +
+
+
+ +
+
Design-Chaos
+
Technische Fehler
+
+
+
+
+
+
@@ -196,87 +221,69 @@ export default function WebsitesPage() { number="05" title="Service" borderTop - illustration={} + illustration={} >
-

+

Änderungen sind
- einfach. Wirklich. -

+ Teil des Konzepts. +
-

- Neue Seite? Neue Funktion? Neue Idee?
- Kein Ticket. Kein Formular. Kein Projektplan. -

+ + Ihr Business entwickelt sich weiter, Ihre Website auch.
+ Keine komplizierten Prozesse, sondern direkte Umsetzung Ihrer Ideen. +
-
-
- -

Kurze Wege

-

Sie schreiben mir, was Sie brauchen.

-
-
- -

Schnelle Umsetzung

-

Ich setze es um. Fertig.

-
+
+ + +
+

Direkter Draht

+ Sie sprechen direkt mit dem Entwickler. Keine Stille Post. +
+
+ + +
+

Agile Anpassung

+ Schnelle Iterationen statt langer Wartezeiten. +
+
- {/* Why */} -
} - > -
- -

- 15 Jahre Agenturen
- waren genug. -

-
- -

- Zu viele Meetings. Zu viele Konzepte. Zu viele Übergaben. Zu viele „eigentlich müsste man mal“. - Meine Websites sind dafür gebaut, dass Dinge einfach passieren. -

-
-
-
- {/* Result */}
} + illustration={} >
-

- Eine Website, die sich wie eine
- erledigte Aufgabe anfühlt. -

+

+ Eine Website, die
+ einfach läuft. +

{[ - { title: 'Kein Stress', desc: 'Keine Wartungspflicht, keine Überraschungen.' }, - { title: 'Keine Abhängigkeit', desc: 'Sauberer Code, der Ihnen gehört.' }, - { title: 'Keine Agentur', desc: 'Direkter Kontakt, schnelle Ergebnisse.' }, + { title: 'Kein Overhead', desc: 'Fokus auf das, was Ihre Kunden wirklich brauchen.' }, + { title: 'Volle Kontrolle', desc: 'Der Code gehört Ihnen, ohne Vendor Lock-in.' }, + { title: 'Echte Performance', desc: 'Messbare Geschwindigkeit für bessere Ergebnisse.' }, ].map((item, i) => ( -
-
{item.title}
-

{item.desc}

+
+
+

{item.title}

+ {item.desc}
))} @@ -285,20 +292,14 @@ export default function WebsitesPage() {
-
Technik
-

- Modern, sicher, schnell. Aber das ist mein Problem, nicht Ihres. -

+ + + Lassen Sie uns über Ihr nächstes Projekt sprechen. +
- + Projekt anfragen - - +
diff --git a/package-lock.json b/package-lock.json index fce3699..68a0a9d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "@types/react-dom": "^19.2.3", "@vercel/og": "^0.8.6", "canvas-confetti": "^1.9.4", + "clsx": "^2.1.1", "framer-motion": "^12.29.2", "ioredis": "^5.9.1", "lucide-react": "^0.468.0", @@ -25,6 +26,7 @@ "react": "^19.2.3", "react-dom": "^19.2.3", "shiki": "^1.24.2", + "tailwind-merge": "^3.4.0", "tailwindcss": "^3.4.0" }, "devDependencies": { @@ -1889,6 +1891,15 @@ "node": ">=0.8" } }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/cluster-key-slot": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", @@ -4575,6 +4586,16 @@ "integrity": "sha512-djbJ/vZKZO+gPoSDThGNpKDO+o+bAeA4XQKovvkNCqnIS2t+S4qnLAGQhyyrulhCFRl1WWzAp0wUDV8PpTVU3g==", "license": "ISC" }, + "node_modules/tailwind-merge": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.4.0.tgz", + "integrity": "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, "node_modules/tailwindcss": { "version": "3.4.19", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz", diff --git a/package.json b/package.json index 0570720..d076e01 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "@types/react-dom": "^19.2.3", "@vercel/og": "^0.8.6", "canvas-confetti": "^1.9.4", + "clsx": "^2.1.1", "framer-motion": "^12.29.2", "ioredis": "^5.9.1", "lucide-react": "^0.468.0", @@ -31,6 +32,7 @@ "react": "^19.2.3", "react-dom": "^19.2.3", "shiki": "^1.24.2", + "tailwind-merge": "^3.4.0", "tailwindcss": "^3.4.0" }, "devDependencies": { diff --git a/src/components/Button.tsx b/src/components/Button.tsx new file mode 100644 index 0000000..5e9e337 --- /dev/null +++ b/src/components/Button.tsx @@ -0,0 +1,67 @@ +import * as React from 'react'; +import { ArrowRight } from 'lucide-react'; +import { motion } from 'framer-motion'; +import Link from 'next/link'; + +interface ButtonProps { + href: string; + children: React.ReactNode; + variant?: 'primary' | 'outline'; + className?: string; + showArrow?: boolean; +} + +export const Button: React.FC = ({ + href, + children, + variant = 'primary', + className = "", + showArrow = true +}) => { + const baseStyles = "inline-flex items-center gap-4 rounded-full font-bold uppercase tracking-widest transition-all duration-500 ease-[cubic-bezier(0.23,1,0.32,1)] group"; + + const variants = { + primary: "px-10 py-5 bg-slate-900 text-white hover:bg-slate-800 hover:-translate-y-1 hover:shadow-2xl hover:shadow-slate-900/20 text-sm", + outline: "px-8 py-4 border border-slate-200 bg-white text-slate-900 hover:border-slate-400 hover:bg-slate-50 hover:-translate-y-0.5 hover:shadow-xl hover:shadow-slate-100 text-sm" + }; + + const content = ( + <> + {children} + {showArrow && } + + ); + + if (href.startsWith('#')) { + return ( + + {content} + + ); + } + + return ( + + {content} + + ); +}; + +export const MotionButton: React.FC = ({ + href, + children, + variant = 'primary', + className = "", + showArrow = true +}) => { + return ( + + + + ); +}; diff --git a/src/components/Landing/AbstractLines.tsx b/src/components/Landing/AbstractLines.tsx index 7920c76..d6a7c0e 100644 --- a/src/components/Landing/AbstractLines.tsx +++ b/src/components/Landing/AbstractLines.tsx @@ -8,7 +8,6 @@ interface LineProps { delay?: number; } -// ... existing components ... export const HeroLines: React.FC = ({ className = "", delay = 0 }) => { return ( @@ -216,150 +215,7 @@ export const ComparisonLines: React.FC = ({ className = "", delay = 0 ) } -// --- New Connector Components --- - -export const ConnectorStart: React.FC = ({ className = "", delay = 0 }) => { - return ( - - - - - {/* Multiple Pulses */} - - - - - - - - ); -}; - -export const ConnectorBranch: React.FC = ({ className = "", delay = 0 }) => { - return ( - - {/* Main vertical line */} - - {/* Branch */} - - - {/* Pulses */} - - - - - - - - ); -}; - -export const ConnectorSplit: React.FC = ({ className = "", delay = 0 }) => { - return ( - - - - - - - - - - - ); -}; - -export const ConnectorEnd: React.FC = ({ className = "", delay = 0 }) => { - return ( - - - - - - - - ); -}; +export const ConnectorStart: React.FC = ({ className = "", delay = 0 }) => null; +export const ConnectorBranch: React.FC = ({ className = "", delay = 0 }) => null; +export const ConnectorSplit: React.FC = ({ className = "", delay = 0 }) => null; +export const ConnectorEnd: React.FC = ({ className = "", delay = 0 }) => null; diff --git a/src/components/Landing/ComparisonRow.tsx b/src/components/Landing/ComparisonRow.tsx index d05c0fc..a235d7e 100644 --- a/src/components/Landing/ComparisonRow.tsx +++ b/src/components/Landing/ComparisonRow.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import { ArrowRight } from 'lucide-react'; import { Reveal } from '../Reveal'; +import { Label, H3, LeadText } from '../Typography'; interface ComparisonRowProps { negativeLabel: string; @@ -23,12 +24,12 @@ export const ComparisonRow: React.FC = ({
-
+
-
+ + {negativeText} -
+
@@ -36,12 +37,12 @@ export const ComparisonRow: React.FC = ({
-
+
-
+ +

{positiveText} -

+
diff --git a/src/components/Landing/Illustrations/index.ts b/src/components/Landing/Illustrations/index.ts index 1508b25..865cae3 100644 --- a/src/components/Landing/Illustrations/index.ts +++ b/src/components/Landing/Illustrations/index.ts @@ -13,3 +13,4 @@ export * from './HeroMainIllustration'; export * from './ExperienceIllustration'; export * from './ResponsibilityIllustration'; export * from './ResultIllustration'; +export * from './WebsitesDescriptive'; diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx new file mode 100644 index 0000000..08ee084 --- /dev/null +++ b/src/components/Layout.tsx @@ -0,0 +1,68 @@ +import * as React from 'react'; +import { cn } from '../utils/cn'; + +export const BackgroundGrid: React.FC = () => ( +
+); + +interface CardProps { + children: React.ReactNode; + className?: string; + variant?: 'white' | 'dark' | 'gray'; + hover?: boolean; + padding?: 'none' | 'small' | 'normal' | 'large'; +} + +export const Card: React.FC = ({ + children, + className = "", + variant = 'white', + hover = true, + padding = 'normal' +}) => { + const variants = { + white: 'bg-white border-slate-100 text-slate-900 shadow-sm', + dark: 'bg-slate-900 border-white/5 text-white shadow-xl', + gray: 'bg-slate-50/50 border-slate-100 text-slate-900' + }; + + const paddings = { + none: 'p-0', + small: 'p-6 md:p-8', + normal: 'p-8 md:p-10', + large: 'p-10 md:p-12' + }; + + return ( +
+ {children} +
+ ); +}; + +export const Container: React.FC<{ children: React.ReactNode; className?: string; variant?: 'narrow' | 'normal' | 'wide' }> = ({ + children, + className = "", + variant = 'normal' +}) => { + const variants = { + narrow: 'max-w-4xl', + normal: 'max-w-6xl', + wide: 'max-w-7xl' + }; + + return ( +
+ {children} +
+ ); +}; diff --git a/src/components/PageHeader.tsx b/src/components/PageHeader.tsx index 46e1b61..736c347 100644 --- a/src/components/PageHeader.tsx +++ b/src/components/PageHeader.tsx @@ -2,6 +2,8 @@ import * as React from 'react'; import { ArrowLeft } from 'lucide-react'; import Link from 'next/link'; import { Reveal } from './Reveal'; +import { H1, LeadText } from './Typography'; +import { cn } from '../utils/cn'; interface PageHeaderProps { title: React.ReactNode; @@ -11,18 +13,20 @@ interface PageHeaderProps { label: string; }; backgroundSymbol?: string; + className?: string; } export const PageHeader: React.FC = ({ title, description, backLink, - backgroundSymbol + backgroundSymbol, + className = "" }) => { return ( -
+
{backgroundSymbol && ( -
+
{backgroundSymbol}
)} @@ -30,24 +34,24 @@ export const PageHeader: React.FC = ({ {backLink && ( - {backLink.label} + {backLink.label} )} -
+
-

+

{title} -

+
{description && ( -

+ {description} -

+
)}
diff --git a/src/components/Section.tsx b/src/components/Section.tsx index e589b1c..e86e6f0 100644 --- a/src/components/Section.tsx +++ b/src/components/Section.tsx @@ -1,5 +1,7 @@ import * as React from 'react'; import { Reveal } from './Reveal'; +import { Label } from './Typography'; +import { cn } from '../utils/cn'; interface SectionProps { number?: string; @@ -9,7 +11,7 @@ interface SectionProps { delay?: number; variant?: 'white' | 'gray'; borderTop?: boolean; - connector?: React.ReactNode; + borderBottom?: boolean; containerVariant?: 'narrow' | 'normal' | 'wide'; illustration?: React.ReactNode; } @@ -22,93 +24,59 @@ export const Section: React.FC = ({ delay = 0, variant = 'white', borderTop = false, - connector, + borderBottom = false, containerVariant = 'narrow', illustration, }) => { - const bgClass = variant === 'gray' ? 'bg-slate-50' : 'bg-white'; - const borderClass = borderTop ? 'border-t border-slate-100' : ''; + const bgClass = variant === 'gray' ? 'bg-slate-50/50' : 'bg-white'; + const borderTopClass = borderTop ? 'border-t border-slate-100' : ''; + const borderBottomClass = borderBottom ? 'border-b border-slate-100' : ''; const containerClass = containerVariant === 'wide' ? 'wide-container' : containerVariant === 'normal' ? 'container' : 'narrow-container'; - // If no number and title, or if we want to force a simple layout, we could add a prop. - // But let's make it smart: if it's wide, maybe we want the title on top anyway? - // The user specifically asked to move it above for the configurator. - - const isTopTitle = containerVariant === 'wide'; - return ( -
-
- {isTopTitle ? ( -
- {(number || title) && ( -
- {number && ( - - - {number} - - - )} - {title && ( - -
-
-

- {title} -

-
-
- )} -
- )} -
{children}
-
- ) : ( -
- {/* Sidebar: Number & Title */} -
- {/* Connector Line */} - {connector && ( -
- {connector} -
+
+
+
+ {/* Sidebar: Number & Title */} +
+
+ {number && ( + + + {number} + + + )} + {title && ( + +
+ +
+
+ )} + {illustration && ( + +
+ {illustration} +
+
)} - -
- {number && ( - - - {number} - - - )} - {title && ( - -
-
-

- {title} -

-
-
- )} - {illustration && ( - -
- {illustration} -
-
- )} -
-
- - {/* Main Content */} -
- {children}
- )} + + {/* Main Content */} +
+ {children} +
+
); diff --git a/src/components/Typography.tsx b/src/components/Typography.tsx new file mode 100644 index 0000000..81ad9b2 --- /dev/null +++ b/src/components/Typography.tsx @@ -0,0 +1,54 @@ +import * as React from 'react'; + +interface TypographyProps { + children: React.ReactNode; + className?: string; +} + +export const H1: React.FC = ({ children, className = "" }) => ( +

+ {children} +

+); + +export const H2: React.FC = ({ children, className = "" }) => ( +

+ {children} +

+); + +export const H3: React.FC = ({ children, className = "" }) => ( +

+ {children} +

+); + +export const H4: React.FC = ({ children, className = "" }) => ( +

+ {children} +

+); + +export const LeadText: React.FC = ({ children, className = "" }) => ( +

+ {children} +

+); + +export const BodyText: React.FC = ({ children, className = "" }) => ( +

+ {children} +

+); + +export const Label: React.FC = ({ children, className = "" }) => ( + + {children} + +); + +export const MonoLabel: React.FC = ({ children, className = "" }) => ( + + {children} + +); diff --git a/src/utils/cn.ts b/src/utils/cn.ts new file mode 100644 index 0000000..9ad0df4 --- /dev/null +++ b/src/utils/cn.ts @@ -0,0 +1,6 @@ +import { type ClassValue, clsx } from 'clsx'; +import { twMerge } from 'tailwind-merge'; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +}