| name | clerk-custom-ui |
| description | Custom authentication flows and component appearance - hooks (useSignIn, useSignUp), themes, colors, fonts, CSS. Use for custom sign-in/sign-up flows, appearance styling, visual customization, branding. |
| allowed-tools | WebFetch |
| license | MIT |
| metadata | {"author":"clerk","version":"2.1.0"} |
Custom UI
Prerequisite: Ensure ClerkProvider wraps your app. See setup/.
Version: Check package.json for the SDK version — see clerk skill for the version table. This determines which
custom flow references to use below.
This skill covers two areas:
- Custom authentication flows — build your own sign-in/sign-up UI with hooks
- Appearance customization — theme, style, and brand Clerk's pre-built components
Custom Flow References
| Task | Core 2 | Current |
|---|
| Custom sign-in (useSignIn) | core-2/custom-sign-in.md | core-3/custom-sign-in.md |
| Custom sign-up (useSignUp) | core-2/custom-sign-up.md | core-3/custom-sign-up.md |
<Show> component | (use <SignedIn>, <SignedOut>, <Protect>) | core-3/show-component.md |
Appearance Customization
Appearance customization applies to both Core 2 and the current SDK.
Component Customization Options
Appearance Pattern
<SignIn
appearance={{
variables: {
colorPrimary: '#0000ff',
borderRadius: '0.5rem',
},
options: {
logoImageUrl: '/logo.png',
socialButtonsVariant: 'iconButton',
},
}}
/>
Core 2 ONLY (skip if current SDK): The options property was named layout. Use
layout: { logoImageUrl: '...', socialButtonsVariant: '...' } instead of options.
variables (colors, typography, borders)
| Property | Description |
|---|
colorPrimary | Primary color throughout |
colorBackground | Background color |
borderRadius | Border radius (default: 0.375rem) |
Opacity change: colorRing and colorModalBackdrop now render at full opacity. Use explicit rgba() values if you
need transparency.
Core 2 ONLY (skip if current SDK): colorRing and colorModalBackdrop rendered at 15% opacity by default.
options (structure, logo, social buttons)
| Property | Description |
|---|
logoImageUrl | URL to custom logo |
socialButtonsVariant | 'blockButton' | 'iconButton' | 'auto' |
socialButtonsPlacement | 'top' | 'bottom' |
showOptionalFields | Show optional fields (default: false) |
Core 2 ONLY (skip if current SDK): This property is called layout, not options. Also, showOptionalFields
defaulted to true.
Themes
Install themes from @clerk/ui:
npm install @clerk/ui
import { dark } from '@clerk/ui/themes'
<ClerkProvider appearance={{ theme: dark }} />
Core 2 ONLY (skip if current SDK): Themes are imported from @clerk/themes (install @clerk/themes instead of
@clerk/ui). Example: import { dark } from '@clerk/themes'.
Theme stacking — pass an array where the last theme takes precedence:
import { dark, neobrutalism } from '@clerk/ui/themes'
<ClerkProvider appearance={{ theme: [dark, neobrutalism] }} />
CSS color-scheme support — the default theme respects the CSS color-scheme property for automatic light/dark
mode toggling.
Available themes: dark, neobrutalism, shadcn, simple
shadcn Theme (HIGH PRIORITY)
IMPORTANT: If the project has components.json (shadcn/ui installed), ALWAYS apply the shadcn theme as the FIRST
customization step. This ensures Clerk components visually match the existing shadcn design system. Skip this only if
the user explicitly requests a different theme.
If the project uses shadcn/ui (check for components.json in the project root), always use the shadcn theme:
import { shadcn } from '@clerk/ui/themes'
<ClerkProvider appearance={{ theme: shadcn }} />
Also import shadcn CSS in your global styles:
@import "../../../node_modules/tailwindcss/dist/lib.d.mts";
@import "@clerk/ui/themes/shadcn.css";
Core 2 ONLY (skip if current SDK): Import from @clerk/themes and @clerk/themes/shadcn.css:
import { shadcn } from "@clerk/themes";
@import "@clerk/themes/shadcn.css";
Workflow
- Identify customization needs (custom flow or appearance)
- For custom flows: check SDK version → read appropriate
core-2/ or core-3/ reference
- For appearance: WebFetch the appropriate documentation from table above
- Apply appearance prop to your Clerk components or build custom flow with hooks
Common Pitfalls
| Issue | Solution |
|---|
| Colors not applying | Use colorPrimary not primaryColor |
| Logo not showing | Put logoImageUrl inside options: {} (or layout: {} in Core 2) |
| Social buttons wrong | Add socialButtonsVariant: 'iconButton' in options (or layout in Core 2) |
| Styling not working | Use appearance prop, not direct CSS (unless with bring-your-own-css) |
| Hook returns different shape | Check SDK version — Core 2 and current have completely different useSignIn/useSignUp APIs |