Previously, HTML in short descriptions was being escaped and displayed as raw text instead of rendering properly. This happened because the safeHTML template function had been removed for security reasons. Changes: - Added safeHTML function back to template.FuncMap (template.go:53-55) - Updated three template locations to use safeHTML pipe: * Experience descriptions (cv-content.html:122) * Award descriptions (cv-content.html:180) * Project descriptions (cv-content.html:232) Security note: The safeHTML function is safe to use here because CV data comes from trusted YAML files controlled by the site owner, not user input. Clear documentation added to prevent misuse with untrusted content. Examples now rendering correctly: - Award: "Premio por excelencia en marketing B2B...con <a href=...>Clicplan</a>" - Projects: Links to Lidering, Jorpack, Delivery Bikes BCN, Mobbeel
CV Site - Go + HTMX
Modern, minimal curriculum vitae website for Juan Andrés Moreno Rubio built with Go and HTMX.
A professional, bilingual CV site with server-side PDF generation, HTMX interactivity, and a clean paper design aesthetic. Built as a personal portfolio project showcasing production-grade Go and HTMX development.
📌 Project Status
This is a personal portfolio project demonstrating production-grade Go and HTMX development.
Open Source: The code is MIT licensed and available for educational purposes. You're welcome to use it as a template or reference for your own projects. This repository is maintained as my personal CV site and may be modified without notice.
Contributions: This is a personal CV project and is feature-complete. I'm not seeking contributions, but you're welcome to use it as a template! If you find a critical security vulnerability, please follow the SECURITY.md process.
📑 Table of Contents
- Features
- Demo
- Quick Start
- Updating Your CV
- Export to PDF
- Key Technologies
- Documentation
- Deployment
- Customization
- Privacy & Analytics
- Contributing
- License
- Support
🚀 Features
- ✅ Bilingual Support - Spanish and English with instant switching (no page reload)
- ✅ Server-Side PDF Export - Professional PDF generation using chromedp (headless Chrome)
- ✅ Browser Print - Alternative print-friendly layout for manual PDF creation
- ✅ HTMX Dynamic Updates - Smooth UX without heavy JavaScript
- ✅ Paper Design - Professional CV on elegant white paper with gray background
- ✅ Responsive - Mobile, tablet, and desktop friendly
- ✅ JSON-Based Content - Easy to update without touching code
- ✅ AI Development Section - Showcases modern AI-assisted development skills
- ✅ Fast & Lightweight - Go backend with chromedp for PDF generation
- ✅ Privacy-Friendly Analytics - Self-hosted Matomo tracking (no third-party data sharing)
- ✅ Security Hardened - CSP headers, XSS protection, origin validation, rate limiting
- ✅ Production Ready - Systemd service, CI/CD workflows, deployment guides
- ✅ Developer Friendly - Hot reload, clear code structure, comprehensive Makefile
📸 Demo
🔗 Live Demo: https://juan.andres.morenorub.io/
Live Features:
- Single-page application with no page reloads
- Instant language switching (English ↔ Spanish)
- Professional PDF export with perfect font rendering
- Responsive design from mobile to desktop
- Clean paper aesthetic on gray background
- Print-friendly layouts
Note: This is my personal CV site. The code is open source for learning and reference purposes.
📋 Running Locally
If you want to explore the code or run it locally:
Prerequisites
- Go 1.21+ installed
- Chrome/Chromium (for PDF generation)
- Make (optional, for easier development)
Local Development
```bash
Download the code
git clone https://github.com/txemac/cv.git cd cv
Option 1: Using Make (recommended)
make dev
Option 2: Using Go directly
go run main.go
Option 3: Build and run binary
go build -o cv-server && ./cv-server ```
Access the Site
Open http://localhost:1999 in your browser
- 🇬🇧 English version: http://localhost:1999/?lang=en
- 🇪🇸 Spanish version: http://localhost:1999/?lang=es
Language switching is instant via HTMX - no page reload required!
📄 Updating Your CV
Edit JSON files in data/:
- English:
data/cv-en.json - Spanish:
data/cv-es.json
No code changes needed - just refresh browser!
🖨️ Export to PDF
Server-Side PDF Generation (Recommended)
- Click "Download as PDF" button in the action bar
- PDF is generated server-side using headless Chrome
- File downloads automatically:
CV-Juan-Andres-Moreno-Rubio-{lang}.pdf
Advantages:
- Consistent rendering across all platforms
- Perfect font rendering
- No browser compatibility issues
- Professional quality output
Browser Print (Alternative)
- Click "Print Friendly" button
- Use browser print dialog (Cmd/Ctrl + P)
- Select "Save as PDF"
Endpoints:
- English PDF:
http://localhost:1999/export/pdf?lang=en - Spanish PDF:
http://localhost:1999/export/pdf?lang=es
🎯 Key Technologies
- Backend: Go 1.21+ (stdlib
net/http, graceful shutdown) - PDF Generation: chromedp (headless Chrome automation)
- Frontend: HTMX 1.9.10 (hypermedia-driven interactions)
- Styling: Custom CSS with Quicksand font from Google Fonts
- Data: JSON files for easy content management
- Deployment: Systemd service, manual binary, GitHub Actions CI/CD
📚 Documentation
- DEPLOYMENT.md - Production deployment guides (VPS, cloud platforms, systemd)
- CUSTOMIZATION.md - Complete guide to customizing this template for your CV
- API.md - HTTP endpoints documentation and HTMX integration
- SECURITY.md - Security policy, vulnerability reporting, deployment considerations
- PRIVACY.md - Privacy policy and analytics disclosure
- LICENSE - MIT License
🚀 Deployment
This project is production-ready with multiple deployment options. See DEPLOYMENT.md for complete guides.
Systemd Service
```bash
Install as systemd service
make install-service
Update running service
make update-service ```
Manual Deployment
```bash
Build optimized binary
make build
Run in production mode
GO_ENV=production ./cv-server ```
Cloud Platforms
Deployment guides available for:
- Fly.io - Complete fly.toml configuration
- Google Cloud Run - Container deployment
- AWS ECS - Task definitions
- Railway / Render - Auto-deploy configs
See DEPLOYMENT.md for detailed instructions.
Environment Configuration: Copy .env.example to .env and customize:
PORT- Server port (default: 1999)GO_ENV- Environment (development/production)TEMPLATE_HOT_RELOAD- Enable template hot-reload in development
Security: See SECURITY.md for production deployment best practices.
🎨 Customization
Want to use this template for your own CV? See CUSTOMIZATION.md for the complete guide!
Quick Start Customization
- Update Content: Edit
data/cv-en.jsonanddata/cv-es.jsonwith your information - Customize Styling: Modify
static/css/main.css(colors, fonts, layout) - Adjust Templates: Edit files in
templates/directory - Add Sections: Update
internal/models/cv.goand JSON files
The CUSTOMIZATION.md guide includes:
- Complete JSON schema documentation
- Visual customization (colors, fonts, layout)
- Template modification examples
- Adding new languages
- Advanced customization patterns
🔒 Privacy & Analytics
This site uses self-hosted Matomo analytics to understand visitor behavior while respecting privacy.
What's tracked:
- Page views and language changes (EN/ES)
- Visitor country/city (approximate)
- Browser type and referring site
- Time on site and navigation patterns
What's NOT tracked:
- Personal identifying information
- Precise geolocation
- Cross-site behavior
- Any data is NOT shared with third parties
Your privacy:
- All data stored on my own server (
matomo.drolo.club) - Respects "Do Not Track" browser settings
- You can disable cookies in browser settings
See PRIVACY.md for complete details and opt-out instructions.
🤝 Using This Template
This project is open-source and available for you to use!
If you use this as a template, you MUST change:
- Matomo Site ID in
templates/index.html(line 644): ChangesetSiteIdfrom'4'to your own - Matomo Server URL in
templates/index.html(line 642): Changehttps://matomo.drolo.club/to your instance - CSP Headers in
internal/middleware/security.go: Update allowed domains for your Matomo server - OR remove Matomo entirely if you don't want analytics (see PRIVACY.md)
Other recommended changes:
- Update all personal information in
data/cv-en.jsonanddata/cv-es.json - Replace profile photo in
static/images/profile/ - Update
ALLOWED_ORIGINSin.envfor API protection - Customize colors and branding in
static/css/main.css
See CUSTOMIZATION.md for the complete customization guide.
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
TL;DR: You can use this template for your own CV site, modify it, and distribute it. Just keep the original copyright notice.
💬 Questions or Issues?
- Questions: Feel free to fork and modify - this is a template!
- Security Issues: See SECURITY.md for reporting security vulnerabilities
- Documentation: Check CUSTOMIZATION.md and DEPLOYMENT.md
🙏 Acknowledgments
- HTMX - For making hypermedia-driven applications enjoyable
- chromedp - For reliable headless Chrome automation
- Go Community - For excellent standard library and tooling
- AI Assistance - For accelerating development and documentation
Built with ❤️ using Go, HTMX, and AI assistance