Personal Portfolio Website

A custom-built portfolio site showcasing DevSecOps projects with dark mode, responsive design, and iterative development philosophy

Frontend Development
Status: launched
Started:
Launched:

Tech Stack

AstroTypeScriptVercelMDXCSS GridGitHub
Viewing Previous Versionv1.0
Table of Contents

    Problem Statement

    Building a portfolio that actually represents who you are is harder than it sounds. Most portfolio sites fall into one of two traps: they’re either cookie-cutter templates that look like everyone else’s, or they’re over-engineered showcases that prioritize flash over substance.

    I wanted something different. A site that stood out not because it tried to impress, but because it incorporated the design elements I personally care about: clean organization, quick performance, and an iterative development approach that values shipping real work over endless polishing. This needed to be a true reflection of how I think about building systems—pragmatic, security-conscious, and focused on delivering value.

    The challenge wasn’t just technical. It was philosophical: How do you create something authentic in a space dominated by marketing-heavy portfolios? How do you showcase DevSecOps work—which is often behind-the-scenes infrastructure—in a way that’s engaging and representative of actual accomplishments?

    Solution Architecture

    I built a custom portfolio from scratch using Astro, a modern static site generator that prioritizes performance and developer experience. The architecture is intentionally simple: a file-based routing system with Markdown content collections for blog posts, projects, and wiki pages.

    Deployment Pipeline

    graph LR
        A[Local Development] --> B[Git Commit]
        B --> C[GitHub Push]
        C --> D[Vercel Auto-Deploy]
        D --> E[Live Site]
    
        F[Content Changes] --> A
        G[Component Updates] --> A
        H[Design Iterations] --> A
    
        style D fill:#4a6741,color:#fff
        style E fill:#3a5231,color:#fff

    Key Components

    1. Astro Framework: Static site generation with component-based architecture for fast, SEO-friendly pages
    2. Content Collections: Structured Markdown/MDX for projects, blog posts, and wiki documentation with type-safe frontmatter
    3. Custom Components: Reusable .astro components for certifications, headers, footers, and navigation
    4. Dark Mode System: CSS custom properties with localStorage persistence and system preference detection
    5. Vercel Hosting: Continuous deployment from GitHub with automatic builds on push
    6. Responsive Design: Mobile-first CSS Grid layouts with breakpoints at 768px (tablet) and 1024px (desktop)

    Technical Implementation

    Framework Selection: Astro

    I chose Astro over Next.js, Gatsby, or traditional SSGs because:

    • Zero JavaScript by default: Ships only HTML/CSS unless you opt into client-side JS
    • Content Collections: First-class support for structured Markdown with TypeScript validation
    • Component Islands: Selective hydration for interactive elements (like the dark mode toggle)
    • Performance: 100/100 Lighthouse scores out of the box
    • Flexibility: Supports multiple UI frameworks (React, Vue, Svelte) if needed later

    Site Architecture

    The site is organized into four main sections:

    1. Projects (/projects): Showcases DevSecOps and cloud security work with custom category filtering (AWS Security, AWS Infrastructure, Homelab, AI Tools, Local Development)

    2. Blog (/blog): Technical writeups and learning notes with RSS feed generation and automatic table of contents

    3. Wiki (/wiki): Knowledge base and documentation organized by topic with search-friendly structure

    4. About (/about): Professional background with custom certification badge component linked to Credly for verification

    Dark Mode Implementation

    The dark mode system was one of the most critical features. It needed to:

    • Persist user preference across sessions
    • Respect system dark mode settings on first visit
    • Prevent flash of unstyled content (FOUC)
    • Support all components and layouts

    Implementation approach:

    // Inline script in <head> prevents FOUC
    const theme = localStorage.getItem('theme') ||
      (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
    if (theme === 'dark') {
      document.documentElement.classList.add('dark');
    }

    CSS Custom Properties in global.css:

    :root {
      --bg-primary: #ffffff;
      --bg-secondary: #f7fafc;
      --text-primary: rgb(var(--gray-dark));
      /* Light mode colors */
    }
    
    :root.dark {
      --bg-primary: #0f1410;    /* Black with green tint */
      --bg-secondary: #1a211a;  /* Dark grey-green */
      --text-primary: rgb(var(--gray-dark));
      /* Dark mode: black/grey/forest green palette */
    }

    The dark mode toggle component uses SVG icons (sun/moon) with smooth transitions and proper ARIA labels for accessibility.

    Custom Certification Badges

    Rather than embedding Credly’s iframe widgets (which are slow and break responsive layouts), I built a custom CertificationBadge.astro component:

    interface Props {
      name: string;
      issuer: string;
      credlyUrl: string;
      dateIssued: string;
      expirationDate?: string;
      inProgress?: boolean;
      badgeImageUrl?: string;
    }

    Features:

    • Displays completed certifications with issued/expiration dates
    • Shows “In Progress” status for certifications being pursued
    • Links to Credly for verification
    • Responsive grid layout (3 columns desktop, 2 tablet, 1 mobile)
    • Pulls badge images directly from Credly CDN for fast loading

    Data structure in src/data/certifications.ts keeps content separate from presentation, making updates simple.

    Responsive Design Strategy

    Mobile-first CSS with three breakpoints:

    • Mobile: 320px - 767px (1-column layouts, simplified navigation)
    • Tablet: 768px - 1023px (2-column grids, collapsible menus)
    • Desktop: 1024px+ (3-column grids, sticky sidebars, full navigation)

    Used CSS Grid for all layouts instead of flexbox for better control over two-dimensional spacing. Implemented CSS custom properties for fluid spacing using clamp():

    --space-md: clamp(1rem, 4vw, 1.2rem);
    --space-lg: clamp(1.5rem, 5vw, 2rem);

    This creates responsive spacing that adapts smoothly across all screen sizes without breakpoint jumps.

    Challenges & Solutions

    Challenge 1: Avoiding Template Paralysis

    Problem: Most portfolio templates are either too opinionated (forcing a specific structure) or too basic (requiring extensive customization). Starting from a template meant inheriting someone else’s design decisions.

    Solution: Started completely from scratch with Astro’s minimal blog template and stripped it down to barebones. Built only what was needed, iteratively adding features based on real content requirements.

    Lesson Learned: Starting simple and building up is faster than starting complex and stripping down. The initial discomfort of a blank slate forces intentional design decisions.

    Challenge 2: Dark Mode Consistency

    Problem: Implementing dark mode across all components and layouts revealed inconsistencies. Some pages used direct color values, others used CSS variables, and cards in dark mode had poor contrast.

    Solution:

    1. Centralized all colors in CSS custom properties in global.css
    2. Created a systematic naming convention (--bg-primary, --bg-secondary, --text-primary)
    3. Audited every component and layout to replace direct color values with variables
    4. Tested both modes on every page to ensure contrast ratios met WCAG AA standards

    Lesson Learned: Theme consistency requires discipline. A centralized design system (even a simple one) prevents drift and makes changes predictable.

    Challenge 3: Content Organization

    Problem: Portfolio content spans multiple formats: projects (technical writeups), blog posts (learning notes), wiki pages (reference docs), and certifications. Each needed different presentation but consistent navigation.

    Solution: Used Astro Content Collections with custom frontmatter schemas for each type:

    • Projects: category, status, techStack, repoUrl, liveUrl
    • Blog: pubDate, updatedDate, heroImage, tags
    • Wiki: category, order, relatedLinks

    This created type-safe content validation and enabled powerful filtering/sorting without a CMS.

    Lesson Learned: Structure your content based on how you’ll query it, not just how you’ll display it. Good information architecture makes features easier to build later.

    Challenge 4: Deployment Simplicity

    Problem: Wanted continuous deployment without managing infrastructure or complex CI/CD pipelines.

    Solution: Connected GitHub repo to Vercel with automatic deployments on push to main. Zero configuration needed—Vercel detected the Astro framework and configured build settings automatically.

    Lesson Learned: For static sites, serverless platforms like Vercel eliminate operational overhead. The best deployment pipeline is the one you don’t have to think about.

    Results & Metrics

    Performance

    • Lighthouse Score: 100/100 (Performance, Accessibility, Best Practices, SEO)
    • First Contentful Paint: < 0.5s
    • Time to Interactive: < 1.0s
    • Total Bundle Size: ~50KB (gzipped)

    Development Velocity

    • Initial launch: 2 days (from empty repo to deployed site with content)
    • Dark mode implementation: 4 hours (including fixing consistency issues across all pages)
    • Custom certification system: 2 hours (component + data structure + integration)

    Design Achievements

    • ✅ Dark mode with localStorage persistence and system preference detection
    • ✅ Custom certification badges replacing slow iframe embeds
    • ✅ Responsive design tested on mobile, tablet, and desktop
    • ✅ Accessible navigation with ARIA labels and keyboard support
    • ✅ Auto-generated table of contents on project and blog pages
    • ✅ RSS feed for blog subscribers

    Code Quality

    • TypeScript for type safety across components and content
    • Conventional commits for clear git history
    • Component-based architecture for reusability
    • No external UI libraries (pure CSS for styling)

    Key Takeaways

    1. Iterative beats perfect: Shipped a working site in 2 days, then improved based on real use. Waiting to launch until everything is “perfect” means never launching.

    2. Performance is a feature: Users notice fast sites. Astro’s zero-JS-by-default approach means the site loads instantly, even on slow connections.

    3. Authenticity over marketing: The site represents actual work—projects I built, certifications I earned, writing that reflects how I think. No stock photos, no generic copy, no inflated claims.

    4. Design systems start small: CSS custom properties for colors and spacing provided 90% of the benefit of a full design system with 10% of the complexity.

    5. Content structure matters: Astro’s Content Collections with TypeScript schemas caught errors before deploy and made adding new projects trivial.

    Future Enhancements

    Short-term (v1.1)

    • Resume transcription: Make resume content searchable and linkable
    • Photo integration: Add professional headshot and project screenshots
    • Analytics: Privacy-respecting analytics (Plausible or GoatCounter) to understand which content resonates

    Medium-term (v2.0)

    • Search functionality: Client-side search across projects, blog, and wiki using Fuse.js
    • Project filtering: Interactive category/tag filters on projects page
    • Reading time estimates: Automatic calculation for blog posts
    • Related content: Show related projects/posts based on tags

    Long-term (v3.0+)

    • Automated content generation: LLM-assisted draft creation for project writeups from git commit history
    • Interactive demos: Embed sandboxes or live demos for frontend projects

    Resources


    This project demonstrates proficiency in frontend development, responsive design, performance optimization, and pragmatic engineering. It showcases the ability to build clean, fast, user-focused applications while maintaining code quality and iterative development practices.