Courses/Grit Desktop/Build & Distribution
Course 5 of 5~30 min10 challenges

Build & Distribution

In this final course, you will compile your desktop app into a native binary, learn about platform targets, customize the app icon, optimize the file size, and understand how to distribute your app to users.


Development vs Production

Until now, you've been running your app in development mode with grit start. Development mode includes tools that help you build the app but are not needed by end users:

Development Build: A version of your app optimized for developers. Includes hot reload (instant updates when you save a file), detailed error messages, debug tools (DevTools, console logs), and source maps. Slower and larger than a production build, but much easier to work with.
Production Build: A version of your app optimized for end users. The Go code is compiled into a single native binary. The React code is bundled, minified, and embedded inside that binary. No source code is visible, no debug tools, no hot reload — just a fast, small, distributable executable file.
FeatureDevelopmentProduction
Hot reloadYesNo
DevToolsAvailableDisabled
File sizeLarge (many files)Small (single binary)
SpeedSlower (interpreted)Fast (compiled)
RequirementsGo, Node, pnpm, WailsNothing (standalone binary)

Building Your App

To compile your app into a production binary, run:

Terminal
grit compile

Or use the Wails command directly:

Terminal
wails build

Here is what happens during the build:

  • 1. Vite builds React — bundles, minifies, and optimizes all JavaScript, CSS, and assets
  • 2. Go embeds the frontend — the built React files are embedded into the Go binary using go:embed
  • 3. Go compiles to native code — the entire application (backend + embedded frontend) becomes a single executable
Native Binary: A compiled executable file that runs directly on the operating system without needing Go, Node, or any runtime installed. The user downloads one file and double-clicks it. On Windows it's a .exe, on macOS it's a .app bundle, and on Linux it's an ELF binary.

The output binary is placed in the build/bin/ directory:

Build output
build/
└── bin/
    └── myapp.exe     # Windows
    └── myapp         # macOS / Linux
1

Challenge: Build Your App

Run grit compile in your project directory. How long does it take? Where is the output file? What is the file size? Try double-clicking the binary — does the app open?

Platform Targets

Wails can build for different operating systems and architectures:

Terminal
# Build for your current platform (default)
wails build

# Build for Windows (64-bit)
wails build -platform windows/amd64

# Build for macOS (Intel)
wails build -platform darwin/amd64

# Build for macOS (Apple Silicon / M1, M2, M3)
wails build -platform darwin/arm64

# Build for Linux (64-bit)
wails build -platform linux/amd64
Cross-platform: Software that runs on multiple operating systems. Wails apps can target Windows, macOS, and Linux from the same Go + React codebase. You write your code once and compile it for each platform.
Cross-compilation (building for a different OS than your development machine) may require additional tools. Building a macOS app from Windows requires a macOS machine or CI service. Building a Windows app from macOS works with the right toolchain installed. Building for your current platform always works out of the box.
2

Challenge: Build for Your Platform

Build for your current platform with grit compile. Find the output binary in build/bin/. Run it directly (double-click on Windows, ./myapp on macOS/Linux). Does it work the same as dev mode?

App Icon

Every desktop app needs an icon — it appears in the taskbar, dock, file explorer, and the window title bar. Wails uses icon files in the build/ directory:

Icon files
build/
├── appicon.png        # 1024x1024 PNG (used for all platforms)
├── windows/
│   └── icon.ico       # Windows icon (multi-size)
├── darwin/
│   └── appicon.icns   # macOS icon (multi-size)
└── linux/
    └── appicon.png    # Linux icon

To change the icon:

  • 1. Create a 1024x1024 pixel PNG image for your app icon
  • 2. Replace build/appicon.png with your new image
  • 3. Rebuild with grit compile — Wails converts it to platform-specific formats
Use a simple, recognizable design for your icon. It will be displayed at sizes from 16x16 to 1024x1024 pixels, so avoid fine details that disappear at small sizes. Tools like Figma, Canva, or icon generators can help you create one.
3

Challenge: Change the App Icon

Find the default app icon file in the build/ directory. Replace it with a custom PNG (1024x1024). Rebuild and check — does the new icon appear in the taskbar and window title?

Window Configuration

The wails.json file controls how the production window appears:

wails.json (window settings)
{
  "name": "My App",
  "width": 1024,
  "height": 768,
  "minWidth": 800,
  "minHeight": 600,
  "frameless": true,
  "fullscreen": false,
  "resizable": true
}

The name field is what appears in the operating system's task manager and window list. The size settings define the default dimensions and minimum size.

4

Challenge: Configure Window Size

Change the default window size to 1200x800 in wails.json. Rebuild with grit compile and run the binary. Is the window larger? Try resizing it below the minimum dimensions — does it stop at the minimum?

File Size

A typical Grit desktop app binary is 15-30 MB. This includes the entire Go backend, all React code, CSS, and embedded assets. For comparison, an Electron app with similar features would be 100-200 MB.

You can reduce the binary size by stripping debug symbols:

Terminal
# Build with stripped debug symbols (smaller binary)
wails build -ldflags "-s -w"

# -s removes the symbol table
# -w removes DWARF debugging information

For even smaller binaries, you can use UPX compression (a tool that compresses executables):

Terminal
# Install UPX (if not already installed)
# Windows: scoop install upx
# macOS: brew install upx
# Linux: apt install upx

# Compress the binary
upx --best build/bin/myapp.exe

Typical size reduction:

Build TypeTypical Size
Default build25-30 MB
Stripped (-s -w)15-20 MB
Stripped + UPX8-12 MB
5

Challenge: Optimize Binary Size

Build your app normally and note the file size. Then rebuild with wails build -ldflags "-s -w". How much smaller is it? If you have UPX installed, compress it further. What's the final size?

Distribution

Once your app is compiled, you need to get it to your users. There are several distribution methods:

Direct Download

The simplest method — upload the binary to your website, GitHub Releases, or a file hosting service. Users download the file and run it. No installer needed.

Windows Installer (NSIS)

Wails can generate an NSIS installer for Windows. This creates a .exe installer that adds your app to the Start Menu, creates desktop shortcuts, and supports uninstallation:

Terminal
wails build -nsis

macOS DMG

On macOS, Wails builds a .app bundle. You can package it into a .dmg disk image for distribution — the standard macOS app distribution format.

Linux AppImage

For Linux, you can package the binary as an AppImage — a single executable that works on most Linux distributions without installation.

Code Signing

Code Signing: Digitally signing your application with a certificate so the operating system trusts it. Without code signing, Windows shows a "Windows protected your PC" warning, and macOS shows an "unidentified developer" warning. Code signing tells the OS that the app comes from a verified developer.
  • Windows — requires a code signing certificate ($200-400/year) from a Certificate Authority
  • macOS — requires an Apple Developer account ($99/year) and notarization through Apple's servers
  • Linux — code signing is optional; most Linux users install from package managers or trust direct downloads
Code signing is important for production apps distributed to many users, but it's not required for personal projects, internal tools, or early development. You can distribute unsigned apps — users just need to click through an extra warning dialog.
6

Challenge: Build an Installer

If you're on Windows, try building with wails build -nsis to generate an installer. Run the installer — does it create a Start Menu entry and desktop shortcut? Can you uninstall it from Settings?

Publishing with GitHub Releases

The most common way to distribute desktop apps for open-source projects is GitHub Releases. You build for each platform and upload the binaries:

Terminal
# Build for your platform
grit compile

# Create a GitHub release (using gh CLI)
gh release create v1.0.0 build/bin/myapp.exe --title "v1.0.0" --notes "Initial release"

# Or upload multiple platform binaries
gh release create v1.0.0   build/bin/myapp-windows-amd64.exe   build/bin/myapp-darwin-amd64   build/bin/myapp-linux-amd64   --title "v1.0.0" --notes "Initial release"

Users visit your GitHub repository's Releases page and download the binary for their platform.

7

Challenge: Prepare for Release

Build your app for your current platform. Create a CHANGELOG.md file documenting what your app does. If you have a GitHub repository, create a release and upload the binary.

What You Learned

  • The difference between development builds and production builds
  • How to compile your app with grit compile or wails build
  • Platform targets — building for Windows, macOS, and Linux
  • How to customize the app icon
  • Window configuration in wails.json
  • Optimizing binary size with -ldflags "-s -w" and UPX
  • Distribution methods — direct download, NSIS installer, DMG, AppImage
  • What code signing is and when you need it
8

Challenge: Full Build Challenge

Build your notes app for your current platform. Test the binary — create some data, export to PDF, verify everything works the same as dev mode. Check the file size.

9

Challenge: Customize and Rebuild

Change the window title in wails.json. Replace the app icon with a custom one. Rebuild with -ldflags "-s -w". Compare the file size to the previous build. Does the new title and icon appear?

10

Challenge: Share Your App

Send the compiled binary to a friend (or test on a different computer). Does it run without installing Go, Node, or Wails? Does the SQLite database get created automatically on first launch? This is the power of a native binary — zero dependencies for the end user.

Course Complete

Congratulations — you've completed the entire Grit Desktop course track. You now know how to:

  • Scaffold a desktop app with grit new-desktop
  • Generate full CRUD resources with Wails bindings
  • Customize the UI with frameless windows, themes, and shadcn/ui
  • Export data to PDF, Excel, and CSV
  • Compile and distribute a native binary

Next steps: build something real. A personal finance tracker, a note-taking app, a project management tool, a CRM for your business — the possibilities are endless. Every app follows the same pattern: scaffold, generate resources, customize the UI, export data, and ship.