feat: New landing page design + Gap analysis document

Landing Page:
- New hero section with 'The market never sleeps' headline
- Live market ticker showing hot auctions
- Three pillars: Discover, Track, Acquire structure
- Better value propositions and CTAs
- Improved TLD trending section
- Cleaner pricing comparison
- More 'Bloomberg meets Apple' aesthetic

Documentation:
- GAP_ANALYSIS.md: Comprehensive comparison of concept vs implementation
- Prioritized roadmap for missing features
- concept.md: Original product concept

Infrastructure:
- Improved start.sh with better process management
- Port cleanup and verification
- Better error handling and logging
This commit is contained in:
2025-12-10 07:31:57 +01:00
parent 3d6fc1f795
commit 72f64cb59f
4 changed files with 750 additions and 198 deletions

226
GAP_ANALYSIS.md Normal file
View File

@ -0,0 +1,226 @@
# Pounce Gap Analysis: Konzept vs. Implementierung
**Erstellt:** 10. Dezember 2024
**Status:** Aktive Entwicklung
---
## Executive Summary
Die aktuelle Implementierung deckt ca. **65-70%** des Konzepts ab. Die Kernfunktionen sind vorhanden, aber einige wichtige Features für die Monetarisierung und Differenzierung fehlen noch.
---
## 1. DISCOVER (Der Trichter für die Masse)
### ✅ Implementiert
| Feature | Status | Anmerkung |
|---------|--------|-----------|
| Schnelles Suchfeld | ✅ | DomainChecker auf Landing Page |
| Domain-Verfügbarkeits-Check | ✅ | WHOIS-basiert, funktioniert |
| Affiliate-Links zu Registraren | ⚠️ | Teilweise (nur in Auktionen) |
### ❌ Fehlt
| Feature | Priorität | Aufwand |
|---------|-----------|---------|
| **Live-Status bei besetzten Domains** | HOCH | Mittel |
| → "Webseite ist offline" | | |
| → "Steht zum Verkauf auf Sedo" | | |
| → "Läuft bald aus" (Expiry-Datum anzeigen) | | |
| **Smarte Alternativen** | MITTEL | Mittel |
| → KI-Vorschläge basierend auf TLD-Daten | | |
| → ".io ist teuer, nimm .xyz für $2" | | |
| **Registrar-Preisvergleich im Suchergebnis** | MITTEL | Klein |
---
## 2. TRACK (Das Herzstück für Bindung)
### ✅ Implementiert
| Feature | Status | Anmerkung |
|---------|--------|-----------|
| Watchlist für Domains | ✅ | Voll funktional |
| E-Mail Alerts | ✅ | Bei Status-Änderung |
| Domain-Limit pro Tier | ✅ | Scout: 5, Trader: 100, Tycoon: 500 |
### ⚠️ Teilweise Implementiert
| Feature | Status | Was fehlt |
|---------|--------|-----------|
| **Status-Karten (Ampel-System)** | ⚠️ | Konzept: 🟢🟡🔴 Karten, Aktuell: Tabelle |
| → 🟢 Chance (Domain dropped/Auktion) | ❌ | |
| → 🟡 Warten (DNS Update, Site down) | ❌ | |
| → 🔴 Stabil (Domain fest in Hand) | ❌ | |
### ❌ Fehlt (Pro Features)
| Feature | Priorität | Aufwand |
|---------|-----------|---------|
| **Deep Intel: Wer ist der Besitzer?** | MITTEL | Mittel |
| → Automatisierte Impressums-Suche | | |
| → Enhanced WHOIS-Daten | | |
| **Pre-Drop Alerts** | HOCH | Hoch |
| → DNS-Änderungen erkennen | | |
| → Warnung BEVOR Domain droppt | | |
| **Website-Monitoring** | MITTEL | Mittel |
| → Ist Seite offline? | | |
| → HTTP-Status-Checks | | |
---
## 3. ACQUIRE (Der Marktplatz für Action)
### ✅ Implementiert
| Feature | Status | Anmerkung |
|---------|--------|-----------|
| Auktions-Aggregation | ✅ | GoDaddy, Sedo, NameJet, DropCatch |
| Filter nach TLD, Preis | ✅ | Voll funktional |
| "Ending Soon" Auktionen | ✅ | Funktioniert |
| "Hot" Auktionen | ✅ | Nach Geboten sortiert |
### ⚠️ Teilweise Implementiert
| Feature | Status | Was fehlt |
|---------|--------|-----------|
| **No-Bullshit-Filter** | ⚠️ | Basis-Filter vorhanden |
| → Automatisches Spam-Filtern | ❌ | Keine KI/Heuristik |
| → "Keine Zahlen, max 2 Hyphens" | ❌ | |
### ❌ Fehlt (Pro Features)
| Feature | Priorität | Aufwand |
|---------|-----------|---------|
| **Deal-Score / Valuation** | HOCH | Mittel |
| → Estibot o.ä. API Integration | | |
| → "Undervalued 🔥" Label | | |
| **Arbitrage-Radar** | MITTEL | Mittel |
| → "Kaufe hier für $60, verkaufe dort für $100" | | |
| **Smart Filter Presets** | NIEDRIG | Klein |
| → "High Value / Low Price" | | |
| → "Short Domains (4 Letters)" | | |
| → "No Trash" | | |
---
## 4. TLD INTELLIGENCE
### ✅ Implementiert
| Feature | Status | Anmerkung |
|---------|--------|-----------|
| 886+ TLDs getrackt | ✅ | Voll funktional |
| Preisentwicklung (Charts) | ✅ | 90-Tage Historie |
| Trending TLDs | ✅ | Auf Landing Page |
| Registrar-Vergleich | ✅ | Pro TLD verfügbar |
### ❌ Fehlt
| Feature | Priorität | Aufwand |
|---------|-----------|---------|
| **Arbitrage Finder Tabelle** | MITTEL | Klein |
| → "Reg Fee vs. Avg Resale Price" | | |
| → Highlight höchste Margen | | |
| **Registrierungs-Trends** | NIEDRIG | Mittel |
| → "Wächst die TLD?" (Volumen) | | |
---
## 5. LANDING PAGE / MARKETING
### ✅ Implementiert
| Feature | Status | Anmerkung |
|---------|--------|-----------|
| Hero mit Suchfeld | ✅ | DomainChecker |
| Trending TLDs | ✅ | 4 Karten |
| Trust Indicators | ✅ | 886+ TLDs, 24/7, etc. |
| Pricing CTA | ✅ | Scout vs Trader |
### ❌ Fehlt (laut Konzept)
| Feature | Priorität | Aufwand |
|---------|-----------|---------|
| **Live Market Ticker** | HOCH | Mittel |
| → Durchlaufende Leiste mit heißen Domains | | |
| **Bessere Headlines** | HOCH | Klein |
| → "Der Markt schläft nie. Du schon." | | |
| → "Don't guess. Know." | | |
| **Value Props klarer** | MITTEL | Klein |
| → Discover, Track, Acquire Struktur | | |
| **Market Preview Teaser** | MITTEL | Klein |
| → "12 unterbewertete .ai Domains" | | |
---
## 6. COMMAND CENTER (Dashboard)
### ✅ Implementiert
| Feature | Status | Anmerkung |
|---------|--------|-----------|
| Dashboard Übersicht | ✅ | Basis-Dashboard |
| Watchlist | ✅ | Voll funktional |
| Portfolio Management | ✅ | Kauf/Verkauf tracking |
| Settings | ✅ | Profil, Billing |
### ⚠️ Teilweise Implementiert
| Feature | Status | Was fehlt |
|---------|--------|-----------|
| **Activity Feed** | ⚠️ | Keine echten Notifications |
| → "3 Domains haben Status geändert" | ❌ | |
| **Market Pulse** | ⚠️ | Nicht im Dashboard |
| → "5 Auktionen enden heute" | ❌ | |
| **Sidebar Navigation** | ⚠️ | Aktuell: Header-Nav |
### ❌ Fehlt
| Feature | Priorität | Aufwand |
|---------|-----------|---------|
| **Pro Dashboard mit Sidebar** | MITTEL | Mittel |
| → Collapsible Sidebar | | |
| → Professionelleres "Tool"-Feeling | | |
| **Saved Filters** | NIEDRIG | Klein |
| → "My AI Search" speichern | | |
---
## 7. TONE OF VOICE & BRANDING
### ⚠️ Teilweise Implementiert
| Aspekt | Status | Anmerkung |
|--------|--------|-----------|
| Dark Mode Design | ✅ | Durchgehend |
| Neon-Akzente (Signalgrün) | ✅ | Accent color |
| Minimalistisch | ✅ | Gutes Design |
### ❌ Verbesserungsbedarf
| Aspekt | Problem | Lösung |
|--------|---------|--------|
| **Headlines** | Zu generisch | Konzept-Headlines verwenden |
| **Sprache** | Zu technisch | Mehr "treibend, präzise" |
| **Versprechen** | Nicht klar | "Don't guess. Know." prominenter |
---
## Priorisierte Roadmap
### Phase 1: Quick Wins (1-2 Wochen)
1.**Landing Page Headlines überarbeiten**
2.**Live Market Ticker hinzufügen**
3.**Deal-Score Placeholder** (auch wenn nur Dummy)
4.**Status-Ampel im Dashboard**
### Phase 2: Value Add (2-4 Wochen)
1. 🚀 **Domain Valuation Integration** (Estibot/GoDaddy API)
2. 🚀 **Enhanced Domain Info** bei Suche (Expiry, Status)
3. 🚀 **Smarte Alternativen** bei Suche
4. 🚀 **No-Bullshit Auction Filter**
### Phase 3: Pro Features (4-8 Wochen)
1. 💎 **Pre-Drop Alerts** (DNS-Monitoring)
2. 💎 **Website-Status Monitoring**
3. 💎 **Arbitrage Finder**
4. 💎 **Sidebar Command Center**
---
## Fazit
Die technische Basis ist **solid**. Was fehlt, sind primär:
1. **Differenzierende Features** (Deal-Score, Arbitrage, Pre-Drop)
2. **Besseres Marketing** (Headlines, Tone of Voice)
3. **UX-Polish** (Ampel-System, Activity Feed, Market Ticker)
Mit den Quick Wins (Phase 1) kann pounce bereits deutlich professioneller wirken und die Conversion verbessern.

0
concept.md Normal file
View File

View File

@ -1,6 +1,6 @@
'use client'
import { useEffect, useState } from 'react'
import { useEffect, useState, useRef } from 'react'
import Image from 'next/image'
import { Header } from '@/components/Header'
import { Footer } from '@/components/Footer'
@ -21,6 +21,15 @@ import {
BarChart3,
Globe,
Check,
Search,
Target,
Gavel,
Sparkles,
Activity,
LineChart,
Lock,
Filter,
Crosshair,
} from 'lucide-react'
import Link from 'next/link'
import clsx from 'clsx'
@ -32,6 +41,13 @@ interface TrendingTld {
price_change: number
}
interface HotAuction {
domain: string
current_bid: number
time_remaining: string
platform: string
}
// Shimmer for loading states
function Shimmer({ className }: { className?: string }) {
return (
@ -70,24 +86,66 @@ function AnimatedNumber({ value, suffix = '' }: { value: number, suffix?: string
return <>{count.toLocaleString()}{suffix}</>
}
// Live Market Ticker
function MarketTicker({ auctions }: { auctions: HotAuction[] }) {
const tickerRef = useRef<HTMLDivElement>(null)
// Duplicate items for seamless loop
const items = [...auctions, ...auctions]
if (auctions.length === 0) return null
return (
<div className="relative overflow-hidden bg-background-secondary/30 border-y border-border/50 py-3">
<div
ref={tickerRef}
className="flex animate-[ticker_30s_linear_infinite] hover:[animation-play-state:paused]"
style={{ width: 'max-content' }}
>
{items.map((auction, i) => (
<div
key={`${auction.domain}-${i}`}
className="flex items-center gap-6 px-8 border-r border-border/30"
>
<div className="flex items-center gap-2">
<span className="w-2 h-2 rounded-full bg-accent animate-pulse" />
<span className="font-mono text-sm text-foreground">{auction.domain}</span>
</div>
<span className="text-sm text-accent font-semibold">${auction.current_bid}</span>
<span className="text-xs text-foreground-subtle">{auction.time_remaining}</span>
<span className="text-xs text-foreground-muted uppercase">{auction.platform}</span>
</div>
))}
</div>
</div>
)
}
export default function HomePage() {
const { checkAuth, isLoading, isAuthenticated } = useStore()
const [trendingTlds, setTrendingTlds] = useState<TrendingTld[]>([])
const [hotAuctions, setHotAuctions] = useState<HotAuction[]>([])
const [loadingTlds, setLoadingTlds] = useState(true)
const [loadingAuctions, setLoadingAuctions] = useState(true)
useEffect(() => {
checkAuth()
fetchTldData()
fetchData()
}, [checkAuth])
const fetchTldData = async () => {
const fetchData = async () => {
try {
const trending = await api.getTrendingTlds()
const [trending, auctions] = await Promise.all([
api.getTrendingTlds(),
api.getHotAuctions(8).catch(() => [])
])
setTrendingTlds(trending.trending.slice(0, 4))
setHotAuctions(auctions.slice(0, 8))
} catch (error) {
console.error('Failed to fetch TLD data:', error)
console.error('Failed to fetch data:', error)
} finally {
setLoadingTlds(false)
setLoadingAuctions(false)
}
}
@ -109,11 +167,8 @@ export default function HomePage() {
<div className="min-h-screen bg-background relative overflow-hidden">
{/* Background Effects */}
<div className="fixed inset-0 pointer-events-none">
{/* Primary glow */}
<div className="absolute top-[-20%] left-1/2 -translate-x-1/2 w-[1200px] h-[800px] bg-accent/[0.03] rounded-full blur-[120px]" />
{/* Secondary glow */}
<div className="absolute bottom-[-10%] right-[-10%] w-[600px] h-[600px] bg-accent/[0.02] rounded-full blur-[100px]" />
{/* Grid pattern */}
<div
className="absolute inset-0 opacity-[0.015]"
style={{
@ -125,60 +180,183 @@ export default function HomePage() {
<Header />
{/* Hero Section */}
<section className="relative pt-32 sm:pt-40 md:pt-48 lg:pt-56 pb-20 sm:pb-28 px-4 sm:px-6">
{/* Hero Section - "Bloomberg meets Apple" */}
<section className="relative pt-32 sm:pt-40 md:pt-48 pb-16 sm:pb-20 px-4 sm:px-6">
<div className="max-w-7xl mx-auto">
<div className="text-center max-w-5xl mx-auto">
{/* Puma Logo */}
<div className="flex justify-center mb-8 sm:mb-10 animate-fade-in">
{/* Brand Mark */}
<div className="flex justify-center mb-6 sm:mb-8 animate-fade-in">
<div className="relative">
<Image
src="/pounce-puma.png"
alt="pounce"
width={400}
height={280}
className="w-40 h-auto sm:w-52 md:w-64 object-contain drop-shadow-[0_0_60px_rgba(16,185,129,0.3)]"
priority
/>
{/* Glow ring */}
<div className="absolute inset-0 -z-10 bg-accent/20 blur-3xl rounded-full scale-150" />
<div className="inline-flex items-center gap-2 px-4 py-2 bg-accent/10 border border-accent/20 rounded-full">
<Activity className="w-4 h-4 text-accent" />
<span className="text-sm font-medium text-accent">Domain Intelligence Platform</span>
</div>
</div>
</div>
{/* Main Headline - MASSIVE */}
{/* Main Headline - Konzept: "Der Markt schläft nie. Du schon." */}
<h1 className="animate-slide-up">
<span className="block font-display text-[3rem] sm:text-[4rem] md:text-[5.5rem] lg:text-[7rem] xl:text-[8rem] leading-[0.9] tracking-[-0.04em] text-foreground">
Others wait.
<span className="block font-display text-[2.5rem] sm:text-[3.5rem] md:text-[4.5rem] lg:text-[5.5rem] xl:text-[6.5rem] leading-[0.95] tracking-[-0.04em] text-foreground">
The market never sleeps.
</span>
<span className="block font-display text-[3rem] sm:text-[4rem] md:text-[5.5rem] lg:text-[7rem] xl:text-[8rem] leading-[0.9] tracking-[-0.04em] text-foreground/40 mt-2">
You pounce.
<span className="block font-display text-[2.5rem] sm:text-[3.5rem] md:text-[4.5rem] lg:text-[5.5rem] xl:text-[6.5rem] leading-[0.95] tracking-[-0.04em] text-foreground/30 mt-1">
You should.
</span>
</h1>
{/* Subheadline */}
<p className="mt-8 sm:mt-10 md:mt-12 text-lg sm:text-xl md:text-2xl text-foreground-muted max-w-2xl mx-auto animate-slide-up delay-100 leading-relaxed">
Domain intelligence for the decisive. Track any domain.
Know the moment it drops. Move before anyone else.
{/* Subheadline - Konzept Versprechen */}
<p className="mt-8 sm:mt-10 text-lg sm:text-xl md:text-2xl text-foreground-muted max-w-2xl mx-auto animate-slide-up delay-100 leading-relaxed">
We scan. We watch. We alert.{' '}
<span className="text-foreground font-medium">You pounce.</span>
</p>
{/* Tagline */}
<p className="mt-4 text-base sm:text-lg text-accent font-medium animate-slide-up delay-150">
Don&apos;t guess. Know.
</p>
{/* Domain Checker */}
<div className="mt-10 sm:mt-14 md:mt-16 animate-slide-up delay-200">
<div className="mt-10 sm:mt-12 animate-slide-up delay-200">
<DomainChecker />
</div>
{/* Trust Indicators */}
<div className="mt-12 sm:mt-16 flex flex-wrap items-center justify-center gap-8 sm:gap-12 text-foreground-subtle animate-fade-in delay-300">
<div className="mt-10 sm:mt-12 flex flex-wrap items-center justify-center gap-6 sm:gap-10 text-foreground-subtle animate-fade-in delay-300">
<div className="flex items-center gap-2">
<Globe className="w-4 h-4 text-accent" />
<span className="text-sm font-medium"><AnimatedNumber value={886} />+ TLDs tracked</span>
<span className="text-sm font-medium"><AnimatedNumber value={886} />+ TLDs</span>
</div>
<div className="flex items-center gap-2">
<BarChart3 className="w-4 h-4 text-accent" />
<span className="text-sm font-medium">Real-time pricing</span>
<Gavel className="w-4 h-4 text-accent" />
<span className="text-sm font-medium">Live Auctions</span>
</div>
<div className="flex items-center gap-2">
<Bell className="w-4 h-4 text-accent" />
<span className="text-sm font-medium">Instant alerts</span>
<span className="text-sm font-medium">Instant Alerts</span>
</div>
<div className="flex items-center gap-2">
<LineChart className="w-4 h-4 text-accent" />
<span className="text-sm font-medium">Price Intel</span>
</div>
</div>
</div>
</div>
</section>
{/* Live Market Ticker */}
{!loadingAuctions && hotAuctions.length > 0 && (
<MarketTicker auctions={hotAuctions} />
)}
{/* Three Pillars: DISCOVER, TRACK, ACQUIRE */}
<section className="relative py-24 sm:py-32 px-4 sm:px-6">
<div className="max-w-7xl mx-auto">
{/* Section Header */}
<div className="text-center max-w-3xl mx-auto mb-16 sm:mb-20">
<span className="text-sm font-semibold text-accent uppercase tracking-wider">Your Command Center</span>
<h2 className="mt-4 font-display text-3xl sm:text-4xl md:text-5xl tracking-[-0.03em] text-foreground">
Three moves to dominate.
</h2>
</div>
{/* Pillars */}
<div className="grid md:grid-cols-3 gap-6 lg:gap-8">
{/* DISCOVER */}
<div className="group relative p-8 sm:p-10 bg-gradient-to-b from-background-secondary/80 to-background-secondary/40
border border-border rounded-3xl hover:border-accent/30 transition-all duration-500">
<div className="absolute inset-0 rounded-3xl bg-accent/5 opacity-0 group-hover:opacity-100 transition-opacity" />
<div className="relative">
<div className="w-16 h-16 bg-accent/10 border border-accent/20 rounded-2xl flex items-center justify-center mb-6">
<Search className="w-7 h-7 text-accent" />
</div>
<h3 className="text-2xl font-display text-foreground mb-4">Discover</h3>
<p className="text-foreground-muted mb-6 leading-relaxed">
Instant domain intel. Not just "taken" but <span className="text-foreground">why</span>,
<span className="text-foreground"> when it expires</span>, and
<span className="text-foreground"> smarter alternatives</span>.
</p>
<ul className="space-y-3 text-sm">
<li className="flex items-center gap-3 text-foreground-subtle">
<Check className="w-4 h-4 text-accent flex-shrink-0" />
<span>Real-time availability across 886+ TLDs</span>
</li>
<li className="flex items-center gap-3 text-foreground-subtle">
<Check className="w-4 h-4 text-accent flex-shrink-0" />
<span>Expiry dates & WHOIS data</span>
</li>
<li className="flex items-center gap-3 text-foreground-subtle">
<Check className="w-4 h-4 text-accent flex-shrink-0" />
<span>AI-powered alternatives</span>
</li>
</ul>
</div>
</div>
{/* TRACK */}
<div className="group relative p-8 sm:p-10 bg-gradient-to-b from-background-secondary/80 to-background-secondary/40
border border-border rounded-3xl hover:border-accent/30 transition-all duration-500
md:-translate-y-4">
<div className="absolute inset-0 rounded-3xl bg-accent/5 opacity-0 group-hover:opacity-100 transition-opacity" />
{/* Popular badge */}
<div className="absolute -top-3 left-1/2 -translate-x-1/2">
<span className="px-4 py-1 bg-accent text-background text-xs font-semibold rounded-full">
Most Popular
</span>
</div>
<div className="relative">
<div className="w-16 h-16 bg-accent/10 border border-accent/20 rounded-2xl flex items-center justify-center mb-6">
<Crosshair className="w-7 h-7 text-accent" />
</div>
<h3 className="text-2xl font-display text-foreground mb-4">Track</h3>
<p className="text-foreground-muted mb-6 leading-relaxed">
Your private watchlist. We monitor 24/7 so you don&apos;t have to.
<span className="text-foreground"> Know the second it drops.</span>
</p>
<ul className="space-y-3 text-sm">
<li className="flex items-center gap-3 text-foreground-subtle">
<Check className="w-4 h-4 text-accent flex-shrink-0" />
<span>Daily status checks</span>
</li>
<li className="flex items-center gap-3 text-foreground-subtle">
<Check className="w-4 h-4 text-accent flex-shrink-0" />
<span>Email & SMS alerts</span>
</li>
<li className="flex items-center gap-3 text-foreground-subtle">
<Check className="w-4 h-4 text-accent flex-shrink-0" />
<span>Pre-drop warnings</span>
</li>
</ul>
</div>
</div>
{/* ACQUIRE */}
<div className="group relative p-8 sm:p-10 bg-gradient-to-b from-background-secondary/80 to-background-secondary/40
border border-border rounded-3xl hover:border-accent/30 transition-all duration-500">
<div className="absolute inset-0 rounded-3xl bg-accent/5 opacity-0 group-hover:opacity-100 transition-opacity" />
<div className="relative">
<div className="w-16 h-16 bg-accent/10 border border-accent/20 rounded-2xl flex items-center justify-center mb-6">
<Gavel className="w-7 h-7 text-accent" />
</div>
<h3 className="text-2xl font-display text-foreground mb-4">Acquire</h3>
<p className="text-foreground-muted mb-6 leading-relaxed">
All auctions. One place. <span className="text-foreground">Filtered</span>.
<span className="text-foreground"> Valued</span>.
<span className="text-foreground"> Ready to strike.</span>
</p>
<ul className="space-y-3 text-sm">
<li className="flex items-center gap-3 text-foreground-subtle">
<Check className="w-4 h-4 text-accent flex-shrink-0" />
<span>GoDaddy, Sedo, NameJet, DropCatch</span>
</li>
<li className="flex items-center gap-3 text-foreground-subtle">
<Check className="w-4 h-4 text-accent flex-shrink-0" />
<span>No-spam smart filters</span>
</li>
<li className="flex items-center gap-3 text-foreground-subtle">
<Check className="w-4 h-4 text-accent flex-shrink-0" />
<span>Deal score & valuation</span>
</li>
</ul>
</div>
</div>
</div>
@ -186,18 +364,21 @@ export default function HomePage() {
</section>
{/* Trending TLDs Section */}
<section className="relative py-20 sm:py-28 px-4 sm:px-6">
<section className="relative py-20 sm:py-28 px-4 sm:px-6 bg-background-secondary/30">
<div className="max-w-7xl mx-auto">
{/* Section Header */}
<div className="flex flex-col sm:flex-row sm:items-end sm:justify-between gap-6 mb-10 sm:mb-14">
<div>
<div className="inline-flex items-center gap-2 px-4 py-2 bg-accent/10 border border-accent/20 rounded-full mb-5">
<TrendingUp className="w-4 h-4 text-accent" />
<span className="text-sm font-medium text-accent">Market Intel</span>
<span className="text-sm font-medium text-accent">TLD Intelligence</span>
</div>
<h2 className="font-display text-3xl sm:text-4xl md:text-5xl tracking-[-0.03em] text-foreground">
Trending Now
Market movers.
</h2>
<p className="mt-3 text-foreground-muted max-w-lg">
Real-time pricing data across 886+ extensions. Know where the value is.
</p>
</div>
<Link
href="/tld-pricing"
@ -212,7 +393,7 @@ export default function HomePage() {
{loadingTlds ? (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-5">
{[...Array(4)].map((_, i) => (
<div key={i} className="p-6 bg-background-secondary/50 border border-border rounded-2xl">
<div key={i} className="p-6 bg-background border border-border rounded-2xl">
<Shimmer className="h-8 w-20 mb-4" />
<Shimmer className="h-4 w-full mb-2" />
<Shimmer className="h-4 w-24" />
@ -225,11 +406,10 @@ export default function HomePage() {
<Link
key={item.tld}
href={isAuthenticated ? `/tld-pricing/${item.tld}` : `/login?redirect=/tld-pricing/${item.tld}`}
className="group relative p-6 bg-background-secondary/50 border border-border rounded-2xl
hover:border-accent/30 hover:bg-background-secondary transition-all duration-300"
className="group relative p-6 bg-background border border-border rounded-2xl
hover:border-accent/30 transition-all duration-300"
style={{ animationDelay: `${index * 100}ms` }}
>
{/* Hover glow */}
<div className="absolute inset-0 rounded-2xl bg-accent/5 opacity-0 group-hover:opacity-100 transition-opacity" />
<div className="relative">
@ -254,7 +434,10 @@ export default function HomePage() {
{isAuthenticated ? (
<span className="text-lg font-semibold text-foreground">${(item.current_price ?? 0).toFixed(2)}<span className="text-sm font-normal text-foreground-muted">/yr</span></span>
) : (
<Shimmer className="h-6 w-20" />
<span className="text-sm text-foreground-subtle flex items-center gap-1">
<Lock className="w-3 h-3" />
Sign in to view
</span>
)}
<ChevronRight className="w-5 h-5 text-foreground-subtle group-hover:text-accent group-hover:translate-x-1 transition-all" />
</div>
@ -266,89 +449,39 @@ export default function HomePage() {
</div>
</section>
{/* Features Section */}
<section className="relative py-20 sm:py-28 px-4 sm:px-6">
<div className="max-w-7xl mx-auto">
{/* Section Header */}
<div className="text-center max-w-3xl mx-auto mb-16 sm:mb-20">
<span className="text-sm font-semibold text-accent uppercase tracking-wider">How It Works</span>
<h2 className="mt-4 font-display text-3xl sm:text-4xl md:text-5xl lg:text-6xl tracking-[-0.03em] text-foreground">
Built for hunters.
</h2>
<p className="mt-5 text-lg text-foreground-muted">
The tools that give you the edge. Simple. Powerful. Decisive.
</p>
</div>
{/* Feature Cards */}
<div className="grid sm:grid-cols-2 lg:grid-cols-4 gap-6">
{[
{
icon: Eye,
title: 'Always Watching',
description: 'Daily scans across 886+ TLDs. You sleep, we hunt.',
},
{
icon: Bell,
title: 'Instant Alerts',
description: 'Domain drops? You know first. Email alerts the moment it happens.',
},
{
icon: Clock,
title: 'Expiry Intel',
description: 'See when domains expire. Plan your acquisition strategy.',
},
{
icon: Shield,
title: 'Your Strategy, Private',
description: 'Your watchlist is yours alone. No one sees what you\'re tracking.',
},
].map((feature, i) => (
<div
key={feature.title}
className="group relative p-8 rounded-2xl border border-transparent hover:border-border
bg-transparent hover:bg-background-secondary/50 transition-all duration-500"
>
<div className="w-14 h-14 bg-foreground/5 border border-border rounded-2xl flex items-center justify-center mb-6
group-hover:border-accent/30 group-hover:bg-accent/5 transition-all duration-500">
<feature.icon className="w-6 h-6 text-foreground-muted group-hover:text-accent transition-colors duration-500" strokeWidth={1.5} />
</div>
<h3 className="text-lg font-semibold text-foreground mb-3">{feature.title}</h3>
<p className="text-sm text-foreground-subtle leading-relaxed">{feature.description}</p>
</div>
))}
</div>
</div>
</section>
{/* Social Proof / Stats Section */}
<section className="relative py-20 sm:py-28 px-4 sm:px-6">
<section className="relative py-24 sm:py-32 px-4 sm:px-6">
<div className="max-w-5xl mx-auto">
<div className="relative p-10 sm:p-14 md:p-20 bg-gradient-to-br from-background-secondary/80 to-background-secondary/40
border border-border rounded-3xl overflow-hidden">
{/* Background pattern */}
<div className="absolute inset-0 opacity-30">
<div className="absolute top-0 right-0 w-[400px] h-[400px] bg-accent/10 rounded-full blur-[100px]" />
</div>
<div className="relative grid sm:grid-cols-3 gap-10 sm:gap-6 text-center">
<div>
<p className="font-display text-5xl sm:text-6xl md:text-7xl text-foreground mb-2">
<AnimatedNumber value={886} />+
</p>
<p className="text-sm text-foreground-muted">TLDs Tracked</p>
</div>
<div>
<p className="font-display text-5xl sm:text-6xl md:text-7xl text-foreground mb-2">
24<span className="text-accent">/</span>7
</p>
<p className="text-sm text-foreground-muted">Monitoring</p>
</div>
<div>
<p className="font-display text-5xl sm:text-6xl md:text-7xl text-foreground mb-2">
<AnimatedNumber value={10} />s
</p>
<p className="text-sm text-foreground-muted">Alert Speed</p>
<div className="relative">
<h2 className="font-display text-3xl sm:text-4xl text-center text-foreground mb-12">
The edge you need.
</h2>
<div className="grid sm:grid-cols-3 gap-10 sm:gap-6 text-center">
<div>
<p className="font-display text-5xl sm:text-6xl md:text-7xl text-foreground mb-2">
<AnimatedNumber value={886} />+
</p>
<p className="text-sm text-foreground-muted">TLDs Tracked Daily</p>
</div>
<div>
<p className="font-display text-5xl sm:text-6xl md:text-7xl text-foreground mb-2">
24<span className="text-accent">/</span>7
</p>
<p className="text-sm text-foreground-muted">Always Watching</p>
</div>
<div>
<p className="font-display text-5xl sm:text-6xl md:text-7xl text-foreground mb-2">
<AnimatedNumber value={10} />s
</p>
<p className="text-sm text-foreground-muted">Alert Speed</p>
</div>
</div>
</div>
</div>
@ -359,36 +492,72 @@ export default function HomePage() {
<section className="relative py-20 sm:py-28 px-4 sm:px-6">
<div className="max-w-4xl mx-auto text-center">
<span className="text-sm font-semibold text-accent uppercase tracking-wider">Pricing</span>
<h2 className="mt-4 font-display text-3xl sm:text-4xl md:text-5xl lg:text-6xl tracking-[-0.03em] text-foreground">
Pick your weapon.
<h2 className="mt-4 font-display text-3xl sm:text-4xl md:text-5xl tracking-[-0.03em] text-foreground">
Simple. Transparent. Powerful.
</h2>
<p className="mt-5 text-lg text-foreground-muted max-w-xl mx-auto">
Start free with 5 domains. Scale to 500+ when you need more firepower.
Start free. Scale when you&apos;re ready.
</p>
{/* Quick Plans */}
<div className="mt-12 flex flex-col sm:flex-row items-center justify-center gap-4">
<div className="flex items-center gap-4 px-6 py-4 bg-background-secondary/50 border border-border rounded-2xl">
<div className="w-12 h-12 bg-foreground/5 rounded-xl flex items-center justify-center">
<Zap className="w-5 h-5 text-foreground-muted" />
</div>
<div className="text-left">
<p className="font-semibold text-foreground">Scout</p>
<p className="text-sm text-foreground-muted">Free forever</p>
<div className="mt-12 grid sm:grid-cols-2 gap-4 max-w-2xl mx-auto">
{/* Free Plan */}
<div className="p-6 bg-background-secondary/50 border border-border rounded-2xl text-left">
<div className="flex items-center gap-3 mb-4">
<div className="w-10 h-10 bg-foreground/5 rounded-xl flex items-center justify-center">
<Zap className="w-5 h-5 text-foreground-muted" />
</div>
<div>
<p className="font-semibold text-foreground">Scout</p>
<p className="text-sm text-foreground-muted">Free forever</p>
</div>
</div>
<ul className="space-y-2 text-sm text-foreground-subtle">
<li className="flex items-center gap-2">
<Check className="w-4 h-4 text-accent" />
<span>5 domains watched</span>
</li>
<li className="flex items-center gap-2">
<Check className="w-4 h-4 text-accent" />
<span>Daily status checks</span>
</li>
<li className="flex items-center gap-2">
<Check className="w-4 h-4 text-accent" />
<span>TLD price explorer</span>
</li>
</ul>
</div>
<ArrowRight className="w-5 h-5 text-foreground-subtle hidden sm:block" />
<ChevronRight className="w-5 h-5 text-foreground-subtle rotate-90 sm:hidden" />
<div className="flex items-center gap-4 px-6 py-4 bg-accent/5 border border-accent/20 rounded-2xl">
<div className="w-12 h-12 bg-accent/10 rounded-xl flex items-center justify-center">
<TrendingUp className="w-5 h-5 text-accent" />
{/* Pro Plan */}
<div className="p-6 bg-accent/5 border border-accent/20 rounded-2xl text-left relative">
<div className="absolute -top-3 right-4">
<span className="px-3 py-1 bg-accent text-background text-xs font-semibold rounded-full">
Popular
</span>
</div>
<div className="text-left">
<p className="font-semibold text-foreground">Trader</p>
<p className="text-sm text-accent">$19/month</p>
<div className="flex items-center gap-3 mb-4">
<div className="w-10 h-10 bg-accent/10 rounded-xl flex items-center justify-center">
<Target className="w-5 h-5 text-accent" />
</div>
<div>
<p className="font-semibold text-foreground">Trader</p>
<p className="text-sm text-accent">$19/month</p>
</div>
</div>
<ul className="space-y-2 text-sm text-foreground-subtle">
<li className="flex items-center gap-2">
<Check className="w-4 h-4 text-accent" />
<span>100 domains watched</span>
</li>
<li className="flex items-center gap-2">
<Check className="w-4 h-4 text-accent" />
<span>Priority alerts</span>
</li>
<li className="flex items-center gap-2">
<Check className="w-4 h-4 text-accent" />
<span>Full auction access</span>
</li>
</ul>
</div>
</div>
@ -398,7 +567,7 @@ export default function HomePage() {
className="inline-flex items-center gap-2 px-8 py-4 bg-foreground text-background rounded-xl
font-semibold hover:bg-foreground/90 transition-all duration-300"
>
Compare Plans
Compare All Plans
<ArrowRight className="w-4 h-4" />
</Link>
<Link
@ -415,11 +584,12 @@ export default function HomePage() {
{/* Final CTA */}
<section className="relative py-24 sm:py-32 px-4 sm:px-6">
<div className="max-w-4xl mx-auto text-center">
<p className="text-accent font-medium mb-4">Join the hunters.</p>
<h2 className="font-display text-4xl sm:text-5xl md:text-6xl lg:text-7xl tracking-[-0.03em] text-foreground mb-6">
Ready to hunt?
Ready to pounce?
</h2>
<p className="text-xl text-foreground-muted mb-10 max-w-lg mx-auto">
Track your first domain in under a minute. No credit card required.
Track your first domain in under a minute. Free forever, no credit card.
</p>
<Link
href={isAuthenticated ? "/dashboard" : "/register"}
@ -427,7 +597,7 @@ export default function HomePage() {
text-lg font-semibold hover:bg-accent-hover transition-all duration-300
shadow-[0_0_40px_rgba(16,185,129,0.2)] hover:shadow-[0_0_60px_rgba(16,185,129,0.3)]"
>
{isAuthenticated ? "Go to Dashboard" : "Get Started Free"}
{isAuthenticated ? "Go to Dashboard" : "Start Hunting — It's Free"}
<ArrowRight className="w-5 h-5 group-hover:translate-x-1 transition-transform" />
</Link>
@ -441,6 +611,14 @@ export default function HomePage() {
</section>
<Footer />
{/* Ticker Animation Keyframes */}
<style jsx global>{`
@keyframes ticker {
0% { transform: translateX(0); }
100% { transform: translateX(-50%); }
}
`}</style>
</div>
)
}

256
start.sh
View File

@ -1,65 +1,213 @@
#!/bin/bash
#
# POUNCE Quick Start Script
# Starts both backend and frontend for development
#
set -e
echo "🐆 Starting POUNCE..."
echo ""
# Pounce Start Script
# Startet Backend und Frontend sauber
# Check if backend venv exists
if [ ! -d "backend/venv" ]; then
echo "❌ Backend not set up. Run ./deploy.sh first!"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BACKEND_DIR="$SCRIPT_DIR/backend"
FRONTEND_DIR="$SCRIPT_DIR/frontend"
echo "=========================================="
echo "🚀 Pounce Start Script"
echo "=========================================="
# Farben für Output
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Funktion zum Beenden von Prozessen
stop_services() {
echo ""
echo -e "${YELLOW}🛑 Beende laufende Prozesse...${NC}"
# Backend (uvicorn) - mehrere Versuche
pkill -9 -f "uvicorn app.main:app" 2>/dev/null || true
pkill -9 -f "uvicorn" 2>/dev/null || true
# Frontend (next) - mehrere Versuche
pkill -9 -f "next start" 2>/dev/null || true
pkill -9 -f "node.*next" 2>/dev/null || true
pkill -9 -f "npm start" 2>/dev/null || true
# Port 3000 freigeben (alle Prozesse auf Port 3000)
lsof -ti:3000 2>/dev/null | xargs kill -9 2>/dev/null || true
# Port 8000 freigeben
lsof -ti:8000 2>/dev/null | xargs kill -9 2>/dev/null || true
sleep 3
# Prüfen ob Ports frei sind
if lsof -i:8000 >/dev/null 2>&1; then
echo -e "${RED}✗ Port 8000 ist noch belegt!${NC}"
lsof -i:8000
exit 1
fi
if lsof -i:3000 >/dev/null 2>&1; then
echo -e "${RED}✗ Port 3000 ist noch belegt!${NC}"
lsof -i:3000
exit 1
fi
echo -e "${GREEN}✓ Alle Prozesse beendet, Ports frei${NC}"
}
# Funktion zum Starten des Backends
start_backend() {
echo ""
echo -e "${YELLOW}🔧 Starte Backend...${NC}"
cd "$BACKEND_DIR"
# Aktiviere Virtual Environment
if [ ! -d "venv" ]; then
echo -e "${RED}✗ venv nicht gefunden!${NC}"
exit 1
fi
source venv/bin/activate
# Lösche altes Log
> backend.log
# Starte uvicorn im Hintergrund
nohup uvicorn app.main:app --host 0.0.0.0 --port 8000 > backend.log 2>&1 &
BACKEND_PID=$!
echo "Backend PID: $BACKEND_PID"
# Warte und prüfe mehrmals
for i in {1..10}; do
sleep 1
if curl -s http://127.0.0.1:8000/health > /dev/null 2>&1; then
echo -e "${GREEN}✓ Backend läuft auf Port 8000${NC}"
return 0
fi
echo -n "."
done
echo ""
echo -e "${RED}✗ Backend konnte nicht gestartet werden${NC}"
echo "Letzte 30 Zeilen vom Log:"
tail -30 backend.log
exit 1
fi
}
# Kill any existing processes on our ports
echo "🔧 Cleaning up old processes..."
lsof -ti:8000 | xargs kill -9 2>/dev/null || true
lsof -ti:3000 | xargs kill -9 2>/dev/null || true
sleep 1
# Start Backend
echo "🚀 Starting Backend on port 8000..."
cd backend
source venv/bin/activate
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000 &
BACKEND_PID=$!
cd ..
# Wait for backend to start
sleep 3
# Check if backend is running
if curl -s http://localhost:8000/health > /dev/null 2>&1; then
echo "✅ Backend running!"
else
echo "❌ Backend failed to start. Check logs."
# Funktion zum Starten des Frontends
start_frontend() {
echo ""
echo -e "${YELLOW}🎨 Starte Frontend...${NC}"
cd "$FRONTEND_DIR"
# Prüfe ob .next existiert
if [ ! -d ".next" ]; then
echo -e "${RED}✗ .next nicht gefunden! Bitte erst 'npm run build' ausführen.${NC}"
exit 1
fi
# Lösche altes Log
> frontend.log
# Starte Frontend im Hintergrund
PORT=3000 nohup npm start > frontend.log 2>&1 &
FRONTEND_PID=$!
echo "Frontend PID: $FRONTEND_PID"
# Warte und prüfe mehrmals
for i in {1..15}; do
sleep 1
# Prüfe ob Prozess noch läuft
if ! kill -0 $FRONTEND_PID 2>/dev/null; then
echo ""
echo -e "${RED}✗ Frontend-Prozess wurde beendet${NC}"
echo "Letzte 30 Zeilen vom Log:"
tail -30 frontend.log
exit 1
fi
# Prüfe ob Port offen ist
if curl -s http://127.0.0.1:3000 > /dev/null 2>&1; then
echo -e "${GREEN}✓ Frontend läuft auf Port 3000${NC}"
return 0
fi
echo -n "."
done
echo ""
echo -e "${RED}✗ Frontend konnte nicht gestartet werden${NC}"
echo "Letzte 30 Zeilen vom Log:"
tail -30 frontend.log
exit 1
fi
}
# Start Frontend
echo "🚀 Starting Frontend on port 3000..."
cd frontend
npm run dev &
FRONTEND_PID=$!
cd ..
# Funktion für Status-Anzeige
show_status() {
echo ""
echo "=========================================="
echo -e "${GREEN}✓ Pounce erfolgreich gestartet!${NC}"
echo "=========================================="
echo ""
echo "URLs:"
echo " Backend: http://127.0.0.1:8000"
echo " Frontend: http://127.0.0.1:3000"
echo " Health: http://127.0.0.1:8000/health"
echo ""
echo "Logs:"
echo " Backend: tail -f $BACKEND_DIR/backend.log"
echo " Frontend: tail -f $FRONTEND_DIR/frontend.log"
echo ""
echo "Laufende Prozesse:"
ps aux | grep -E "(uvicorn|next start)" | grep -v grep | awk '{print " PID " $2 ": " $11 " " $12 " " $13}'
echo ""
echo "Ports:"
lsof -i:8000 -i:3000 2>/dev/null | grep LISTEN || echo " Keine Port-Info verfügbar"
echo ""
}
echo ""
echo "================================================"
echo " POUNCE is starting..."
echo "================================================"
echo ""
echo " Backend: http://localhost:8000"
echo " Frontend: http://localhost:3000"
echo " API Docs: http://localhost:8000/docs"
echo ""
echo " Press Ctrl+C to stop all services"
echo ""
# Funktion zum Testen der Services
test_services() {
echo ""
echo -e "${YELLOW}🧪 Teste Services...${NC}"
# Test Backend Health
HEALTH=$(curl -s http://127.0.0.1:8000/health | grep -o '"status":"healthy"' || echo "")
if [ -n "$HEALTH" ]; then
echo -e "${GREEN}✓ Backend Health Check OK${NC}"
else
echo -e "${RED}✗ Backend Health Check FAILED${NC}"
fi
# Test Frontend
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:3000)
if [ "$HTTP_CODE" = "200" ]; then
echo -e "${GREEN}✓ Frontend HTTP 200 OK${NC}"
else
echo -e "${RED}✗ Frontend HTTP $HTTP_CODE${NC}"
fi
# Test OAuth Providers
OAUTH=$(curl -s http://127.0.0.1:8000/api/v1/oauth/providers | grep -o '"google_enabled":true' || echo "")
if [ -n "$OAUTH" ]; then
echo -e "${GREEN}✓ OAuth Providers OK${NC}"
else
echo -e "${YELLOW}⚠ OAuth Check konnte nicht durchgeführt werden${NC}"
fi
}
# Wait for both processes
trap "kill $BACKEND_PID $FRONTEND_PID 2>/dev/null" EXIT
wait
# Main
stop_services
start_backend
start_frontend
test_services
show_status
echo -e "${GREEN}🎉 Alles läuft!${NC}"
echo ""
echo "Zum Stoppen: pkill -f 'uvicorn' && pkill -f 'next start'"