diff --git a/ADDING-YOUR-PHOTO.md b/ADDING-YOUR-PHOTO.md deleted file mode 100644 index 589c56a..0000000 --- a/ADDING-YOUR-PHOTO.md +++ /dev/null @@ -1,72 +0,0 @@ -# CΓ³mo AΓ±adir tu Foto al CV - -## πŸ“Έ Paso 1: Prepara tu Foto - -1. **Busca una foto profesional** (preferiblemente tipo LinkedIn) -2. **Formato recomendado**: JPG o PNG -3. **TamaΓ±o**: Al menos 300x300 pΓ­xeles (cuadrada es mejor) -4. **Calidad**: Fondo neutro, buena iluminaciΓ³n - -## πŸ“ Paso 2: Guarda la Foto - -Guarda tu foto en: -``` -static/images/profile/photo.jpg -``` - -Puedes usar cualquiera de estos nombres: -- `photo.jpg` βœ… (recomendado) -- `photo.png` (cambiar en template) -- `profile.jpg` (cambiar en template) - -## πŸ”„ Paso 3: Actualizar (si usas otro nombre) - -Si tu foto se llama diferente a `photo.jpg`, edita `templates/cv-content.html`: - -```html - - - - - -``` - -## πŸ–ΌοΈ Descargar desde LinkedIn - -### OpciΓ³n 1: Manualmente -1. Abre tu perfil de LinkedIn -2. Click derecho en tu foto β†’ "Guardar imagen como..." -3. GuΓ‘rdala como `photo.jpg` en `static/images/profile/` - -### OpciΓ³n 2: Desde tu sitio actual -Si ya tienes tu foto en https://juan.andres.morenoyrubio.com: - -```bash -cd static/images/profile -# Abre el inspector del navegador, busca tu foto, y copia la URL -curl -o photo.jpg "URL_DE_TU_FOTO" -``` - -## βœ… Verificar - -1. Reinicia el servidor: `./cv-server` -2. Abre http://localhost:1999 -3. DeberΓ­as ver tu foto en la esquina superior izquierda - -Si no funciona, verΓ‘s un placeholder gris con el texto "Add your photo". - -## 🎨 Ajustar el TamaΓ±o (Opcional) - -La foto se muestra como un cΓ­rculo de 120px. Para cambiar el tamaΓ±o, edita `static/css/main.css`: - -```css -.cv-photo { - width: 150px; /* Cambiar aquΓ­ */ - height: 150px; /* Y aquΓ­ */ - border-radius: 50%; -} -``` - ---- - -**Nota**: El template ya incluye un fallback automΓ‘tico al placeholder si la foto no existe, asΓ­ que el sitio funcionarΓ‘ con o sin foto. diff --git a/DEPLOYMENT_SETUP.md b/DEPLOYMENT_SETUP.md deleted file mode 100644 index 414bf68..0000000 --- a/DEPLOYMENT_SETUP.md +++ /dev/null @@ -1,320 +0,0 @@ -# Deployment Setup Guide - -This guide will help you configure GitHub Actions for automatic deployment of your CV site. - -## Overview - -The deployment system is now fully configured with: -- βœ… GitHub Actions workflows (`.github/workflows/`) -- βœ… Deployment scripts (`scripts/`) -- βœ… Systemd service configuration (`config/systemd/cv.service`) -- βœ… Updated Makefile with CI/CD targets - -## Required GitHub Secrets - -To enable automatic deployment, you need to configure these secrets in your GitHub repository: - -Go to: **Settings β†’ Secrets and variables β†’ Actions β†’ New repository secret** - -### Essential Secrets - -| Secret Name | Value | Description | -|------------|-------|-------------| -| `SSH_PRIVATE_KEY` | Your private SSH key | Used to connect to the production server | -| `SSH_HOST` | `localhost` or your server IP | Production server hostname | -| `SSH_USER` | `txeo` | SSH username for deployment | -| `SSH_PORT` | `22` (default) | SSH port (optional if using default) | - -### Optional Secrets - -| Secret Name | Description | -|------------|-------------| -| `SLACK_WEBHOOK` | Slack webhook URL for deployment notifications | - -## Setting Up SSH Key for GitHub Actions - -Since this machine is both the development and production server, you need to set up SSH access for GitHub Actions to deploy here. - -### Option 1: Deploy to localhost (Recommended for same-machine setup) - -If GitHub Actions will run on the same machine, you can use localhost: - -```bash -# Generate a deployment key (reusable for all projects) -ssh-keygen -t ed25519 -C "github-actions-deployment" -f ~/.ssh/github-deploy -N "" - -# Add the public key to authorized_keys -cat ~/.ssh/github-deploy.pub >> ~/.ssh/authorized_keys -chmod 600 ~/.ssh/authorized_keys - -# Copy the private key to add to GitHub Secrets (use this for ALL projects) -cat ~/.ssh/github-deploy -# Copy the entire output (including BEGIN and END lines) -``` - -**GitHub Secrets Configuration:** -- `SSH_PRIVATE_KEY`: (paste the private key output from above) -- `SSH_HOST`: `localhost` or `127.0.0.1` -- `SSH_USER`: `txeo` -- `SSH_PORT`: `22` - -### Option 2: Deploy from GitHub hosted runners - -If using GitHub's hosted runners to deploy to this server: - -```bash -# Generate a deployment key (reusable for all projects) -ssh-keygen -t ed25519 -C "github-actions-deployment" -f ~/.ssh/github-deploy -N "" - -# Add the public key to authorized_keys -cat ~/.ssh/github-deploy.pub >> ~/.ssh/authorized_keys - -# Get your public IP address -curl ifconfig.me - -# Copy the private key (use this for ALL projects) -cat ~/.ssh/github-deploy -``` - -**GitHub Secrets Configuration:** -- `SSH_PRIVATE_KEY`: (paste the private key output) -- `SSH_HOST`: (your public IP from `curl ifconfig.me`) -- `SSH_USER`: `txeo` -- `SSH_PORT`: `22` - -## Reusing Secrets Across Multiple Projects - -**Important**: If you have multiple projects deploying to the same server, use **one shared SSH key** for all of them. - -### Why One Shared Key? - -βœ… **Advantages:** -- **Simpler management** - One key to rotate/update instead of multiple -- **Same access level** - All projects deploy as the same user anyway -- **Easier setup** - Generate once, reuse everywhere -- **Standard practice** - CI/CD systems typically use one deploy key per server - -❌ **You don't need separate keys because:** -- All projects deploy to the same server -- All projects use the same user account (`txeo`) -- Separation is already handled by different deployment paths and services - -### Shared Secrets (Same for All 3+ Projects) - -Copy these exact same values to all your project repositories: -- `SSH_PRIVATE_KEY` - The `~/.ssh/github-deploy` key you generated once -- `SSH_HOST` - Same server (localhost or your IP) -- `SSH_USER` - Same user (`txeo`) -- `SSH_PORT` - Same SSH port (`22`) -- `SLACK_WEBHOOK` - Same notification channel (optional) - -### Project-Specific Configuration - -Only change these in each project's `.github/workflows/deploy.yml` (in the `env` section): - -| Project | APP_NAME | SERVICE_NAME | DEPLOY_PATH | PORT | -|---------|----------|--------------|-------------|------| -| CV Site | cv-server | cv | /home/txeo/Git/yo/cv | 1999 | -| Project 2 | project2-server | project2 | /home/txeo/Git/yo/project2 | 2000 | -| Project 3 | project3-server | project3 | /home/txeo/Git/yo/project3 | 2001 | - -### Setup Process - -1. **Generate SSH key once** on the server: - ```bash - ssh-keygen -t ed25519 -C "github-actions-deployment" -f ~/.ssh/github-deploy -N "" - cat ~/.ssh/github-deploy.pub >> ~/.ssh/authorized_keys - ``` - -2. **Copy the key** for use in all projects: - ```bash - cat ~/.ssh/github-deploy - ``` - -3. **Add to each repository's GitHub Secrets** (same values): - - Repository 1 (cv) β†’ Add secrets - - Repository 2 (project2) β†’ Add **same** secrets - - Repository 3 (project3) β†’ Add **same** secrets - -4. **Customize each workflow** by editing only the `env` section in `deploy.yml` - -## Service Configuration - -The systemd service configuration has been created at: -- **Template**: `config/systemd/cv.service` -- **Active service**: `/etc/systemd/system/cv.service` - -### Update the Active Service (if needed) - -If you want to use the new service template with better security settings: - -```bash -# Update the systemd service -make update-service - -# Or manually: -sudo cp config/systemd/cv.service /etc/systemd/system/ -sudo systemctl daemon-reload -sudo systemctl restart cv -sudo systemctl status cv -``` - -## Testing the Deployment Locally - -Before pushing to GitHub, you can test the deployment scripts locally: - -```bash -# Build the binary -make ci-build - -# Test the deployment script -cd build -tar -czf cv-server-test.tar.gz cv-server -cd .. -mv build/cv-server-test.tar.gz ./cv-server.new -chmod +x scripts/deploy.sh -./scripts/deploy.sh cv-server cv - -# Check service status -systemctl status cv - -# Test health check -make health-check -``` - -## Deployment Workflow - -Once configured, the deployment works automatically: - -1. **Push to main branch** β†’ Triggers deployment -2. **Run tests** β†’ Ensures code quality -3. **Build binary** β†’ Creates production binary -4. **Deploy to server** β†’ Uploads and installs new version -5. **Health check** β†’ Verifies deployment success -6. **Send notification** β†’ (if Slack webhook configured) - -### Manual Deployment - -You can also trigger deployment manually: - -1. Go to **Actions** tab in GitHub -2. Select **Deploy CV Site to Production** -3. Click **Run workflow** -4. Choose options (e.g., skip tests) -5. Click **Run workflow** - -## Rollback - -If a deployment fails or you need to rollback: - -```bash -# View available backups -./scripts/rollback.sh cv-server cv - -# Rollback to the most recent version -./scripts/rollback.sh cv-server cv latest - -# Rollback to specific version (e.g., version #2) -./scripts/rollback.sh cv-server cv 2 -``` - -## Monitoring - -### Check Service Status - -```bash -# Service status -systemctl status cv - -# View logs -journalctl -u cv -f - -# View recent logs -journalctl -u cv -n 50 --no-pager -``` - -### Check Application Health - -```bash -# Local health check -curl http://localhost:1999/health - -# Public health check -curl https://juan.andres.morenorub.io/health - -# Or use the make target -make health-check -``` - -## File Structure - -``` -cv/ -β”œβ”€β”€ .github/ -β”‚ └── workflows/ -β”‚ β”œβ”€β”€ deploy.yml # Main deployment workflow -β”‚ └── test.yml # Testing workflow -β”œβ”€β”€ scripts/ -β”‚ β”œβ”€β”€ deploy.sh # Deployment script -β”‚ β”œβ”€β”€ healthcheck.sh # Health check script -β”‚ └── rollback.sh # Rollback script -β”œβ”€β”€ config/ -β”‚ └── systemd/ -β”‚ └── cv.service # Systemd service template -β”œβ”€β”€ backups/ # (created during deployment) -β”‚ └── cv-server.* # Binary backups -└── Makefile # Build and deployment targets -``` - -## Troubleshooting - -### Deployment Fails with SSH Error - -```bash -# Test SSH connection -ssh -p 22 txeo@localhost "echo 'SSH works'" - -# Check SSH key permissions -ls -la ~/.ssh/github-deploy -# Should show: -rw------- (600) -``` - -### Service Won't Start - -```bash -# Check service logs -sudo journalctl -u cv -n 50 - -# Test binary manually -./cv-server - -# Check port availability -sudo netstat -tlnp | grep 1999 -``` - -### Health Check Fails - -```bash -# Check if service is running -systemctl is-active cv - -# Test health endpoint -curl -v http://localhost:1999/health - -# Check firewall -sudo ufw status -``` - -## Next Steps - -1. **Add GitHub Secrets** as documented above -2. **Push to main branch** to trigger first deployment -3. **Monitor the deployment** in GitHub Actions tab -4. **Verify deployment** by checking https://juan.andres.morenorub.io - -## Support - -For issues or questions: -- Check GitHub Actions logs in the **Actions** tab -- Review systemd logs: `journalctl -u cv -f` -- Review the main deployment guide: `GITHUB_ACTIONS_DEPLOYMENT_GUIDE.md` diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 4fdd05b..0000000 --- a/Dockerfile +++ /dev/null @@ -1,46 +0,0 @@ -# Build stage -FROM golang:1.25-alpine AS builder - -WORKDIR /app - -# Copy go mod files -COPY go.mod ./ - -# Download dependencies -RUN go mod download - -# Copy source code -COPY . . - -# Build binary -RUN CGO_ENABLED=0 GOOS=linux go build -o cv-server -ldflags="-s -w" . - -# Runtime stage -FROM alpine:latest - -# Install CA certificates for HTTPS -RUN apk --no-cache add ca-certificates - -WORKDIR /root/ - -# Copy binary from builder -COPY --from=builder /app/cv-server . - -# Copy application files -COPY templates templates/ -COPY data data/ -COPY static static/ - -# Expose port -EXPOSE 1999 - -# Set production environment -ENV GO_ENV=production -ENV PORT=1999 - -# Health check -HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ - CMD wget --no-verbose --tries=1 --spider http://localhost:1999/health || exit 1 - -# Run the binary -CMD ["./cv-server"] diff --git a/ERROR-HANDLING-IMPLEMENTED.md b/ERROR-HANDLING-IMPLEMENTED.md deleted file mode 100644 index 25a13fe..0000000 --- a/ERROR-HANDLING-IMPLEMENTED.md +++ /dev/null @@ -1,507 +0,0 @@ -# Error Handling Implementation βœ… - -**Date:** October 30, 2025 -**Time Required:** 1 hour -**Status:** Fully implemented and tested - ---- - -## 🎯 Overview - -Comprehensive error handling system with user-friendly error toasts, bilingual messages, and smooth UX for all failure scenarios. - ---- - -## βœ… What Was Implemented - -### 1. **Error Toast Component** (HTML) - -**Location:** `templates/index.html` (before ``) - -```html - - -``` - -**Features:** -- βœ… Accessible (`role="alert"`, `aria-live="assertive"`) -- βœ… Visual warning icon -- βœ… Dismissible with close button -- βœ… Auto-hides after 5 seconds -- βœ… Hidden from print output - ---- - -### 2. **Error Toast Styling** (CSS) - -**Location:** `static/css/main.css` - -```css -/* Error Toast */ -.error-toast { - position: fixed; - bottom: 2rem; - right: 2rem; - background: #fee2e2; - color: #dc2626; - padding: 1rem 1.5rem; - border-radius: 8px; - border-left: 4px solid #dc2626; - box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); - animation: slideIn 0.3s ease-out; - z-index: 1000; -} - -@keyframes slideIn { - from { - transform: translateX(120%); - opacity: 0; - } - to { - transform: translateX(0); - opacity: 1; - } -} -``` - -**Features:** -- βœ… Fixed position (bottom-right) -- βœ… Smooth slide-in animation (300ms) -- βœ… Professional error styling (red theme) -- βœ… Responsive on mobile (full-width) -- βœ… High z-index (always on top) - ---- - -### 3. **HTMX Error Handlers** (JavaScript) - -**Location:** `templates/index.html` (in ` -``` - -**File:** `/Users/txeo/Git/yo/cv/static/css/main.css` - -**Add at the end of the file:** - -```css -/* Error Toast */ -.error-toast { - position: fixed; - bottom: 2rem; - right: 2rem; - background: #fee2e2; - color: #dc2626; - padding: 1rem 1.5rem; - border-radius: 8px; - border-left: 4px solid #dc2626; - box-shadow: var(--shadow-lg); - display: flex; - align-items: center; - gap: 1rem; - max-width: 400px; - z-index: 1000; - animation: slideIn 0.2s ease-out; -} - -@keyframes slideIn { - from { - transform: translateX(100%); - opacity: 0; - } - to { - transform: translateX(0); - opacity: 1; - } -} - -.error-toast button { - background: none; - border: none; - font-size: 1.5rem; - color: #dc2626; - cursor: pointer; - padding: 0; - width: 24px; - height: 24px; - display: flex; - align-items: center; - justify-content: center; - transition: opacity 0.2s; -} - -.error-toast button:hover { - opacity: 0.7; -} - -/* Smooth transitions */ -.cv-paper { - transition: opacity 200ms; -} - -.cv-paper.htmx-swapping { - opacity: 0; -} -``` - ---- - -### 4. HTMX Configuration (5 minutes) - -**File:** `/Users/txeo/Git/yo/cv/templates/index.html` - -**Add in `` section after meta viewport:** - -```html - - -``` - ---- - -## ⏱️ 1-Hour Enhancement: SEO & Meta Tags - -**File:** `/Users/txeo/Git/yo/cv/templates/index.html` - -**Replace entire `` section:** - -```html - - - - - - - - - - - - - - - - - - - - - - {{.CV.Personal.Name}} - Curriculum Vitae - - - - - - - - - - - - - - - - - - - -``` - ---- - -## πŸ”’ 2-Hour Enhancement: Security Headers - -**Create file:** `/Users/txeo/Git/yo/cv/middleware/security.go` - -```go -package middleware - -import ( - "net/http" - "os" -) - -// SecurityHeaders adds security headers to all responses -func SecurityHeaders(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // Prevent clickjacking - w.Header().Set("X-Frame-Options", "DENY") - w.Header().Set("X-Content-Type-Options", "nosniff") - w.Header().Set("X-XSS-Protection", "1; mode=block") - - // Content Security Policy - csp := "default-src 'self'; " + - "script-src 'self' 'unsafe-inline' https://unpkg.com; " + - "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; " + - "font-src 'self' https://fonts.gstatic.com; " + - "img-src 'self' data:; " + - "connect-src 'self'" - w.Header().Set("Content-Security-Policy", csp) - - // Referrer Policy - w.Header().Set("Referrer-Policy", "strict-origin-when-cross-origin") - - // Permissions Policy - w.Header().Set("Permissions-Policy", "geolocation=(), microphone=(), camera=()") - - // HTTPS-only in production - if os.Getenv("GO_ENV") == "production" { - w.Header().Set("Strict-Transport-Security", "max-age=31536000; includeSubDomains") - } - - next.ServeHTTP(w, r) - }) -} - -// CORS allows cross-origin requests (if needed) -func CORS(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - origin := os.Getenv("ALLOWED_ORIGIN") - if origin == "" { - origin = "*" // Development only - } - - w.Header().Set("Access-Control-Allow-Origin", origin) - w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS") - w.Header().Set("Access-Control-Allow-Headers", "Content-Type") - - if r.Method == "OPTIONS" { - w.WriteHeader(http.StatusOK) - return - } - - next.ServeHTTP(w, r) - }) -} -``` - -**Update file:** `/Users/txeo/Git/yo/cv/main.go` - -**Add imports:** -```go -import ( - // ... existing imports - "yourproject/middleware" // Update with your module path -) -``` - -**Update main() function to use middleware:** -```go -func main() { - // ... existing setup code - - // Apply middleware - http.Handle("/", middleware.SecurityHeaders(http.HandlerFunc(handleHome))) - http.Handle("/cv", middleware.SecurityHeaders(http.HandlerFunc(handleCV))) - http.Handle("/export/pdf", middleware.SecurityHeaders(http.HandlerFunc(handlePDFExport))) - - // ... rest of main() -} -``` - -**Or create a middleware chain:** -```go -func main() { - // ... existing setup code - - // Create base handler - mux := http.NewServeMux() - mux.HandleFunc("/", handleHome) - mux.HandleFunc("/cv", handleCV) - mux.HandleFunc("/export/pdf", handlePDFExport) - - // Static files - mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static")))) - - // Apply middleware chain - handler := middleware.SecurityHeaders( - middleware.CORS(mux), - ) - - // ... start server with handler - log.Fatal(http.ListenAndServe(":1999", handler)) -} -``` - ---- - -## βœ… Testing Your Improvements - -### 1. Test Browser History -```bash -# Start server -go run main.go - -# Open browser, click language buttons -# Press browser back button - should work! -``` - -### 2. Test Error Handling -```bash -# Stop the server -# In browser, click language button -# Should see error toast! -``` - -### 3. Test Accessibility -```bash -# Use keyboard only: -# Tab to language buttons -# Press Enter to activate -# Tab to export button -# Press Enter to print -``` - -### 4. Test Security Headers -```bash -curl -I http://localhost:1999/ -# Should see security headers in response -``` - ---- - -## πŸ“Š Before vs After - -### Before (Current) -- ❌ No browser history on language change -- ❌ No error handling -- ❌ Limited accessibility -- ⚠️ Missing SEO meta tags -- ⚠️ No security headers -- βœ… Excellent performance - -### After (30 minutes) -- βœ… Browser history works -- βœ… Error handling with toast -- βœ… ARIA attributes for accessibility -- βœ… Smooth transitions -- βœ… HTMX timeout configured -- βœ… Still excellent performance - -### After (2 hours) -- βœ… All of the above PLUS: -- βœ… Complete SEO meta tags -- βœ… Structured data (JSON-LD) -- βœ… Security headers -- βœ… SRI for external scripts -- βœ… Production-ready! - ---- - -## 🎯 Next Steps - -1. **Apply 30-minute fixes** ← Start here! -2. **Test in browser** -3. **Apply 1-hour SEO enhancements** -4. **Apply 2-hour security enhancements** -5. **Run Lighthouse audit** -6. **Deploy to production!** - ---- - -## πŸ’‘ Pro Tips - -1. **Backup first:** - ```bash - cp templates/index.html templates/index.html.backup - cp static/css/main.css static/css/main.css.backup - ``` - -2. **Test incrementally:** - - Apply one fix at a time - - Test in browser - - Commit to git - - Move to next fix - -3. **Use the enhanced templates:** - ```bash - # I've already created fully enhanced versions: - mv templates/index-improved.html templates/index.html - mv static/css/main-enhanced.css static/css/main.css - ``` - -4. **Validate with tools:** - - Lighthouse: `lighthouse http://localhost:1999` - - WAVE: Install browser extension - - axe DevTools: Install browser extension - ---- - -## πŸš€ Ready to Go! - -These quick fixes will take you from **85% β†’ 95% production-ready** in just 30 minutes! - -For the complete guide, see: `HTMX-PRODUCTION-RECOMMENDATIONS.md` diff --git a/QUICK-WINS-APPLIED.md b/QUICK-WINS-APPLIED.md deleted file mode 100644 index 77ce151..0000000 --- a/QUICK-WINS-APPLIED.md +++ /dev/null @@ -1,279 +0,0 @@ -# Quick Wins Applied βœ… - -**Date:** October 30, 2025 -**Time Required:** 30 minutes -**Status:** All improvements successfully implemented and tested - ---- - -## βœ… What Was Improved - -### 1. Browser History Management (5 minutes) -**Problem:** Language changes didn't update browser URL, back button didn't work -**Solution:** Added `hx-push-url` to language buttons - -```html - -