Svelte
Learn how to use Permix with Svelte applications
Overview
Permix provides official Svelte integration through the PermixProvider component and usePermix hook. This allows you to manage permissions reactively in your Svelte app using runes.
Before getting started with Svelte integration, make sure you've completed the initial setup steps in the Quick Start guide. Svelte integration requires Svelte 5.
Setup
First, wrap your application with the PermixProvider:
<script lang="ts">
import { PermixProvider } from 'permix/svelte'
import { permix } from './lib/permix'
let { children } = $props()
</script>
<PermixProvider {permix}>
{@render children()}
</PermixProvider>Remember to always pass the same Permix instance to both the PermixProvider and usePermix hook to maintain type safety.
Hook
For checking permissions in your components, you can use the usePermix hook. And to avoid importing the hook and Permix instance in every component, you can create a custom utility:
import { usePermix } from 'permix/svelte'
import { permix } from './permix'
export function usePermissions() {
return usePermix(permix)
}Components
If you prefer using components, you can import the createComponents function from permix/svelte and create checking components:
import { createComponents } from 'permix/svelte'
// ...
export const { Check } = createComponents(permix)And then you can use the Check component in your components. The default content is rendered when a user has permission, and the otherwise snippet is rendered when they don't:
<script lang="ts">
import { Check } from './lib/permix'
</script>
<!--
reverse: Will flip the logic of the permission check
otherwise: Will show this if a user doesn't have permission
-->
<Check path="post.create" reverse>
Will show this if a user has permission
{#snippet otherwise()}
Will show this if a user doesn't have permission
{/snippet}
</Check>Usage
Use the usePermix hook and checking components in your components:
<script lang="ts">
import { usePermix } from 'permix/svelte'
import { permix } from './lib/permix'
import { Check } from './lib/permix'
let { post } = $props()
const permissions = usePermix(permix)
</script>
<div>
{#if !permissions.isReady}
<div>Loading permissions...</div>
{:else if permissions.check('post.edit', post)}
<button>Edit Post</button>
{:else}
<p>You don't have permission to edit this post</p>
{/if}
<Check path="post.create">
Can I create a post inside the Check component?
</Check>
</div>usePermix returns an object with a reactive isReady getter and a check method. Access them directly on the returned object (for example permissions.isReady) to keep reactivity — don't destructure isReady.
Hydration
For SSR, wrap the app with PermixHydrate and pass the dehydrated server state. Call permix.setup() on the client afterward to restore function-based rules and set isReady:
<script lang="ts">
import type { DehydratedState } from 'permix'
import { onMount } from 'svelte'
import { PermixHydrate, PermixProvider } from 'permix/svelte'
import { permix } from './lib/permix'
import { getClientRules } from './lib/permissions'
let { children, dehydratedState }: {
children: import('svelte').Snippet
dehydratedState: DehydratedState<any>
} = $props()
onMount(() => {
permix.setup(getClientRules())
})
</script>
<PermixProvider {permix}>
<PermixHydrate state={dehydratedState}>
{@render children()}
</PermixHydrate>
</PermixProvider>See the Hydration guide.