Quick Start
This page loads a configuration file, layers environment overrides on top, and decodes the result into a struct.
1. Write a config file
Create config.toml next to your program:
# config.toml
addr = "127.0.0.1:8080"
timeout = 15
log_level = "info"
[cache]
enabled = true
size_mb = 64
2. Describe it as a struct
Fields are matched to keys with the flora struct tag. Nested tables map to nested structs.
type Config struct {
Addr string `flora:"addr"`
Timeout int `flora:"timeout"`
LogLevel string `flora:"log_level"`
Cache struct {
Enabled bool `flora:"enabled"`
SizeMB int `flora:"size_mb"`
} `flora:"cache"`
}
3. Load it
Load takes a pointer to your struct and an ordered list of sources. Later sources override earlier ones.
func main() {
var cfg Config
err := flora.Load(&cfg,
flora.File("config.toml"),
flora.Env("APP_"),
)
if err != nil {
log.Fatal(err)
}
log.Printf("listening on %s", cfg.Addr)
}
4. Override from the environment
With the APP_ prefix registered, any matching variable wins over the file. Nested keys use __ as the separator:
APP_ADDR="0.0.0.0:9090" \
APP_CACHE__SIZE_MB=128 \
./myserver
How precedence works
Sources are applied left to right, so
Env overrides File here. See Configuration → Precedence for the full rules.
5. Validate before you trust it
Add lightweight checks with the validate tag, then call Load with WithValidation():
type Config struct {
Addr string `flora:"addr" validate:"required,hostport"`
Timeout int `flora:"timeout" validate:"min=1,max=300"`
}
err := flora.Load(&cfg,
flora.File("config.toml"),
flora.WithValidation(),
)
That is the whole loop: write a file, declare a struct, load, override, validate. Next, read the Configuration guide for source types and decoding details.