Create the App
This chapter creates the App the rest of the tutorial builds on. You will learn how to:
- Install the Tinka CLI and
act - Create an App from the skeleton starter kit
- Run the App with
act serveand send it a request - Read what
act servedoes when you save a change
Overview
The skeleton starter kit gives a new App the structure every later chapter relies on: configuration read from the environment, one place for routes, and tests ready to run. act serve then runs the App and builds it again each time you save a file, so you start it once, in a terminal of its own, and keep it running while you work.
Install the tools
Tinka has two commands, both installed with Go's own tooling. tinka creates Apps, and act runs Commands inside an App, such as act serve.
Install the Tinka CLI
Terminal go install github.com/mucolabs/tinka/cmd/tinka@latestInstall act
Terminal go install github.com/mucolabs/tinka/cmd/act@latest
Go places both binaries in $(go env GOPATH)/bin, which must be on your PATH. Installation shows how to check them, and the setting Go needs during the alpha, while the Tinka repository is private.
Create the App
Run tinka new with the directory to create. It asks which starter kit to use: choose skeleton. Answer yes when it asks whether to initialize a git repository, since the last chapter versions the App from its git tags.
tinka new blog Copying the skeleton kit ............................................ 5ms DONE
Installing dependencies ............................................ 70ms DONE
Initializing a git repository ....................................... 9ms DONE
Created blog with the skeleton kit
cd blog
act servetinka new copies the kit, requires the version of Tinka it was installed at, downloads the dependencies and generates the App's APP_KEY into .env. It also trusts the new directory, so act builds and runs the App's code without asking first. Move into the App:
cd blogLook around the App
The skeleton puts each kind of code in its own package. These are the ones the tutorial changes:
| Path | Holds |
|---|---|
main.go |
The entry point: it loads the configuration and runs the App |
start/app.go |
App, which builds the App and adds its services and Commands |
start/routes.go |
Routes, which registers the App's routes |
app/handlers |
The handlers that answer requests |
config |
The configuration, read from the environment at boot |
tests |
tests.App, which builds the App for tests, and the tests themselves |
Folder structure describes every file. For now, two matter. start/routes.go registers the home route, and the health check routes the last chapter uses:
package start
import (
"github.com/mucolabs/tinka"
"github.com/mucolabs/tinka/health"
"blog/app/handlers"
)
// Routes registers the App's routes. It runs as the App starts, after the
// providers registered their services, so it can resolve them; an error
// stops the App before it serves.
func Routes(app *tinka.App) error {
app.Get("/", handlers.Home)
// GET /health/live and GET /health/ready, for load balancers. Add a
// check for each service the App can't serve without, such as its
// database.
app.Health(health.New(health.DiskSpace("/")))
return nil
}The home route's handler returns a struct, which the App sends as JSON:
// Package handlers holds the App's handlers: the functions that answer
// requests.
package handlers
import "github.com/mucolabs/tinka"
type greeting struct {
Hello string `json:"hello"`
}
// Home answers GET / with JSON.
func Home(c *tinka.Ctx) (greeting, error) {
return greeting{Hello: "world"}, nil
}Run the App
Start the dev server from the App's directory, in a terminal you leave open:
act serve INFO Watching for changes (inotify, 8 directories)
INFO Built in 1.3s, serving http://localhost:3000
[01:07:43.106] INFO: server started addr=127.0.0.1:35265 took=694.584µsThe lines starting with INFO come from act serve, and the timestamped ones from the App's own logger. act serve listens on localhost:3000 and forwards each request to the App, which listens on a private port of its own: that's the address the App logs. In another terminal, request the home route:
curl localhost:3000/{"hello":"world"}The dev server's terminal logs the request, with its status, its duration and the request's ID:
[01:07:43.123] INFO: request method=GET path=/ status=200 took=83.306µs request_id=T2BGTXNW3JFUQLWPTFHY3S6PJWSave a change
act serve builds the App again each time you save a Go file, while the running App keeps answering. Make a mistake on purpose to see what a failed build does: remove , nil from the handler's return, and save.
// Home answers GET / with JSON.
func Home(c *tinka.Ctx) (greeting, error) {
return greeting{Hello: "world"}, nil
return greeting{Hello: "world"}
}The build fails, and the dev server prints the compiler's error:
ERROR The build failed after 149ms; the App keeps running its previous code
# blog/app/handlers
app/handlers/home.go:13:9: not enough return values
have (greeting)
want (greeting, error)curl still gets {"hello":"world"} from the App that was running before the change, so a typo never takes the App down. A page you open in the browser shows the error instead, where you're looking. Put , nil back and save again. The new build replaces the old App in a few milliseconds:
[01:08:03.974] INFO: server stopped
INFO Built in 965ms, restarted in 34ms
[01:08:04.015] INFO: server started addr=127.0.0.1:35265 took=805.55µsRequests that arrive during the restart wait for the new App instead of failing. Keep act serve running: every change in the next chapters takes effect when you save it.
Recap
You installed tinka and act, created the blog App from the skeleton starter kit, and ran it with act serve, which rebuilds and restarts it on every save and keeps the old App serving when a build fails. Next, Routes and handlers gives the App its first posts.
See also: Installation, Folder structure, Development environment setup, Commands reference