diff --git a/HISTORY.md b/HISTORY.md
index 51a3a9af..cd800cb1 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -2,7 +2,13 @@
 
 **How to upgrade**: remove your `$GOPATH/src/github.com/kataras/iris` folder, open your command-line and execute this command: `go get -u github.com/kataras/iris/iris`.
 
-## 4.1.1 -> 4.1.2 
+## 4.1.2 -> 4.1.3
+
+Zero front-end changes. No real improvements, developers can ignore this update.
+
+- Replace the template engines with a new cross-framework package, [go-template](https://github.com/kataras/go-websocket). Same front-end API, examples and iris-contrib/template are compatible.
+
+## 4.1.1 -> 4.1.2
 
 Zero front-end changes. No real improvements, developers can ignore this update.
 
diff --git a/README.md b/README.md
index 0f4ea59e..dd68f077 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@
 
 <a href="https://github.com/kataras/iris/blob/master/LICENSE"><img src="https://img.shields.io/badge/%20license-MIT%20%20License%20-E91E63.svg?style=flat-square" alt="License"></a>
 
-<a href="https://github.com/kataras/iris/releases"><img src="https://img.shields.io/badge/%20release%20-%20v4.1.2%20-blue.svg?style=flat-square" alt="Releases"></a>
+<a href="https://github.com/kataras/iris/releases"><img src="https://img.shields.io/badge/%20release%20-%20v4.1.3%20-blue.svg?style=flat-square" alt="Releases"></a>
 
 <a href="https://www.gitbook.com/book/kataras/iris/details"><img src="https://img.shields.io/badge/%20docs-reference-5272B4.svg?style=flat-square" alt="Practical Guide/Docs"></a><br/>
 
@@ -113,10 +113,11 @@ go-* packages
 
 | Name        | Description           
 | ------------------|:---------------------:|
+| [go-template](https://github.com/kataras/go-template)      | Cross-framework template engines
+| [go-websocket](https://github.com/kataras/go-errors) | A websocket server and ,optionally, client side lib  for Go
 | [go-errors](https://github.com/kataras/go-errors)      | Error handling
 | [go-fs](https://github.com/kataras/go-fs)      | FileSystem utils and common net/http static files handlers  
 | [go-events](https://github.com/kataras/go-events) | EventEmmiter for Go
-| [go-websocket](https://github.com/kataras/go-errors) | A websocket server and ,optionally, client side lib  for Go
 | [go-ssh](https://github.com/kataras/go-ssh) | SSH Server, build ssh interfaces, remote commands and remote cli with ease
 | [go-gzipwriter](https://github.com/kataras/go-gzipwriter) | Write gzip data to a io.Writer
 | [go-mailer](https://github.com/kataras/go-mailer) | E-mail Sender, send rich mails with one call  
@@ -159,7 +160,7 @@ I recommend writing your API tests using this new library, [httpexpect](https://
 Versioning
 ------------
 
-Current: **v4.1.2**
+Current: **v4.1.3**
 
 >  Iris is an active project
 
@@ -194,7 +195,7 @@ License can be found [here](LICENSE).
 [Travis]: http://travis-ci.org/kataras/iris
 [License Widget]: https://img.shields.io/badge/license-MIT%20%20License%20-E91E63.svg?style=flat-square
 [License]: https://github.com/kataras/iris/blob/master/LICENSE
-[Release Widget]: https://img.shields.io/badge/release-v4.1.2-blue.svg?style=flat-square
+[Release Widget]: https://img.shields.io/badge/release-v4.1.3-blue.svg?style=flat-square
 [Release]: https://github.com/kataras/iris/releases
 [Chat Widget]: https://img.shields.io/badge/community-chat-00BCD4.svg?style=flat-square
 [Chat]: https://kataras.rocket.chat/channel/iris
diff --git a/context.go b/context.go
index f9b14eb3..b973d3bd 100644
--- a/context.go
+++ b/context.go
@@ -546,7 +546,7 @@ func (ctx *Context) Gzip(b []byte, status int) {
 func (ctx *Context) RenderWithStatus(status int, name string, binding interface{}, options ...map[string]interface{}) error {
 	ctx.SetStatusCode(status)
 	if strings.IndexByte(name, '.') > -1 { //we have template
-		return ctx.framework.templates.getBy(name).execute(ctx, name, binding, options...)
+		return ctx.framework.templates.render(ctx, name, binding, options...)
 	}
 	return ctx.framework.responses.getBy(name).render(ctx, binding, options...)
 }
diff --git a/iris.go b/iris.go
index aa6dd8f1..48dcd250 100644
--- a/iris.go
+++ b/iris.go
@@ -78,6 +78,7 @@ import (
 	"github.com/iris-contrib/template/html"
 	"github.com/kataras/go-errors"
 	"github.com/kataras/go-fs"
+	"github.com/kataras/go-template"
 	"github.com/kataras/iris/config"
 	"github.com/kataras/iris/context"
 	"github.com/kataras/iris/utils"
@@ -86,7 +87,7 @@ import (
 
 const (
 	// Version of the iris
-	Version = "4.1.2"
+	Version = "4.1.3"
 
 	banner = `         _____      _
         |_   _|    (_)
@@ -155,7 +156,7 @@ type (
 		Close() error
 		UseSessionDB(SessionDatabase)
 		UseResponse(ResponseEngine, ...string) func(string)
-		UseTemplate(TemplateEngine) *TemplateEngineLocation
+		UseTemplate(template.Engine) *template.Loader
 		UseGlobal(...Handler)
 		UseGlobalFunc(...HandlerFunc)
 		Lookup(string) Route
@@ -216,13 +217,10 @@ func New(cfg ...config.Iris) *Framework {
 		// set the plugin container
 		s.Plugins = &pluginContainer{logger: s.Logger}
 		// set the templates
-		s.templates = &templateEngines{
-			helpers: map[string]interface{}{
-				"url":     s.URL,
-				"urlpath": s.Path,
-			},
-			engines: make([]*templateEngineWrapper, 0),
-		}
+		s.templates = newTemplateEngines(map[string]interface{}{
+			"url":     s.URL,
+			"urlpath": s.Path,
+		})
 		// set the sessions
 		if s.Config.Sessions.Cookie != "" {
 			//set the session manager
@@ -270,13 +268,13 @@ func (s *Framework) initialize() {
 	// prepare the templates if enabled
 	if !s.Config.DisableTemplateEngines {
 
-		s.templates.reload = s.Config.IsDevelopment
+		s.templates.Reload = s.Config.IsDevelopment
 		// check and prepare the templates
-		if len(s.templates.engines) == 0 { // no template engine is registered, let's use the default
+		if len(s.templates.Entries) == 0 { // no template engine is registered, let's use the default
 			s.UseTemplate(html.New())
 		}
 
-		if err := s.templates.loadAll(); err != nil {
+		if err := s.templates.Load(); err != nil {
 			s.Logger.Panic(err) // panic on templates loading before listening if we have an error.
 		}
 	}
@@ -661,14 +659,14 @@ func (s *Framework) UseResponse(e ResponseEngine, forContentTypesOrKeys ...strin
 
 // UseTemplate adds a template engine to the iris view system
 // it does not build/load them yet
-func UseTemplate(e TemplateEngine) *TemplateEngineLocation {
+func UseTemplate(e template.Engine) *template.Loader {
 	return Default.UseTemplate(e)
 }
 
 // UseTemplate adds a template engine to the iris view system
 // it does not build/load them yet
-func (s *Framework) UseTemplate(e TemplateEngine) *TemplateEngineLocation {
-	return s.templates.add(e)
+func (s *Framework) UseTemplate(e template.Engine) *template.Loader {
+	return s.templates.AddEngine(e)
 }
 
 // UseGlobal registers Handler middleware  to the beginning, prepends them instead of append
@@ -938,7 +936,8 @@ func (s *Framework) TemplateString(templateFile string, pageContext interface{},
 	if s.Config.DisableTemplateEngines {
 		return ""
 	}
-	res, err := s.templates.getBy(templateFile).executeToString(templateFile, pageContext, options...)
+
+	res, err := s.templates.ExecuteString(templateFile, pageContext, options...)
 	if err != nil {
 		return ""
 	}
diff --git a/iris/create.go b/iris/create.go
index 4f68dd55..f83855e9 100644
--- a/iris/create.go
+++ b/iris/create.go
@@ -9,7 +9,6 @@ import (
 
 	"github.com/kataras/cli"
 	"github.com/kataras/go-fs"
-	"github.com/kataras/go-installer"
 	"github.com/kataras/iris/utils"
 )
 
@@ -86,7 +85,7 @@ func create(flags cli.Flags) (err error) {
 func downloadPackages() {
 	errMsg := "\nProblem while downloading the assets from the internet for the first time. Trace: %s"
 
-	installedDir, err := installer.Install(PackagesURL, packagesInstallDir, true)
+	installedDir, err := fs.Install(PackagesURL, packagesInstallDir, true)
 	if err != nil {
 		printer.Dangerf(errMsg, err.Error())
 		return
diff --git a/plugin.go b/plugin.go
index d2915812..931db534 100644
--- a/plugin.go
+++ b/plugin.go
@@ -7,7 +7,6 @@ import (
 
 	"github.com/iris-contrib/logger"
 	"github.com/kataras/go-fs"
-	"github.com/kataras/go-installer"
 )
 
 var (
@@ -205,12 +204,12 @@ func (d *pluginDownloadManager) DirectoryExists(dir string) bool {
 
 // DownloadZip downlodas a zip to the given local path location
 func (d *pluginDownloadManager) DownloadZip(zipURL string, targetDir string) (string, error) {
-	return installer.DownloadZip(zipURL, targetDir, true)
+	return fs.DownloadZip(zipURL, targetDir, true)
 }
 
 // Unzip unzips a zip to the given local path location
 func (d *pluginDownloadManager) Unzip(archive string, target string) (string, error) {
-	return installer.DownloadZip(archive, target, true)
+	return fs.DownloadZip(archive, target, true)
 }
 
 // Remove deletes/removes/rm a file
@@ -220,7 +219,7 @@ func (d *pluginDownloadManager) Remove(filePath string) error {
 
 // Install is just the flow of the: DownloadZip->Unzip->Remove the zip
 func (d *pluginDownloadManager) Install(remoteFileZip string, targetDirectory string) (string, error) {
-	return installer.Install(remoteFileZip, targetDirectory, true)
+	return fs.Install(remoteFileZip, targetDirectory, true)
 }
 
 // pluginContainer is the base container of all Iris, registed plugins
diff --git a/response.go b/response.go
index 0dc2c0df..46298c12 100644
--- a/response.go
+++ b/response.go
@@ -4,6 +4,7 @@ import (
 	"strings"
 
 	"github.com/kataras/go-errors"
+	"github.com/kataras/go-template"
 	"github.com/valyala/fasthttp"
 )
 
@@ -139,10 +140,8 @@ func (r *responseEngineMap) render(ctx *Context, obj interface{}, options ...map
 	gzipEnabled := ctx.framework.Config.Gzip
 	charset := ctx.framework.Config.Charset
 	if len(options) > 0 {
-		gzipEnabled = getGzipOption(ctx, options[0]) // located to the template.go below the RenderOptions
-		if chs := getCharsetOption(options[0]); chs != "" {
-			charset = chs
-		}
+		gzipEnabled = template.GetGzipOption(gzipEnabled, options[0]) // located to the template.go below the RenderOptions
+		charset = template.GetCharsetOption(charset, options[0])
 	}
 	ctype := r.contentType
 
diff --git a/template.go b/template.go
index fb7e970a..7fd5d7cb 100644
--- a/template.go
+++ b/template.go
@@ -1,192 +1,49 @@
 package iris
 
 import (
+	"github.com/kataras/go-template"
 	"io"
-
-	"path/filepath"
-
-	"github.com/kataras/go-errors"
-	"github.com/kataras/iris/utils"
 )
 
 var (
 	builtinFuncs = [...]string{"url", "urlpath"}
-
-	// DefaultTemplateDirectory the default directory if empty setted
-	DefaultTemplateDirectory = "." + utils.PathSeparator + "templates"
 )
 
 const (
-
-	// DefaultTemplateExtension the default file extension if empty setted
-	DefaultTemplateExtension = ".html"
 	// NoLayout to disable layout for a particular template file
-	NoLayout = "@.|.@iris_no_layout@.|.@"
+	NoLayout = template.NoLayout
 	// TemplateLayoutContextKey is the name of the user values which can be used to set a template layout from a middleware and override the parent's
 	TemplateLayoutContextKey = "templateLayout"
 )
 
 type (
-	// TemplateEngine the interface that all template engines must implement
-	TemplateEngine interface {
-		// LoadDirectory builds the templates, usually by directory and extension but these are engine's decisions
-		LoadDirectory(directory string, extension string) error
-		// LoadAssets loads the templates by binary
-		// assetFn is a func which returns bytes, use it to load the templates by binary
-		// namesFn returns the template filenames
-		LoadAssets(virtualDirectory string, virtualExtension string, assetFn func(name string) ([]byte, error), namesFn func() []string) error
-
-		// ExecuteWriter finds, execute a template and write its result to the out writer
-		// options are the optional runtime options can be passed by user and catched by the template engine when render
-		// an example of this is the "layout" or "gzip" option
-		ExecuteWriter(out io.Writer, name string, binding interface{}, options ...map[string]interface{}) error
-	}
-
-	// TemplateEngineFuncs is optional interface for the TemplateEngine
-	// used to insert the Iris' standard funcs, see var 'usedFuncs'
-	TemplateEngineFuncs interface {
-		// Funcs should returns the context or the funcs,
-		// this property is used in order to register the iris' helper funcs
-		Funcs() map[string]interface{}
-	}
-)
-
-type (
-	// TemplateFuncs is is a helper type for map[string]interface{}
-	TemplateFuncs map[string]interface{}
 	// RenderOptions is a helper type for  the optional runtime options can be passed by user when Render
 	// an example of this is the "layout" or "gzip" option
 	// same as Map but more specific name
 	RenderOptions map[string]interface{}
 )
 
-// IsFree returns true if a function can be inserted to this map
-// return false if this key is already used by Iris
-func (t TemplateFuncs) IsFree(key string) bool {
-	for i := range builtinFuncs {
-		if builtinFuncs[i] == key {
-			return false
-		}
-	}
-	return true
+// templateEngines just a wrapper of template.Mux in order to use it's execute without break the whole of the API
+type templateEngines struct {
+	*template.Mux
 }
 
-func getGzipOption(ctx *Context, options map[string]interface{}) bool {
-	gzipOpt := options["gzip"] // we only need that, so don't create new map to keep the options.
-	if b, isBool := gzipOpt.(bool); isBool {
-		return b
-	}
-	return ctx.framework.Config.Gzip
+func newTemplateEngines(sharedFuncs map[string]interface{}) *templateEngines {
+	return &templateEngines{Mux: template.NewMux(sharedFuncs)}
 }
 
-func getCharsetOption(options map[string]interface{}) string {
-	charsetOpt := options["charset"]
-	if s, isString := charsetOpt.(string); isString {
-		return s
-	}
-	return "" // we return empty in order to set the default charset if not founded.
-}
-
-type (
-	// TemplateEngineLocation contains the funcs to set the location for the templates by directory or by binary
-	TemplateEngineLocation struct {
-		directory string
-		extension string
-		assetFn   func(name string) ([]byte, error)
-		namesFn   func() []string
-	}
-	// TemplateEngineBinaryLocation called after TemplateEngineLocation's Directory, used when files are distrubuted inside the app executable
-	TemplateEngineBinaryLocation struct {
-		location *TemplateEngineLocation
-	}
-)
-
-// Directory sets the directory to load from
-// returns the Binary location which is optional
-func (t *TemplateEngineLocation) Directory(dir string, fileExtension string) *TemplateEngineBinaryLocation {
-	if dir == "" {
-		dir = DefaultTemplateDirectory // the default templates dir
-	}
-	if fileExtension == "" {
-		fileExtension = DefaultTemplateExtension
-	} else if fileExtension[0] != '.' { // if missing the start dot
-		fileExtension = "." + fileExtension
-	}
-
-	t.directory = dir
-	t.extension = fileExtension
-	return &TemplateEngineBinaryLocation{location: t}
-}
-
-// Binary sets the asset(s) and asssets names to load from, works with Directory
-func (t *TemplateEngineBinaryLocation) Binary(assetFn func(name string) ([]byte, error), namesFn func() []string) {
-	if assetFn == nil || namesFn == nil {
-		return
-	}
-
-	t.location.assetFn = assetFn
-	t.location.namesFn = namesFn
-	// if extension is not static(setted by .Directory)
-	if t.location.extension == "" {
-		if names := namesFn(); len(names) > 0 {
-			t.location.extension = filepath.Ext(names[0]) // we need the extension to get the correct template engine on the Render method
-		}
-	}
-}
-
-func (t *TemplateEngineLocation) isBinary() bool {
-	return t.assetFn != nil && t.namesFn != nil
-}
-
-// templateEngineWrapper is the wrapper of a template engine
-type templateEngineWrapper struct {
-	TemplateEngine
-	location *TemplateEngineLocation
-	buffer   *utils.BufferPool
-	reload   bool
-}
-
-var (
-	errMissingDirectoryOrAssets = errors.New("Missing Directory or Assets by binary for the template engine!")
-	errNoTemplateEngineForExt   = errors.New("No template engine found to manage '%s' extensions")
-)
-
-func (t *templateEngineWrapper) load() error {
-	if t.location.isBinary() {
-		t.LoadAssets(t.location.directory, t.location.extension, t.location.assetFn, t.location.namesFn)
-	} else if t.location.directory != "" {
-		t.LoadDirectory(t.location.directory, t.location.extension)
-	} else {
-		return errMissingDirectoryOrAssets
-	}
-	return nil
-}
-
-// execute execute a template and write its result to the context's body
+// render executes a template and write its result to the context's body
 // options are the optional runtime options can be passed by user and catched by the template engine when render
 // an example of this is the "layout"
 // note that gzip option is an iris dynamic option which exists for all template engines
 // the gzip and charset options are built'n with iris
-func (t *templateEngineWrapper) execute(ctx *Context, filename string, binding interface{}, options ...map[string]interface{}) (err error) {
-	if t == nil {
-		//file extension, but no template engine registered, this caused by context, and templateEngines. getBy
-		return errNoTemplateEngineForExt.Format(filepath.Ext(filename))
-	}
-	if t.reload {
-		if err = t.load(); err != nil {
-			return
-		}
-	}
-
+func (t *templateEngines) render(ctx *Context, filename string, binding interface{}, options ...map[string]interface{}) (err error) {
 	// we do all these because we don't want to initialize a new map for each execution...
 	gzipEnabled := ctx.framework.Config.Gzip
 	charset := ctx.framework.Config.Charset
 	if len(options) > 0 {
-		gzipEnabled = getGzipOption(ctx, options[0])
-
-		if chs := getCharsetOption(options[0]); chs != "" {
-			charset = chs
-		}
+		gzipEnabled = template.GetGzipOption(gzipEnabled, options[0])
+		charset = template.GetCharsetOption(charset, options[0])
 	}
 
 	ctxLayout := ctx.GetString(TemplateLayoutContextKey)
@@ -215,88 +72,3 @@ func (t *templateEngineWrapper) execute(ctx *Context, filename string, binding i
 	err = t.ExecuteWriter(out, filename, binding, options...)
 	return err
 }
-
-// executeToString executes a template from a specific template engine and returns its contents result as string, it doesn't renders
-func (t *templateEngineWrapper) executeToString(filename string, binding interface{}, opt ...map[string]interface{}) (result string, err error) {
-	if t == nil {
-		//file extension, but no template engine registered, this caused by context, and templateEngines. getBy
-		return "", errNoTemplateEngineForExt.Format(filepath.Ext(filename))
-	}
-	if t.reload {
-		if err = t.load(); err != nil {
-			return
-		}
-	}
-
-	out := t.buffer.Get()
-	defer t.buffer.Put(out)
-	err = t.ExecuteWriter(out, filename, binding, opt...)
-	if err == nil {
-		result = out.String()
-	}
-	return
-}
-
-// templateEngines is the container and manager of the template engines
-type templateEngines struct {
-	helpers map[string]interface{}
-	engines []*templateEngineWrapper
-	reload  bool
-}
-
-// getBy receives a filename, gets its extension and returns the template engine responsible for that file extension
-func (t *templateEngines) getBy(filename string) *templateEngineWrapper {
-	extension := filepath.Ext(filename)
-	for i, n := 0, len(t.engines); i < n; i++ {
-		e := t.engines[i]
-
-		if e.location.extension == extension {
-			return e
-		}
-	}
-	return nil
-}
-
-// add adds but not loads a template engine
-func (t *templateEngines) add(e TemplateEngine) *TemplateEngineLocation {
-	location := &TemplateEngineLocation{}
-	// add the iris helper funcs
-	if funcer, ok := e.(TemplateEngineFuncs); ok {
-		if funcer.Funcs() != nil {
-			for k, v := range t.helpers {
-				funcer.Funcs()[k] = v
-			}
-		}
-	}
-
-	tmplEngine := &templateEngineWrapper{
-		TemplateEngine: e,
-		location:       location,
-		buffer:         utils.NewBufferPool(8),
-		reload:         t.reload,
-	}
-
-	t.engines = append(t.engines, tmplEngine)
-	return location
-}
-
-// loadAll loads all templates using all template engines, returns the first error
-// called on iris' initialize
-func (t *templateEngines) loadAll() error {
-	for i, n := 0, len(t.engines); i < n; i++ {
-		e := t.engines[i]
-		if e.location.directory == "" {
-			e.location.directory = DefaultTemplateDirectory // the defualt dir ./templates
-		}
-		if e.location.extension == "" {
-			e.location.extension = DefaultTemplateExtension // the default file ext .html
-		}
-
-		e.reload = t.reload // update the configuration every time a load happens
-
-		if err := e.load(); err != nil {
-			return err
-		}
-	}
-	return nil
-}