diff --git a/attached_assets/generated_images/arch_linux_i3_terminal_screenshot.png b/attached_assets/generated_images/arch_linux_i3_terminal_screenshot.png
new file mode 100644
index 0000000..fa94326
Binary files /dev/null and b/attached_assets/generated_images/arch_linux_i3_terminal_screenshot.png differ
diff --git a/attached_assets/generated_images/elementary_os_mac-like_screenshot.png b/attached_assets/generated_images/elementary_os_mac-like_screenshot.png
new file mode 100644
index 0000000..622a2b3
Binary files /dev/null and b/attached_assets/generated_images/elementary_os_mac-like_screenshot.png differ
diff --git a/attached_assets/generated_images/fedora_kde_plasma_screenshot.png b/attached_assets/generated_images/fedora_kde_plasma_screenshot.png
new file mode 100644
index 0000000..9de5764
Binary files /dev/null and b/attached_assets/generated_images/fedora_kde_plasma_screenshot.png differ
diff --git a/attached_assets/generated_images/linux_mint_cinnamon_screenshot.png b/attached_assets/generated_images/linux_mint_cinnamon_screenshot.png
new file mode 100644
index 0000000..05354d6
Binary files /dev/null and b/attached_assets/generated_images/linux_mint_cinnamon_screenshot.png differ
diff --git a/attached_assets/generated_images/pop_os_developer_screenshot.png b/attached_assets/generated_images/pop_os_developer_screenshot.png
new file mode 100644
index 0000000..8f74242
Binary files /dev/null and b/attached_assets/generated_images/pop_os_developer_screenshot.png differ
diff --git a/attached_assets/generated_images/ubuntu_gnome_desktop_screenshot.png b/attached_assets/generated_images/ubuntu_gnome_desktop_screenshot.png
new file mode 100644
index 0000000..b0ab5ea
Binary files /dev/null and b/attached_assets/generated_images/ubuntu_gnome_desktop_screenshot.png differ
diff --git a/client/index.html b/client/index.html
index 5ac9c7f..599027f 100644
--- a/client/index.html
+++ b/client/index.html
@@ -3,6 +3,10 @@
+
+
+
+ DistroMatch - Find Your Perfect Linux Distro
diff --git a/client/src/App.tsx b/client/src/App.tsx
index b4c5b9e..f86c957 100644
--- a/client/src/App.tsx
+++ b/client/src/App.tsx
@@ -4,13 +4,12 @@ import { QueryClientProvider } from "@tanstack/react-query";
import { Toaster } from "@/components/ui/toaster";
import { TooltipProvider } from "@/components/ui/tooltip";
import NotFound from "@/pages/not-found";
+import Home from "@/pages/home";
function Router() {
return (
- {/* Add pages below */}
- {/* */}
- {/* Fallback to 404 */}
+
);
diff --git a/client/src/components/ActionButtons.tsx b/client/src/components/ActionButtons.tsx
new file mode 100644
index 0000000..394c1f0
--- /dev/null
+++ b/client/src/components/ActionButtons.tsx
@@ -0,0 +1,56 @@
+import { Heart, X, RotateCcw } from 'lucide-react';
+import { Button } from '@/components/ui/button';
+
+interface ActionButtonsProps {
+ onLike: () => void;
+ onDislike: () => void;
+ onReset?: () => void;
+ showReset?: boolean;
+ disabled?: boolean;
+}
+
+export default function ActionButtons({
+ onLike,
+ onDislike,
+ onReset,
+ showReset = false,
+ disabled = false,
+}: ActionButtonsProps) {
+ return (
+
+
+
+ {showReset && onReset && (
+
+ )}
+
+
+
+ );
+}
diff --git a/client/src/components/CardStack.tsx b/client/src/components/CardStack.tsx
new file mode 100644
index 0000000..f18992e
--- /dev/null
+++ b/client/src/components/CardStack.tsx
@@ -0,0 +1,102 @@
+import { useState, useCallback } from 'react';
+import { AnimatePresence, motion } from 'framer-motion';
+import SwipeCard from './SwipeCard';
+import ActionButtons from './ActionButtons';
+import EndOfDeck from './EndOfDeck';
+import type { DistroCard } from '@/data/distros';
+
+interface CardStackProps {
+ cards: DistroCard[];
+ onBackgroundChange?: (colors: string[]) => void;
+}
+
+export default function CardStack({ cards, onBackgroundChange }: CardStackProps) {
+ const [currentIndex, setCurrentIndex] = useState(0);
+ const [likedCards, setLikedCards] = useState([]);
+ const [dislikedCards, setDislikedCards] = useState([]);
+
+ const visibleCards = cards.slice(currentIndex, currentIndex + 3);
+ const isFinished = currentIndex >= cards.length;
+
+ const handleSwipe = useCallback(
+ (direction: 'left' | 'right') => {
+ const currentCard = cards[currentIndex];
+ if (!currentCard) return;
+
+ if (direction === 'right') {
+ setLikedCards((prev) => [...prev, currentCard]);
+ console.log('Liked:', currentCard.distroName);
+ } else {
+ setDislikedCards((prev) => [...prev, currentCard]);
+ console.log('Disliked:', currentCard.distroName);
+ }
+
+ const nextIndex = currentIndex + 1;
+ setCurrentIndex(nextIndex);
+
+ const nextCard = cards[nextIndex];
+ if (nextCard && onBackgroundChange) {
+ onBackgroundChange(nextCard.colorPalette);
+ }
+ },
+ [currentIndex, cards, onBackgroundChange]
+ );
+
+ const handleReset = useCallback(() => {
+ setCurrentIndex(0);
+ setLikedCards([]);
+ setDislikedCards([]);
+ if (cards[0] && onBackgroundChange) {
+ onBackgroundChange(cards[0].colorPalette);
+ }
+ }, [cards, onBackgroundChange]);
+
+ if (isFinished) {
+ return ;
+ }
+
+ return (
+
+
+
+ {visibleCards.map((card, index) => {
+ const isTop = index === 0;
+ const scale = 1 - index * 0.05;
+ const offsetY = index * 12;
+ const zIndex = visibleCards.length - index;
+
+ return (
+
+ );
+ })}
+
+
+
+
+ handleSwipe('right')}
+ onDislike={() => handleSwipe('left')}
+ onReset={handleReset}
+ showReset={currentIndex > 0}
+ disabled={isFinished}
+ />
+
+
+
+ {currentIndex + 1} / {cards.length}
+
+
+ );
+}
diff --git a/client/src/components/DynamicBackground.tsx b/client/src/components/DynamicBackground.tsx
new file mode 100644
index 0000000..c97951f
--- /dev/null
+++ b/client/src/components/DynamicBackground.tsx
@@ -0,0 +1,23 @@
+import { motion } from 'framer-motion';
+
+interface DynamicBackgroundProps {
+ colors: string[];
+}
+
+export default function DynamicBackground({ colors }: DynamicBackgroundProps) {
+ const gradientColors = colors.length >= 2
+ ? colors
+ : ['#6B46C1', '#4F46E5', '#2563EB'];
+
+ return (
+
+
+
+ );
+}
diff --git a/client/src/components/EndOfDeck.tsx b/client/src/components/EndOfDeck.tsx
new file mode 100644
index 0000000..6ac7724
--- /dev/null
+++ b/client/src/components/EndOfDeck.tsx
@@ -0,0 +1,86 @@
+import { motion } from 'framer-motion';
+import { PartyPopper, RotateCcw, Download } from 'lucide-react';
+import { Button } from '@/components/ui/button';
+import type { DistroCard } from '@/data/distros';
+
+interface EndOfDeckProps {
+ likedCards: DistroCard[];
+ onReset: () => void;
+}
+
+export default function EndOfDeck({ likedCards, onReset }: EndOfDeckProps) {
+ return (
+
+
+
+
+
+
+
+ Öneriler Hazır!
+
+
+ {likedCards.length > 0
+ ? `${likedCards.length} dağıtım beğendin`
+ : 'Hiçbir dağıtım beğenmedin'}
+
+
+
+ {likedCards.length > 0 && (
+
+ {likedCards.map((card) => (
+
+
+
+
{card.distroName}
+
{card.desktopEnvironment}
+
+
+ ))}
+
+ )}
+
+
+
+ {likedCards.length > 0 && (
+
+ )}
+
+
+ );
+}
diff --git a/client/src/components/Header.tsx b/client/src/components/Header.tsx
new file mode 100644
index 0000000..573e22b
--- /dev/null
+++ b/client/src/components/Header.tsx
@@ -0,0 +1,22 @@
+import { motion } from 'framer-motion';
+import { Terminal } from 'lucide-react';
+
+export default function Header() {
+ return (
+
+
+
+
+
+
+ DistroMatch
+
+
+
+ );
+}
diff --git a/client/src/components/SwipeCard.tsx b/client/src/components/SwipeCard.tsx
new file mode 100644
index 0000000..3a862ab
--- /dev/null
+++ b/client/src/components/SwipeCard.tsx
@@ -0,0 +1,130 @@
+import { motion, useMotionValue, useTransform, PanInfo } from 'framer-motion';
+import { Heart, X } from 'lucide-react';
+import type { DistroCard } from '@/data/distros';
+
+interface SwipeCardProps {
+ card: DistroCard;
+ isTop: boolean;
+ onSwipe: (direction: 'left' | 'right') => void;
+ scale?: number;
+ zIndex: number;
+ offsetY?: number;
+}
+
+export default function SwipeCard({
+ card,
+ isTop,
+ onSwipe,
+ scale = 1,
+ zIndex,
+ offsetY = 0,
+}: SwipeCardProps) {
+ const x = useMotionValue(0);
+ const rotate = useTransform(x, [-300, 0, 300], [-15, 0, 15]);
+ const likeOpacity = useTransform(x, [0, 150], [0, 1]);
+ const nopeOpacity = useTransform(x, [-150, 0], [1, 0]);
+
+ const handleDragEnd = (_: MouseEvent | TouchEvent | PointerEvent, info: PanInfo) => {
+ const threshold = 150;
+ if (info.offset.x > threshold) {
+ onSwipe('right');
+ } else if (info.offset.x < -threshold) {
+ onSwipe('left');
+ }
+ };
+
+ return (
+ 0 ? 500 : -500,
+ opacity: 0,
+ rotate: x.get() > 0 ? 20 : -20,
+ transition: { duration: 0.3 },
+ }}
+ >
+
+
+

+
+ {isTop && (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+ >
+ )}
+
+
+
+
+ {card.wittyTitle}
+
+
+
+ {card.distroName}
+
+
+ {card.desktopEnvironment}
+
+
+ {card.tags.slice(0, 3).map((tag) => (
+
+ {tag}
+
+ ))}
+
+
+
+
+
+ );
+}
diff --git a/client/src/components/examples/ActionButtonsExample.tsx b/client/src/components/examples/ActionButtonsExample.tsx
new file mode 100644
index 0000000..c07e207
--- /dev/null
+++ b/client/src/components/examples/ActionButtonsExample.tsx
@@ -0,0 +1,14 @@
+import ActionButtons from '../ActionButtons';
+
+export default function ActionButtonsExample() {
+ return (
+
+
console.log('Liked!')}
+ onDislike={() => console.log('Disliked!')}
+ onReset={() => console.log('Reset!')}
+ showReset={true}
+ />
+
+ );
+}
diff --git a/client/src/components/examples/CardStackExample.tsx b/client/src/components/examples/CardStackExample.tsx
new file mode 100644
index 0000000..ea652f2
--- /dev/null
+++ b/client/src/components/examples/CardStackExample.tsx
@@ -0,0 +1,13 @@
+import CardStack from '../CardStack';
+import { distroCards } from '@/data/distros';
+
+export default function CardStackExample() {
+ return (
+
+ console.log('Colors:', colors)}
+ />
+
+ );
+}
diff --git a/client/src/components/examples/EndOfDeckExample.tsx b/client/src/components/examples/EndOfDeckExample.tsx
new file mode 100644
index 0000000..87b7f90
--- /dev/null
+++ b/client/src/components/examples/EndOfDeckExample.tsx
@@ -0,0 +1,15 @@
+import EndOfDeck from '../EndOfDeck';
+import { distroCards } from '@/data/distros';
+
+export default function EndOfDeckExample() {
+ const likedCards = distroCards.slice(0, 3);
+
+ return (
+
+ console.log('Reset!')}
+ />
+
+ );
+}
diff --git a/client/src/components/examples/HeaderExample.tsx b/client/src/components/examples/HeaderExample.tsx
new file mode 100644
index 0000000..87947a1
--- /dev/null
+++ b/client/src/components/examples/HeaderExample.tsx
@@ -0,0 +1,9 @@
+import Header from '../Header';
+
+export default function HeaderExample() {
+ return (
+
+
+
+ );
+}
diff --git a/client/src/components/examples/SwipeCardExample.tsx b/client/src/components/examples/SwipeCardExample.tsx
new file mode 100644
index 0000000..de89c0d
--- /dev/null
+++ b/client/src/components/examples/SwipeCardExample.tsx
@@ -0,0 +1,21 @@
+import SwipeCard from '../SwipeCard';
+import { distroCards } from '@/data/distros';
+
+export default function SwipeCardExample() {
+ const card = distroCards[0];
+
+ return (
+
+
+ console.log('Swiped:', dir)}
+ scale={1}
+ zIndex={10}
+ offsetY={0}
+ />
+
+
+ );
+}
diff --git a/client/src/data/distros.ts b/client/src/data/distros.ts
new file mode 100644
index 0000000..a41cd48
--- /dev/null
+++ b/client/src/data/distros.ts
@@ -0,0 +1,73 @@
+import ubuntuScreenshot from '@assets/generated_images/ubuntu_gnome_desktop_screenshot.png';
+import archScreenshot from '@assets/generated_images/arch_linux_i3_terminal_screenshot.png';
+import elementaryScreenshot from '@assets/generated_images/elementary_os_mac-like_screenshot.png';
+import fedoraScreenshot from '@assets/generated_images/fedora_kde_plasma_screenshot.png';
+import mintScreenshot from '@assets/generated_images/linux_mint_cinnamon_screenshot.png';
+import popScreenshot from '@assets/generated_images/pop_os_developer_screenshot.png';
+
+export interface DistroCard {
+ id: string;
+ distroName: string;
+ screenshot: string;
+ wittyTitle: string;
+ desktopEnvironment: string;
+ tags: string[];
+ colorPalette: string[];
+}
+
+export const distroCards: DistroCard[] = [
+ {
+ id: '1',
+ distroName: 'Ubuntu',
+ screenshot: ubuntuScreenshot,
+ wittyTitle: 'Sadece çalışsın yeter',
+ desktopEnvironment: 'GNOME',
+ tags: ['beginner-friendly', 'stable', 'popular'],
+ colorPalette: ['#E95420', '#77216F', '#5E2750'],
+ },
+ {
+ id: '2',
+ distroName: 'Arch Linux',
+ screenshot: archScreenshot,
+ wittyTitle: 'Terminalden çıkmam',
+ desktopEnvironment: 'i3wm',
+ tags: ['advanced', 'minimal', 'customizable'],
+ colorPalette: ['#1793D1', '#333333', '#0D47A1'],
+ },
+ {
+ id: '3',
+ distroName: 'elementary OS',
+ screenshot: elementaryScreenshot,
+ wittyTitle: 'Mac gibi olsun',
+ desktopEnvironment: 'Pantheon',
+ tags: ['beautiful', 'simple', 'curated'],
+ colorPalette: ['#64BAFF', '#3689E6', '#0D52BF'],
+ },
+ {
+ id: '4',
+ distroName: 'Fedora',
+ screenshot: fedoraScreenshot,
+ wittyTitle: 'Her zaman güncel',
+ desktopEnvironment: 'KDE Plasma',
+ tags: ['cutting-edge', 'developer', 'reliable'],
+ colorPalette: ['#51A2DA', '#294172', '#3C6EB4'],
+ },
+ {
+ id: '5',
+ distroName: 'Linux Mint',
+ screenshot: mintScreenshot,
+ wittyTitle: 'Windows gibi ama özgür',
+ desktopEnvironment: 'Cinnamon',
+ tags: ['familiar', 'stable', 'beginner-friendly'],
+ colorPalette: ['#87CF3E', '#5FAD56', '#3E8E41'],
+ },
+ {
+ id: '6',
+ distroName: 'Pop!_OS',
+ screenshot: popScreenshot,
+ wittyTitle: 'Özelleştirme canavarı',
+ desktopEnvironment: 'COSMIC',
+ tags: ['gaming', 'developer', 'modern'],
+ colorPalette: ['#FAA41A', '#48B9C7', '#574F4A'],
+ },
+];
diff --git a/client/src/index.css b/client/src/index.css
index c8a4f35..a1f0801 100644
--- a/client/src/index.css
+++ b/client/src/index.css
@@ -43,9 +43,9 @@
--chart-3: 245 85% 55%;
--chart-4: 310 70% 48%;
--chart-5: 230 80% 52%;
- --font-sans: Open Sans, sans-serif;
+ --font-sans: Inter, sans-serif;
--font-serif: Georgia, serif;
- --font-mono: Menlo, monospace;
+ --font-mono: 'Space Grotesk', monospace;
--radius: .5rem;
--shadow-2xs: 0px 2px 0px 0px hsl(0 0% 0% / 0.00);
--shadow-xs: 0px 2px 0px 0px hsl(0 0% 0% / 0.00);
diff --git a/client/src/pages/home.tsx b/client/src/pages/home.tsx
new file mode 100644
index 0000000..d7565f1
--- /dev/null
+++ b/client/src/pages/home.tsx
@@ -0,0 +1,29 @@
+import { useState, useEffect } from 'react';
+import Header from '@/components/Header';
+import CardStack from '@/components/CardStack';
+import DynamicBackground from '@/components/DynamicBackground';
+import { distroCards } from '@/data/distros';
+
+export default function Home() {
+ const [backgroundColors, setBackgroundColors] = useState(
+ distroCards[0]?.colorPalette || ['#6B46C1', '#4F46E5', '#2563EB']
+ );
+
+ useEffect(() => {
+ document.documentElement.classList.add('dark');
+ }, []);
+
+ return (
+
+
+
+
+
+
+
+
+ );
+}