Courses/Grit Desktop/Your First Desktop App
Course 1 of 5~30 min12 challenges

Your First Desktop App

In this course, you will install Wails, scaffold a desktop application with Grit, understand how Go functions are called directly from React, and run your app in dev mode. By the end, you will have a working desktop app with authentication, blog CRUD, and a SQLite database.


What is a Desktop App?

Desktop Application: A program that runs directly on your computer's operating system (Windows, macOS, or Linux). Unlike a web app that runs in a browser, a desktop app is a standalone window on your computer. Think VS Code, Spotify, or Discord — they run without needing a browser.
Native App: An application compiled specifically for one operating system. It can access local files, system notifications, the clipboard, and other OS features that web apps cannot.

Desktop apps are different from web apps in several important ways:

  • They run locally — no browser needed, no internet required (unless your app needs it)
  • They can access the filesystem — read and write files on the user's computer
  • They feel faster — no network latency between the UI and backend
  • They are distributed as a single file — users download one executable and run it

Grit uses Wails to build desktop apps. You write Go for the backend and React for the UI — the same languages you already know from Grit web.

What is Wails?

Wails: A Go framework for building desktop applications using web technologies. Go handles the backend logic, React handles the UI. The key difference from web apps: Go functions are directly callable from JavaScript — no HTTP requests, no REST APIs, no fetch(). Just function calls.

Wails works by embedding a webview (a lightweight browser engine) inside a native window. Your React app runs in this webview, and Wails creates a bridge so JavaScript can call Go functions directly:

  • Go side: You write normal Go methods like GetUsers() or CreateBlog(input)
  • React side: You import and call them as if they were local functions — const users = await GetUsers()
  • No HTTP layer: No REST endpoints, no fetch(), no axios — direct function calls over an internal bridge

Learn more at wails.io. Wails supports Windows, macOS, and Linux from a single codebase.

1

Challenge: Visit Wails.io

Open wails.io in your browser. What platforms does Wails support? Find the "Getting Started" section — does it mention Go as a requirement?

Prerequisites

You need the same tools as Grit web (Go, Node.js, pnpm) plus one more — the Wails CLI:

ToolVersionCheck
Go1.21+go version
Node.js18+node --version
pnpm8+pnpm --version
Wails CLIv2wails version

Install the Wails CLI with:

Terminal
go install github.com/wailsapp/wails/v2/cmd/wails@latest

After installation, verify everything is working:

Terminal
wails doctor

The wails doctor command checks your system for all required dependencies (Go, Node, npm/pnpm, platform-specific build tools) and reports any issues.

2

Challenge: Install Wails CLI

Run go install github.com/wailsapp/wails/v2/cmd/wails@latest to install the Wails CLI. Then run wails doctor. Does it pass all checks? If any checks fail, follow the instructions to fix them.

Scaffold a Desktop App

The command for desktop apps is grit new-desktop — this is different from grit new which creates a web monorepo:

Terminal
grit new-desktop myapp
grit new-desktop creates a standalone app, not a monorepo. There is no apps/ folder, no packages/ folder, no Turborepo. Everything lives in a single flat directory. This is intentional — desktop apps are self-contained.

After running the command, Grit creates a complete desktop project with authentication, blog CRUD, contact CRUD, a dark theme, and a SQLite database — all wired up and ready to run.

3

Challenge: Scaffold Your First Desktop App

Run grit new-desktop notes-app. Look at the folder structure that was created. How many Go files are in the root directory? How many folders are there?

Project Structure

A Grit desktop project has a flat, simple structure:

Project Structure
notes-app/
├── main.go          <- Wails bootstrap + Go embed
├── app.go           <- Bound methods (Go functions callable from React)
├── internal/        <- Go backend (models, services, config, db)
├── frontend/        <- React app (Vite + TanStack Router)
├── wails.json       <- Wails configuration
└── .env             <- Environment variables

Compare this to a Grit web project which has apps/api, apps/web, apps/admin, and packages/shared. A desktop project is much simpler — everything is in one place.

Wails Bindings: Go functions exposed to JavaScript. You write a Go method like GetUsers() and call it from React as if it were a local function. No HTTP, no REST — direct function calls. Wails automatically generates TypeScript wrappers for every bound Go method.

The key file is app.go — this is where all your Go methods that React can call are defined. Every public method on the App struct becomes available in the frontend:

app.go (simplified)
type App struct {
    ctx         context.Context
    authService *services.AuthService
    blogService *services.BlogService
}

// React can call: Login({ email, password })
func (a *App) Login(input types.LoginInput) (*types.AuthResponse, error) {
    return a.authService.Login(input)
}

// React can call: GetBlogs()
func (a *App) GetBlogs() ([]models.Blog, error) {
    return a.blogService.List()
}
4

Challenge: Explore app.go

Open app.go in your notes-app project. What methods are available? These are the functions React can call. Count how many public methods the App struct has.

Running in Dev Mode

Start your desktop app with either command:

Terminal
cd notes-app
grit start

Or use the Wails command directly:

Terminal
wails dev
Hot Reload: The app automatically updates when you save a file. Change Go code and the backend restarts. Change React code and the UI updates instantly. No manual restart needed. This makes development fast — save a file and see the result immediately.

When you run grit start, a native desktop window opens with your app. The frontend dev server runs at localhost:34115 (you can also open it in a browser for debugging).

If you need to debug the frontend, right-click inside the desktop window and select "Inspect Element"to open the browser DevTools — just like in Chrome.
5

Challenge: Run Your Desktop App

Run grit start in your notes-app directory. The app should open as a desktop window. Try the login page — can you see the registration form?

SQLite Database

SQLite: A file-based database that requires no server. Your entire database lives in a single .db file in your project folder. No Docker, no PostgreSQL installation, no configuration. SQLite is the most widely deployed database engine in the world — it's inside every smartphone, every browser, and now inside your desktop app.

Desktop apps use SQLite instead of PostgreSQL because users should not need to install a database server. The database file travels with the app — it's just a file on disk:

.env
DB_PATH=./data.db

When the app starts, GORM automatically creates the .db file and runs migrations. You can browse the database with GORM Studio:

Terminal
grit studio
6

Challenge: Find the Database File

After running the app and registering an account, find the .db file in your project folder. Open GORM Studio with grit studio and browse the tables. Can you see the user you just registered?

Tour the App

Your scaffolded desktop app comes with everything you need to start building:

  • Login and Register pages — local authentication with bcrypt password hashing
  • Dashboard — stats cards showing total blogs, contacts, and recent activity
  • Blog CRUD — create, read, update, and delete blog posts
  • Contact CRUD — manage a contacts list with full CRUD operations
  • Sidebar navigation — collapsible sidebar with icons for every section
  • Dark theme — premium dark UI using Grit's design system
7

Challenge: Create Some Data

Register an account in your app. Create 3 blog posts with different titles and content. Create 2 contacts with names and emails. Visit the dashboard — do the stats update to show your new data?

The .env File

Desktop apps have a simpler .env file compared to web projects — no database URLs, no Redis, no S3 storage:

.env
APP_NAME=notes-app
JWT_SECRET=your-secret-key-change-in-production
DB_PATH=./data.db
TOTP_ISSUER=notes-app
  • APP_NAME — your application name, shown in the title bar
  • JWT_SECRET — secret key for signing authentication tokens
  • DB_PATH — path to the SQLite database file
  • TOTP_ISSUER — name shown in authenticator apps for two-factor auth
8

Challenge: Read the .env File

Open the .env file in your project. What is the database file name? What is the JWT_SECRET set to?

Essential Commands

Here are the commands you'll use every day when building desktop apps:

CommandWhat it does
grit startStart the app in dev mode with hot reload
grit studioOpen the database browser for your SQLite database
grit generate resourceGenerate a new CRUD resource (model, service, routes, UI)
grit routesList all bound methods (desktop equivalent of API routes)
grit compileBuild a production-ready executable
9

Challenge: Try the Commands

Run grit routes in your project folder. How many routes does the desktop app have? Can you identify which ones handle blogs and which handle contacts?

10

Challenge: Explore GORM Studio

Run grit studio. Browse the tables in your SQLite database. Can you see the blogs and contacts you created earlier? Try editing a record directly in Studio.

What You Learned

  • What desktop apps are and how they differ from web apps
  • What Wails is — Go + React desktop framework with direct function calls
  • How to install the Wails CLI and verify with wails doctor
  • How to scaffold a desktop app with grit new-desktop
  • The flat project structure (main.go, app.go, internal/, frontend/)
  • How Wails bindings work — Go methods callable from React
  • How to run in dev mode with grit start and hot reload
  • SQLite as the database — file-based, no server required
  • The essential CLI commands for desktop development
11

Challenge: Final Challenge: Build a Todo App

Create a brand new desktop app called todo-app with grit new-desktop todo-app. Start it, register an account, create 5 blog posts, then open GORM Studio to see the data in SQLite. Verify the .db file exists in the project folder.

12

Challenge: Bonus: Compare Web vs Desktop

If you've completed the Grit Web course, create a web project with grit new webtest and a desktop project with grit new-desktop desktest side by side. List 3 differences you notice in the project structure, the way data is fetched, and the dev experience.