Development environment setup
This guide covers the development environment for Tinka Apps. You will learn how to:
- Run the App with
act serve, which rebuilds and restarts it when you change a file - Read build errors in the terminal and in the browser
- Reload open pages after each change
- Watch files on network drives and in containers
- Set up your code editor
Overview
While you work, the App should follow your edits without you stopping and starting it. act serve builds the App, runs it, and watches its files. When you save a change, it builds the new App while the old one keeps serving, then restarts it in a few milliseconds. Requests that arrive during the restart wait instead of failing, and pages open in your browser reload.
act serve runs the App's own binary, the one that runs in production, built with the same go build. Nothing is generated before the build, and nothing about the App changes in development: shutdown hooks run on each restart exactly as they do when your platform stops the App.
Run the dev server
Run act serve from the App's directory:
act serve INFO Watching for changes (inotify, 12 directories)
INFO Built in 2.0s, serving http://localhost:3000Open the address it prints. Building and running the App runs its code, so the first time, act asks whether you trust the App's directory. See act trust.
act serve serves on localhost:3000. Pass --addr for another address, such as --addr :8080 to accept connections from other machines on your network:
act serve --addr localhost:8080The App's own Addr doesn't apply under act serve: the dev server decides where the App listens, and passes it the listener.
act serve answers requests for localhost, its subdomains such as blog.localhost, and IP addresses. A request for any other name gets a 403, because a web page you visit could otherwise point a name of its own at your machine and read your App through your browser. To open the App under a name of your own, such as one in /etc/hosts, allow it:
act serve --allow-host blog.testWhat happens on a change
act serve reacts to the files a build reads: Go files, go.mod, go.sum and files your code embeds. A save that changes none of them, such as an editor's swap file, starts no build. For a change that does:
Build
The new App is built while the old one keeps serving the previous code. A change made during a build cancels it and starts again from the newest files.
Stop the old App
The old App receives
SIGTERMand shuts down gracefully: requests in flight finish and shutdown hooks run. It is killed if it hasn't stopped after 15 seconds.Start the new App
The new App starts on the same listener. Requests that arrived in between wait in the queue, so none fails.
INFO Built in 1.3s, restarted in 37msWhen the App stops on its own, such as when it fails to connect to its database at startup, act serve shows its output and starts it again on your next change.
Read build errors
When a build fails, the old App keeps running and act serve prints the compiler's errors:
ERROR The build failed after 412ms; the App keeps running its previous code
# example.com/blog
./posts.go:14:9: undefined: renderPages you open in the browser show the same errors instead of the App, so you see them where you're looking. Requests that don't come from a browser page, such as fetch calls and API clients, still reach the old App. Fixing the error swaps the new App in.
Reload open pages
After each restart, and when a build fails, pages open in the browser reload on their own. act serve adds a small script, /__tinka/live.js, before the closing </body> of every full HTML page the App returns. Fragments, such as htmx's partial responses, and anything that isn't HTML are left as they are. The script is a file of its own, so a Content-Security-Policy of script-src 'self' allows it.
Watch network drives and containers
act serve learns about changes from the operating system on Linux and Windows. Some file systems never report changes, such as network drives, folders shared into a virtual machine or a container, and paths under /mnt in WSL. Pass --poll to check for changes on a timer instead:
act serve --pollOn macOS, act serve always checks on a timer. A check takes a few milliseconds for an App of a few hundred files.
Serve without the proxy
act serve listens on --addr and forwards requests to the App, which is what lets it hold requests during a restart, show build errors and reload pages. Pass --no-proxy to give the App the address directly, with none of these:
act serve --no-proxyOn Linux and macOS the port still stays open across restarts. On Windows, connections made during a restart fail.
Set up your editor
Tinka is plain Go, so every editor with Go support works. Install gopls, the Go team's language server, through your editor's Go extension, and turn on formatting on save, so every file stays gofmted.
See also: Commands reference, Application lifecycle, Configuration & Environment