Quick Start

Install GoLazy

Install the lazy CLI, create a GoLazy app, and run it locally.

By Guillermo Alvarez - Published - Updated

Install the CLI

Install the lazy command with the GoLazy installer:

curl -fsSL https://golazy.dev/install.sh | sh

The installer checks for Go, installs mise when it is missing, installs the latest lazy command from golazy.dev/lazy into a stable user bin directory, and prints a lazy new command using your GitHub username when it can detect one. When $SHELL resolves to bash, zsh, or fish, it tries the matching official mise shell installer first so future shells get activation; if that does not complete, it falls back to the plain bootstrap script. This avoids version-manager-specific Go bin directories.

Confirm the command is on your PATH:

lazy --version

If the installer prints a PATH note, add the printed export PATH=... line to your shell startup before continuing. The example uses $HOME/... for install directories under your home directory and the full path for any other directory. Opening a new shell is usually enough after the installer updates your shell startup files. To continue in the same shell, use the printed export PATH=... lines before running lazy new and lazy.

lazy --version is also used by lazy new to select the matching sample_app tag.

Inside an existing GoLazy app, app-bound lazy commands follow the golazy.dev version required by that app's go.mod. If your global lazy binary is newer or older, it runs or installs the matching CLI version from your user cache before continuing.

Create a full app

Generate an application from the sample app template:

lazy new github.com/user/my_first_lazy_app
cd my_first_lazy_app

The generated module is a normal Go module. Its executable lives under cmd/app, while application behavior lives under app and init. Before cloning a remote template, lazy new checks for a newer lazy at https://golazy.dev/lazy.version with a one-second timeout. If a newer CLI is available, update lazy first or pass --skip-update-check. Use lazy new --version v0.1.10 ... when you intentionally need an older sample app tag. lazy new also trusts the generated mise.toml, runs mise install, and validates the app with the current go on PATH. If mise was just installed into $HOME/.local/bin and your current shell has not picked that up yet, lazy new uses that mise directly for setup. Open a new shell before running lazy normally. After validation, lazy new initializes a fresh Git repository, commits the generated checkout with a command-local GoLazy identity, and prints the generated app directory and the lazy command to run next.

Run the app

Start the development loop:

lazy

If you are continuing in the same shell that ran the installer before opening a new shell, apply the printed export PATH=... lines first:

lazy

The command finds the app command, generates JavaScript assets when js.toml is present, runs go mod tidy, builds a temporary binary, starts it on an internal loopback address, and proxies the public address. By default the public address is :3000.

Set a different address when needed:

ADDR=127.0.0.1:4000 lazy

If you need to run the app while sorting out CLI installation, use Go directly:

go run ./cmd/app

What to inspect first

The first request goes through the same files every generated app uses:

cmd/app/main.go
init/app.go
init/context.go
init/routes.go
app/controllers/home/
app/views/home/index.html.tpl

For the standard route table, init/routes.go starts small:

func Draw(router *lazyroutes.Scope) {
    router.Get("/", home.New, (*home.HomeController).Index)
    router.Resources(postcontroller.New)
}

Verify the generated app

Run the app checks from the module root:

lazy tailwind
lazy js
go test ./...

The asset commands refresh generated public files before Go tests or builds embed them.

Continue with Single-File App when you want the smallest possible shape, or Full App when you want to understand the generated layout.