Skip to content
Electron App Scaffolder logo

Electron App Scaffolder

Creates a production-ready Electron application with TypeScript, React, Vite, and best practices.

SKILL.md

Full skill instructions

Electron App Scaffolder

Creates a production-ready Electron application with TypeScript, React, Vite, and best practices.

Usage

/​electron-app <app-name> [--with-db] [--with-tests] [--with-storybook]

Arguments

  • app-name (required): Name of the application (kebab-case recommended)
  • --with-db: Include SQLite database with Knex.js migrations
  • --with-tests: Include Jest testing setup
  • --with-storybook: Include Storybook for component development

Instructions

When this skill is invoked, create a new Electron application following these steps:

1. Project Initialization

Create the project directory and initialize:

mkdir <app-name>
cd <app-name>
npm init -y

2. Directory Structure

Create the following structure:

<app-name>/
├── electron/
│   ├── main.ts
│   └── preload.ts
├── src/
│   ├── renderer/
│   │   ├── components/
│   │   ├── types/
│   │   │   └── electron.d.ts
│   │   ├── utils/
│   │   ├── App.tsx
│   │   ├── main.tsx
│   │   └── index.css
│   └── main/
├── dist/
│   ├── main/
│   └── renderer/
├── index.html
├── tsconfig.json
├── tsconfig.node.json
├── vite.config.ts
└── package.json

If --with-db is specified, also create:

├── migrations/
├── knexfile.js
└── scripts/
    └── seed-db.js

If --with-tests is specified, also create:

├── jest.config.js
├── src/​renderer/​setupTests.ts
└── __tests__/

If --with-storybook is specified, also create:

└── .storybook/
    ├── main.ts
    └── preview.ts

3. Package.json Configuration

Update package.json with:

Core Dependencies:

  • electron: Latest stable
  • react, react-dom: ^18.x
  • electron-builder: For distribution

Development Dependencies:

  • typescript: ^5.x
  • vite: ^5.x
  • @vitejs/​plugin-react: Latest
  • electron-builder: Latest
  • concurrently: For running dev servers
  • wait-on: For coordinating startup

If --with-db:

  • better-sqlite3: ^9.x
  • knex: ^3.x
  • @faker-js/​faker: For seeding

If --with-tests:

  • jest, @types/​jest
  • ts-jest
  • @testing-library/​react, @testing-library/​jest-dom

Scripts:

{
  "scripts": {
    "dev": "concurrently \"npm run dev:vite\" \"npm run dev:electron\"",
    "dev:vite": "vite",
    "dev:electron": "wait-on http://localhost:5173 && electron .",
    "build": "tsc && vite build && electron-builder",
    "build:mac": "npm run build -- --mac",
    "build:win": "npm run build -- --win",
    "build:linux": "npm run build -- --linux",
    "lint": "eslint src --ext ts,tsx",
    "test": "jest",
    "test:watch": "jest --watch"
  }
}

Add --with-db scripts if needed:

{
  "scripts": {
    "migrate": "knex migrate:latest",
    "migrate:rollback": "knex migrate:rollback",
    "seed": "node scripts/​seed-db.js"
  }
}

4. TypeScript Configuration

tsconfig.json:

{
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "skipLibCheck": true,
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,
    "paths": {
      "@/​*": ["./​src/​*"]
    }
  },
  "include": ["src"],
  "references": [{ "path": "./​tsconfig.node.json" }]
}

tsconfig.node.json:

{
  "compilerOptions": {
    "composite": true,
    "skipLibCheck": true,
    "module": "ESNext",
    "moduleResolution": "bundler",
    "allowSyntheticDefaultImports": true,
    "outDir": "dist/​main"
  },
  "include": ["electron"]
}

5. Vite Configuration

vite.config.ts:

import { defineConfig } from 'vite';
import react from '@vitejs/​plugin-react';
import path from 'path';

export default defineConfig({
  plugins: [react()],
  base: './',
  build: {
    outDir: 'dist/​renderer',
  },
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './​src'),
    },
  },
  server: {
    port: 5173,
  },
});

6. Main Process (electron/​main.ts)

Create a secure main process with:

  • BrowserWindow with contextIsolation: true and nodeIntegration: false
  • IPC handlers for app operations
  • Development/​production URL loading logic
  • If --with-db: Database initialization and IPC handlers

Key patterns:

import { app, BrowserWindow, ipcMain } from 'electron';
import path from 'path';

let mainWindow: BrowserWindow | null = null;

function createWindow() {
  mainWindow = new BrowserWindow({
    width: 1200,
    height: 800,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      contextIsolation: true,
      nodeIntegration: false,
    },
  });

  if (process.env.NODE_ENV === 'development') {
    mainWindow.loadURL('http://localhost:5173');
    mainWindow.webContents.openDevTools();
  } else {
    mainWindow.loadFile(path.join(__dirname, '../​renderer/​index.html'));
  }
}

app.whenReady().then(() => {
  // Initialize database if --with-db
  createWindow();

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow();
    }
  });
});

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

// IPC Handlers
ipcMain.handle('app:getVersion', () => app.getVersion());

7. Preload Script (electron/​preload.ts)

Create secure context bridge:

import { contextBridge, ipcRenderer } from 'electron';

export interface ElectronAPI {
  getVersion: () => Promise<string>;
  // Add more API methods here
}

contextBridge.exposeInMainWorld('electronAPI', {
  getVersion: () => ipcRenderer.invoke('app:getVersion'),
} as ElectronAPI);

8. Renderer Type Definitions (src/​renderer/​types/​electron.d.ts)

import type { ElectronAPI } from '../​../​../​electron/​preload';

declare global {
  interface Window {
    electronAPI: ElectronAPI;
  }
}

export {};

9. React Application

index.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title><app-name></​title>
  </​head>
  <body>
    <div id="root"></​div>
    <script type="module" src="/​src/​renderer/​main.tsx"></​script>
  </​body>
</​html>

src/​renderer/​main.tsx:

import React from 'react';
import ReactDOM from 'react-dom/​client';
import App from './​App';
import './​index.css';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <App />
  </​React.StrictMode>
);

src/​renderer/​App.tsx:

import React, { useEffect, useState } from 'react';

function App() {
  const [version, setVersion] = useState<string>('');

  useEffect(() => {
    window.electronAPI.getVersion().then(setVersion);
  }, []);

  return (
    <div className="app">
      <h1>Welcome to <app-name></​h1>
      <p>App version: {version}</​p>
    </​div>
  );
}

export default App;

10. Database Setup (if --with-db)

knexfile.js:

const path = require('path');
const { app } = require('electron');

const dbPath = app
  ? path.join(app.getPath('userData'), '<app-name>.db')
  : path.join(__dirname, '<app-name>.db');

module.exports = {
  client: 'better-sqlite3',
  connection: {
    filename: dbPath,
  },
  useNullAsDefault: true,
  migrations: {
    directory: './​migrations',
  },
};

Create initial migration:

npx knex migrate:make create_initial_tables

11. Testing Setup (if --with-tests)

jest.config.js:

module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'jsdom',
  roots: ['<rootDir>/​src'],
  testMatch: ['**/​__tests__/​**/​*.test.ts?(x)'],
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/​src/​$1',
    '\\.(css|less|scss|sass)$': 'identity-obj-proxy',
  },
  setupFilesAfterEnv: ['<rootDir>/​src/​renderer/​setupTests.ts'],
};

src/​renderer/​setupTests.ts:

import '@testing-library/​jest-dom';

12. Electron Builder Configuration

Add to package.json:

{
  "main": "dist/​main/​main.js",
  "build": {
    "appId": "com.<app-name>.app",
    "productName": "<app-name>",
    "files": [
      "dist/​**/​*",
      "package.json"
    ],
    "directories": {
      "output": "release"
    },
    "mac": {
      "target": ["dmg"],
      "category": "public.app-category.utilities"
    },
    "win": {
      "target": ["nsis"]
    },
    "linux": {
      "target": ["AppImage"],
      "category": "Utility"
    }
  }
}

13. Git Ignore

Create .gitignore:

node_modules/
dist/
release/
*.log
.DS_Store
*.db
*.db-shm
*.db-wal

14. README

Create a README.md with:

  • Project description
  • Development setup instructions
  • Available npm scripts
  • Architecture overview
  • Build instructions

15. Final Steps

After scaffolding:

  1. Run npm install to install all dependencies
  2. If --with-db: Run npm run migrate to create database
  3. Inform user they can start development with npm run dev
  4. List all available commands
  5. Mention key files to customize

Security Best Practices

Ensure all generated code follows:

  • ✅ contextIsolation: true
  • ✅ nodeIntegration: false
  • ✅ Use contextBridge for all IPC
  • ✅ Validate all IPC inputs in main process
  • ✅ Never expose full Electron APIs to renderer

Success Criteria

The skill should create a fully functional Electron app that:

  • ✅ Runs in development with hot reload
  • ✅ Has proper TypeScript types throughout
  • ✅ Uses secure IPC communication
  • ✅ Can be built for production
  • ✅ Follows modern Electron best practices
  • ✅ Is well-documented and ready to extend

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View