From c8fe134ba34ad2cd2d18661f2cea596a2ca871a6 Mon Sep 17 00:00:00 2001 From: "yves.gugger" Date: Tue, 9 Dec 2025 17:14:05 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Redesign=20blog=20pages=20with=20st?= =?UTF-8?q?ylish=20modern=20look?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Blog listing: Featured post hero section, animated card grid - Category filters with accent styling - Blog detail: Improved typography, social sharing, author box - Consistent background effects matching landing page - Newsletter CTA section on blog listing - fadeInUp animations for posts grid --- frontend/src/app/blog/[slug]/page.tsx | 269 +++++++++++++++++-------- frontend/src/app/blog/page.tsx | 280 ++++++++++++++++++-------- 2 files changed, 381 insertions(+), 168 deletions(-) diff --git a/frontend/src/app/blog/[slug]/page.tsx b/frontend/src/app/blog/[slug]/page.tsx index 1562d36..58660c4 100644 --- a/frontend/src/app/blog/[slug]/page.tsx +++ b/frontend/src/app/blog/[slug]/page.tsx @@ -1,7 +1,7 @@ 'use client' import { useEffect, useState } from 'react' -import { useParams, useRouter } from 'next/navigation' +import { useParams } from 'next/navigation' import Link from 'next/link' import Image from 'next/image' import { Header } from '@/components/Header' @@ -17,6 +17,11 @@ import { User, Share2, BookOpen, + Twitter, + Linkedin, + Copy, + Check, + Sparkles, } from 'lucide-react' interface BlogPost { @@ -43,12 +48,12 @@ interface BlogPost { export default function BlogPostPage() { const params = useParams() - const router = useRouter() const slug = params.slug as string const [post, setPost] = useState(null) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) + const [copied, setCopied] = useState(false) useEffect(() => { if (slug) { @@ -83,44 +88,55 @@ export default function BlogPostPage() { return `${minutes} min read` } - const handleShare = async () => { - if (navigator.share) { - try { - await navigator.share({ - title: post?.title, - url: window.location.href, - }) - } catch (err) { - // User cancelled or error - } - } else { - // Fallback: copy to clipboard - navigator.clipboard.writeText(window.location.href) - } + const handleCopyLink = async () => { + await navigator.clipboard.writeText(window.location.href) + setCopied(true) + setTimeout(() => setCopied(false), 2000) + } + + const shareOnTwitter = () => { + const url = encodeURIComponent(window.location.href) + const text = encodeURIComponent(post?.title || '') + window.open(`https://twitter.com/intent/tweet?url=${url}&text=${text}`, '_blank') + } + + const shareOnLinkedIn = () => { + const url = encodeURIComponent(window.location.href) + window.open(`https://www.linkedin.com/sharing/share-offsite/?url=${url}`, '_blank') } if (loading) { return (
- +
+ +

Loading article...

+
) } if (error || !post) { return ( -
+
+ {/* Background */} +
+
+
+
-
+
- -

Post Not Found

-

- The blog post you're looking for doesn't exist or has been removed. +

+ +
+

Article Not Found

+

+ The article you're looking for doesn't exist or has been removed from our collection.

Back to Blog @@ -137,66 +153,111 @@ export default function BlogPostPage() { {/* Background Effects */}
+
+
-
+
{/* Back Link */} - + Back to Blog - {/* Header */} -
- {post.category && ( - - {post.category} - - )} - -

- {post.title} -

- - {/* Meta */} -
- {post.author.name && ( - - - {post.author.name} + {/* Hero Header */} +
+
+ {post.category && ( + + + {post.category} )} - - - {post.published_at ? formatDate(post.published_at) : formatDate(post.created_at)} - - + {estimateReadTime(post.content)} - - - {post.view_count} views - - +
+ +

+ {post.title} +

+ + {post.excerpt && ( +

+ {post.excerpt} +

+ )} + + {/* Meta Row */} +
+
+ {post.author.name && ( +
+
+ +
+
+

{post.author.name}

+

Author

+
+
+ )} +
+ +
+ + + {post.published_at ? formatDate(post.published_at) : formatDate(post.created_at)} + + + + {post.view_count} views + +
+ + {/* Share */} +
+ + + +
{/* Cover Image */} {post.cover_image && ( -
+
{post.title} {/* Tags */} {post.tags.length > 0 && ( -
-
+
+
{post.tags.map((tag) => ( {tag} @@ -243,20 +305,53 @@ export default function BlogPostPage() {
)} + {/* Author Box */} + {post.author.name && ( +
+
+
+ +
+
+

Written by

+

{post.author.name}

+

+ Expert domain hunter sharing insights and strategies to help you find premium domains. +

+
+
+
+ )} + {/* CTA */} -
-

- Ready to start hunting domains? -

-

- Join thousands of domain hunters using pounce to find and secure premium domains. -

- - Get Started Free - +
+
+
+
+ + Ready to Hunt? +
+

+ Start finding premium domains today +

+

+ Join thousands of domain hunters using pounce to discover, monitor, and secure valuable domains. +

+
+ + Get Started Free + + + More Articles + +
+
diff --git a/frontend/src/app/blog/page.tsx b/frontend/src/app/blog/page.tsx index 827b7cc..53f9987 100644 --- a/frontend/src/app/blog/page.tsx +++ b/frontend/src/app/blog/page.tsx @@ -12,9 +12,10 @@ import { Clock, Eye, ArrowRight, - Tag, Loader2, FileText, + Sparkles, + TrendingUp, } from 'lucide-react' import clsx from 'clsx' @@ -72,24 +73,28 @@ export default function BlogPage() { const formatDate = (dateString: string) => { return new Date(dateString).toLocaleDateString('en-US', { year: 'numeric', - month: 'long', + month: 'short', day: 'numeric', }) } const estimateReadTime = (excerpt: string | null) => { - if (!excerpt) return '3 min read' + if (!excerpt) return '3 min' const words = excerpt.split(' ').length - const minutes = Math.ceil(words / 200) + 2 // Assume full article is longer - return `${minutes} min read` + const minutes = Math.ceil(words / 200) + 2 + return `${minutes} min` } + const featuredPost = posts[0] + const otherPosts = posts.slice(1) + return (
{/* Background Effects */}
+
- {/* Header */} -
-
- - Domain Intelligence Blog + {/* Hero Header */} +
+
+ + Domain Intelligence
-

- Insights & Strategies. + +

+ The Hunt
+ Begins Here.

-

- Domain hunting tips, market analysis, and expert strategies to help you secure premium domains. + +

+ Expert strategies, market insights, and proven tactics from professional domain hunters.

{/* Categories */} {categories.length > 0 && ( -
+
))}
)} - {/* Posts Grid */} + {/* Posts */} {loading ? ( -
- +
+
+ +

Loading insights...

+
) : posts.length === 0 ? ( -
- -

No posts yet

-

- Check back soon for domain hunting insights and strategies. +

+
+ +
+

Coming Soon

+

+ We're preparing expert content. Check back soon for domain hunting insights and strategies.

) : ( <> -
- {posts.map((post, index) => ( + {/* Featured Post */} + {featuredPost && !selectedCategory && ( + +
+
+ {/* Image */} +
+ {featuredPost.cover_image ? ( + {featuredPost.title} + ) : ( +
+ +
+ )} +
+ + {/* Featured Badge */} +
+ + Featured +
+
+ + {/* Content */} +
+ {featuredPost.category && ( + + {featuredPost.category} + + )} + +

+ {featuredPost.title} +

+ + {featuredPost.excerpt && ( +

+ {featuredPost.excerpt} +

+ )} + +
+ + + {featuredPost.published_at ? formatDate(featuredPost.published_at) : formatDate(featuredPost.created_at)} + + + + {estimateReadTime(featuredPost.excerpt)} + + + + {featuredPost.view_count} + +
+ + + Read Article + + +
+
+
+ + )} + + {/* Posts Grid */} +
+ {(selectedCategory ? posts : otherPosts).map((post, index) => ( - {/* Cover Image */} - {post.cover_image ? ( -
+ {/* Cover */} +
+ {post.cover_image ? ( {post.title} - {post.category && ( - - {post.category} - - )} -
- ) : ( -
- - {post.category && ( - - {post.category} - - )} -
- )} + ) : ( +
+ +
+ )} +
+ + {post.category && ( + + {post.category} + + )} +
{/* Content */} -
-

+
+

{post.title} -

+

+ {post.excerpt && ( -

+

{post.excerpt}

)} - {/* Meta */} -
- - - {post.published_at ? formatDate(post.published_at) : formatDate(post.created_at)} - - - - {estimateReadTime(post.excerpt)} - - - - {post.view_count} - +
+
+ + + {post.published_at ? formatDate(post.published_at) : formatDate(post.created_at)} + + + + {post.view_count} + +
+
- - {/* Hover Indicator */} -
- - Read more - -
))}
@@ -247,18 +328,55 @@ export default function BlogPage() { console.error('Failed to load more posts:', error) } }} - className="px-6 py-3 bg-background-secondary border border-border rounded-xl text-foreground font-medium hover:bg-foreground/5 transition-all" + className="group inline-flex items-center gap-3 px-8 py-4 bg-background-secondary/50 border border-border rounded-full text-foreground font-medium hover:border-accent/50 hover:bg-accent/5 transition-all duration-300" > - Load More Posts + Load More Articles +
)} )} + + {/* Newsletter CTA */} +
+
+
+

+ Get hunting tips in your inbox +

+

+ Join domain hunters who receive weekly insights, market trends, and exclusive strategies. +

+
+ + +
+
+
) }