diff --git a/Documentation/templates.md b/Documentation/templates.md
new file mode 100644
index 0000000000000000000000000000000000000000..7906363b67476c4c887b666acc39f2a412bc792b
--- /dev/null
+++ b/Documentation/templates.md
@@ -0,0 +1,24 @@
+# Templates
+
+## Using your own templates
+
+Dex supports using your own templates and passing arbitrary data to them to help customize your installation.
+
+Steps:
+
+1. Copy contents of the `web` directory over to a new directory.
+2. Customize the templates as needed, be sure to retain all the existing variables so Dex continues working correctly.
+  a. Use this syntax `{{ "your_key" | extra }}` to use values from `frontend.extra`.
+3. Write a theme for your templates in the `themes` directory.
+4. Add your custom data to the Dex configuration `frontend.extra`.
+   ```yaml
+   frontend:
+     dir: /path/to/custom/web
+     extra:
+       tos_footer_link: "https://example.com/terms"
+       client_logo_url: "../theme/client-logo.png"
+       foo: "bar"
+   ```
+5. Set the `frontend.dir` value to your own `web` directory.
+
+To test your templates simply run Dex with a valid configuration and go through a login flow.
\ No newline at end of file
diff --git a/cmd/dex/config_test.go b/cmd/dex/config_test.go
index 06a8e4294ad5fe7fb4068394ae1cf5fb4a4802ac..1e5697bf1075a0489e03ed79d0671e2d82c6c531 100644
--- a/cmd/dex/config_test.go
+++ b/cmd/dex/config_test.go
@@ -1,6 +1,7 @@
 package main
 
 import (
+	"github.com/dexidp/dex/server"
 	"testing"
 
 	"github.com/ghodss/yaml"
@@ -69,6 +70,12 @@ storage:
     connectionTimeout: 3
 web:
   http: 127.0.0.1:5556
+
+frontend:
+  dir: ./web
+  extra:
+    foo: bar
+
 staticClients:
 - id: example-app
   redirectURIs:
@@ -130,6 +137,12 @@ logger:
 		Web: Web{
 			HTTP: "127.0.0.1:5556",
 		},
+		Frontend: server.WebConfig{
+			Dir: "./web",
+			Extra: map[string]string{
+				"foo": "bar",
+			},
+		},
 		StaticClients: []storage.Client{
 			{
 				ID:     "example-app",
diff --git a/server/server.go b/server/server.go
index e125815137a31fe510e77bcd828f336dc2a0c092..aa1352c1bb8528953a99a27540c6e5817fc8534b 100644
--- a/server/server.go
+++ b/server/server.go
@@ -107,6 +107,9 @@ type WebConfig struct {
 
 	// Defaults to "coreos"
 	Theme string
+
+	// Map of extra values passed into the templates
+	Extra map[string]string
 }
 
 func value(val, defaultValue time.Duration) time.Duration {
@@ -181,6 +184,7 @@ func newServer(ctx context.Context, c Config, rotationStrategy rotationStrategy)
 		issuerURL: c.Issuer,
 		issuer:    c.Web.Issuer,
 		theme:     c.Web.Theme,
+		extra:     c.Web.Extra,
 	}
 
 	static, theme, tmpls, err := loadWebConfig(web)
diff --git a/server/templates.go b/server/templates.go
index ab9e5802056868dd0df3f1bfbe5edb89741875a7..89d413719d855221da521d28da8b647c591ee8ec 100644
--- a/server/templates.go
+++ b/server/templates.go
@@ -42,6 +42,7 @@ type webConfig struct {
 	issuer    string
 	theme     string
 	issuerURL string
+	extra     map[string]string
 }
 
 func join(base, path string) string {
@@ -140,6 +141,7 @@ func loadTemplates(c webConfig, templatesDir string) (*templates, error) {
 		"logo":   func() string { return c.logoURL },
 		"url":    func(s string) string { return join(c.issuerURL, s) },
 		"lower":  strings.ToLower,
+		"extra":  func(k string) string { return c.extra[k] },
 	}
 
 	tmpls, err := template.New("").Funcs(funcs).ParseFiles(filenames...)