BREAKING CHANGE: API parameter renamed from 'extended' to 'long' ## Breaking Change: Terminology Standardization Renamed 'extended' to 'long' across entire codebase for consistency: **Backend (Go):** - internal/handlers/cv.go (7 locations) - Migration logic to auto-convert 'extended' → 'long' cookies - API validation now rejects 'extended', requires 'long' - Toggle state logic updated - internal/handlers/pdf_test.go (17 occurrences) - Test function renamed: TestExportPDF_ExtendedWithSkills → TestExportPDF_LongWithSkills - All test cases, parameters, and expected filenames updated - internal/pdf/generator.go (2 comment updates) **Frontend:** - PDF-EXPORT-FEATURE.md (3 occurrences) - doc/3-API.md (parameter documentation) - doc/7-CUSTOMIZATION.md (examples updated) - templates/partials/modals/pdf-modal.html (button text, URLs) - static/js/main.js (migration logic) - static/hyperscript/toggles._hs (toggle logic) - tests/mjs/24-pdf-download-params.test.mjs (test expectations) - tests/mjs/test-preference-migration.test.mjs (NEW) - tests/mjs/verify-migration.test.mjs (NEW) **PDFs Renamed:** - cv-extended-with_skills-jamr-2025-en.pdf → cv-long-with_skills-jamr-2025-en.pdf - cv-extended-with_skills-jamr-2025-es.pdf → cv-long-with_skills-jamr-2025-es.pdf **Migration:** Automatic cookie migration from 'extended' → 'long' for seamless UX ## New Feature: Compact Sidebar Fonts Reduces page count for short CV with skills from 6 → 5 pages: **Implementation:** - Location: internal/pdf/generator.go (lines 154-215) - Cookie detection: `cookies["cv-length"] == "short"` - Font reduction: 2-6% (0.94-0.98em) - very subtle - Only activates for: `length=short` + `version=with_skills` - Long version: Always uses full-size fonts **Impact:** - Page count: 6 pages → 5 pages (16.7% reduction) - Readability: Maintained - fonts remain professional - Design philosophy: Subtle, natural content flow **Testing:** - New test: TestPDFGenerator_CompactSidebarFonts - Comprehensive coverage of cookie detection and PDF generation - Manual verification: 5-page PDF with compact but readable fonts **Documentation:** - doc/LONG-PDF-GENERATION.md (NEW, 13 KB) - Complete feature documentation - Implementation details with code examples - Font size breakdown table - Testing and troubleshooting guides - Compact sidebar fonts section (comprehensive) **Files Changed:** - 11 modified (backend + frontend + docs) - 5 new files (2 PDFs, 1 doc, 2 tests) - 2 files renamed (PDFs) **Tests:** All Go tests passing, API validation verified, PDF generation tested
13 KiB
Long PDF Generation with Skills Sidebars
Overview
The long PDF generation feature creates a comprehensive CV that includes technical skills sidebars positioned on the left and right sides, while hiding UI elements for a clean, print-optimized output.
Page counts:
- Long version (9 pages) - Full-size fonts, comprehensive content
- Short version with skills (5 pages) - Compact sidebar fonts for reduced page count
Key Features
- 9-page layout with optimal content density
- 25% sidebars for skills/competencies display
- 2-column approach matching web layout (no wasted space)
- Page breaks between left and right sidebar sections
- Hidden mobile UI elements (accordion headers, navigation)
- Print media CSS for compact, professional typography
Architecture
PDF Generation Flow
User clicks "Long CV (9 pages)" in PDF Modal
↓
Frontend: `/export/pdf?lang=es&length=long&icons=show&version=with_skills`
↓
Backend: GenerateFromURLWithOptions(url, cookies, RenderModeScreen)
↓
Chromedp: Navigate to URL with cookies
↓
CSS Injection: Override print.css + Show sidebars + 2-column layout
↓
PDF Generation: PrintToPDF with A4 dimensions
↓
Output: 9-page PDF with sidebars (or 5 pages with compact fonts for short version)
Critical Components
1. PDF Generator (internal/pdf/generator.go)
RenderMode:
RenderModePrint- Clean version (hides sidebars)RenderModeScreen- Long version (shows sidebars)
CSS Injection Strategy:
// Override parent width constraints (full A4 width)
'.cv-page, .cv-paper, .cv-container { max-width: 100% !important; ... }'
// Show sidebars (override print.css hiding)
'.cv-sidebar, .cv-sidebar-left, .cv-sidebar-right { display: block !important; }'
// Hide mobile UI elements
'.sidebar-accordion-header { display: none !important; }'
// Force page break before page 2
'.page-2 { page-break-before: always !important; break-before: page !important; }'
// 2-column layouts (no wasted space)
'.page-1 .page-content { grid-template-columns: 25% 75% !important; }'
'.page-2 .page-content { grid-template-columns: 75% 25% !important; }'
2. HTML Structure (templates/cv-content.html)
Page 1: Left sidebar + Main content
<div class="cv-page page-1">
<div class="page-content">
<aside class="cv-sidebar cv-sidebar-left">...</aside>
<main class="cv-main">...</main>
</div>
</div>
Page 2: Main content + Right sidebar
<div class="cv-page page-2">
<div class="page-content">
<main class="cv-main">...</main>
<aside class="cv-sidebar cv-sidebar-right">...</aside>
</div>
</div>
3. Frontend Integration (templates/partials/modals/pdf-modal.html)
PDF Modal Options:
- Short CV (4 pages) -
version=clean - Long CV (9 pages) -
version=with_skills← This feature - Short CV with skills (5 pages) -
length=short&version=with_skillswith compact fonts - Current View - Uses localStorage settings
Why 2-Column Layout?
❌ Previous Approach (3-column - WRONG)
.page-1, .page-2: 25% | 50% | 25% /* Always 3 columns */
- Page 1 had empty right column (25% wasted)
- Page 2 had empty left column (25% wasted)
- Result: 10-19 pages
✅ Current Approach (2-column - CORRECT)
.page-1: 25% | 75% /* Left sidebar + Main, NO right space */
.page-2: 75% | 25% /* Main + Right sidebar, NO left space */
- No wasted space on either page
- Matches web's actual layout exactly
- Result: 9 pages
Configuration
Sidebar Width Tuning
Sidebar width affects page count:
| Width | Layout | Pages | Notes |
|---|---|---|---|
| 18% | 18% | 82% | 9 pages | Too narrow |
| 20% | 20% | 80% | 8 pages | Minimal sidebars |
| 25% | 25% | 75% | 9 pages | ✅ Current (optimal balance) |
| 30% | 30% | 70% | 10+ pages | Too wide |
Current Setting: 25% sidebars (internal/pdf/generator.go:176,181)
Adjusting Sidebar Width
To change sidebar width, update two lines in internal/pdf/generator.go:
// Page 1: Left sidebar (XX%) + Main (YY%) - NO right space
'.page-1 .page-content { ' +
'grid-template-columns: XX% YY% !important; ' +
'} ' +
// Page 2: Main (YY%) + Right sidebar (XX%) - NO left space
'.page-2 .page-content { ' +
'grid-template-columns: YY% XX% !important; ' +
'} ' +
Where XX + YY = 100
Print Media CSS
The extended PDF uses @media print from static/css/08-contexts/_print.css for:
- Compact fonts and spacing
- Hiding UI chrome (navigation, buttons, footer)
- Professional typography
Overridden in PDF:
- Sidebar hiding (
.cv-sidebar { display: none }→display: block !important) - Accordion headers (
.sidebar-accordion-header { display: none !important })
Testing
Unit Tests
The long PDF feature has comprehensive test coverage in internal/handlers/pdf_test.go:
Test Functions:
TestExportPDF_LongWithSkills- Tests long PDF with multiple language/icon combinationsTestPDFGenerator_RenderModes- Tests bothRenderModePrintandRenderModeScreenTestExportPDF_SkillsSidebarFeatures- Tests specific skills sidebar features:- Version parameter validation (
clean,with_skills) - PDF modal integration URLs
- Frontend button parameter correctness
- Version parameter validation (
TestPDFGenerator_CompactSidebarFonts- Tests compact font feature for short version
Run the tests:
go test ./internal/handlers -v -run TestExportPDF
Integration Testing
Check page count and PDF generation:
# Download long PDF (9 pages with sidebars)
curl "http://localhost:1999/export/pdf?lang=es&length=long&icons=show&version=with_skills" -o test-long.pdf
# Download short PDF with skills (5 pages with compact fonts)
curl "http://localhost:1999/export/pdf?lang=es&length=short&icons=show&version=with_skills" -o test-short-skills.pdf
# Download short PDF clean (4 pages, no sidebars)
curl "http://localhost:1999/export/pdf?lang=es&length=short&icons=show&version=clean" -o test-short.pdf
# Verify page counts
pdfinfo test-long.pdf | grep Pages
# Expected: Pages: 9
pdfinfo test-short-skills.pdf | grep Pages
# Expected: Pages: 5
pdfinfo test-short.pdf | grep Pages
# Expected: Pages: 4
Manual Verification
Long CV (9 pages):
- Open http://localhost:1999 in browser
- Click "Descargar PDF" button
- Select "CV Largo (9 páginas)" / "Long CV (9 pages)"
- Click "Descargar PDF"
- Verify downloaded PDF has:
- 9 pages total
- 25% sidebars on left (page 1) and right (page 2+)
- Full-size fonts in sidebars
- No "Competencias Técnicas" accordion header visible
- Page break between page 1 and page 2
- Skills content displayed in sidebars
Short CV with skills (5 pages with compact fonts):
- Toggle to short view and with_skills theme
- Download PDF
- Verify:
- 5 pages total
- Compact sidebar fonts (0.94-0.98em)
- All content fits naturally without overflow
- Maintained readability
API Endpoint
URL: /export/pdf
Query Parameters:
lang- Language (es,en)length- CV length (short,long)icons- Show icons (show,hide)version- Layout version (clean,with_skills)
Examples:
# Long CV with skills (9 pages, full-size fonts)
GET /export/pdf?lang=es&length=long&icons=show&version=with_skills
# Short CV with skills (5 pages, compact sidebar fonts)
GET /export/pdf?lang=es&length=short&icons=show&version=with_skills
# Short CV clean (4 pages, no sidebars)
GET /export/pdf?lang=es&length=short&icons=show&version=clean
Troubleshooting
Issue: Sidebars not showing
Solution: Check RenderModeScreen is being used (not RenderModePrint)
Issue: Wrong page count
Solution:
- Check sidebar width percentage (should be 25%)
- Verify CSS injection is working
- Check for browser console errors
Issue: Accordion header visible
Solution: Ensure .sidebar-accordion-header { display: none !important; } in CSS injection
Issue: No page break between pages
Solution: Verify .page-2 { page-break-before: always !important; } is applied
Compact Sidebar Fonts Feature
Overview
The compact sidebar fonts feature automatically reduces sidebar font sizes by 2-6% only for short CVs with skills (length=short&version=with_skills), reducing page count from 6 pages to 5 pages while maintaining excellent readability.
Impact:
- Page count reduction: 6 pages → 5 pages (16.7% reduction)
- Font size reduction: 2-6% (very subtle, 0.94-0.98em)
- Readability: Maintained - fonts remain professional and readable
- Only for short version: Long version uses full-size fonts
When It Activates
The feature automatically activates when both conditions are met:
length=short(detected viacv-lengthcookie)version=with_skills(RenderModeScreen with sidebars)
Does NOT activate for:
- Long CVs (
length=long) - always use full-size fonts - Clean version (
version=clean) - no sidebars shown - Short clean version - no sidebars to compact
Implementation
Location: internal/pdf/generator.go (lines 154-215)
Cookie Detection:
// Check if this is a short version (to apply compact sidebar fonts)
// The length parameter is passed as a cookie, not in the URL
isShortVersion := cookies["cv-length"] == "short"
CSS Injection (only when isShortVersion == true):
compactFontCSS := ""
if isShortVersion {
compactFontCSS = ` +
// Compact sidebar fonts (SHORT VERSION ONLY) - very subtle reduction
'.cv-sidebar * { font-size: 0.96em !important; line-height: 1.4 !important; } ' +
'.cv-sidebar h3 { font-size: 0.98em !important; margin: 0.4em 0 !important; } ' +
'.cv-sidebar h4 { font-size: 0.96em !important; margin: 0.35em 0 !important; } ' +
'.cv-sidebar p, .cv-sidebar li { font-size: 0.94em !important; line-height: 1.4 !important; } ' +
'.cv-sidebar ul, .cv-sidebar ol { margin: 0.4em 0 0.4em 1.2em !important; } ' +
'.cv-sidebar li { margin-bottom: 0.25em !important; } ' +
'.cv-sidebar section { margin-bottom: 0.8em !important; } '`
}
Font Size Breakdown
| Element | Full-Size (Long) | Compact (Short) | Reduction |
|---|---|---|---|
| General text | 1.0em | 0.96em | 4% |
| H3 headings | 1.0em | 0.98em | 2% |
| H4 headings | 1.0em | 0.96em | 4% |
| Paragraphs & lists | 1.0em | 0.94em | 6% |
Line height: Consistent 1.4 for improved readability
Design Philosophy
Why subtle reduction?
- Readability first: 2-6% reduction is barely noticeable
- Professional appearance: No "squeezed" or cramped feel
- Natural flow: Content reflows organically, not forced
- Consistent UX: Main content uses full-size fonts
Why only short version?
- Short CV has less content → compact fonts sufficient
- Long CV needs maximum readability for extensive content
- Consistent with "short = concise, long = comprehensive" semantics
Testing
Test function: TestPDFGenerator_CompactSidebarFonts in internal/handlers/pdf_test.go
Test coverage:
- Cookie-based detection (
cv-length=shortvscv-length=long) - PDF generation with compact fonts
- Version parameter validation (
with_skillsvsclean) - Page count verification (5 pages for short with skills)
Run tests:
go test ./internal/handlers -v -run TestPDFGenerator_CompactSidebarFonts
Manual Verification
- Navigate to http://localhost:1999
- Toggle to short view (localStorage:
cv-length=short) - Toggle to with_skills theme (localStorage:
cv-theme=defaultorwith_skills) - Download PDF
- Verify:
- 5 pages total (not 6)
- Sidebar fonts slightly smaller than main content
- Still professional and readable
- No content overflow or truncation
Compare with long version:
- Toggle to long view (
cv-length=long) - Download PDF
- Verify:
- 9 pages total
- Sidebar fonts same size as short version main content
- Full-size fonts throughout
Troubleshooting
Issue: Short PDF still has 6 pages
Solution:
- Verify
cv-lengthcookie is set toshort(check browser DevTools) - Ensure
isShortVersiondetection works in generator.go:156 - Check CSS injection is applied (add debug logging)
Issue: Fonts too small or hard to read
Solution:
- Adjust font size percentages in generator.go:206-214
- Increase from 0.94em to 0.96em for paragraphs
- Test with actual content to verify readability
Issue: Long version also has compact fonts
Solution:
- Check cookie detection logic - must be
cookies["cv-length"] == "short" - Verify compactFontCSS is only appended when
isShortVersion == true - Ensure long version passes
cv-length=longcookie
Future Improvements
- Make sidebar width configurable via query parameter
- Add option to customize page break positioning
- Support for different paper sizes (Letter, Legal)
- Transparent background option
- Custom padding/margin configuration
Related Files
internal/pdf/generator.go- PDF generation logictemplates/cv-content.html- HTML structuretemplates/partials/modals/pdf-modal.html- Frontend UIstatic/css/08-contexts/_print.css- Print media CSSinternal/handlers/pdf.go- HTTP handlertests/mjs/24-pdf-download-params.test.mjs- Frontend tests