Add an ‘About’ page to the application
Your goal for this exercise is to add a new ‘About’ page to the application. It should be mapped to the GET /about
route, available to both authenticated and unauthenticated users, and look similar to this:

Step 1
Create a GET /about
route which maps to a new about
handler. Think about which middleware stack is appropriate for the route to use.
Step 2
Create a new ui/html/pages/about.tmpl
file, following the same template pattern that we’ve used for the other pages of the application. Include a title, heading and some placeholder copy for the ‘About’ page.
Step 3
Update the main navigation bar for the application to include a link to the new ‘About’ page (the link should be visible to all users, irrespective of whether they are logged in or not).
Step 4
Update the about
handler so that it renders the about.tmpl
file that you’ve just created. Then sanity check that the new page and navigation works by visiting https://localhost:4000/about
in your browser.
Suggested code
Suggested code for step 1
package main ... func (app *application) about(w http.ResponseWriter, r *http.Request) { // Some code will go here later... }
package main ... func (app *application) routes() http.Handler { mux := http.NewServeMux() mux.Handle("GET /static/", http.FileServerFS(ui.Files)) mux.HandleFunc("GET /ping", ping) dynamic := alice.New(app.sessionManager.LoadAndSave, noSurf, app.authenticate) mux.Handle("GET /{$}", dynamic.ThenFunc(app.home)) // Add the about route. mux.Handle("GET /about", dynamic.ThenFunc(app.about)) mux.Handle("GET /snippet/view/{id}", dynamic.ThenFunc(app.snippetView)) mux.Handle("GET /user/signup", dynamic.ThenFunc(app.userSignup)) mux.Handle("POST /user/signup", dynamic.ThenFunc(app.userSignupPost)) mux.Handle("GET /user/login", dynamic.ThenFunc(app.userLogin)) mux.Handle("POST /user/login", dynamic.ThenFunc(app.userLoginPost)) protected := dynamic.Append(app.requireAuthentication) mux.Handle("GET /snippet/create", protected.ThenFunc(app.snippetCreate)) mux.Handle("POST /snippet/create", protected.ThenFunc(app.snippetCreatePost)) mux.Handle("POST /user/logout", protected.ThenFunc(app.userLogoutPost)) standard := alice.New(app.recoverPanic, app.logRequest, commonHeaders) return standard.Then(mux) }
Suggested code for step 2
{{define "title"}}About{{end}} {{define "main"}} <h2>About</h2> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi at mauris dignissim, consectetur tellus in, fringilla ante. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed dignissim hendrerit scelerisque.</p> <p>Praesent a dignissim arcu. Cras a metus sagittis, pellentesque odio sit amet, lacinia velit. In hac habitasse platea dictumst. </p> {{end}}
Suggested code for step 3
{{define "nav"}} <nav> <div> <a href='/'>Home</a> <!-- Include a new link, visible to all users --> <a href='/about'>About</a> {{if .IsAuthenticated}} <a href='/snippet/create'>Create snippet</a> {{end}} </div> <div> {{if .IsAuthenticated}} <form action='/user/logout' method='POST'> <input type='hidden' name='csrf_token' value='{{.CSRFToken}}'> <button>Logout</button> </form> {{else}} <a href='/user/signup'>Signup</a> <a href='/user/login'>Login</a> {{end}} </div> </nav> {{end}}
Suggested code for step 4
package main ... func (app *application) about(w http.ResponseWriter, r *http.Request) { data := app.newTemplateData(r) app.render(w, r, http.StatusOK, "about.tmpl", data) }