# Streambert Custom Frameless Titlebar on Windows and Linux: Complete Implementation Guide

> Implement a custom frameless titlebar for Streambert on Windows and Linux using Electron. This guide details platform detection, React component rendering, and window control API integration.

- Repository: [true_lock/streambert](https://github.com/truelockmc/streambert)
- Tags: how-to-guide
- Published: 2026-05-21

---

**Streambert implements a custom frameless titlebar on Windows and Linux by detecting the host platform at startup, conditionally rendering a React-based `WindowTitlebar` component, and exposing window-control APIs through Electron's preload script to handle minimize, maximize, and close actions.**

The truelockmc/streambert repository uses Electron's `BrowserWindow` with `titleBarStyle: "hidden"` to create a chrome-less application window. When the app launches on Windows or Linux, it injects a custom draggable titlebar that matches the application's streaming interface, ensuring consistent cross-platform aesthetics while maintaining native window management functionality.

## Platform Detection in App.jsx

The implementation begins in [`src/App.jsx`](https://github.com/truelockmc/streambert/blob/main/src/App.jsx) where the renderer process queries the main process for the host platform. The application calls `window.electron.getPlatform()` during initialization and stores the result in React state.

When the platform resolves to `"win32"` or `"linux"`, two critical actions occur:

1. **State Update** – A boolean flag `hasCustomTitlebar` becomes true, triggering a conditional render
2. **CSS Hook** – The code sets `document.documentElement.setAttribute("data-win-titlebar", "1")` to enable platform-specific styling rules

```jsx
// src/App.jsx – Platform detection and conditional rendering
const [platform, setPlatform] = useState("");

useEffect(() => {
  window.electron?.getPlatform().then((p) => {
    setPlatform(p);
    if (p === "win32" || p === "linux") {
      document.documentElement.setAttribute("data-win-titlebar", "1");
    }
  });
}, []);

const hasCustomTitlebar = platform === "win32" || platform === "linux";

return (
  <>
    {hasCustomTitlebar && <WindowTitlebar />}
    {/* Application routes and components */}
  </>
);

```

*Source*: [src/App.jsx#L11-L38](https://github.com/truelockmc/streambert/blob/main/src/App.jsx#L11-L38)

## The WindowTitlebar React Component

The `WindowTitlebar` component in [`src/components/WindowTitlebar.jsx`](https://github.com/truelockmc/streambert/blob/main/src/components/WindowTitlebar.jsx) renders the draggable bar and window controls. It utilizes the `-webkit-app-region: drag` CSS property to make the bar behave like a native titlebar, allowing users to click and drag the entire window from the custom UI element.

The component maintains internal state for the maximized status and syncs with the main process through IPC listeners:

```jsx
// src/components/WindowTitlebar.jsx
export default function WindowTitlebar() {
  const [maximized, setMaximized] = useState(false);

  const applyMaximizedState = (isMax) => {
    setMaximized(isMax);
    if (isMax) {
      document.documentElement.setAttribute("data-maximized", "1");
    } else {
      document.documentElement.removeAttribute("data-maximized");
    }
  };

  useEffect(() => {
    if (!window.electron) return;
    
    // Initialize state
    window.electron.windowIsMaximized?.().then(applyMaximizedState);
    
    // Listen for state changes from main process
    const handler = window.electron.onWindowMaximize?.(applyMaximizedState);
    return () => window.electron.offWindowMaximize?.(handler);
  }, []);

  const minimize = () => window.electron?.windowMinimize();
  const toggleMaximize = () => window.electron?.windowToggleMaximize();
  const close = () => window.electron?.windowClose();

  return (
    <div className="window-titlebar" style={{ WebkitAppRegion: "drag" }}>
      <div style={{ WebkitAppRegion: "no-drag" }}>STREAMBERT</div>
      
      <div style={{ WebkitAppRegion: "no-drag" }}>
        <button onClick={minimize}>Minimize</button>
        <button onClick={toggleMaximize}>
          {maximized ? "Restore" : "Maximize"}
        </button>
        <button onClick={close}>Close</button>
      </div>
    </div>
  );
}

```

*Source*: [src/components/WindowTitlebar.jsx](https://github.com/truelockmc/streambert/blob/main/src/components/WindowTitlebar.jsx)

## IPC Bridge in the Preload Script

The preload script exposes a secure API surface for window management through `contextBridge.exposeInMainWorld`. This allows the renderer process to invoke main process methods without exposing the full Node.js or Electron API.

The following methods are injected into the global `window.electron` object:

- `windowMinimize()` – Invokes `window-minimize` IPC channel
- `windowToggleMaximize()` – Invokes `window-toggle-maximize` IPC channel  
- `windowClose()` – Invokes `window-close` IPC channel
- `windowIsMaximized()` – Returns promise with current maximized state
- `onWindowMaximize(callback)` – Registers listener for maximize state changes
- `offWindowMaximize(handler)` – Removes maximize state listener
- `getPlatform()` – Returns the host platform string (`win32`, `linux`, `darwin`)

```javascript
// preload.js – IPC exposure for custom titlebar controls
contextBridge.exposeInMainWorld("electron", {
  windowMinimize: () => ipcRenderer.invoke("window-minimize"),
  windowToggleMaximize: () => ipcRenderer.invoke("window-toggle-maximize"),
  windowClose: () => ipcRenderer.invoke("window-close"),
  windowIsMaximized: () => ipcRenderer.invoke("window-is-maximized"),

  onWindowMaximize: (callback) => {
    const handler = (_, value) => callback(value);
    ipcRenderer.on("window-maximized", handler);
    return handler;
  },
  
  offWindowMaximize: (handler) => {
    ipcRenderer.removeListener("window-maximized", handler);
  },

  getPlatform: () => ipcRenderer.invoke("get-platform"),
});

```

*Source*: [preload.js#L46-L58](https://github.com/truelockmc/streambert/blob/main/preload.js#L46-L58)

## CSS Integration and Styling

The global stylesheet in [`src/styles/global.css`](https://github.com/truelockmc/streambert/blob/main/src/styles/global.css) leverages the `data-win-titlebar` HTML attribute to conditionally apply styles only when the custom titlebar is present. This ensures the application layout adjusts correctly to accommodate the 32-pixel draggable region at the top of the window.

A specific rule at line 1019 handles fullscreen video player scenarios, ensuring the custom titlebar remains accessible or properly hidden depending on the viewing mode:

```css
/* src/styles/global.css – Titlebar visibility in fullscreen mode */
[data-player-fullscreen] .window-titlebar {
  /* Maintains bar visibility or adjusts z-index during fullscreen playback */
}

```

*Source*: [src/styles/global.css#L1019](https://github.com/truelockmc/streambert/blob/main/src/styles/global.css#L1019)

## End-to-End Execution Flow

1. **Application Startup** – Main process creates a `BrowserWindow` with `titleBarStyle: "hidden"` and loads the renderer
2. **Platform Query** – [`App.jsx`](https://github.com/truelockmc/streambert/blob/main/App.jsx) executes `window.electron.getPlatform()` and sets `data-win-titlebar="1"` on the document element for supported platforms
3. **Component Mount** – React renders `<WindowTitlebar />` which immediately queries `windowIsMaximized()` to sync initial state
4. **User Interaction** – Clicking minimize, maximize, or close buttons invokes the corresponding preload API, which sends IPC messages to the main process
5. **State Synchronization** – The main process broadcasts `window-maximized` events when the window state changes, updating the component's button icons (maximize vs. restore)

## Summary

- **Platform Detection** occurs in [`src/App.jsx`](https://github.com/truelockmc/streambert/blob/main/src/App.jsx) using `window.electron.getPlatform()`, enabling the custom titlebar only on Windows and Linux
- **WindowTitlebar Component** provides a draggable region using `WebkitAppRegion: "drag"` and three control buttons using `WebkitAppRegion: "no-drag"`
- **IPC Layer** in [`preload.js`](https://github.com/truelockmc/streambert/blob/main/preload.js) exposes `windowMinimize()`, `windowToggleMaximize()`, and `windowClose()` methods that communicate with the main process
- **CSS Hooks** leverage the `data-win-titlebar` attribute to conditionally style the application when the custom chrome is present
- **State Management** uses a combination of initial async queries and event listeners (`onWindowMaximize`) to keep the UI synchronized with the actual window state

## Frequently Asked Questions

### How does Streambert detect whether to show the custom titlebar?

The application calls `window.electron.getPlatform()` in [`src/App.jsx`](https://github.com/truelockmc/streambert/blob/main/src/App.jsx) during the initial render cycle. If the returned string equals `"win32"` or `"linux"`, the code sets `hasCustomTitlebar` to true and injects the `<WindowTitlebar />` component. This detection happens before the main UI renders, ensuring no visual flicker between native and custom chrome.

### What Electron APIs enable the window controls to function?

The preload script exposes IPC channels that map to `BrowserWindow` methods in the main process. Specifically, `windowMinimize()` invokes `win.minimize()`, `windowToggleMaximize()` calls `win.maximize()` or `win.unmaximize()` depending on current state, and `windowClose()` executes `win.close()`. These are bridged through `ipcRenderer.invoke()` and `ipcRenderer.on()` for asynchronous communication.

### Why does the custom titlebar use WebkitAppRegion CSS properties?

The `-webkit-app-region: drag` property allows HTML elements to behave like native titlebars, enabling users to click and drag the entire application window from that region. Conversely, `-webkit-app-region: no-drag` applied to the control buttons ensures that clicking minimize, maximize, or close does not initiate a window drag operation, maintaining expected desktop application behavior.

### How does the application handle maximized state synchronization?

The `WindowTitlebar` component initializes its state by calling `window.electron.windowIsMaximized()`, which returns a promise resolving to the current maximized boolean. It then registers a listener via `window.electron.onWindowMaximize()` that updates React state whenever the main process emits `window-maximized` events. This bidirectional sync ensures the maximize/restore button icon accurately reflects the window state even when changed via OS shortcuts or taskbar interactions.