your personal website on atproto - mirror blento.app

Merge pull request #36 from jycouet/feat/error

Add a dummy error

authored by Florian and committed by GitHub a895c753 c33dee29

+127 -27
+7 -2
src/lib/atproto/methods.ts
··· 10 10 } from '@atcute/identity-resolver'; 11 11 import { Client, simpleFetchHandler } from '@atcute/client'; 12 12 import type { AppBskyActorDefs } from '@atcute/bluesky'; 13 + import { redirect } from '@sveltejs/kit'; 13 14 14 15 export type Collection = `${string}.${string}.${string}`; 15 16 ··· 30 31 } 31 32 }); 32 33 33 - const data = await handleResolver.resolve(handle); 34 - return data; 34 + try { 35 + const data = await handleResolver.resolve(handle); 36 + return data; 37 + } catch (error) { 38 + redirect(307, '/?error=handle_not_found&handle=' + handle); 39 + } 35 40 } 36 41 37 42 const didResolver = new CompositeDidDocumentResolver({
+2 -8
src/lib/website/EditableProfile.svelte
··· 4 4 import PlainTextEditor from '$lib/components/PlainTextEditor.svelte'; 5 5 import MarkdownTextEditor from '$lib/components/MarkdownTextEditor.svelte'; 6 6 import type { Editor } from '@tiptap/core'; 7 + import MadeWithBlento from './MadeWithBlento.svelte'; 7 8 8 9 let { data = $bindable() }: { data: WebsiteData } = $props(); 9 10 ··· 144 145 145 146 <div class="h-10.5 w-1 @5xl/wrapper:hidden"></div> 146 147 147 - <div class="hidden text-xs font-light @5xl/wrapper:block"> 148 - made with <a 149 - href="https://blento.app" 150 - target="_blank" 151 - class="hover:text-accent-600 dark:hover:text-accent-400 font-medium transition-colors duration-200" 152 - >blento</a 153 - > 154 - </div> 148 + <MadeWithBlento class="hidden @5xl/wrapper:block" /> 155 149 </div> 156 150 </div>
+12
src/lib/website/MadeWithBlento.svelte
··· 1 + <script lang="ts"> 2 + let { class: className = '' }: { class?: string } = $props(); 3 + </script> 4 + 5 + <div class={['text-xs font-light', className]}> 6 + made with <a 7 + href="https://blento.app" 8 + target="_blank" 9 + class="hover:text-accent-600 dark:hover:text-accent-400 font-medium transition-colors duration-200" 10 + >blento</a 11 + > 12 + </div>
+2 -8
src/lib/website/Profile.svelte
··· 9 9 import { page } from '$app/state'; 10 10 import type { ActorIdentifier } from '@atcute/lexicons'; 11 11 import { qrOverlay } from '$lib/components/qr/qrOverlay.svelte'; 12 + import MadeWithBlento from './MadeWithBlento.svelte'; 12 13 13 14 let { 14 15 data, ··· 123 124 </div> 124 125 {/if} 125 126 {/if} 126 - <div class="hidden text-xs font-light @5xl/wrapper:block"> 127 - made with <a 128 - href="https://blento.app" 129 - target="_blank" 130 - class="hover:text-accent-600 dark:hover:text-accent-400 font-medium transition-colors duration-200" 131 - >blento</a 132 - > 133 - </div> 127 + <MadeWithBlento class="hidden @5xl/wrapper:block" /> 134 128 </div> 135 129 </div>
+2 -8
src/lib/website/Website.svelte
··· 7 7 import BaseCard from '../cards/BaseCard/BaseCard.svelte'; 8 8 import type { WebsiteData } from '$lib/types'; 9 9 import Context from './Context.svelte'; 10 + import MadeWithBlento from './MadeWithBlento.svelte'; 10 11 import Head from './Head.svelte'; 11 12 import type { Did, Handle } from '@atcute/lexicons'; 12 13 import QRModalProvider from '$lib/components/qr/QRModalProvider.svelte'; ··· 69 70 </div> 70 71 </div> 71 72 72 - <div class="mx-auto block pb-8 text-center text-xs font-light @5xl/wrapper:hidden"> 73 - made with <a 74 - href="https://blento.app" 75 - target="_blank" 76 - class="hover:text-accent-600 dark:hover:text-accent-400 font-medium transition-colors duration-200" 77 - >blento</a 78 - > 79 - </div> 73 + <MadeWithBlento class="mx-auto block pb-8 text-center @5xl/wrapper:hidden" /> 80 74 </div> 81 75 </Context>
+87
src/routes/+error.svelte
··· 1 + <script lang="ts"> 2 + import { page } from '$app/stores'; 3 + import MadeWithBlento from '$lib/website/MadeWithBlento.svelte'; 4 + </script> 5 + 6 + <div 7 + class="bg-base-100 dark:bg-base-950 text-base-900 dark:text-base-50 min-h-screen px-4 py-8 lg:px-8" 8 + > 9 + <div class="@container/grid mx-auto max-w-4xl"> 10 + <!-- Bento Grid --> 11 + <div class="grid grid-cols-4 gap-3 lg:grid-cols-8 lg:gap-4"> 12 + <!-- Error Code - Large prominent card --> 13 + <div 14 + class="col-span-4 row-span-2 flex flex-col items-center justify-center rounded-3xl bg-gradient-to-br from-pink-500 to-rose-500 p-8 text-white lg:col-span-4" 15 + > 16 + <span class="text-8xl font-black lg:text-9xl">{$page.status}</span> 17 + <span class="mt-2 text-xl font-medium opacity-90">Error</span> 18 + </div> 19 + 20 + <!-- Oops card --> 21 + <div 22 + class="col-span-2 flex items-center justify-center rounded-3xl bg-amber-500 p-6 text-white" 23 + > 24 + <span class="text-2xl font-bold lg:text-3xl">Oops!</span> 25 + </div> 26 + 27 + <!-- Decorative emoji card --> 28 + <div 29 + class="col-span-2 flex items-center justify-center rounded-3xl bg-violet-500 p-6 text-4xl lg:text-5xl" 30 + > 31 + <span class="animate-bounce">:(</span> 32 + </div> 33 + 34 + <!-- Message card --> 35 + <div 36 + class="bg-base-200/50 dark:bg-base-800/50 text-base-700 dark:text-base-300 col-span-4 flex items-center justify-center rounded-3xl p-6 text-center" 37 + > 38 + <p class="text-lg font-medium"> 39 + {$page.error?.message || 40 + "Something went wrong. We couldn't find what you're looking for."} 41 + </p> 42 + </div> 43 + 44 + <!-- Decorative pattern card --> 45 + <div 46 + class="col-span-2 flex items-center justify-center overflow-hidden rounded-3xl bg-cyan-500 p-4" 47 + > 48 + <div class="grid grid-cols-3 gap-2"> 49 + {#each Array(9) as _, i (i)} 50 + <div class="h-3 w-3 rounded-full bg-white/40 lg:h-4 lg:w-4"></div> 51 + {/each} 52 + </div> 53 + </div> 54 + 55 + <!-- Home link card --> 56 + <a 57 + href="/" 58 + class="col-span-2 flex items-center justify-center rounded-3xl bg-emerald-500 p-6 text-white transition-transform hover:scale-[1.02] active:scale-[0.98]" 59 + > 60 + <span class="text-lg font-bold lg:text-xl">Go Home</span> 61 + </a> 62 + 63 + <!-- Decorative stripes card --> 64 + <div class="col-span-2 overflow-hidden rounded-3xl bg-blue-500 p-4"> 65 + <div class="flex h-full w-full flex-col justify-center gap-2"> 66 + <div class="h-2 w-full rounded-full bg-white/30"></div> 67 + <div class="h-2 w-3/4 rounded-full bg-white/40"></div> 68 + <div class="h-2 w-1/2 rounded-full bg-white/50"></div> 69 + </div> 70 + </div> 71 + 72 + <!-- Decorative circles card --> 73 + <div 74 + class="col-span-2 flex items-center justify-center rounded-3xl bg-orange-500 p-4 lg:col-span-2" 75 + > 76 + <div class="relative h-16 w-16 lg:h-20 lg:w-20"> 77 + <div class="absolute inset-0 rounded-full border-4 border-white/40"></div> 78 + <div class="absolute inset-2 rounded-full border-4 border-white/50"></div> 79 + <div class="absolute inset-4 rounded-full border-4 border-white/60"></div> 80 + </div> 81 + </div> 82 + </div> 83 + </div> 84 + 85 + <!-- Footer --> 86 + <MadeWithBlento class="text-base-500 mt-12 text-center" /> 87 + </div>
+15 -1
src/routes/+layout.svelte
··· 1 1 <script lang="ts"> 2 2 import '../app.css'; 3 3 4 - import { ThemeToggle } from '@foxui/core'; 4 + import { ThemeToggle, Toaster, toast } from '@foxui/core'; 5 5 import { onMount } from 'svelte'; 6 6 import { initClient } from '$lib/atproto'; 7 7 import YoutubeVideoPlayer, { videoPlayer } from '$lib/components/YoutubeVideoPlayer.svelte'; 8 + import { page } from '$app/state'; 9 + import { goto } from '$app/navigation'; 8 10 9 11 let { children } = $props(); 12 + 13 + const errorMessages: Record<string, (params: URLSearchParams) => string> = { 14 + handle_not_found: (p) => `Handle ${p.get('handle') ?? ''} not found!` 15 + }; 10 16 11 17 onMount(() => { 12 18 initClient(); 19 + 20 + const error = page.url.searchParams.get('error'); 21 + if (error) { 22 + const msg = errorMessages[error]?.(page.url.searchParams) ?? error; 23 + toast.error(msg); 24 + goto(page.url.pathname, { replaceState: true }); 25 + } 13 26 }); 14 27 </script> 15 28 16 29 {@render children()} 17 30 18 31 <ThemeToggle class="fixed top-2 left-2 z-10" /> 32 + <Toaster /> 19 33 20 34 {#if videoPlayer.id} 21 35 <YoutubeVideoPlayer />