tinka alpha

URL builder

This guide covers building URLs for routes in Tinka. You will learn how to:

Overview

Links and redirects that repeat a route's path break when the path changes, and a path assembled by hand goes wrong in ways tests rarely catch: a title with a / or ? in it ends up in the wrong place. Named routes solve both. You name a route once, where you register it, and build its URL from the name everywhere else, with every value escaped for its place.

Name a route

As names the route it's called on. Names are unique, and dots group related routes by convention:

main.go
	app.Get("/posts", listPosts).As("posts.index")
	app.Get("/posts/{id}", showPost).As("posts.show")
	app.Route("/teams/{team}", func(r *tinka.Router) {
		r.Get("/members/{id}", showMember).As("teams.members.show")
	})
	app.Get("/docs/{path...}", showDoc).As("docs.show")

A route inside Route keeps its full path, so its URL includes the prefix.

Build a URL

URL takes a route's name and one value for each of its parameters, in order, and returns the path. Strings, integers and any fmt.Stringer work as values:

go
	app.URL("posts.index")                     // /posts
	app.URL("posts.show", 7)                   // /posts/7
	app.URL("teams.members.show", "go", 42)    // /teams/go/members/42

A handler that redirects after creating a post builds the new post's URL the same way:

posts.go
func (h Posts) Create(c *tinka.Ctx) (tinka.Response, error) {
	post, err := h.Service.Create(c, "Second post")
	if err != nil {
		return nil, err
	}
	return tinka.Redirect(h.App.URL("posts.show", post.ID)), nil
}

URL is a method of every *tinka.Router, so code that registers routes inside a group can build URLs too.

Add a query string

Pass a url.Values after the parameters, and it becomes the query string:

go
	app.URL("posts.index", url.Values{"page": {"2"}, "tag": {"go"}}) // /posts?page=2&tag=go

How values are escaped

Each value is escaped for its place, so it always reaches the route as the same value. A {name} parameter is one path segment, so a / in the value is escaped too. A {name...} wildcard keeps the slashes of its value and escapes each segment:

go
	app.URL("posts.show", "a/b?c")              // /posts/a%2Fb%3Fc
	app.URL("docs.show", "guides/basics/routing") // /docs/guides/basics/routing
	app.URL("docs.show", "release notes/2026")    // /docs/release%20notes/2026

URL panics when no route has the name, or when the number of values doesn't match the route's parameters. A link to a page that doesn't exist is a bug, and the panic shows where it is the first time the code runs, in tests or in development.

See also: Routing, Response