diff --git a/.env.example b/.env.example index 7359138..8caece3 100644 --- a/.env.example +++ b/.env.example @@ -2,7 +2,7 @@ # Copy this file to .env and customize as needed # Server Configuration -PORT=8080 +PORT=1999 HOST=localhost GO_ENV=development diff --git a/ADDING-YOUR-PHOTO.md b/ADDING-YOUR-PHOTO.md index 0552177..589c56a 100644 --- a/ADDING-YOUR-PHOTO.md +++ b/ADDING-YOUR-PHOTO.md @@ -50,7 +50,7 @@ curl -o photo.jpg "URL_DE_TU_FOTO" ## ✅ Verificar 1. Reinicia el servidor: `./cv-server` -2. Abre http://localhost:8080 +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". diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index df90a8b..9526f0f 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -114,7 +114,7 @@ handler := middleware.Recovery( ```go cfg := config.Load() // Reads from env vars -cfg.Server.Port // Defaults to "8080" +cfg.Server.Port // Defaults to "1999" cfg.Template.HotReload // Auto-detects development mode ``` @@ -278,19 +278,19 @@ if r.Header.Get("HX-Request") != "" { ```bash # 1. Health check -curl http://localhost:8080/health +curl http://localhost:1999/health # 2. Happy path -curl "http://localhost:8080/?lang=en" +curl "http://localhost:1999/?lang=en" # 3. Error cases -curl "http://localhost:8080/?lang=invalid" # 400 Bad Request +curl "http://localhost:1999/?lang=invalid" # 400 Bad Request # 4. HTMX requests -curl -H "HX-Request: true" "http://localhost:8080/cv?lang=es" +curl -H "HX-Request: true" "http://localhost:1999/cv?lang=es" # 5. Security headers -curl -I http://localhost:8080/ +curl -I http://localhost:1999/ ``` ### Future: Automated Tests @@ -325,7 +325,7 @@ go build -o cv-server -ldflags="-s -w" . ```bash docker build -t cv-server . -docker run -p 8080:8080 cv-server +docker run -p 1999:1999 cv-server ``` ### 3. Cloud Platforms diff --git a/Dockerfile b/Dockerfile index 9b94982..4fdd05b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -32,15 +32,15 @@ COPY data data/ COPY static static/ # Expose port -EXPOSE 8080 +EXPOSE 1999 # Set production environment ENV GO_ENV=production -ENV PORT=8080 +ENV PORT=1999 # Health check HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ - CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1 + CMD wget --no-verbose --tries=1 --spider http://localhost:1999/health || exit 1 # Run the binary CMD ["./cv-server"] diff --git a/HTMX-PRODUCTION-RECOMMENDATIONS.md b/HTMX-PRODUCTION-RECOMMENDATIONS.md index b743d43..e1e0c8e 100644 --- a/HTMX-PRODUCTION-RECOMMENDATIONS.md +++ b/HTMX-PRODUCTION-RECOMMENDATIONS.md @@ -631,7 +631,7 @@ terser static/js/main.js -o static/js/main.min.js -c -m **Create `.env.production`:** ```env GO_ENV=production -PORT=8080 +PORT=1999 HOST=0.0.0.0 ALLOWED_ORIGINS=https://yoursite.com CACHE_CONTROL_MAX_AGE=86400 @@ -802,13 +802,13 @@ go run main.go ### Test HTMX endpoints ```bash # Test initial load -curl -s 'http://localhost:8080/?lang=en' | head -50 +curl -s 'http://localhost:1999/?lang=en' | head -50 # Test HTMX partial -curl -s 'http://localhost:8080/cv?lang=es' | head -50 +curl -s 'http://localhost:1999/cv?lang=es' | head -50 # Test performance -curl -o /dev/null -s -w "Time: %{time_total}s\n" 'http://localhost:8080/cv?lang=en' +curl -o /dev/null -s -w "Time: %{time_total}s\n" 'http://localhost:1999/cv?lang=en' ``` ### Run Lighthouse audit @@ -817,7 +817,7 @@ curl -o /dev/null -s -w "Time: %{time_total}s\n" 'http://localhost:8080/cv?lang= npm install -g lighthouse # Run audit -lighthouse http://localhost:8080/?lang=en --view +lighthouse http://localhost:1999/?lang=en --view ``` ### Test accessibility @@ -826,7 +826,7 @@ lighthouse http://localhost:8080/?lang=en --view npm install -g @axe-core/cli # Run audit -axe http://localhost:8080/?lang=en +axe http://localhost:1999/?lang=en ``` --- diff --git a/Makefile b/Makefile index a37953c..80c20a4 100644 --- a/Makefile +++ b/Makefile @@ -24,20 +24,20 @@ run: build test: @echo "🧪 Testing endpoints..." @echo "\n1. Health check:" - @curl -s http://localhost:8080/health | jq . + @curl -s http://localhost:1999/health | jq . @echo "\n2. English CV (first 50 chars):" - @curl -s "http://localhost:8080/?lang=en" | head -c 50 + @curl -s "http://localhost:1999/?lang=en" | head -c 50 @echo "\n\n3. Spanish CV content (first 50 chars):" - @curl -s "http://localhost:8080/cv?lang=es" | head -c 50 + @curl -s "http://localhost:1999/cv?lang=es" | head -c 50 @echo "\n\n4. Security headers:" - @curl -I http://localhost:8080/ 2>&1 | grep -E "^(X-|Content-Security)" + @curl -I http://localhost:1999/ 2>&1 | grep -E "^(X-|Content-Security)" @echo "\n✓ All tests complete" # Test error handling test-errors: @echo "🧪 Testing error handling..." @echo "\n1. Invalid language:" - @curl -i "http://localhost:8080/?lang=invalid" 2>&1 | head -15 + @curl -i "http://localhost:1999/?lang=invalid" 2>&1 | head -15 @echo "\n2. Error logging check" @echo "✓ Error tests complete" @@ -55,7 +55,7 @@ docker-build: docker-run: @echo "🐳 Running Docker container..." - docker run -p 8080:8080 cv-server:latest + docker run -p 1999:1999 cv-server:latest # Help help: diff --git a/QUICK-START-IMPROVEMENTS.md b/QUICK-START-IMPROVEMENTS.md index 964bf26..c825d46 100644 --- a/QUICK-START-IMPROVEMENTS.md +++ b/QUICK-START-IMPROVEMENTS.md @@ -401,7 +401,7 @@ func main() { ) // ... start server with handler - log.Fatal(http.ListenAndServe(":8080", handler)) + log.Fatal(http.ListenAndServe(":1999", handler)) } ``` @@ -436,7 +436,7 @@ go run main.go ### 4. Test Security Headers ```bash -curl -I http://localhost:8080/ +curl -I http://localhost:1999/ # Should see security headers in response ``` @@ -503,7 +503,7 @@ curl -I http://localhost:8080/ ``` 4. **Validate with tools:** - - Lighthouse: `lighthouse http://localhost:8080` + - Lighthouse: `lighthouse http://localhost:1999` - WAVE: Install browser extension - axe DevTools: Install browser extension diff --git a/README.md b/README.md index 02622d1..b4d41b6 100644 --- a/README.md +++ b/README.md @@ -26,10 +26,10 @@ go build -o cv-server && ./cv-server \`\`\` -Open **http://localhost:8080** +Open **http://localhost:1999** -- 🇬🇧 English: http://localhost:8080/?lang=en -- 🇪🇸 Spanish: http://localhost:8080/?lang=es +- 🇬🇧 English: http://localhost:1999/?lang=en +- 🇪🇸 Spanish: http://localhost:1999/?lang=es ## 📄 Updating Your CV diff --git a/internal/config/config.go b/internal/config/config.go index e16ebb6..37a7683 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -23,9 +23,9 @@ type ServerConfig struct { // TemplateConfig contains template-specific settings type TemplateConfig struct { - Dir string + Dir string PartialsDir string - HotReload bool + HotReload bool } // DataConfig contains data directory settings @@ -37,15 +37,15 @@ type DataConfig struct { func Load() *Config { return &Config{ Server: ServerConfig{ - Port: getEnv("PORT", "8080"), + Port: getEnv("PORT", "1999"), Host: getEnv("HOST", "localhost"), ReadTimeout: getEnvAsInt("READ_TIMEOUT", 15), WriteTimeout: getEnvAsInt("WRITE_TIMEOUT", 15), }, Template: TemplateConfig{ - Dir: getEnv("TEMPLATE_DIR", "templates"), + Dir: getEnv("TEMPLATE_DIR", "templates"), PartialsDir: getEnv("PARTIALS_DIR", "templates/partials"), - HotReload: getEnvAsBool("TEMPLATE_HOT_RELOAD", isDevelopment()), + HotReload: getEnvAsBool("TEMPLATE_HOT_RELOAD", isDevelopment()), }, Data: DataConfig{ Dir: getEnv("DATA_DIR", "data"), diff --git a/static/css/main.css b/static/css/main.css index 330ec84..e200d66 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -1,17 +1,14 @@ -/* Minimal CV Design - A4 Page Simulation */ +/* CV Design - Original Style Recreation */ :root { --bg-gray: #525659; + --sidebar-gray: #d9d9d9; + --black-bar: #2b2b2b; --paper-white: #ffffff; --text-dark: #2d2d2d; --text-gray: #555555; --accent-blue: #0066cc; --border-gray: #dddddd; - - /* A4 dimensions */ - --a4-width: 210mm; - --a4-height: 297mm; - --page-padding: 20mm; } * { @@ -21,7 +18,7 @@ } body { - font-family: 'Inter', Arial, sans-serif; + font-family: Arial, Helvetica, sans-serif; background-color: var(--bg-gray); color: var(--text-dark); line-height: 1.6; @@ -36,21 +33,23 @@ a:hover { text-decoration: underline; } -/* Action Bar */ +/* Single Black Top Bar */ .action-bar { - background: white; - border-bottom: 1px solid var(--border-gray); + background: var(--black-bar); + color: white; position: sticky; top: 0; z-index: 100; + box-shadow: 0 2px 5px rgba(0,0,0,0.3); } .action-bar-content { - max-width: var(--a4-width); - margin: 0 auto; + max-width: 100%; + margin: 0; padding: 1rem 2rem; - display: flex; - justify-content: space-between; + display: grid; + grid-template-columns: auto 1fr auto; + gap: 2rem; align-items: center; } @@ -61,35 +60,64 @@ a:hover { .lang-btn { padding: 0.4rem 1rem; - border: 1px solid var(--border-gray); - background: white; + border: 1px solid rgba(255,255,255,0.3); + background: transparent; + color: white; border-radius: 4px; cursor: pointer; font-size: 0.9rem; } .lang-btn:hover { - background: #f5f5f5; + background: rgba(255,255,255,0.1); } .lang-btn.active { - background: var(--accent-blue); - color: white; - border-color: var(--accent-blue); + background: rgba(255,255,255,0.2); + border-color: white; } .export-btn { padding: 0.4rem 1.2rem; - background: var(--accent-blue); + background: transparent; color: white; - border: none; + border: 1px solid rgba(255,255,255,0.3); border-radius: 4px; cursor: pointer; font-size: 0.9rem; } .export-btn:hover { - background: #0052a3; + background: rgba(255,255,255,0.1); +} + +/* Title badges in center of bar */ +.title-badges { + display: flex; + justify-content: center; + align-items: center; + flex-wrap: wrap; + gap: 0.8rem; +} + +.title-badge { + font-size: 0.75rem; + letter-spacing: 1px; + font-weight: 400; + color: white; + white-space: nowrap; +} + +.title-separator { + color: rgba(255,255,255,0.4); + font-size: 0.75rem; +} + +/* Action buttons on right */ +.action-buttons { + display: flex; + gap: 0.5rem; + align-items: center; } /* Loading Indicator */ @@ -103,7 +131,7 @@ a:hover { .loader { border: 2px solid #f3f3f3; - border-top: 2px solid var(--accent-blue); + border-top: 2px solid white; border-radius: 50%; width: 20px; height: 20px; @@ -115,27 +143,26 @@ a:hover { 100% { transform: rotate(360deg); } } -/* A4 Page Container */ +/* Main CV Container */ .cv-container { width: 100%; - max-width: 100%; - margin: 0; - padding: 2rem 0; + max-width: 1200px; + margin: 0 auto; + padding: 0; display: flex; flex-direction: column; - align-items: center; - gap: 2rem; } -/* A4 Paper - Exact dimensions */ +/* CV Paper - Two-column layout with shadow */ .cv-paper { - width: var(--a4-width); - min-height: var(--a4-height); + width: 100%; background: var(--paper-white); - padding: var(--page-padding); - box-shadow: 0 2px 10px rgba(0,0,0,0.1); - margin: 0 auto; + box-shadow: 0 0 30px rgba(0,0,0,0.4); + margin: 0; position: relative; + display: grid; + grid-template-columns: 300px 1fr; + min-height: 100vh; } /* Page break helpers */ @@ -149,31 +176,55 @@ a:hover { break-inside: avoid; } -/* Header - Photo on right, inline with text */ -.cv-header { - display: flex; - justify-content: space-between; - align-items: flex-start; - gap: 2rem; - border-bottom: 2px solid var(--text-dark); - padding-bottom: 1.5rem; +/* Sidebar - Left column */ +.cv-sidebar { + background: var(--sidebar-gray); + padding: 2rem 1.5rem; + font-size: 0.9rem; +} + +.sidebar-section { margin-bottom: 2rem; } -.cv-header-left { - flex: 1; +.sidebar-title { + font-size: 1rem; + font-weight: 700; + margin-bottom: 0.8rem; + color: var(--text-dark); } -.cv-header-right { - flex-shrink: 0; +.sidebar-content { + line-height: 1.8; +} + +.skill-item { + margin-bottom: 0.3rem; + color: var(--text-dark); +} + +/* Main Content - Right column */ +.cv-main { + background: var(--paper-white); + padding: 2rem 2.5rem; +} + +/* Header with photo and name */ +.cv-header { + margin-bottom: 2rem; +} + +.cv-header-content { + display: flex; + align-items: flex-start; + gap: 1.5rem; } .cv-photo { - width: 100px; - height: 100px; - border-radius: 50%; + width: 150px; + height: 200px; + flex-shrink: 0; overflow: hidden; - border: 3px solid var(--border-gray); } .cv-photo img { @@ -183,230 +234,117 @@ a:hover { } .cv-name { - font-size: 2rem; - font-weight: 700; - margin-bottom: 0.5rem; -} - -.cv-title { - font-size: 1.1rem; + font-size: 2.5rem; font-weight: 400; - color: var(--text-gray); - margin-bottom: 1rem; + margin-bottom: 0.5rem; + color: var(--text-dark); } -.cv-contact { - display: grid; - grid-template-columns: repeat(2, 1fr); - gap: 0.4rem; - font-size: 0.85rem; +.cv-experience-years { + font-size: 1rem; color: var(--text-gray); + margin: 0; } /* Sections */ .cv-section { - margin-bottom: 1.5rem; + margin-bottom: 2rem; page-break-inside: avoid; } .section-title { - font-size: 1.2rem; + font-size: 1.1rem; font-weight: 700; margin-bottom: 1rem; - padding-bottom: 0.3rem; - border-bottom: 1px solid var(--border-gray); + color: var(--text-dark); } .summary-text { line-height: 1.6; text-align: justify; - font-size: 0.9rem; + font-size: 0.95rem; + color: var(--text-dark); } -/* Experience - with separators */ +/* Experience */ .experience-item { - margin-bottom: 1.2rem; - padding-bottom: 1.2rem; - border-bottom: 1px solid var(--border-gray); + margin-bottom: 1.5rem; page-break-inside: avoid; } -.experience-item:last-child { - border-bottom: none; +.experience-header { + margin-bottom: 0.6rem; } -.experience-header { +.experience-title-line { display: flex; justify-content: space-between; - margin-bottom: 0.6rem; + align-items: baseline; gap: 1rem; - align-items: center; -} - -.company-logo { - width: 35px; - height: 35px; - flex-shrink: 0; - display: flex; - align-items: center; - justify-content: center; - margin-right: 0.75rem; -} - -.company-logo img { - max-width: 100%; - max-height: 100%; - object-fit: contain; -} - -.experience-title { - flex: 1; + flex-wrap: wrap; } .position { font-size: 1rem; font-weight: 600; - margin-bottom: 0.2rem; -} - -.company { - color: var(--text-gray); - font-size: 0.85rem; + margin: 0; + color: var(--text-dark); } .experience-period { color: var(--text-gray); - font-size: 0.8rem; - white-space: nowrap; + font-size: 0.85rem; font-style: italic; } .short-desc { - color: var(--text-gray); - font-size: 0.85rem; - line-height: 1.5; - margin-bottom: 0.6rem; + color: var(--text-dark); + font-size: 0.9rem; + line-height: 1.6; + margin-top: 0.5rem; } .responsibilities { list-style: none; - margin-bottom: 0.6rem; + margin-top: 0.5rem; + padding-left: 0; } .responsibilities li { - padding-left: 1rem; - margin-bottom: 0.3rem; + padding-left: 1.2rem; + margin-bottom: 0.4rem; position: relative; - font-size: 0.85rem; + font-size: 0.9rem; + color: var(--text-dark); + line-height: 1.5; } .responsibilities li:before { content: "•"; position: absolute; left: 0; - font-weight: bold; -} - -.technologies { - font-size: 0.8rem; color: var(--text-gray); - font-style: italic; } /* Education */ .education-item { - margin-bottom: 0.8rem; - font-size: 0.9rem; -} - -.education-header { - display: flex; - justify-content: space-between; - margin-bottom: 0.3rem; -} - -.degree { - font-size: 0.95rem; - font-weight: 600; -} - -.education-period { - color: var(--text-gray); - font-size: 0.8rem; - font-style: italic; -} - -.institution { - color: var(--text-gray); - font-size: 0.85rem; -} - -/* Skills */ -.skill-block { - margin-bottom: 0.8rem; -} - -.skill-title { - font-size: 0.95rem; - font-weight: 600; - margin-bottom: 0.3rem; -} - -.skill-list { - color: var(--text-gray); - font-size: 0.85rem; -} - -/* Projects */ -.project-item { margin-bottom: 1rem; font-size: 0.9rem; + line-height: 1.6; + color: var(--text-dark); } -.project-header { - display: flex; - justify-content: space-between; - margin-bottom: 0.3rem; -} - -.project-name { - font-size: 1rem; - font-weight: 600; -} - -.project-period { - color: var(--text-gray); - font-size: 0.8rem; - font-style: italic; -} - -.project-role { - color: var(--text-gray); - font-size: 0.85rem; - margin-bottom: 0.3rem; -} - -.project-description { - margin-bottom: 0.3rem; - font-size: 0.85rem; -} - -/* Certifications & Awards */ -.cert-item, -.award-item { - margin-bottom: 0.4rem; - font-size: 0.85rem; -} /* Languages */ .languages-list { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 0.5rem; + display: flex; + flex-wrap: wrap; + gap: 1.5rem; } .language-item { - font-size: 0.85rem; + font-size: 0.9rem; + color: var(--text-dark); } /* Footer */ @@ -417,30 +355,6 @@ footer { font-size: 0.85rem; } -/* CV Length Toggle */ -.cv-length-toggle { - display: flex; - gap: 0.5rem; -} - -.length-btn { - padding: 0.4rem 1rem; - border: 1px solid var(--border-gray); - background: white; - border-radius: 4px; - cursor: pointer; - font-size: 0.9rem; -} - -.length-btn:hover { - background: #f5f5f5; -} - -.length-btn.active { - background: var(--accent-blue); - color: white; - border-color: var(--accent-blue); -} /* Short CV - Hide detailed content */ .cv-short .long-only { @@ -468,57 +382,47 @@ footer { /* Responsive - tablet/mobile */ @media (max-width: 900px) { .cv-paper { - width: 100%; - min-height: auto; - padding: 15mm; + grid-template-columns: 1fr; box-shadow: none; } - - .cv-container { - padding: 1rem; + + .cv-sidebar { + padding: 1.5rem 1rem; } - + + .cv-main { + padding: 1.5rem 1rem; + } + .cv-name { font-size: 1.8rem; } - - .cv-header { - flex-direction: column; - align-items: center; - text-align: center; - } - + .cv-photo { - order: -1; - margin-bottom: 1rem; + width: 120px; + height: 150px; } - - .cv-contact { - grid-template-columns: 1fr; - text-align: center; - } - - .experience-header, - .project-header, - .education-header { - flex-direction: column; - gap: 0.25rem; - } - - .company-logo { - display: none; - } - + .action-bar-content { - flex-wrap: wrap; + grid-template-columns: 1fr; + gap: 1rem; + padding: 1rem; + } + + .language-toggle, + .title-badges, + .action-buttons { justify-content: center; } - - .cv-length-toggle { - order: 1; - width: 100%; - justify-content: center; - margin-top: 0.5rem; + + .title-badges { + order: -1; + } + + .experience-title-line { + flex-direction: column; + align-items: flex-start; + gap: 0.25rem; } } diff --git a/templates/cv-content.html b/templates/cv-content.html index 7c7d98c..b8919e4 100644 --- a/templates/cv-content.html +++ b/templates/cv-content.html @@ -1,153 +1,120 @@ - -
-
-
-

{{.CV.Personal.Name}}

-

{{.CV.Personal.Title}}

-
-
-
{{.CV.Personal.Location}}
- -
{{.CV.Personal.Phone}}
- - -
-
-
-
- {{.CV.Personal.Name}} -
-
-
- - -
-

{{if eq .Lang "es"}}Resumen{{else}}Summary{{end}}

-

{{.CV.Summary}}

-
- - -
-

{{if eq .Lang "es"}}Experiencia Laboral{{else}}Work History{{end}}

- - {{range .CV.Experience}} -
-
- {{if .CompanyLogo}} - - {{end}} -
-

{{.Position}}

-
{{.Company}}, {{.Location}}
-
-
- {{.StartDate}} - {{if .Current}}{{if eq $.Lang "es"}}Presente{{else}}Present{{end}}{{else}}{{.EndDate}}{{end}} -
-
- - {{if .ShortDescription}} -

{{.ShortDescription}}

- {{end}} - - - - {{if .Technologies}} -
- {{range $index, $tech := .Technologies}}{{if $index}}, {{end}}{{$tech}}{{end}} + +
- {{end}} -
+ {{end}} + - -
-

{{if eq .Lang "es"}}Formación{{else}}Education{{end}}

- - {{range .CV.Education}} -
-
-

{{.Degree}}

-
{{.StartDate}} - {{.EndDate}}
+ + + + + + +
+ +
+
+
+ {{.CV.Personal.Name}} +
+
+

{{.CV.Personal.Name}}

+

{{if eq .Lang "es"}}20 años de experiencia{{else}}20 years of experience{{end}}

+
-
{{.Institution}}, {{.Location}}
- {{end}} -
- -
-

{{if eq .Lang "es"}}Competencias{{else}}Skills{{end}}

+ +
+

{{if eq .Lang "es"}}Resumen{{else}}Training{{end}}

+

{{.CV.Summary}}

+
- {{range .CV.Skills.Technical}} -
-

{{.Category}}

-

- {{range $index, $item := .Items}}{{if $index}}, {{end}}{{$item}}{{end}} + +

+

{{if eq .Lang "es"}}Formación{{else}}Training{{end}}

+ {{range .CV.Education}} +
+ {{.Degree}} ({{.StartDate}}-{{.EndDate}}) {{if eq $.Lang "es"}}obtenido de{{else}}obtained from the{{end}} {{.Institution}} ({{.Location}}) +
+ {{end}} +
+ + +
+

{{if eq .Lang "es"}}Competencias{{else}}Skills{{end}}

+

+ {{if eq .Lang "es"}} + Amplio conocimiento en entornos web, tanto J2EE como PHP. Experto en tecnologías front-end, aunque con considerable experiencia en sistemas back-end. Receptivo al aprendizaje de nuevas tecnologías, y con una gran dosis de creatividad. Capacidad de analizar problemas y aportar soluciones específicas adaptadas a cada tipo de cliente. Me gusta trabajar tanto solo como en grupos. + {{else}} + Extensive knowledge in web environments, both J2EE and PHP. Expert in front-end technologies, although with considerable experience in back-end systems. Receptive to learning new technologies, and with a large dose of creativity. Ability to analyze problems and provide specific solutions tailored to each client type. I like to work both alone and in groups. + {{end}}

-
- {{end}} -
+ - -{{if .CV.Projects}} -
-

{{if eq .Lang "es"}}Proyectos{{else}}Projects{{end}}

+ +
+

{{if eq .Lang "es"}}Experiencia{{else}}Experience{{end}}

- {{range .CV.Projects}} -
-
-

{{.Name}}

-
{{.Period}}
-
-
{{.Role}}
-

{{.Description}}

-
- {{end}} -
-{{end}} + {{range .CV.Experience}} +
+
+
+

{{.Position}} / {{if eq $.Lang "es"}}Analista Programador{{else}}Analyst Programmer{{end}}

+ {{.StartDate}} / {{if .Current}}{{if eq $.Lang "es"}}presente{{else}}now{{end}}{{else}}{{.EndDate}}{{end}} - ({{.Location}}) +
+
- -{{if .CV.Certifications}} -
-

{{if eq .Lang "es"}}Certificaciones{{else}}Certifications{{end}}

+ {{if .ShortDescription}} +

{{.ShortDescription}}

+ {{end}} - {{range .CV.Certifications}} -
- {{.Name}} - {{.Issuer}} ({{.Date}}) -
- {{end}} -
-{{end}} - - -{{if .CV.Awards}} -
-

{{if eq .Lang "es"}}Premios{{else}}Awards{{end}}

- - {{range .CV.Awards}} -
- {{.Title}} - {{.Issuer}} ({{.Date}}) -
- {{end}} -
-{{end}} - - -
-

{{if eq .Lang "es"}}Idiomas{{else}}Languages{{end}}

- -
- {{range .CV.Languages}} -
- {{.Language}}: {{.Proficiency}} +
+
    + {{range .Responsibilities}} +
  • {{.}}
  • + {{end}} +
+
{{end}} -
-
+
+ + +
+

{{if eq .Lang "es"}}Idiomas{{else}}Languages{{end}}

+
+ {{range .CV.Languages}} +
+ {{.Language}}: {{.Proficiency}} +
+ {{end}} +
+
+ diff --git a/templates/index.html b/templates/index.html index 4771c9a..86b30cb 100644 --- a/templates/index.html +++ b/templates/index.html @@ -20,9 +20,10 @@ - +
+
-
- - + +
+ ANALYST PROGRAMMER + | + NODEJS + REACTJS DEVELOPER + | + WEB DEVELOPER + | + JAVA DEVELOPER + | + PHP DEVELOPER
-
+ +
+