From 1041be46f3ad6262f95d3bce425b3f58000f389a Mon Sep 17 00:00:00 2001 From: b1rdmania <102524336+b1rdmania@users.noreply.github.com> Date: Mon, 29 Dec 2025 13:25:27 +0000 Subject: [PATCH] Add short links with song title in OG preview MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Re-enable /api/share for short links (/s/abc123) - Title shows as "Song Name - WARIO SYNTH" - Description: "I made this in WARIO SYNTH" - Falls back to long URL if short link fails 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- server/src/server.ts | 2 +- src/main.ts | 54 ++++++++++++++++++++++++++++++++------------ 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/server/src/server.ts b/server/src/server.ts index 58b9e8c..2dcd108 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -221,7 +221,7 @@ app.get('/s/:code', async (req, res) => { const sharedTitle = (payload.title || '').trim(); const ogTitle = sharedTitle ? `${sharedTitle} - WARIO SYNTH` : 'WARIO SYNTH'; - const ogDescription = 'Tap to play this Gameboy tune'; + const ogDescription = sharedTitle ? 'I made this in WARIO SYNTH' : 'Tap to play this Gameboy tune'; const html = ` diff --git a/src/main.ts b/src/main.ts index b646176..fb1798b 100644 --- a/src/main.ts +++ b/src/main.ts @@ -185,7 +185,7 @@ class MotifApp { this.motifProgressBar.addEventListener('input', seekHandler); this.motifProgressBar.addEventListener('change', seekHandler); - this.copyLinkBtn.addEventListener('click', () => this.handleCopyLink()); + this.copyLinkBtn.addEventListener('click', () => void this.handleCopyLink()); // Embed snippet copy (may be disabled / not-live) this.copyEmbedBtn?.addEventListener('click', () => void this.copyEmbedSnippet()); @@ -671,26 +671,52 @@ class MotifApp { this.status.textContent = message; } - private handleCopyLink(): void { + private async handleCopyLink(): Promise { if (!this.hasGenerated) return; const result = this.searchResults[this.selectedResultIndex]; if (!result?.midiUrl) return; - // Build share URL with title - const title = encodeURIComponent(result.title || ''); - let shareUrl: string; - if (result.source === 'bitmidi') { - const m = String(result.midiUrl).match(/\/uploads\/(\d+)\.mid/i); - if (m?.[1]) { - shareUrl = `${window.location.origin}/play?src=bitmidi&id=${encodeURIComponent(m[1])}&title=${title}`; - } else { - shareUrl = `${window.location.origin}/play?u=${encodeURIComponent(result.midiUrl)}&title=${title}`; + const title = result.title || ''; + + // Try to get a short link with dynamic OG tags + let shareUrl: string | null = null; + try { + let payload: any = null; + if (result.source === 'bitmidi') { + const m = String(result.midiUrl).match(/\/uploads\/(\d+)\.mid/i); + if (m?.[1]) payload = { src: 'bitmidi', id: m[1], title }; } - } else { - shareUrl = `${window.location.origin}/play?u=${encodeURIComponent(result.midiUrl)}&title=${title}`; + if (!payload) payload = { u: result.midiUrl, title }; + + const resp = await fetch('/api/share', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload), + }); + if (resp.ok) { + const data = await resp.json(); + if (data?.url) shareUrl = `${window.location.origin}${data.url}`; + } + } catch { + // Fall through to long URL } - // Show the link in a text box for easy copying + // Fallback: direct /play link + if (!shareUrl) { + const encodedTitle = encodeURIComponent(title); + if (result.source === 'bitmidi') { + const m = String(result.midiUrl).match(/\/uploads\/(\d+)\.mid/i); + if (m?.[1]) { + shareUrl = `${window.location.origin}/play?src=bitmidi&id=${encodeURIComponent(m[1])}&title=${encodedTitle}`; + } else { + shareUrl = `${window.location.origin}/play?u=${encodeURIComponent(result.midiUrl)}&title=${encodedTitle}`; + } + } else { + shareUrl = `${window.location.origin}/play?u=${encodeURIComponent(result.midiUrl)}&title=${encodedTitle}`; + } + } + + // Show the link this.shareLinkInput.value = shareUrl; this.shareLinkBox.style.display = 'block'; this.shareLinkInput.select();