# How the Plane Admin Panel Manages Instance-Level Settings: Architecture and Implementation

> Learn how the Plane admin panel efficiently manages instance level settings using a reactive MobX store and a REST service layer for seamless configuration updates via the UI.

- Repository: [Plane/plane](https://github.com/makeplane/plane)
- Tags: architecture
- Published: 2026-06-22

---

**The Plane admin panel uses a reactive MobX store (`InstanceStore`) paired with a thin REST service layer (`InstanceService`) to fetch, cache, and update instance-wide configuration through a dedicated UI in `apps/admin`.**

The `makeplane/plane` repository provides a dedicated admin interface located at `apps/admin` that allows instance administrators to view and edit deployment-wide configuration. Understanding how this admin panel manages instance-level settings reveals a clean architectural separation between state management, API communication, and UI components that ensures a single source of truth across the entire administrative experience.

## Architecture Overview

The admin panel follows a four-layer separation of concerns to handle instance-level settings:

1. **State & API Layer** – [`instance.store.ts`](https://github.com/makeplane/plane/blob/main/instance.store.ts) manages reactive state using MobX and coordinates with backend services.
2. **Service Layer** – `InstanceService` wraps REST API endpoints under `/api/instances/*`.
3. **UI Components** – Forms such as `InstanceSetupForm` and `InstanceFormHeader` render settings and handle user input.
4. **Context Provider** – [`instance.provider.tsx`](https://github.com/makeplane/plane/blob/main/instance.provider.tsx) injects the store into the React component tree, enabling reactive data access throughout the admin views.

## State Management with InstanceStore

The `InstanceStore` class in [`apps/admin/store/instance.store.ts`](https://github.com/makeplane/plane/blob/main/apps/admin/store/instance.store.ts) serves as the single source of truth for instance data. It holds the current instance record and loading state as MobX observables, ensuring that any UI component referencing these values automatically re-renders when changes occur.

The store exposes two primary methods for managing instance-level settings:

- `fetchInstance()` – Retrieves the current instance metadata via GET request.
- `updateInstance(payload)` – Persists partial updates to the instance configuration via PATCH request.

```typescript
// apps/admin/store/instance.store.ts
export class InstanceStore {
  @observable instance?: IInstance = undefined;
  @observable isLoading = false;

  async fetchInstance() {
    this.isLoading = true;
    const data = await instanceService.get();
    runInAction(() => {
      this.instance = data;
      this.isLoading = false;
    });
  }

  async updateInstance(payload: Partial<IInstance>) {
    this.isLoading = true;
    const data = await instanceService.patch(payload);
    runInAction(() => {
      this.instance = data;
      this.isLoading = false;
    });
  }
}

```

Both methods wrap the asynchronous service calls in `runInAction` blocks to ensure MobX properly tracks state mutations and notifies all observers.

## API Abstraction via InstanceService

The `InstanceService` class in [`packages/services/src/instance/instance.service.ts`](https://github.com/makeplane/plane/blob/main/packages/services/src/instance/instance.service.ts) provides a thin abstraction over the REST API. It handles communication with four key endpoints that manage instance-level settings:

- **GET `/api/instances/`** – Retrieves current instance metadata.
- **PATCH `/api/instances/`** – Updates mutable fields such as instance name, email domain, or telemetry flags.
- **GET `/api/instances/configurations/`** – Fetches advanced configuration objects including email credentials.
- **PATCH `/api/instances/configurations/`** – Persists changes to advanced configuration objects.

```typescript
// packages/services/src/instance/instance.service.ts
export class InstanceService extends APIService {
  async get() {
    return this.get("/api/instances/", { validateStatus: null });
  }

  async patch(data: Partial<IInstance>) {
    return this.patch("/api/instances/", data);
  }

  async getConfigurations() {
    return this.get("/api/instances/configurations/");
  }

  async patchConfigurations(data: Partial<IFormattedInstanceConfiguration>) {
    return this.patch("/api/instances/configurations/", data);
  }
}

```

This service layer centralizes API logic, making the store agnostic of HTTP implementation details and enabling easier testing and maintenance.

## React Context and Dependency Injection

To ensure all admin panel components share the same reactive state, the `InstanceProvider` in [`apps/admin/providers/instance.provider.tsx`](https://github.com/makeplane/plane/blob/main/apps/admin/providers/instance.provider.tsx) creates a singleton `InstanceStore` instance and injects it into the React context tree. This provider fetches instance data immediately upon mounting, guaranteeing that settings are available before any child components render.

```tsx
// apps/admin/providers/instance.provider.tsx
export const InstanceProvider = ({ children }: Props) => {
  const store = useMemo(() => new InstanceStore(), []);
  useEffect(() => {
    store.fetchInstance();
  }, [store]);

  return <InstanceContext.Provider value={store}>{children}</InstanceContext.Provider>;
};

```

Any component within the admin panel can access this store via the `useInstanceStore` hook, enabling reactive reads and writes to instance-level settings without prop drilling.

## UI Forms and Components

The admin panel renders instance settings through specialized React components that bind to the MobX store. Two critical components handle distinct phases of instance management:

**InstanceSetupForm** ([`apps/admin/components/instance/setup-form.tsx`](https://github.com/makeplane/plane/blob/main/apps/admin/components/instance/setup-form.tsx)) handles first-time administrator creation. Unlike standard settings updates, this form submits directly to `POST /api/instances/admins/sign-up/` with a traditional HTML form POST to handle initial authentication setup, including CSRF token validation.

```tsx
// apps/admin/components/instance/setup-form.tsx
<form
  method="POST"
  action={`${API_BASE_URL}/api/instances/admins/sign-up/`}
  onSubmit={() => setIsSubmitting(true)}
>
  <input type="hidden" name="csrfmiddlewaretoken" value={csrfToken} />
  {/* email, password, company name fields */}
</form>

```

**Settings Pages** (email configuration, telemetry toggles, etc.) read current values from `instanceStore.instance` and invoke `instanceStore.updateInstance()` or configuration-specific service methods when users modify fields. Because the store is observable, these components instantly reflect state changes across the entire UI without manual refresh logic.

The `InstanceFormHeader` component ([`apps/admin/components/instance/form-header.tsx`](https://github.com/makeplane/plane/blob/main/apps/admin/components/instance/form-header.tsx)) provides consistent navigation and breadcrumb structure across all instance-level pages.

## The Complete Update Flow

When an administrator modifies instance-level settings, the system executes the following sequence:

1. **Initial Load** – `InstanceProvider` mounts and calls `store.fetchInstance()`, populating the observable store with current configuration.
2. **Render** – UI components read `instanceStore.instance` to display current values in forms and toggles.
3. **Modification** – Admin changes a value (e.g., disables telemetry).
4. **Submission** – UI calls `instanceStore.updateInstance({ is_telemetry_enabled: false })`.
5. **API Request** – Store forwards the payload to `InstanceService.patch("/api/instances/", payload)`.
6. **State Update** – On success, the store updates its `instance` observable within a `runInAction` block.
7. **UI Sync** – MobX triggers re-renders in all observing components, immediately displaying the updated configuration.
8. **Error Handling** – Any validation or permission errors returned by the API surface via toast notifications or banner components.

## Summary

- The **InstanceStore** in [`apps/admin/store/instance.store.ts`](https://github.com/makeplane/plane/blob/main/apps/admin/store/instance.store.ts) uses MobX observables to maintain a reactive, single source of truth for instance configuration.
- The **InstanceService** in [`packages/services/src/instance/instance.service.ts`](https://github.com/makeplane/plane/blob/main/packages/services/src/instance/instance.service.ts) abstracts REST API calls to `/api/instances/` and `/api/instances/configurations/` endpoints.
- The **InstanceProvider** in [`apps/admin/providers/instance.provider.tsx`](https://github.com/makeplane/plane/blob/main/apps/admin/providers/instance.provider.tsx) injects the store into the React tree, ensuring all admin components share live state.
- **UI components** such as `InstanceSetupForm` handle both initial setup and ongoing settings management, binding form inputs to the reactive store.
- Updates flow unidirectionally from UI → Store → Service → API → Store → UI, guaranteeing consistency across the admin panel.

## Frequently Asked Questions

### What is the role of InstanceStore in the Plane admin panel?

The `InstanceStore` acts as the central state container for instance-level settings within the admin panel. Implemented as a MobX store in [`apps/admin/store/instance.store.ts`](https://github.com/makeplane/plane/blob/main/apps/admin/store/instance.store.ts), it holds the current instance record, manages loading states, and exposes `fetchInstance()` and `updateInstance()` methods that synchronize the UI with the backend. Its observable properties ensure that any component reading from the store automatically re-renders when configuration changes occur.

### Which API endpoints handle instance configuration updates?

According to the `InstanceService` implementation in [`packages/services/src/instance/instance.service.ts`](https://github.com/makeplane/plane/blob/main/packages/services/src/instance/instance.service.ts), instance-level settings are managed through two primary endpoint patterns: `/api/instances/` for core metadata (name, telemetry flags) and `/api/instances/configurations/` for advanced settings like email credentials. The service uses PATCH requests to persist updates and GET requests to retrieve current state.

### How does the admin panel handle first-time instance setup?

First-time setup uses the `InstanceSetupForm` component in [`apps/admin/components/instance/setup-form.tsx`](https://github.com/makeplane/plane/blob/main/apps/admin/components/instance/setup-form.tsx), which submits a traditional HTML form POST to `/api/instances/admins/sign-up/` rather than using the JavaScript API layer. This approach handles initial administrator account creation, CSRF token validation, and captures the company name and telemetry preferences during the instance initialization phase.

### What ensures that all admin UI components stay synchronized?

The `InstanceProvider` in [`apps/admin/providers/instance.provider.tsx`](https://github.com/makeplane/plane/blob/main/apps/admin/providers/instance.provider.tsx) creates a singleton `InstanceStore` instance and provides it via React Context to the entire admin component tree. Because the store uses MobX observables, any mutation to the `instance` object—whether from initial fetch or subsequent updates—immediately propagates to all observing UI components without requiring manual state management or refresh logic.