WIP: My personal website
1<script lang="ts">
2 import { reveal } from '$lib/actions/reveal';
3 import LazyLoadingImg from './LazyLoadingImg.svelte';
4 import webDev from '$lib/assets/seenOn/webDev.webp';
5 import atadventWorkshop from '$lib/assets/seenOn/atadventWorkshop.webp';
6 type Appearance = {
7 title: string;
8 description: string;
9 image: string;
10 href: string;
11 platform: string; // e.g. 'YouTube', 'Talk', 'Podcast'
12 action?: string; // e.g. 'Watch', 'Listen'
13 };
14
15 const appearances: Appearance[] = [
16 {
17 title: 'CodeTV Web Dev Challenge with ATproto',
18 description:
19 'I was on an episode of CodeTV where me and 5 others rebuilt our personal websites (again) but using ATproto.',
20 image: webDev,
21 href: 'https://www.youtube.com/watch?v=S-XytKfGCO8',
22 platform: 'YouTube',
23 action: 'Watch'
24 },
25 {
26 title: 'at://advent, an atproto adventure',
27 description:
28 'Me and Fig hosted a workshop at the Atmosphere Conf 2026 where we showed off at://advent, an atproto adventure and a fun way for developers to learn atproto.',
29 image: atadventWorkshop,
30 href: 'https://advent.codes/',
31 platform: 'Workshop',
32 action: 'Learn'
33 }
34 ];
35
36 const INITIAL_COUNT = 4;
37 const LOAD_STEP = 2;
38 let visibleCount = $state(INITIAL_COUNT);
39 const visibleAppearances = $derived(appearances.slice(0, visibleCount));
40 const hasMore = $derived(visibleCount < appearances.length);
41</script>
42
43<div id="as-seen-on" class="mt-10 flex flex-col items-center justify-center md:mt-20" use:reveal>
44 <div class="flex flex-col items-center justify-center">
45 <h1 class="text-center font-urbanist text-2xl font-semibold md:text-5xl">As Seen On</h1>
46 <span class="text-md mt-2 px-2 text-center font-urbanist md:mt-4 md:px-5 md:text-xl">
47 Talks, videos, and places I've shown up.
48 </span>
49 </div>
50 <div class="container mt-10 grid gap-10 p-4 md:grid-cols-2 xl:grid-cols-3">
51 {#each visibleAppearances as item (item.title)}
52 <div class="card bg-base-100 shadow-sm transition duration-300 hover:-translate-y-1">
53 <figure>
54 <LazyLoadingImg class="h-48 w-full" src={item.image} alt={item.title} />
55 </figure>
56 <div class="card-body">
57 <div class="badge font-urbanist badge-secondary">{item.platform}</div>
58 <h2 class="card-title font-urbanist text-2xl font-black">{item.title}</h2>
59 <p class="text-md font-urbanist font-medium opacity-60">{item.description}</p>
60 <div class="mt-2 card-actions justify-end">
61 <a
62 class="btn font-urbanist btn-primary"
63 href={item.href}
64 target="_blank"
65 rel="noopener noreferrer"
66 >
67 {item.action ?? 'Watch'}
68 </a>
69 </div>
70 </div>
71 </div>
72 {/each}
73 </div>
74 {#if hasMore}
75 <button
76 class="btn mt-10 font-urbanist btn-primary"
77 onclick={() => (visibleCount = Math.min(visibleCount + LOAD_STEP, appearances.length))}
78 >
79 Load More
80 </button>
81 {/if}
82</div>