Skip to content

Examples

Confii includes focused runnable examples for individual APIs and workflows. They live in the examples/ directory.

If you are creating an application rather than exploring one isolated feature, start with the Quick Start. It installs the CLI, runs confii init, explains the generated project structure, and uses the same self-configured runtime path recommended for new projects.

For a realistic CRUD application that combines multiple environments, LocalStack-backed cloud configuration, Vault/OpenBao, introspection, Docker, and CLI usage, use the companion confiify/confii-go-examples repository.


Running Examples

cd examples/<name> && go run .

For example:

cd examples/basic && go run .

Check each example's directory

Most examples include a config.yaml or similar file alongside main.go. The example reads from these local files, so always cd into the example directory before running.

If you are new to Confii, run examples in this order:

  1. basic -- plain loading and scalar access.
  2. typed -- Config[T], Typed, and struct tags.
  3. self-config -- zero-code .confii.yaml discovery.
  4. environment -- defaults plus selected environment values.
  5. multi-source -- source precedence.
  6. validation -- reject invalid candidates before publication.
  7. secrets -- eager placeholder resolution with a local store.
  8. lifecycle -- reload, override, freeze, and callbacks.
  9. introspection -- explain where values came from.

For a full application, move next to the companion confii-go-examples repository.

Expected Output Pattern

Most examples print one or more resolved values and then exit. If an example uses an environment selector, run it twice to see the difference:

cd examples/environment
go run .
APP_ENV=production go run .

Use confii plan and confii explain in a self-configured project when you want the exact source order and key provenance.


Getting Started

Example Description Key Concepts
basic Load a YAML file, access values with dot notation New, Get, GetIntOr, GetBoolOr
typed Type-safe Config[T] with struct validation Config[T], Typed(), validate tags
builder Fluent builder pattern for conditional construction NewBuilder, AddLoader, Build
self-config .confii.yaml auto-discovery Self-configuration file

Loading & Merging

Example Description Key Concepts
multi-source Multiple loaders + environment variables WithLoaders, precedence order
environment Environment-aware config (default + production) WithEnv, default section merging
merge-strategies Per-path merge strategies WithMergeStrategyMap, 7 strategies
composition _include and _defaults directives Hydra-style composition, cycle detection
cloud Cloud loaders and secret stores S3, SSM, Azure, GCP, Vault

Cloud and Full Application Examples

The focused examples/cloud directory shows provider APIs in isolation. For a realistic consumer project with Docker Compose, LocalStack, Vault/OpenBao, OIDC, protected APIs, PostgreSQL, and CLI preflights, use the separate confii-go-examples repository. It is the best place to study production-shaped wiring after the core examples make sense.


Processing & Validation

Example Description Key Concepts
hooks Key, value, condition, and global hooks Construction-time hook options, 4 hook types
validation Struct tags + JSON Schema validation WithValidateOnLoad, JSON Schema
secrets Secret resolution with ${secret:key} SecretResolver, DictStore, caching
mixed-secrets Mixed secret backends with environment defaults and explicit routing default_provider, environment_defaults, ${secret@provider:key}

Runtime & Debugging

Example Description Key Concepts
lifecycle Reload, freeze, override, change callbacks Reload, Freeze, Override, OnChange
dynamic-reload File watching with fsnotify WithDynamicReloading, StopWatching
introspection Explain, Layers, source tracking, debug Explain, Layers, PrintDebugInfo
observability Metrics and event emission EnableObservability, EnableEvents
versioning Snapshot, compare, and rollback EnableVersioning, SaveVersion, RollbackToVersion
diff Diff configs and detect drift Diff, DetectDrift, DriftDetector
export Export to JSON/YAML/TOML + doc generation Export, GenerateDocs

Example Walkthroughs

Basic Usage

package main

import (
    "context"
    "fmt"
    "log"

    confii "github.com/confiify/confii-go/v2"
    "github.com/confiify/confii-go/v2/loader"
)

func main() {
    cfg, err := confii.New[any](confii.WithLoaders(
            loader.NewYAML("config.yaml"),
            loader.NewEnvironment("APP"),
        ),
        confii.WithEnv("production"),
    )
    if err != nil {
        log.Fatal(err)
    }

    host, _ := cfg.Get("database.host")
    port := cfg.GetIntOr("database.port", 5432)
    debug := cfg.GetBoolOr("debug", false)

    fmt.Printf("Host: %v, Port: %d, Debug: %v\n", host, port, debug)
    fmt.Printf("All keys: %v\n", cfg.Keys())
}

Type-Safe Config

package main

import (
    "context"
    "fmt"
    "log"

    confii "github.com/confiify/confii-go/v2"
    "github.com/confiify/confii-go/v2/loader"
)

type AppConfig struct {
    Database struct {
        Host string `confii:"host" validate:"required,hostname"`
        Port int    `confii:"port" validate:"required,min=1,max=65535"`
    } `confii:"database"`
    App struct {
        Name  string `confii:"name" validate:"required"`
        Debug bool   `confii:"debug"`
    } `confii:"app"`
}

func main() {
    cfg, err := confii.New[AppConfig](confii.WithLoaders(loader.NewYAML("config.yaml")),
        confii.WithValidateOnLoad(true),
    )
    if err != nil {
        log.Fatal(err)
    }

    model, _ := cfg.Typed()
    fmt.Printf("App: %s\n", model.App.Name)
    fmt.Printf("DB:  %s:%d\n", model.Database.Host, model.Database.Port)
}

Introspection

package main

import (
    "context"
    "fmt"
    "log"

    confii "github.com/confiify/confii-go/v2"
    "github.com/confiify/confii-go/v2/loader"
)

func main() {
    cfg, err := confii.New[any](confii.WithLoaders(
            loader.NewYAML("base.yaml"),
            loader.NewYAML("prod.yaml"),
        ),
        confii.WithEnv("production"),
        confii.WithDebugMode(true),
    )
    if err != nil {
        log.Fatal(err)
    }

    // Explain where a value came from
    info := cfg.Explain("database.host")
    fmt.Printf("database.host = %v (from %s, overridden %v times)\n",
        info["value"], info["source"], info["override_count"])

    // Show all layers
    fmt.Println("\nLayers:")
    for _, l := range cfg.Layers() {
        fmt.Printf("  %s (%s): %d keys\n",
            l["source"], l["loader_type"], l["key_count"])
    }

    // Print full debug info
    fmt.Println("\nDebug Info:")
    fmt.Print(cfg.PrintDebugInfo(""))
}