Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding screencast for using plush templates inside buffalo apps #169

merged 20 commits into from Jul 2, 2019
Changes from all commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.


Just for now

@@ -41,3 +41,8 @@ episode22/public

@@ -5,6 +5,9 @@
Welcome Gophers! First off, lots of :heart: from me to you. I hope you enjoy
the screencasts, and as always, keep on rockin!

>Go in 5 Minutes was featured on [GoTime]( Check out the [episode](!


This repository has code and outlines for [Go In 5 Minutes Screencasts](htttp:// All content (code samples, outlines, etc...) is organized into folders, starting with [`episode0`]( and going from there.
@@ -0,0 +1,3 @@
"presets": ["@babel/preset-env"]
@@ -0,0 +1,21 @@
app_root: .
- vendor
- log
- logs
- assets
- public
- grifts
- tmp
- bin
- node_modules
- .sass-cache
- .go
- .env
build_path: tmp
build_delay: 200ns
binary_name: episode25-build
command_flags: []
enable_colors: true
log_name: buffalo
@@ -0,0 +1,20 @@
enabled: true
enabled: true
enabled: true
enabled: true
- grifts/**/*
- "**/*_test.go"
- "*_test.go"
- "**_test.go"
- logs/*
- public/*
- templates/*
- "**.go"
@@ -0,0 +1,3 @@
@@ -0,0 +1,9 @@
# This .env file was generated by buffalo, add here the env variables you need
# buffalo to load into the ENV on application startup so your application works correctly.
# To add variables use KEY=VALUE format, you can later retrieve this in your application
# by using os.Getenv("KEY").
# Example:
@@ -0,0 +1,34 @@
# This is a multi-stage Dockerfile and requires >= Docker 17.05
FROM gobuffalo/buffalo:v0.14.6 as builder

RUN mkdir -p $GOPATH/src/episode25
WORKDIR $GOPATH/src/episode25

# this will cache the npm install step, unless package.json changes
ADD package.json .
ADD yarn.lock .
RUN yarn install --no-progress
ADD . .
RUN go get $(go list ./... | grep -v /vendor/)
RUN buffalo build --static -o /bin/app

FROM alpine
RUN apk add --no-cache bash
RUN apk add --no-cache ca-certificates


COPY --from=builder /bin/app .

# Uncomment to run the binary in "production" mode:
# ENV GO_ENV=production

# Bind the app to so it can be seen from outside the container


# Uncomment to run the migrations before running the binary:
# CMD /bin/app migrate; /bin/app
CMD exec /bin/app
@@ -0,0 +1,29 @@
# The [Buffalo]( Series #4 - Templates

Go in 5 Minutes, episode 25.

We've been looking at the [Buffalo framework]( lately, and
we're gonna keep on going today with [templating](

If you're building a webapp, templating is crucial for you to be able to serve dynamic content to your users. For example, if you need to fetch the user's name and information from your database, you'll need to somehow put that data into HTML that you can serve to their browser.

Templates are how you do it, and Buffalo has a great, easy to understand template engine to help you out!

Here's what we'll learn today:

- Introduction to templating
- The [plush]( template engine
- How to use plush from your Buffalo app

And like always I'll be showing live code.

Check out the screencast for more!

# Show Notes

- Buffalo templates:
- Go standard library [`html/template`]( and [`text/template`](
- [CSRF](
- [Prevention cheat sheet](
- See [here]( for a great explanation on how `authenticity_token` fits in
@@ -0,0 +1,24 @@
package actions

import (


type ActionSuite struct {

func Test_ActionSuite(t *testing.T) {
action, err := suite.NewActionWithFixtures(App(), packr.New("../fixtures", "../fixtures"))
if err != nil {

as := &ActionSuite{
Action: action,
suite.Run(t, as)
@@ -0,0 +1,93 @@
package actions

import (
forcessl ""
paramlogger ""

// "episode25/models"

// ""
csrf ""
i18n ""

// ENV is used to help switch settings based on where the
// application is being run. Default is "development".
var ENV = envy.Get("GO_ENV", "development")
var app *buffalo.App
var T *i18n.Translator

// App is where all routes and middleware for buffalo
// should be defined. This is the nerve center of your
// application.
// Routing, middleware, groups, etc... are declared TOP -> DOWN.
// This means if you add a middleware to `app` *after* declaring a
// group, that group will NOT have that new middleware. The same
// is true of resource declarations as well.
// It also means that routes are checked in the order they are declared.
// `ServeFiles` is a CATCH-ALL route, so it should always be
// placed last in the route declarations, as it will prevent routes
// declared after it to never be called.
func App() *buffalo.App {
if app == nil {
app = buffalo.New(buffalo.Options{
Env: ENV,
SessionName: "_episode25_session",

// Automatically redirect to SSL

// Log request parameters (filters apply).

// Protect against CSRF attacks.
// Remove to disable this.

// Wraps each request in a transaction.
// c.Value("tx").(*pop.Connection)
// Remove to disable this.
// app.Use(popmw.Transaction(models.DB))

// Setup and use translations:

app.GET("/", HomeHandler)
app.POST("/", HomePostHandler)

app.ServeFiles("/", assetsBox) // serve files from the public directory

return app

// translations will load locale files, set up the translator `actions.T`,
// and will return a middleware to use to load the correct locale for each
// request.
// for more information:
func translations() buffalo.MiddlewareFunc {
var err error
if T, err = i18n.New(packr.New("../locales", "../locales"), "en-US"); err != nil {
return T.Middleware()

// forceSSL will return a middleware that will redirect an incoming request
// if it is not HTTPS. "" => "".
// This middleware does **not** enable SSL. for your application. To do that
// we recommend using a proxy:
// for more information:
func forceSSL() buffalo.MiddlewareFunc {
return forcessl.Middleware(secure.Options{
SSLRedirect: ENV == "production",
SSLProxyHeaders: map[string]string{"X-Forwarded-Proto": "https"},
@@ -0,0 +1,24 @@
package actions

import (


// HomeHandler is a default handler to serve up
// a home page.
func HomeHandler(c buffalo.Context) error {
return c.Render(200, r.HTML("index.html"))

// HomePostHandler is a handler to serve the POST / page
func HomePostHandler(c buffalo.Context) error {
var name string
if c.Param("name") != "" {
name = c.Param("name")
c.Set("name", name)
return c.Render(200, r.HTML("index.html"))
return c.Redirect(http.StatusFound, "/")
@@ -0,0 +1,7 @@
package actions

func (as *ActionSuite) Test_HomeHandler() {
res := as.HTML("/").Get()
as.Equal(200, res.Code)
as.Contains(res.Body.String(), "Welcome to Buffalo")
@@ -0,0 +1,27 @@
package actions

import (

var r *render.Engine
var assetsBox = packr.NewBox("../public")

func init() {
r = render.New(render.Options{
// HTML layout to be used for all HTML requests:
HTMLLayout: "application.html",

// Box containing all of the templates:
TemplatesBox: packr.New("../templates", "../templates"),
AssetsBox: assetsBox,

// Add template helpers here:
Helpers: render.Helpers{
// uncomment for non-Bootstrap form helpers:
// "form": plush.FormHelper,
// "form_for": plush.FormForHelper,
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.