Merge pull request #55 from davidmonterocrespo24/website

feat: update SEO handling by dynamically setting canonical links and …
pull/74/head
David Montero Crespo 2026-03-23 15:07:19 -03:00 committed by GitHub
commit 35640f3a04
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 19 additions and 16 deletions

View File

@ -13,7 +13,7 @@
<meta name="keywords" content="arduino emulator, arduino simulator, arduino simulator free, avr8 emulator, avr simulator, atmega328p simulator, atmega2560 simulator, attiny85 simulator, arduino uno simulator, arduino mega simulator, arduino nano simulator, rp2040 emulator, raspberry pi pico simulator, esp32 emulator, esp32 simulator, esp32-c3 simulator, esp32-s3 emulator, risc-v simulator, ch32v003, raspberry pi 3 emulator, wokwi alternative, arduino ide browser, arduino online, electronics simulator, velxio" />
<meta name="author" content="David Montero Crespo" />
<meta name="robots" content="index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1" />
<link rel="canonical" href="https://velxio.dev/" />
<!-- canonical is set dynamically per-route by the useSEO hook -->
<!-- Google Search Console verification — replace token after verifying in Search Console -->
<!-- <meta name="google-site-verification" content="REPLACE_WITH_YOUR_VERIFICATION_TOKEN" /> -->

View File

@ -129,18 +129,6 @@
<priority>0.85</priority>
</url>
<url>
<loc>https://velxio.dev/login</loc>
<lastmod>2026-03-06</lastmod>
<changefreq>yearly</changefreq>
<priority>0.3</priority>
</url>
<url>
<loc>https://velxio.dev/register</loc>
<lastmod>2026-03-06</lastmod>
<changefreq>yearly</changefreq>
<priority>0.3</priority>
</url>
<!-- Auth pages intentionally excluded from sitemap (not for indexing) -->
</urlset>

View File

@ -47,6 +47,17 @@ export function useSEO({ title, description, url, ogImage, jsonLd }: SEOMeta) {
const origTwDesc = get(twDescEl);
const origCanonical = canonicalEl?.getAttribute('href') ?? '';
// If no <link rel="canonical"> exists yet, create one so each SPA route
// gets its own canonical (avoids all routes appearing to point back to /).
let createdCanonical = false;
let activeCanonical: HTMLLinkElement | null = canonicalEl as HTMLLinkElement | null;
if (!activeCanonical) {
activeCanonical = document.createElement('link') as HTMLLinkElement;
activeCanonical.rel = 'canonical';
document.head.appendChild(activeCanonical);
createdCanonical = true;
}
// Apply
document.title = title;
set(descEl, description);
@ -56,7 +67,7 @@ export function useSEO({ title, description, url, ogImage, jsonLd }: SEOMeta) {
if (ogImage) set(ogImgEl, ogImage);
set(twTitleEl, title);
set(twDescEl, description);
canonicalEl?.setAttribute('href', url);
activeCanonical.setAttribute('href', url);
// Inject JSON-LD once (module-level constants don't change)
if (jsonLd && !scriptRef.current) {
@ -77,7 +88,11 @@ export function useSEO({ title, description, url, ogImage, jsonLd }: SEOMeta) {
if (ogImage) set(ogImgEl, origOgImg);
set(twTitleEl, origTwTitle);
set(twDescEl, origTwDesc);
canonicalEl?.setAttribute('href', origCanonical);
if (createdCanonical && activeCanonical && document.head.contains(activeCanonical)) {
document.head.removeChild(activeCanonical);
} else {
activeCanonical?.setAttribute('href', origCanonical);
}
if (scriptRef.current) {
document.head.removeChild(scriptRef.current);
scriptRef.current = null;