this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: add embed_assets config option independent of mode

Allow controlling asset embedding separately from the mode setting.
This enables running in development mode (verbose logging, detailed
errors) while still using embedded assets for deployment.

- Add EmbedAssets config field (default: true)
- Update renderer to check EmbedAssets instead of Mode
- Document new setting in README

+31 -14
+16 -2
README.md
··· 108 108 - `TUMBLE_DRIVER=mysql` 109 109 - `TUMBLE_DATABASE=production_db` 110 110 - `TUMBLE_MODE=development` (Options: `development`, `production`. Default: `production`) 111 + - `TUMBLE_EMBED_ASSETS=true` (Options: `true`, `false`. Default: `true`) 111 112 - `TUMBLE_LOGGING_LEVEL=debug` 112 113 113 114 ### Environment Modes (`TUMBLE_MODE`) 114 115 115 116 - **development**: 116 117 - **Logging**: Text format, Debug level, Full SQL query logging. 117 - - **Templates**: Hot-reloading from disk (edit HTML files to see changes immediately). 118 118 - **Errors**: Displays detailed error messages in the browser. 119 119 - **production** (default): 120 120 - **Logging**: JSON format, Info level, Error-only SQL logging. 121 - - **Templates**: Cached in memory for performance. 122 121 - **Errors**: Displays generic "Internal Server Error" message to users. 122 + 123 + ### Asset Embedding (`TUMBLE_EMBED_ASSETS`) 124 + 125 + Controls whether templates and static assets are loaded from the embedded binary or from the filesystem. 126 + 127 + - **true** (default): Assets are loaded from the compiled binary. This is the recommended setting for deployment - you only need the binary and a config file. 128 + - **false**: Assets are loaded from the filesystem (`internal/templates/views/` and `internal/assets/`). Templates are re-parsed on every request, enabling hot-reload during development. 129 + 130 + This setting is independent of `TUMBLE_MODE`, allowing you to run in development mode (for verbose logging and detailed errors) while still using embedded assets for deployment. 131 + 132 + **Deployment Example:** 133 + ```yaml 134 + mode: development # Get detailed error messages and text logging 135 + embed_assets: true # But still use embedded assets (no source checkout needed) 136 + ``` 123 137 124 138 ### 2. Initialize Database 125 139
+2
internal/config/config.go
··· 16 16 Driver string `yaml:"driver" mapstructure:"driver"` 17 17 Port string `yaml:"port" mapstructure:"port"` 18 18 Mode string `yaml:"mode" mapstructure:"mode"` 19 + EmbedAssets bool `yaml:"embed_assets" mapstructure:"embed_assets"` 19 20 ClickSigningKey string `yaml:"click_signing_key" mapstructure:"click_signing_key"` 20 21 Logging Logging `yaml:"logging" mapstructure:"logging"` 21 22 Caching Caching `yaml:"caching" mapstructure:"caching"` ··· 37 38 v.SetDefault("driver", "mysql") 38 39 v.SetDefault("port", "8080") 39 40 v.SetDefault("mode", "production") 41 + v.SetDefault("embed_assets", true) 40 42 v.SetDefault("logging.level", "info") 41 43 v.SetDefault("logging.output", "stdout") 42 44 v.SetDefault("caching.enabled", true)
+13 -12
internal/templates/renderer.go
··· 82 82 83 83 func (r *Renderer) parseTemplates() error { 84 84 var err error 85 - // Determine source: Embed or Filesystem 86 - if r.cfg.Mode == "development" { 87 - // Parse from local filesystem for reload 88 - // Assuming running from project root 89 - r.htmlTmpls, err = template.New("").Funcs(templateFuncs).ParseGlob("internal/templates/views/*.html") 85 + // Determine source: Embed or Filesystem based on embed_assets config 86 + if r.cfg.EmbedAssets { 87 + // Use embedded FS (default for production deployments) 88 + r.htmlTmpls, err = template.New("").Funcs(templateFuncs).ParseFS(viewsFS, "views/*.html") 90 89 if err != nil { 91 90 return err 92 91 } 93 - r.xmlTmpls, err = texttemplate.New("").Funcs(textTemplateFuncs).ParseGlob("internal/templates/views/*.xml") 92 + r.xmlTmpls, err = texttemplate.New("").Funcs(textTemplateFuncs).ParseFS(viewsFS, "views/*.xml") 94 93 if err != nil { 95 94 return err 96 95 } 97 96 } else { 98 - // Use embedded FS for production 99 - r.htmlTmpls, err = template.New("").Funcs(templateFuncs).ParseFS(viewsFS, "views/*.html") 97 + // Parse from local filesystem for hot-reload during development 98 + // Assumes running from project root 99 + r.htmlTmpls, err = template.New("").Funcs(templateFuncs).ParseGlob("internal/templates/views/*.html") 100 100 if err != nil { 101 101 return err 102 102 } 103 - r.xmlTmpls, err = texttemplate.New("").Funcs(textTemplateFuncs).ParseFS(viewsFS, "views/*.xml") 103 + r.xmlTmpls, err = texttemplate.New("").Funcs(textTemplateFuncs).ParseGlob("internal/templates/views/*.xml") 104 104 if err != nil { 105 105 return err 106 106 } ··· 109 109 } 110 110 111 111 func (r *Renderer) Render(w io.Writer, name string, data interface{}) error { 112 - if r.cfg.Mode == "development" { 113 - // Re-parse on every request 112 + if !r.cfg.EmbedAssets { 113 + // Re-parse on every request when using filesystem (for hot-reload) 114 114 if err := r.parseTemplates(); err != nil { 115 115 return err 116 116 } ··· 123 123 } 124 124 125 125 func (r *Renderer) RenderToString(name string, data interface{}) (string, error) { 126 - if r.cfg.Mode == "development" { 126 + if !r.cfg.EmbedAssets { 127 + // Re-parse when using filesystem (for hot-reload) 127 128 if err := r.parseTemplates(); err != nil { 128 129 return "", err 129 130 }