Skip to content

andorep/electron-start

Repository files navigation

🚀 @andore/electron-start

The Type-Safe IPC Layer for Modern Electron Apps

License: MIT PRs Welcome

@andore/electron-start is a Vite-powered build-time transformer that eliminates the manual boilerplate of Electron's Inter-Process Communication (IPC). Heavily inspired by the "Server Functions" pattern in TanStack Start, it allows you to define type-safe, validated functions that bridge the gap between your Main and Renderer processes effortlessly.


✨ Why @andore/electron-start?

In traditional Electron development, IPC is a fragmented mess. @andore/electron-start collapses these layers into a single, cohesive definition.

  • 🔒 End-to-End Type Safety: Shared types between processes.
  • Built-in Validation: First-class Zod support for input validation.
  • 🪄 Zero Boilerplate: No more manual contextBridge or magic strings.
  • 🏗️ Tree-Shakable: Code is surgically extracted to the correct process bundle.
  • Developer Velocity: Write logic once, call it like a regular function.
  • 🛠️ Powered by vite-plugin-electron

🛠️ The "Magic" in Action

Define your IPC logic in a file ending with .ipc.ts. @andore/electron-start handles the rest.

// src/shared/file-ops.ipc.ts
import { createIpcFn } from '@andore/electron-start';
import { z } from 'zod';

export const readFile = createIpcFn()
  .inputValidator(z.string()) // Automatic validation!
  .handler(async (filePath, context) => {
    // This body ONLY runs in the Main process.
    // Node.js APIs are safe to use here.
    const fs = await import('node:fs/promises');
    return await fs.readFile(filePath, 'utf-8');
  });

1. In your Renderer (React/Vue/Svelte)

Just import and call. No window.api nonsense.

// App.tsx
import { readFile } from './shared/file-ops.ipc';

function App() {
  const handleOpen = async () => {
    // Fully typed! Result is string.
    const content = await readFile('/path/to/config.json');
    console.log(content);
  };
}

2. What happens under the hood?

At build time, the Vite plugin splits this function:

  • Main Process: Becomes an ipcMain.handle listener.
  • Preload: Injected into the contextBridge.
  • Renderer: Becomes a lightweight proxy calling ipcRenderer.invoke.

📦 Installation

pnpm add @andore/electron-start

🚀 Quick Start

1. Configure the Vite Plugin

Add electronStart to your main Vite config. It automatically configures vite-plugin-electron for you, managing the complex build orchestrations for Main, Preload, and Renderer processes seamlessly.

// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { electronStart } from '@andore/electron-start/plugin/vite';

export default defineConfig({
  plugins: [
    react(),
    electronStart({
      mainEntry: 'electron/main-process.ts',
      preloadEntry: 'electron/preload.ts'
    })
  ]
});

2. Set up the Context (Optional)

Inject state or services into your IPC handlers in the Main process.

// main.ts
import { setIpcContext } from '@andore/electron-start';

setIpcContext({
  db: new Database(),
  mainWindow: myWindow
});

🎨 Inspired by the Best

This project is a love letter to TanStack Start. We believe that the boundary between processes (or client/server) should be a type-safe implementation detail, not a chore for the developer.


🛡️ Security

@andore/electron-start follows Electron security best practices by default:

  • Uses contextBridge for secure exposure.
  • Encourages inputValidator (Zod) to sanitize IPC inputs.
  • Keeps Node.js logic out of the Renderer bundle via build-time extraction.

Built with ❤️ for the Electron Community.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors