From b05e98ea1edd3f41653c1083181844e04965f8b7 Mon Sep 17 00:00:00 2001 From: Pihkaal Date: Thu, 27 Nov 2025 18:37:59 +0100 Subject: [PATCH] feat(projects): add technology badges on the previews --- .../Projects/TopScreen/Previews.vue | 57 +++++++++++++++++++ app/stores/projects.ts | 2 + content.config.ts | 1 + content/projects/biobleud/index.md | 1 + content/projects/lbf-bot/index.md | 1 + content/projects/lilou-cat/index.md | 1 + content/projects/pihkaal-me/index.md | 1 + content/projects/s3pweb/index.md | 1 + content/projects/simple-qr/index.md | 1 + content/projects/tlock/index.md | 1 + 10 files changed, 67 insertions(+) diff --git a/app/components/Projects/TopScreen/Previews.vue b/app/components/Projects/TopScreen/Previews.vue index be215c8..8db475b 100644 --- a/app/components/Projects/TopScreen/Previews.vue +++ b/app/components/Projects/TopScreen/Previews.vue @@ -13,6 +13,53 @@ const getBounds = () => ({ endIndex: Math.min(store.currentProject + 1 + 1, store.projects.length), }); +const TECH_BADGES: Record = { + nuxt: { label: "Nuxt", color: "#00DC82" }, + typescript: { label: "TypeScript", color: "#3178C6" }, + rust: { label: "Rust", color: "#CE422B" }, + html: { label: "HTML", color: "#E34C26" }, + go: { label: "Go", color: "#00ADD8" }, + node: { label: "Node", color: "#339933" }, + stenciljs: { label: "Stencil", color: "#5851FF" }, + jira: { label: "Jira", color: "#0052CC" }, + confluence: { label: "Confluence", color: "#2DA2E5" }, + vba: { label: "VBA", color: "#5D2B90" }, +}; + +const BADGE_PADDING = 2; +const BADGE_SPACING = 2; +const BADGE_MARGIN = 1; +const BADGE_HEIGHT = 11; + +const drawTechBadges = ( + ctx: CanvasRenderingContext2D, + technologies: string[], + x: number, + y: number, +): void => { + ctx.font = "7px NDS7"; + + let currentX = x; + for (let i = technologies.length - 1; i >= 0; i--) { + const badge = TECH_BADGES[technologies[i]?.toLowerCase() ?? ""]; + if (!badge) throw new Error(`Unknown technology: ${technologies[i]}`); + + const { actualBoundingBoxRight: textWidth } = ctx.measureText(badge.label); + const badgeWidth = textWidth + BADGE_PADDING * 2; + + currentX -= badgeWidth; + + ctx.fillStyle = badge.color; + ctx.fillRect(currentX, y, badgeWidth, BADGE_HEIGHT); + + ctx.fillStyle = "#FFFFFF"; + ctx.textBaseline = "top"; + ctx.fillText(badge.label, currentX + BADGE_PADDING, y + 2); + + currentX -= BADGE_SPACING; + } +}; + useRender((ctx) => { const project = store.projects[store.currentProject]; if (!project) return; @@ -39,6 +86,7 @@ useRender((ctx) => { ctx.fillStyle = "#000000"; ctx.fillRect(-1, -1, preview.width + 2, preview.height + 2); + ctx.save(); ctx.shadowColor = "rgba(0, 0, 0, 0.5)"; ctx.shadowBlur = 10; ctx.shadowOffsetX = 2; @@ -46,6 +94,15 @@ useRender((ctx) => { ctx.drawImage(preview, 0, 0); ctx.restore(); + + const project = store.projects[i]!; + if (project.technologies && project.technologies.length > 0) { + const badgeY = preview.height - BADGE_HEIGHT - BADGE_MARGIN; + const badgeX = preview.width - BADGE_MARGIN; + drawTechBadges(ctx, project.technologies, badgeX, badgeY); + } + + ctx.restore(); } }); diff --git a/app/stores/projects.ts b/app/stores/projects.ts index 7a006bf..6c1004b 100644 --- a/app/stores/projects.ts +++ b/app/stores/projects.ts @@ -65,6 +65,7 @@ export const useProjectsStore = defineStore("projects", { thumbnail: string; preview: string; url: string | null; + technologies: string[]; body: MarkdownBody; }[], currentProject: 0, @@ -90,6 +91,7 @@ export const useProjectsStore = defineStore("projects", { thumbnail: `/images/projects/${id}/thumbnail.webp`, preview: `/images/projects/${id}/preview.webp`, url: project.url, + technologies: project.technologies, body: simplifyMarkdownAST(project.body), }); } diff --git a/content.config.ts b/content.config.ts index a09ffe2..4d24667 100644 --- a/content.config.ts +++ b/content.config.ts @@ -10,6 +10,7 @@ export default defineContentConfig({ description: z.string(), url: z.url().nullable(), order: z.number(), + technologies: z.array(z.string()), }), }), }, diff --git a/content/projects/biobleud/index.md b/content/projects/biobleud/index.md index eaba19e..2aee581 100644 --- a/content/projects/biobleud/index.md +++ b/content/projects/biobleud/index.md @@ -2,4 +2,5 @@ description: Biobleud - Automated Excel imports\nfor an ERP system url: null order: 100 +technologies: [VBA] --- diff --git a/content/projects/lbf-bot/index.md b/content/projects/lbf-bot/index.md index 2a9be87..7a19735 100644 --- a/content/projects/lbf-bot/index.md +++ b/content/projects/lbf-bot/index.md @@ -2,6 +2,7 @@ description: LBF Bot - Custom Discord bot for\na gaming group url: https://github.com/pihkaal/lbf-bot order: 50 +technologies: [Node, TypeScript] --- a diff --git a/content/projects/lilou-cat/index.md b/content/projects/lilou-cat/index.md index baa43a6..c1802c0 100644 --- a/content/projects/lilou-cat/index.md +++ b/content/projects/lilou-cat/index.md @@ -2,4 +2,5 @@ description: lilou.cat - My cat's website url: https://lilou.cat order: 40 +technologies: [HTML, Go] --- diff --git a/content/projects/pihkaal-me/index.md b/content/projects/pihkaal-me/index.md index 20fb4cb..8bc1e2e 100644 --- a/content/projects/pihkaal-me/index.md +++ b/content/projects/pihkaal-me/index.md @@ -2,6 +2,7 @@ description: pihkaal.me - my personal website url: https://pihkaal.me order: 10 +technologies: [Nuxt, TypeScript] --- # pihkaal.me diff --git a/content/projects/s3pweb/index.md b/content/projects/s3pweb/index.md index efb9574..dd24137 100644 --- a/content/projects/s3pweb/index.md +++ b/content/projects/s3pweb/index.md @@ -2,4 +2,5 @@ description: S3PWeb - Intership and\napprenticeship url: null order: 80 +technologies: [Node, StencilJS, TypeScript] --- diff --git a/content/projects/simple-qr/index.md b/content/projects/simple-qr/index.md index 25a0418..85284dc 100644 --- a/content/projects/simple-qr/index.md +++ b/content/projects/simple-qr/index.md @@ -2,4 +2,5 @@ description: Simple QR - Simple QR code generator\nwith straightforward API url: https://simple-qr.com order: 30 +technologies: [Nuxt, TypeScript] --- diff --git a/content/projects/tlock/index.md b/content/projects/tlock/index.md index 3e1b95e..82f0918 100644 --- a/content/projects/tlock/index.md +++ b/content/projects/tlock/index.md @@ -2,4 +2,5 @@ description: tlock - fully customizable and cross-\nplatform terminal based clock url: https://github.com/pihkaal/tlock order: 20 +technologies: [Rust] ---