# How to Customize the UI Theming in Stirling-PDF Using the @app Import Path Pattern

> Easily customize Stirling-PDF UI theming with the @app import path pattern. Override Mantine themes for consistent styling across web, desktop, and proprietary builds.

- Repository: [Stirling Tools/Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF)
- Tags: how-to-guide
- Published: 2026-03-01

---

**Override the default Mantine theme by creating a custom theme file in `frontend/src/core/theme/` and importing it via the `@app/` alias, which Vite resolves to the core directory, enabling consistent theming across web, desktop, and proprietary builds.**

Stirling-PDF’s frontend is built with React, Vite, Mantine, and Tailwind CSS, with all UI-related code centralized under `frontend/src/core/`. Customizing the UI theming using the `@app/` import path pattern ensures your modifications remain portable across the web application, desktop (Tauri) builds, and proprietary distributions without requiring path refactoring.

## How the @app Import Alias Works

The `@app/` pattern is a **Vite resolve alias** defined in [`frontend/vite.config.ts`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/frontend/vite.config.ts) that maps imports to the absolute path of the core directory:

```typescript
// frontend/vite.config.ts
import path from 'path';

export default {
  resolve: {
    alias: {
      '@app': path.resolve(__dirname, 'src/core')
    }
  }
};

```

When you write `import { mantineTheme } from '@app/theme/mantineTheme'`, Vite rewrites this to `<repository-root>/frontend/src/core/theme/mantineTheme.ts`. This abstraction eliminates relative path gymnastics (e.g., `../../../theme/`) and guarantees that modules resolve correctly regardless of whether the code runs in the web build, desktop wrapper, or proprietary fork.

## Locating the Default Theme Files

The theming system relies on four key files within `frontend/src/core/`:

- **[`theme/mantineTheme.ts`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/theme/mantineTheme.ts)** – Contains the `extendTheme` definition including color palettes, component defaults, and global styles
- **[`constants/theme.ts`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/constants/theme.ts)** – Exports the `ThemeMode` type (`'light' | 'dark' | 'rainbow'`) and detects OS-level theme preferences
- **[`hooks/useRainbowTheme.ts`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/hooks/useRainbowTheme.ts)** – Implements the special "rainbow" animated theme mode
- **[`services/preferencesService.ts`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/services/preferencesService.ts)** – Persists user theme selections to `localStorage` via the `Preferences` interface

These files are imported throughout the application using the `@app/` prefix. For example, the root provider typically instantiates Mantine with:

```typescript
import { mantineTheme } from '@app/theme/mantineTheme';

<MantineProvider theme={mantineTheme}>
  {/* Application components */}
</MantineProvider>

```

## Creating Custom Theme Overrides

To customize the UI theming, create a new file at [`frontend/src/core/theme/customTheme.ts`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/frontend/src/core/theme/customTheme.ts) that extends the base configuration while preserving the original file untouched.

### Overriding Color Palettes

Define new color scales and assign them as the primary palette:

```typescript
// frontend/src/core/theme/customTheme.ts
import { mantineTheme } from '@app/theme/mantineTheme';

export const customTheme = {
  ...mantineTheme,
  colors: {
    ...mantineTheme.colors,
    brand: ['#e0f2ff', '#b3e5ff', '#80d4ff', '#4dc2ff', '#1ab1ff', '#0099e6', '#0077b3', '#005580', '#00334d', '#001122'],
    primary: ['#e6fffa', '#b3fff0', '#80ffe6', '#4dffdc', '#1affd2', '#00e6b8', '#00b38f', '#008066', '#004d3c', '#001913'],
  },
  primaryColor: 'brand',
};

```

### Implementing Dark-Mode Specific Styles

For dynamic dark-mode adjustments, export a theme factory function that receives the current color scheme:

```typescript
// frontend/src/core/theme/customTheme.ts
import { mantineTheme } from '@app/theme/mantineTheme';

export const customTheme = (colorScheme: 'light' | 'dark') => ({
  ...mantineTheme,
  colors: {
    ...mantineTheme.colors,
    dark: colorScheme === 'dark'
      ? ['#0d0d0d', '#1a1a1a', '#262626', '#333333', '#404040', '#4d4d4d', '#595959', '#666666', '#737373', '#808080']
      : mantineTheme.colors.dark,
  },
});

```

### Customizing Component Styles

Modify default props for all instances of a component by extending the `components` key:

```typescript
export const customTheme = {
  ...mantineTheme,
  components: {
    ...mantineTheme.components,
    Button: {
      styles: (theme) => ({
        root: {
          borderRadius: theme.radius.md,
          padding: `${theme.spacing.xs} ${theme.spacing.sm}`,
        },
      }),
    },
  },
};

```

## Registering Your Custom Theme

Update the root application file (typically [`frontend/src/App.tsx`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/frontend/src/App.tsx)) to import your custom theme using the `@app/` alias:

```typescript
import { MantineProvider } from '@mantine/core';
import { customTheme } from '@app/theme/customTheme';
import { usePreferences } from '@app/contexts/PreferencesContext';

function App() {
  const { theme } = usePreferences(); // Returns 'light', 'dark', or 'rainbow'
  
  return (
    <MantineProvider theme={customTheme(theme)} colorScheme={theme}>
      {/* Rest of application */}
    </MantineProvider>
  );
}

```

Using the `@app/theme/customTheme` path ensures the import resolves correctly in all build targets without modification.

## Adding New Theme Modes

To introduce a custom mode such as `highContrast`:

1. **Extend the type definition** in [`frontend/src/core/constants/theme.ts`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/frontend/src/core/constants/theme.ts):

```typescript
export type ThemeMode = 'light' | 'dark' | 'rainbow' | 'highContrast';

```

2. **Update the preferences service** at [`frontend/src/core/services/preferencesService.ts`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/frontend/src/core/services/preferencesService.ts) to include a default value for the new mode (the service already handles `localStorage` read/write operations via the `Preferences` interface).

3. **Add a UI toggle** in [`frontend/src/core/components/rightRail/ThemeSwitcher.tsx`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/frontend/src/core/components/rightRail/ThemeSwitcher.tsx) (or equivalent) that calls `updatePreference('theme', 'highContrast')`. The `usePreferences` hook propagates this change automatically, causing the theme provider to re-render with the new mode.

## Summary

- **The `@app/` alias** resolves to `frontend/src/core/` via Vite configuration in [`vite.config.ts`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/vite.config.ts), enabling consistent imports across web, desktop, and proprietary builds
- **Base theme configuration** resides in [`theme/mantineTheme.ts`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/theme/mantineTheme.ts) and should remain unmodified to facilitate updates
- **Custom themes** are created by extending the base theme object and importing via `@app/theme/customTheme`
- **Dynamic theming** is achieved by exporting theme factory functions that accept the current `colorScheme`
- **New theme modes** require extending the `ThemeMode` type in [`constants/theme.ts`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/constants/theme.ts) and updating the preferences service interface

## Frequently Asked Questions

### What is the @app import path in Stirling-PDF?

The `@app/` path is a Vite resolve alias configured in [`frontend/vite.config.ts`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/frontend/vite.config.ts) that maps to `frontend/src/core/`. It allows developers to import core modules using absolute-style paths (e.g., `@app/theme/mantineTheme`) rather than relative paths, ensuring code portability between the web application, desktop (Tauri) builds, and proprietary distributions.

### Where is the default Mantine theme defined?

The default theme is defined in [`frontend/src/core/theme/mantineTheme.ts`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/frontend/src/core/theme/mantineTheme.ts) using Mantine's `extendTheme` function. This file exports the color palettes, component default props, and global styles that drive the application's visual appearance. Constants and types supporting this theme are located in [`frontend/src/core/constants/theme.ts`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/frontend/src/core/constants/theme.ts).

### How do I add a new theme mode like high contrast?

Extend the `ThemeMode` type in [`frontend/src/core/constants/theme.ts`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/frontend/src/core/constants/theme.ts) to include your new mode (e.g., `'highContrast'`). The [`preferencesService.ts`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/preferencesService.ts) already persists theme selections to `localStorage`, so you only need to ensure your new mode is handled in the theme factory function and add a UI control that calls `updatePreference('theme', 'highContrast')`.

### Will custom themes work in the desktop application?

Yes. Because the `@app/` alias resolves to the same `src/core/` directory in all build configurations (web, desktop, and proprietary), custom themes imported via `@app/theme/customTheme` will function identically across all platforms without requiring path adjustments or conditional imports.