feat(blog): add blog feature with layout, list component and i18n support
- Create BlogLayout for consistent blog page structure - Implement BlogList component with responsive design and line-clamp - Add blog navigation to header with proper routing - Include i18n support for both English and Chinese - Add sample blog pages with mock data
This commit is contained in:
127
src/pages/blog/index.astro
Normal file
127
src/pages/blog/index.astro
Normal file
@@ -0,0 +1,127 @@
|
||||
---
|
||||
import BlogLayout from '../../layouts/BlogLayout.astro';
|
||||
import BlogList from '../../components/BlogList.tsx';
|
||||
|
||||
// Sample blog data - inline for now
|
||||
const blogPosts = [
|
||||
{
|
||||
id: 1,
|
||||
title: "Mastering React Hooks: A Deep Dive",
|
||||
description: "Explore the power of React Hooks to manage state and side effects in functional components, with practical examples and best practices.",
|
||||
image: "https://images.unsplash.com/photo-1633356122544-f134324a6cee?w=400&h=250&fit=crop&crop=center",
|
||||
date: "May 10, 2025",
|
||||
readTime: "5 min read",
|
||||
tags: ["React", "JavaScript", "Frontend"],
|
||||
slug: "mastering-react-hooks"
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: "Scaling Node.js Apps with Docker",
|
||||
description: "Learn how to containerize Node.js applications using Docker for seamless deployment and scalability in production environments.",
|
||||
image: "https://images.unsplash.com/photo-1605745341112-85968b19335b?w=400&h=250&fit=crop&crop=center",
|
||||
date: "April 25, 2025",
|
||||
readTime: "7 min read",
|
||||
tags: ["Node.js", "Docker", "DevOps"],
|
||||
slug: "scaling-nodejs-docker"
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: "Building Modern UIs with Tailwind CSS",
|
||||
description: "Discover how to create beautiful, responsive user interfaces using Tailwind CSS utility classes and component patterns.",
|
||||
image: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=400&h=250&fit=crop&crop=center",
|
||||
date: "April 15, 2025",
|
||||
readTime: "6 min read",
|
||||
tags: ["CSS", "Tailwind", "UI/UX"],
|
||||
slug: "modern-ui-tailwind"
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
title: "TypeScript Best Practices for Large Projects",
|
||||
description: "Essential TypeScript patterns and practices for maintaining code quality and developer productivity in enterprise applications.",
|
||||
image: "https://images.unsplash.com/photo-1516321318423-f06f85e504b3?w=400&h=250&fit=crop&crop=center",
|
||||
date: "March 30, 2025",
|
||||
readTime: "8 min read",
|
||||
tags: ["TypeScript", "JavaScript", "Architecture"],
|
||||
slug: "typescript-best-practices"
|
||||
}
|
||||
];
|
||||
|
||||
// Sample categories and tags
|
||||
const categories = ["React", "Node.js", "TailwindCSS", "TypeScript", "DevOps"];
|
||||
const tags = ["#React", "#JavaScript", "#Frontend", "#Node.js", "#Docker", "#DevOps", "#TailwindCSS", "#CSS", "#TypeScript"];
|
||||
|
||||
---
|
||||
|
||||
<BlogLayout title="Blog - Joy Zhao" description="Dive into my thoughts on coding, tech trends, and developer life. Explore my latest posts below.">
|
||||
<main class="min-h-screen">
|
||||
<!-- Header Section -->
|
||||
<div class="container mx-auto px-4 pt-24 pb-12">
|
||||
<div class="text-center mb-16">
|
||||
<h1 class="text-5xl md:text-6xl font-bold bg-gradient-to-r from-foreground via-purple-600 to-purple-800 dark:from-foreground dark:via-purple-200 dark:to-purple-300 bg-clip-text text-transparent mb-6">
|
||||
Our <span class="text-purple-500">Latest</span> Blog
|
||||
</h1>
|
||||
<p class="text-xl text-muted-foreground max-w-3xl mx-auto">
|
||||
Dive into my thoughts on coding, tech trends, and developer life. Explore my latest posts below.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Content -->
|
||||
<div class="container mx-auto px-4 pb-20">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-4 gap-8">
|
||||
<!-- Sidebar -->
|
||||
<div class="lg:col-span-1 space-y-8">
|
||||
<!-- Categories -->
|
||||
<div class="bg-card/50 backdrop-blur-sm rounded-2xl p-6 border border-border">
|
||||
<h3 class="text-xl font-semibold text-card-foreground mb-4 flex items-center">
|
||||
<svg class="w-5 h-5 mr-2 text-purple-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14-7l2 2-2 2m2-2H9m10 0V9M5 19l2-2-2-2m2 2H3m2 0v2"></path>
|
||||
</svg>
|
||||
Categories
|
||||
</h3>
|
||||
<div class="space-y-2">
|
||||
{categories.map((category) => (
|
||||
<a href={`/blog/categories/${category.toLowerCase()}`}
|
||||
class="block text-muted-foreground hover:text-purple-500 transition-colors duration-200">
|
||||
{category}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tags -->
|
||||
<div class="bg-card/50 backdrop-blur-sm rounded-2xl p-6 border border-border">
|
||||
<h3 class="text-xl font-semibold text-card-foreground mb-4 flex items-center">
|
||||
<svg class="w-5 h-5 mr-2 text-purple-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z"></path>
|
||||
</svg>
|
||||
# Tags
|
||||
</h3>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
{tags.map((tag) => (
|
||||
<a href={`/blog/tags/${tag.slice(1).toLowerCase()}`}
|
||||
class="inline-block px-3 py-1 text-sm bg-muted text-muted-foreground rounded-full hover:bg-purple-500/20 hover:text-purple-500 transition-all duration-200">
|
||||
{tag}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Blog Posts -->
|
||||
<div class="lg:col-span-3">
|
||||
<BlogList posts={blogPosts} lang="en" client:load />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</BlogLayout>
|
||||
|
||||
<style>
|
||||
.line-clamp-3 {
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user