Skip to main content

Overview

This portfolio is built with Astro and Tailwind CSS, making it highly customizable. You can easily modify colors, typography, animations, and content to match your personal brand.

Customizing Colors

The color scheme is defined in tailwind.config.mjs using Tailwind’s theme extension system.

Primary and Accent Colors

The portfolio uses a primary blue color palette and an accent cyan palette:
tailwind.config.mjs
export default {
  theme: {
    extend: {
      colors: {
        primary: {
          50: '#eff6ff',
          100: '#dbeafe',
          200: '#bfdbfe',
          300: '#93c5fd',
          400: '#60a5fa',
          500: '#3b82f6',
          600: '#2563eb',
          700: '#1d4ed8',
          800: '#1e40af',
          900: '#1e3a8a',
          950: '#172554',
        },
        accent: {
          400: '#22d3ee',
          500: '#06b6d4',
          600: '#0891b2',
        },
      },
    },
  },
};
Use a tool like Tailwind Color Generator to generate a complete color palette from a single base color.

Changing the Color Scheme

To change to a different color scheme:
1

Choose your base color

Select a primary color that represents your brand. You can use any hex color code.
2

Generate the palette

Use a palette generator to create shades from 50 to 950. Replace the primary object in tailwind.config.mjs.
3

Update accent colors

Choose complementary accent colors and update the accent object.
4

Test in dark mode

Ensure your colors have sufficient contrast in both light and dark modes.

Dark Mode Colors

Dark mode uses Tailwind’s class-based dark mode (darkMode: 'class'). The base colors are defined in the Layout component:
src/layouts/Layout.astro
body {
  background-color: #f8fafc;
  color: #1e293b;
}

.dark body {
  background-color: #020617;
  color: #f1f5f9;
}
To customize dark mode:
  • Update background: Change #020617 (slate-950)
  • Update text: Change #f1f5f9 (slate-100)

Customizing Typography

Font Family

The portfolio uses Inter font from Google Fonts. To change it:
1

Update Tailwind config

Modify the fontFamily in tailwind.config.mjs:
tailwind.config.mjs
theme: {
  extend: {
    fontFamily: {
      sans: ['Your Font', 'system-ui', 'sans-serif'],
    },
  },
}
2

Update font imports

In src/layouts/Layout.astro, update the Google Fonts URL:
src/layouts/Layout.astro
<link rel="preload" 
  href="https://fonts.googleapis.com/css2?family=Your+Font:wght@300;400;500;600;700;800&display=swap" 
  as="style" 
  onload="this.onload=null;this.rel='stylesheet'" />
The font is preloaded for performance. Keep the onload attribute to prevent render-blocking.

Custom Animations

The portfolio includes several custom animations defined in tailwind.config.mjs:
tailwind.config.mjs
animation: {
  'float': 'float 8s ease-in-out infinite',
  'float-delayed': 'float 8s ease-in-out 2s infinite',
  'pulse-slow': 'pulse 4s cubic-bezier(0.4, 0, 0.6, 1) infinite',
  'gradient': 'gradient 8s ease infinite',
  'border-spin': 'border-spin 5s linear infinite',
},
keyframes: {
  float: {
    '0%, 100%': { transform: 'translateY(0px)' },
    '50%': { transform: 'translateY(-20px)' },
  },
  gradient: {
    '0%, 100%': { backgroundPosition: '0% 50%' },
    '50%': { backgroundPosition: '100% 50%' },
  },
  'border-spin': {
    '0%': { transform: 'rotate(0deg)' },
    '100%': { transform: 'rotate(360deg)' },
  },
}

Creating Custom Animations

To add your own animation:
  1. Define the keyframes in the keyframes object
  2. Reference it in the animation object
  3. Use it in your components with animate-{name}
keyframes: {
  'slide-in': {
    '0%': { transform: 'translateX(-100%)' },
    '100%': { transform: 'translateX(0)' },
  },
}

Updating Content

Personal Information

Content is managed through the i18n translation system. Edit src/i18n/utils.ts:
src/i18n/utils.ts
export const translations = {
  es: {
    'hero.name': 'Your Name',
    'hero.role': 'Your Role',
    'hero.bio': 'Your bio description...',
    // ... more translations
  },
  en: {
    'hero.name': 'Your Name',
    'hero.role': 'Your Role',
    'hero.bio': 'Your bio description...',
    // ... more translations
  },
};
Make sure to update both es (Spanish) and en (English) translations to keep the site consistent across languages.

Updating CV Files

CV/Resume files are stored in public/cv/ with separate folders for each language:
  • public/cv/es/ - Spanish CV
  • public/cv/en/ - English CV
Replace the PDF files in these directories with your own CV.

Images and Assets

Static assets are stored in the public/ directory:
  • public/favicon.svg - Site favicon
  • public/cv/ - CV/Resume files
To change the favicon, replace public/favicon.svg with your own SVG or add PNG versions:
src/layouts/Layout.astro
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />

Customizing Components

Modifying Layout

The main layout is in src/layouts/Layout.astro. This controls:
  • HTML structure
  • Meta tags and SEO
  • Font loading
  • Dark mode initialization
  • Global styles
  • Scroll animations

Component Structure

Components are located in src/components/:
  • Hero.astro - Landing section
  • About.astro - About/experience section
  • Projects.astro - Projects/case studies
  • Skills.astro - Technical skills
  • Contact.astro - Contact information
  • Navbar.astro - Navigation bar
  • Footer.astro - Footer
  • ThemeToggle.astro - Dark mode toggle
  • LanguageSelector.astro - Language switcher

Customizing the Navbar

Navigation links are defined by translation keys. To add a new section:
  1. Add translation keys in src/i18n/utils.ts:
'nav.blog': 'Blog',
  1. Update the Navbar component to include the new link
  2. Create the corresponding section component

Scroll Animations

The portfolio uses the Intersection Observer API for scroll-reveal animations. Elements with the .reveal class fade in as they scroll into view.
Example Usage
<div class="reveal" style="--reveal-delay: 100ms">
  <!-- Content fades in with 100ms delay -->
</div>
The animation is defined in the Layout component:
src/layouts/Layout.astro
.reveal {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity .7s cubic-bezier(.16,1,.3,1), 
              transform .7s cubic-bezier(.16,1,.3,1);
  transition-delay: var(--reveal-delay, 0ms);
}

.reveal.revealed {
  opacity: 1;
  transform: translateY(0);
}
Customize:
  • opacity - Initial transparency
  • translateY - Initial vertical offset
  • Duration - Change .7s to your preferred timing
  • Easing - Modify the cubic-bezier values

Next Steps

Internationalization

Learn how to add new languages and manage translations

Dark Mode

Customize dark mode colors and behavior

Deployment

Deploy your customized portfolio to production

Build docs developers (and LLMs) love