ES

electron-shadcn

Overview

Comprehensive technical overview of the electron-shadcn template architecture, core technologies, and implementation details

The content in this page may have been generated by AI.

electron-shadcn is a production-ready Electron application template that combines the power of Electron with modern React development practices, specifically integrating the shadcn/ui component system. It's designed to help developers quickly bootstrap beautiful, functional desktop applications with minimal setup.

Get started in minutes with pre-configured Electron, React, TypeScript, and shadcn/ui. This template is perfect for building cross-platform desktop applications with a modern tech stack.


Architecture

The template follows a modular, type-safe architecture with clear separation of concerns between Electron's processes:

main.ts
preload.ts
renderer.ts
app.tsx
router.ts
handler.ts
manager.ts
context.ts
index.ts
handlers.ts
schemas.ts
types.d.ts
forge.config.ts
package.json
tsconfig.json
vite.main.config.mts
vite.preload.config.mts
vite.renderer.config.mts

Process Architecture

Main Process

Manages Electron app lifecycle, creates BrowserWindow instances, and sets up IPC handlers.

main.ts
import { app, BrowserWindow } from "electron";
import { ipcMain } from "electron/main";
import { ipcContext } from "./ipc/context";

function createWindow() {
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      devTools: inDevelopment,
      contextIsolation: true,
      nodeIntegration: true,
    },
    titleBarStyle: process.platform === "darwin" ? "hiddenInset" : "hidden",
  });
  ipcContext.setMainWindow(mainWindow);
  // ...
}

app.whenReady().then(async () => {
  createWindow();
  await installExtensions();
  checkForUpdates();
  await setupORPC();
});

Preload Process

Bridge between main and renderer processes, exposes limited Electron APIs to renderer.

preload.ts
import { ipcRenderer } from "electron";
import { IPC_CHANNELS } from "./constants";

window.addEventListener("message", (event) => {
  if (event.data === IPC_CHANNELS.START_ORPC_SERVER) {
    const [serverPort] = event.ports;
    ipcRenderer.postMessage(IPC_CHANNELS.START_ORPC_SERVER, null, [serverPort]);
  }
});

Renderer Process

React application running in the browser context with TanStack Router.

app.tsx
import { RouterProvider } from "@tanstack/react-router";
import React from "react";
import { createRoot } from "react-dom/client";
import { router } from "./utils/routes";
import "./localization/i18n";

export default function App() {
  return <RouterProvider router={router} />;
}

const container = document.getElementById("app");
const root = createRoot(container);
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

Core Technologies

Runtime & Build

Prop

Type

UI Layer

Prop

Type

IPC & Communication

Prop

Type

Testing

Prop

Type

Code Quality

Prop

Type


Key Implementation Details

Type-Safe IPC with oRPC

The template implements a sophisticated IPC system using oRPC that addresses Electron's traditional IPC challenges:

Key benefits of this approach:

  • MessagePort-based communication for security
  • Domain-specific routers for modular organization
  • Zod validation for runtime type safety
  • Context injection via oRPC middleware

IPC Initialization Flow

  1. Main process creates BrowserWindow with preload script
  2. Preload script listens for START_ORPC_SERVER message
  3. Renderer creates MessageChannel with two ports
  4. Client port stays in renderer, server port sent to main via window.postMessage
  5. Main process receives port, starts oRPC server with router
  6. Renderer creates oRPC client with client port
  7. Type-safe IPC communication established

Example: Theme Handler with Zod Validation

schemas.ts
import { z } from "zod";

export const setThemeModeInputSchema = z.enum(["light", "dark", "system"]);
handlers.ts
import { os } from "@orpc/server";
import { nativeTheme } from "electron";
import { setThemeModeInputSchema } from "./schemas";

export const getCurrentThemeMode = os.handler(() => 
  nativeTheme.themeSource
);

export const setThemeMode = os
  .input(setThemeModeInputSchema)
  .handler(({ input: mode }) => {
    nativeTheme.themeSource = mode;
    return nativeTheme.themeSource;
  });
index.ts
export const theme = {
  getCurrentThemeMode,
  setThemeMode,
  toggleThemeMode,
};

Window Management

The template uses a custom title bar implementation with hidden native title bar. Platform-specific styling is applied for macOS (hiddenInset) vs other platforms (hidden).

Window Configuration
const mainWindow = new BrowserWindow({
  width: 800,
  height: 600,
  webPreferences: {
    devTools: inDevelopment,
    contextIsolation: true,
    nodeIntegration: true,
    nodeIntegrationInSubFrames: false,
    preload,
  },
  titleBarStyle: process.platform === "darwin" ? "hiddenInset" : "hidden",
  trafficLightPosition: process.platform === "darwin" ? { x: 5, y: 5 } : undefined,
});

Auto-Update System

Public Repositories Only

Auto-update uses GitHub Releases as the update source. This only works for public GitHub repositories. For private repositories, you need to setup a custom update server.

React Compiler

React Compiler is enabled by default, which automatically memoizes React components. This provides better performance without manual useMemo, useCallback, or React.memo usage.


Intended Use Case

This template is ideal for:

This template is perfect for:

  • Desktop application development (Windows, macOS, Linux)
  • Rapid prototyping with modern tooling
  • Production-ready applications with testing and CI/CD
  • Type-safe development across all layers
  • International applications with i18n support
  • Accessible applications following WAI-ARIA standards

Development Workflow

Setup

Clone the repository

git clone https://github.com/LuanRoger/electron-shadcn.git

Install dependencies

cd electron-shadcn && npm install

Development

Start the application

npm run start

Starts Vite dev server with HMR and Electron main process.

Modify the app

Edit files in /src/routes/ to customize your application. Changes are reflected immediately thanks to HMR.

Testing

Run all tests

npm run test:all

Run unit tests

npm run test:unit

Run E2E tests

npm run test:e2e

Watch mode

npm run test:watch

Building & Packaging

Build for all platforms

npm run make

Supported platforms: Windows (Squirrel/MSI), macOS (ZIP/DMG), Linux (Deb/RPM/ZIP)

Publishing

Create GitHub release

npm run publish

Requires GITHUB_TOKEN environment variable with repo permissions.


Real-World Usage

The template is used in production by several projects:

Prop

Type


Best Practices

Follow these patterns when extending the template:

Adding New IPC Methods

Create a new domain folder in src/ipc/ or use existing one
Define Zod schemas in schemas.ts
Implement handlers in handlers.ts using oRPC
Export from index.ts
Add to main router in src/ipc/router.ts

Adding New Components

Use shadcn/ui CLI:

npx shadcn@latest add [component-name]
Component is automatically added to src/components/ui/
components.json is updated automatically
Required dependencies are installed

Adding New Pages

Create a new .tsx file in src/routes/
Route is automatically discovered by TanStack Router
Run npx @tanstack/router-plugin to regenerate route tree (if needed)

Security Considerations

The template follows these security measures by default:

  • Context Isolation: Enabled to prevent direct Node.js API access from renderer
  • Preload Script: Only exposes necessary Electron APIs to renderer
  • Zod Validation: All IPC inputs are validated before processing
  • Type Safety: TypeScript ensures type correctness across all layers

Performance Optimizations

The template includes several performance improvements:

  • React Compiler: Automatic memoization of React components
  • Vite: Fast HMR and optimized builds
  • Tailwind CSS 4.3: Improved performance over v3
  • oRPC: Efficient MessagePort-based IPC with minimal overhead

Configuration Files

Prop

Type


Additional Resources


Last updated: 2026-06-26T21:07:12.692Z

On this page