xiaohongshu
xiaohongshu
electron-scaffold
Scaffold a native-looking, effective Electron app with best practices baked in. Creates a production-ready Electron application with security hardening, modern tooling, proper IPC patterns, auto-updates, native UI elements, and optimal build configuration. Use this skill when users want to start ...
Full skill instructions
Create production-ready Electron applications with security, performance, and native platform integration best practices built in from the start.
Use this skill when:
Before scaffolding, verify:
Node.js: Check Node.js version (18.x or higher recommended)
node --version
npm or yarn: Verify package manager is available
npm --version
Git: Ensure git is available for version control
git --version
Ask the user which build system they prefer (or recommend based on use case):
Electron Forge (Recommended for most projects)
Electron Builder
Vite + Electron
Determine the UI framework:
Strongly recommend TypeScript for:
Based on tooling choice, initialize the project:
For Electron Forge (Recommended):
npm init electron-app@latest <app-name> -- --template=webpack-typescript
For Vite + Electron:
npm create @quick-start/electron <app-name>
For custom setup: Create package.json with proper dependencies (see templates).
Create a well-organized project structure:
<app-name>/
├── src/
│ ├── main/ # Main process
│ │ ├── main.ts # Entry point
│ │ ├── ipc/ # IPC handlers
│ │ ├── menu.ts # Native menu
│ │ └── tray.ts # System tray (if needed)
│ ├── preload/ # Preload scripts
│ │ └── preload.ts # Context bridge
│ ├── renderer/ # Renderer process
│ │ ├── index.html
│ │ ├── index.ts
│ │ └── styles/
│ └── shared/ # Shared types/utilities
│ └── types.ts
├── assets/ # Icons, images
├── resources/ # Build resources
├── dist/ # Build output
├── package.json
├── tsconfig.json
└── electron-builder.yml # or forge.config.js
CRITICAL: Implement security best practices from the start.
1. BrowserWindow Security Options:
const mainWindow = new BrowserWindow({
width: 1200,
height: 800,
webPreferences: {
// Security: Use preload scripts instead of nodeIntegration
nodeIntegration: false,
// Security: Isolate context between web content and preload
contextIsolation: true,
// Security: Disable remote module
enableRemoteModule: false,
// Security: Use sandboxed renderer
sandbox: true,
// Preload script for safe IPC
preload: path.join(__dirname, 'preload.js'),
// Security: Disable web security only in development if needed
webSecurity: true,
// Security: Disable navigation
allowRunningInsecureContent: false,
},
});
2. Content Security Policy (CSP):
// In main process or HTML meta tag
session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
callback({
responseHeaders: {
...details.responseHeaders,
'Content-Security-Policy': [
"default-src 'self'",
"script-src 'self'",
"style-src 'self' 'unsafe-inline'",
"img-src 'self' data: https:",
"connect-src 'self'",
].join('; '),
},
});
});
3. Context Bridge (preload.ts):
import { contextBridge, ipcRenderer } from 'electron';
// Expose protected methods that allow the renderer process to use
// the ipcRenderer without exposing the entire object
contextBridge.exposeInMainWorld('electronAPI', {
// Invoke pattern (request-response)
getAppVersion: () => ipcRenderer.invoke('app:get-version'),
// Send pattern (one-way)
logMessage: (message: string) => ipcRenderer.send('log:message', message),
// Listener pattern (for receiving events)
onUpdateAvailable: (callback: (info: any) => void) => {
ipcRenderer.on('update:available', (_event, info) => callback(info));
},
// Remove listener
removeUpdateListener: () => {
ipcRenderer.removeAllListeners('update:available');
},
});
4. IPC Security Pattern:
// main/ipc/handlers.ts
import { ipcMain } from 'electron';
// Use invoke/handle pattern for request-response
ipcMain.handle('app:get-version', async () => {
return app.getVersion();
});
// Validate and sanitize all inputs
ipcMain.handle('file:read', async (_event, filePath: string) => {
// Validate path is within allowed directories
const allowedDir = app.getPath('userData');
const resolvedPath = path.resolve(filePath);
if (!resolvedPath.startsWith(allowedDir)) {
throw new Error('Access denied');
}
return fs.readFile(resolvedPath, 'utf-8');
});
Create native-looking UI components:
1. Application Menu:
// main/menu.ts
import { Menu, shell } from 'electron';
export function createApplicationMenu(mainWindow: BrowserWindow) {
const template: MenuItemConstructorOptions[] = [
{
label: 'File',
submenu: [
{
label: 'New',
accelerator: 'CmdOrCtrl+N',
click: () => mainWindow.webContents.send('file:new'),
},
{ type: 'separator' },
{ role: 'quit' },
],
},
{
label: 'Edit',
submenu: [
{ role: 'undo' },
{ role: 'redo' },
{ type: 'separator' },
{ role: 'cut' },
{ role: 'copy' },
{ role: 'paste' },
],
},
{
label: 'View',
submenu: [
{ role: 'reload' },
{ role: 'forceReload' },
{ role: 'toggleDevTools' },
{ type: 'separator' },
{ role: 'resetZoom' },
{ role: 'zoomIn' },
{ role: 'zoomOut' },
{ type: 'separator' },
{ role: 'togglefullscreen' },
],
},
{
label: 'Help',
submenu: [
{
label: 'Learn More',
click: async () => {
await shell.openExternal('https://electronjs.org');
},
},
],
},
];
const menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);
}
2. System Tray (Optional):
// main/tray.ts
import { Tray, Menu, nativeImage } from 'electron';
export function createTray(mainWindow: BrowserWindow) {
const icon = nativeImage.createFromPath(
path.join(__dirname, '../assets/tray-icon.png')
);
const tray = new Tray(icon);
const contextMenu = Menu.buildFromTemplate([
{
label: 'Show App',
click: () => {
mainWindow.show();
},
},
{
label: 'Quit',
click: () => {
app.quit();
},
},
]);
tray.setContextMenu(contextMenu);
tray.setToolTip('My Electron App');
return tray;
}
1. Hot Reload Configuration:
// main.ts
const isDevelopment = process.env.NODE_ENV === 'development';
if (isDevelopment) {
mainWindow.loadURL('http://localhost:5173'); // Vite dev server
mainWindow.webContents.openDevTools();
} else {
mainWindow.loadFile(path.join(__dirname, '../renderer/index.html'));
}
2. Package.json Scripts:
{
"scripts": {
"dev": "concurrently \"npm:dev:*\"",
"dev:vite": "vite",
"dev:electron": "electron .",
"build": "npm run build:renderer && npm run build:main",
"build:renderer": "vite build",
"build:main": "tsc -p tsconfig.main.json",
"package": "electron-builder",
"package:all": "electron-builder -mwl",
"lint": "eslint src --ext .ts,.tsx",
"typecheck": "tsc --noEmit"
}
}
Implement automatic updates using electron-updater:
1. Install Dependencies:
npm install electron-updater
2. Update Configuration:
// main/updater.ts
import { autoUpdater } from 'electron-updater';
export function setupAutoUpdater(mainWindow: BrowserWindow) {
// Configure update server
autoUpdater.setFeedURL({
provider: 'github',
owner: 'your-username',
repo: 'your-repo',
});
// Check for updates on startup
autoUpdater.checkForUpdatesAndNotify();
// Update events
autoUpdater.on('update-available', (info) => {
mainWindow.webContents.send('update:available', info);
});
autoUpdater.on('update-downloaded', (info) => {
mainWindow.webContents.send('update:downloaded', info);
});
autoUpdater.on('error', (err) => {
mainWindow.webContents.send('update:error', err);
});
}
3. electron-builder Configuration:
# electron-builder.yml
appId: com.yourcompany.yourapp
productName: YourApp
directories:
output: dist
buildResources: resources
files:
- src/**/*
- package.json
mac:
category: public.app-category.productivity
target:
- dmg
- zip
hardenedRuntime: true
gatekeeperAssess: false
entitlements: resources/entitlements.mac.plist
win:
target:
- nsis
- portable
publisherName: Your Company
linux:
target:
- AppImage
- deb
category: Utility
publish:
provider: github
owner: your-username
repo: your-repo
tsconfig.json:
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"lib": ["ES2020", "DOM"],
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"outDir": "./dist",
"rootDir": "./src",
"types": ["node", "electron"]
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
Development:
npm run dev
Production Build:
npm run build
npm run package
Multi-platform Build:
npm run package:all
When scaffolding, ensure these are implemented:
process.on('uncaughtException', (error) => {
console.error('Uncaught Exception:', error);
// Log to file or error tracking service
app.quit();
});
process.on('unhandledRejection', (reason) => {
console.error('Unhandled Rejection:', reason);
});
window.addEventListener('error', (event) => {
window.electronAPI.logError({
message: event.error.message,
stack: event.error.stack,
});
});
window.addEventListener('unhandledrejection', (event) => {
window.electronAPI.logError({
message: 'Unhandled Promise Rejection',
reason: event.reason,
});
});
.icns icon formatactivate event (reopen window).ico icon format.png icon format.desktop file# Initialize with Forge
npm init electron-app@latest my-app -- --template=webpack-typescript
# Add security defaults
# Add IPC patterns
# Configure build
# Create with Vite template
npm create @quick-start/electron my-app -- --template react-ts
# Add security hardening
# Configure auto-update
# Add native menus
dist/, node_modules/, .envnodeIntegration without good reasonapp.getPath())For most users, recommend this command:
# Create app with TypeScript and Webpack
npm init electron-app@latest <app-name> -- --template=webpack-typescript
# Then apply security hardening, native UI, and build configuration
For detailed Electron API examples and configuration templates, see:
references/electron-security.md - Security best practicesreferences/ipc-patterns.md - IPC communication patternsreferences/build-config.md - Build and packaging configurationscripts/scaffold.sh - Automated scaffolding scriptAfter scaffolding, guide the user to:
package.json metadataThis skill targets:
Always check the latest Electron documentation for breaking changes.
xiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
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