Skip to content

Commit 5d467a4

Browse files
dsactiviclaude
andcommitted
Add Electron MacOS desktop app support
- Added electron/main.js for desktop wrapper - Configured electron-builder for DMG/ZIP builds - Updated package.json with electron scripts and build config - Removed unused backend dependencies (better-sqlite3, express) - Updated .gitignore for build artifacts 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 483c994 commit 5d467a4

4 files changed

Lines changed: 9746 additions & 1076 deletions

File tree

‎.gitignore‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ node_modules/
33

44
# Build output
55
dist/
6+
build/
7+
dist-electron/
68

79
# Data
810
data/

‎electron/main.js‎

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
const { app, BrowserWindow, Menu } = require('electron');
2+
const path = require('path');
3+
4+
let mainWindow;
5+
6+
function createWindow() {
7+
mainWindow = new BrowserWindow({
8+
width: 1400,
9+
height: 900,
10+
minWidth: 800,
11+
minHeight: 600,
12+
titleBarStyle: 'hiddenInset',
13+
trafficLightPosition: { x: 15, y: 15 },
14+
webPreferences: {
15+
nodeIntegration: false,
16+
contextIsolation: true,
17+
},
18+
icon: path.join(__dirname, 'icon.png'),
19+
});
20+
21+
// Load the built app
22+
if (process.env.NODE_ENV === 'development') {
23+
mainWindow.loadURL('http://localhost:5173');
24+
mainWindow.webContents.openDevTools();
25+
} else {
26+
mainWindow.loadFile(path.join(__dirname, '../build/index.html'));
27+
}
28+
29+
mainWindow.on('closed', () => {
30+
mainWindow = null;
31+
});
32+
}
33+
34+
// Create menu
35+
const template = [
36+
{
37+
label: app.name,
38+
submenu: [
39+
{ role: 'about' },
40+
{ type: 'separator' },
41+
{ role: 'services' },
42+
{ type: 'separator' },
43+
{ role: 'hide' },
44+
{ role: 'hideOthers' },
45+
{ role: 'unhide' },
46+
{ type: 'separator' },
47+
{ role: 'quit' },
48+
],
49+
},
50+
{
51+
label: 'Edit',
52+
submenu: [
53+
{ role: 'undo' },
54+
{ role: 'redo' },
55+
{ type: 'separator' },
56+
{ role: 'cut' },
57+
{ role: 'copy' },
58+
{ role: 'paste' },
59+
{ role: 'selectAll' },
60+
],
61+
},
62+
{
63+
label: 'View',
64+
submenu: [
65+
{ role: 'reload' },
66+
{ role: 'forceReload' },
67+
{ role: 'toggleDevTools' },
68+
{ type: 'separator' },
69+
{ role: 'resetZoom' },
70+
{ role: 'zoomIn' },
71+
{ role: 'zoomOut' },
72+
{ type: 'separator' },
73+
{ role: 'togglefullscreen' },
74+
],
75+
},
76+
{
77+
label: 'Window',
78+
submenu: [
79+
{ role: 'minimize' },
80+
{ role: 'zoom' },
81+
{ type: 'separator' },
82+
{ role: 'front' },
83+
],
84+
},
85+
];
86+
87+
app.whenReady().then(() => {
88+
const menu = Menu.buildFromTemplate(template);
89+
Menu.setApplicationMenu(menu);
90+
createWindow();
91+
92+
app.on('activate', () => {
93+
if (BrowserWindow.getAllWindows().length === 0) {
94+
createWindow();
95+
}
96+
});
97+
});
98+
99+
app.on('window-all-closed', () => {
100+
if (process.platform !== 'darwin') {
101+
app.quit();
102+
}
103+
});

0 commit comments

Comments
 (0)