# How Sign-In Experience Customization Works in Logto: Console-to-Experience Flow Explained

> Learn how Logto customization works for your sign-in experience. Fetch configuration from the backend and see instant updates in the Experience SPA without reloads.

- Repository: [Logto/logto](https://github.com/logto-io/logto)
- Tags: deep-dive
- Published: 2026-07-05

---

**Logto's sign-in experience customization is handled through a React context-based architecture that fetches configuration from the Core backend, stores it in a shared PageContext, and reflects changes instantly in the Experience SPA without requiring a page reload.**

The logto-io/logto repository provides a fully configurable authentication layer where sign-in experience customization occurs entirely within the Console admin UI. This system allows administrators to modify branding, colors, authentication methods, and custom CSS through a live-editable interface that synchronizes immediately with the end-user Experience SPA.

## Architecture Overview

The sign-in experience customization follows a strict separation of concerns across four distinct layers. The **Data layer** handles API communication with `getSignInExperienceSettings()` fetching from `/api/sign-in-experience`. The **State layer** uses `PageContext` to store the `SignInExperienceResponse` object. The **Hook layer** provides the `useSignInExperience` hook for consuming components, while the **Provider layer** manages the `SettingsProvider` to determine whether to load preview or production data.

This architecture enables the Console to edit settings while the Experience SPA consumes the same context, ensuring that any configuration change appears instantly in the live preview without flashing or page reloads.

## Data Flow and State Management

### Fetching Configuration from the Core API

When the Console page loads, the `useSignInExperience` hook (located in [`packages/experience/src/Providers/SettingsProvider/use-sign-in-experience.tsx`](https://github.com/logto-io/logto/blob/main/packages/experience/src/Providers/SettingsProvider/use-sign-in-experience.tsx)) triggers an asynchronous fetch to the Core backend. The hook calls `getSignInExperienceSettings()` from [`packages/experience/src/utils/sign-in-experience.ts`](https://github.com/logto-io/logto/blob/main/packages/experience/src/utils/sign-in-experience.ts), which makes a GET request to `/api/sign-in-experience` and returns the complete `SignInExperienceResponse` object containing branding, colors, language settings, and enabled authentication methods.

### Storing Settings in PageContext

The fetched configuration is stored in `PageContext` ([`packages/experience/src/Providers/PageContextProvider/PageContext.tsx`](https://github.com/logto-io/logto/blob/main/packages/experience/src/Providers/PageContextProvider/PageContext.tsx)). This context exposes `experienceSettings` and `setExperienceSettings`, making the data accessible to any component in the Experience SPA. The `SettingsProvider` ([`packages/experience/src/Providers/SettingsProvider/index.tsx`](https://github.com/logto-io/logto/blob/main/packages/experience/src/Providers/SettingsProvider/index.tsx)) wraps the application and decides whether to inject preview data (for demo purposes) or real settings from the API.

## Editing via the Console

Administrators customize the sign-in flow through the Console interface at [`packages/console/src/pages/SignInExperience/index.tsx`](https://github.com/logto-io/logto/blob/main/packages/console/src/pages/SignInExperience/index.tsx). This page renders sub-components for **Branding**, **Custom UI**, **Social Connectors**, and **Sign-in Methods**. Each form component updates the local context state immediately.

When an admin clicks **Save**, the Console makes a `PUT /api/sign-in-experience` request with the updated `SignInExperienceResponse` payload. The Core server validates the configuration and persists it to the database, making the changes available for subsequent GET requests.

## Live Preview Implementation

The Experience SPA consumes the same `PageContext` as the Console. Because the context updates instantly when `setExperienceSettings` is called, the sign-in pages preview new configurations without a full page reload. In [`use-sign-in-experience.tsx`](https://github.com/logto-io/logto/blob/main/use-sign-in-experience.tsx) (lines 19-22), the hook sets the theme immediately after fetching data, preventing any visual flashing during the transition.

For development and testing, the system uses mock data from [`packages/experience/src/__mocks__/logto.tsx`](https://github.com/logto-io/logto/blob/main/packages/experience/src/__mocks__/logto.tsx), which provides a default `SignInExperienceResponse` object when the API is unavailable.

## Key Implementation Files

| File | Responsibility |
|------|----------------|
| [`packages/experience/src/Providers/SettingsProvider/use-sign-in-experience.tsx`](https://github.com/logto-io/logto/blob/main/packages/experience/src/Providers/SettingsProvider/use-sign-in-experience.tsx) | Loads settings on mount and applies theming logic. |
| [`packages/experience/src/Providers/PageContextProvider/PageContext.tsx`](https://github.com/logto-io/logto/blob/main/packages/experience/src/Providers/PageContextProvider/PageContext.tsx) | Stores `experienceSettings` and provides the setter function. |
| [`packages/experience/src/Providers/SettingsProvider/index.tsx`](https://github.com/logto-io/logto/blob/main/packages/experience/src/Providers/SettingsProvider/index.tsx) | Determines preview vs. real data mode. |
| [`packages/console/src/pages/SignInExperience/index.tsx`](https://github.com/logto-io/logto/blob/main/packages/console/src/pages/SignInExperience/index.tsx) | Main Console interface for editing configuration. |
| [`packages/experience/src/utils/sign-in-experience.ts`](https://github.com/logto-io/logto/blob/main/packages/experience/src/utils/sign-in-experience.ts) | Utility functions for GET/PUT API requests. |
| [`packages/experience/src/__mocks__/logto.tsx`](https://github.com/logto-io/logto/blob/main/packages/experience/src/__mocks__/logto.tsx) | Mock data for development and testing. |

## Practical Code Examples

### Accessing Settings in a Component

```tsx
import useSignInExperience from '@/Providers/SettingsProvider/use-sign-in-experience';
import { useContext } from 'react';
import PageContext from '@/Providers/PageContextProvider/PageContext';

// Inside a component
useSignInExperience();                     // Triggers the async fetch on mount
const { experienceSettings } = useContext(PageContext);

// `experienceSettings` now contains the full configuration object

```

### Updating Sign-In Methods Programmatically

```tsx
// Assume `settings` is the current `SignInExperienceResponse`
const updated = {
  ...settings,
  signIn: {
    methods: [
      { identifier: SignInIdentifier.Email, password: true, verificationCode: true, isPasswordPrimary: true },
      { identifier: SignInIdentifier.Phone, password: true, verificationCode: true, isPasswordPrimary: true },
    ],
  },
};

// Persist the change (Console UI uses an internal API client)
await fetch('/api/sign-in-experience', {
  method: 'PUT',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify(updated),
});

```

### Rendering with Live Preview

```tsx
// Inside the Experience app
const { experienceSettings } = useContext(PageContext);
if (!experienceSettings) {
  return <LoadingScreen />;
}

// Render the sign-in page according to the settings
return <SignInPage config={experienceSettings} />;

```

## Summary

- **Logto's sign-in experience customization** uses a React context pattern where `PageContext` stores the `SignInExperienceResponse` shared between Console and Experience SPA.
- The `useSignInExperience` hook in [`packages/experience/src/Providers/SettingsProvider/use-sign-in-experience.tsx`](https://github.com/logto-io/logto/blob/main/packages/experience/src/Providers/SettingsProvider/use-sign-in-experience.tsx) handles fetching from `/api/sign-in-experience` and applies themes before rendering.
- Changes made in [`packages/console/src/pages/SignInExperience/index.tsx`](https://github.com/logto-io/logto/blob/main/packages/console/src/pages/SignInExperience/index.tsx) persist via `PUT /api/sign-in-experience` and reflect immediately in the live preview without page reloads.
- The architecture separates data fetching, state management, and UI editing into distinct layers for maintainability.

## Frequently Asked Questions

### How does Logto handle real-time updates to the sign-in experience?

Logto uses a shared `PageContext` that both the Console and Experience SPA consume. When an admin saves changes via `PUT /api/sign-in-experience`, the Console updates the local context state, which triggers an immediate re-render of the preview components. This avoids full page reloads and prevents visual flashing by setting the theme before the component mounts (as seen in lines 19-22 of [`use-sign-in-experience.tsx`](https://github.com/logto-io/logto/blob/main/use-sign-in-experience.tsx)).

### What is the difference between preview data and real settings in Logto?

The `SettingsProvider` ([`packages/experience/src/Providers/SettingsProvider/index.tsx`](https://github.com/logto-io/logto/blob/main/packages/experience/src/Providers/SettingsProvider/index.tsx)) determines whether to load preview data or production settings. Preview data typically comes from [`packages/experience/src/__mocks__/logto.tsx`](https://github.com/logto-io/logto/blob/main/packages/experience/src/__mocks__/logto.tsx) for development and Storybook demonstrations, while real settings are fetched from the Core API at `/api/sign-in-experience` in production environments.

### Where are sign-in experience settings stored in the Logto codebase?

The configuration is stored in the Core backend database and accessed via the `/api/sign-in-experience` endpoint. In the frontend, the types and interfaces are defined in the Experience package, with the primary context living in [`packages/experience/src/Providers/PageContextProvider/PageContext.tsx`](https://github.com/logto-io/logto/blob/main/packages/experience/src/Providers/PageContextProvider/PageContext.tsx) and API utilities in [`packages/experience/src/utils/sign-in-experience.ts`](https://github.com/logto-io/logto/blob/main/packages/experience/src/utils/sign-in-experience.ts).

### How can I customize the sign-in methods programmatically?

You can modify the `signIn.methods` array within the `SignInExperienceResponse` object and send it via a `PUT` request to `/api/sign-in-experience`. Each method object requires an `identifier` (Email or Phone), boolean flags for `password` and `verificationCode`, and an `isPasswordPrimary` boolean to determine the default authentication flow.