Discussion on rendering links in Portabletext with @portabletext/svelte and potential solutions
You're right that links not rendering in @portabletext/svelte is a common issue! The key thing is that you need to provide custom components for marks like links – they don't render automatically out of the box.
The Solution
The @portabletext/svelte package requires you to pass custom components through the components prop (not serializers as some older examples might show). Here's how to handle link rendering:
<script>
import {PortableText} from '@portabletext/svelte'
import Link from './Link.svelte' // Your custom link component
</script>
<PortableText
value={yourBlocks}
components={{
marks: {
link: Link
}
}}
/>Then create your Link.svelte component:
<script lang="ts">
import type {MarkComponentProps} from '@portabletext/svelte'
import {Snippet} from 'svelte'
interface Props {
portableText: MarkComponentProps<{href?: string}>
children: Snippet
}
let {portableText, children}: Props = $props()
let {value} = $derived(portableText)
</script>
{#if value.href}
<a href={value.href}>
{@render children()}
</a>
{:else}
{@render children()}
{/if}Important Notes
For Svelte 5+: The library requires Svelte 5.0.0 or higher and uses the modern runes syntax ($props(), $derived()) as shown above. The components prop structure is the current standard.
Your schema is fine: The standard Portable Text block type in Sanity Studio already includes link annotations by default – the issue is purely on the rendering side with how @portabletext/svelte handles marks.
Why links need custom components: The library doesn't provide default implementations for annotation marks (like links with href data), only for decorator marks (like strong or em). This is by design since link rendering often needs customization (external link icons, target="_blank", routing library integration, etc.).
You can check out the official svelte-portabletext repository for more examples of customizing marks, blocks, and other components!
Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.