Menu

Change language

GitHub repo

500 Server Error

blocklayout

Full-page 500 with an isometric crashed-server illustration, HTTP code, headline, and Try again + Back to home + Contact support. Prop-driven: pass title, description, image, action labels, hrefs, and layout (`page` | `contained`). Pass `image=""` to hide the art.

Installation

$npx shadcn-svelte@latest add https://uipkge.dev/r/svelte/error-500.json
Manifest:https://uipkge.dev/r/svelte/error-500.jsonInstalls to:src/lib/components/blocks/error-500/

Variants

Loading interactive previews…

npm dependencies

Includes

Files installed (1)

  • src/lib/components/blocks/error-500/Error500.svelte5.9 kB
    <script lang="ts" module>
      export interface Error500Props {
        code?: string
        title?: string
        description?: string
        /** Replaces the HTTP response panel. Pass `''` to hide art entirely. */
        image?: string
        imageAlt?: string
        primaryLabel?: string
        secondaryLabel?: string
        tertiaryLabel?: string
        primaryHref?: string
        secondaryHref?: string
        tertiaryHref?: string
        showPrimary?: boolean
        showSecondary?: boolean
        showTertiary?: boolean
        primaryDisabled?: boolean
        secondaryDisabled?: boolean
        tertiaryDisabled?: boolean
        onPrimary?: () => void
        onSecondary?: () => void
        onTertiary?: () => void
        /** `'page'` fills the viewport; `'contained'` fits a preview or nested panel. */
        layout?: 'page' | 'contained'
        class?: string
      }
    </script>
    
    <script lang="ts">
      import { LifeBuoy, RefreshCcw } from '@lucide/svelte'
      import { cn } from '$lib/utils'
      import { Button } from '$lib/components/ui/button'
    
      let {
        code: codeOverride,
        title: titleOverride,
        description: descriptionOverride,
        image = '/illustrations/error-500.jpg',
        imageAlt = '',
        primaryLabel: primaryLabelOverride,
        secondaryLabel: secondaryLabelOverride,
        tertiaryLabel: tertiaryLabelOverride,
        primaryHref,
        secondaryHref,
        tertiaryHref,
        showPrimary = true,
        showSecondary = true,
        showTertiary = true,
        primaryDisabled = false,
        secondaryDisabled = false,
        tertiaryDisabled = false,
        onPrimary,
        onSecondary,
        onTertiary,
        layout = 'page',
        class: className,
      }: Error500Props = $props()
    
      const copy = (fallback: string, override?: string) => (override === undefined ? fallback : override)
    
      const code = $derived(copy('500', codeOverride))
      const title = $derived(copy('Something went wrong', titleOverride))
      const description = $derived(
        copy(
          'We hit an unexpected error on our side. Try again in a moment — if it keeps happening, our team is on it.',
          descriptionOverride,
        ),
      )
      const primaryLabel = $derived(copy('Try again', primaryLabelOverride))
      const secondaryLabel = $derived(copy('Back to home', secondaryLabelOverride))
      const tertiaryLabel = $derived(copy('Contact support', tertiaryLabelOverride))
    </script>
    
    <section
      data-slot="error-500"
      data-layout={layout}
      class={cn(
        'bg-background relative flex items-center overflow-hidden px-6 py-16',
        layout === 'page' ? 'min-h-svh' : 'min-h-[28rem]',
        className,
      )}
    >
      <div class="mx-auto grid w-full max-w-5xl items-center gap-10 lg:grid-cols-2 lg:gap-16">
        <div>
          {#if code}
            <p class="text-muted-foreground text-sm font-medium">HTTP {code}</p>
            <p class="mt-3 text-6xl font-semibold tracking-tighter sm:text-7xl">{code}</p>
          {/if}
          <h1 class="mt-3 text-2xl font-semibold tracking-tight sm:text-3xl">{title}</h1>
          {#if description}
            <p class="text-muted-foreground mt-4 max-w-md text-base">{description}</p>
          {/if}
          {#if showPrimary || showSecondary || showTertiary}
            <div class="mt-8 flex flex-wrap items-center gap-3">
              {#if showPrimary}
                {#if primaryHref}
                  <Button size="lg" disabled={primaryDisabled} onclick={() => onPrimary?.()}>
                    {#snippet child({ props })}
                      <a href={primaryHref} {...props}>
                        <RefreshCcw />
                        {primaryLabel}
                      </a>
                    {/snippet}
                  </Button>
                {:else}
                  <Button size="lg" disabled={primaryDisabled} onclick={() => onPrimary?.()}>
                    <RefreshCcw />
                    {primaryLabel}
                  </Button>
                {/if}
              {/if}
              {#if showSecondary}
                {#if secondaryHref}
                  <Button variant="outline" size="lg" disabled={secondaryDisabled} onclick={() => onSecondary?.()}>
                    {#snippet child({ props })}
                      <a href={secondaryHref} {...props}>
                        {secondaryLabel}
                      </a>
                    {/snippet}
                  </Button>
                {:else}
                  <Button variant="outline" size="lg" disabled={secondaryDisabled} onclick={() => onSecondary?.()}>
                    {secondaryLabel}
                  </Button>
                {/if}
              {/if}
              {#if showTertiary}
                {#if tertiaryHref}
                  <Button variant="ghost" size="lg" disabled={tertiaryDisabled} onclick={() => onTertiary?.()}>
                    {#snippet child({ props })}
                      <a href={tertiaryHref} {...props}>
                        {tertiaryLabel}
                        <LifeBuoy />
                      </a>
                    {/snippet}
                  </Button>
                {:else}
                  <Button variant="ghost" size="lg" disabled={tertiaryDisabled} onclick={() => onTertiary?.()}>
                    {tertiaryLabel}
                    <LifeBuoy />
                  </Button>
                {/if}
              {/if}
            </div>
          {/if}
        </div>
        {#if image}
          <div class="border-border bg-muted overflow-hidden rounded-xl border">
            <img src={image} alt={imageAlt} class="aspect-[4/3] w-full object-cover" />
          </div>
        {:else if image === undefined}
          <div class="border-border bg-muted/40 overflow-hidden rounded-xl border font-mono" aria-hidden="true">
            <div class="border-border text-muted-foreground truncate border-b px-3 py-2 text-xs">POST /api/v1/invoices</div>
            <div class="space-y-1 p-4 text-xs leading-relaxed">
              <p>
                <span class="text-muted-foreground">HTTP/1.1</span>
                {' '}
                <span class="text-destructive">{code || '500'} Internal Server Error</span>
              </p>
              <p class="text-muted-foreground">error: ECONNRESET</p>
              <p class="text-muted-foreground">at: Worker.run:142</p>
              <p class="text-muted-foreground">x-request-id: req_8f3c2a</p>
            </div>
          </div>
        {/if}
      </div>
    </section>
    

Raw manifest:https://uipkge.dev/r/svelte/error-500.json