Skip to main content

Overview

The CardsBlog component displays blog posts in a responsive card grid with built-in search functionality. It queries published posts from the blog collection and renders them with styled cards.

Features

  • Automatic Post Loading - Fetches and displays published blog posts from content collections
  • Search Functionality - Filter posts by title, description, or tags
  • Responsive Grid - Adapts from 1 column (mobile) to 3 columns (desktop)
  • Hover Effects - Smooth animations on card hover
  • Tag Display - Shows post tags as styled badges
  • Date Formatting - Displays post creation date in readable format
  • Empty State - Shows message when no posts are published or found

Source Code

src/components/Blog/CardsBlog.astro
---
import { getCollection } from 'astro:content';

const posts = await getCollection('blog', ({ data }) => {
  return data.publish === true;
});

// Sort posts by creation date (newest first)
const sortedPosts = posts.sort((a, b) => 
  Number(b.data.createdAt.valueOf()) - Number(a.data.createdAt.valueOf())
);
---

<style>
  .article-card .card {
    transition: transform 0.3s ease, box-shadow 0.3s ease;
    border: 1px solid rgba(2, 129, 198, 0.2);
    background: linear-gradient(180deg, #003553, #001a29);
    border-radius: 15px;
  }

  .article-card .card:hover {
    transform: translateY(-5px);
    box-shadow: 0 8px 20px rgba(2, 129, 198, 0.2);
  }

  .article-card .badge {
    background-color: #0281C6 !important;
    color: white;
  }
</style>

<div class="container py-4 py-xl-5">
  {sortedPosts.map((post) => (
    <div class="col article-card">
      <a href={`/blog/${post.slug}`}>
        <div class="card h-100 text-white rounded-3"> 
          <div class="card-body p-4">
            <h4 class="card-title">{post.data.title}</h4>
            <p class="card-text">{post.data.description}</p>
            <div class="d-flex flex-wrap gap-2 mb-3">
              {post.data.tags?.map((tag) => (
                <span class="badge rounded-pill">{tag}</span>
              ))}
            </div>
          </div>
        </div>
      </a>
    </div>
  ))}
</div>

Usage

The CardsBlog component is primarily used on the blog index page to display all published posts:
src/pages/blog/index.astro
---
import Layout from "../../layouts/Layout.astro";
import CardsBlog from "../../components/Blog/CardsBlog.astro";
---

<Layout 
  title="Blog - RobTop Games" 
  description="Latest articles and guides"
>
  <CardsBlog />
</Layout>

Search Functionality

The component includes a built-in search script that filters posts:
Search Implementation
function performSearch() {
  const searchTerm = searchInput?.value.toLowerCase() || '';
  
  articleCards.forEach(card => {
    const title = card.querySelector('.card-title')?.textContent?.toLowerCase() || '';
    const description = card.querySelector('.card-text')?.textContent?.toLowerCase() || '';
    const tags = card.querySelector('.article-tags')?.textContent?.toLowerCase() || '';
    
    const matches = title.includes(searchTerm) || 
                   description.includes(searchTerm) || 
                   tags.includes(searchTerm);

    card.style.display = matches ? 'block' : 'none';
  });
}
The search filters posts in real-time by:
  • Post title
  • Post description
  • Post tags

Styling

The component uses a dark gradient background matching the site theme:
  • Background: Linear gradient from #003553 to #001a29
  • Border: Subtle blue border with rgba(2, 129, 198, 0.2)
  • Hover Effect: Lifts card with translateY(-5px) and enhances shadow
  • Border Radius: 15px for smooth corners
  • Badge Color: #0281C6 (blue accent)

Responsive Behavior

The grid adapts to screen size:
BreakpointColumnsWidth
Mobile (< 768px)1100%
Tablet (768px+)250%
Desktop (1200px+)333.33%

Empty States

When no posts have publish: true, displays:
No Articles Published
New content coming soon.

Post Data Structure

Each post card displays data from the blog collection schema:
interface BlogPost {
  title: string;           // Card title
  description: string;     // Card description
  createdAt: Date;        // Formatted date
  tags?: string[];        // Badge pills
  slug: string;           // Link URL
  publish: boolean;       // Filter criteria
}

Blog System

Learn about the complete blog architecture

Content Collections

Understand how blog posts are structured

Build docs developers (and LLMs) love