Skip to main content

Overview

The Astro Portfolio v3 project uses a well-organized component architecture that promotes reusability and maintainability. All components are built using Astro’s component syntax, which combines HTML, CSS, and JavaScript in a single file.
Components are located in ~/workspace/source/src/components/ and are organized by category: home/, navs/, shared/, and ui/.

Component Categories

Home Section Components

These components make up the various sections of the homepage and are located in src/components/home/.

About Component

Renders the about section with content from the content collection.
---
// src/components/home/About.astro
import SideNav from '../SideNav.astro';
import { getEntry } from 'astro:content';

const aboutContent = await getEntry('about', 'about-content');
const { Content } = await aboutContent.render();
---

<section class='py-20 relative' id='about'>
  <div class='container-fluid relative'>
    <h2 class='text-4xl font-semibold'>About me</h2>
    <Content />
  </div>
</section>
Location: src/components/home/About.astro:1

Projects Component

Displays featured projects from the projects content collection.Location: src/components/home/Projects.astro:1

Work Experience Component

Shows work history in a timeline format.Location: src/components/home/WorkExperience.astro:1

Hero Components

  • HeroText.astro - Main hero text and CTA
  • HeroImage.astro - Hero section image/illustration

Blog Component

Lists recent blog posts on the homepage.Location: src/components/home/Blogs.astro:1

Author Sidebar

Displays author information in article pages. Location: src/components/AuthorSidebar.astro:1

Sponsors Sidebar

Shows sponsor information and advertisements. Location: src/components/SponsorsSidebar.astro:1

Side Navigation

Navigation sidebar for the about page. Location: src/components/SideNav.astro:1

Component Patterns

Content Integration

Components frequently integrate with Astro’s Content Collections:
---
import { getEntry } from 'astro:content';

// Fetch content from a collection
const aboutContent = await getEntry('about', 'about-content');

// Render markdown content
const { Content } = await aboutContent.render();
---

<section>
  <Content />
</section>

Component Composition

Components are designed to be composable:
---
import { ThemeSwitcher, LanguageSwitcher } from '@/components/shared';
import { Navbar } from '@/components/navs';
---

<Navbar>
  <div class='flex gap-2'>
    <LanguageSwitcher />
    <ThemeSwitcher />
  </div>
</Navbar>

Client-Side Interactivity

Components with client-side behavior use inline <script> tags:
<button class='theme-toggle'>
  Toggle Theme
</button>

<script>
  function initThemeToggle() {
    const toggle = document.querySelector('.theme-toggle');
    toggle.addEventListener('click', () => {
      // Handle theme switching
    });
  }
  
  initThemeToggle();
  
  // Re-initialize after page transitions
  document.addEventListener('astro:after-swap', initThemeToggle);
</script>
The astro:after-swap event ensures components work correctly with Astro’s view transitions.

Styling Components

Components use Tailwind CSS utility classes for styling:
<button class='p-2 rounded-md hover:bg-accent transition-colors'>
  Click me
</button>
Theme-aware classes:
  • dark: prefix for dark mode styles
  • retro: prefix for retro theme styles
  • CSS variables for dynamic theming

Using Components

Import and Use

---
// Import from the components directory
import { About, Projects, WorkExperience } from '@/components/home';
import Navbar from '@/components/navs/Navbar.astro';
---

<Navbar />

<main>
  <About />
  <WorkExperience />
  <Projects />
</main>

Index Files

Component groups export their components via index.ts files:
// src/components/home/index.ts
export { default as About } from './About.astro';
export { default as Blogs } from './Blogs.astro';
export { default as HeroImage } from './HeroImage.astro';
export { default as HeroText } from './HeroText.astro';
export { default as Projects } from './Projects.astro';
export { default as WorkExperience } from './WorkExperience.astro';
This allows for clean imports:
import { About, Projects } from '@/components/home';

Creating New Components

To create a new component:
  1. Choose the appropriate directory based on the component’s purpose
  2. Create an .astro file with a descriptive name
  3. Add to the index file if it’s part of a group
  4. Follow naming conventions: PascalCase for component files
Example:
---
// src/components/shared/NewComponent.astro
interface Props {
  title: string;
  description?: string;
}

const { title, description } = Astro.props;
---

<div class='my-component'>
  <h3>{title}</h3>
  {description && <p>{description}</p>}
</div>

<style>
  .my-component {
    /* Component-scoped styles */
  }
</style>

Best Practices

  1. Keep components focused - Each component should have a single responsibility
  2. Use TypeScript interfaces - Define prop types for better type safety
  3. Leverage content collections - Fetch content from collections rather than hardcoding
  4. Make components responsive - Use Tailwind’s responsive prefixes
  5. Handle page transitions - Use astro:after-swap for client-side scripts
  6. Export from index files - Make component groups easier to import
  7. Use semantic HTML - Ensure accessibility with proper HTML structure

Theming

Learn how the ThemeSwitcher component works

i18n

Understand the LanguageSwitcher implementation

Content Collections

See how components integrate with content

Project Structure

Understand the overall project organization

Build docs developers (and LLMs) love