a Linkat frontend.

feat(meta): unify styling of the metadata

+82 -51
+67 -48
src/routes/+page.svelte
··· 1 <script lang="ts"> 2 - import { onMount } from "svelte"; 3 import { getStores } from "$app/stores"; 4 - const { page } = getStores(); 5 import UserDirectory from "$lib/components/archive/UserDirectory.svelte"; 6 import DynamicHead from "$lib/components/layout/DynamicHead.svelte"; 7 8 let { data } = $props(); 9 let displayUserBanner = $derived(data.displayUserBanner); 10 let displayUserDescription = $derived(data.displayUserDescription); 11 ··· 17 function shuffleArray<T>(array: T[]): T[] { 18 let currentIndex = array.length, randomIndex; 19 20 - // While there remain elements to shuffle. 21 while (currentIndex !== 0) { 22 - // Pick a remaining element. 23 randomIndex = Math.floor(Math.random() * currentIndex); 24 currentIndex--; 25 26 - // And swap it with the current element. 27 [array[currentIndex], array[randomIndex]] = [ 28 array[randomIndex], 29 array[currentIndex], ··· 32 return array; 33 } 34 35 - // State to track if locale has been properly loaded 36 - let localeLoaded = $state(false); 37 - 38 - onMount(() => { 39 - // Set a brief timeout to ensure the browser has time to determine locale 40 - setTimeout(() => { 41 - localeLoaded = true; 42 - }, 10); 43 - }); 44 - 45 - import { getProfile } from "$lib/components/profile/profile"; 46 - let profile = $state<{ displayName?: string; handle?: string } | null>(null); 47 - let loading = $state(true); 48 - let error = $state<string | null>(null); 49 - 50 - $effect(() => { 51 - if (import.meta.env.DIRECTORY_OWNER) { 52 - loading = true; 53 - getProfile(fetch) 54 - .then((p) => { 55 - profile = p; 56 - error = null; 57 - }) 58 - .catch((err) => { 59 - console.error('Failed to load profile:', err); 60 - error = err.message; 61 - profile = null; 62 - }) 63 - .finally(() => { 64 - loading = false; 65 - }); 66 - } else { 67 - loading = false; 68 - } 69 - }); 70 </script> 71 72 <DynamicHead 73 - title={profile?.displayName || "Linkat Directory"} 74 - description={profile?.displayName ? `Discover users' links curated by ${profile.displayName}` : "Discover amazing users curated by the Linkat community"} 75 - keywords={`Linkat, directory, links, Bluesky, community, curation${profile?.displayName ? `, ${profile.displayName}` : ''}`} 76 - ogTitle={profile?.displayName || "Linkat Directory"} 77 - ogDescription={profile?.displayName ? `Discover users' links curated by ${profile.displayName}` : "Discover amazing users' links curated by the Linkat community"} 78 - twitterTitle={profile?.displayName || "Linkat Directory"} 79 - twitterDescription={profile?.displayName ? `Discover users' links curated by ${profile.displayName}` : "Discover amazing users' links curated by the Linkat community"} 80 /> 81 82 <div class="container mx-auto px-4 py-8"> ··· 98 </div> 99 </div> 100 {:else} 101 - <UserDirectory users={shuffleArray([...data.linkatUsers]).map(did => ({ did }))} primaryUserDid={data.primaryUserDid} userLinkBoards={data.userLinkBoards} displayBanner={displayUserBanner} displayDescription={displayUserDescription} /> 102 {/if} 103 </div>
··· 1 <script lang="ts"> 2 import { getStores } from "$app/stores"; 3 + import { env } from "$env/dynamic/public"; 4 import UserDirectory from "$lib/components/archive/UserDirectory.svelte"; 5 import DynamicHead from "$lib/components/layout/DynamicHead.svelte"; 6 + import { getProfile } from "$lib/components/profile/profile"; 7 8 + const { page } = getStores(); 9 let { data } = $props(); 10 + 11 + // Environment variable for directory owner 12 + let directoryOwner = env.DIRECTORY_OWNER ?? ""; 13 + 14 + // Profile state for directory owner 15 + let ownerProfile = $state<{ displayName?: string; handle?: string } | null>(null); 16 + 17 + // Load the directory owner's profile 18 + $effect(() => { 19 + if (directoryOwner) { 20 + const loadOwner = async () => { 21 + try { 22 + const result = await getProfile(fetch); 23 + ownerProfile = result; 24 + } catch (err) { 25 + console.error("Could not fetch owner profile:", err); 26 + ownerProfile = null; 27 + } 28 + }; 29 + loadOwner(); 30 + } 31 + }); 32 + 33 + // Derived reactive values for user display options 34 let displayUserBanner = $derived(data.displayUserBanner); 35 let displayUserDescription = $derived(data.displayUserDescription); 36 ··· 42 function shuffleArray<T>(array: T[]): T[] { 43 let currentIndex = array.length, randomIndex; 44 45 while (currentIndex !== 0) { 46 randomIndex = Math.floor(Math.random() * currentIndex); 47 currentIndex--; 48 49 [array[currentIndex], array[randomIndex]] = [ 50 array[randomIndex], 51 array[currentIndex], ··· 54 return array; 55 } 56 57 + const getDisplayName = (p: { displayName?: string; handle?: string } | null | undefined) => 58 + p?.displayName || p?.handle || null; 59 </script> 60 61 <DynamicHead 62 + title={ 63 + directoryOwner 64 + ? `${getDisplayName(ownerProfile) || directoryOwner}'s Linkat Directory` 65 + : "Linkat Directory" 66 + } 67 + description={ 68 + directoryOwner 69 + ? `Discover users' links curated by ${getDisplayName(ownerProfile) || directoryOwner} in ${getDisplayName(ownerProfile) || directoryOwner}'s Linkat Directory` 70 + : "Discover amazing users curated by the Linkat community" 71 + } 72 + keywords={`Linkat, directory, links, Bluesky, community, curation${directoryOwner ? `, ${getDisplayName(ownerProfile) || directoryOwner}` : ""}`} 73 + ogTitle={ 74 + directoryOwner 75 + ? `${getDisplayName(ownerProfile) || directoryOwner}'s Linkat Directory` 76 + : "Linkat Directory" 77 + } 78 + ogDescription={ 79 + directoryOwner 80 + ? `Discover users' links curated by ${getDisplayName(ownerProfile) || directoryOwner} in ${getDisplayName(ownerProfile) || directoryOwner}'s Linkat Directory` 81 + : "Discover amazing users' links curated by the Linkat community" 82 + } 83 + twitterTitle={ 84 + directoryOwner 85 + ? `${getDisplayName(ownerProfile) || directoryOwner}'s Linkat Directory` 86 + : "Linkat Directory" 87 + } 88 + twitterDescription={ 89 + directoryOwner 90 + ? `Discover users' links curated by ${getDisplayName(ownerProfile) || directoryOwner} in ${getDisplayName(ownerProfile) || directoryOwner}'s Linkat Directory` 91 + : "Discover amazing users' links curated by the Linkat community" 92 + } 93 /> 94 95 <div class="container mx-auto px-4 py-8"> ··· 111 </div> 112 </div> 113 {:else} 114 + <UserDirectory 115 + users={shuffleArray([...data.linkatUsers]).map(did => ({ did }))} 116 + primaryUserDid={directoryOwner} 117 + userLinkBoards={data.userLinkBoards} 118 + displayBanner={displayUserBanner} 119 + displayDescription={displayUserDescription} 120 + /> 121 {/if} 122 </div>
+15 -3
src/routes/user/[did]/+page.svelte
··· 41 ? `${getDisplayName(profile) || did} – ${getDisplayName(ownerProfile) || directoryOwner}'s Linkat Directory` 42 : `${getDisplayName(profile) || did} – Linkat Directory` 43 } 44 - description={`View ${getDisplayName(profile) || did}'s curated links in ${directoryOwner ? getDisplayName(ownerProfile) || directoryOwner + "'s" : "the"} Linkat Directory`} 45 ogTitle={ 46 directoryOwner 47 ? `${getDisplayName(profile) || did} – ${getDisplayName(ownerProfile) || directoryOwner}'s Linkat Directory` 48 : `${getDisplayName(profile) || did} – Linkat Directory` 49 } 50 - ogDescription={`View ${getDisplayName(profile) || did}'s curated links in ${directoryOwner ? getDisplayName(ownerProfile) || directoryOwner + "'s" : "the"} Linkat Directory`} 51 twitterTitle={ 52 directoryOwner 53 ? `${getDisplayName(profile) || did} – ${getDisplayName(ownerProfile) || directoryOwner}'s Linkat Directory` 54 : `${getDisplayName(profile) || did} – Linkat Directory` 55 } 56 - twitterDescription={`View ${getDisplayName(profile) || did}'s curated links in ${directoryOwner ? getDisplayName(ownerProfile) || directoryOwner + "'s" : "the"} Linkat Directory`} 57 keywords={`Linkat, directory, links, Bluesky, curation, ${getDisplayName(profile) || did}, ${getDisplayName(ownerProfile) || directoryOwner}`} 58 /> 59
··· 41 ? `${getDisplayName(profile) || did} – ${getDisplayName(ownerProfile) || directoryOwner}'s Linkat Directory` 42 : `${getDisplayName(profile) || did} – Linkat Directory` 43 } 44 + description={ 45 + directoryOwner 46 + ? `View ${getDisplayName(profile) || did}'s curated links in ${getDisplayName(ownerProfile) || directoryOwner}'s Linkat Directory` 47 + : `View ${getDisplayName(profile) || did}'s curated links in the Linkat Directory` 48 + } 49 ogTitle={ 50 directoryOwner 51 ? `${getDisplayName(profile) || did} – ${getDisplayName(ownerProfile) || directoryOwner}'s Linkat Directory` 52 : `${getDisplayName(profile) || did} – Linkat Directory` 53 } 54 + ogDescription={ 55 + directoryOwner 56 + ? `View ${getDisplayName(profile) || did}'s curated links in ${getDisplayName(ownerProfile) || directoryOwner}'s Linkat Directory` 57 + : `View ${getDisplayName(profile) || did}'s curated links in the Linkat Directory` 58 + } 59 twitterTitle={ 60 directoryOwner 61 ? `${getDisplayName(profile) || did} – ${getDisplayName(ownerProfile) || directoryOwner}'s Linkat Directory` 62 : `${getDisplayName(profile) || did} – Linkat Directory` 63 } 64 + twitterDescription={ 65 + directoryOwner 66 + ? `View ${getDisplayName(profile) || did}'s curated links in ${getDisplayName(ownerProfile) || directoryOwner}'s Linkat Directory` 67 + : `View ${getDisplayName(profile) || did}'s curated links in the Linkat Directory` 68 + } 69 keywords={`Linkat, directory, links, Bluesky, curation, ${getDisplayName(profile) || did}, ${getDisplayName(ownerProfile) || directoryOwner}`} 70 /> 71