cerrado @ 1e45ae2ea3497958b2ea6a20137955cfc3bbc964

feat: Add UI/Handler login process

It adds the whole workflow to store and handle login on both UI and
handler level. With that the login information should be available at
any point given the context.
diff --git a/main.go b/main.go
index ab4aee90d096f54cc9235ea4b5e48c27a206774b..797ebea41f73cc63fed21d9fdd12a7cd2bbe4f78 100644
--- a/main.go
+++ b/main.go
@@ -74,8 +74,7 @@ 	if err != nil {
 		return err
 	}
 
-	// checking chroma configurationo
-
+	// checking chroma configuration
 	if _, ok := styles.Registry[configRepo.GetSyntaxHighlight()]; !ok {
 		slog.Warn(
 			"Invalid Syntax highlight selected",
@@ -87,8 +86,13 @@ 	}
 
 	// services
 	gitService := service.NewGitService(configRepo)
+	authService := service.NewAuthService(configRepo)
 
-	handler, err := handler.MountHandler(gitService, configRepo)
+	handler, err := handler.MountHandler(
+		gitService,
+		authService,
+		configRepo,
+	)
 	if err != nil {
 		return err
 	}
diff --git a/pkg/config/config.go b/pkg/config/config.go
index 812a06ef7ead3d270cd1b2d7d5d31a3033aabc5e..da6e0e7044745edf7ef9a5b3e720f97b2ce62df0 100644
--- a/pkg/config/config.go
+++ b/pkg/config/config.go
@@ -55,8 +55,8 @@ 	// information.
 	ConfigurationRepository struct {
 		rootReadme      string
 		listenAddr      string
-		passphrase      string
-		aesKey          string
+		passphrase      []byte
+		aesKey          []byte
 		syntaxHighlight string
 		repositories    []*GitRepositoryConfiguration
 	}
@@ -74,9 +74,9 @@ 		return nil, err
 	}
 
 	repo := &ConfigurationRepository{
-		aesKey:          config.AESKey,
+		aesKey:          []byte(config.AESKey),
 		listenAddr:      config.ListenAddr,
-		passphrase:      config.Passphrase,
+		passphrase:      []byte(config.Passphrase),
 		repositories:    config.Repositories,
 		rootReadme:      config.RootReadme,
 		syntaxHighlight: config.SyntaxHighlight,
@@ -103,6 +103,14 @@ }
 
 func (c *ConfigurationRepository) GetListenAddr() string {
 	return c.listenAddr
+}
+
+func (c *ConfigurationRepository) GetPassphrase() []byte {
+	return c.passphrase
+}
+
+func (c *ConfigurationRepository) GetBase64AesKey() []byte {
+	return c.aesKey
 }
 
 // GetByName returns configuration of repository for a given name.
diff --git a/pkg/ext/auth.go b/pkg/ext/auth.go
new file mode 100644
index 0000000000000000000000000000000000000000..bb6c0a2c07f23394ead3809aa54390326fd0fcd0
--- /dev/null
+++ b/pkg/ext/auth.go
@@ -0,0 +1,45 @@
+package ext
+
+import (
+	"context"
+	"encoding/base64"
+	"log/slog"
+	"net/http"
+)
+
+type authService interface {
+	ValidateToken(token []byte) (bool, error)
+}
+
+func Authenticate(auth authService) func(next http.HandlerFunc) http.HandlerFunc {
+	return func(next http.HandlerFunc) http.HandlerFunc {
+		return func(w http.ResponseWriter, r *http.Request) {
+			cookie, err := r.Cookie("auth")
+			if err != nil {
+				slog.Error("Error loading cookie", "error", err)
+				next(w, r)
+				return
+			}
+
+			value, err := base64.StdEncoding.DecodeString(cookie.Value)
+			if err != nil {
+				slog.Error("Error decoding", "error", err)
+				next(w, r)
+				return
+			}
+
+			valid, err := auth.ValidateToken(value)
+			if err != nil {
+				slog.Error("Error validating token", "error", err, "cookie", cookie.Value)
+				next(w, r)
+				return
+			}
+
+			ctx := r.Context()
+			ctx = context.WithValue(ctx, "logged", true)
+
+			slog.Info("Validated token", "valid?", valid)
+			next(w, r.WithContext(ctx))
+		}
+	}
+}
diff --git a/pkg/ext/router.go b/pkg/ext/router.go
index 96da1c9399992e589bbd4fefdb0bfc78b5e59b80..956254d06334a443ea3e66b37bded75847120230 100644
--- a/pkg/ext/router.go
+++ b/pkg/ext/router.go
@@ -23,6 +23,7 @@ 	return &Router{
 		router: http.NewServeMux(),
 	}
 }
+
 func (r *Router) Handler() http.Handler {
 	return r.router
 }
@@ -35,9 +36,9 @@ func wrapError(next ErrorRequestHandler) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
 		if err := next(w, r); err != nil {
 			if errors.Is(err, service.ErrRepositoryNotFound) {
-				NotFound(w)
+				NotFound(w, r)
 			} else {
-				InternalServerError(w, err)
+				InternalServerError(r, w, err)
 			}
 		}
 	}
@@ -57,16 +58,21 @@ func (r *Router) HandleFunc(path string, handler ErrorRequestHandler) {
 	r.router.HandleFunc(path, r.run(handler))
 }
 
-func NotFound(w http.ResponseWriter) {
+func NotFound(w http.ResponseWriter, r *http.Request) {
 	w.WriteHeader(http.StatusNotFound)
 	templates.WritePageTemplate(w, &templates.ErrorPage{
 		Message: "Not Found",
-	})
+	}, r.Context())
 }
 
-func InternalServerError(w http.ResponseWriter, err error) {
+func Redirect(w http.ResponseWriter, location string) {
+	w.Header().Add("location", location)
+	w.WriteHeader(http.StatusTemporaryRedirect)
+}
+
+func InternalServerError(r *http.Request, w http.ResponseWriter, err error) {
 	w.WriteHeader(http.StatusInternalServerError)
 	templates.WritePageTemplate(w, &templates.ErrorPage{
 		Message: fmt.Sprintf("Internal Server Error:\n%s", err.Error()),
-	})
+	}, r.Context())
 }
diff --git a/pkg/handler/about/handler.go b/pkg/handler/about/handler.go
index ac3d31417836e98121bd03807b2993fa2dbf27cb..ee084cd38dc3bf6124cd8e7462005446cfb0222c 100644
--- a/pkg/handler/about/handler.go
+++ b/pkg/handler/about/handler.go
@@ -26,7 +26,7 @@ func NewAboutHandler(configRepo configurationRepository) *AboutHandler {
 	return &AboutHandler{configRepo.GetRootReadme()}
 }
 
-func (g *AboutHandler) About(w http.ResponseWriter, _ *http.Request) error {
+func (g *AboutHandler) About(w http.ResponseWriter, r *http.Request) error {
 	f, err := os.Open(g.readmePath)
 	if err != nil {
 		return err
@@ -50,6 +50,6 @@
 	gitList := &templates.AboutPage{
 		Body: bs,
 	}
-	templates.WritePageTemplate(w, gitList)
+	templates.WritePageTemplate(w, gitList, r.Context())
 	return nil
 }
diff --git a/pkg/handler/auth/login.go b/pkg/handler/auth/login.go
index 7e77a67ba295d77bb0b742eb3ccefea98d9fd411..7014548c0965def2eba242a03ae269b8c27f7a00 100644
--- a/pkg/handler/auth/login.go
+++ b/pkg/handler/auth/login.go
@@ -1,20 +1,87 @@
 package auth
 
 import (
+	"encoding/base64"
 	"net/http"
+	"time"
 
 	"git.gabrielgio.me/cerrado/pkg/ext"
 	"git.gabrielgio.me/cerrado/templates"
 )
 
 type (
-	LoginHandler struct{}
+	LoginHandler struct {
+		auth authService
+	}
+
+	authService interface {
+		CheckAuth(username, password string) bool
+		IssueToken() ([]byte, error)
+	}
 )
 
+func NewLoginHandler(auth authService) *LoginHandler {
+	return &LoginHandler{
+		auth: auth,
+	}
+}
+
+func (g *LoginHandler) Logout(w http.ResponseWriter, r *http.Request) error {
+	cookie := &http.Cookie{
+		Name:    "auth",
+		Value:   "",
+		Path:    "/",
+		Expires: time.Unix(0, 0),
+	}
+
+	referer := r.Header.Get("Referer")
+	if referer == "" {
+		referer = "/"
+	}
+
+	http.SetCookie(w, cookie)
+	ext.Redirect(w, referer)
+	return nil
+}
+
 func (g *LoginHandler) Login(w http.ResponseWriter, r *http.Request) error {
-	ext.SetHTML(w)
+	if r.Method == "GET" {
+		ext.SetHTML(w)
+
+		login := &templates.LoginPage{}
+		templates.WritePageTemplate(w, login, r.Context())
+	} else if r.Method == "POST" {
+
+		username := r.FormValue("username")
+		password := r.FormValue("password")
+
+		if !g.auth.CheckAuth(username, password) {
+			login := &templates.LoginPage{
+				ErrorMessage: "Invalid login",
+			}
+			templates.WritePageTemplate(w, login, r.Context())
+		} else {
+
+			bytes, err := g.auth.IssueToken()
+			if err != nil {
+				return err
+			}
+
+			cookie := &http.Cookie{
+				Name:     "auth",
+				Value:    base64.StdEncoding.EncodeToString(bytes),
+				Path:     "/",
+				MaxAge:   3600,
+				HttpOnly: true,
+				Secure:   true,
+				SameSite: http.SameSiteStrictMode,
+			}
+
+			http.SetCookie(w, cookie)
+			ext.Redirect(w, "/")
+		}
 
-	login := &templates.LoginPage{}
-	templates.WritePageTemplate(w, login)
+	}
+
 	return nil
 }
diff --git a/pkg/handler/git/handler.go b/pkg/handler/git/handler.go
index 5739c8e9dbca0c7b015224ed3af26f53118eb72c..42761595323c97d0ea49dc3fe69d618446284bcc 100644
--- a/pkg/handler/git/handler.go
+++ b/pkg/handler/git/handler.go
@@ -43,7 +43,7 @@ 		config:     confRepo,
 	}
 }
 
-func (g *GitHandler) List(w http.ResponseWriter, _ *http.Request) error {
+func (g *GitHandler) List(w http.ResponseWriter, r *http.Request) error {
 	repos, err := g.gitService.ListRepositories()
 	if err != nil {
 		return err
@@ -73,7 +73,7 @@ 	gitList := &templates.GitListPage{
 		Respositories: repos,
 		About:         bs,
 	}
-	templates.WritePageTemplate(w, gitList)
+	templates.WritePageTemplate(w, gitList, r.Context())
 	return nil
 }
 
@@ -85,7 +85,7 @@ 	ref := strings.TrimSuffix(file, ".tar.gz")
 
 	// TODO: remove it once we can support more than gzip
 	if !strings.HasSuffix(file, ".tar.gz") {
-		ext.NotFound(w)
+		ext.NotFound(w, r)
 		return nil
 	}
 
@@ -135,7 +135,7 @@ 			Branches: branches,
 			Commits:  commits,
 		},
 	}
-	templates.WritePageTemplate(w, gitList)
+	templates.WritePageTemplate(w, gitList, r.Context())
 	return nil
 }
 
@@ -155,7 +155,7 @@ 			Ref:  ref.Name().Short(),
 			GitItemBase: &templates.GitItemAboutPage{
 				About: []byte("About file not configured properly"),
 			},
-		})
+		}, r.Context())
 		return nil
 	}
 	if err != nil {
@@ -179,7 +179,7 @@ 		GitItemBase: &templates.GitItemAboutPage{
 			About: bs,
 		},
 	}
-	templates.WritePageTemplate(w, gitList)
+	templates.WritePageTemplate(w, gitList, r.Context())
 	return nil
 }
 
@@ -210,7 +210,7 @@ 			Tags:     tags,
 			Branches: branches,
 		},
 	}
-	templates.WritePageTemplate(w, gitList)
+	templates.WritePageTemplate(w, gitList, r.Context())
 	return nil
 }
 
@@ -239,7 +239,7 @@ 			Path: paths,
 			Tree: tree,
 		},
 	}
-	templates.WritePageTemplate(w, gitList)
+	templates.WritePageTemplate(w, gitList, r.Context())
 	return nil
 }
 
@@ -270,7 +270,7 @@ 				Path:    paths,
 				Content: []byte("Binary file"),
 			},
 		}
-		templates.WritePageTemplate(w, gitList)
+		templates.WritePageTemplate(w, gitList, r.Context())
 		return nil
 	}
 
@@ -307,7 +307,7 @@ 			Path:    paths,
 			Content: code.Bytes(),
 		},
 	}
-	templates.WritePageTemplate(w, gitList)
+	templates.WritePageTemplate(w, gitList, r.Context())
 	return nil
 }
 
@@ -328,7 +328,7 @@ 		GitItemBase: &templates.GitItemLogPage{
 			Commits: commits,
 		},
 	}
-	templates.WritePageTemplate(w, gitList)
+	templates.WritePageTemplate(w, gitList, r.Context())
 	return nil
 }
 
@@ -355,7 +355,7 @@ 			Commit: commit,
 			Diff:   diff,
 		},
 	}
-	templates.WritePageTemplate(w, gitList)
+	templates.WritePageTemplate(w, gitList, r.Context())
 	return nil
 }
 
diff --git a/pkg/handler/router.go b/pkg/handler/router.go
index 32bd78adff98f82bca843aba96d2ddb85d7c79f7..ee4081b504b8291e24926062dfb9bc1765119874 100644
--- a/pkg/handler/router.go
+++ b/pkg/handler/router.go
@@ -17,12 +17,13 @@ // This functons wraps the whole handler package and wraps it into one part so
 // its sub package don't leak in other places.
 func MountHandler(
 	gitService *service.GitService,
+	authService *service.AuthService,
 	configRepo *serverconfig.ConfigurationRepository,
 ) (http.Handler, error) {
 	var (
 		gitHandler   = git.NewGitHandler(gitService, configRepo)
 		aboutHandler = about.NewAboutHandler(configRepo)
-		loginHandler = &auth.LoginHandler{}
+		loginHandler = auth.NewLoginHandler(authService)
 	)
 
 	staticHandler, err := static.ServeStaticHandler()
@@ -32,10 +33,12 @@ 	}
 
 	mux := ext.NewRouter()
 	mux.AddMiddleware(ext.Compress)
+	mux.AddMiddleware(ext.Authenticate(authService))
 	mux.AddMiddleware(ext.Log)
 
 	mux.HandleFunc("/static/{file}", staticHandler)
 	mux.HandleFunc("/login/{$}", loginHandler.Login)
+	mux.HandleFunc("/logout/{$}", loginHandler.Logout)
 	mux.HandleFunc("/{name}/about/{$}", gitHandler.About)
 	mux.HandleFunc("/{name}/", gitHandler.Summary)
 	mux.HandleFunc("/{name}/refs/{$}", gitHandler.Refs)
diff --git a/pkg/service/auth.go b/pkg/service/auth.go
index 1fbf4b61724c079a9557bc675846ba94d1ad370e..0dbd960ff2a49368f531da1b5ceb58719c8537fe 100644
--- a/pkg/service/auth.go
+++ b/pkg/service/auth.go
@@ -23,7 +23,13 @@ 		GetBase64AesKey() []byte
 	}
 )
 
-var tokenSeed = []byte("cerrado")
+var tokenSeed = []byte("this is a token for cerrado")
+
+func NewAuthService(repostiory authRepository) *AuthService {
+	return &AuthService{
+		authRepository: repostiory,
+	}
+}
 
 func (a *AuthService) CheckAuth(username, password string) bool {
 	passphrase := a.authRepository.GetPassphrase()
diff --git a/pkg/service/git.go b/pkg/service/git.go
index f03ba426f3933a7bf8f1a9f1ff15e6b88613954a..6c3912fae3c57a3500849ef2e15d2616b838f144 100644
--- a/pkg/service/git.go
+++ b/pkg/service/git.go
@@ -30,9 +30,7 @@ 		GetByName(name string) *config.GitRepositoryConfiguration
 	}
 )
 
-var (
-	ErrRepositoryNotFound = errors.New("Repository not found")
-)
+var ErrRepositoryNotFound = errors.New("Repository not found")
 
 // TODO: make it configurable
 const timeFormat = "2006.01.02 15:04:05"
diff --git a/templates/about.qtpl b/templates/about.qtpl
index faee50e18821c54e739efd5611c0b548cf94cc15..cfbf0d9001e0dea884eb1096834169bc2d620496 100644
--- a/templates/about.qtpl
+++ b/templates/about.qtpl
@@ -1,16 +1,19 @@
+{% import "context" %}
+
 {% code
 type AboutPage struct {
+    LoggedIn bool
     Body []byte
 }
 %}
 
-{% func (p *AboutPage) Title() %}Hello{% endfunc %}
+{% func (p *AboutPage) Title(ctx context.Context) %}Hello{% endfunc %}
 
-{% func (p *AboutPage) Navbar() %}{%= Navbar(About) %}{% endfunc %}
+{% func (p *AboutPage) Navbar(ctx context.Context) %}{%= Navbar(ctx, About) %}{% endfunc %}
 
-{% func (p *AboutPage) Content() %}
+{% func (p *AboutPage) Content(ctx context.Context) %}
 {%z= p.Body %}
 {% endfunc %}
 
-{% func (p *AboutPage) Script() %}
+{% func (p *AboutPage) Script(ctx context.Context) %}
 {% endfunc %}
diff --git a/templates/about.qtpl.go b/templates/about.qtpl.go
index 2c07ceb1818619df56672b4bea08b8b1af0bcb62..a640f7eddc849adab11651d44c5644ad367240d4 100644
--- a/templates/about.qtpl.go
+++ b/templates/about.qtpl.go
@@ -5,130 +5,100 @@ //line templates/about.qtpl:1
 package templates
 
 //line templates/about.qtpl:1
+import "context"
+
+//line templates/about.qtpl:3
 import (
 	qtio422016 "io"
 
 	qt422016 "github.com/valyala/quicktemplate"
 )
 
-//line templates/about.qtpl:1
+//line templates/about.qtpl:3
 var (
 	_ = qtio422016.Copy
 	_ = qt422016.AcquireByteBuffer
 )
 
-//line templates/about.qtpl:2
+//line templates/about.qtpl:4
 type AboutPage struct {
-	Body []byte
+	LoggedIn bool
+	Body     []byte
 }
 
-//line templates/about.qtpl:7
-func (p *AboutPage) StreamTitle(qw422016 *qt422016.Writer) {
-//line templates/about.qtpl:7
+//line templates/about.qtpl:10
+func (p *AboutPage) StreamTitle(qw422016 *qt422016.Writer, ctx context.Context) {
+//line templates/about.qtpl:10
 	qw422016.N().S(`Hello`)
-//line templates/about.qtpl:7
-}
-
-//line templates/about.qtpl:7
-func (p *AboutPage) WriteTitle(qq422016 qtio422016.Writer) {
-//line templates/about.qtpl:7
-	qw422016 := qt422016.AcquireWriter(qq422016)
-//line templates/about.qtpl:7
-	p.StreamTitle(qw422016)
-//line templates/about.qtpl:7
-	qt422016.ReleaseWriter(qw422016)
-//line templates/about.qtpl:7
-}
-
-//line templates/about.qtpl:7
-func (p *AboutPage) Title() string {
-//line templates/about.qtpl:7
-	qb422016 := qt422016.AcquireByteBuffer()
-//line templates/about.qtpl:7
-	p.WriteTitle(qb422016)
-//line templates/about.qtpl:7
-	qs422016 := string(qb422016.B)
-//line templates/about.qtpl:7
-	qt422016.ReleaseByteBuffer(qb422016)
-//line templates/about.qtpl:7
-	return qs422016
-//line templates/about.qtpl:7
-}
-
-//line templates/about.qtpl:9
-func (p *AboutPage) StreamNavbar(qw422016 *qt422016.Writer) {
-//line templates/about.qtpl:9
-	StreamNavbar(qw422016, About)
-//line templates/about.qtpl:9
+//line templates/about.qtpl:10
 }
 
-//line templates/about.qtpl:9
-func (p *AboutPage) WriteNavbar(qq422016 qtio422016.Writer) {
-//line templates/about.qtpl:9
+//line templates/about.qtpl:10
+func (p *AboutPage) WriteTitle(qq422016 qtio422016.Writer, ctx context.Context) {
+//line templates/about.qtpl:10
 	qw422016 := qt422016.AcquireWriter(qq422016)
-//line templates/about.qtpl:9
-	p.StreamNavbar(qw422016)
-//line templates/about.qtpl:9
+//line templates/about.qtpl:10
+	p.StreamTitle(qw422016, ctx)
+//line templates/about.qtpl:10
 	qt422016.ReleaseWriter(qw422016)
-//line templates/about.qtpl:9
+//line templates/about.qtpl:10
 }
 
-//line templates/about.qtpl:9
-func (p *AboutPage) Navbar() string {
-//line templates/about.qtpl:9
+//line templates/about.qtpl:10
+func (p *AboutPage) Title(ctx context.Context) string {
+//line templates/about.qtpl:10
 	qb422016 := qt422016.AcquireByteBuffer()
-//line templates/about.qtpl:9
-	p.WriteNavbar(qb422016)
-//line templates/about.qtpl:9
+//line templates/about.qtpl:10
+	p.WriteTitle(qb422016, ctx)
+//line templates/about.qtpl:10
 	qs422016 := string(qb422016.B)
-//line templates/about.qtpl:9
+//line templates/about.qtpl:10
 	qt422016.ReleaseByteBuffer(qb422016)
-//line templates/about.qtpl:9
+//line templates/about.qtpl:10
 	return qs422016
-//line templates/about.qtpl:9
+//line templates/about.qtpl:10
 }
 
-//line templates/about.qtpl:11
-func (p *AboutPage) StreamContent(qw422016 *qt422016.Writer) {
-//line templates/about.qtpl:11
-	qw422016.N().S(`
-`)
 //line templates/about.qtpl:12
-	qw422016.N().Z(p.Body)
+func (p *AboutPage) StreamNavbar(qw422016 *qt422016.Writer, ctx context.Context) {
 //line templates/about.qtpl:12
-	qw422016.N().S(`
-`)
-//line templates/about.qtpl:13
+	StreamNavbar(qw422016, ctx, About)
+//line templates/about.qtpl:12
 }
 
-//line templates/about.qtpl:13
-func (p *AboutPage) WriteContent(qq422016 qtio422016.Writer) {
-//line templates/about.qtpl:13
+//line templates/about.qtpl:12
+func (p *AboutPage) WriteNavbar(qq422016 qtio422016.Writer, ctx context.Context) {
+//line templates/about.qtpl:12
 	qw422016 := qt422016.AcquireWriter(qq422016)
-//line templates/about.qtpl:13
-	p.StreamContent(qw422016)
-//line templates/about.qtpl:13
+//line templates/about.qtpl:12
+	p.StreamNavbar(qw422016, ctx)
+//line templates/about.qtpl:12
 	qt422016.ReleaseWriter(qw422016)
-//line templates/about.qtpl:13
+//line templates/about.qtpl:12
 }
 
-//line templates/about.qtpl:13
-func (p *AboutPage) Content() string {
-//line templates/about.qtpl:13
+//line templates/about.qtpl:12
+func (p *AboutPage) Navbar(ctx context.Context) string {
+//line templates/about.qtpl:12
 	qb422016 := qt422016.AcquireByteBuffer()
-//line templates/about.qtpl:13
-	p.WriteContent(qb422016)
-//line templates/about.qtpl:13
+//line templates/about.qtpl:12
+	p.WriteNavbar(qb422016, ctx)
+//line templates/about.qtpl:12
 	qs422016 := string(qb422016.B)
-//line templates/about.qtpl:13
+//line templates/about.qtpl:12
 	qt422016.ReleaseByteBuffer(qb422016)
-//line templates/about.qtpl:13
+//line templates/about.qtpl:12
 	return qs422016
-//line templates/about.qtpl:13
+//line templates/about.qtpl:12
 }
 
+//line templates/about.qtpl:14
+func (p *AboutPage) StreamContent(qw422016 *qt422016.Writer, ctx context.Context) {
+//line templates/about.qtpl:14
+	qw422016.N().S(`
+`)
 //line templates/about.qtpl:15
-func (p *AboutPage) StreamScript(qw422016 *qt422016.Writer) {
+	qw422016.N().Z(p.Body)
 //line templates/about.qtpl:15
 	qw422016.N().S(`
 `)
@@ -136,22 +106,22 @@ //line templates/about.qtpl:16
 }
 
 //line templates/about.qtpl:16
-func (p *AboutPage) WriteScript(qq422016 qtio422016.Writer) {
+func (p *AboutPage) WriteContent(qq422016 qtio422016.Writer, ctx context.Context) {
 //line templates/about.qtpl:16
 	qw422016 := qt422016.AcquireWriter(qq422016)
 //line templates/about.qtpl:16
-	p.StreamScript(qw422016)
+	p.StreamContent(qw422016, ctx)
 //line templates/about.qtpl:16
 	qt422016.ReleaseWriter(qw422016)
 //line templates/about.qtpl:16
 }
 
 //line templates/about.qtpl:16
-func (p *AboutPage) Script() string {
+func (p *AboutPage) Content(ctx context.Context) string {
 //line templates/about.qtpl:16
 	qb422016 := qt422016.AcquireByteBuffer()
 //line templates/about.qtpl:16
-	p.WriteScript(qb422016)
+	p.WriteContent(qb422016, ctx)
 //line templates/about.qtpl:16
 	qs422016 := string(qb422016.B)
 //line templates/about.qtpl:16
@@ -160,3 +130,37 @@ //line templates/about.qtpl:16
 	return qs422016
 //line templates/about.qtpl:16
 }
+
+//line templates/about.qtpl:18
+func (p *AboutPage) StreamScript(qw422016 *qt422016.Writer, ctx context.Context) {
+//line templates/about.qtpl:18
+	qw422016.N().S(`
+`)
+//line templates/about.qtpl:19
+}
+
+//line templates/about.qtpl:19
+func (p *AboutPage) WriteScript(qq422016 qtio422016.Writer, ctx context.Context) {
+//line templates/about.qtpl:19
+	qw422016 := qt422016.AcquireWriter(qq422016)
+//line templates/about.qtpl:19
+	p.StreamScript(qw422016, ctx)
+//line templates/about.qtpl:19
+	qt422016.ReleaseWriter(qw422016)
+//line templates/about.qtpl:19
+}
+
+//line templates/about.qtpl:19
+func (p *AboutPage) Script(ctx context.Context) string {
+//line templates/about.qtpl:19
+	qb422016 := qt422016.AcquireByteBuffer()
+//line templates/about.qtpl:19
+	p.WriteScript(qb422016, ctx)
+//line templates/about.qtpl:19
+	qs422016 := string(qb422016.B)
+//line templates/about.qtpl:19
+	qt422016.ReleaseByteBuffer(qb422016)
+//line templates/about.qtpl:19
+	return qs422016
+//line templates/about.qtpl:19
+}
diff --git a/templates/base.qtpl b/templates/base.qtpl
index 566308f9c13c670c3106c8ba2c51230e533e00d8..2a42cb889be45ffeb308c0aae56cd37666f9e2f8 100644
--- a/templates/base.qtpl
+++ b/templates/base.qtpl
@@ -1,5 +1,6 @@
 This is a base page template. All the other template pages implement this interface.
 
+{% import "context" %}
 {% import "strconv" %}
 {% import "time" %}
 
@@ -9,10 +10,10 @@ %}
 
 {% interface
 Page {
-	Title()
-	Content()
-    Script()
-    Navbar()
+	Title(ctx context.Context)
+	Content(ctx context.Context)
+    Script(ctx context.Context)
+    Navbar(ctx context.Context)
 }
 %}
 
@@ -24,6 +25,8 @@         }
         return ""
     }
 %}
+
+
 
 {% code func TimeFormat(t time.Time) string {
         return t.Format("02.01.2006")
@@ -35,24 +38,30 @@         return v
     }
 %}
 
+{% code func IsLoggedIn(ctx context.Context) bool {
+	t, ok := ctx.Value("logged").(bool)
+	return ok && t
+    }
+%}
+
 Page prints a page implementing Page interface.
-{% func PageTemplate(p Page) %}
+{% func PageTemplate(p Page, ctx context.Context) %}
 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="utf-8">
     <link rel="icon" href="data:,">
-    <title>{%= p.Title() %}</title> 
+    <title>{%= p.Title(ctx) %}</title> 
     <link rel="stylesheet" href="/static/main{%s Slug %}.css">
     <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
     <meta name="viewport" content="width=device-width, initial-scale=1" />
   </head>
   <body>
-    {%= p.Navbar() %}
+    {%= p.Navbar(ctx) %}
     <div class="container">
-      {%= p.Content() %}
+      {%= p.Content(ctx) %}
     </div>
   </body>
-  {%= p.Script() %}
+  {%= p.Script(ctx) %}
 </html>
 {% endfunc %}
diff --git a/templates/base.qtpl.go b/templates/base.qtpl.go
index f8ff91f23386053a256a62cf482aaaaa4f68d5f7..5bb45323a0d55b6106c12d8370671c6e3e909553 100644
--- a/templates/base.qtpl.go
+++ b/templates/base.qtpl.go
@@ -8,57 +8,60 @@ //line templates/base.qtpl:3
 package templates
 
 //line templates/base.qtpl:3
+import "context"
+
+//line templates/base.qtpl:4
 import "strconv"
 
-//line templates/base.qtpl:4
+//line templates/base.qtpl:5
 import "time"
 
-//line templates/base.qtpl:6
+//line templates/base.qtpl:7
 import (
 	qtio422016 "io"
 
 	qt422016 "github.com/valyala/quicktemplate"
 )
 
-//line templates/base.qtpl:6
+//line templates/base.qtpl:7
 var (
 	_ = qtio422016.Copy
 	_ = qt422016.AcquireByteBuffer
 )
 
-//line templates/base.qtpl:7
+//line templates/base.qtpl:8
 var Slug = ""
 
-//line templates/base.qtpl:11
+//line templates/base.qtpl:12
 type Page interface {
-//line templates/base.qtpl:11
-	Title() string
-//line templates/base.qtpl:11
-	StreamTitle(qw422016 *qt422016.Writer)
-//line templates/base.qtpl:11
-	WriteTitle(qq422016 qtio422016.Writer)
-//line templates/base.qtpl:11
-	Content() string
-//line templates/base.qtpl:11
-	StreamContent(qw422016 *qt422016.Writer)
-//line templates/base.qtpl:11
-	WriteContent(qq422016 qtio422016.Writer)
-//line templates/base.qtpl:11
-	Script() string
-//line templates/base.qtpl:11
-	StreamScript(qw422016 *qt422016.Writer)
-//line templates/base.qtpl:11
-	WriteScript(qq422016 qtio422016.Writer)
-//line templates/base.qtpl:11
-	Navbar() string
-//line templates/base.qtpl:11
-	StreamNavbar(qw422016 *qt422016.Writer)
-//line templates/base.qtpl:11
-	WriteNavbar(qq422016 qtio422016.Writer)
-//line templates/base.qtpl:11
+//line templates/base.qtpl:12
+	Title(ctx context.Context) string
+//line templates/base.qtpl:12
+	StreamTitle(qw422016 *qt422016.Writer, ctx context.Context)
+//line templates/base.qtpl:12
+	WriteTitle(qq422016 qtio422016.Writer, ctx context.Context)
+//line templates/base.qtpl:12
+	Content(ctx context.Context) string
+//line templates/base.qtpl:12
+	StreamContent(qw422016 *qt422016.Writer, ctx context.Context)
+//line templates/base.qtpl:12
+	WriteContent(qq422016 qtio422016.Writer, ctx context.Context)
+//line templates/base.qtpl:12
+	Script(ctx context.Context) string
+//line templates/base.qtpl:12
+	StreamScript(qw422016 *qt422016.Writer, ctx context.Context)
+//line templates/base.qtpl:12
+	WriteScript(qq422016 qtio422016.Writer, ctx context.Context)
+//line templates/base.qtpl:12
+	Navbar(ctx context.Context) string
+//line templates/base.qtpl:12
+	StreamNavbar(qw422016 *qt422016.Writer, ctx context.Context)
+//line templates/base.qtpl:12
+	WriteNavbar(qq422016 qtio422016.Writer, ctx context.Context)
+//line templates/base.qtpl:12
 }
 
-//line templates/base.qtpl:20
+//line templates/base.qtpl:21
 func FromUInttoString(u *uint) string {
 	if u != nil {
 		return strconv.FormatUint(uint64(*u), 10)
@@ -66,21 +69,27 @@ 	}
 	return ""
 }
 
-//line templates/base.qtpl:28
+//line templates/base.qtpl:31
 func TimeFormat(t time.Time) string {
 	return t.Format("02.01.2006")
 }
 
-//line templates/base.qtpl:33
+//line templates/base.qtpl:36
 func Ignore[T any](v T, _ error) T {
 	return v
 }
 
+//line templates/base.qtpl:41
+func IsLoggedIn(ctx context.Context) bool {
+	t, ok := ctx.Value("logged").(bool)
+	return ok && t
+}
+
 // Page prints a page implementing Page interface.
 
-//line templates/base.qtpl:39
-func StreamPageTemplate(qw422016 *qt422016.Writer, p Page) {
-//line templates/base.qtpl:39
+//line templates/base.qtpl:48
+func StreamPageTemplate(qw422016 *qt422016.Writer, p Page, ctx context.Context) {
+//line templates/base.qtpl:48
 	qw422016.N().S(`
 <!DOCTYPE html>
 <html lang="en">
@@ -88,64 +97,64 @@   <head>
     <meta charset="utf-8">
     <link rel="icon" href="data:,">
     <title>`)
-//line templates/base.qtpl:45
-	p.StreamTitle(qw422016)
-//line templates/base.qtpl:45
+//line templates/base.qtpl:54
+	p.StreamTitle(qw422016, ctx)
+//line templates/base.qtpl:54
 	qw422016.N().S(`</title> 
     <link rel="stylesheet" href="/static/main`)
-//line templates/base.qtpl:46
+//line templates/base.qtpl:55
 	qw422016.E().S(Slug)
-//line templates/base.qtpl:46
+//line templates/base.qtpl:55
 	qw422016.N().S(`.css">
     <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
     <meta name="viewport" content="width=device-width, initial-scale=1" />
   </head>
   <body>
     `)
-//line templates/base.qtpl:51
-	p.StreamNavbar(qw422016)
-//line templates/base.qtpl:51
+//line templates/base.qtpl:60
+	p.StreamNavbar(qw422016, ctx)
+//line templates/base.qtpl:60
 	qw422016.N().S(`
     <div class="container">
       `)
-//line templates/base.qtpl:53
-	p.StreamContent(qw422016)
-//line templates/base.qtpl:53
+//line templates/base.qtpl:62
+	p.StreamContent(qw422016, ctx)
+//line templates/base.qtpl:62
 	qw422016.N().S(`
     </div>
   </body>
   `)
-//line templates/base.qtpl:56
-	p.StreamScript(qw422016)
-//line templates/base.qtpl:56
+//line templates/base.qtpl:65
+	p.StreamScript(qw422016, ctx)
+//line templates/base.qtpl:65
 	qw422016.N().S(`
 </html>
 `)
-//line templates/base.qtpl:58
+//line templates/base.qtpl:67
 }
 
-//line templates/base.qtpl:58
-func WritePageTemplate(qq422016 qtio422016.Writer, p Page) {
-//line templates/base.qtpl:58
+//line templates/base.qtpl:67
+func WritePageTemplate(qq422016 qtio422016.Writer, p Page, ctx context.Context) {
+//line templates/base.qtpl:67
 	qw422016 := qt422016.AcquireWriter(qq422016)
-//line templates/base.qtpl:58
-	StreamPageTemplate(qw422016, p)
-//line templates/base.qtpl:58
+//line templates/base.qtpl:67
+	StreamPageTemplate(qw422016, p, ctx)
+//line templates/base.qtpl:67
 	qt422016.ReleaseWriter(qw422016)
-//line templates/base.qtpl:58
+//line templates/base.qtpl:67
 }
 
-//line templates/base.qtpl:58
-func PageTemplate(p Page) string {
-//line templates/base.qtpl:58
+//line templates/base.qtpl:67
+func PageTemplate(p Page, ctx context.Context) string {
+//line templates/base.qtpl:67
 	qb422016 := qt422016.AcquireByteBuffer()
-//line templates/base.qtpl:58
-	WritePageTemplate(qb422016, p)
-//line templates/base.qtpl:58
+//line templates/base.qtpl:67
+	WritePageTemplate(qb422016, p, ctx)
+//line templates/base.qtpl:67
 	qs422016 := string(qb422016.B)
-//line templates/base.qtpl:58
+//line templates/base.qtpl:67
 	qt422016.ReleaseByteBuffer(qb422016)
-//line templates/base.qtpl:58
+//line templates/base.qtpl:67
 	return qs422016
-//line templates/base.qtpl:58
+//line templates/base.qtpl:67
 }
diff --git a/templates/error.qtpl b/templates/error.qtpl
index 771d5333f95ee509b2e1680de168003bf24b2b32..65e1321d87ff4dbe30790880e238fc7f5ce5dd14 100644
--- a/templates/error.qtpl
+++ b/templates/error.qtpl
@@ -1,16 +1,18 @@
+{% import "context" %}
+
 {% code
 type ErrorPage struct {
     Message string
 }
 %}
 
-{% func (p *ErrorPage) Title() %}Error{% endfunc %}
+{% func (p *ErrorPage) Title(ctx context.Context) %}Error{% endfunc %}
 
-{% func (p *ErrorPage) Navbar() %}{%= Navbar(Git) %}{% endfunc %}
+{% func (p *ErrorPage) Navbar(ctx context.Context) %}{%= Navbar(ctx, Git) %}{% endfunc %}
 
-{% func (p *ErrorPage) Content() %}
+{% func (p *ErrorPage) Content(ctx context.Context) %}
 {%s p.Message %}
 {% endfunc %}
 
-{% func (p *ErrorPage) Script() %}
+{% func (p *ErrorPage) Script(ctx context.Context) %}
 {% endfunc %}
diff --git a/templates/error.qtpl.go b/templates/error.qtpl.go
index f415968c0d258de095a65790f09956cbf2976396..d4732c525cc879e2ac39ad7b46b481fa35edd748 100644
--- a/templates/error.qtpl.go
+++ b/templates/error.qtpl.go
@@ -5,80 +5,50 @@ //line templates/error.qtpl:1
 package templates
 
 //line templates/error.qtpl:1
+import "context"
+
+//line templates/error.qtpl:3
 import (
 	qtio422016 "io"
 
 	qt422016 "github.com/valyala/quicktemplate"
 )
 
-//line templates/error.qtpl:1
+//line templates/error.qtpl:3
 var (
 	_ = qtio422016.Copy
 	_ = qt422016.AcquireByteBuffer
 )
 
-//line templates/error.qtpl:2
+//line templates/error.qtpl:4
 type ErrorPage struct {
 	Message string
 }
 
-//line templates/error.qtpl:7
-func (p *ErrorPage) StreamTitle(qw422016 *qt422016.Writer) {
-//line templates/error.qtpl:7
-	qw422016.N().S(`Error`)
-//line templates/error.qtpl:7
-}
-
-//line templates/error.qtpl:7
-func (p *ErrorPage) WriteTitle(qq422016 qtio422016.Writer) {
-//line templates/error.qtpl:7
-	qw422016 := qt422016.AcquireWriter(qq422016)
-//line templates/error.qtpl:7
-	p.StreamTitle(qw422016)
-//line templates/error.qtpl:7
-	qt422016.ReleaseWriter(qw422016)
-//line templates/error.qtpl:7
-}
-
-//line templates/error.qtpl:7
-func (p *ErrorPage) Title() string {
-//line templates/error.qtpl:7
-	qb422016 := qt422016.AcquireByteBuffer()
-//line templates/error.qtpl:7
-	p.WriteTitle(qb422016)
-//line templates/error.qtpl:7
-	qs422016 := string(qb422016.B)
-//line templates/error.qtpl:7
-	qt422016.ReleaseByteBuffer(qb422016)
-//line templates/error.qtpl:7
-	return qs422016
-//line templates/error.qtpl:7
-}
-
 //line templates/error.qtpl:9
-func (p *ErrorPage) StreamNavbar(qw422016 *qt422016.Writer) {
+func (p *ErrorPage) StreamTitle(qw422016 *qt422016.Writer, ctx context.Context) {
 //line templates/error.qtpl:9
-	StreamNavbar(qw422016, Git)
+	qw422016.N().S(`Error`)
 //line templates/error.qtpl:9
 }
 
 //line templates/error.qtpl:9
-func (p *ErrorPage) WriteNavbar(qq422016 qtio422016.Writer) {
+func (p *ErrorPage) WriteTitle(qq422016 qtio422016.Writer, ctx context.Context) {
 //line templates/error.qtpl:9
 	qw422016 := qt422016.AcquireWriter(qq422016)
 //line templates/error.qtpl:9
-	p.StreamNavbar(qw422016)
+	p.StreamTitle(qw422016, ctx)
 //line templates/error.qtpl:9
 	qt422016.ReleaseWriter(qw422016)
 //line templates/error.qtpl:9
 }
 
 //line templates/error.qtpl:9
-func (p *ErrorPage) Navbar() string {
+func (p *ErrorPage) Title(ctx context.Context) string {
 //line templates/error.qtpl:9
 	qb422016 := qt422016.AcquireByteBuffer()
 //line templates/error.qtpl:9
-	p.WriteNavbar(qb422016)
+	p.WriteTitle(qb422016, ctx)
 //line templates/error.qtpl:9
 	qs422016 := string(qb422016.B)
 //line templates/error.qtpl:9
@@ -89,74 +59,107 @@ //line templates/error.qtpl:9
 }
 
 //line templates/error.qtpl:11
-func (p *ErrorPage) StreamContent(qw422016 *qt422016.Writer) {
+func (p *ErrorPage) StreamNavbar(qw422016 *qt422016.Writer, ctx context.Context) {
+//line templates/error.qtpl:11
+	StreamNavbar(qw422016, ctx, Git)
+//line templates/error.qtpl:11
+}
+
+//line templates/error.qtpl:11
+func (p *ErrorPage) WriteNavbar(qq422016 qtio422016.Writer, ctx context.Context) {
+//line templates/error.qtpl:11
+	qw422016 := qt422016.AcquireWriter(qq422016)
+//line templates/error.qtpl:11
+	p.StreamNavbar(qw422016, ctx)
+//line templates/error.qtpl:11
+	qt422016.ReleaseWriter(qw422016)
 //line templates/error.qtpl:11
+}
+
+//line templates/error.qtpl:11
+func (p *ErrorPage) Navbar(ctx context.Context) string {
+//line templates/error.qtpl:11
+	qb422016 := qt422016.AcquireByteBuffer()
+//line templates/error.qtpl:11
+	p.WriteNavbar(qb422016, ctx)
+//line templates/error.qtpl:11
+	qs422016 := string(qb422016.B)
+//line templates/error.qtpl:11
+	qt422016.ReleaseByteBuffer(qb422016)
+//line templates/error.qtpl:11
+	return qs422016
+//line templates/error.qtpl:11
+}
+
+//line templates/error.qtpl:13
+func (p *ErrorPage) StreamContent(qw422016 *qt422016.Writer, ctx context.Context) {
+//line templates/error.qtpl:13
 	qw422016.N().S(`
 `)
-//line templates/error.qtpl:12
+//line templates/error.qtpl:14
 	qw422016.E().S(p.Message)
-//line templates/error.qtpl:12
+//line templates/error.qtpl:14
 	qw422016.N().S(`
 `)
-//line templates/error.qtpl:13
+//line templates/error.qtpl:15
 }
 
-//line templates/error.qtpl:13
-func (p *ErrorPage) WriteContent(qq422016 qtio422016.Writer) {
-//line templates/error.qtpl:13
+//line templates/error.qtpl:15
+func (p *ErrorPage) WriteContent(qq422016 qtio422016.Writer, ctx context.Context) {
+//line templates/error.qtpl:15
 	qw422016 := qt422016.AcquireWriter(qq422016)
-//line templates/error.qtpl:13
-	p.StreamContent(qw422016)
-//line templates/error.qtpl:13
+//line templates/error.qtpl:15
+	p.StreamContent(qw422016, ctx)
+//line templates/error.qtpl:15
 	qt422016.ReleaseWriter(qw422016)
-//line templates/error.qtpl:13
+//line templates/error.qtpl:15
 }
 
-//line templates/error.qtpl:13
-func (p *ErrorPage) Content() string {
-//line templates/error.qtpl:13
+//line templates/error.qtpl:15
+func (p *ErrorPage) Content(ctx context.Context) string {
+//line templates/error.qtpl:15
 	qb422016 := qt422016.AcquireByteBuffer()
-//line templates/error.qtpl:13
-	p.WriteContent(qb422016)
-//line templates/error.qtpl:13
+//line templates/error.qtpl:15
+	p.WriteContent(qb422016, ctx)
+//line templates/error.qtpl:15
 	qs422016 := string(qb422016.B)
-//line templates/error.qtpl:13
+//line templates/error.qtpl:15
 	qt422016.ReleaseByteBuffer(qb422016)
-//line templates/error.qtpl:13
+//line templates/error.qtpl:15
 	return qs422016
-//line templates/error.qtpl:13
+//line templates/error.qtpl:15
 }
 
-//line templates/error.qtpl:15
-func (p *ErrorPage) StreamScript(qw422016 *qt422016.Writer) {
-//line templates/error.qtpl:15
+//line templates/error.qtpl:17
+func (p *ErrorPage) StreamScript(qw422016 *qt422016.Writer, ctx context.Context) {
+//line templates/error.qtpl:17
 	qw422016.N().S(`
 `)
-//line templates/error.qtpl:16
+//line templates/error.qtpl:18
 }
 
-//line templates/error.qtpl:16
-func (p *ErrorPage) WriteScript(qq422016 qtio422016.Writer) {
-//line templates/error.qtpl:16
+//line templates/error.qtpl:18
+func (p *ErrorPage) WriteScript(qq422016 qtio422016.Writer, ctx context.Context) {
+//line templates/error.qtpl:18
 	qw422016 := qt422016.AcquireWriter(qq422016)
-//line templates/error.qtpl:16
-	p.StreamScript(qw422016)
-//line templates/error.qtpl:16
+//line templates/error.qtpl:18
+	p.StreamScript(qw422016, ctx)
+//line templates/error.qtpl:18
 	qt422016.ReleaseWriter(qw422016)
-//line templates/error.qtpl:16
+//line templates/error.qtpl:18
 }
 
-//line templates/error.qtpl:16
-func (p *ErrorPage) Script() string {
-//line templates/error.qtpl:16
+//line templates/error.qtpl:18
+func (p *ErrorPage) Script(ctx context.Context) string {
+//line templates/error.qtpl:18
 	qb422016 := qt422016.AcquireByteBuffer()
-//line templates/error.qtpl:16
-	p.WriteScript(qb422016)
-//line templates/error.qtpl:16
+//line templates/error.qtpl:18
+	p.WriteScript(qb422016, ctx)
+//line templates/error.qtpl:18
 	qs422016 := string(qb422016.B)
-//line templates/error.qtpl:16
+//line templates/error.qtpl:18
 	qt422016.ReleaseByteBuffer(qb422016)
-//line templates/error.qtpl:16
+//line templates/error.qtpl:18
 	return qs422016
-//line templates/error.qtpl:16
+//line templates/error.qtpl:18
 }
diff --git a/templates/gititem.qtpl b/templates/gititem.qtpl
index a6a312d333e2e4942004073ed33494454f1eeeea..c43bbfdf906e81797b9bbbc00e8dab843f960be0 100644
--- a/templates/gititem.qtpl
+++ b/templates/gititem.qtpl
@@ -1,3 +1,5 @@
+{% import "context" %}
+
 {% interface 
 GitItemBase {
    Nav(name, ref string)
@@ -13,16 +15,16 @@     GitItemBase
 }
 %}
 
-{% func (p *GitItemPage) Title() %}Git | {%s p.Name %}{% endfunc %}
+{% func (p *GitItemPage) Title(ctx context.Context) %}Git | {%s p.Name %}{% endfunc %}
 
-{% func (p *GitItemPage) Navbar() %}{%= Navbar(Git) %}{% endfunc %}
+{% func (p *GitItemPage) Navbar(ctx context.Context) %}{%= Navbar(ctx, Git) %}{% endfunc %}
 
-{% func (p *GitItemPage) Content() %}
+{% func (p *GitItemPage) Content(ctx context.Context) %}
 {%= p.Nav(p.Name, p.Ref) %}
 <div class="container">
 {%= p.GitContent(p.Name, p.Ref) %}
 </div>
 {% endfunc %}
 
-{% func (p *GitItemPage) Script() %}
+{% func (p *GitItemPage) Script(ctx context.Context) %}
 {% endfunc %}
diff --git a/templates/gititem.qtpl.go b/templates/gititem.qtpl.go
index c9a00b29d0fd28cd514db8e97d63f5dcff9b172b..5292e44812ac71d251a8678380da7c80b40e48e8 100644
--- a/templates/gititem.qtpl.go
+++ b/templates/gititem.qtpl.go
@@ -5,101 +5,71 @@ //line templates/gititem.qtpl:1
 package templates
 
 //line templates/gititem.qtpl:1
+import "context"
+
+//line templates/gititem.qtpl:3
 import (
 	qtio422016 "io"
 
 	qt422016 "github.com/valyala/quicktemplate"
 )
 
-//line templates/gititem.qtpl:1
+//line templates/gititem.qtpl:3
 var (
 	_ = qtio422016.Copy
 	_ = qt422016.AcquireByteBuffer
 )
 
-//line templates/gititem.qtpl:2
+//line templates/gititem.qtpl:4
 type GitItemBase interface {
-//line templates/gititem.qtpl:2
+//line templates/gititem.qtpl:4
 	Nav(name, ref string) string
-//line templates/gititem.qtpl:2
+//line templates/gititem.qtpl:4
 	StreamNav(qw422016 *qt422016.Writer, name, ref string)
-//line templates/gititem.qtpl:2
+//line templates/gititem.qtpl:4
 	WriteNav(qq422016 qtio422016.Writer, name, ref string)
-//line templates/gititem.qtpl:2
+//line templates/gititem.qtpl:4
 	GitContent(name, ref string) string
-//line templates/gititem.qtpl:2
+//line templates/gititem.qtpl:4
 	StreamGitContent(qw422016 *qt422016.Writer, name, ref string)
-//line templates/gititem.qtpl:2
+//line templates/gititem.qtpl:4
 	WriteGitContent(qq422016 qtio422016.Writer, name, ref string)
-//line templates/gititem.qtpl:2
+//line templates/gititem.qtpl:4
 }
 
-//line templates/gititem.qtpl:9
+//line templates/gititem.qtpl:11
 type GitItemPage struct {
 	Name string
 	Ref  string
 	GitItemBase
 }
 
-//line templates/gititem.qtpl:16
-func (p *GitItemPage) StreamTitle(qw422016 *qt422016.Writer) {
-//line templates/gititem.qtpl:16
+//line templates/gititem.qtpl:18
+func (p *GitItemPage) StreamTitle(qw422016 *qt422016.Writer, ctx context.Context) {
+//line templates/gititem.qtpl:18
 	qw422016.N().S(`Git | `)
-//line templates/gititem.qtpl:16
+//line templates/gititem.qtpl:18
 	qw422016.E().S(p.Name)
-//line templates/gititem.qtpl:16
-}
-
-//line templates/gititem.qtpl:16
-func (p *GitItemPage) WriteTitle(qq422016 qtio422016.Writer) {
-//line templates/gititem.qtpl:16
-	qw422016 := qt422016.AcquireWriter(qq422016)
-//line templates/gititem.qtpl:16
-	p.StreamTitle(qw422016)
-//line templates/gititem.qtpl:16
-	qt422016.ReleaseWriter(qw422016)
-//line templates/gititem.qtpl:16
-}
-
-//line templates/gititem.qtpl:16
-func (p *GitItemPage) Title() string {
-//line templates/gititem.qtpl:16
-	qb422016 := qt422016.AcquireByteBuffer()
-//line templates/gititem.qtpl:16
-	p.WriteTitle(qb422016)
-//line templates/gititem.qtpl:16
-	qs422016 := string(qb422016.B)
-//line templates/gititem.qtpl:16
-	qt422016.ReleaseByteBuffer(qb422016)
-//line templates/gititem.qtpl:16
-	return qs422016
-//line templates/gititem.qtpl:16
-}
-
-//line templates/gititem.qtpl:18
-func (p *GitItemPage) StreamNavbar(qw422016 *qt422016.Writer) {
-//line templates/gititem.qtpl:18
-	StreamNavbar(qw422016, Git)
 //line templates/gititem.qtpl:18
 }
 
 //line templates/gititem.qtpl:18
-func (p *GitItemPage) WriteNavbar(qq422016 qtio422016.Writer) {
+func (p *GitItemPage) WriteTitle(qq422016 qtio422016.Writer, ctx context.Context) {
 //line templates/gititem.qtpl:18
 	qw422016 := qt422016.AcquireWriter(qq422016)
 //line templates/gititem.qtpl:18
-	p.StreamNavbar(qw422016)
+	p.StreamTitle(qw422016, ctx)
 //line templates/gititem.qtpl:18
 	qt422016.ReleaseWriter(qw422016)
 //line templates/gititem.qtpl:18
 }
 
 //line templates/gititem.qtpl:18
-func (p *GitItemPage) Navbar() string {
+func (p *GitItemPage) Title(ctx context.Context) string {
 //line templates/gititem.qtpl:18
 	qb422016 := qt422016.AcquireByteBuffer()
 //line templates/gititem.qtpl:18
-	p.WriteNavbar(qb422016)
+	p.WriteTitle(qb422016, ctx)
 //line templates/gititem.qtpl:18
 	qs422016 := string(qb422016.B)
 //line templates/gititem.qtpl:18
@@ -110,81 +80,114 @@ //line templates/gititem.qtpl:18
 }
 
 //line templates/gititem.qtpl:20
-func (p *GitItemPage) StreamContent(qw422016 *qt422016.Writer) {
+func (p *GitItemPage) StreamNavbar(qw422016 *qt422016.Writer, ctx context.Context) {
+//line templates/gititem.qtpl:20
+	StreamNavbar(qw422016, ctx, Git)
+//line templates/gititem.qtpl:20
+}
+
+//line templates/gititem.qtpl:20
+func (p *GitItemPage) WriteNavbar(qq422016 qtio422016.Writer, ctx context.Context) {
+//line templates/gititem.qtpl:20
+	qw422016 := qt422016.AcquireWriter(qq422016)
+//line templates/gititem.qtpl:20
+	p.StreamNavbar(qw422016, ctx)
+//line templates/gititem.qtpl:20
+	qt422016.ReleaseWriter(qw422016)
+//line templates/gititem.qtpl:20
+}
+
+//line templates/gititem.qtpl:20
+func (p *GitItemPage) Navbar(ctx context.Context) string {
+//line templates/gititem.qtpl:20
+	qb422016 := qt422016.AcquireByteBuffer()
+//line templates/gititem.qtpl:20
+	p.WriteNavbar(qb422016, ctx)
+//line templates/gititem.qtpl:20
+	qs422016 := string(qb422016.B)
 //line templates/gititem.qtpl:20
+	qt422016.ReleaseByteBuffer(qb422016)
+//line templates/gititem.qtpl:20
+	return qs422016
+//line templates/gititem.qtpl:20
+}
+
+//line templates/gititem.qtpl:22
+func (p *GitItemPage) StreamContent(qw422016 *qt422016.Writer, ctx context.Context) {
+//line templates/gititem.qtpl:22
 	qw422016.N().S(`
 `)
-//line templates/gititem.qtpl:21
+//line templates/gititem.qtpl:23
 	p.StreamNav(qw422016, p.Name, p.Ref)
-//line templates/gititem.qtpl:21
+//line templates/gititem.qtpl:23
 	qw422016.N().S(`
 <div class="container">
 `)
-//line templates/gititem.qtpl:23
+//line templates/gititem.qtpl:25
 	p.StreamGitContent(qw422016, p.Name, p.Ref)
-//line templates/gititem.qtpl:23
+//line templates/gititem.qtpl:25
 	qw422016.N().S(`
 </div>
 `)
-//line templates/gititem.qtpl:25
+//line templates/gititem.qtpl:27
 }
 
-//line templates/gititem.qtpl:25
-func (p *GitItemPage) WriteContent(qq422016 qtio422016.Writer) {
-//line templates/gititem.qtpl:25
+//line templates/gititem.qtpl:27
+func (p *GitItemPage) WriteContent(qq422016 qtio422016.Writer, ctx context.Context) {
+//line templates/gititem.qtpl:27
 	qw422016 := qt422016.AcquireWriter(qq422016)
-//line templates/gititem.qtpl:25
-	p.StreamContent(qw422016)
-//line templates/gititem.qtpl:25
+//line templates/gititem.qtpl:27
+	p.StreamContent(qw422016, ctx)
+//line templates/gititem.qtpl:27
 	qt422016.ReleaseWriter(qw422016)
-//line templates/gititem.qtpl:25
+//line templates/gititem.qtpl:27
 }
 
-//line templates/gititem.qtpl:25
-func (p *GitItemPage) Content() string {
-//line templates/gititem.qtpl:25
+//line templates/gititem.qtpl:27
+func (p *GitItemPage) Content(ctx context.Context) string {
+//line templates/gititem.qtpl:27
 	qb422016 := qt422016.AcquireByteBuffer()
-//line templates/gititem.qtpl:25
-	p.WriteContent(qb422016)
-//line templates/gititem.qtpl:25
+//line templates/gititem.qtpl:27
+	p.WriteContent(qb422016, ctx)
+//line templates/gititem.qtpl:27
 	qs422016 := string(qb422016.B)
-//line templates/gititem.qtpl:25
+//line templates/gititem.qtpl:27
 	qt422016.ReleaseByteBuffer(qb422016)
-//line templates/gititem.qtpl:25
+//line templates/gititem.qtpl:27
 	return qs422016
-//line templates/gititem.qtpl:25
+//line templates/gititem.qtpl:27
 }
 
-//line templates/gititem.qtpl:27
-func (p *GitItemPage) StreamScript(qw422016 *qt422016.Writer) {
-//line templates/gititem.qtpl:27
+//line templates/gititem.qtpl:29
+func (p *GitItemPage) StreamScript(qw422016 *qt422016.Writer, ctx context.Context) {
+//line templates/gititem.qtpl:29
 	qw422016.N().S(`
 `)
-//line templates/gititem.qtpl:28
+//line templates/gititem.qtpl:30
 }
 
-//line templates/gititem.qtpl:28
-func (p *GitItemPage) WriteScript(qq422016 qtio422016.Writer) {
-//line templates/gititem.qtpl:28
+//line templates/gititem.qtpl:30
+func (p *GitItemPage) WriteScript(qq422016 qtio422016.Writer, ctx context.Context) {
+//line templates/gititem.qtpl:30
 	qw422016 := qt422016.AcquireWriter(qq422016)
-//line templates/gititem.qtpl:28
-	p.StreamScript(qw422016)
-//line templates/gititem.qtpl:28
+//line templates/gititem.qtpl:30
+	p.StreamScript(qw422016, ctx)
+//line templates/gititem.qtpl:30
 	qt422016.ReleaseWriter(qw422016)
-//line templates/gititem.qtpl:28
+//line templates/gititem.qtpl:30
 }
 
-//line templates/gititem.qtpl:28
-func (p *GitItemPage) Script() string {
-//line templates/gititem.qtpl:28
+//line templates/gititem.qtpl:30
+func (p *GitItemPage) Script(ctx context.Context) string {
+//line templates/gititem.qtpl:30
 	qb422016 := qt422016.AcquireByteBuffer()
-//line templates/gititem.qtpl:28
-	p.WriteScript(qb422016)
-//line templates/gititem.qtpl:28
+//line templates/gititem.qtpl:30
+	p.WriteScript(qb422016, ctx)
+//line templates/gititem.qtpl:30
 	qs422016 := string(qb422016.B)
-//line templates/gititem.qtpl:28
+//line templates/gititem.qtpl:30
 	qt422016.ReleaseByteBuffer(qb422016)
-//line templates/gititem.qtpl:28
+//line templates/gititem.qtpl:30
 	return qs422016
-//line templates/gititem.qtpl:28
+//line templates/gititem.qtpl:30
 }
diff --git a/templates/gitlist.qtpl b/templates/gitlist.qtpl
index 7c104ca5b394315b2657d598ddd79f797af27de7..fa470089e9f4fd64c066822ec1c849628ddd4f1e 100644
--- a/templates/gitlist.qtpl
+++ b/templates/gitlist.qtpl
@@ -1,4 +1,5 @@
 {% import "git.gabrielgio.me/cerrado/pkg/service" %}
+{% import "context" %}
 
 {% code
 type GitListPage struct {
@@ -7,11 +8,11 @@     About []byte
 }
 %}
 
-{% func (p *GitListPage) Title() %}Git | List{% endfunc %}
+{% func (p *GitListPage) Title(ctx context.Context) %}Git | List{% endfunc %}
 
-{% func (p *GitListPage) Navbar() %}{%= Navbar(Git) %}{% endfunc %}
+{% func (p *GitListPage) Navbar(ctx context.Context) %}{%= Navbar(ctx, Git) %}{% endfunc %}
 
-{% func (p *GitListPage) Content() %}
+{% func (p *GitListPage) Content(ctx context.Context) %}
 <div class="row">
   <div class="col-md-6 order-last order-md-first">
     <div class="event-list">
@@ -40,5 +41,5 @@   </div>
 </div>
 {% endfunc %}
 
-{% func (p *GitListPage) Script() %}
+{% func (p *GitListPage) Script(ctx context.Context) %}
 {% endfunc %}
diff --git a/templates/gitlist.qtpl.go b/templates/gitlist.qtpl.go
index 29adbc6d54b1d1bc78b24b34043d756ee96e5d81..601dbb2fa8c947e791800ebded6aabbd64005919 100644
--- a/templates/gitlist.qtpl.go
+++ b/templates/gitlist.qtpl.go
@@ -7,159 +7,162 @@
 //line templates/gitlist.qtpl:1
 import "git.gabrielgio.me/cerrado/pkg/service"
 
-//line templates/gitlist.qtpl:3
+//line templates/gitlist.qtpl:2
+import "context"
+
+//line templates/gitlist.qtpl:4
 import (
 	qtio422016 "io"
 
 	qt422016 "github.com/valyala/quicktemplate"
 )
 
-//line templates/gitlist.qtpl:3
+//line templates/gitlist.qtpl:4
 var (
 	_ = qtio422016.Copy
 	_ = qt422016.AcquireByteBuffer
 )
 
-//line templates/gitlist.qtpl:4
+//line templates/gitlist.qtpl:5
 type GitListPage struct {
 	Respositories []*service.Repository
 	About         []byte
 }
 
-//line templates/gitlist.qtpl:10
-func (p *GitListPage) StreamTitle(qw422016 *qt422016.Writer) {
-//line templates/gitlist.qtpl:10
+//line templates/gitlist.qtpl:11
+func (p *GitListPage) StreamTitle(qw422016 *qt422016.Writer, ctx context.Context) {
+//line templates/gitlist.qtpl:11
 	qw422016.N().S(`Git | List`)
-//line templates/gitlist.qtpl:10
+//line templates/gitlist.qtpl:11
 }
 
-//line templates/gitlist.qtpl:10
-func (p *GitListPage) WriteTitle(qq422016 qtio422016.Writer) {
-//line templates/gitlist.qtpl:10
+//line templates/gitlist.qtpl:11
+func (p *GitListPage) WriteTitle(qq422016 qtio422016.Writer, ctx context.Context) {
+//line templates/gitlist.qtpl:11
 	qw422016 := qt422016.AcquireWriter(qq422016)
-//line templates/gitlist.qtpl:10
-	p.StreamTitle(qw422016)
-//line templates/gitlist.qtpl:10
+//line templates/gitlist.qtpl:11
+	p.StreamTitle(qw422016, ctx)
+//line templates/gitlist.qtpl:11
 	qt422016.ReleaseWriter(qw422016)
-//line templates/gitlist.qtpl:10
+//line templates/gitlist.qtpl:11
 }
 
-//line templates/gitlist.qtpl:10
-func (p *GitListPage) Title() string {
-//line templates/gitlist.qtpl:10
+//line templates/gitlist.qtpl:11
+func (p *GitListPage) Title(ctx context.Context) string {
+//line templates/gitlist.qtpl:11
 	qb422016 := qt422016.AcquireByteBuffer()
-//line templates/gitlist.qtpl:10
-	p.WriteTitle(qb422016)
-//line templates/gitlist.qtpl:10
+//line templates/gitlist.qtpl:11
+	p.WriteTitle(qb422016, ctx)
+//line templates/gitlist.qtpl:11
 	qs422016 := string(qb422016.B)
-//line templates/gitlist.qtpl:10
+//line templates/gitlist.qtpl:11
 	qt422016.ReleaseByteBuffer(qb422016)
-//line templates/gitlist.qtpl:10
+//line templates/gitlist.qtpl:11
 	return qs422016
-//line templates/gitlist.qtpl:10
+//line templates/gitlist.qtpl:11
 }
 
-//line templates/gitlist.qtpl:12
-func (p *GitListPage) StreamNavbar(qw422016 *qt422016.Writer) {
-//line templates/gitlist.qtpl:12
-	StreamNavbar(qw422016, Git)
-//line templates/gitlist.qtpl:12
+//line templates/gitlist.qtpl:13
+func (p *GitListPage) StreamNavbar(qw422016 *qt422016.Writer, ctx context.Context) {
+//line templates/gitlist.qtpl:13
+	StreamNavbar(qw422016, ctx, Git)
+//line templates/gitlist.qtpl:13
 }
 
-//line templates/gitlist.qtpl:12
-func (p *GitListPage) WriteNavbar(qq422016 qtio422016.Writer) {
-//line templates/gitlist.qtpl:12
+//line templates/gitlist.qtpl:13
+func (p *GitListPage) WriteNavbar(qq422016 qtio422016.Writer, ctx context.Context) {
+//line templates/gitlist.qtpl:13
 	qw422016 := qt422016.AcquireWriter(qq422016)
-//line templates/gitlist.qtpl:12
-	p.StreamNavbar(qw422016)
-//line templates/gitlist.qtpl:12
+//line templates/gitlist.qtpl:13
+	p.StreamNavbar(qw422016, ctx)
+//line templates/gitlist.qtpl:13
 	qt422016.ReleaseWriter(qw422016)
-//line templates/gitlist.qtpl:12
+//line templates/gitlist.qtpl:13
 }
 
-//line templates/gitlist.qtpl:12
-func (p *GitListPage) Navbar() string {
-//line templates/gitlist.qtpl:12
+//line templates/gitlist.qtpl:13
+func (p *GitListPage) Navbar(ctx context.Context) string {
+//line templates/gitlist.qtpl:13
 	qb422016 := qt422016.AcquireByteBuffer()
-//line templates/gitlist.qtpl:12
-	p.WriteNavbar(qb422016)
-//line templates/gitlist.qtpl:12
+//line templates/gitlist.qtpl:13
+	p.WriteNavbar(qb422016, ctx)
+//line templates/gitlist.qtpl:13
 	qs422016 := string(qb422016.B)
-//line templates/gitlist.qtpl:12
+//line templates/gitlist.qtpl:13
 	qt422016.ReleaseByteBuffer(qb422016)
-//line templates/gitlist.qtpl:12
+//line templates/gitlist.qtpl:13
 	return qs422016
-//line templates/gitlist.qtpl:12
+//line templates/gitlist.qtpl:13
 }
 
-//line templates/gitlist.qtpl:14
-func (p *GitListPage) StreamContent(qw422016 *qt422016.Writer) {
-//line templates/gitlist.qtpl:14
+//line templates/gitlist.qtpl:15
+func (p *GitListPage) StreamContent(qw422016 *qt422016.Writer, ctx context.Context) {
+//line templates/gitlist.qtpl:15
 	qw422016.N().S(`
 <div class="row">
   <div class="col-md-6 order-last order-md-first">
     <div class="event-list">
       `)
-//line templates/gitlist.qtpl:18
+//line templates/gitlist.qtpl:19
 	for _, r := range p.Respositories {
-//line templates/gitlist.qtpl:18
+//line templates/gitlist.qtpl:19
 		qw422016.N().S(`
       <div class="event">
         <h4>
           <a href="/`)
-//line templates/gitlist.qtpl:21
+//line templates/gitlist.qtpl:22
 		qw422016.E().S(r.Name)
-//line templates/gitlist.qtpl:21
+//line templates/gitlist.qtpl:22
 		qw422016.N().S(`/">`)
-//line templates/gitlist.qtpl:21
+//line templates/gitlist.qtpl:22
 		qw422016.E().S(r.Name)
-//line templates/gitlist.qtpl:21
+//line templates/gitlist.qtpl:22
 		qw422016.N().S(`</a>
         </h4>
         </hr>
         <p>`)
-//line templates/gitlist.qtpl:24
+//line templates/gitlist.qtpl:25
 		qw422016.E().S(r.Description)
-//line templates/gitlist.qtpl:24
+//line templates/gitlist.qtpl:25
 		qw422016.N().S(`</p>
         <p>
           <a href="/`)
-//line templates/gitlist.qtpl:26
+//line templates/gitlist.qtpl:27
 		qw422016.E().S(r.Name)
-//line templates/gitlist.qtpl:26
+//line templates/gitlist.qtpl:27
 		qw422016.N().S(`/log/`)
-//line templates/gitlist.qtpl:26
+//line templates/gitlist.qtpl:27
 		qw422016.E().S(r.Ref)
-//line templates/gitlist.qtpl:26
+//line templates/gitlist.qtpl:27
 		qw422016.N().S(`/">log</a>
           <a href="/`)
-//line templates/gitlist.qtpl:27
+//line templates/gitlist.qtpl:28
 		qw422016.E().S(r.Name)
-//line templates/gitlist.qtpl:27
+//line templates/gitlist.qtpl:28
 		qw422016.N().S(`/tree/`)
-//line templates/gitlist.qtpl:27
+//line templates/gitlist.qtpl:28
 		qw422016.E().S(r.Ref)
-//line templates/gitlist.qtpl:27
+//line templates/gitlist.qtpl:28
 		qw422016.N().S(`/">tree</a>
           <a href="/`)
-//line templates/gitlist.qtpl:28
+//line templates/gitlist.qtpl:29
 		qw422016.E().S(r.Name)
-//line templates/gitlist.qtpl:28
+//line templates/gitlist.qtpl:29
 		qw422016.N().S(`/refs/">refs</a>
         </p>
       </div>
       `)
-//line templates/gitlist.qtpl:31
+//line templates/gitlist.qtpl:32
 	}
-//line templates/gitlist.qtpl:31
+//line templates/gitlist.qtpl:32
 	qw422016.N().S(`
     </div>
   </div>
   <div id="about" class="col-md-4 order-first order-md-last">
     `)
-//line templates/gitlist.qtpl:35
+//line templates/gitlist.qtpl:36
 	qw422016.N().Z(p.About)
-//line templates/gitlist.qtpl:35
+//line templates/gitlist.qtpl:36
 	qw422016.N().S(`
     <div class="alert alert-warning text-center" role="alert">
         This project is under development, things may be broken or incomplete.
@@ -167,65 +170,65 @@     </div>
   </div>
 </div>
 `)
-//line templates/gitlist.qtpl:41
+//line templates/gitlist.qtpl:42
 }
 
-//line templates/gitlist.qtpl:41
-func (p *GitListPage) WriteContent(qq422016 qtio422016.Writer) {
-//line templates/gitlist.qtpl:41
+//line templates/gitlist.qtpl:42
+func (p *GitListPage) WriteContent(qq422016 qtio422016.Writer, ctx context.Context) {
+//line templates/gitlist.qtpl:42
 	qw422016 := qt422016.AcquireWriter(qq422016)
-//line templates/gitlist.qtpl:41
-	p.StreamContent(qw422016)
-//line templates/gitlist.qtpl:41
+//line templates/gitlist.qtpl:42
+	p.StreamContent(qw422016, ctx)
+//line templates/gitlist.qtpl:42
 	qt422016.ReleaseWriter(qw422016)
-//line templates/gitlist.qtpl:41
+//line templates/gitlist.qtpl:42
 }
 
-//line templates/gitlist.qtpl:41
-func (p *GitListPage) Content() string {
-//line templates/gitlist.qtpl:41
+//line templates/gitlist.qtpl:42
+func (p *GitListPage) Content(ctx context.Context) string {
+//line templates/gitlist.qtpl:42
 	qb422016 := qt422016.AcquireByteBuffer()
-//line templates/gitlist.qtpl:41
-	p.WriteContent(qb422016)
-//line templates/gitlist.qtpl:41
+//line templates/gitlist.qtpl:42
+	p.WriteContent(qb422016, ctx)
+//line templates/gitlist.qtpl:42
 	qs422016 := string(qb422016.B)
-//line templates/gitlist.qtpl:41
+//line templates/gitlist.qtpl:42
 	qt422016.ReleaseByteBuffer(qb422016)
-//line templates/gitlist.qtpl:41
+//line templates/gitlist.qtpl:42
 	return qs422016
-//line templates/gitlist.qtpl:41
+//line templates/gitlist.qtpl:42
 }
 
-//line templates/gitlist.qtpl:43
-func (p *GitListPage) StreamScript(qw422016 *qt422016.Writer) {
-//line templates/gitlist.qtpl:43
+//line templates/gitlist.qtpl:44
+func (p *GitListPage) StreamScript(qw422016 *qt422016.Writer, ctx context.Context) {
+//line templates/gitlist.qtpl:44
 	qw422016.N().S(`
 `)
-//line templates/gitlist.qtpl:44
+//line templates/gitlist.qtpl:45
 }
 
-//line templates/gitlist.qtpl:44
-func (p *GitListPage) WriteScript(qq422016 qtio422016.Writer) {
-//line templates/gitlist.qtpl:44
+//line templates/gitlist.qtpl:45
+func (p *GitListPage) WriteScript(qq422016 qtio422016.Writer, ctx context.Context) {
+//line templates/gitlist.qtpl:45
 	qw422016 := qt422016.AcquireWriter(qq422016)
-//line templates/gitlist.qtpl:44
-	p.StreamScript(qw422016)
-//line templates/gitlist.qtpl:44
+//line templates/gitlist.qtpl:45
+	p.StreamScript(qw422016, ctx)
+//line templates/gitlist.qtpl:45
 	qt422016.ReleaseWriter(qw422016)
-//line templates/gitlist.qtpl:44
+//line templates/gitlist.qtpl:45
 }
 
-//line templates/gitlist.qtpl:44
-func (p *GitListPage) Script() string {
-//line templates/gitlist.qtpl:44
+//line templates/gitlist.qtpl:45
+func (p *GitListPage) Script(ctx context.Context) string {
+//line templates/gitlist.qtpl:45
 	qb422016 := qt422016.AcquireByteBuffer()
-//line templates/gitlist.qtpl:44
-	p.WriteScript(qb422016)
-//line templates/gitlist.qtpl:44
+//line templates/gitlist.qtpl:45
+	p.WriteScript(qb422016, ctx)
+//line templates/gitlist.qtpl:45
 	qs422016 := string(qb422016.B)
-//line templates/gitlist.qtpl:44
+//line templates/gitlist.qtpl:45
 	qt422016.ReleaseByteBuffer(qb422016)
-//line templates/gitlist.qtpl:44
+//line templates/gitlist.qtpl:45
 	return qs422016
-//line templates/gitlist.qtpl:44
+//line templates/gitlist.qtpl:45
 }
diff --git a/templates/login.qtpl b/templates/login.qtpl
index eee57117106360c2f0d9bbf104e0b820bf051e92..7815bd7401ff8cdee199144ac88b61421f253eb7 100644
--- a/templates/login.qtpl
+++ b/templates/login.qtpl
@@ -1,31 +1,41 @@
+{% import "context" %}
+
 {% code
 type LoginPage struct {
+    ErrorMessage string
 }
 %}
 
-{% func (p *LoginPage) Title() %}Hello{% endfunc %}
+{% func (p *LoginPage) Title(ctx context.Context) %}Hello{% endfunc %}
 
-{% func (p *LoginPage) Navbar() %}{%= Navbar(Login) %}{% endfunc %}
+{% func (p *LoginPage) Navbar(ctx context.Context) %}{%= Navbar(ctx, Login) %}{% endfunc %}
 
-{% func (p *LoginPage) Content() %}
+{% func (p *LoginPage) Content(ctx context.Context) %}
 <div class="row">
   <div class="col-md-6 offset-md-3">
-    <form>
+    <form action="/login/" method="POST">
       <div class="form-group m-3">
         <label for="username" class="form-label">Username</label>
-        <input type="text" class="form-control" id="username" aria-describedby="emailHelp">
+        <input type="text" class="form-control" name="username" id="username">
       </div>
       <div class="form-group m-3">
         <label for="password" class="form-label">Password</label>
-        <input type="password" class="form-control" id="password">
+        <input type="password" class="form-control" name="password" id="password">
       </div>
       <div class="form-group m-3">
         <button type="submit" class="btn btn-primary">Login</button>
       </div>
     </form>
   </div>
+  {% if p.ErrorMessage != "" %}
+  <div class="col-md-6 offset-md-3">
+    <div class="alert alert-warning text-center" >
+        {%s p.ErrorMessage  %}
+    </div>
+  </div>
+  {% endif %}
 </div>
 {% endfunc %}
 
-{% func (p *LoginPage) Script() %}
+{% func (p *LoginPage) Script(ctx context.Context) %}
 {% endfunc %}
diff --git a/templates/login.qtpl.go b/templates/login.qtpl.go
index 0d3d2b0c41d592cf030a0806131d1057e8726786..5c07a44eea42027c0c04ab1e56ec192c187964cb 100644
--- a/templates/login.qtpl.go
+++ b/templates/login.qtpl.go
@@ -5,169 +5,192 @@ //line templates/login.qtpl:1
 package templates
 
 //line templates/login.qtpl:1
+import "context"
+
+//line templates/login.qtpl:3
 import (
 	qtio422016 "io"
 
 	qt422016 "github.com/valyala/quicktemplate"
 )
 
-//line templates/login.qtpl:1
+//line templates/login.qtpl:3
 var (
 	_ = qtio422016.Copy
 	_ = qt422016.AcquireByteBuffer
 )
 
-//line templates/login.qtpl:2
+//line templates/login.qtpl:4
 type LoginPage struct {
+	ErrorMessage string
 }
 
-//line templates/login.qtpl:6
-func (p *LoginPage) StreamTitle(qw422016 *qt422016.Writer) {
-//line templates/login.qtpl:6
+//line templates/login.qtpl:9
+func (p *LoginPage) StreamTitle(qw422016 *qt422016.Writer, ctx context.Context) {
+//line templates/login.qtpl:9
 	qw422016.N().S(`Hello`)
-//line templates/login.qtpl:6
+//line templates/login.qtpl:9
 }
 
-//line templates/login.qtpl:6
-func (p *LoginPage) WriteTitle(qq422016 qtio422016.Writer) {
-//line templates/login.qtpl:6
+//line templates/login.qtpl:9
+func (p *LoginPage) WriteTitle(qq422016 qtio422016.Writer, ctx context.Context) {
+//line templates/login.qtpl:9
 	qw422016 := qt422016.AcquireWriter(qq422016)
-//line templates/login.qtpl:6
-	p.StreamTitle(qw422016)
-//line templates/login.qtpl:6
+//line templates/login.qtpl:9
+	p.StreamTitle(qw422016, ctx)
+//line templates/login.qtpl:9
 	qt422016.ReleaseWriter(qw422016)
-//line templates/login.qtpl:6
+//line templates/login.qtpl:9
 }
 
-//line templates/login.qtpl:6
-func (p *LoginPage) Title() string {
-//line templates/login.qtpl:6
+//line templates/login.qtpl:9
+func (p *LoginPage) Title(ctx context.Context) string {
+//line templates/login.qtpl:9
 	qb422016 := qt422016.AcquireByteBuffer()
-//line templates/login.qtpl:6
-	p.WriteTitle(qb422016)
-//line templates/login.qtpl:6
+//line templates/login.qtpl:9
+	p.WriteTitle(qb422016, ctx)
+//line templates/login.qtpl:9
 	qs422016 := string(qb422016.B)
-//line templates/login.qtpl:6
+//line templates/login.qtpl:9
 	qt422016.ReleaseByteBuffer(qb422016)
-//line templates/login.qtpl:6
+//line templates/login.qtpl:9
 	return qs422016
-//line templates/login.qtpl:6
+//line templates/login.qtpl:9
 }
 
-//line templates/login.qtpl:8
-func (p *LoginPage) StreamNavbar(qw422016 *qt422016.Writer) {
-//line templates/login.qtpl:8
-	StreamNavbar(qw422016, Login)
-//line templates/login.qtpl:8
+//line templates/login.qtpl:11
+func (p *LoginPage) StreamNavbar(qw422016 *qt422016.Writer, ctx context.Context) {
+//line templates/login.qtpl:11
+	StreamNavbar(qw422016, ctx, Login)
+//line templates/login.qtpl:11
 }
 
-//line templates/login.qtpl:8
-func (p *LoginPage) WriteNavbar(qq422016 qtio422016.Writer) {
-//line templates/login.qtpl:8
+//line templates/login.qtpl:11
+func (p *LoginPage) WriteNavbar(qq422016 qtio422016.Writer, ctx context.Context) {
+//line templates/login.qtpl:11
 	qw422016 := qt422016.AcquireWriter(qq422016)
-//line templates/login.qtpl:8
-	p.StreamNavbar(qw422016)
-//line templates/login.qtpl:8
+//line templates/login.qtpl:11
+	p.StreamNavbar(qw422016, ctx)
+//line templates/login.qtpl:11
 	qt422016.ReleaseWriter(qw422016)
-//line templates/login.qtpl:8
+//line templates/login.qtpl:11
 }
 
-//line templates/login.qtpl:8
-func (p *LoginPage) Navbar() string {
-//line templates/login.qtpl:8
+//line templates/login.qtpl:11
+func (p *LoginPage) Navbar(ctx context.Context) string {
+//line templates/login.qtpl:11
 	qb422016 := qt422016.AcquireByteBuffer()
-//line templates/login.qtpl:8
-	p.WriteNavbar(qb422016)
-//line templates/login.qtpl:8
+//line templates/login.qtpl:11
+	p.WriteNavbar(qb422016, ctx)
+//line templates/login.qtpl:11
 	qs422016 := string(qb422016.B)
-//line templates/login.qtpl:8
+//line templates/login.qtpl:11
 	qt422016.ReleaseByteBuffer(qb422016)
-//line templates/login.qtpl:8
+//line templates/login.qtpl:11
 	return qs422016
-//line templates/login.qtpl:8
+//line templates/login.qtpl:11
 }
 
-//line templates/login.qtpl:10
-func (p *LoginPage) StreamContent(qw422016 *qt422016.Writer) {
-//line templates/login.qtpl:10
+//line templates/login.qtpl:13
+func (p *LoginPage) StreamContent(qw422016 *qt422016.Writer, ctx context.Context) {
+//line templates/login.qtpl:13
 	qw422016.N().S(`
 <div class="row">
   <div class="col-md-6 offset-md-3">
-    <form>
+    <form action="/login/" method="POST">
       <div class="form-group m-3">
         <label for="username" class="form-label">Username</label>
-        <input type="text" class="form-control" id="username" aria-describedby="emailHelp">
+        <input type="text" class="form-control" name="username" id="username">
       </div>
       <div class="form-group m-3">
         <label for="password" class="form-label">Password</label>
-        <input type="password" class="form-control" id="password">
+        <input type="password" class="form-control" name="password" id="password">
       </div>
       <div class="form-group m-3">
         <button type="submit" class="btn btn-primary">Login</button>
       </div>
     </form>
   </div>
+  `)
+//line templates/login.qtpl:30
+	if p.ErrorMessage != "" {
+//line templates/login.qtpl:30
+		qw422016.N().S(`
+  <div class="col-md-6 offset-md-3">
+    <div class="alert alert-warning text-center" >
+        `)
+//line templates/login.qtpl:33
+		qw422016.E().S(p.ErrorMessage)
+//line templates/login.qtpl:33
+		qw422016.N().S(`
+    </div>
+  </div>
+  `)
+//line templates/login.qtpl:36
+	}
+//line templates/login.qtpl:36
+	qw422016.N().S(`
 </div>
 `)
-//line templates/login.qtpl:28
+//line templates/login.qtpl:38
 }
 
-//line templates/login.qtpl:28
-func (p *LoginPage) WriteContent(qq422016 qtio422016.Writer) {
-//line templates/login.qtpl:28
+//line templates/login.qtpl:38
+func (p *LoginPage) WriteContent(qq422016 qtio422016.Writer, ctx context.Context) {
+//line templates/login.qtpl:38
 	qw422016 := qt422016.AcquireWriter(qq422016)
-//line templates/login.qtpl:28
-	p.StreamContent(qw422016)
-//line templates/login.qtpl:28
+//line templates/login.qtpl:38
+	p.StreamContent(qw422016, ctx)
+//line templates/login.qtpl:38
 	qt422016.ReleaseWriter(qw422016)
-//line templates/login.qtpl:28
+//line templates/login.qtpl:38
 }
 
-//line templates/login.qtpl:28
-func (p *LoginPage) Content() string {
-//line templates/login.qtpl:28
+//line templates/login.qtpl:38
+func (p *LoginPage) Content(ctx context.Context) string {
+//line templates/login.qtpl:38
 	qb422016 := qt422016.AcquireByteBuffer()
-//line templates/login.qtpl:28
-	p.WriteContent(qb422016)
-//line templates/login.qtpl:28
+//line templates/login.qtpl:38
+	p.WriteContent(qb422016, ctx)
+//line templates/login.qtpl:38
 	qs422016 := string(qb422016.B)
-//line templates/login.qtpl:28
+//line templates/login.qtpl:38
 	qt422016.ReleaseByteBuffer(qb422016)
-//line templates/login.qtpl:28
+//line templates/login.qtpl:38
 	return qs422016
-//line templates/login.qtpl:28
+//line templates/login.qtpl:38
 }
 
-//line templates/login.qtpl:30
-func (p *LoginPage) StreamScript(qw422016 *qt422016.Writer) {
-//line templates/login.qtpl:30
+//line templates/login.qtpl:40
+func (p *LoginPage) StreamScript(qw422016 *qt422016.Writer, ctx context.Context) {
+//line templates/login.qtpl:40
 	qw422016.N().S(`
 `)
-//line templates/login.qtpl:31
+//line templates/login.qtpl:41
 }
 
-//line templates/login.qtpl:31
-func (p *LoginPage) WriteScript(qq422016 qtio422016.Writer) {
-//line templates/login.qtpl:31
+//line templates/login.qtpl:41
+func (p *LoginPage) WriteScript(qq422016 qtio422016.Writer, ctx context.Context) {
+//line templates/login.qtpl:41
 	qw422016 := qt422016.AcquireWriter(qq422016)
-//line templates/login.qtpl:31
-	p.StreamScript(qw422016)
-//line templates/login.qtpl:31
+//line templates/login.qtpl:41
+	p.StreamScript(qw422016, ctx)
+//line templates/login.qtpl:41
 	qt422016.ReleaseWriter(qw422016)
-//line templates/login.qtpl:31
+//line templates/login.qtpl:41
 }
 
-//line templates/login.qtpl:31
-func (p *LoginPage) Script() string {
-//line templates/login.qtpl:31
+//line templates/login.qtpl:41
+func (p *LoginPage) Script(ctx context.Context) string {
+//line templates/login.qtpl:41
 	qb422016 := qt422016.AcquireByteBuffer()
-//line templates/login.qtpl:31
-	p.WriteScript(qb422016)
-//line templates/login.qtpl:31
+//line templates/login.qtpl:41
+	p.WriteScript(qb422016, ctx)
+//line templates/login.qtpl:41
 	qs422016 := string(qb422016.B)
-//line templates/login.qtpl:31
+//line templates/login.qtpl:41
 	qt422016.ReleaseByteBuffer(qb422016)
-//line templates/login.qtpl:31
+//line templates/login.qtpl:41
 	return qs422016
-//line templates/login.qtpl:31
+//line templates/login.qtpl:41
 }
diff --git a/templates/navbar.qtpl b/templates/navbar.qtpl
index 18400b19faa99a904eecd35b103dce288b378cfb..3cd1b39dd764a9754891be72beb340c74bcae476 100644
--- a/templates/navbar.qtpl
+++ b/templates/navbar.qtpl
@@ -1,3 +1,5 @@
+{% import "context" %}
+
 {% code
 type Selection int
 const (
@@ -22,13 +24,17 @@ %}
 
 {% func insertIfEqual(s, d any) %}{% if s == d %} selected{% endif %}{% endfunc %}
 
-{% func Navbar (s Selection) %}
+{% func Navbar (ctx context.Context, s Selection) %}
         <nav class="container navbar navbar-expand">
           <div class="navbar-nav">
             <a class="nav-link{%= insertIfEqual(s, Git) %}" href="/">git</a>
           </div>
           <div class="navbar-nav ms-auto">
+          {% if IsLoggedIn(ctx) %}
+            <a class="nav-link{%= insertIfEqual(s, Login) %}" href="/logout">logout</a>
+          {% else %}
             <a class="nav-link{%= insertIfEqual(s, Login) %}" href="/login">login</a>
+          {% endif %}
 {% comment %}
 Add this back once needed
             <a class="nav-link{%= insertIfEqual(s, List) %}" href="/list/">list</a>
diff --git a/templates/navbar.qtpl.go b/templates/navbar.qtpl.go
index e080785da7c19c0dee4de95c1e329e319d293957..d900c9cfe6bf59b13261796d539952e453cec6d0 100644
--- a/templates/navbar.qtpl.go
+++ b/templates/navbar.qtpl.go
@@ -5,19 +5,22 @@ //line templates/navbar.qtpl:1
 package templates
 
 //line templates/navbar.qtpl:1
+import "context"
+
+//line templates/navbar.qtpl:3
 import (
 	qtio422016 "io"
 
 	qt422016 "github.com/valyala/quicktemplate"
 )
 
-//line templates/navbar.qtpl:1
+//line templates/navbar.qtpl:3
 var (
 	_ = qtio422016.Copy
 	_ = qt422016.AcquireByteBuffer
 )
 
-//line templates/navbar.qtpl:2
+//line templates/navbar.qtpl:4
 type Selection int
 
 const (
@@ -28,7 +31,7 @@ 	Config
 	Login
 )
 
-//line templates/navbar.qtpl:13
+//line templates/navbar.qtpl:15
 type GitSelection int
 
 const (
@@ -39,213 +42,233 @@ 	Refs
 	Tree
 )
 
-//line templates/navbar.qtpl:23
+//line templates/navbar.qtpl:25
 func streaminsertIfEqual(qw422016 *qt422016.Writer, s, d any) {
-//line templates/navbar.qtpl:23
+//line templates/navbar.qtpl:25
 	if s == d {
-//line templates/navbar.qtpl:23
+//line templates/navbar.qtpl:25
 		qw422016.N().S(` selected`)
-//line templates/navbar.qtpl:23
+//line templates/navbar.qtpl:25
 	}
-//line templates/navbar.qtpl:23
+//line templates/navbar.qtpl:25
 }
 
-//line templates/navbar.qtpl:23
+//line templates/navbar.qtpl:25
 func writeinsertIfEqual(qq422016 qtio422016.Writer, s, d any) {
-//line templates/navbar.qtpl:23
+//line templates/navbar.qtpl:25
 	qw422016 := qt422016.AcquireWriter(qq422016)
-//line templates/navbar.qtpl:23
+//line templates/navbar.qtpl:25
 	streaminsertIfEqual(qw422016, s, d)
-//line templates/navbar.qtpl:23
+//line templates/navbar.qtpl:25
 	qt422016.ReleaseWriter(qw422016)
-//line templates/navbar.qtpl:23
+//line templates/navbar.qtpl:25
 }
 
-//line templates/navbar.qtpl:23
+//line templates/navbar.qtpl:25
 func insertIfEqual(s, d any) string {
-//line templates/navbar.qtpl:23
+//line templates/navbar.qtpl:25
 	qb422016 := qt422016.AcquireByteBuffer()
-//line templates/navbar.qtpl:23
+//line templates/navbar.qtpl:25
 	writeinsertIfEqual(qb422016, s, d)
-//line templates/navbar.qtpl:23
+//line templates/navbar.qtpl:25
 	qs422016 := string(qb422016.B)
-//line templates/navbar.qtpl:23
+//line templates/navbar.qtpl:25
 	qt422016.ReleaseByteBuffer(qb422016)
-//line templates/navbar.qtpl:23
+//line templates/navbar.qtpl:25
 	return qs422016
-//line templates/navbar.qtpl:23
+//line templates/navbar.qtpl:25
 }
 
-//line templates/navbar.qtpl:25
-func StreamNavbar(qw422016 *qt422016.Writer, s Selection) {
-//line templates/navbar.qtpl:25
+//line templates/navbar.qtpl:27
+func StreamNavbar(qw422016 *qt422016.Writer, ctx context.Context, s Selection) {
+//line templates/navbar.qtpl:27
 	qw422016.N().S(`
         <nav class="container navbar navbar-expand">
           <div class="navbar-nav">
             <a class="nav-link`)
-//line templates/navbar.qtpl:28
+//line templates/navbar.qtpl:30
 	streaminsertIfEqual(qw422016, s, Git)
-//line templates/navbar.qtpl:28
+//line templates/navbar.qtpl:30
 	qw422016.N().S(`" href="/">git</a>
           </div>
           <div class="navbar-nav ms-auto">
+          `)
+//line templates/navbar.qtpl:33
+	if IsLoggedIn(ctx) {
+//line templates/navbar.qtpl:33
+		qw422016.N().S(`
             <a class="nav-link`)
-//line templates/navbar.qtpl:31
-	streaminsertIfEqual(qw422016, s, Login)
-//line templates/navbar.qtpl:31
-	qw422016.N().S(`" href="/login">login</a>
+//line templates/navbar.qtpl:34
+		streaminsertIfEqual(qw422016, s, Login)
+//line templates/navbar.qtpl:34
+		qw422016.N().S(`" href="/logout">logout</a>
+          `)
+//line templates/navbar.qtpl:35
+	} else {
+//line templates/navbar.qtpl:35
+		qw422016.N().S(`
+            <a class="nav-link`)
+//line templates/navbar.qtpl:36
+		streaminsertIfEqual(qw422016, s, Login)
+//line templates/navbar.qtpl:36
+		qw422016.N().S(`" href="/login">login</a>
+          `)
+//line templates/navbar.qtpl:37
+	}
+//line templates/navbar.qtpl:37
+	qw422016.N().S(`
 `)
-//line templates/navbar.qtpl:35
+//line templates/navbar.qtpl:41
 	qw422016.N().S(`
 `)
-//line templates/navbar.qtpl:39
+//line templates/navbar.qtpl:45
 	qw422016.N().S(`
           </div>
         </nav>
 `)
-//line templates/navbar.qtpl:42
+//line templates/navbar.qtpl:48
 }
 
-//line templates/navbar.qtpl:42
-func WriteNavbar(qq422016 qtio422016.Writer, s Selection) {
-//line templates/navbar.qtpl:42
+//line templates/navbar.qtpl:48
+func WriteNavbar(qq422016 qtio422016.Writer, ctx context.Context, s Selection) {
+//line templates/navbar.qtpl:48
 	qw422016 := qt422016.AcquireWriter(qq422016)
-//line templates/navbar.qtpl:42
-	StreamNavbar(qw422016, s)
-//line templates/navbar.qtpl:42
+//line templates/navbar.qtpl:48
+	StreamNavbar(qw422016, ctx, s)
+//line templates/navbar.qtpl:48
 	qt422016.ReleaseWriter(qw422016)
-//line templates/navbar.qtpl:42
+//line templates/navbar.qtpl:48
 }
 
-//line templates/navbar.qtpl:42
-func Navbar(s Selection) string {
-//line templates/navbar.qtpl:42
+//line templates/navbar.qtpl:48
+func Navbar(ctx context.Context, s Selection) string {
+//line templates/navbar.qtpl:48
 	qb422016 := qt422016.AcquireByteBuffer()
-//line templates/navbar.qtpl:42
-	WriteNavbar(qb422016, s)
-//line templates/navbar.qtpl:42
+//line templates/navbar.qtpl:48
+	WriteNavbar(qb422016, ctx, s)
+//line templates/navbar.qtpl:48
 	qs422016 := string(qb422016.B)
-//line templates/navbar.qtpl:42
+//line templates/navbar.qtpl:48
 	qt422016.ReleaseByteBuffer(qb422016)
-//line templates/navbar.qtpl:42
+//line templates/navbar.qtpl:48
 	return qs422016
-//line templates/navbar.qtpl:42
+//line templates/navbar.qtpl:48
 }
 
-//line templates/navbar.qtpl:44
+//line templates/navbar.qtpl:50
 func StreamGitItemNav(qw422016 *qt422016.Writer, name, ref string, s GitSelection) {
-//line templates/navbar.qtpl:44
+//line templates/navbar.qtpl:50
 	qw422016.N().S(`
 <div class="row">
     <h3 id="name">`)
-//line templates/navbar.qtpl:46
+//line templates/navbar.qtpl:52
 	qw422016.E().S(name)
-//line templates/navbar.qtpl:46
+//line templates/navbar.qtpl:52
 	qw422016.N().S(` `)
-//line templates/navbar.qtpl:46
+//line templates/navbar.qtpl:52
 	if ref != "" && (s == Log || s == Tree) {
-//line templates/navbar.qtpl:46
+//line templates/navbar.qtpl:52
 		qw422016.N().S(`@ `)
-//line templates/navbar.qtpl:46
+//line templates/navbar.qtpl:52
 		qw422016.E().S(ref)
-//line templates/navbar.qtpl:46
+//line templates/navbar.qtpl:52
 	}
-//line templates/navbar.qtpl:46
+//line templates/navbar.qtpl:52
 	qw422016.N().S(`</h3>
 </div>
 <div class="row">
   <ul class="nav">
     <li class="nav-item">
       <a class="nav-link`)
-//line templates/navbar.qtpl:51
+//line templates/navbar.qtpl:57
 	streaminsertIfEqual(qw422016, s, Readme)
-//line templates/navbar.qtpl:51
+//line templates/navbar.qtpl:57
 	qw422016.N().S(`" aria-current="page" href="/`)
-//line templates/navbar.qtpl:51
+//line templates/navbar.qtpl:57
 	qw422016.E().S(name)
-//line templates/navbar.qtpl:51
+//line templates/navbar.qtpl:57
 	qw422016.N().S(`/about/">about</a>
     </li>
     <li class="nav-item">
       <a class="nav-link`)
-//line templates/navbar.qtpl:54
+//line templates/navbar.qtpl:60
 	streaminsertIfEqual(qw422016, s, Summary)
-//line templates/navbar.qtpl:54
+//line templates/navbar.qtpl:60
 	qw422016.N().S(`" aria-current="page" href="/`)
-//line templates/navbar.qtpl:54
+//line templates/navbar.qtpl:60
 	qw422016.E().S(name)
-//line templates/navbar.qtpl:54
+//line templates/navbar.qtpl:60
 	qw422016.N().S(`/">summary</a>
     </li>
     <li class="nav-item">
       <a class="nav-link`)
-//line templates/navbar.qtpl:57
+//line templates/navbar.qtpl:63
 	streaminsertIfEqual(qw422016, s, Refs)
-//line templates/navbar.qtpl:57
+//line templates/navbar.qtpl:63
 	qw422016.N().S(`" aria-current="page" href="/`)
-//line templates/navbar.qtpl:57
+//line templates/navbar.qtpl:63
 	qw422016.E().S(name)
-//line templates/navbar.qtpl:57
+//line templates/navbar.qtpl:63
 	qw422016.N().S(`/refs/">refs</a>
     </li>
     <li class="nav-item">
       <a class="nav-link`)
-//line templates/navbar.qtpl:60
+//line templates/navbar.qtpl:66
 	streaminsertIfEqual(qw422016, s, Log)
-//line templates/navbar.qtpl:60
+//line templates/navbar.qtpl:66
 	qw422016.N().S(`" aria-current="page" href="/`)
-//line templates/navbar.qtpl:60
+//line templates/navbar.qtpl:66
 	qw422016.E().S(name)
-//line templates/navbar.qtpl:60
+//line templates/navbar.qtpl:66
 	qw422016.N().S(`/log/`)
-//line templates/navbar.qtpl:60
+//line templates/navbar.qtpl:66
 	qw422016.E().S(ref)
-//line templates/navbar.qtpl:60
+//line templates/navbar.qtpl:66
 	qw422016.N().S(`/">log</a>
     </li>
     <li class="nav-item">
       <a class="nav-link`)
-//line templates/navbar.qtpl:63
+//line templates/navbar.qtpl:69
 	streaminsertIfEqual(qw422016, s, Tree)
-//line templates/navbar.qtpl:63
+//line templates/navbar.qtpl:69
 	qw422016.N().S(`" aria-current="page" href="/`)
-//line templates/navbar.qtpl:63
+//line templates/navbar.qtpl:69
 	qw422016.E().S(name)
-//line templates/navbar.qtpl:63
+//line templates/navbar.qtpl:69
 	qw422016.N().S(`/tree/`)
-//line templates/navbar.qtpl:63
+//line templates/navbar.qtpl:69
 	qw422016.E().S(ref)
-//line templates/navbar.qtpl:63
+//line templates/navbar.qtpl:69
 	qw422016.N().S(`/">tree</a>
     </li>
   </ul>
 </div>
 `)
-//line templates/navbar.qtpl:67
+//line templates/navbar.qtpl:73
 }
 
-//line templates/navbar.qtpl:67
+//line templates/navbar.qtpl:73
 func WriteGitItemNav(qq422016 qtio422016.Writer, name, ref string, s GitSelection) {
-//line templates/navbar.qtpl:67
+//line templates/navbar.qtpl:73
 	qw422016 := qt422016.AcquireWriter(qq422016)
-//line templates/navbar.qtpl:67
+//line templates/navbar.qtpl:73
 	StreamGitItemNav(qw422016, name, ref, s)
-//line templates/navbar.qtpl:67
+//line templates/navbar.qtpl:73
 	qt422016.ReleaseWriter(qw422016)
-//line templates/navbar.qtpl:67
+//line templates/navbar.qtpl:73
 }
 
-//line templates/navbar.qtpl:67
+//line templates/navbar.qtpl:73
 func GitItemNav(name, ref string, s GitSelection) string {
-//line templates/navbar.qtpl:67
+//line templates/navbar.qtpl:73
 	qb422016 := qt422016.AcquireByteBuffer()
-//line templates/navbar.qtpl:67
+//line templates/navbar.qtpl:73
 	WriteGitItemNav(qb422016, name, ref, s)
-//line templates/navbar.qtpl:67
+//line templates/navbar.qtpl:73
 	qs422016 := string(qb422016.B)
-//line templates/navbar.qtpl:67
+//line templates/navbar.qtpl:73
 	qt422016.ReleaseByteBuffer(qb422016)
-//line templates/navbar.qtpl:67
+//line templates/navbar.qtpl:73
 	return qs422016
-//line templates/navbar.qtpl:67
+//line templates/navbar.qtpl:73
 }