Skip to content

vhrita/definitive-portfolio

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

188 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🎯 Vitor Rita Portfolio

Modern, multilingual portfolio built with React + Vite, featuring smooth animations and production-ready SEO optimization.

React Vite License

✨ Features

  • 🌍 Multilingual - English (default), Portuguese, Japanese with automatic detection
  • πŸ“± Fully Responsive - Mobile-first design with fluid animations
  • 🎭 Rich Animations - GSAP and Framer Motion integrations
  • πŸ” SEO Optimized - Hybrid system: static HTML for crawlers + dynamic meta tags
  • πŸ“± Social Media Ready - Open Graph, Twitter Cards with multilingual support
  • ⚑ Performance Focused - Code splitting, lazy loading (~300KB gzipped)
  • β™Ώ Accessible - WCAG 2.1 AA compliant with keyboard navigation
  • 🎨 Modern Stack - React 18, Vite 5, SCSS, React Router v7

πŸš€ Quick Start

# Install dependencies
npm install

# Start development server
npm run dev

# Build for production
npm run build

# Preview production build
npm run preview

🌐 URL Structure

Language Home About Portfolio Contact
English / /about /portfolio /contact
Portuguese /pt/ /pt/about /pt/portfolio /pt/contact
Japanese /ja/ /ja/about /ja/portfolio /ja/contact

πŸ› οΈ Tech Stack

Core

  • React 18 - UI library
  • Vite 5 - Build tool & dev server
  • React Router DOM v7 - Client-side routing
  • SCSS - Styling with responsive mixins

Animations

  • Framer Motion - React animation library
  • GSAP - Advanced scroll animations

Internationalization

  • react-i18next - Translation management
  • i18next-browser-languagedetector - Automatic language detection

SEO

  • React Helmet Async - Dynamic meta tags
  • Custom static HTML generator - Pre-rendered pages for crawlers
  • nginx - Crawler detection & routing

Forms

  • Formspree - Contact form backend

πŸ“ Project Structure

src/
β”œβ”€β”€ components/          # Reusable components
β”‚   β”œβ”€β”€ SEO.jsx         # Dynamic meta tags
β”‚   β”œβ”€β”€ Router.jsx      # Client-side routing
β”‚   β”œβ”€β”€ Navbar/         # Navigation component
β”‚   β”œβ”€β”€ Social/         # Social media links
β”‚   └── ...
β”œβ”€β”€ pages/              # Page components
β”‚   β”œβ”€β”€ Home/
β”‚   β”œβ”€β”€ About/
β”‚   β”œβ”€β”€ Portfolio/
β”‚   └── Contact/
β”œβ”€β”€ config/             # Configuration files
β”‚   β”œβ”€β”€ constants.js    # Shared constants
β”‚   └── internationalization/
β”œβ”€β”€ data/               # Static data
β”‚   └── projects.js     # Portfolio projects
β”œβ”€β”€ utils/              # Utility functions
β”‚   β”œβ”€β”€ languageUtils.js
β”‚   β”œβ”€β”€ mixins.scss
β”‚   └── variables.scss
└── assets/             # Images, icons, fonts

scripts/
β”œβ”€β”€ generate-static-seo.mjs  # Static HTML generation
└── generate-sitemap.mjs     # XML sitemap generation

public/
β”œβ”€β”€ og-image.png        # Social sharing (EN)
β”œβ”€β”€ og-image-pt.png     # Social sharing (PT)
β”œβ”€β”€ og-image-ja.png     # Social sharing (JA)
β”œβ”€β”€ resume.pdf          # Resume file
β”œβ”€β”€ robots.txt          # Crawler directives
└── site.webmanifest    # PWA manifest

πŸ“Š SEO Implementation

Hybrid Approach

The portfolio uses a hybrid SEO system:

  1. For crawlers (Facebook, WhatsApp, Google): Pre-rendered static HTML pages with correct localized meta tags
  2. For users: Full React SPA with dynamic meta tags via React Helmet

Why? Social media crawlers don't execute JavaScript, so dynamic meta tags don't work. The solution: nginx detects crawlers and serves them static pages.

How It Works

Request to /pt/contact
        ↓
    nginx.conf (crawler detection)
        ↓
   Is crawler? ──Yesβ†’ Serve /pt/contact/index.html (static)
        ↓
       No
        ↓
   Serve SPA β†’ React Router β†’ SEO.jsx (dynamic)

πŸ“ˆ Performance

Bundle Size

Production Build (gzipped):
β”œβ”€β”€ vendor.js      141KB  (React + ReactDOM)
β”œβ”€β”€ animations.js  179KB  (Framer Motion + GSAP)
β”œβ”€β”€ i18n.js        81KB   (Internationalization)
β”œβ”€β”€ main.js        121KB  (App core)
β”œβ”€β”€ components.js  40KB   (Components)
└── utils.js       31KB   (Utilities)
────────────────────────────────────────
Total:             ~300KB

Optimizations Implemented

  • βœ… Route-based code splitting with React.lazy()
  • βœ… Vendor chunk separation
  • βœ… Native image lazy loading
  • βœ… Optimized Vite build configuration

πŸ”§ Development Commands

# Development
npm run dev              # Start dev server (http://localhost:5173)

# Building
npm run build           # Build + generate sitemap + static SEO pages
npm run build:simple    # Build only (without post-build scripts)
npm run generate:sitemap # Generate sitemap.xml only
npm run preview         # Preview production build (http://localhost:4173)

πŸš€ Deployment

Current Setup: CapRover with nginx

Also compatible with:

  • Netlify
  • Vercel
  • Any static host with nginx/Apache configuration

Required Files:

  • nginx.conf - Production nginx configuration
  • Dockerfile - Container setup (CapRover)
  • dist/ - Build output

Environment Variables

None required! The app is fully static after build.

πŸ§ͺ Testing

# Test production build locally
npm run build && npm run preview

# Test different languages
open http://localhost:4173/pt/contact
open http://localhost:4173/ja/about

# Test social media sharing
# Facebook: https://developers.facebook.com/tools/debug/
# Twitter: https://cards-dev.twitter.com/validator

πŸ“ Adding New Content

Add a New Project

  1. Add project images to src/assets/portfolio/
  2. Update src/data/projects.js:
    'new-project-id': {
      images: [newProjectImg],
      imagePositions: ['center top'],
      techs: ['React', 'Node.js'],
      link: 'https://...',
      repository: 'https://github.com/...'
    }
  3. Add translations in all language files:
    {
      "projects": [
        {
          "id": "new-project-id",
          "title": "...",
          "description": "..."
        }
      ]
    }

Update SEO Meta Tags

Edit seo section in translation files:

{
  "seo": {
    "home": {
      "title": "...",
      "description": "...",
      "keywords": "..."
    }
  }
}

Run npm run build to regenerate static SEO pages.

🎨 Customization

Colors

Edit src/utils/variables.scss:

$dark: #242424;
$blue: #2bcab6;
$white: #ffffff;

Fonts

Currently using Google Fonts (Space Grotesk). To self-host:

npm install @fontsource/space-grotesk

Update src/main.jsx:

import '@fontsource/space-grotesk/400.css'
import '@fontsource/space-grotesk/700.css'

Responsive Breakpoints

Defined in src/utils/mixins.scss:

$breakpoints: (
  'mobile': 480px,
  'tablet': 768px,
  'tablet-landscape': 1024px,
  'desktop': 1024px,
  'large': 1400px
);

🀝 Contributing

This is a personal portfolio, but you're welcome to:

  • Report bugs via GitHub Issues
  • Suggest improvements
  • Use as inspiration for your own portfolio

πŸ“„ License

MIT License - feel free to use this project as inspiration for your own portfolio.

πŸ™ Acknowledgments

  • Framer Motion - Beautiful animations
  • GSAP - Advanced scroll effects
  • React Helmet Async - SEO meta tag management
  • Formspree - Simple form backend

Built with ❀️ by Vitor Rita

LinkedIn GitHub

About

Ok, this time I will finish it

Resources

License

Stars

Watchers

Forks

Contributors

Languages