diff --git a/render/html_test.go b/render/html_test.go
index ae6b14445..a5e558d18 100644
--- a/render/html_test.go
+++ b/render/html_test.go
@@ -2,8 +2,8 @@ package render_test
 
 import (
 	"bytes"
-	"io/ioutil"
 	"os"
+	"path/filepath"
 	"strings"
 	"testing"
 
@@ -14,7 +14,12 @@ import (
 func Test_HTML(t *testing.T) {
 	r := require.New(t)
 
-	tmpFile, err := ioutil.TempFile("", "test")
+	tmpDir := filepath.Join(os.TempDir(), "html_test")
+	err := os.MkdirAll(tmpDir, 0766)
+	r.NoError(err)
+	defer os.Remove(tmpDir)
+
+	tmpFile, err := os.Create(filepath.Join(tmpDir, "test.html"))
 	r.NoError(err)
 	defer os.Remove(tmpFile.Name())
 
@@ -37,7 +42,7 @@ func Test_HTML(t *testing.T) {
 	t.Run("with a layout", func(st *testing.T) {
 		r := require.New(st)
 
-		layout, err := ioutil.TempFile("", "test")
+		layout, err := os.Create(filepath.Join(tmpDir, "layout.html"))
 		r.NoError(err)
 		defer os.Remove(layout.Name())
 
@@ -61,7 +66,7 @@ func Test_HTML(t *testing.T) {
 
 		st.Run("overriding the HTMLLayout", func(sst *testing.T) {
 			r := require.New(sst)
-			nlayout, err := ioutil.TempFile("", "test-layout2")
+			nlayout, err := os.Create(filepath.Join(tmpDir, "layout2.html"))
 			r.NoError(err)
 			defer os.Remove(nlayout.Name())
 
diff --git a/render/js_test.go b/render/js_test.go
index 45119bc91..b1a0c28a4 100644
--- a/render/js_test.go
+++ b/render/js_test.go
@@ -16,9 +16,13 @@ import (
 func Test_JavaScript(t *testing.T) {
 	r := require.New(t)
 
-	tmpFile, err := ioutil.TempFile("", "test")
+	tmpDir := filepath.Join(os.TempDir(), "markdown_test")
+	err := os.MkdirAll(tmpDir, 0766)
+	r.NoError(err)
+	defer os.Remove(tmpDir)
+
+	tmpFile, err := os.Create(filepath.Join(tmpDir, "test.js"))
 	r.NoError(err)
-	defer os.Remove(tmpFile.Name())
 
 	_, err = tmpFile.Write([]byte("<%= name %>"))
 	r.NoError(err)
@@ -39,9 +43,8 @@ func Test_JavaScript(t *testing.T) {
 	t.Run("with a layout", func(st *testing.T) {
 		r := require.New(st)
 
-		layout, err := ioutil.TempFile("", "test")
+		layout, err := os.Create(filepath.Join(tmpDir, "layout.js"))
 		r.NoError(err)
-		defer os.Remove(layout.Name())
 
 		_, err = layout.Write([]byte("<body><%= yield %></body>"))
 		r.NoError(err)
@@ -63,9 +66,8 @@ func Test_JavaScript(t *testing.T) {
 
 		st.Run("overriding the JavaScriptLayout", func(sst *testing.T) {
 			r := require.New(sst)
-			nlayout, err := ioutil.TempFile("", "test-layout2")
+			nlayout, err := os.Create(filepath.Join(tmpDir, "layout2.js"))
 			r.NoError(err)
-			defer os.Remove(nlayout.Name())
 
 			_, err = nlayout.Write([]byte("<html><%= yield %></html>"))
 			r.NoError(err)
diff --git a/render/markdown_test.go b/render/markdown_test.go
index 463b7e4b5..2b1371950 100644
--- a/render/markdown_test.go
+++ b/render/markdown_test.go
@@ -2,7 +2,6 @@ package render_test
 
 import (
 	"bytes"
-	"io/ioutil"
 	"os"
 	"path/filepath"
 	"strings"
@@ -47,7 +46,7 @@ func Test_Markdown(t *testing.T) {
 	t.Run("with a layout", func(st *testing.T) {
 		r := require.New(st)
 
-		layout, err := ioutil.TempFile("", "test")
+		layout, err := os.Create(filepath.Join("", "test.html"))
 		r.NoError(err)
 		defer os.Remove(layout.Name())
 
diff --git a/render/template.go b/render/template.go
index 2d2e63738..b3e8cd617 100644
--- a/render/template.go
+++ b/render/template.go
@@ -47,13 +47,25 @@ func (s templateRenderer) partial(name string, dd Data) (template.HTML, error) {
 }
 
 func (s templateRenderer) exec(name string, data Data) (template.HTML, error) {
+	ct := strings.ToLower(s.contentType)
+	data["contentType"] = ct
+
+	if filepath.Ext(name) == "" {
+		switch {
+		case strings.Contains(ct, "html"):
+			name += ".html"
+		case strings.Contains(ct, "javascript"):
+			name += ".js"
+		case strings.Contains(ct, "markdown"):
+			name += ".md"
+		}
+	}
+
 	source, err := s.TemplatesBox.MustBytes(name)
 	if err != nil {
 		return "", err
 	}
 
-	data["contentType"] = strings.ToLower(s.contentType)
-
 	helpers := map[string]interface{}{
 		"partial": s.partial,
 	}
diff --git a/render/template_test.go b/render/template_test.go
index 06e6a8c2b..a7f3c1680 100644
--- a/render/template_test.go
+++ b/render/template_test.go
@@ -60,20 +60,48 @@ func Test_Template_Partial(t *testing.T) {
 
 	type ji func(string, ...string) render.Renderer
 
-	table := []ji{
-		render.New(render.Options{
-			TemplatesBox: packr.NewBox(tPath),
-		}).Template,
-	}
+	j := render.New(render.Options{
+		TemplatesBox: packr.NewBox(tPath),
+	}).Template
 
-	for _, j := range table {
-		re := j("foo/bar", "index.html")
-		r.Equal("foo/bar", re.ContentType())
-		bb := &bytes.Buffer{}
-		err = re.Render(bb, render.Data{"name": "Mark"})
-		r.NoError(err)
-		r.Equal("Foo > Mark", strings.TrimSpace(bb.String()))
-	}
+	re := j("foo/bar", "index.html")
+	r.Equal("foo/bar", re.ContentType())
+	bb := &bytes.Buffer{}
+	err = re.Render(bb, render.Data{"name": "Mark"})
+	r.NoError(err)
+	r.Equal("Foo > Mark", strings.TrimSpace(bb.String()))
+}
+
+func Test_Template_Partial_WithoutExtension(t *testing.T) {
+	r := require.New(t)
+
+	tPath, err := ioutil.TempDir("", "")
+	r.NoError(err)
+	defer os.Remove(tPath)
+
+	partFile, err := os.Create(filepath.Join(tPath, "_foo.html"))
+	r.NoError(err)
+
+	_, err = partFile.Write([]byte("Foo > <%= name %>"))
+	r.NoError(err)
+
+	tmpFile, err := os.Create(filepath.Join(tPath, "index.html"))
+	r.NoError(err)
+
+	_, err = tmpFile.Write([]byte(`<%= partial("foo") %>`))
+	r.NoError(err)
+
+	type ji func(string, ...string) render.Renderer
+
+	j := render.New(render.Options{
+		TemplatesBox: packr.NewBox(tPath),
+	}).HTML
+
+	re := j("index.html")
+	bb := &bytes.Buffer{}
+	err = re.Render(bb, render.Data{"name": "Mark"})
+	r.NoError(err)
+	r.Equal("Foo > Mark", strings.TrimSpace(bb.String()))
 }
 
 func Test_AssetPath(t *testing.T) {
@@ -101,7 +129,7 @@ func Test_AssetPath(t *testing.T) {
 
 	for original, expected := range cases {
 
-		tmpFile, err := ioutil.TempFile(tdir, "test")
+		tmpFile, err := os.Create(filepath.Join(tdir, "test.html"))
 		r.NoError(err)
 
 		_, err = tmpFile.Write([]byte("<%= assetPath(\"" + original + "\") %>"))
@@ -136,7 +164,7 @@ func Test_AssetPathNoManifest(t *testing.T) {
 
 	for original, expected := range cases {
 
-		tmpFile, err := ioutil.TempFile(tdir, "test")
+		tmpFile, err := os.Create(filepath.Join(tdir, "test.html"))
 		r.NoError(err)
 
 		_, err = tmpFile.Write([]byte("<%= assetPath(\"" + original + "\") %>"))
@@ -171,7 +199,7 @@ func Test_AssetPathManifestCorrupt(t *testing.T) {
 
 	for original, expected := range cases {
 
-		tmpFile, err := ioutil.TempFile(tdir, "test")
+		tmpFile, err := os.Create(filepath.Join(tdir, "test.html"))
 		r.NoError(err)
 
 		_, err = tmpFile.Write([]byte("<%= assetPath(\"" + original + "\") %>"))