Skip to content

LuisUrrutia/website

Repository files navigation

urrutia.me

Personal portfolio and blog built with Astro v5 and Tailwind CSS v4.

GitHub Release Twitter License CC BY-NC-ND 4.0

View Live SiteFeaturesTech StackGetting StartedProject Structure


Features

  • Multilingual -- English (default) and Spanish with full i18n support, per-locale RSS feeds, and hreflang tags
  • Blog -- MDX-powered blog with pagination, reading time, social sharing, and Giscus comments
  • SEO -- Canonical URLs, Open Graph, Twitter Cards, JSON-LD structured data (Person, WebSite, ProfilePage, BlogPosting, BreadcrumbList), auto-generated OG images, sitemap with hreflang
  • Dark mode -- Three-state theme toggle (auto/light/dark) with blocking script to prevent flash of wrong theme
  • Accessibility -- Skip links, ARIA labels, focus-visible indicators, prefers-reduced-motion support, screen reader announcements
  • Performance -- Zero JS by default, inlined CSS, subsetted variable font, Brotli + gzip compression, lazy-loaded images with AVIF/WebP and responsive srcset
  • View Transitions -- Native CSS view transitions with lazy transition-name assignment for smooth page navigation

Tech Stack

Core

Technology Description
Astro v5 Static site generator with zero JS by default
Tailwind CSS v4 Utility-first CSS framework
TypeScript Type-safe JavaScript
MDX Markdown with components for blog posts

Development

Tool Description
Bun Fast JavaScript runtime and package manager
OxLint High-performance linter with type-aware rules
Prettier Code formatter with Astro and Tailwind plugins
Husky Git hooks
Commitlint Conventional commit linting
lint-staged Run linters on staged files

Build Pipeline

Step Description
Astro Static page generation with inlined CSS
astro-og-canvas Build-time OG image generation per blog post
@playform/compress HTML, CSS, JS, JSON, SVG, and image minification
astro-compressor Brotli and gzip pre-compression
SVGO SVG optimization via Astro experimental flag

CI/CD

Workflow Description
Verify Lint, format check, and build on PRs
Release Semantic-release with Cloudflare Pages deployment
CodeQL Security vulnerability scanning
Lighthouse Performance and accessibility audits (>= 90%)
Commitlint Validates conventional commit format
Dependabot Weekly automated dependency updates

Getting Started

Prerequisites

Installation

git clone https://github.com/LuisUrrutia/website.git
cd website
bun install

Development

bun run dev

The site will be available at http://localhost:4321 with hot module replacement.

Commands

Command Description
bun run dev Start development server at localhost:4321 with HMR
bun run build Build optimized production site to dist/
bun run preview Preview the production build locally
bun run build:preview Build and preview in one command
bun run lint Run OxLint with type-aware rules
bun run fmt Check code formatting with Prettier
bun run fmt:fix Auto-fix formatting issues

Testing with Docker

A docker-compose.yml is provided to test the production build with Static Web Server, which supports Brotli compression and proper cache headers:

bun run build
docker compose up -d
# Site available at http://localhost:8080

Project Structure

src/
├── assets/
│   ├── blog/              # Blog post images
│   ├── icons/             # SVG icons (optimized via SVGO)
│   ├── images/            # Site images (processed by Astro)
│   └── testimonials/      # Testimonial photos
├── components/            # Reusable UI components (.astro)
│   ├── mdx/               # Custom MDX components
│   └── seo/               # JSON-LD, meta tags, Open Graph
├── content/
│   └── blog/              # MDX blog posts (en/ and es/)
├── data/                  # Static data (blog, seo, technologies, companies)
├── i18n/                  # Translations and i18n utilities
├── integrations/          # Custom Astro integrations (sitemap hreflang)
├── layouts/               # Layout.astro
├── lib/                   # Utilities (formatters, theme, social-share)
├── pages/                 # File-based routes
│   ├── blog/              # Blog listing, pagination, and post pages
│   ├── es/                # Spanish locale routes
│   ├── og/                # Auto-generated OG images
│   ├── robots.txt.ts      # Dynamic robots.txt
│   └── rss.xml.ts         # RSS feed
├── sections/              # Page sections (Hero, Stack, Testimonials, Contact)
├── styles/                # Theme tokens (oklch), global CSS, utilities
├── types/                 # TypeScript definitions
└── views/                 # Page compositions (HomePage, BlogPage, BlogPostPage)
public/
├── companies/             # Company logo SVGs (light + dark variants)
├── favicons/              # Favicon files (SVG, PNG at multiple sizes)
├── fonts/                 # Self-hosted Inter Variable (subsetted woff2)
├── images/                # Static images
└── tech/                  # Technology icon SVGs

Architecture

Pages are thin routing files that delegate to Views, which compose Sections and Components. This avoids duplication between English and Spanish routes:

Page (/pages/index.astro) → View (HomePage.astro) → Sections (HeroSection, StackSection, ...)
Page (/pages/es/index.astro) → View (HomePage.astro) → same sections, different locale

Configuration

Theme

Colors use oklch for perceptual uniformity and P3 gamut support. Semantic tokens reference primitives and are defined in src/styles/theme.css:

  • Light theme on :root, dark theme on [data-theme="dark"]
  • Three-state toggle: auto (follows system), light, dark
  • Persisted in localStorage, applied via blocking <head> script

Internationalization

  • Locales: English (no URL prefix) and Spanish (/es/)
  • Translations: src/i18n/ui.ts with type-safe keys
  • Access: Astro.locals.t("key") and Astro.locals.lang
  • Blog translations linked via translationSlug frontmatter field

Lighthouse Thresholds

CI enforces minimum Lighthouse scores (configurable in lighthouserc.json):

  • Performance: 90%
  • Accessibility: 90%
  • Best Practices: 90%
  • SEO: 90%

Contributing

While this is a personal portfolio, bug reports and suggestions are welcome. Please open an issue to discuss any changes.

Commit Convention

This project uses Conventional Commits:

feat: new feature
fix: bug fix
refactor: code refactoring
chore: maintenance tasks
perf: performance improvements
docs: documentation changes
style: formatting changes

License

This project is licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.

CC BY-NC-ND 4.0

You are free to:

  • Share -- copy and redistribute the material in any medium or format

Under the following terms:

  • Attribution -- You must give appropriate credit, provide a link to the license, and indicate if changes were made
  • NonCommercial -- You may not use the material for commercial purposes
  • NoDerivatives -- If you remix, transform, or build upon the material, you may not distribute the modified material

About

My personal portfolio website built with Astro and Tailwind CSS v4

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors