Windows and the renderer
Handle the window lifecycle
Follow macOS, Windows, and Linux conventions when the app starts, closes its windows, and becomes active again.
Electron APIs like BrowserWindow are not usable the moment your module loads. Electron has to finish starting first. So we create the first window only after app.whenReady() resolves:
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
This is a short block, but it encodes two different operating-system cultures. Let’s look at both.
Windows and Linux versus macOS
On Windows and Linux, closing the last window means quitting the app. Users expect the process to go away. That’s what the window-all-closed handler does: when no windows remain and we’re not on macOS, we call app.quit().
On macOS, apps usually keep running with no windows open. You see them in the Dock, and clicking the icon opens a new window. That’s the activate event. If there are no windows, we create one. On macOS, process.platform is 'darwin', which is why the quit branch is skipped there.
Four events that are easy to confuse
They sound similar, but they are different things:
- closing a window destroys that one window
window-all-closedfires when no application windows remain- quitting ends the main process
activatemeans the operating system brought the app to the front
A window can close without the app quitting. The app can quit with windows still open. Keep the two ideas apart in your head and in your code.
Don’t touch a destroyed window
After a window closes, its BrowserWindow object is destroyed. Calling methods on it throws. This bites you later, when the application menu sends an event to the window: check that mainWindow exists and that isDestroyed() is false before you call webContents.send().
That’s also why the previous lesson reset mainWindow to null in the closed handler.
Test the sequence on every platform
I run this checklist on each operating system I ship to:
- Launch the app and confirm one window appears.
- Close that window.
- On macOS, click the Dock icon and confirm a new window appears.
- On Windows or Linux, confirm the application exits.
- Quit from the menu and confirm no background process remains.
Step 5 matters. A main process that keeps running after quit is a bug users notice only in their task manager.
Desktop Notes saves on submit, so there is nothing to lose on close. If your real app has unsaved changes, decide where the close confirmation lives and test both paths: the user cancels, and the user confirms the quit. Lifecycle code that loses data is not finished.
Lesson completed