Skip to main content

Overview

Card components are specialized display components that present structured data in a consistent, visually appealing format. All card components are located in src/components/cards/.

ProjectCard

Displays a project with an image, title, description, technologies, and links.

Props

project
Project
required
Project object with the following structure:
project.title
string
required
Project name
project.description
string
required
Brief project description
project.image
ImageMetadata
Project screenshot or logo (optional)
project.technologies
string[]
Array of technology names (e.g., [“React”, “TypeScript”])
URL to the GitHub repository
project.website
string
URL to the live website (optional)

Usage

---
import ProjectCard from "../components/cards/ProjectCard.astro";
import { projects } from "../data";
---

<div class="grid grid-cols-1 gap-8 md:grid-cols-2 lg:grid-cols-3">
  {projects.map((project) => <ProjectCard project={project} />)}
</div>

Features

  • Image with hover zoom animation
  • Technology badges
  • GitHub and website links with icons
  • Hover effects (shadow, lift, color transition)
  • Responsive layout

Example Data

const project = {
  title: "My Awesome Project",
  description: "A revolutionary tool that solves real problems",
  image: import("./images/project.png"),
  technologies: ["TypeScript", "Astro", "TailwindCSS"],
  githubLink: "https://github.com/username/project",
  website: "https://project.example.com"
};

BlogCard

Displays a blog post with title, description, publish date, and reading time.

Props

post
BlogPost
required
Blog post object with frontmatter:
post.url
string
required
URL to the blog post
post.frontmatter.title
string
required
Post title
post.frontmatter.description
string
required
Post description or excerpt
post.frontmatter.pubDate
string
required
Publication date (e.g., “Jan 15, 2024”)
post.frontmatter.readingTime
string
required
Estimated reading time (e.g., “5 min read”)

Usage

---
import BlogCard from "../components/cards/BlogCard.astro";

const blogs = Object.values(
  import.meta.glob("./posts/*.md", { eager: true })
);
---

<div class="grid grid-cols-1 gap-8 md:grid-cols-2 lg:grid-cols-3">
  {blogs.map((post) => <BlogCard post={post} />)}
</div>

Features

  • Clickable card linking to full post
  • Calendar and clock icons for metadata
  • HTML description support
  • Hover effects

Example Data

---
title: "Understanding Astro Components"
description: "A deep dive into Astro's component architecture"
pubDate: "Mar 4, 2026"
readingTime: "8 min read"
---

Your blog content here...

WorkExperienceCard

Displays work experience with company name, positions, duration, and technologies.

Props

experience
WorkExperience
required
Work experience object:
experience.company
string
required
Company name
experience.website
string
required
Company website URL
experience.type
string
required
Employment type: "full-time", "part-time", "contract", "internship", or "volunteer"
experience.positions
Position[]
required
Array of positions at the company:
positions[].title
string
required
Job title
positions[].duration
string
required
Duration (e.g., “Jan 2023 - Present”)
experience.technologies
string[]
Array of technologies used (optional)

Usage

---
import WorkExperienceCard from "../components/cards/WorkExperienceCard.astro";
import { workExperience } from "../data";
---

<div class="mx-auto grid max-w-6xl grid-cols-1 gap-8 lg:grid-cols-2">
  {workExperience.map((experience) => (
    <WorkExperienceCard experience={experience} />
  ))}
</div>

Features

  • Type-based badge with icon (full-time, contract, etc.)
  • Multiple positions support
  • Technology badges
  • Clickable card linking to company website
  • Calendar icon for duration

Example Data

const experience = {
  company: "Tech Corp",
  website: "https://techcorp.example.com",
  type: "full-time",
  positions: [
    {
      title: "Senior Developer",
      duration: "Jan 2023 - Present"
    },
    {
      title: "Developer",
      duration: "Mar 2021 - Dec 2022"
    }
  ],
  technologies: ["TypeScript", "React", "Node.js"]
};

Type Configuration

Each employment type has a specific badge color and icon:
  • full-time: Green badge with briefcase icon
  • part-time: Blue badge with clock icon
  • contract: Gray badge with handshake icon
  • internship: Orange badge with school icon
  • volunteer: Red badge with heart icon

AchievementCard

Displays an achievement or recognition with an icon and title.

Props

achievement
Achievement
required
Achievement object:
achievement.title
string
required
Achievement title
achievement.icon
string
Iconify icon name (defaults to "mdi:security")
achievement.url
string
required
URL to achievement details or certificate

Usage

---
import AchievementCard from "../components/cards/AchievementCard.astro";
import { achievements } from "../data";
---

<div class="grid grid-cols-1 gap-8 md:grid-cols-3">
  {achievements.map((achievement) => (
    <AchievementCard achievement={achievement} />
  ))}
</div>

Features

  • Large icon display
  • Clickable card opening in new tab
  • Centered layout
  • Icon color transition on hover

Example Data

const achievement = {
  title: "HackerOne Top 100",
  icon: "mdi:shield-check",
  url: "https://hackerone.com/username"
};

Common Features

All card components share these features:

Base Card Component

They all use the Card UI component (see UI Elements) which provides:
  • Rounded corners (rounded-2xl)
  • Shadow effects with hover animation
  • Lift effect on hover (hover:-translate-y-1)
  • Smooth transitions

Hover Effects

  • Shadow intensity increase
  • Vertical lift animation
  • Color transitions on text/icons
  • Image zoom (ProjectCard)

Responsive Design

Cards work across all screen sizes:
<!-- Mobile: 1 column, Tablet: 2 columns, Desktop: 3 columns -->
<div class="grid grid-cols-1 gap-8 md:grid-cols-2 lg:grid-cols-3">
  {items.map((item) => <Card {...item} />)}
</div>

UI Elements

Learn about the base Card, Badge, and Icon components

Sections

See how to organize cards into sections

Build docs developers (and LLMs) love