Skip to main content

Overview

The Projects component displays a grid of case study cards showcasing cloud engineering projects. Each card follows a challenge-solution format with technology stack badges.

Source Location

/src/components/Projects.astro

Features

  • Grid layout of case study cards
  • Challenge/Solution format for each project
  • Technology stack tags
  • Custom icons for different project types
  • Staggered reveal animations
  • Background decorative elements
  • Fully internationalized

Props

No props required. Uses internal caseStudies array and translation system.

Data Structure

Case Studies Array

const caseStudies = [
  {
    titleKey: 'case1.title' as const,
    challengeKey: 'case1.challenge' as const,
    solutionKey: 'case1.solution' as const,
    tech: ['Azure RBAC', 'PowerShell'],
    icon: 'shield',
  },
  // ... more case studies
];
titleKey
string
Translation key for the case study title
challengeKey
string
Translation key for the challenge description
solutionKey
string
Translation key for the solution description
tech
string[]
Array of technology names used in the project
icon
string
Icon identifier: ‘shield’, ‘search’, ‘migrate’, ‘cost’, or ‘document’

Code Example

import Projects from '../components/Projects.astro';

<Projects />

Available Case Studies

1. Security & Permissions (icon: shield)

  • Tech: Azure RBAC, PowerShell
  • Focus on access control and security optimization
  • Tech: Azure Resource Graph, Cloudockit, Governance
  • Resource inventory and compliance

3. Migration & Disaster Recovery (icon: migrate)

  • Tech: Azure Backup, App Service Cloning, Disaster Recovery
  • Cross-region migration projects

4. Cost Optimization (icon: cost)

  • Tech: Azure Cost Management, Excel/PowerBI, FinOps
  • Financial operations and cost analysis

5. Documentation (icon: document)

  • Tech: Technical Writing, Canva, Cloud Adoption Framework (CAF)
  • Creating technical documentation and diagrams

Translation Keys

casestudies.title          // Main section title
casestudies.challengeLabel // "Challenge" label
casestudies.solutionLabel  // "Solution" label
casestudies.stackLabel     // "Tech Stack" label

Component Usage

Grid Layout

<div class="grid md:grid-cols-2 gap-6">
  {caseStudies.map((cs, i) => (
    <div class="reveal" style={`--reveal-delay: ${i * 120}ms`}>
      <CaseStudyCard
        title={t(cs.titleKey)}
        challenge={t(cs.challengeKey)}
        solution={t(cs.solutionKey)}
        tech={cs.tech}
        icon={cs.icon}
        challengeLabel={t('casestudies.challengeLabel')}
        solutionLabel={t('casestudies.solutionLabel')}
        stackLabel={t('casestudies.stackLabel')}
      />
    </div>
  ))}
</div>

Background Decoration

<div class="absolute inset-0 pointer-events-none overflow-hidden">
  <div class="absolute top-0 right-0 w-72 h-72 bg-primary-400/10 dark:bg-primary-500/5 rounded-full blur-2xl"></div>
  <div class="absolute bottom-0 left-0 w-96 h-96 bg-accent-400/10 dark:bg-accent-500/5 rounded-full blur-2xl"></div>
</div>

Styling

Section Container

<section id="projects" class="relative py-20 lg:py-28" style="content-visibility: auto; contain-intrinsic-size: auto 600px;">
  • Performance optimized with content-visibility
  • Responsive padding: py-20 (mobile) to py-28 (desktop)
  • Positioned relatively for absolute background elements

Reveal Animations

Staggered animations with 120ms delay increments:
<div class="reveal" style={`--reveal-delay: ${i * 120}ms`}>

Performance

The Projects section uses content-visibility: auto to defer rendering when off-screen, improving initial page load performance.
  • Content visibility optimization
  • Minimal layout shifts with intrinsic sizing
  • CSS-only background animations
  • Efficient grid layout

Accessibility

  • Semantic section element with id="projects"
  • Proper heading hierarchy
  • All case study content is keyboard accessible
  • ARIA labels passed to child components

Customization

Adding a New Case Study

  1. Add entry to the caseStudies array:
const caseStudies = [
  // existing entries...
  {
    titleKey: 'case6.title' as const,
    challengeKey: 'case6.challenge' as const,
    solutionKey: 'case6.solution' as const,
    tech: ['Azure Functions', 'Logic Apps', 'Event Grid'],
    icon: 'search', // or create a new icon
  },
];
  1. Add translations in your i18n files:
case6: {
  title: 'Your Project Title',
  challenge: 'The challenge description...',
  solution: 'How you solved it...'
}

Changing Grid Layout

Modify the grid classes:
<!-- 3 columns on large screens -->
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-6">

<!-- Single column on all screens -->
<div class="grid grid-cols-1 gap-6">
  • CaseStudyCard - Child component rendering individual cards
  • Skills - Complements projects by showing technical capabilities
  • About - Provides professional context for projects

Build docs developers (and LLMs) love