From 5ebaaece67ca2c2989ada1f058b14ffce53d5279 Mon Sep 17 00:00:00 2001 From: Marcelo Santos <117441129+marcelo-m7@users.noreply.github.com> Date: Mon, 17 Nov 2025 22:27:05 +0000 Subject: [PATCH] fix: improve favicon and github ctas --- index.html | 3 +++ src/lib/solutions.ts | 37 ++++++++++++++++++++++++- src/pages/Projects.tsx | 41 ++++++++++++++++++++++++++++ src/pages/Solutions.tsx | 43 ++++++++++++++++++++++++++++- src/pages/solutions/[slug].tsx | 49 +++++++++++++++++++++++++++++++++- src/types/solutions.ts | 2 ++ 6 files changed, 172 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index f1da896..4a21164 100644 --- a/index.html +++ b/index.html @@ -9,7 +9,10 @@ content="Democratizing innovation through inclusive, accessible solutions that empower diverse communities and promote social equity." /> + + + { + if (!value) { + return null; + } + + const trimmed = value.trim(); + if (!trimmed) { + return null; + } + + const normalized = /^https?:\/\//i.test(trimmed) + ? trimmed + : `https://${trimmed}`; + + try { + const url = new URL(normalized); + if (!['http:', 'https:'].includes(url.protocol)) { + return null; + } + + return url.toString(); + } catch { + return null; + } +}; + const uniqueNonEmpty = (values: Array): string[] => { const seen = new Set(); const result: string[] = []; @@ -114,12 +140,14 @@ const buildFeatureList = ( ? uniqueNonEmpty(repository.topics) : []; + const homepageUrl = sanitizeUrl(repository.homepage); + const formattedUpdatedAt = formatDate(repository.updated_at ?? repository.pushed_at) ?? undefined; const metadata = uniqueNonEmpty([ repository.language ? `Built with ${repository.language}.` : null, - repository.homepage ? `Live project: ${repository.homepage}` : null, + homepageUrl ? `Live project: ${homepageUrl}` : null, repository.stargazers_count > 0 ? `${repository.stargazers_count} ⭐ stars on GitHub` : null, @@ -153,6 +181,9 @@ export const mapGitHubRepoToContent = ( const description = repository.description?.trim(); + const repositoryUrl = sanitizeUrl(repository.html_url) ?? repository.html_url; + const websiteUrl = sanitizeUrl(repository.homepage); + return { id: String(repository.id), title: fallback?.title ?? repository.name, @@ -165,6 +196,8 @@ export const mapGitHubRepoToContent = ( imageUrl: fallback?.imageUrl ?? null, features: buildFeatureList(repository, fallback), gradient, + repositoryUrl, + websiteUrl, }; }; @@ -196,6 +229,8 @@ export const mapSupabaseSolutionToContent = ( imageUrl: solution.image_url ?? fallback?.imageUrl ?? null, features, gradient, + repositoryUrl: fallback?.repositoryUrl ?? null, + websiteUrl: fallback?.websiteUrl ?? null, }; }; diff --git a/src/pages/Projects.tsx b/src/pages/Projects.tsx index 649e381..50500a9 100644 --- a/src/pages/Projects.tsx +++ b/src/pages/Projects.tsx @@ -316,6 +316,47 @@ const Projects = () => { )} + {(solution.repositoryUrl || solution.websiteUrl) && ( + + {solution.repositoryUrl && ( + + + + {t('projects.viewGithub')} + + + )} + {solution.websiteUrl && ( + + + + {t('projects.liveDemo')} + + + )} + + )} + { )} + {(solution.repositoryUrl || solution.websiteUrl) && ( + + {solution.repositoryUrl && ( + + + + {t('projects.viewGithub')} + + + )} + {solution.websiteUrl && ( + + + + {t('projects.liveDemo')} + + + )} + + )} + { + + {(displaySolution.repositoryUrl || displaySolution.websiteUrl) && ( + + {displaySolution.repositoryUrl && ( + + + + {t('projects.viewGithub')} + + + )} + {displaySolution.websiteUrl && ( + + + + {t('projects.liveDemo')} + + + )} + + )} {displaySolution.imageUrl && ( diff --git a/src/types/solutions.ts b/src/types/solutions.ts index 152eb69..4b68db7 100644 --- a/src/types/solutions.ts +++ b/src/types/solutions.ts @@ -6,4 +6,6 @@ export interface SolutionContent { imageUrl?: string | null; features: string[]; gradient: string; + repositoryUrl?: string | null; + websiteUrl?: string | null; }