# How to Ship a Desktop App as a Side Project
> Ship a desktop app as a side project: Electron vs Tauri, one OS first, codesigning, notarization, and auto-update before polish.

```yaml
url: "https://sidehunt.io/studio/how-to-ship-a-desktop-app-as-a-side-project"
markdown: "https://sidehunt.io/studio/how-to-ship-a-desktop-app-as-a-side-project.md"
title: How to Ship a Desktop App as a Side Project
slug: how-to-ship-a-desktop-app-as-a-side-project
category: Growth
tags:
  - side projects
  - desktop app
  - Electron
  - Tauri
  - Electron vs Tauri
  - codesign
  - notarization
  - auto-update
  - side project shipping
  - Growth
published_at: "2026-11-05T11:07:41.678Z"
updated_at: "2026-11-05T11:07:42.057Z"
featured_image: "https://txmhk1zrnc.ufs.sh/f/xSkWTCqmKWx9THaU5BGjqPRb1rifnSW7TtzXYp0eG5ma38QA"
```

## Article

To ship a desktop app as a side project, you usually do not need a native Mac or Windows rewrite. Pick Electron if you want your web stack inside a Chromium shell, or Tauri if you want a smaller binary that uses the system webview plus a Rust core; ship one OS first; get codesigning, notarization and auto-update right before you chase polish.

This guide is for employed builders with nights and weekends, often people who already have a web app or a local script and keep hearing "is there a desktop app?" Framework facts were checked against Electron, Tauri, Apple and Microsoft primary docs on 5 November 2026. The worked example is made up on purpose.

## When does a desktop app beat a website, a PWA or a phone app?

A desktop app is the right shape when the job lives on the computer itself: always-on tray or menu bar access, local files, offline-first tooling, OS shortcuts, or distribution that does not need a store listing on day one. If install-from-the-browser is enough, read [turning a side project into an installable web app](https://sidehunt.io/studio/how-to-turn-a-side-project-into-a-pwa). If the job is truly a phone job, read [shipping your first mobile app as a side project](https://sidehunt.io/studio/how-to-ship-a-mobile-app-as-a-side-project). This post does not re-teach manifests, service workers, App Store accounts or TestFlight.

Job

Desktop app fit

Usually better as

Always-on tray / menu bar companion

Strong

-

Reads and writes local project folders

Strong

-

Offline-first tooling with OS shortcuts

Strong

-

Same UI as your website, no local privileges

Weak

Website or PWA

Camera, maps, on-the-go capture

Weak

Phone app

You need store discovery more than a download page

Mixed

Store later, direct download first

## Electron vs Tauri: how do you choose?

[Electron](https://www.electronjs.org/) embeds Chromium and Node.js so one JavaScript codebase can ship on macOS, Windows and Linux. [Tauri](https://v2.tauri.app/start/) lets any HTML/JS/CSS frontend talk to a Rust (or plugin) core and uses the system webview instead of bundling a browser engine. Tauri's docs say a minimal app can be less than 600KB; Electron installers are larger because they ship Chromium and Node with your code. Native Swift, Kotlin or C# apps still win for deep platform UI, but they are a rewrite, not a side-project wrap of what you already built.

Question

Electron

Tauri

Native

Language / stack

JavaScript/TypeScript + Node in a Chromium shell

Web frontend + Rust core (Swift/Kotlin plugins optional)

Platform UI toolkits

Bundle size order of magnitude

Ships Chromium + Node with the app

System webview; minimal app can be under 600KB

Varies by toolkit

Security model

`contextIsolation` on, `nodeIntegration` off, renderer sandbox; no remote Node code

Capabilities / permissions gate what the webview can invoke

OS process model

Auto-update

`autoUpdater`, `update-electron-app`, or `electron-updater`

Official updater plugin with signed feeds

Store or custom

macOS / Windows / Linux

All three are first-class

All three desktop targets; mobile exists separately

Per platform

Rule of thumb for a React or Next side project: stay on Electron if you want one rendering target and the npm ecosystem. Pick Tauri when download size and a smaller attack surface matter more than Chromium parity, and you are willing to own a little Rust plus webview differences across OSes.

![A developer at a wooden desk with multiple laptops, a desktop monitor showing code, keyboards and an open notebook](https://images.pexels.com/photos/4974914/pexels-photo-4974914.jpeg?auto=compress&cs=tinysrgb&w=1200&h=800&fit=crop)

## Why ship one OS first?

For a nights-and-weekends project, pick Mac or Windows first based on where your early users already work. Packaging, codesigning, notarization or SmartScreen, and auto-update each have OS-specific steps. Linux can wait until one paid OS path is boring and documented in your own notes. Cross-compiling Windows NSIS from Linux or macOS is documented for Tauri, but local VMs or CI runners on the target OS are less fragile for a first release.

## What does a minimum project look like?

Both stacks start from a scaffold. [Electron's packaging tutorial](https://www.electronjs.org/docs/latest/tutorial/tutorial-packaging) points to [Electron Forge](https://www.electronforge.io/): import an existing app with `npx create-electron-app@latest import` (or scaffold fresh), then use `electron-forge start`, `electron-forge package` and `electron-forge make`, with makers listed in `forge.config.js`. Tauri starts with `npm create tauri-app@latest`, then a web frontend folder plus `src-tauri` for Rust, `tauri.conf.json` and a `capabilities` directory (see Tauri's [project structure](https://v2.tauri.app/start/project-structure/)).

Primary path in this post (Electron): one main process file, one preload that exposes a tiny API through `contextBridge`, one renderer (your existing React UI), and Forge makers for the OS you chose first. Sketch the Tauri twin lightly: frontend build output pointed at by `tauri.conf.json`, a few `invoke` commands, and a default capability JSON that lists only the permissions those commands need.

- Electron: main + preload + renderer; never put secrets in the renderer.
- Tauri: frontend + src-tauri ; grant capabilities per window, not "allow everything".
- Either way: one OS make/build script that produces an installer you can install on a clean machine.

## How do you package installers?

Electron core does not ship packaging. Forge is the officially documented all-in-one pipeline (`package` then `make`) and can produce OS-specific distributables such as DMG, MSI and zip through makers. [electron-builder](https://www.electron.build/) is the widely used community alternative; its homepage documents installers plus built-in `electron-updater` with staged rollouts. Tauri uses `tauri build` / `tauri bundle` (see the [distribute guide](https://v2.tauri.app/distribute/)) and can emit DMG or `.app` on macOS, MSI and NSIS (`-setup.exe`) on Windows per the [Windows installer docs](https://v2.tauri.app/distribute/windows-installer/), and AppImage (plus deb/rpm and others) on Linux.

- macOS: DMG or .app archive for direct download; App Store is a separate track.
- Windows: MSI (WiX Toolset v3) or NSIS setup exe.
- Linux: AppImage is the common "download and run" shape for side projects; add distro packages later if users ask.

## What do codesigning and notarization actually mean?

Codesigning attaches your developer identity to the binary so the OS can check it was not altered. On macOS, [Apple's Gatekeeper guide](https://support.apple.com/en-us/102445) explains that software from outside the Mac App Store is checked for a Developer ID signature, and that macOS Catalina and later also expect notarization so Apple can look for known malware. [Developer ID](https://developer.apple.com/developer-id/) certificates come with Apple Developer Program membership. Apple's enrollment help states the Program annual fee is 99 USD per membership year (local currency where available). You create a Developer ID Application certificate for apps shipped outside the Mac App Store, submit the build for notarization, then staple the ticket so offline Gatekeeper checks still pass. Ad-hoc or unpaid Personal Team signing is fine for your own Mac; Apple's membership overview and Tauri's [macOS signing guide](https://v2.tauri.app/distribute/sign/macos/) both note that free accounts cannot notarize, so other people still see unverified warnings.

On Windows, Authenticode signing with [SignTool](https://learn.microsoft.com/en-us/windows/win32/seccrypto/signtool) (Windows SDK) or a cloud flow such as [Azure Artifact Signing](https://learn.microsoft.com/en-us/azure/trusted-signing/how-to-signing-integrations) (formerly discussed as Trusted Signing) marks the installer as coming from a publisher. [Microsoft Defender SmartScreen](https://learn.microsoft.com/en-us/windows/security/operating-system-security/virus-and-threat-protection/microsoft-defender-smartscreen/) still warns on files that are not on its list of well-known, frequently downloaded files, so a brand-new signed build can show caution until reputation builds. Tauri's [Windows signing guide](https://v2.tauri.app/distribute/sign/windows/) notes that signing every release with the same certificate helps reputation carry forward, and that Windows 11 Smart App Control can block unknown unsigned apps entirely when it is on.

![A developer with headphones coding on a laptop at a desk by a city window with dual monitors](https://images.pexels.com/photos/1181676/pexels-photo-1181676.jpeg?auto=compress&cs=tinysrgb&w=1200&h=800&fit=crop)

## How do you ship auto-updates without breaking users?

Do not ask people to re-download the installer every week. Electron's [updating applications](https://www.electronjs.org/docs/latest/tutorial/updates) guide covers the built-in `autoUpdater` module (Squirrel.Mac / Squirrel.Windows), the free `update.electronjs.org` service for public GitHub Releases (macOS/Windows, codesigned on macOS), and helpers like `update-electron-app`. electron-builder's `electron-updater` adds providers such as GitHub Releases and S3, differential updates and staged rollouts. Tauri's [updater plugin](https://v2.tauri.app/plugin/updater/) requires signed update artifacts (public key in config, private key only in CI), HTTPS endpoints in production, and a static JSON or dynamic server feed. Ship a signed update channel before you grow past a handful of testers. Staged rollout, in one line: send the new build to a percentage of installs first so a bad update cannot brick everyone at once.

## Which security basics do first-timers miss?

Electron's [security tutorial](https://www.electronjs.org/docs/latest/tutorial/security) is blunt: Electron is not a browser. Defaults since recent majors keep `nodeIntegration` off, `contextIsolation` on and renderer sandboxing on; leave them that way. Load local packaged UI, not remote HTML with Node powers. Do not disable `webSecurity`. Prefer a Content-Security-Policy. Validate IPC senders. Never ship API keys or signing private keys inside the binary.

Tauri's [security overview](https://v2.tauri.app/security/) and [capabilities](https://v2.tauri.app/security/capabilities/) docs describe a hard split: Rust core code has full system power; the webview only gets what you grant through capabilities and command scopes.

- Electron: contextIsolation: true , nodeIntegration: false , sandbox on; expose only narrow contextBridge APIs.
- Tauri: start from least-privilege capabilities; do not grant filesystem or shell permissions "just in case".
- Both: treat update feeds and download URLs as security boundaries; only install signed updates.

## Should you start outside the stores?

Yes for a side project. GitHub Releases plus a simple download page lets you iterate without review queues. Mac App Store and Microsoft Store add discovery and some trust signals, but also agreements, sandbox rules and slower loops. Ship direct download with proper codesigning first; revisit stores when users ask or when enterprise IT requires a store link. If you later open-source the wrapper, keep license choice to one honest line and point at [open-sourcing a side project without regretting it](https://sidehunt.io/studio/how-to-open-source-your-side-project-without-regretting-it).

## How do you measure installs lightly?

Count GitHub Release asset downloads for a coarse install signal. Optionally add a first-run ping that only fires after an in-app consent screen, and keep it to one event with an app version string. For product analytics on the marketing site or account dashboard, reuse what you already check on Mondays; see [analytics for a side project you will actually check](https://sidehunt.io/studio/how-to-set-up-analytics-for-a-side-project-youll-actually-check). This section is not an analytics tooling guide.

## Weak patterns vs better patterns

Weak

Better

Unsigned DMG / EXE and a blog post saying "ignore the warning"

Developer ID + notarization (Mac) or Authenticode (Windows)

Giant Electron build with `nodeIntegration` on

Isolated preload API, Node off in the renderer

"Please download the new zip" every release

Signed auto-update feed with a staged rollout

Shipping Mac and Windows and Linux in week one

One OS until signing and updates are boring

Hard-coding secrets into the packaged app

Secrets only on your server or in the user's keychain

## Which traps catch first-time desktop shippers?

- Polishing UI for three weekends before the first signed installer exists.
- Testing only on your already-trusted machine (Gatekeeper and SmartScreen behave differently for strangers).
- Turning off Electron isolation flags "just to make IPC easier".
- Losing the Tauri updater private key or the Apple/Windows signing cert backup.
- Promising Linux, Mac App Store and Microsoft Store on the launch tweet.

## A made-up example: Mira and Querntray

Mira is a backend engineer. Querntray is invented for this article: a menu-bar / tray clipboard helper that keeps colour codes and asset URLs for a small design team. Numbers below are made up.

She already had a React UI for a private web version. Users asked for a desktop app so pastes worked offline during flights. She chose Electron because the UI was already React and she did not want a Rust learning week before the first install. Weekend one: Forge import, tray window, one OS (Mac, because her five testers were on Mac), Developer ID signing and notarization wired in CI with environment variables, not files committed to git. Weekend two: `update-electron-app` pointed at GitHub Releases, a first-run consent ping, and a Windows NSIS build only after two Mac releases felt calm. She skipped stores. Download counts on GitHub plus three customer replies were enough signal to decide the next feature.

## A one-weekend / two-weekend plan

Timings are suggestions for an employed builder, not promises.

Block

Focus

Done when

Friday evening

Fit check + stack pick (Electron or Tauri) + one OS

Written decision in the README

Saturday morning

Scaffold, load your existing UI, tray or main window

App runs locally on your machine

Saturday afternoon

Package an installer; install on a clean profile/VM

You can open the installed app without the dev command

Sunday

Codesign (+ notarize on Mac); publish to GitHub Releases

A friend can install without you screensharing

Next weekend

Auto-update + minimal first-run metric + second OS only if needed

An update installs from the feed on a test machine

## FAQ

### Electron or Tauri for a React or Next side project?

Electron if you want Chromium parity and the least new language surface. Tauri if a small download and capability-based IPC matter more, and you accept system webview differences plus some Rust.

### Do I need an Apple Developer account?

To distribute a Mac build other people can open without scary Gatekeeper detours, yes: a paid Apple Developer Program membership is what Apple documents for Developer ID signing and Mac software notarization. A free Personal Team is for your own devices and expires quickly.

### Can I wrap my existing website?

You can load local UI that talks to your API. Loading a remote site with Node integration enabled is exactly what Electron's security guide warns against. Prefer a packaged renderer and a small trusted bridge.

### Will antivirus or SmartScreen flag my app?

New downloads often get caution screens until reputation exists. Signing helps identity; it does not skip reputation. Unsigned builds are worse, and Smart App Control can block them outright.

## Ship the installer people can trust

Pick the shell that matches your stack, finish one OS with signing and updates, then invite real users. When you want a calm place to launch the side project around that desktop build, [SideHunt](https://sidehunt.io/) is built for weekly side-project hunts.

## Links

- [Studio post (HTML)](https://sidehunt.io/studio/how-to-ship-a-desktop-app-as-a-side-project)
- [AI-friendly Markdown](https://sidehunt.io/studio/how-to-ship-a-desktop-app-as-a-side-project.md)

## Explore

- [Studio index](https://sidehunt.io/studio)
- [Blog](https://sidehunt.io/blog)
- [Launches](https://sidehunt.io/launches)

_HTML version: https://sidehunt.io/studio/how-to-ship-a-desktop-app-as-a-side-project_
