From 9a2343a71e723926c658e8931716b56394cae530 Mon Sep 17 00:00:00 2001 From: juanatsap Date: Mon, 4 May 2026 13:42:40 +0100 Subject: [PATCH] feat: GitHub stars badge on open-source projects via shields.io MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - New openSource field in project model distinguishes OS from private - shields.io badge shows live star count for open-source projects - SoundInbox marked as NOT open source (no badge, no stars) - Immich Photo Manager, Cmux Resurrect, Gotify Commander, CDC Starter Kit → open source - Stars badge hidden in print view --- data/cv-en.json | 4 ++++ data/cv-es.json | 4 ++++ internal/models/cv.go | 1 + internal/models/cv/cv.go | 1 + internal/templates/template.go | 9 +++++++++ static/css/03-components/_cv-section.css | 13 +++++++++++++ static/css/print.css | 4 ++++ templates/partials/sections/projects.html | 1 + 8 files changed, 37 insertions(+) diff --git a/data/cv-en.json b/data/cv-en.json index 69c80ed..d9ebe12 100644 --- a/data/cv-en.json +++ b/data/cv-en.json @@ -546,6 +546,7 @@ "projectDesc": "AI-Powered Photo Library MCP Server", "url": "https://drolosoft.com/immich-photo-manager.html?lang=en", "gitRepoUrl": "https://github.com/drolosoft/immich-photo-manager", + "openSource": true, "projectLogo": "immich-photo-manager.png", "location": "Online", "startDate": "2026", @@ -573,6 +574,7 @@ "projectDesc": "Terminal Session Persistence Tool", "url": "https://drolosoft.com/cmux-resurrect.html?lang=en", "gitRepoUrl": "https://github.com/drolosoft/cmux-resurrect", + "openSource": true, "projectLogo": "cmux-resurrect.png", "location": "Online", "startDate": "2026", @@ -600,6 +602,7 @@ "projectDesc": "Bidirectional Server Control Plugin", "url": "https://github.com/drolosoft/gotify-commander", "gitRepoUrl": "https://github.com/drolosoft/gotify-commander", + "openSource": true, "projectLogo": "gotify-commander.png", "location": "Online", "startDate": "2026", @@ -726,6 +729,7 @@ "projectDesc": "SAP Customer Data Cloud Demo", "url": "https://gigyademo.com/cdc-starter-kit/", "gitRepoUrl": "https://github.com/gigya/cdc-starter-kit", + "openSource": true, "projectLogo": "sap.png", "logoIndex": 8, "location": "Online", diff --git a/data/cv-es.json b/data/cv-es.json index 202b561..215ef3d 100644 --- a/data/cv-es.json +++ b/data/cv-es.json @@ -546,6 +546,7 @@ "projectDesc": "Servidor MCP para Gestión de Fotos con IA", "url": "https://drolosoft.com/immich-photo-manager.html?lang=es", "gitRepoUrl": "https://github.com/drolosoft/immich-photo-manager", + "openSource": true, "projectLogo": "immich-photo-manager.png", "location": "Online", "startDate": "2026", @@ -573,6 +574,7 @@ "projectDesc": "Herramienta de Persistencia de Sesiones de Terminal", "url": "https://drolosoft.com/cmux-resurrect.html?lang=es", "gitRepoUrl": "https://github.com/drolosoft/cmux-resurrect", + "openSource": true, "projectLogo": "cmux-resurrect.png", "location": "Online", "startDate": "2026", @@ -600,6 +602,7 @@ "projectDesc": "Plugin Bidireccional de Control de Servidores", "url": "https://github.com/drolosoft/gotify-commander", "gitRepoUrl": "https://github.com/drolosoft/gotify-commander", + "openSource": true, "projectLogo": "gotify-commander.png", "location": "Online", "startDate": "2026", @@ -726,6 +729,7 @@ "projectDesc": "Demo de SAP Customer Data Cloud", "url": "https://gigyademo.com/cdc-starter-kit/", "gitRepoUrl": "https://github.com/gigya/cdc-starter-kit", + "openSource": true, "projectLogo": "sap.png", "logoIndex": 8, "location": "Online", diff --git a/internal/models/cv.go b/internal/models/cv.go index a9d2a2d..78729e5 100644 --- a/internal/models/cv.go +++ b/internal/models/cv.go @@ -100,6 +100,7 @@ type Project struct { ProjectLogo string `json:"projectLogo,omitempty"` // Optional logo filename LogoIndex *int `json:"logoIndex,omitempty"` // Sprite sheet index (nil means no sprite) GitRepoUrl string `json:"gitRepoUrl,omitempty"` // Optional git repository URL for dynamic dates + OpenSource bool `json:"openSource,omitempty"` // True if project is open source (shows stars badge) Location string `json:"location"` StartDate string `json:"startDate,omitempty"` // Optional static start date Current bool `json:"current"` diff --git a/internal/models/cv/cv.go b/internal/models/cv/cv.go index 7c71c9a..572f446 100644 --- a/internal/models/cv/cv.go +++ b/internal/models/cv/cv.go @@ -105,6 +105,7 @@ type Project struct { ProjectLogo string `json:"projectLogo,omitempty"` // Optional logo filename LogoIndex *int `json:"logoIndex,omitempty"` // Sprite sheet index (nil means no sprite) GitRepoUrl string `json:"gitRepoUrl,omitempty"` // Optional git repository URL for dynamic dates + OpenSource bool `json:"openSource,omitempty"` // True if project is open source (shows stars badge) Location string `json:"location"` StartDate string `json:"startDate,omitempty"` // Optional static start date Current bool `json:"current"` diff --git a/internal/templates/template.go b/internal/templates/template.go index 78698dc..5ef8ab3 100644 --- a/internal/templates/template.go +++ b/internal/templates/template.go @@ -68,6 +68,15 @@ func (m *Manager) loadTemplatesLocked() error { "replaceDrolosoft": func(s string) string { return strings.Replace(s, "drolosoft", `drolosoft`, 1) }, + // githubRepo extracts "owner/repo" from a GitHub URL + "githubRepo": func(url string) string { + url = strings.TrimSuffix(url, "/") + parts := strings.Split(url, "github.com/") + if len(parts) == 2 { + return parts[1] + } + return "" + }, // dict creates a map from key-value pairs for passing to sub-templates "dict": func(values ...interface{}) (map[string]interface{}, error) { if len(values)%2 != 0 { diff --git a/static/css/03-components/_cv-section.css b/static/css/03-components/_cv-section.css index f5396a0..f1f69a9 100644 --- a/static/css/03-components/_cv-section.css +++ b/static/css/03-components/_cv-section.css @@ -194,6 +194,19 @@ font-size: 1.2em; } +.stars-badge { + display: inline-flex; + align-items: center; + margin-left: 0.3em; + vertical-align: middle; + text-decoration: none; +} + +.stars-badge img { + height: 18px; + vertical-align: middle; +} + .maintained-badge { display: inline-block; background: #3498db; diff --git a/static/css/print.css b/static/css/print.css index be13984..d4a5a45 100644 --- a/static/css/print.css +++ b/static/css/print.css @@ -105,6 +105,10 @@ text-decoration: none !important; } + .stars-badge { + display: none !important; + } + /* =================================== REMOVE ALL SHADOWS & BORDERS (Nuclear Option) =================================== */ diff --git a/templates/partials/sections/projects.html b/templates/partials/sections/projects.html index f85b8b8..ac75d64 100644 --- a/templates/partials/sections/projects.html +++ b/templates/partials/sections/projects.html @@ -32,6 +32,7 @@ {{if .Current}}LIVE{{end}} {{if .GitRepoUrl}}GitHub{{end}} + {{if and .OpenSource .GitRepoUrl}}GitHub stars{{end}} {{if .MaintainedBy}}{{$.UI.Sections.MaintainedBy}} {{.MaintainedBy}}{{end}}
{{if .StartDate}}{{.StartDate}}{{if .Current}}{{if .DynamicDate}} / {{.DynamicDate}}{{else}} / {{$.UI.Sections.Present}}{{end}}{{end}}{{end}} - ({{.Location}})