Kaiber
Generate, edit, and beat-sync AI video with leading models in one workspace.
Creates a production-ready Electron application with TypeScript, React, Vite, and best practices.
Full skill instructions
Creates a production-ready Electron application with TypeScript, React, Vite, and best practices.
/electron-app <app-name> [--with-db] [--with-tests] [--with-storybook]
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 developmentWhen this skill is invoked, create a new Electron application following these steps:
Create the project directory and initialize:
mkdir <app-name>
cd <app-name>
npm init -y
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
Update package.json with:
Core Dependencies:
electron: Latest stablereact, react-dom: ^18.xelectron-builder: For distributionDevelopment Dependencies:
typescript: ^5.xvite: ^5.x@vitejs/plugin-react: Latestelectron-builder: Latestconcurrently: For running dev serverswait-on: For coordinating startupIf --with-db:
better-sqlite3: ^9.xknex: ^3.x@faker-js/faker: For seedingIf --with-tests:
jest, @types/jestts-jest@testing-library/react, @testing-library/jest-domScripts:
{
"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"
}
}
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"]
}
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,
},
});
Create a secure main process with:
contextIsolation: true and nodeIntegration: false--with-db: Database initialization and IPC handlersKey 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());
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);
import type { ElectronAPI } from '../../../electron/preload';
declare global {
interface Window {
electronAPI: ElectronAPI;
}
}
export {};
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;
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
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';
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"
}
}
}
Create .gitignore:
node_modules/
dist/
release/
*.log
.DS_Store
*.db
*.db-shm
*.db-wal
Create a README.md with:
After scaffolding:
npm install to install all dependencies--with-db: Run npm run migrate to create databasenpm run devEnsure all generated code follows:
contextIsolation: truenodeIntegration: falsecontextBridge for all IPCThe skill should create a fully functional Electron app that:
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience