{"id":37742786,"url":"https://github.com/darkdarkfruit/templatemanager","last_synced_at":"2026-01-16T14:12:12.929Z","repository":{"id":57552707,"uuid":"129192865","full_name":"darkdarkfruit/templatemanager","owner":"darkdarkfruit","description":"go(golang) template manager, especially for web development","archived":false,"fork":false,"pushed_at":"2020-12-20T03:44:37.000Z","size":186,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-30T01:01:50.829Z","etag":null,"topics":["gin","go","golang","template","template-manager","template-rendering","web","web-development"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/darkdarkfruit.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-04-12T04:28:38.000Z","updated_at":"2025-01-14T06:10:55.000Z","dependencies_parsed_at":"2022-09-26T18:50:50.240Z","dependency_job_id":null,"html_url":"https://github.com/darkdarkfruit/templatemanager","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/darkdarkfruit/templatemanager","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darkdarkfruit%2Ftemplatemanager","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darkdarkfruit%2Ftemplatemanager/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darkdarkfruit%2Ftemplatemanager/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darkdarkfruit%2Ftemplatemanager/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/darkdarkfruit","download_url":"https://codeload.github.com/darkdarkfruit/templatemanager/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darkdarkfruit%2Ftemplatemanager/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28479193,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T11:59:17.896Z","status":"ssl_error","status_checked_at":"2026-01-16T11:55:55.838Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gin","go","golang","template","template-manager","template-rendering","web","web-development"],"created_at":"2026-01-16T14:12:08.933Z","updated_at":"2026-01-16T14:12:12.922Z","avatar_url":"https://github.com/darkdarkfruit.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"Go(Golang) template manager, especially suited for web. Already supports [gin](https://github.com/gin-gonic/gin) server.\n========================================================\n1. [Install](#install)\n2. [Description](#description)\n3. [TemplateEnv](#templateenv)\n4. [Examples](#examples)\n5. [Config Comments](#config-comments)\n6. [Deploy Mode](#deploy-mode)\n7. [Screenshots](#screenshots)\n7. [Benchmark](#benchmark)\n7. [A complete example of gin web server](#a-complete-example-of-gin-web-server.)\n7. [A Complete example of net/http server](#a-complete-example-of-net/http-server)\n7. [Licence](#licence)\n\n\n## Install \ngo get github.com/darkdarkfruit/templatemanager\n\nThen use it:\n```\nimport github.com/darkdarkfruit/templatemanager\n```\n\n\n## Description\nGo(Golang) template manager, especially suited for web. Already supports [gin](https://github.com/gin-gonic/gin) server.\n\nFeatures:\n* support debug mode (Re-render the template when next request comes.)\n* support production mode (Automatically enables template cache.)\n* support context-render (template (nest/inheritance almost))\n* support single file render (the same as html/template)\n* support multiple files render (the same as html/template)\n* support gin-gonic(gin) already\n\n## TemplateEnv\nThere are 2 types of templateEnv(aka: 2 types of templateName). \nDefault is ContextMode which uses template nesting(somewhat like template-inheritance in django/jinja2/...)\n\nContextMode will load context templates, then execute template in file: `FilePathOfBaseRelativeToRoot`.\n\nFilesMode is basically the same as http/template\n\n1. ContextMode: Name starts with \"C-\u003e\" or not starts with \"F-\u003e\"\n```\n\teg: \"C-\u003emain/demo/demo.tpl.html\"\n\t or \"C-\u003e main/demo/demo.tpl.html\" (not: blanks before file(main/demo/demo.tpl.html) will be discarded)\n\t or\t\"main/demo/demo.tpl.html\"\n```\n2. FilesMode:   Name starts with \"F-\u003e\". (default separator of multiple files is \";\")\n```\n\teg: \"F-\u003emain/demo/demo.tpl.html\"\n     or \"F-\u003e main/demo/demo.tpl.html\"\n     or \"F-\u003e main/demo/demo.tpl.html;main/demo/demo_ads.tpl.html\" (will use the first file name when executing template)\n```\n\n## Examples\nSee detailed examples at [examples/](./examples)\n\n### We will use the templates layout below:\n```\n\ntemplates/\n├── context\n│   ├── layout\n│   │   └── layout.tpl.html\n│   └── partial\n│       └── ads.tpl.html\n└── main\n    └── demo\n        ├── demo1.tpl.html\n        ├── demo2.tpl.html\n        └── dir1\n            └── dir2\n                └── any.tpl.html\n\n```\n\n#### A very basic example.\n```\n// use gin as web server\n...\n\nfunc main(){\n    router := gin.Default() // \n    tplMgr := templatemanager.Default(true)\n    tplMgr.Init(true)\n    router.HTMLRender = tplMgr \n}\n\n...\n\t\n```\n\n#### A customized example\n```\n// use gin as web server\n...\n\nfunc main(){\n    router := gin.Default() // \n    tplConfig := templatemanager.DefaultConfig(gin.IsDebugging())\n    tplConfig.DirOfRoot = templatesDir\n    tplConfig.FuncMap = template.FuncMap{\n    \t\"FormatAsDate\":   FormatAsDate,\n    \t\"time_ISOFormat\": TimeISOFormat,\n    \t\"unescaped\":      unescaped,\n    \t}\n    tplMgr := templatemanager.New(tplConfig)\n    tplMgr.Init(true)\n    router.HTMLRender = tplMgr \n}\n\n...\n\t\n```\n\n## Config comments\n``` \ntype TemplateConfig struct {\n\tDirOfRoot                    string           //template root dir\n\tDirOfMainRelativeToRoot      string           //template dir: main\n\tDirOfContextRelativeToRoot   string           //template dir: context\n\tFilePathOfBaseRelativeToRoot string           //template layout file path\n\tExtension                    string           //template extension\n\tFuncMap                      template.FuncMap //template functions\n\tDelims                       Delims           //delimeters\n\n\tIsDebugging bool // true: Show debug info; false: disable debug info and enable cache.\n}\n```\n\n## Deploy mode\n1. debug mode\n``` \nset \"config: IsDebugging\" to true.\neg:\n    templatemanager.Default(true)\n```\n\n2. production mode\n``` \nset \"config: isDebugging\" to false\n    templatemanager.Default(true)\n```\n\n3. set by gin web server\n```\n    templatemanager.Default(gin.IsDebugging()) \n```\n\n\n## Screenshots\n```\nTake examples/gin_web_server as an example\n```\n\n1. demo1\n    ![demo1](examples/gin_web_server/demo1-Screenshot_2018-04-13_16-51-15.jpg)\n1. demo2\n    ![demo2](examples/gin_web_server/demo-2-Screenshot_2018-04-13_16-53-31.jpg)\n1. any file at any depth of main directory\n    ![any file at any depth of main directory](examples/gin_web_server/any-Screenshot_2018-04-13_16-53-53.png)\n\n\n\n## Benchmark\nEnv:\n \n    CPU: (Years ago with very poor performance)AMD Athlon(tm) X4 850 Quad Core Processor\n    MEM: 8G\n\n\n```bash\n# debug-mode\n\u003e wrk -d5 'http://localhost:10000/demo1'\nRunning 5s test @ http://localhost:10000/demo1\n  2 threads and 10 connections\n  Thread Stats   Avg      Stdev     Max   +/- Stdev\n    Latency     4.97ms    5.06ms  50.28ms   86.82%\n    Req/Sec     1.27k   295.83     2.61k    76.00%\n  12695 requests in 5.01s, 53.21MB read\nRequests/sec:   2532.09\nTransfer/sec:     10.61MB\n\n```\n\n```bash\n# production-mode\n\u003e wrk -d5 'http://localhost:10000/demo1'\nRunning 5s test @ http://localhost:10000/demo1\n  2 threads and 10 connections\n  Thread Stats   Avg      Stdev     Max   +/- Stdev\n    Latency     1.21ms    2.32ms  36.00ms   90.58%\n    Req/Sec    10.09k     1.82k   15.99k    70.00%\n  100514 requests in 5.01s, 421.08MB read\nRequests/sec:  20073.50\nTransfer/sec:     84.09MB\n\n```\n\n## A Complete example of net/http server\n```go\npackage main\n\nimport (\n\t\"log\"\n\t\"github.com/darkdarkfruit/templatemanager\"\n\t\"time\"\n\t\"net/http\"\n\t\"html/template\"\n)\n\nvar isDebugging bool\nvar tplMgr *templatemanager.TemplateManager\n\n//func init() {\n//}\n\nfunc time_isoformat(t time.Time) string {\n\treturn t.Format(time.RFC3339)\n}\n\nfunc HomeHandler(w http.ResponseWriter, req *http.Request) {\n\ttplMgr.ExecuteTemplate(w, \"main/home/home.tpl.html\", map[string]interface{}{\n\t\t\"now\": time.Now(),\n\t})\n}\n\nfunc Demo1Handler(w http.ResponseWriter, req *http.Request) {\n\ttplMgr.ExecuteTemplate(w, \"main/demo/demo1.tpl.html\", map[string]interface{}{\n\t\t\"now\": time.Now(),\n\t})\n}\n\nfunc Demo2Handler(w http.ResponseWriter, req *http.Request) {\n\ttplMgr.ExecuteTemplate(w, \"main/demo/demo2.tpl.html\", map[string]interface{}{\n\t\t\"now\": time.Now(),\n\t})\n}\n\nfunc AnyFileHandler(w http.ResponseWriter, req *http.Request) {\n\ttplName := \"main/demo/dir1/dir2/any.tpl.html\"\n\ttplMgr.ExecuteTemplate(w, tplName, map[string]interface{}{\n\t\t\"now\":     time.Now(),\n\t\t\"tplName\": tplName,\n\t})\n}\n\nfunc main() {\n\tlog.SetFlags(log.LstdFlags | log.Lshortfile)\n\tisDebugging = true\n\ttplMgr = templatemanager.Default(isDebugging)\n\ttplMgr.Config.FuncMap = template.FuncMap{\n\t\t\"time_isoformat\": time_isoformat,\n\t}\n\ttplMgr.Init(true)\n\n\tmux := http.NewServeMux()\n\tlog.Printf(\"isDebugging: %v\", isDebugging)\n\n\tmux.HandleFunc(\"/\", HomeHandler)\n\tmux.HandleFunc(\"/demo1\", Demo1Handler)\n\tmux.HandleFunc(\"/demo2\", Demo2Handler)\n\tmux.HandleFunc(\"/any\", AnyFileHandler)\n\n\taddr := \":10001\"\n\thttpAddr := \"http://localhost\" + addr\n\tlog.Printf(\"urls are: \\n%s/ \\n%s/demo1 \\n%s/demo2 \\n%s/any \\n\", httpAddr, httpAddr, httpAddr, httpAddr)\n\tlog.Printf(\"net-http-server is running at %s\", addr)\n\thttp.ListenAndServe(addr, mux)\n}\n\n```\n\n## A complete example of gin web server\n```go\npackage main\n\nimport (\n\t\"log\"\n\t\"github.com/darkdarkfruit/templatemanager\"\n\t\"github.com/gin-gonic/gin\"\n\t\"html/template\"\n\t\"time\"\n\t\"net/http\"\n)\n\nfunc time_isoformat(t time.Time) string {\n\treturn t.Format(time.RFC3339)\n}\n\nfunc HomeHandler(c *gin.Context) {\n\tc.HTML(http.StatusOK, \"main/home/home.tpl.html\", gin.H{\n\t\t\"now\": time.Now(),\n\t})\n}\n\nfunc Demo1Handler(c *gin.Context) {\n\tc.HTML(http.StatusOK, \"main/demo/demo1.tpl.html\", gin.H{\n\t\t\"now\": time.Now(),\n\t})\n}\n\nfunc Demo2Handler(c *gin.Context) {\n\tc.HTML(http.StatusOK, \"main/demo/demo2.tpl.html\", gin.H{\n\t\t\"now\": time.Now(),\n\t})\n}\n\nfunc AnyFileHandler(c *gin.Context) {\n\ttplName := \"main/demo/dir1/dir2/any.tpl.html\"\n\tc.HTML(http.StatusOK, tplName, gin.H{\n\t\t\"now\":     time.Now(),\n\t\t\"tplName\": tplName,\n\t})\n}\n\nfunc main() {\n\tlog.Printf(\"gin mode: %s, isDebugging: %v\", gin.Mode(), gin.IsDebugging())\n\n\trouter := gin.Default()\n\ttplMgr := templatemanager.Default(false)\n\ttplMgr.Config.FuncMap = template.FuncMap{\n\t\t\"time_isoformat\": time_isoformat,\n\t}\n\ttplMgr.Init(true)\n\trouter.HTMLRender = tplMgr\n\n\trouter.GET(\"/\", HomeHandler)\n\trouter.GET(\"/demo1\", Demo1Handler)\n\trouter.GET(\"/demo2\", Demo2Handler)\n\trouter.GET(\"/any\", AnyFileHandler)\n\n\taddr := \":10000\"\n\tlog.Printf(\"gin-web-server is running at %s\", addr)\n\trouter.Run(addr)\n}\n\n```\n## licence\n[MIT licence](./LICENSE)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdarkdarkfruit%2Ftemplatemanager","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdarkdarkfruit%2Ftemplatemanager","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdarkdarkfruit%2Ftemplatemanager/lists"}