audio streaming app plyr.fm

fix: jam link previews showing generic plyr.fm branding (#990)

/jam/ was missing from hasPageMetadata in root layout, so default OG
tags rendered first and crawlers used the generic logo instead of
jam-specific metadata. Also expanded jam OG tags to match track/album
quality (og:type, og:site_name, twitter card, image dimensions).

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

authored by zzstoatzz.io

Claude Opus 4.6 and committed by
GitHub
ebb6fbb7 84be96f2

+24 -4
+1
frontend/src/routes/+layout.svelte
··· 34 34 $page.url.pathname.startsWith('/playlist/') || // playlist detail 35 35 $page.url.pathname.startsWith('/tag/') || // tag detail 36 36 $page.url.pathname === '/liked' || // liked tracks 37 + $page.url.pathname.startsWith('/jam/') || // jam invite 37 38 $page.url.pathname.match(/^\/u\/[^/]+$/) || // artist detail 38 39 $page.url.pathname.match(/^\/u\/[^/]+\/album\/[^/]+/) // album detail 39 40 );
+23 -4
frontend/src/routes/jam/[code]/+page.svelte
··· 23 23 </script> 24 24 25 25 <svelte:head> 26 - <title>joining jam - {APP_NAME}</title> 27 26 {#if data.preview} 28 27 {@const preview = data.preview} 29 28 {@const title = preview.name ?? `${preview.host_display_name}'s jam`} 30 29 {@const description = 31 30 preview.participant_count > 1 32 - ? `join ${preview.host_display_name} and ${preview.participant_count - 1} others on plyr.fm` 33 - : `join ${preview.host_display_name} on plyr.fm`} 31 + ? `join ${preview.host_display_name} and ${preview.participant_count - 1} others on ${APP_NAME}` 32 + : `${preview.host_display_name} is listening on ${APP_NAME} — join in`} 33 + <title>{title} - {APP_NAME}</title> 34 + <meta name="description" content={description} /> 35 + 36 + <!-- Open Graph --> 37 + <meta property="og:type" content="website" /> 34 38 <meta property="og:title" content={title} /> 35 39 <meta property="og:description" content={description} /> 40 + <meta property="og:url" content={`${APP_CANONICAL_URL}/jam/${preview.code}`} /> 41 + <meta property="og:site_name" content={APP_NAME} /> 36 42 {#if preview.host_avatar_url} 37 43 <meta property="og:image" content={preview.host_avatar_url} /> 44 + <meta property="og:image:secure_url" content={preview.host_avatar_url} /> 45 + <meta property="og:image:width" content="400" /> 46 + <meta property="og:image:height" content="400" /> 47 + <meta property="og:image:alt" content="{preview.host_display_name}'s avatar" /> 38 48 {/if} 39 - <meta property="og:url" content={`${APP_CANONICAL_URL}/jam/${preview.code}`} /> 49 + 50 + <!-- Twitter --> 51 + <meta name="twitter:card" content="summary" /> 52 + <meta name="twitter:title" content={title} /> 53 + <meta name="twitter:description" content={description} /> 54 + {#if preview.host_avatar_url} 55 + <meta name="twitter:image" content={preview.host_avatar_url} /> 56 + {/if} 57 + {:else} 58 + <title>joining jam - {APP_NAME}</title> 40 59 {/if} 41 60 </svelte:head> 42 61