Upgrading to Clerk Core 2
Overview
In April 2024, we updated Clerk's SDKs to include Core 2. This new core includes:
- 💅 Redesigned and improved component UIs.
- 🔪 The 401 & "flash of white page" that was visible sometimes when syncing auth state was eliminated.
- 🧹 A large number of smaller housekeeping changes, bugfixes, and improvements.
- 📊 Telemetry to allow us to better determine feature usage and priority (easy opt-out if you don't like this)
Component redesign
The new version ships with improved design and UX across all of Clerk's UI components. If you have used the appearance prop or tokens for a custom theme, you will likely need to make some adjustments to ensure your styling is still looking great. If you're using the localization prop you will likely need to make adjustments to account for added or removed localization keys.
The sections below contain more info on each change made to the customization ids and localization keys for reference. Regardless of how thoroughly you have reviewed the following information, we still recommend that you ensure that you have taken some time to manually look through each of your views to ensure that everything looks good still.
Appearance Changes
Within <UserProfile />, Multi-Factor Auth is Added via Dropdown
<UserProfile />, Multi-Factor Auth is Added via DropdownWithin the <UserProfile /> component (which is also rendered by <UserButton />), adding a multi-factor auth (MFA) method is now rendered as a dropdown instead of a modal. If you were relying on the modal for any sort of customizations, these customizations will need to be adjusted to the new form factor.
Two new appearance prop keys were added to aid with this process: cl-menuList__mfa for styling the list of MFA factors, and cl-menuItem__mfa for styling individual items.
Breaking Changes to appearance variables
Several appearance variables have been removed or renamed. If you were using these variables in your application, you will need to update your code to use the new variables.
- The
fontSmoothingvariable has been removed. - The
shadowShimmervariable has been removed. - The
colorAlphaShadevariable has been renamed tocolorNeutral.
Settings -> General tab in OrganizationProfile
Settings -> General tab in OrganizationProfileThe "Settings" tab within the <OrganizationProfile /> component has been renamed to "General". If you are linking directly to /organization-settings from anywhere, the link will need to be updated to /organization-general.
If you are customizing the component by re-ordering the pages, the label used to target this page must be changed from settings to general as well.
If you are using the appearance prop to customize the appearance of the <OrganizationProfile /> component, note that the cl-profilePage__organizationSettings key has also been changed to cl-profilePage__organizationGeneral to be consistent with the naming change.
Within <UserProfile />, Account and Security Pages Separated
<UserProfile />, Account and Security Pages SeparatedWithin the <UserProfile /> component (which is also rendered by <UserButton />), the "Account" and "Security" pages now live within their own tabs. Previously, "Security" was a section within the "Account" tab. The "Security" page can now be directly linked to under the /security path if desired.
Within <UserProfile />, Connected Accounts Added via Dropdown
<UserProfile />, Connected Accounts Added via DropdownWithin the <UserProfile /> component (which is also rendered by <UserButton />), adding a connected account is now rendered as a dropdown instead of a modal. If you were relying on the modal for any sort of customizations, these customizations will need to be adjusted to the new form factor.
New appearance prop keys were added to aid with customization, if desired:
cl-menuList__connectedAccountsfor styling the list of connected account addition optionscl-menuItem__connectedAccountsfor styling individual items in the connected account options listcl-menuList__web3Walletsfor styling the list of web3 wallet addition optionscl-menuItem__web3Walletsfor styling individual items in the web3 wallets options list
userButtonPopoverActionButtonText customization id removed
userButtonPopoverActionButtonText customization id removedThe userButtonPopoverActionButtonText customization id has been removed, as the text for this button is now directly rendered inside the button rather than an extra wrapping element. The nested ids userButtonPopoverActionButtonText__signOut and userButtonPopoverActionButtonText__manageAccount have also been removed. Any styling that needs to apply to the text can be applied to its direct parent cl-userButtonPopoverActionButton.
userButtonBox is now a child of userButtonTrigger
userButtonBox is now a child of userButtonTriggerThe parent-child relationship of the two elements userButtonTrigger and userButtonBox has been swapped. Previously, userButtonTrigger was nested inside of userButtonBox, and now userButtonBox is nested inside of userButtonTrigger. This change resolves some usability issues in <UserButton />. If you are applying style customization to either of these elements, your customizations may need to be adjusted.
organizationSwitcherPopoverActionButtonText customization id removed
organizationSwitcherPopoverActionButtonText customization id removedThe organizationSwitcherPopoverActionButtonText customization id has been removed, as the text for this button is now directly rendered inside the button rather than an extra wrapping element. The nested ids organizationSwitcherPopoverActionButtonText__manageOrganization and organizationSwitcherPopoverActionButtonText__createOrganization have also been removed. Any styling that needs to apply to the text can be applied to its direct parent cl-organizationSwitcherPopoverActionButton.
Changes to the card customization id
card customization idThe card customization id in the previous major version was the main and only container element for components. Outside the card element, a new cardBox id was introduced that allows more fine-grained style customization.
As a note, if you are changing the background color of card, you will also need to also apply the same color on the footer id as well. The footer now gray by default, and it’s located outside card, but inside cardBox.
A footerItem id was also added for more targeted styling of items inside the footer.
Back button customization ids change on alternative 2fa methods page
The "back" button on the panel within <SignIn /> that lists out alternative two factor auth methods has changed location, and there have been some changes to the ids as a result of this:
headerBackIconhas been removed, as there is no longer an associated iconheaderBackRowhas been renamed tobackRowas it's no longer in the headerheaderBackLinkhas been renamed tobackLinkas it's no longer in the header
button -> organizationListCreateOrganizationActionButton customization id
button -> organizationListCreateOrganizationActionButton customization idThe button customization id was used only in one place, for a button to create a new organization in the <OrganizationList /> component. This id has been removed and replaced by the more appropriately named organizationListCreateOrganizationActionButton customization id instead.
socialButtonsBlockButtonArrow customization id removed
socialButtonsBlockButtonArrow customization id removedSocial sign-in buttons in the new component designs no longer include arrows, so the socialButtonsBlockButtonArrow customization id has been removed. You can use the socialButtonsIconButton to apply custom styling to the social buttons if desired.
Identity preview avatar customization ids removed
When signing in with the <SignIn /> component, after entering a username or email the user is brought to a second pane where they can enter a second factor such as a password. On this pane, there is an area called "identity preview" that shows the username/email that they are entering a password/etc for. Previously, this area included the user's avatar, but this is no longer the case in updated designs. As such, the customization ids related to the user's avatar have been removed.
Changes to default variables
The default values of some appearance variables have changed which may impact your UI (if you are not already overriding them).
- The default
colorPrimaryvalue changed from#103FEFto#2F3037. As the new color is a dark grey, thecolorPrimaryof the dark theme was changed to#FFFFFF. - The default
fontSizevalue changed from1remto0.8125rem - The default
fontWeightvalues changed from{ normal: 400, medium: 500, bold: 600 }to{ normal: 400, medium: 500, semibold: 600, bold: 700 }.
New localization keys added
As part of the redesign of Clerk's components, a number of new localization keys have been added and can be seen along with their default english values in the code block below. If you do not supply translated values for these keys in your custom localization, they will fall back to the default english values specified below.
const newValues = {
formButtonPrimary__verify: 'Verify',
formFieldInputPlaceholder__confirmDeletionUserAccount: 'Delete account',
organizationProfile: {
invitePage: {
selectDropdown__role: 'Select role',
},
navbar: {
description: 'Manage your organization.',
general: 'General',
members: 'Members',
title: 'Organization',
},
profilePage: {
domainSection: {
menuAction__manage: 'Manage',
menuAction__remove: 'Delete',
menuAction__verify: 'Verify',
},
},
start: {
headerTitle__general: 'General',
profileSection: {
primaryButton: 'Edit profile',
title: 'Organization Profile',
uploadAction__title: 'Logo',
},
},
verifiedDomainPage: {
title: 'Update {{domain}}',
},
},
signIn: {
accountSwitcher: {
action__addAccount: 'Add account',
action__signOutAll: 'Sign out of all accounts',
subtitle: 'Select the account with which you wish to continue.',
title: 'Choose an account',
},
alternativeMethods: {
actionText: 'Don’t have any of these?',
subtitle: 'Facing issues? You can use any of these methods to sign in.',
},
forgotPassword: {
subtitle_email: 'First, enter the code sent to your email ID',
subtitle_phone: 'First, enter the code sent to your phone',
title: 'Reset password',
},
},
unstable__errors: {
form_param_format_invalid__phone_number: 'Phone number must be in a valid international format',
},
userProfile: {
emailAddressPage: {
verifyTitle: 'Verify email address',
},
formButtonPrimary__add: 'Add',
formButtonPrimary__remove: 'Remove',
formButtonPrimary__save: 'Save',
mfaPhoneCodePage: {
backButton: 'Use existing number',
successMessage1:
'When signing in, you will need to enter a verification code sent to this phone number as an additional step.',
successMessage2:
'Save these backup codes and store them somewhere safe. If you lose access to your authentication device, you can use backup codes to sign in.',
successTitle: 'SMS code verification enabled',
},
navbar: {
account: 'Profile',
description: 'Manage your account info.',
security: 'Security',
title: 'Account',
},
phoneNumberPage: {
verifySubtitle: 'Enter the verification code sent to {{identifier}}',
verifyTitle: 'Verify phone number',
},
start: {
profileSection: {
primaryButton: 'Edit profile',
},
},
},
}Removed localization keys
As part of the redesign of Clerk's components, a number of localization keys have been removed as they were no longer present in the new designs. You should remove any of these keys that are present in your localization object as they are no longer needed.
const deletedKeys = [
'formFieldLabel__emailAddress_phoneNumber',
'formFieldLabel__phoneNumber_username',
'formFieldLabel__emailAddress_phoneNumber_username',
'formFieldInputPlaceholder__emailAddress_phoneNumber',
'formFieldInputPlaceholder__phoneNumber_username',
'formFieldInputPlaceholder__emailAddress_phoneNumber_username',
'signIn.forgotPassword.title_email',
'signIn.forgotPassword.title_phone',
'signIn.forgotPassword.formSubtitle_email',
'signIn.forgotPassword.formSubtitle_phone',
'signIn.emailCode.formSubtitle',
'signIn.phoneCode.formSubtitle',
'signIn.phoneCodeMfa.formSubtitle',
'signIn.totpMfa.formSubtitle',
'signIn.backupCodeMfa.formTitle',
'signIn.backupCodeMfa.formSubtitle',
'userProfile.start.headerSubtitle__account',
'userProfile.start.headerSubtitle__security',
'userProfile.start.emailAddressesSection.detailsTitle__primary',
'userProfile.start.emailAddressesSection.detailsSubtitle__primary',
'userProfile.start.emailAddressesSection.detailsTitle__nonPrimary',
'userProfile.start.emailAddressesSection.detailsSubtitle__nonPrimary',
'userProfile.start.emailAddressesSection.detailsTitle__unverified',
'userProfile.start.emailAddressesSection.detailsSubtitle__unverified',
'userProfile.start.emailAddressesSection.destructiveActionTitle',
'userProfile.start.emailAddressesSection.destructiveActionSubtitle',
'userProfile.start.phoneNumbersSection.detailsTitle__primary',
'userProfile.start.phoneNumbersSection.detailsSubtitle__primary',
'userProfile.start.phoneNumbersSection.detailsTitle__nonPrimary',
'userProfile.start.phoneNumbersSection.detailsSubtitle__nonPrimary',
'userProfile.start.phoneNumbersSection.detailsTitle__unverified',
'userProfile.start.phoneNumbersSection.detailsSubtitle__unverified',
'userProfile.start.phoneNumbersSection.destructiveActionTitle',
'userProfile.start.phoneNumbersSection.destructiveActionSubtitle',
'userProfile.start.connectedAccountsSection.title__connectionFailed',
'userProfile.start.connectedAccountsSection.title__connectionFailed',
'userProfile.start.connectedAccountsSection.title__reauthorize',
'userProfile.start.connectedAccountsSection.actionLabel__connectionFailed',
'userProfile.start.connectedAccountsSection.destructiveActionSubtitle',
'userProfile.start.connectedAccountsSection.destructiveActionAccordionSubtitle',
'userProfile.start.mfaSection.phoneCode.destructiveActionTitle',
'userProfile.start.mfaSection.phoneCode.destructiveActionSubtitle',
'userProfile.start.mfaSection.phoneCode.title__default',
'userProfile.start.mfaSection.phoneCode.title__setDefault',
'userProfile.start.mfaSection.phoneCode.subtitle__default',
'userProfile.start.mfaSection.phoneCode.subtitle__setDefault',
'userProfile.start.mfaSection.totp.title',
'userProfile.start.mfaSection.totp.subtitle',
'userProfile.start.mfaSection.totp.destructiveActionSubtitle',
'userProfile.start.mfaSection.totp.destructiveActionLabel',
'userProfile.start.activeDevicesSection.primaryButton',
'userProfile.start.activeDevicesSection.detailsTitle',
'userProfile.start.activeDevicesSection.detailsSubtitle',
'userProfile.start.activeDevicesSection.destructiveActionTitle',
'userProfile.start.activeDevicesSection.destructiveActionSubtitle',
'userProfile.start.web3WalletsSection.destructiveActionTitle',
'userProfile.start.web3WalletsSection.destructiveActionSubtitle',
'userProfile.start.dangerSection.deleteAccountTitle',
'userProfile.start.dangerSection.deleteAccountDescription',
'userProfile.profilePage.fileDropAreaTitle',
'userProfile.profilePage.fileDropAreaAction',
'userProfile.phoneNumberPage.infoText__secondary',
'userProfile.mfaPhoneCodePage.successMessage',
'organizationProfile.start.headerTitle__settings',
'organizationProfile.start.headerSubtitle__members',
'organizationProfile.start.headerSubtitle__settings',
'organizationProfile.profilePage.subtitle',
'organizationProfile.profilePage.domainSection.unverifiedDomain_menuAction__verify',
'organizationProfile.profilePage.domainSection.unverifiedDomain_menuAction__remove',
'organizationProfile.membersPage.start.headerTitle__active',
'organizationProfile.membersPage.start.headerTitle__invited',
'organizationProfile.membersPage.invitationsTab.manualInvitations.headerTitle',
'organizationProfile.membersPage.invitationsTab.manualInvitations.headerSubtitle',
'organizationProfile.membersPage.requestsTab.requests.headerTitle',
'organizationProfile.membersPage.requestsTab.requests.headerSubtitle',
'createOrganization.subtitle',
]If you'd like to automate this, you can use the lodash omit function as such:
import { omit } from 'lodash-es'
const localization = omit(yourOldObject, deletedKeys)Localization keys changed
The values of some keys have been changed on the default en-US localization object. The list below shows you the new defaults (as of writing this guide) which you can either use or overwrite. If you have overridden these values, make sure to double check so you can be sure that your modifications are appropriate.
const changedValues = {
formFieldLabel__organizationName: 'Name',
formFieldLabel__organizationSlug: 'Slug',
formFieldInputPlaceholder__emailAddresses: 'example@email.com, example2@email.com',
formFieldInputPlaceholder__organizationSlug: 'my-org',
signUp: {
start: {
subtitle: 'Welcome! Please fill in the details to get started.',
actionText: 'Already have an account?',
},
emailCode: {
subtitle: 'Enter the verification code sent to your email',
},
phoneCode: {
subtitle: 'Enter the verification code sent to your phone',
},
continue: {
subtitle: 'Please fill in the remaining details to continue.',
actionText: 'Already have an account?',
},
},
signIn: {
start: {
title: 'Sign in to {{applicationName}}',
subtitle: 'Welcome back! Please sign in to continue',
actionText: 'Don’t have an account?',
},
password: {
subtitle: 'Enter the password associated with your account',
},
forgotPasswordAlternativeMethods: {
label__alternativeMethods: 'Or, sign in with another method',
},
resetPassword: {
title: 'Set new password',
},
phoneCodeMfa: {
subtitle: 'To continue, please enter the verification code sent to your phone',
},
totpMfa: {
subtitle:
'To continue, please enter the verification code generated by your authenticator app',
},
backupCodeMfa: {
subtitle: 'Your backup code is the one you got when setting up two-step authentication.',
},
},
userProfile: {
start: {
headerTitle__account: 'Profile details',
emailAddressesSection: {
primaryButton: 'Add email address',
detailsAction__unverified: 'Verify',
destructiveAction: 'Remove email',
},
phoneNumbersSection: {
primaryButton: 'Add phone number',
},
mfaSection: {
phoneCode: {
destructiveActionLabel: 'Remove',
},
backupCodes: {
actionLabel__regenerate: 'Regenerate',
},
},
dangerSection: {
title: 'Delete account',
deleteAccountButton: 'Delete account',
},
},
profilePage: {
imageFormSubtitle: 'Upload',
imageFormDestructiveActionSubtitle: 'Remove',
fileDropAreaHint: 'Recommended size 1:1, up to 10MB.',
},
phoneNumberPage: {
infoText:
'A text message containing a verification code will be sent to this phone number. Message and data rates may apply.',
},
connectedAccountPage: {
socialButtonsBlockButton: '{{provider|titleize}}',
},
mfaPhoneCodePage: {
primaryButton__addPhoneNumber: 'Add phone number',
subtitle__availablePhoneNumbers:
'Select an existing phone number to register for SMS code two-step verification or add a new one.',
subtitle__unavailablePhoneNumbers:
'There are no available phone numbers to register for SMS code two-step verification, please add a new one.',
},
deletePage: {
actionDescription: "Type 'Delete account' below to continue.",
},
},
organizationSwitcher: {
action__createOrganization: 'Create organization',
action__manageOrganization: 'Manage',
},
organizationProfile: {
profilePage: {
title: 'Update Profile',
dangerSection: {
leaveOrganization: {
actionDescription: "Type '{{organizationName}}' below to continue.",
},
deleteOrganization: {
actionDescription: "Type '{{organizationName}}' below to continue.",
},
},
},
invitePage: {
title: 'Invite new members',
subtitle: 'Enter or paste one or more email addresses, separated by spaces or commas.',
},
},
createOrganization: {
title: 'Create organization',
},
organizationList: {
title: 'Choose an account',
titleWithoutPersonal: 'Choose an organization',
},
}SDK Guides
Core 2 brings both UI changes and breaking code changes, so each SDK has been updated to a new major version. We expect upgrades to take less than 30 minutes, and are providing a CLI tool to assist with the process. Select your SDK below to get started:
Note that the Go, and Ruby SDKs do not yet have a Core 2 release ready - if you are using any of these SDKs there is nothing actionable right now.
Feedback
Last updated on