Created
January 15, 2025 19:52
-
-
Save airstrike/923a7049d5cde7405e60e99e224476b6 to your computer and use it in GitHub Desktop.
A React component for a curated product launch platform that focuses on quality over quantity. Features a daily showcase carousel, ranked submissions, and a clean, minimalist design. Built with React and Tailwind CSS.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useState } from 'react'; | |
import { Clock, ArrowUp, MessageSquare, ChevronLeft, ChevronRight, Search, ExternalLink } from 'lucide-react'; | |
const LaunchPlatform = () => { | |
const [currentSlide, setCurrentSlide] = useState(0); | |
const todaysLaunches = [ | |
{ | |
id: 1, | |
name: "CodePilot Pro", | |
description: "AI pair programming assistant", | |
longDescription: "Your intelligent coding companion that helps you write better code faster. Using advanced AI, CodePilot Pro understands your codebase and provides contextual suggestions.", | |
features: ["Real-time code analysis", "Smart completions", "Architecture suggestions"], | |
votes: 2, | |
comments: 1, | |
tags: ["AI", "Development", "Productivity"] | |
}, | |
{ | |
id: 2, | |
name: "DataViz Studio", | |
description: "Create stunning data visualizations", | |
longDescription: "Transform your data into beautiful, interactive visualizations with our intuitive drag-and-drop interface. Perfect for analysts and data storytellers.", | |
features: ["40+ chart types", "Interactive dashboards", "Real-time collaboration"], | |
votes: 4, | |
comments: 2, | |
tags: ["Data", "Design", "Analytics"] | |
}, | |
{ | |
id: 3, | |
name: "CloudGuard", | |
description: "Simple cloud security management", | |
longDescription: "Protect your cloud infrastructure with our all-in-one security platform. Monitor, detect, and respond to threats in real-time.", | |
features: ["Threat detection", "Compliance monitoring", "Auto-remediation"], | |
votes: 3, | |
comments: 2, | |
tags: ["Security", "DevOps", "Cloud"] | |
}, | |
{ | |
id: 4, | |
name: "MarketMuse", | |
description: "AI-powered market research", | |
longDescription: "Get instant market insights and competitor analysis powered by AI. Make better business decisions with real-time data.", | |
features: ["Competitor tracking", "Trend analysis", "Market predictions"], | |
votes: 1, | |
comments: 0, | |
tags: ["AI", "Business", "Analytics"] | |
} | |
]; | |
const yesterdaysLaunches = [ | |
{ | |
id: 1, | |
name: "SponsorApp", | |
description: "Make money with your website", | |
longDescription: "Connect with sponsors directly through our platform", | |
votes: 156, | |
comments: 24, | |
rank: 1 | |
}, | |
{ | |
id: 2, | |
name: "OG Image Generator", | |
description: "Free Open Graph Image Generator", | |
longDescription: "Create social media previews in seconds", | |
votes: 143, | |
comments: 18, | |
rank: 2 | |
}, | |
{ | |
id: 3, | |
name: "LightUp", | |
description: "Genius annotations for every page on the web", | |
longDescription: "Add context to any webpage instantly", | |
votes: 128, | |
comments: 15, | |
rank: 3 | |
}, | |
{ | |
id: 4, | |
name: "DeployBot", | |
description: "Zero-config deployment automation", | |
votes: 89, | |
comments: 12 | |
}, | |
{ | |
id: 5, | |
name: "PixelPerfect", | |
description: "Design collaboration for remote teams", | |
votes: 76, | |
comments: 8 | |
}, | |
{ | |
id: 6, | |
name: "TaskFlow", | |
description: "Beautiful Kanban boards for teams", | |
votes: 67, | |
comments: 9 | |
}, | |
{ | |
id: 7, | |
name: "CopyAI", | |
description: "AI-powered copywriting assistant", | |
votes: 54, | |
comments: 7 | |
}, | |
{ | |
id: 8, | |
name: "BugHunter", | |
description: "Automated testing made simple", | |
votes: 45, | |
comments: 5 | |
}, | |
{ | |
id: 9, | |
name: "AnalyticsPro", | |
description: "Privacy-first analytics platform", | |
votes: 34, | |
comments: 4 | |
}, | |
{ | |
id: 10, | |
name: "DevNews", | |
description: "Curated tech news for developers", | |
votes: 23, | |
comments: 3 | |
} | |
]; | |
const pastLaunches = [ | |
{ | |
id: 1, | |
name: "CloudStack", | |
description: "Infrastructure as code made easy", | |
date: "Jan 13", | |
votes: 234 | |
}, | |
{ | |
id: 2, | |
name: "DesignSystem", | |
description: "Create consistent UI in minutes", | |
date: "Jan 12", | |
votes: 187 | |
}, | |
{ | |
id: 3, | |
name: "SEOBooster", | |
description: "AI-powered SEO optimization", | |
date: "Jan 11", | |
votes: 156 | |
}, | |
{ | |
id: 4, | |
name: "CodeReview", | |
description: "Automated code review assistant", | |
date: "Jan 10", | |
votes: 143 | |
} | |
]; | |
const nextSlide = () => { | |
setCurrentSlide((prev) => (prev + 1) % todaysLaunches.length); | |
}; | |
const prevSlide = () => { | |
setCurrentSlide((prev) => (prev - 1 + todaysLaunches.length) % todaysLaunches.length); | |
}; | |
return ( | |
<div className="max-w-6xl mx-auto p-6 font-sans"> | |
{/* Header */} | |
<header className="flex justify-between items-center mb-8"> | |
<div className="flex items-center gap-8"> | |
<h1 className="text-2xl font-bold">Quality Over Quantity</h1> | |
<nav className="flex items-center gap-4"> | |
<a href="#" className="text-gray-600 hover:text-gray-900">Today</a> | |
<a href="#" className="text-gray-600 hover:text-gray-900">Past</a> | |
<div className="relative w-64"> | |
<Search className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-4 h-4" /> | |
<input | |
type="text" | |
placeholder="Search launches..." | |
className="w-full pl-9 pr-4 py-1.5 text-sm border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-teal-500" | |
/> | |
</div> | |
</nav> | |
</div> | |
<div className="flex gap-4 items-center"> | |
<button className="px-4 py-2 text-gray-600 hover:text-gray-900">Sign In</button> | |
<button className="px-4 py-2 bg-teal-600 hover:bg-teal-700 text-white rounded-lg transition-colors"> | |
Submit Your Product! | |
</button> | |
</div> | |
</header> | |
<div className="flex gap-8"> | |
{/* Main Content */} | |
<main className="flex-1"> | |
{/* Today's Launches Carousel */} | |
<div className="rounded-xl p-6 mb-12 bg-gradient-to-br from-gray-50 to-gray-100 border border-gray-200 shadow-md relative min-h-[400px]"> | |
<div className="absolute left-2 top-1/2 -translate-y-1/2 z-10"> | |
<button onClick={prevSlide} className="p-2 hover:bg-white rounded-full"> | |
<ChevronLeft className="w-6 h-6" /> | |
</button> | |
</div> | |
<div className="absolute right-2 top-1/2 -translate-y-1/2 z-10"> | |
<button onClick={nextSlide} className="p-2 hover:bg-white rounded-full"> | |
<ChevronRight className="w-6 h-6" /> | |
</button> | |
</div> | |
<div className="px-8"> | |
<h2 className="text-lg font-bold mb-6">Today's Launches</h2> | |
<div className="flex items-start gap-4"> | |
<div className="w-16 h-16 bg-white rounded-xl flex items-center justify-center shadow-sm"> | |
<img src="/api/placeholder/64/64" alt={todaysLaunches[currentSlide].name} className="w-12 h-12" /> | |
</div> | |
<div className="flex-1"> | |
<div className="flex justify-between items-start"> | |
<div className="space-y-4"> | |
<div> | |
<h2 className="text-xl font-bold mb-2">{todaysLaunches[currentSlide].name}</h2> | |
<p className="text-gray-600">{todaysLaunches[currentSlide].description}</p> | |
</div> | |
<div className="flex gap-2"> | |
{todaysLaunches[currentSlide].tags.map((tag) => ( | |
<span key={tag} className="px-3 py-1 bg-white rounded-full text-sm text-gray-600"> | |
{tag} | |
</span> | |
))} | |
</div> | |
<p className="text-gray-700">{todaysLaunches[currentSlide].longDescription}</p> | |
<div className="space-y-2"> | |
<div className="flex items-center gap-2 text-gray-600"> | |
<span className="font-medium">Key Features:</span> | |
</div> | |
<ul className="list-disc ml-5 text-gray-600 space-y-1"> | |
{todaysLaunches[currentSlide].features.map((feature, index) => ( | |
<li key={index}>{feature}</li> | |
))} | |
</ul> | |
</div> | |
</div> | |
<div className="flex gap-4 items-center"> | |
<div className="flex items-center gap-2"> | |
<button className="p-2 hover:bg-white rounded-full"> | |
<ArrowUp className="w-5 h-5" /> | |
</button> | |
<span>{todaysLaunches[currentSlide].votes}</span> | |
</div> | |
<div className="flex items-center gap-2"> | |
<MessageSquare className="w-5 h-5" /> | |
<span>{todaysLaunches[currentSlide].comments}</span> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
{/* Carousel Indicators */} | |
<div className="flex justify-center gap-2 mt-6"> | |
{todaysLaunches.map((_, index) => ( | |
<button | |
key={index} | |
onClick={() => setCurrentSlide(index)} | |
className={`w-2 h-2 rounded-full ${ | |
index === currentSlide ? 'bg-gray-800' : 'bg-gray-300' | |
}`} | |
/> | |
))} | |
</div> | |
{/* CTA Button */} | |
<div className="absolute bottom-6 right-6"> | |
<button className="px-6 py-3 bg-teal-600 hover:bg-teal-700 text-white rounded-lg flex items-center gap-2 transition-colors"> | |
Check it out | |
<ExternalLink className="w-4 h-4" /> | |
</button> | |
</div> | |
</div> | |
</div> | |
{/* Yesterday's Winners */} | |
<section className="mb-8"> | |
<h3 className="text-lg font-bold mb-6">Yesterday's Winners</h3> | |
<div className="space-y-4"> | |
{yesterdaysLaunches.map((product, index) => ( | |
<div | |
key={product.id} | |
className={`flex items-center gap-4 p-4 ${ | |
product.rank | |
? 'bg-white border-2 border-gray-200 rounded-lg shadow-sm' | |
: 'border-b border-gray-200' | |
}`} | |
> | |
{product.rank && ( | |
<span className="text-2xl"> | |
{product.rank === 1 ? "🥇" : product.rank === 2 ? "🥈" : "🥉"} | |
</span> | |
)} | |
<div className="w-12 h-12 bg-gray-100 rounded-lg flex items-center justify-center"> | |
<img src="/api/placeholder/48/48" alt={product.name} className="w-8 h-8" /> | |
</div> | |
<div className="flex-1"> | |
<h4 className="font-medium">{product.name}</h4> | |
<p className="text-sm text-gray-600">{product.description}</p> | |
</div> | |
<div className="flex items-center gap-4"> | |
<div className="flex items-center gap-2"> | |
<ArrowUp className="w-4 h-4" /> | |
<span className="text-sm">{product.votes}</span> | |
</div> | |
<div className="flex items-center gap-1"> | |
<MessageSquare className="w-4 h-4" /> | |
<span className="text-sm">{product.comments}</span> | |
</div> | |
</div> | |
</div> | |
))} | |
</div> | |
</section> | |
</main> | |
{/* Sidebar */} | |
<aside className="w-80"> | |
{/* Next Launch Timer */} | |
<div className="bg-black p-4 rounded-xl mb-6"> | |
<div className="flex flex-col items-center"> | |
<div className="flex items-center gap-2 mb-2"> | |
<Clock className="w-5 h-5 text-teal-400" /> | |
<span className="text-white font-medium">Next launch in</span> | |
</div> | |
<div className="font-mono text-3xl text-teal-400 tracking-wider">09:25:31</div> | |
</div> | |
</div> | |
{/* Platform Info */} | |
<div className="bg-blue-50 p-6 rounded-xl mb-6"> | |
<h3 className="font-bold mb-4">A Different Kind of Launch Platform</h3> | |
<ul className="space-y-4"> | |
<li className="flex items-start gap-2"> | |
<span className="text-blue-600 font-bold">+</span> | |
<span>Only 10 products featured daily for meaningful discovery</span> | |
</li> | |
<li className="flex items-start gap-2"> | |
<span className="text-blue-600 font-bold">+</span> | |
<span>2 daily upvotes to support products you truly believe in</span> | |
</li> | |
<li className="flex items-start gap-2"> | |
<span className="text-blue-600 font-bold">+</span> | |
<span>Quality over quantity, focused on genuine engagement</span> | |
</li> | |
</ul> | |
</div> | |
{/* Previous Launches */} | |
<div className="bg-white border border-gray-200 rounded-xl p-6"> | |
<div className="flex items-center justify-between mb-4"> | |
<h3 className="font-bold">Previous Launches</h3> | |
<a href="#" className="text-teal-600 hover:text-teal-700">View all</a> | |
</div> | |
<div className="space-y-4"> | |
{pastLaunches.map((launch) => ( | |
<div key={launch.id} className="flex items-center gap-3"> | |
<div className="w-10 h-10 bg-gray-100 rounded-lg flex items-center justify-center"> | |
<img src="/api/placeholder/40/40" alt={launch.name} className="w-6 h-6" /> | |
</div> | |
<div className="flex-1 min-w-0"> | |
<h4 className="font-medium truncate">{launch.name}</h4> | |
<p className="text-xs text-gray-500">{launch.date}</p> | |
</div> | |
<div className="flex items-center gap-1 text-gray-600"> | |
<ArrowUp className="w-3 h-3" /> | |
<span className="text-sm">{launch.votes}</span> | |
</div> | |
</div> | |
))} | |
</div> | |
</div> | |
</aside> | |
</div> | |
</div> | |
); | |
}; | |
export default LaunchPlatform; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment