tracks lexicons and how many times they appeared on the jetstream
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: dont fetch data from server on page load, let the server provide it

dusk 4ae54481 20e92a30

+31 -29
+11
src/routes/+page.server.ts
··· 1 + import { eventTracker } from "$lib/db"; 2 + 3 + export const load = async () => { 4 + const events = eventTracker.getNsidCounts(); 5 + const totalEvents = eventTracker.getEventCount(); 6 + 7 + return { 8 + events, 9 + totalEvents, 10 + }; 11 + };
+20 -29
src/routes/+page.svelte
··· 1 1 <script lang="ts"> 2 - import { onMount } from "svelte"; 3 2 import type { EventRecord } from "$lib/db.js"; 4 3 5 - let events: EventRecord[] = []; 6 - let totalEvents = 0; 7 - let isLoading = true; 8 - let error: string | null = null; 4 + interface Props { 5 + // eslint-disable-next-line @typescript-eslint/no-explicit-any 6 + data: any; 7 + } 8 + let { data }: Props = $props(); 9 + 10 + let events: EventRecord[] = $state(data.events); 11 + let totalEvents = $state(data.totalEvents); 12 + let error: string | null = $state(null); 9 13 10 14 const loadData = async () => { 11 15 try { 12 - isLoading = true; 13 16 error = null; 14 17 15 18 const response = await fetch("/api/events"); ··· 25 28 err instanceof Error 26 29 ? err.message 27 30 : "an unknown error occurred"; 28 - console.error("Error loading data:", err); 29 - } finally { 30 - isLoading = false; 31 + console.error("error loading data:", err); 31 32 } 32 33 }; 33 34 34 - onMount(() => { 35 - loadData(); 36 - }); 37 - 38 35 const formatNumber = (num: number): string => { 39 36 return num.toLocaleString(); 40 37 }; ··· 49 46 <meta name="description" content="tracks bluesky events by collection" /> 50 47 </svelte:head> 51 48 52 - <div class="max-w-[66vw] mx-auto p-2"> 49 + <div class="max-w-[60vw] mx-auto p-2"> 53 50 <header class="text-center mb-8"> 54 51 <h1 class="text-4xl font-bold mb-2 text-gray-900"> 55 - 🦋 bluesky event tracker 52 + bluesky event tracker 56 53 </h1> 57 54 <p class="text-gray-600"> 58 55 tracking of bluesky events by collection from the jetstream 59 56 </p> 60 57 </header> 61 58 62 - <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-8"> 59 + <div class="mx-auto w-fit grid grid-cols-1 md:grid-cols-2 mb-8"> 63 60 <div 64 61 class="bg-gradient-to-r from-blue-50 to-blue-100 p-6 rounded-lg border border-blue-200" 65 62 > 66 - <h3 class="text-sm font-medium text-blue-700 mb-2">total events</h3> 63 + <h3 class="text-base font-medium text-blue-700 mb-2"> 64 + total events 65 + </h3> 67 66 <p class="text-3xl font-bold text-blue-900"> 68 67 {formatNumber(totalEvents)} 69 68 </p> ··· 71 70 <div 72 71 class="bg-gradient-to-r from-green-50 to-green-100 p-6 rounded-lg border border-green-200" 73 72 > 74 - <h3 class="text-sm font-medium text-green-700 mb-2"> 73 + <h3 class="text-base font-medium text-green-700 mb-2"> 75 74 unique collections 76 75 </h3> 77 76 <p class="text-3xl font-bold text-green-900"> ··· 82 81 83 82 <div class="text-center mb-8"> 84 83 <button 85 - on:click={loadData} 86 - disabled={isLoading} 84 + onclick={loadData} 87 85 class="bg-blue-600 hover:bg-blue-700 disabled:bg-gray-400 disabled:cursor-not-allowed text-white px-6 py-3 rounded-lg font-medium transition-colors" 88 86 > 89 - {isLoading ? "loading..." : "refresh"} 87 + refresh 90 88 </button> 91 89 </div> 92 90 ··· 98 96 </div> 99 97 {/if} 100 98 101 - {#if isLoading} 102 - <div class="text-center py-12"> 103 - <div 104 - class="inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600" 105 - ></div> 106 - <p class="mt-4 text-gray-600">loading events...</p> 107 - </div> 108 - {:else if events.length > 0} 99 + {#if events.length > 0} 109 100 <div class="mb-8"> 110 101 <h2 class="text-2xl font-bold mb-6 text-gray-900"> 111 102 events by collection