# Customizing the Logto Sign-In Experience and UI: A Complete Guide to Runtime Configuration

> Customize the Logto sign-in experience and UI with runtime configuration. Easily update branding, connectors, and security policies without code changes. Learn how in this complete guide.

- Repository: [Logto/logto](https://github.com/logto-io/logto)
- Tags: how-to-guide
- Published: 2026-07-04

---

**Logto provides a runtime-configurable sign-in UI that renders authentication flows based on tenant-specific settings fetched from the `/api/.well-known/experience` endpoint, requiring no code changes to update branding, connectors, or security policies.**

Logto is an open-source identity infrastructure that separates authentication logic from presentation. The `logto-io/logto` repository implements a dynamic sign-in experience where all UI elements—from logos to multi-factor authentication rules—are controlled via a JSON configuration stored in the database and consumed by the Experience package at runtime.

## How Runtime Configuration Drives the UI

The sign-in experience initializes through a React context hierarchy that fetches tenant settings before rendering any authentication components.

In [`packages/experience/src/Providers/SettingsProvider/use-sign-in-experience.ts`](https://github.com/logto-io/logto/blob/main/packages/experience/src/Providers/SettingsProvider/use-sign-in-experience.ts), the `SettingsProvider` loads the configuration and initializes internationalization:

```typescript
// packages/experience/src/Providers/SettingsProvider/use-sign-in-experience.ts
const [settings] = await Promise.all([getSignInExperienceSettings(), initI18n()]);
setExperienceSettings(settings);

```

These settings propagate through `PageContext` and are consumed throughout the application. The provider in [`packages/experience/src/Providers/SettingsProvider/index.tsx`](https://github.com/logto-io/logto/blob/main/packages/experience/src/Providers/SettingsProvider/index.tsx) conditionally renders children only after configuration loads:

```typescript
// packages/experience/src/Providers/SettingsProvider/index.tsx
const { isPreview, experienceSettings } = useContext(PageContext);
const usePageLoad = useMemo(() => (isPreview ? usePreview : useSignInExperience), [isPreview]);
usePageLoad();
return experienceSettings ? children : null;

```

Individual pages then read this context to determine which components to display. For example, [`packages/experience/src/pages/SignIn/Main.tsx`](https://github.com/logto-io/logto/blob/main/packages/experience/src/pages/SignIn/Main.tsx) uses the settings to conditionally render social login buttons, password fields, or passkey options based on the tenant's enabled methods.

## The FullSignInExperience Data Model

The configuration schema defined in [`packages/schemas/src/types/sign-in-experience.ts`](https://github.com/logto-io/logto/blob/main/packages/schemas/src/types/sign-in-experience.ts) (lines 34-63) determines every UI-visible aspect of authentication. The `FullSignInExperience` type includes:

- **Branding assets** – Logo URLs, primary colors, dark mode preferences
- **Connector configurations** – Social identity providers and SSO settings
- **Security policies** – Password requirements, captcha settings, and adaptive MFA rules
- **Registration flows** – Custom profile fields and required user data
- **Google One-Tap** – Optional seamless authentication configuration

The server aggregates this data at [`packages/core/src/routes/well-known/well-known.experience.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/well-known/well-known.experience.ts) (lines 11-13), exposing it via the `/api/.well-known/experience` endpoint. The Experience package fetches this payload on load, caches it, and supplies it to the UI context.

## Customization Points Available Without Code Changes

Logto's architecture allows complete UI customization through API calls or the admin console, with changes reflecting immediately on the next page load.

**Branding and Theming**
The `settings.color` object controls primary colors, while logo assets and dark-mode toggles are configured via the `branding` field. These values flow directly into the CSS variables of the Experience package.

**Authentication Methods**
Social connectors render dynamically based on the `socialConnectors` array. Adding a new connector automatically generates the corresponding button in [`packages/experience/src/pages/SignIn/Main.tsx`](https://github.com/logto-io/logto/blob/main/packages/experience/src/pages/SignIn/Main.tsx) without frontend redeployment.

**Adaptive MFA**
Security rules defined in `packages/core/src/routes/experience/classes/libraries/adaptive-mfa-validator/` (such as [`untrusted-ip.ts`](https://github.com/logto-io/logto/blob/main/untrusted-ip.ts)) determine when to challenge users for additional factors. The UI reads these rules from the context to conditionally render TOTP or WebAuthn prompts.

**Custom Profile Fields**
Registration flows support custom profile fields chosen in the admin console, rendered through the `customProfileFields` configuration in the sign-in experience settings.

## Programmatically Updating the Sign-In Experience

While the admin console provides a GUI, you can programmatically modify the sign-in experience using the REST API endpoint `PATCH /api/sign-in-exp`.

### Adding a Custom Social Connector

The following example demonstrates fetching connector metadata and updating the sign-in experience to include a new social provider:

```typescript
import { updateSignInExperience } from '#src/api/sign-in-experience.js';
import { fetchConnectorMetadata } from '#src/api/connector.js';

// 1️⃣ Fetch the connector metadata (only the fields needed for UI)
const connector = await fetchConnectorMetadata('my-google-connector');

// 2️⃣ Update the tenant’s sign-in experience
await updateSignInExperience({
  socialConnectors: [
    // Preserve existing connectors (simplified)
    ...existing.socialConnectors,
    {
      id: connector.id,
      name: connector.name,
      logo: connector.logo,
      // other fields required by ExperienceSocialConnector
    },
  ],
});

// 3️⃣ The next page load will automatically render the new button

```

### Enabling Google One-Tap

To enable seamless authentication, update the configuration with your Google client credentials:

```typescript
await updateSignInExperience({
  googleOneTap: {
    clientId: 'YOUR_GOOGLE_CLIENT_ID',
    connectorId: 'google-connector-id',
    // Additional Google One-Tap config (if any)
    ...googleOneTapConfig,
  },
});

```

Once the payload includes `googleOneTap`, the sign-in page conditionally injects the One-Tap script. The implementation in [`packages/experience/src/pages/SignIn/index.tsx`](https://github.com/logto-io/logto/blob/main/packages/experience/src/pages/SignIn/index.tsx) reads this value from context to determine whether to initialize the Google SDK.

## Key Implementation Files

Understanding these source files clarifies how configuration transforms into UI:

- **[`packages/experience/src/Providers/SettingsProvider/index.tsx`](https://github.com/logto-io/logto/blob/main/packages/experience/src/Providers/SettingsProvider/index.tsx)** – Initializes the UI context with sign-in experience data and handles preview modes
- **[`packages/experience/src/Providers/SettingsProvider/use-sign-in-experience.ts`](https://github.com/logto-io/logto/blob/main/packages/experience/src/Providers/SettingsProvider/use-sign-in-experience.ts)** – Fetches the experience JSON from the well-known endpoint and sets the theme
- **[`packages/schemas/src/types/sign-in-experience.ts`](https://github.com/logto-io/logto/blob/main/packages/schemas/src/types/sign-in-experience.ts)** – TypeScript definitions for the `FullSignInExperience` configuration object
- **[`packages/core/src/routes/well-known/well-known.experience.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/well-known/well-known.experience.ts)** – Server-side endpoint that aggregates and returns the tenant's configuration
- **[`packages/experience/src/pages/SignIn/Main.tsx`](https://github.com/logto-io/logto/blob/main/packages/experience/src/pages/SignIn/Main.tsx)** – Core sign-in page that decides which method components (password, social, passkey) to render
- **`packages/core/src/routes/experience/classes/libraries/adaptive-mfa-validator/`** – Contains rule implementations for untrusted IP detection and other adaptive MFA logic

## Summary

- **Logto's sign-in UI is purely reactive**, rendering based on JSON configuration from the `/api/.well-known/experience` endpoint rather than hardcoded components.
- **Changes apply immediately** without code modifications or redeployment, as the `SettingsProvider` fetches fresh configuration on page load.
- **The `FullSignInExperience` type** in [`packages/schemas/src/types/sign-in-experience.ts`](https://github.com/logto-io/logto/blob/main/packages/schemas/src/types/sign-in-experience.ts) defines all customizable elements, from branding to MFA rules.
- **Social connectors and authentication methods** appear automatically when added to the configuration array, with the UI in [`packages/experience/src/pages/SignIn/Main.tsx`](https://github.com/logto-io/logto/blob/main/packages/experience/src/pages/SignIn/Main.tsx) conditionally rendering them.
- **Programmatic updates** use the `PATCH /api/sign-in-exp` endpoint, allowing CI/CD pipelines to modify authentication flows alongside infrastructure changes.

## Frequently Asked Questions

### How do I change the logo and brand colors without redeploying Logto?

Update the tenant's sign-in experience via the admin console or API. The `branding` object in the configuration accepts logo URLs and color hex codes. When you save changes to `PATCH /api/sign-in-exp`, the `SettingsProvider` automatically fetches the new settings on the next user request, applying the updated CSS variables immediately without server restart.

### Can I enable passkey authentication programmatically?

Yes. Passkey (WebAuthn) support is controlled through the sign-in experience settings. Use the `updateSignInExperience` API to enable the feature, and ensure the user's browser supports WebAuthn. The UI components in [`packages/experience/src/pages/SignIn/Main.tsx`](https://github.com/logto-io/logto/blob/main/packages/experience/src/pages/SignIn/Main.tsx) check the context settings to determine whether to render the passkey button and handle the authentication flow accordingly.

### What is the well-known endpoint and how does it work?

The `/api/.well-known/experience` endpoint (implemented in [`packages/core/src/routes/well-known/well-known.experience.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/well-known/well-known.experience.ts)) aggregates the tenant's complete sign-in configuration, including connectors, branding, and MFA policies. The Experience frontend calls this endpoint during initialization via `getSignInExperienceSettings()`, caching the result to render the appropriate UI components for that specific tenant.

### How does Logto handle adaptive MFA in the UI?

Adaptive MFA rules defined in `packages/core/src/routes/experience/classes/libraries/adaptive-mfa-validator/` evaluate risk factors like IP trust status. When these rules trigger, the backend includes MFA requirements in the authentication response. The UI then conditionally renders TOTP input fields or WebAuthn prompts based on the `experienceSettings` context, ensuring users only see additional verification steps when security policies require them.