Use this guide for assistance migrating from Para version 2.x to Para’s version 3.0 release.Documentation Index
Fetch the complete documentation index at: https://docs.getpara.com/llms.txt
Use this file to discover all available pages before exploring further.
Summary of Breaking Changes
The v3.0 release simplifies the modal theming system and updates the portal URL helper return shape for advanced custom UI consumers:-
foregroundColornow drives the entire UI palette — buttons, accents, rings, and primary colors are all generated from it via OKLCH color space. Previously,foregroundColorwas the text/icon color; that role is now auto-generated from the background. -
accentColoris deprecated — it still works for backward compatibility (and takes precedence overforegroundColorwhen both are provided), but you should migrate to usingforegroundColorinstead. -
Dark mode variant colors removed —
darkForegroundColor,darkBackgroundColor, anddarkAccentColorno longer exist. Just provide your dark colors asbackgroundColorandforegroundColordirectly — the system auto-detects dark/light mode from the background color lightness. -
customPalette,customFontSizes,customBorderRadiiremoved — replaced bycssOverridesfor advanced cases. -
overlayBackgroundremoved from the theme type. -
oAuthLogoVariantremoved from the theme type. -
New properties added —
foregroundMixRatioandcssOverrides. -
Portal URL helpers now return
{ url, fullUrl }- default modal users do not need to change anything, but custom UI consumers that read portal URL fields directly should review the Portal URL Return Shape section.
Beyond theming, v3 also moves most configuration (auth methods, external wallets, branding, and more) to the partner record in the Developer Portal. That change is non-breaking; your existing
paraModalConfig props keep working as a deprecated fallback, and configOverrides is available when a setting must still be controlled in code. See Configuration moves to the partner record below.Property Mapping
| v2 Property | v3 Equivalent |
|---|---|
foregroundColor | foregroundColor (new semantics: drives accent palette) |
backgroundColor | backgroundColor (unchanged) |
accentColor | foregroundColor (accentColor still accepted but deprecated) |
darkForegroundColor | Removed — provide dark colors via foregroundColor directly |
darkBackgroundColor | Removed — provide dark colors via backgroundColor directly |
darkAccentColor | Removed — provide dark colors via foregroundColor directly |
overlayBackground | Removed |
oAuthLogoVariant | Removed |
customPalette | cssOverrides |
customFontSizes | cssOverrides |
customBorderRadii | cssOverrides |
mode | mode (unchanged) |
borderRadius | borderRadius (unchanged) |
font | font (unchanged) |
| — | foregroundMixRatio (new, default 0.04) |
| — | cssOverrides (new) |
Before & After
In most cases, the v3.0 theme is dramatically simpler. The OKLCH color generation system automatically produces a harmonious palette from your
foregroundColor and backgroundColor. Only use cssOverrides if you need to fine-tune specific generated colors.Detailed Changes
Color Properties Simplified
Color Properties Simplified
What changed: If the auto-detection misclassifies your background color (e.g., a color near the light/dark boundary), use
foregroundColor previously set the text and icon color. In v3, it sets the primary interactive color (buttons, accents, rings, links) and the text color is auto-generated from the background lightness.accentColor deprecated: If you were using accentColor to set the interactive color, rename it to foregroundColor. If you pass both, accentColor takes precedence for backward compatibility.Dark mode variants removed: Instead of maintaining separate darkForegroundColor, darkBackgroundColor, and darkAccentColor, provide your dark colors directly as backgroundColor and foregroundColor. The system auto-detects dark mode from the background color lightness:mode to override it:Custom Palette → CSS Overrides
Custom Palette → CSS Overrides
What changed: The deeply nested See the Style the Modal guide for the full list of available CSS variables.
customPalette, customFontSizes, and customBorderRadii objects have been replaced by a flat cssOverrides map.Migration: Identify the specific colors you customized and map them to CSS custom properties:Removed Properties
Removed Properties
overlayBackground — The modal overlay backdrop styling is no longer configurable through the theme. Use the className prop on paraModalConfig for custom overlay styling if needed.oAuthLogoVariant — The OAuth provider logo variant ('dark' | 'light' | 'default') has been removed. Logos are automatically styled based on the theme mode.New Properties
New Properties
foregroundMixRatio (default: 0.04): Controls how much the foregroundColor mixes into UI surfaces like buttons, inputs, and borders. Useful for fine-tuning the visual weight of your accent color across the interface.cssOverrides — A Record<string, string> for setting raw CSS custom properties after theme generation. This is an advanced escape hatch for overriding specific generated colors without affecting the rest of the palette.Backward Compatibility
Existing v2.x theme configurations will largely continue to work:
accentColoris still accepted and maps toforegroundColorbackgroundColor,mode,borderRadius, andfontwork identically- Unknown properties (like
darkForegroundColororcustomPalette) are silently ignored
accentColor to foregroundColor to avoid deprecation warnings, and replacing customPalette with cssOverrides if you used advanced palette customization.Configuration moves to the partner record
In v3, your partner record (managed in the Developer Portal) is the source of truth for most configuration, including authentication methods, theme, external wallets, links, and more. The SDK reads that record at runtime, then applies any explicitconfigOverrides. The matching paraModalConfig props still work but are now deprecated: they’re the lowest-priority fallback and will be removed in the next major release. Each logs a one-time deprecation warning.
This change is non-breaking. If you upgrade without touching the Developer Portal, your existing props keep working exactly as before — migrate at your own pace. For the full model (layering,
configOverrides, enforcement), see How Configuration Works.What to do instead
Move each setting to the partner record in the Developer Portal. For overrides that must live in code (e.g. one API key powering multiple brand contexts), use theconfigOverrides prop on ParaProvider instead of paraModalConfig.
Deprecated paraModalConfig prop | Configure instead |
|---|---|
oAuthMethods | Portal → Authentication, or configOverrides.authConfig.oAuthMethods |
disableEmailLogin / disablePhoneLogin | Portal → Authentication, or configOverrides.authConfig.* |
twoFactorAuthEnabled | Portal → Authentication, or configOverrides.authConfig.twoFactorAuthEnabled |
isGuestModeEnabled | Portal → Authentication, or configOverrides.authConfig.isGuestModeEnabled |
authLayout | Portal → Authentication, or configOverrides.modalConfig.authLayout |
hideWallets | Portal, or configOverrides.modalConfig.hideWallets |
theme | Portal → Branding, or configOverrides.themeConfig |
logo | Portal → Branding, or configOverrides.modalConfig.logo |
supportedAccountLinks | Portal (partner-authoritative) |
balances | Portal (partner-authoritative) |
Before & After
New enforcement behavior
Because the SDK now enforces the resolved auth and wallet configuration at its entry points, calling a method for something that is explicitly disabled throws aPartnerConfigError (with a stable .code, e.g. GUEST_MODE_DISABLED). This applies to direct SDK calls and custom UI; the default <ParaModal /> simply hides disabled options.
Portal URL Return Shape
v3.0 introduces companion*FullUrl fields on the auth state types and changes the internal portal URL helpers to return { url, fullUrl } instead of a bare string. This powers the new preloaded portal iframe — navigating a preloaded iframe to a shortened URL forces a redirect that negates the preload, so the SDK now surfaces the unshortened URL alongside the (possibly shortened) one.
Who needs to care
- Default modal users (
<ParaModal />): No action required. The modal consumes the new fields internally. - Custom UI consumers (callers of
signUpOrLogIn,verifyOAuth,verifyNewAccount,onStatePhaseChange, etc. who readpasskeyUrl/passwordUrl/pinUrl/loginUrlthemselves): read the note below. - Callers of
PortalUrlService.constructPortalUrl/PortalUrlService.getLoginUrl, or subclasses that callParaCore.constructPortalUrldirectly: the return value is now{ url, fullUrl }instead ofstring. Update your call sites to destructure.
What changed on the auth state types
AuthStateVerify, AuthStateLogin, and AuthStateSignup each gained optional *FullUrl siblings next to their existing URL fields:
| Existing field | New companion field | Where it appears |
|---|---|---|
loginUrl | loginFullUrl | AuthStateVerify |
passkeyUrl | passkeyFullUrl | AuthStateLogin, AuthStateSignup |
passwordUrl | passwordFullUrl | AuthStateLogin, AuthStateSignup |
pinUrl | pinFullUrl | AuthStateLogin, AuthStateSignup |
useShortUrls is false (the default), *Url and *FullUrl hold the same value. When useShortUrls is true, *Url is the shortened URL and *FullUrl is the unshortened one.
The same fields are mirrored on authStateInfo exposed by onStatePhaseChange / useParaStatus: passkeyFullUrl, passwordFullUrl, pinFullUrl, and verificationFullUrl.
The OAuth callback signature also picked up the full URL as a second argument:
Picking which URL to open
Opening in a popup or new tab (passkeys, QR codes, email handoff)
Opening in a popup or new tab (passkeys, QR codes, email handoff)
Keep using the existing
passkeyUrl / passwordUrl / pinUrl / loginUrl / url values. You get short URLs when you opt in via useShortUrls: true, which is still the right call for QR codes and links you pass around.Navigating a preloaded portal iframe
Navigating a preloaded portal iframe
Custom UI example
Service-layer callers (advanced)
If you callPortalUrlService directly, or subclass ParaCore and call constructPortalUrl, the method signatures changed:
ParaCore.getLoginUrl(), ParaCore.getOAuthUrl(), and ParaCore.addCredential() still return a bare string; those are unchanged.