Add custom pages and links to the <UserProfile />
component
The <UserProfile />
component supports the addition of custom pages and external links to the component's sidenav.
Before you start
To access the <UserProfile />
component, the user must select the <UserButton />
component and then select the Manage account menu item. The <UserProfile />
will open as a modal by default. You can also render the component as a dedicated page. This guide includes examples for both use cases. On the code examples, you can select one of the following two tabs to see the implementation for your preferred use case:
<UserButton />
tab: By default, the<UserButton />
setsuserProfileMode='modal'
. If you are using the default settings, then you should select this tab.Dedicated page
tab: If you do not want the<UserProfile />
to open as a modal, then you should select this tab. For these examples, you need to setuserProfileMode='navigation'
anduserProfileUrl='/user-profile'
on the<UserButton />
component.
Add a custom page
To add a custom page to the <UserProfile />
component, use the <UserButton.UserProfilePage />
component or the <UserProfile.Page />
component, depending on your use case.
Props
<UserButton.UserProfilePage />
and <UserProfile.Page />
accept the following props, all of which are required:
- Name
label
- Type
string
- Description
The name that will be displayed in the navigation sidebar for the custom page.
- Name
labelIcon
- Type
React.ReactElement
- Description
An icon displayed next to the label in the navigation sidebar.
- Name
url
- Type
string
- Description
The path segment that will be used to navigate to the custom page. For example, if the
<UserProfile />
component is rendered at/user
, then the custom page will be accessed at/user/{url}
when using path routing.
- Name
children
- Type
React.ReactElement
- Description
The content to be rendered inside the custom page.
The following example demonstrates two ways that you can render content in a custom page: as a component or as a direct child.
'use client'
import { UserButton } from '@clerk/nextjs'
const DotIcon = () => {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z" />
</svg>
)
}
const CustomPage = () => {
return (
<div>
<h1>Custom page</h1>
<p>This is the content of the custom page.</p>
</div>
)
}
export default function Home() {
return (
<header>
<UserButton>
{/* You can pass the content as a component */}
<UserButton.UserProfilePage label="Custom Page" url="custom" labelIcon={<DotIcon />}>
<CustomPage />
</UserButton.UserProfilePage>
{/* You can also pass the content as direct children */}
<UserButton.UserProfilePage label="Terms" labelIcon={<DotIcon />} url="terms">
<div>
<h1>Custom Terms Page</h1>
<p>This is the content of the custom terms page.</p>
</div>
</UserButton.UserProfilePage>
</UserButton>
</header>
)
}
'use client'
import { UserProfile } from '@clerk/nextjs'
const DotIcon = () => {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z" />
</svg>
)
}
const CustomPage = () => {
return (
<div>
<h1>Custom page</h1>
<p>This is the content of the custom page.</p>
</div>
)
}
const UserProfilePage = () => (
<UserProfile path="/user-profile" routing="path">
{/* You can pass the content as a component */}
<UserProfile.Page label="Custom Page" labelIcon={<DotIcon />} url="custom-page">
<CustomPage />
</UserProfile.Page>
{/* You can also pass the content as direct children */}
<UserProfile.Page label="Terms" labelIcon={<DotIcon />} url="terms">
<div>
<h1>Custom Terms Page</h1>
<p>This is the content of the custom terms page.</p>
</div>
</UserProfile.Page>
</UserProfile>
)
export default UserProfilePage
To add custom pages to the <UserProfile />
component using the JavaScript SDK, pass the customPages
property to the mountUserProfile()
method, as shown in the following example:
import { Clerk } from '@clerk/clerk-js'
const pubKey = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY
const clerk = new Clerk(pubKey)
await clerk.load()
document.getElementById('app').innerHTML = `
<div id="user-profile"></div>
`
const userProfileDiv = document.getElementById('user-profile')
clerk.mountUserProfile(userProfileDiv, {
customPages: [
{
url: 'custom-page',
label: 'Custom Page',
mountIcon: (el) => {
el.innerHTML = '👋'
},
unmountIcon: (el) => {
el.innerHTML = ''
},
mount: (el) => {
el.innerHTML = `
<h1><b>Custom Page</b></h1>
<p>This is the content of the custom page.</p>
`
},
unmount: (el) => {
el.innerHTML = ''
},
},
{
url: '/other-page',
label: 'Other Page',
mountIcon: (el) => {
el.innerHTML = '🌐'
},
unmountIcon: (el) => {
el.innerHTML = ''
},
},
],
})
---
import { UserButton } from '@clerk/astro/components'
---
<header>
<UserButton>
<UserButton.UserProfilePage label="Custom Page" url="custom">
<svg
slot="label-icon"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentColor"
>
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"></path>
</svg>
<div>
<h1>Custom page</h1>
<p>This is the content of the custom page.</p>
</div>
</UserButton.UserProfilePage>
</UserButton>
</header>
---
import { UserProfile } from '@clerk/astro/components'
---
<UserProfile>
<UserProfile.Page label="Custom Page" url="custom-page">
<svg
slot="label-icon"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentColor"
>
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"></path>
</svg>
<div>
<h1>Custom page</h1>
<p>This is the content of the custom page.</p>
</div>
</UserProfile.Page>
</UserProfile>
<script setup lang="ts">
import { UserButton } from '@clerk/vue'
</script>
<template>
<header>
<UserButton>
<UserButton.UserProfilePage label="Custom Page" url="custom">
<template #labelIcon>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"></path>
</svg>
</template>
<div>
<h1>Custom page</h1>
<p>This is the content of the custom page.</p>
</div>
</UserButton.UserProfilePage>
</UserButton>
</header>
</template>
<script setup lang="ts">
import { UserProfile } from '@clerk/vue'
</script>
<template>
<UserProfile>
<UserProfile.Page label="Custom Page" url="custom">
<template #labelIcon>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"></path>
</svg>
</template>
<div>
<h1>Custom page</h1>
<p>This is the content of the custom page.</p>
</div>
</UserProfile.Page>
</UserProfile>
</template>
Add a custom link
To add a custom link to the <UserProfile />
component, use the <UserButton.UserProfileLink />
component or the <UserProfile.Link />
component, depending on your use case.
Props
<UserButton.UserProfileLink />
and <UserProfile.Link />
accept the following props, all of which are required:
- Name
label
- Type
string
- Description
The name that will be displayed in the navigation sidebar for the link.
- Name
labelIcon
- Type
React.ReactElement
- Description
An icon displayed next to the label in the navigation sidebar.
- Name
url
- Type
string
- Description
The path segment that will be used to navigate to the custom page. For example, if the
<UserProfile />
component is rendered at/user
, then the custom link will be navigate to/user/{url}
when using path routing.
Example
The following example adds a custom link to the <UserProfile />
sidenav that navigates to the homepage.
'use client'
import { UserButton } from '@clerk/nextjs'
const DotIcon = () => {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z" />
</svg>
)
}
export default function Home() {
return (
<header>
<UserButton>
<UserButton.UserProfileLink label="Homepage" url="/" labelIcon={<DotIcon />} />
</UserButton>
</header>
)
}
'use client'
import { UserProfile } from '@clerk/nextjs'
const DotIcon = () => {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z" />
</svg>
)
}
const UserProfilePage = () => (
<UserProfile path="/user-profile" routing="path">
<UserProfile.Link label="Homepage" labelIcon={<DotIcon />} url="/" />
</UserProfile>
)
export default UserProfilePage
---
import { UserButton } from '@clerk/astro/components'
---
<header>
<UserButton>
<UserButton.UserProfileLink label="Homepage" url="/">
<svg
slot="label-icon"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentColor"
>
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"></path>
</svg>
</UserButton.UserProfileLink>
</UserButton>
</header>
---
import { UserProfile } from '@clerk/astro/components'
---
<UserProfile>
<UserProfile.Link label="Homepage" url="/">
<svg
slot="label-icon"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentColor"
>
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"></path>
</svg>
</UserProfile.Link>
</UserProfile>
<script setup lang="ts">
import { UserButton } from '@clerk/vue'
</script>
<template>
<header>
<UserButton>
<UserButton.UserProfileLink label="Homepage" url="/">
<template #labelIcon>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"></path>
</svg>
</template>
</UserButton.UserProfileLink>
</UserButton>
</header>
</template>
<script setup lang="ts">
import { UserProfile } from '@clerk/vue'
</script>
<template>
<UserProfile>
<UserProfile.Link label="Homepage" url="/">
<template #labelIcon>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"></path>
</svg>
</template>
</UserProfile.Link>
</UserProfile>
</template>
Reorder default routes
The <UserProfile />
component includes two default menu items: Account
and Security
, in that order. You can reorder these default items by setting the label
prop to 'account'
or 'security'
. This will target the existing default item and allow you to rearrange it.
Note that when reordering default routes, the first item in the navigation sidebar cannot be a custom link.
The following example adds a custom page as the first item in the sidenav, followed by a custom link to the homepage, and then the default account and security pages.
'use client'
import { UserButton } from '@clerk/nextjs'
const DotIcon = () => {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z" />
</svg>
)
}
const CustomPage = () => {
return (
<div>
<h1>Custom page</h1>
<p>This is the content of the custom page.</p>
</div>
)
}
export default function Home() {
return (
<header>
<UserButton>
<UserButton.UserProfilePage label="Custom Page" url="custom" labelIcon={<DotIcon />}>
<CustomPage />
</UserButton.UserProfilePage>
<UserButton.UserProfileLink label="Homepage" url="/" labelIcon={<DotIcon />} />
<UserButton.UserProfilePage label="account" />
<UserButton.UserProfilePage label="security" />
</UserButton>
</header>
)
}
'use client'
import { UserProfile } from '@clerk/nextjs'
const DotIcon = () => {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z" />
</svg>
)
}
const CustomPage = () => {
return (
<div>
<h1>Custom page</h1>
<p>This is the content of the custom page.</p>
</div>
)
}
const UserProfilePage = () => (
<UserProfile>
<UserProfile.Page label="Custom Page" url="custom" labelIcon={<DotIcon />}>
<CustomPage />
</UserProfile.Page>
<UserProfile.Link label="Homepage" url="/" labelIcon={<DotIcon />} />
<UserProfile.Page label="account" />
<UserProfile.Page label="security" />
</UserProfile>
)
export default UserProfilePage
---
import { UserButton } from '@clerk/astro/components'
---
<header>
<UserButton>
<UserButton.UserProfilePage label="Custom Page" url="custom">
<svg
slot="label-icon"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentColor"
>
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"></path>
</svg>
<div>
<h1>Custom page</h1>
<p>This is the content of the custom page.</p>
</div>
</UserButton.UserProfilePage>
<UserButton.UserProfileLink label="Homepage" url="/">
<svg
slot="label-icon"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentColor"
>
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"></path>
</svg>
</UserButton.UserProfileLink>
<UserButton.UserProfilePage label="account" />
<UserButton.UserProfilePage label="security" />
</UserButton>
</header>
---
import { UserProfile } from '@clerk/astro/components'
---
<UserProfile>
<UserProfile.Page label="Custom Page" url="custom">
<svg
slot="label-icon"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentColor"
>
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"></path>
</svg>
<div>
<h1>Custom page</h1>
<p>This is the content of the custom page.</p>
</div>
</UserProfile.Page>
<UserProfile.Link label="Homepage" url="/">
<svg
slot="label-icon"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
fill="currentColor"
>
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"></path>
</svg>
</UserProfile.Link>
<UserProfile.Page label="account" />
<UserProfile.Page label="security" />
</UserProfile>
<script setup lang="ts">
import { UserButton } from '@clerk/vue'
</script>
<template>
<UserButton>
<UserButton.UserProfilePage label="Custom Page" url="custom">
<template #labelIcon>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"></path>
</svg>
</template>
<div>
<h1>Custom page</h1>
<p>This is the content of the custom page.</p>
</div>
</UserButton.UserProfilePage>
<UserButton.UserProfileLink label="Homepage" url="/">
<template #labelIcon>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"></path>
</svg>
</template>
</UserButton.UserProfileLink>
<UserButton.UserProfilePage label="account" />
<UserButton.UserProfilePage label="security" />
</UserButton>
</template>
<script setup lang="ts">
import { UserProfile } from '@clerk/vue'
</script>
<template>
<UserProfile>
<UserProfile.Page label="Custom Page" url="custom">
<template #labelIcon>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"></path>
</svg>
</template>
<div>
<h1>Custom page</h1>
<p>This is the content of the custom page.</p>
</div>
</UserProfile.Page>
<UserProfile.Link label="Homepage" url="/">
<template #labelIcon>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor">
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z"></path>
</svg>
</template>
</UserProfile.Link>
<UserProfile.Page label="account" />
<UserProfile.Page label="security" />
</UserProfile>
</template>
Feedback
Last updated on