# How MobX Manages Shared State Across Plane's Frontend Applications

> Discover how MobX manages shared state in Plane's frontend. Learn about observable stores, CoreRootStore, and React Context integration for seamless data synchronization.

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

---

**Plane implements a centralized state management system using MobX observable stores composed into a single `CoreRootStore` and distributed via React Context to synchronize data across its web and Community Edition (CE) applications.**

Plane's frontend architecture relies on MobX to maintain a single source of truth for application state. The open-source project management platform uses a store-centric pattern where TypeScript classes define observable properties that automatically trigger UI updates. This approach enables seamless state sharing between the main web application and the CE frontend while maintaining type safety and SSR compatibility.

## Observable Store Classes with makeObservable

Individual feature stores in Plane are implemented as plain TypeScript classes that declare their state using MobX's `makeObservable` utility. In [`packages/shared-state/src/store/workspace.store.ts`](https://github.com/makeplane/plane/blob/main/packages/shared-state/src/store/workspace.store.ts), the `WorkspaceStore` defines observable properties for workspace metadata:

```typescript
import { makeObservable, observable } from "mobx";

export class WorkspaceStore implements IWorkspaceStore {
  id: string;
  name: string;
  createdAt: string;
  updatedAt: string;

  constructor(data: IWorkspaceStore) {
    makeObservable(this, {
      id:          observable.ref,
      name:        observable.ref,
      createdAt:   observable.ref,
      updatedAt:   observable.ref,
    });
    this.id        = data.id;
    this.name      = data.name;
    this.createdAt = data.createdAt;
    this.updatedAt = data.updatedAt;
  }
}

```

This pattern ensures that any changes to these properties automatically notify subscribed components.

## Composing State with CoreRootStore

Application-wide state coordination happens in [`apps/web/core/store/root.store.ts`](https://github.com/makeplane/plane/blob/main/apps/web/core/store/root.store.ts), where the `CoreRootStore` aggregates all feature-specific stores into a unified hierarchy. This root store instantiates children like `WorkspaceRootStore`, `ProjectRootStore`, and `IssueRootStore`, passing its own reference to enable cross-store communication:

```typescript
import { enableStaticRendering } from "mobx-react";

enableStaticRendering(typeof window === "undefined");

export class CoreRootStore {
  workspaceRoot: WorkspaceRootStore;
  projectRoot:   ProjectRootStore;
  issue:         IssueRootStore;

  constructor() {
    this.workspaceRoot = new WorkspaceRootStore(this as unknown as RootStore);
    this.projectRoot   = new ProjectRootStore(this);
    this.issue         = new IssueRootStore(this as unknown as RootStore);
  }
}

```

The implementation also addresses server-side rendering concerns by calling `enableStaticRendering` at the module level, which disables MobX's reactive tracking during SSR to prevent memory leaks.

## React Integration via Context

To make the state tree accessible throughout the component hierarchy, Plane uses a React Context pattern defined in [`apps/web/core/lib/store-context.tsx`](https://github.com/makeplane/plane/blob/main/apps/web/core/lib/store-context.tsx). The `StoreProvider` component wraps the application and injects a singleton `RootStore` instance:

```typescript
import { createContext } from "react";

export let rootStore = new RootStore();
export const StoreContext = createContext<RootStore>(rootStore);

export function StoreProvider({ children }: { children: ReactElement }) {
  return <StoreContext.Provider value={store}>{children}</StoreContext.Provider>;
}

```

Components consume this context using `useContext` and wrap themselves with the `observer` HOC from `mobx-react-lite`. This subscription mechanism ensures components re-render only when the specific observables they access actually change:

```typescript
import { observer } from "mobx-react-lite";

const WorkspaceName = observer(() => {
  const { workspaceRoot } = useContext(StoreContext);
  return <h1>{workspaceRoot.workspace.name}</h1>;
});

```

## Cross-Application State Sharing

Both the web (`apps/web`) and Community Edition (`apps/ce`) frontends import store definitions from the shared `@plane/shared-state` package. Because stores are framework-agnostic TypeScript classes, the same business logic and state structures power multiple application bundles without duplication.

The `StoreProvider` ensures each navigation session maintains a single source of truth, while the shared package guarantees type consistency across deployment targets.

## State Reset and Lifecycle Management

When users sign out, Plane clears sensitive state to prevent data leakage between sessions. The `resetOnSignOut` method in `CoreRootStore` (found at line 137 of [`apps/web/core/store/root.store.ts`](https://github.com/makeplane/plane/blob/main/apps/web/core/store/root.store.ts)) reinstantiates each child store, returning the application to its initial clean state.

## Summary

- Plane uses MobX observable classes defined in `packages/shared-state` to model application state with `makeObservable`
- The `CoreRootStore` in [`apps/web/core/store/root.store.ts`](https://github.com/makeplane/plane/blob/main/apps/web/core/store/root.store.ts) composes all feature stores into a single hierarchy
- `enableStaticRendering` ensures SSR compatibility by disabling reactive tracking on the server
- React Context (`StoreContext`) distributes the root store globally via `StoreProvider`
- Components use `observer` from `mobx-react-lite` for fine-grained, automatic re-rendering
- The `@plane/shared-state` package enables code sharing between web and CE applications
- `resetOnSignOut` provides secure state cleanup between user sessions

## Frequently Asked Questions

### How does Plane prevent memory leaks during server-side rendering with MobX?

Plane calls `enableStaticRendering` from `mobx-react` at the top of [`apps/web/core/store/root.store.ts`](https://github.com/makeplane/plane/blob/main/apps/web/core/store/root.store.ts) to disable MobX's reaction tracking when running on the server. This check against `typeof window === "undefined"` ensures that server-side renders don't accumulate active reactions that would leak memory between requests.

### What pattern does Plane use to share state between different frontend applications?

Plane packages its store definitions in `@plane/shared-state` and imports them into both the web and CE applications. A singleton `CoreRootStore` instantiated in [`apps/web/core/lib/store-context.tsx`](https://github.com/makeplane/plane/blob/main/apps/web/core/lib/store-context.tsx) provides a single source of truth per session, while React Context makes this store accessible to any component in the tree regardless of which application bundle is running.

### How do components subscribe to MobX state changes in Plane?

Components import the `observer` function from `mobx-react-lite` and wrap their component definitions. Inside the component, they access the store via `useContext(StoreContext)`. MobX automatically tracks which observable properties are accessed during render, and the `observer` HOC ensures the component re-renders only when those specific properties change.

### Where does Plane handle state cleanup when a user signs out?

The `CoreRootStore` class implements a `resetOnSignOut` method that reinstantiates all child stores including workspace, project, and user stores. This method, located at line 137 of [`apps/web/core/store/root.store.ts`](https://github.com/makeplane/plane/blob/main/apps/web/core/store/root.store.ts), ensures that stale user data is completely removed from memory before the next authentication session begins.