[{"data":1,"prerenderedAt":1393},["ShallowReactive",2],{"navigation_docs_en":3,"-en-envconf-overview":441,"-en-envconf-overview-surround":1388},[4,45,60,81,112,129,146,173,197,213,242,279,356,372,384,403,429],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":44},"Getting Started","i-lucide-rocket","\u002Fen\u002Fgetting-started","en\u002F1.getting-started",[10,15,20,24,29,34,39],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fen\u002Fgetting-started\u002Fintroduction","en\u002F1.getting-started\u002F1.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Coming from Laravel","\u002Fen\u002Fgetting-started\u002Fcoming-from-laravel","en\u002F1.getting-started\u002F2.coming-from-laravel","i-lucide-arrow-right-left",{"title":21,"path":22,"stem":23,"icon":19},"Coming from Symfony","\u002Fen\u002Fgetting-started\u002Fcoming-from-symfony","en\u002F1.getting-started\u002F3.coming-from-symfony",{"title":25,"path":26,"stem":27,"icon":28},"Installation","\u002Fen\u002Fgetting-started\u002Finstallation","en\u002F1.getting-started\u002F4.installation","i-lucide-download",{"title":30,"path":31,"stem":32,"icon":33},"Your first module","\u002Fen\u002Fgetting-started\u002Ffirst-module","en\u002F1.getting-started\u002F5.first-module","i-lucide-package-plus",{"title":35,"path":36,"stem":37,"icon":38},"Project structure","\u002Fen\u002Fgetting-started\u002Fproject-structure","en\u002F1.getting-started\u002F6.project-structure","i-lucide-folder-tree",{"title":40,"path":41,"stem":42,"icon":43},"The shop sample application","\u002Fen\u002Fgetting-started\u002Fsample-app","en\u002F1.getting-started\u002F7.sample-app","i-lucide-shopping-cart",false,{"title":46,"icon":47,"path":48,"stem":49,"children":50,"page":44},"queue","i-lucide-layers","\u002Fen\u002Fqueue","en\u002F10.queue",[51,56],{"title":52,"path":53,"stem":54,"icon":55},"Overview","\u002Fen\u002Fqueue\u002Foverview","en\u002F10.queue\u002F1.overview","i-lucide-list-ordered",{"title":57,"path":58,"stem":59,"icon":47},"Tasks","\u002Fen\u002Fqueue\u002Ftasks","en\u002F10.queue\u002F2.tasks",{"title":61,"icon":62,"path":63,"stem":64,"children":65,"page":44},"events","i-lucide-workflow","\u002Fen\u002Fevents","en\u002F11.events",[66,71,76],{"title":67,"path":68,"stem":69,"icon":70},"Events","\u002Fen\u002Fevents\u002Foverview","en\u002F11.events\u002F1.overview","i-lucide-radio",{"title":72,"path":73,"stem":74,"icon":75},"Outbox","\u002Fen\u002Fevents\u002Foutbox","en\u002F11.events\u002F2.outbox","i-lucide-inbox",{"title":77,"path":78,"stem":79,"icon":80},"Scheduling","\u002Fen\u002Fevents\u002Fscheduler","en\u002F11.events\u002F3.scheduler","i-lucide-calendar-clock",{"title":82,"icon":83,"path":84,"stem":85,"children":86,"page":44},"auth","i-lucide-shield-check","\u002Fen\u002Fauth","en\u002F12.auth",[87,92,97,102,107],{"title":88,"path":89,"stem":90,"icon":91},"Authentication","\u002Fen\u002Fauth\u002Foverview","en\u002F12.auth\u002F1.overview","i-lucide-key-round",{"title":93,"path":94,"stem":95,"icon":96},"RBAC","\u002Fen\u002Fauth\u002Frbac","en\u002F12.auth\u002F2.rbac","i-lucide-users",{"title":98,"path":99,"stem":100,"icon":101},"Policies","\u002Fen\u002Fauth\u002Fpolicy","en\u002F12.auth\u002F3.policy","i-lucide-gavel",{"title":103,"path":104,"stem":105,"icon":106},"Using auth standalone","\u002Fen\u002Fauth\u002Fstandalone","en\u002F12.auth\u002F4.standalone","i-lucide-plug",{"title":108,"path":109,"stem":110,"icon":111},"Social login with goth, standalone","\u002Fen\u002Fauth\u002Fsocial-standalone","en\u002F12.auth\u002F5.social-standalone","i-lucide-log-in",{"title":113,"icon":114,"path":115,"stem":116,"children":117,"page":44},"mail","i-lucide-mail","\u002Fen\u002Fmail","en\u002F13.mail",[118,121,125],{"title":52,"path":119,"stem":120,"icon":114},"\u002Fen\u002Fmail\u002Foverview","en\u002F13.mail\u002F1.overview",{"title":122,"path":123,"stem":124,"icon":114},"SMTP","\u002Fen\u002Fmail\u002Fsmtp","en\u002F13.mail\u002F2.smtp",{"title":126,"path":127,"stem":128,"icon":114},"MJML","\u002Fen\u002Fmail\u002Fmjml","en\u002F13.mail\u002F3.mjml",{"title":130,"icon":131,"path":132,"stem":133,"children":134,"page":44},"notify","i-lucide-bell","\u002Fen\u002Fnotify","en\u002F14.notify",[135,138,142],{"title":52,"path":136,"stem":137,"icon":131},"\u002Fen\u002Fnotify\u002Foverview","en\u002F14.notify\u002F1.overview",{"title":139,"path":140,"stem":141,"icon":131},"Database channel","\u002Fen\u002Fnotify\u002Fdatabase","en\u002F14.notify\u002F2.database",{"title":143,"path":144,"stem":145,"icon":131},"Broadcast channel","\u002Fen\u002Fnotify\u002Fbroadcast","en\u002F14.notify\u002F3.broadcast",{"title":147,"icon":148,"path":149,"stem":150,"children":151,"page":44},"storage","i-lucide-hard-drive","\u002Fen\u002Fstorage","en\u002F15.storage",[152,155,159,163,168],{"title":52,"path":153,"stem":154,"icon":148},"\u002Fen\u002Fstorage\u002Foverview","en\u002F15.storage\u002F1.overview",{"title":156,"path":157,"stem":158},"Disk API","\u002Fen\u002Fstorage\u002Fdisk-api","en\u002F15.storage\u002F2.disk-api",{"title":160,"path":161,"stem":162,"icon":148},"Memory and local disk","\u002Fen\u002Fstorage\u002Flocal","en\u002F15.storage\u002F3.local",{"title":164,"path":165,"stem":166,"icon":167},"S3","\u002Fen\u002Fstorage\u002Fs3","en\u002F15.storage\u002F4.s3","i-lucide-cloud",{"title":169,"path":170,"stem":171,"icon":172},"Testing","\u002Fen\u002Fstorage\u002Ftesting","en\u002F15.storage\u002F5.testing","i-lucide-flask-conical",{"title":174,"icon":175,"path":176,"stem":177,"children":178,"page":44},"telemetry","i-lucide-activity","\u002Fen\u002Ftelemetry","en\u002F16.telemetry",[179,182,187,192],{"title":52,"path":180,"stem":181,"icon":175},"\u002Fen\u002Ftelemetry\u002Foverview","en\u002F16.telemetry\u002F1.overview",{"title":183,"path":184,"stem":185,"icon":186},"Logging","\u002Fen\u002Ftelemetry\u002Flogging","en\u002F16.telemetry\u002F2.logging","i-lucide-scroll-text",{"title":188,"path":189,"stem":190,"icon":191},"OpenTelemetry","\u002Fen\u002Ftelemetry\u002Fopentelemetry","en\u002F16.telemetry\u002F3.opentelemetry","i-lucide-radar",{"title":193,"path":194,"stem":195,"icon":196},"Sentry","\u002Fen\u002Ftelemetry\u002Fsentry","en\u002F16.telemetry\u002F4.sentry","i-lucide-bug",{"title":198,"icon":199,"path":200,"stem":201,"children":202,"page":44},"Reference","i-lucide-book-open","\u002Fen\u002Freference","en\u002F17.reference",[203,208],{"title":204,"path":205,"stem":206,"icon":207},"Configuration","\u002Fen\u002Freference\u002Fconfiguration","en\u002F17.reference\u002F1.configuration","i-lucide-settings",{"title":209,"path":210,"stem":211,"icon":212},"External dependencies","\u002Fen\u002Freference\u002Fdependencies","en\u002F17.reference\u002F2.dependencies","i-lucide-package",{"title":214,"icon":215,"path":216,"stem":217,"children":218,"page":44},"Concepts","i-lucide-lightbulb","\u002Fen\u002Fconcepts","en\u002F2.concepts",[219,223,228,232,237],{"title":220,"path":221,"stem":222,"icon":47},"Architecture","\u002Fen\u002Fconcepts\u002Farchitecture","en\u002F2.concepts\u002F1.architecture",{"title":224,"path":225,"stem":226,"icon":227},"Error model","\u002Fen\u002Fconcepts\u002Ferror-model","en\u002F2.concepts\u002F2.error-model","i-lucide-shield-alert",{"title":204,"path":229,"stem":230,"icon":231},"\u002Fen\u002Fconcepts\u002Fconfiguration","en\u002F2.concepts\u002F3.configuration","i-lucide-settings-2",{"title":233,"path":234,"stem":235,"icon":236},"Codegen pipeline","\u002Fen\u002Fconcepts\u002Fcodegen-pipeline","en\u002F2.concepts\u002F4.codegen-pipeline","i-lucide-file-json",{"title":238,"path":239,"stem":240,"icon":241},"Design patterns","\u002Fen\u002Fconcepts\u002Fdesign-patterns","en\u002F2.concepts\u002F5.design-patterns","i-lucide-puzzle",{"title":243,"icon":244,"path":245,"stem":246,"children":247,"page":44},"Kit","i-lucide-box","\u002Fen\u002Fkit","en\u002F3.kit",[248,251,256,261,266,270,275],{"title":52,"path":249,"stem":250,"icon":244},"\u002Fen\u002Fkit\u002Foverview","en\u002F3.kit\u002F1.overview",{"title":252,"path":253,"stem":254,"icon":255},"Application lifecycle","\u002Fen\u002Fkit\u002Fapp","en\u002F3.kit\u002F2.app","i-lucide-power",{"title":257,"path":258,"stem":259,"icon":260},"Server","\u002Fen\u002Fkit\u002Fserver","en\u002F3.kit\u002F3.server","i-lucide-server",{"title":262,"path":263,"stem":264,"icon":265},"Worker","\u002Fen\u002Fkit\u002Fworker","en\u002F3.kit\u002F4.worker","i-lucide-cog",{"title":267,"path":268,"stem":269,"icon":70},"Realtime","\u002Fen\u002Fkit\u002Frealtime","en\u002F3.kit\u002F5.realtime",{"title":271,"path":272,"stem":273,"icon":274},"Migrations","\u002Fen\u002Fkit\u002Fmigrations","en\u002F3.kit\u002F6.migrations","i-lucide-file-stack",{"title":276,"path":277,"stem":278,"icon":111},"Social login","\u002Fen\u002Fkit\u002Fsocial-login","en\u002F3.kit\u002F7.social-login",{"title":280,"icon":281,"path":282,"stem":283,"children":284,"page":44},"CLI Reference","i-lucide-terminal","\u002Fen\u002Fcli","en\u002F4.cli",[285,288,293,298,303,308,313,318,323,328,333,337,342,347,351],{"title":52,"path":286,"stem":287,"icon":281},"\u002Fen\u002Fcli\u002Foverview","en\u002F4.cli\u002F1.overview",{"title":289,"path":290,"stem":291,"icon":292},"add db","\u002Fen\u002Fcli\u002Fadd-db","en\u002F4.cli\u002F10.add-db","i-lucide-database-zap",{"title":294,"path":295,"stem":296,"icon":297},"add compose \u002F add docker","\u002Fen\u002Fcli\u002Fadd-compose","en\u002F4.cli\u002F11.add-compose","i-lucide-container",{"title":299,"path":300,"stem":301,"icon":302},"add mail","\u002Fen\u002Fcli\u002Fadd-mail","en\u002F4.cli\u002F12.add-mail","i-lucide-mail-plus",{"title":304,"path":305,"stem":306,"icon":307},"add notification","\u002Fen\u002Fcli\u002Fadd-notification","en\u002F4.cli\u002F13.add-notification","i-lucide-bell-plus",{"title":309,"path":310,"stem":311,"icon":312},"add realtime","\u002Fen\u002Fcli\u002Fadd-realtime","en\u002F4.cli\u002F14.add-realtime","i-lucide-radio-tower",{"title":314,"path":315,"stem":316,"icon":317},"add seeder","\u002Fen\u002Fcli\u002Fadd-seeder","en\u002F4.cli\u002F15.add-seeder","i-lucide-sprout",{"title":319,"path":320,"stem":321,"icon":322},"new project","\u002Fen\u002Fcli\u002Fnew-project","en\u002F4.cli\u002F2.new-project","i-lucide-folder-plus",{"title":324,"path":325,"stem":326,"icon":327},"new module","\u002Fen\u002Fcli\u002Fnew-module","en\u002F4.cli\u002F3.new-module","i-lucide-blocks",{"title":329,"path":330,"stem":331,"icon":332},"add surface","\u002Fen\u002Fcli\u002Fadd-surface","en\u002F4.cli\u002F4.add-surface","i-lucide-layers-2",{"title":334,"path":335,"stem":336,"icon":244},"add core","\u002Fen\u002Fcli\u002Fadd-core","en\u002F4.cli\u002F5.add-core",{"title":338,"path":339,"stem":340,"icon":341},"add handler","\u002Fen\u002Fcli\u002Fadd-handler","en\u002F4.cli\u002F6.add-handler","i-lucide-webhook",{"title":343,"path":344,"stem":345,"icon":346},"new migration","\u002Fen\u002Fcli\u002Fnew-migration","en\u002F4.cli\u002F7.new-migration","i-lucide-file-plus",{"title":348,"path":349,"stem":350,"icon":265},"worker generators","\u002Fen\u002Fcli\u002Fworker-generators","en\u002F4.cli\u002F8.worker-generators",{"title":352,"path":353,"stem":354,"icon":355},"upgrade templates","\u002Fen\u002Fcli\u002Fupgrade-templates","en\u002F4.cli\u002F9.upgrade-templates","i-lucide-refresh-cw",{"title":357,"icon":227,"path":358,"stem":359,"children":360,"page":44},"errs","\u002Fen\u002Ferrs","en\u002F5.errs",[361,364,368],{"title":52,"path":362,"stem":363,"icon":227},"\u002Fen\u002Ferrs\u002Foverview","en\u002F5.errs\u002F1.overview",{"title":365,"path":366,"stem":367},"API","\u002Fen\u002Ferrs\u002Fapi","en\u002F5.errs\u002F2.api",{"title":369,"path":370,"stem":371,"icon":227},"Integration","\u002Fen\u002Ferrs\u002Fintegration","en\u002F5.errs\u002F3.integration",{"title":373,"icon":231,"path":374,"stem":375,"children":376,"page":44},"envconf","\u002Fen\u002Fenvconf","en\u002F6.envconf",[377,380],{"title":52,"path":378,"stem":379,"icon":231},"\u002Fen\u002Fenvconf\u002Foverview","en\u002F6.envconf\u002F1.overview",{"title":381,"path":382,"stem":383},"Recipes","\u002Fen\u002Fenvconf\u002Frecipes","en\u002F6.envconf\u002F2.recipes",{"title":385,"icon":386,"path":387,"stem":388,"children":389,"page":44},"httperr","i-lucide-globe","\u002Fen\u002Fhttperr","en\u002F7.httperr",[390,393,398],{"title":52,"path":391,"stem":392,"icon":386},"\u002Fen\u002Fhttperr\u002Foverview","en\u002F7.httperr\u002F1.overview",{"title":394,"path":395,"stem":396,"icon":397},"Error responses","\u002Fen\u002Fhttperr\u002Ferror-responses","en\u002F7.httperr\u002F2.error-responses","i-lucide-octagon-alert",{"title":399,"path":400,"stem":401,"icon":402},"Validation","\u002Fen\u002Fhttperr\u002Fvalidation","en\u002F7.httperr\u002F3.validation","i-lucide-badge-check",{"title":404,"icon":405,"path":406,"stem":407,"children":408,"page":44},"dbx","i-lucide-database","\u002Fen\u002Fdbx","en\u002F8.dbx",[409,412,416,420,425],{"title":52,"path":410,"stem":411,"icon":405},"\u002Fen\u002Fdbx\u002Foverview","en\u002F8.dbx\u002F1.overview",{"title":413,"path":414,"stem":415,"icon":106},"pgx","\u002Fen\u002Fdbx\u002Fpg","en\u002F8.dbx\u002F2.pg",{"title":417,"path":418,"stem":419,"icon":47},"bun","\u002Fen\u002Fdbx\u002Fbunx","en\u002F8.dbx\u002F3.bunx",{"title":421,"path":422,"stem":423,"icon":424},"Transactions","\u002Fen\u002Fdbx\u002Ftransactions","en\u002F8.dbx\u002F4.transactions","i-lucide-git-merge",{"title":426,"path":427,"stem":428,"icon":317},"Seeders","\u002Fen\u002Fdbx\u002Fseed","en\u002F8.dbx\u002F5.seed",{"title":430,"icon":55,"path":431,"stem":432,"children":433,"page":44},"paginate","\u002Fen\u002Fpaginate","en\u002F9.paginate",[434,437],{"title":52,"path":435,"stem":436,"icon":55},"\u002Fen\u002Fpaginate\u002Foverview","en\u002F9.paginate\u002F1.overview",{"title":438,"path":439,"stem":440,"icon":19},"Cursor pagination","\u002Fen\u002Fpaginate\u002Fcursor","en\u002F9.paginate\u002F2.cursor",{"id":442,"title":52,"body":443,"description":1381,"extension":1382,"links":1383,"meta":1384,"navigation":1385,"path":378,"seo":1386,"stem":379,"__hash__":1387},"docs_en\u002Fen\u002F6.envconf\u002F1.overview.md",{"type":444,"value":445,"toc":1373},"minimark",[446,489,494,533,543,547,644,668,779,792,870,874,887,965,994,998,1025,1058,1064,1068,1294,1320,1340,1344,1369],[447,448,449,452,453,456,457,460,461,470,471,478,479,481,482,485,486,488],"p",{},[450,451,373],"code",{}," is a standalone Go module (",[450,454,455],{},"github.com\u002Fgp-system\u002Fenvconf","): typed configuration loaded from environment variables into a Go struct, once, at process start, with an optional ",[450,458,459],{},".env"," file for local development. It has two dependencies, ",[462,463,467],"a",{"href":464,"rel":465},"https:\u002F\u002Fgithub.com\u002Fcaarlos0\u002Fenv",[466],"nofollow",[450,468,469],{},"caarlos0\u002Fenv"," (the struct-tag parser) and ",[462,472,475],{"href":473,"rel":474},"https:\u002F\u002Fgithub.com\u002Fjoho\u002Fgodotenv",[466],[450,476,477],{},"joho\u002Fgodotenv"," (",[450,480,459],{}," file loading), and no gp-system-specific knowledge: it works the same way in any Go program. The gpsystem kit uses it as the single loading step every generated project runs in ",[450,483,484],{},"main()","; see ",[462,487,204],{"href":229}," for how a project composes a dozen modules' worth of settings into one struct with it.",[490,491,493],"h2",{"id":492},"install","Install",[495,496,501],"pre",{"className":497,"code":498,"language":499,"meta":500,"style":500},"language-sh shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","go get github.com\u002Fgp-system\u002Fenvconf@v0.1.0 # the kit itself uses this tag\ngo get github.com\u002Fgp-system\u002Fenvconf@latest\n","sh","",[450,502,503,523],{"__ignoreMap":500},[504,505,508,512,516,519],"span",{"class":506,"line":507},"line",1,[504,509,511],{"class":510},"sBMFI","go",[504,513,515],{"class":514},"sfazB"," get",[504,517,518],{"class":514}," github.com\u002Fgp-system\u002Fenvconf@v0.1.0",[504,520,522],{"class":521},"sHwdD"," # the kit itself uses this tag\n",[504,524,526,528,530],{"class":506,"line":525},2,[504,527,511],{"class":510},[504,529,515],{"class":514},[504,531,532],{"class":514}," github.com\u002Fgp-system\u002Fenvconf@latest\n",[447,534,535,536,539,540,542],{},"Go 1.25+. Dependency footprint: ",[450,537,538],{},"caarlos0\u002Fenv\u002Fv11"," and ",[450,541,477],{},", nothing else.",[490,544,546],{"id":545},"load-mustload-loadprefixed","Load, MustLoad, LoadPrefixed",[495,548,551],{"className":549,"code":550,"language":511,"meta":500,"style":500},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","func Load[T any]() (T, error)\nfunc MustLoad[T any]() T\nfunc LoadPrefixed[T any](prefix string) (T, error)\n",[450,552,553,590,608],{"__ignoreMap":500},[504,554,555,559,563,566,570,573,576,578,580,583,587],{"class":506,"line":507},[504,556,558],{"class":557},"sMK4o","func",[504,560,562],{"class":561},"s2Zo4"," Load",[504,564,565],{"class":557},"[",[504,567,569],{"class":568},"sHdIc","T",[504,571,572],{"class":510}," any",[504,574,575],{"class":557},"]()",[504,577,478],{"class":557},[504,579,569],{"class":510},[504,581,582],{"class":557},",",[504,584,586],{"class":585},"spNyl"," error",[504,588,589],{"class":557},")\n",[504,591,592,594,597,599,601,603,605],{"class":506,"line":525},[504,593,558],{"class":557},[504,595,596],{"class":561}," MustLoad",[504,598,565],{"class":557},[504,600,569],{"class":568},[504,602,572],{"class":510},[504,604,575],{"class":557},[504,606,607],{"class":510}," T\n",[504,609,611,613,616,618,620,622,625,628,631,634,636,638,640,642],{"class":506,"line":610},3,[504,612,558],{"class":557},[504,614,615],{"class":561}," LoadPrefixed",[504,617,565],{"class":557},[504,619,569],{"class":568},[504,621,572],{"class":510},[504,623,624],{"class":557},"](",[504,626,627],{"class":568},"prefix",[504,629,630],{"class":585}," string",[504,632,633],{"class":557},")",[504,635,478],{"class":557},[504,637,569],{"class":510},[504,639,582],{"class":557},[504,641,586],{"class":585},[504,643,589],{"class":557},[447,645,646,649,650,652,653,656,657,660,661,664,665,667],{},[450,647,648],{},"Load"," parses environment variables into a new ",[450,651,569],{},", following ",[450,654,655],{},"env:\"...\""," struct tags, and returns the populated value or an error (a missing ",[450,658,659],{},"required"," variable, a value that doesn't parse into the field's type). ",[450,662,663],{},"MustLoad"," is the same, but panics instead of returning an error: the form you actually want at the top of ",[450,666,484],{},", where there is nothing meaningful to do with a configuration error except fail fast and loudly.",[495,669,671],{"className":549,"code":670,"language":511,"meta":500,"style":500},"type Config struct {\n    ListenAddr string        `env:\"LISTEN_ADDR\" envDefault:\":3000\"`\n    DBHost     string        `env:\"DB_HOST,required\"`\n    Timeout    time.Duration `env:\"TIMEOUT\" envDefault:\"5s\"`\n}\n\ncfg := envconf.MustLoad[Config]()\n",[450,672,673,687,705,719,742,748,755],{"__ignoreMap":500},[504,674,675,678,681,684],{"class":506,"line":507},[504,676,677],{"class":557},"type",[504,679,680],{"class":510}," Config",[504,682,683],{"class":557}," struct",[504,685,686],{"class":557}," {\n",[504,688,689,693,696,699,702],{"class":506,"line":525},[504,690,692],{"class":691},"sTEyZ","    ListenAddr ",[504,694,695],{"class":585},"string",[504,697,698],{"class":557},"        `",[504,700,701],{"class":514},"env:\"LISTEN_ADDR\" envDefault:\":3000\"",[504,703,704],{"class":557},"`\n",[504,706,707,710,712,714,717],{"class":506,"line":610},[504,708,709],{"class":691},"    DBHost     ",[504,711,695],{"class":585},[504,713,698],{"class":557},[504,715,716],{"class":514},"env:\"DB_HOST,required\"",[504,718,704],{"class":557},[504,720,722,725,728,731,734,737,740],{"class":506,"line":721},4,[504,723,724],{"class":691},"    Timeout    ",[504,726,727],{"class":510},"time",[504,729,730],{"class":557},".",[504,732,733],{"class":510},"Duration",[504,735,736],{"class":557}," `",[504,738,739],{"class":514},"env:\"TIMEOUT\" envDefault:\"5s\"",[504,741,704],{"class":557},[504,743,745],{"class":506,"line":744},5,[504,746,747],{"class":557},"}\n",[504,749,751],{"class":506,"line":750},6,[504,752,754],{"emptyLinePlaceholder":753},true,"\n",[504,756,758,761,764,767,769,771,773,776],{"class":506,"line":757},7,[504,759,760],{"class":691},"cfg ",[504,762,763],{"class":557},":=",[504,765,766],{"class":691}," envconf",[504,768,730],{"class":557},[504,770,663],{"class":561},[504,772,565],{"class":557},[504,774,775],{"class":510},"Config",[504,777,778],{"class":557},"]()\n",[447,780,781,784,785,787,788,791],{},[450,782,783],{},"LoadPrefixed"," is ",[450,786,648],{}," with every field's env variable additionally prefixed, useful when the same config shape needs to be loaded more than once under different names (see ",[462,789,381],{"href":790},"\u002Fen\u002Fenvconf\u002Frecipes#prefixed-multi-instance-loads"," for a two-Valkey-connections example):",[495,793,795],{"className":549,"code":794,"language":511,"meta":500,"style":500},"primary, err := envconf.LoadPrefixed[ValkeyConfig](\"PRIMARY_\")   \u002F\u002F PRIMARY_ADDR, PRIMARY_PASSWORD, ...\nreplica, err := envconf.LoadPrefixed[ValkeyConfig](\"REPLICA_\")   \u002F\u002F REPLICA_ADDR, REPLICA_PASSWORD, ...\n",[450,796,797,835],{"__ignoreMap":500},[504,798,799,802,804,807,809,811,813,815,817,820,822,825,828,830,832],{"class":506,"line":507},[504,800,801],{"class":691},"primary",[504,803,582],{"class":557},[504,805,806],{"class":691}," err ",[504,808,763],{"class":557},[504,810,766],{"class":691},[504,812,730],{"class":557},[504,814,783],{"class":561},[504,816,565],{"class":557},[504,818,819],{"class":510},"ValkeyConfig",[504,821,624],{"class":557},[504,823,824],{"class":557},"\"",[504,826,827],{"class":514},"PRIMARY_",[504,829,824],{"class":557},[504,831,633],{"class":557},[504,833,834],{"class":521},"   \u002F\u002F PRIMARY_ADDR, PRIMARY_PASSWORD, ...\n",[504,836,837,840,842,844,846,848,850,852,854,856,858,860,863,865,867],{"class":506,"line":525},[504,838,839],{"class":691},"replica",[504,841,582],{"class":557},[504,843,806],{"class":691},[504,845,763],{"class":557},[504,847,766],{"class":691},[504,849,730],{"class":557},[504,851,783],{"class":561},[504,853,565],{"class":557},[504,855,819],{"class":510},[504,857,624],{"class":557},[504,859,824],{"class":557},[504,861,862],{"class":514},"REPLICA_",[504,864,824],{"class":557},[504,866,633],{"class":557},[504,868,869],{"class":521},"   \u002F\u002F REPLICA_ADDR, REPLICA_PASSWORD, ...\n",[490,871,873],{"id":872},"tags-and-defaults","Tags and defaults",[447,875,876,877,880,881,883,884,886],{},"The parsing itself is ",[462,878,469],{"href":464,"rel":879},[466],"'s: ",[450,882,373],{}," adds the ",[450,885,459],{}," loading step in front of it, nothing more. The tags that matter day to day:",[888,889,890,903],"table",{},[891,892,893],"thead",{},[894,895,896,900],"tr",{},[897,898,899],"th",{},"Tag",[897,901,902],{},"Meaning",[904,905,906,917,933,945,955],"tbody",{},[894,907,908,914],{},[909,910,911],"td",{},[450,912,913],{},"env:\"NAME\"",[909,915,916],{},"the environment variable to read",[894,918,919,924],{},[909,920,921],{},[450,922,923],{},"env:\"NAME,required\"",[909,925,926,927,929,930,932],{},"fails ",[450,928,648],{},"\u002F",[450,931,663],{}," if the variable is unset",[894,934,935,940],{},[909,936,937],{},[450,938,939],{},"envDefault:\"value\"",[909,941,942,943,633],{},"used when the variable is unset (and not ",[450,944,659],{},[894,946,947,952],{},[909,948,949],{},[450,950,951],{},"envPrefix:\"DB_\"",[909,953,954],{},"on a nested struct field, prefixes every one of its own tags",[894,956,957,962],{},[909,958,959],{},[450,960,961],{},"envSeparator:\",\"",[909,963,964],{},"for slice fields, the separator between values",[447,966,967,968,970,971,970,974,970,977,970,980,983,984,987,988,990,991,993],{},"Field types follow Go's usual parsing: ",[450,969,695],{},", ",[450,972,973],{},"int",[450,975,976],{},"bool",[450,978,979],{},"time.Duration",[450,981,982],{},"[]string",", and anything implementing ",[450,985,986],{},"encoding.TextUnmarshaler",". A ",[450,989,659],{}," field with no default and no value set is exactly the failure ",[450,992,648],{}," is supposed to catch before the process finishes booting, not on the first request that touches it.",[490,995,997],{"id":996},"env-loading",".env loading",[447,999,1000,1001,929,1003,929,1005,1007,1008,1010,1011,1015,1016,1018,1019,1021,1022,1024],{},"Before parsing, ",[450,1002,648],{},[450,1004,663],{},[450,1006,783],{}," load a ",[450,1009,459],{}," file from the working directory via godotenv, ",[1012,1013,1014],"strong",{},"best-effort",": a missing ",[450,1017,459],{}," file is not an error. Crucially, godotenv never overrides a variable that's already set in the process environment, so ",[450,1020,459],{}," only fills in gaps, it never shadows a value the real environment already provided. That single rule is what lets the same ",[450,1023,775],{}," struct behave correctly everywhere:",[1026,1027,1028,1037,1049],"ul",{},[1029,1030,1031,1034,1035,730],"li",{},[1012,1032,1033],{},"Local development",", with nothing exported in the shell: every value comes from ",[450,1036,459],{},[1029,1038,1039,1042,1043,1045,1046,730],{},[1012,1040,1041],{},"A docker-compose dev stack",": the same ",[450,1044,459],{}," file, service hostnames resolving to the compose network instead of ",[450,1047,1048],{},"localhost",[1029,1050,1051,1054,1055,1057],{},[1012,1052,1053],{},"Staging\u002Fproduction",": the real environment (systemd, a Kubernetes ConfigMap\u002FSecret) sets variables directly; ",[450,1056,459],{}," is typically absent, and even if a stray one were present, the already-set variables win regardless.",[447,1059,1060,1061,1063],{},"This makes ",[450,1062,459],{}," purely a developer convenience: nothing about how the config loads changes between environments, only what's providing the values.",[490,1065,1067],{"id":1066},"standalone-example","Standalone example",[495,1069,1072],{"className":549,"code":1070,"filename":1071,"language":511,"meta":500,"style":500},"package main\n\nimport (\n    \"fmt\"\n    \"time\"\n\n    \"github.com\u002Fgp-system\u002Fenvconf\"\n)\n\ntype Config struct {\n    ListenAddr string        `env:\"LISTEN_ADDR\" envDefault:\":3000\"`\n    APIKey     string        `env:\"API_KEY,required\"`\n    Timeout    time.Duration `env:\"TIMEOUT\" envDefault:\"5s\"`\n}\n\nfunc main() {\n    cfg := envconf.MustLoad[Config]()\n    fmt.Printf(\"listening on %s, timeout %s\\n\", cfg.ListenAddr, cfg.Timeout)\n}\n","main.go",[450,1073,1074,1082,1086,1095,1106,1114,1118,1126,1131,1136,1147,1160,1175,1192,1197,1202,1215,1235,1289],{"__ignoreMap":500},[504,1075,1076,1079],{"class":506,"line":507},[504,1077,1078],{"class":557},"package",[504,1080,1081],{"class":510}," main\n",[504,1083,1084],{"class":506,"line":525},[504,1085,754],{"emptyLinePlaceholder":753},[504,1087,1088,1092],{"class":506,"line":610},[504,1089,1091],{"class":1090},"s7zQu","import",[504,1093,1094],{"class":557}," (\n",[504,1096,1097,1100,1103],{"class":506,"line":721},[504,1098,1099],{"class":557},"    \"",[504,1101,1102],{"class":510},"fmt",[504,1104,1105],{"class":557},"\"\n",[504,1107,1108,1110,1112],{"class":506,"line":744},[504,1109,1099],{"class":557},[504,1111,727],{"class":510},[504,1113,1105],{"class":557},[504,1115,1116],{"class":506,"line":750},[504,1117,754],{"emptyLinePlaceholder":753},[504,1119,1120,1122,1124],{"class":506,"line":757},[504,1121,1099],{"class":557},[504,1123,455],{"class":510},[504,1125,1105],{"class":557},[504,1127,1129],{"class":506,"line":1128},8,[504,1130,589],{"class":557},[504,1132,1134],{"class":506,"line":1133},9,[504,1135,754],{"emptyLinePlaceholder":753},[504,1137,1139,1141,1143,1145],{"class":506,"line":1138},10,[504,1140,677],{"class":557},[504,1142,680],{"class":510},[504,1144,683],{"class":557},[504,1146,686],{"class":557},[504,1148,1150,1152,1154,1156,1158],{"class":506,"line":1149},11,[504,1151,692],{"class":691},[504,1153,695],{"class":585},[504,1155,698],{"class":557},[504,1157,701],{"class":514},[504,1159,704],{"class":557},[504,1161,1163,1166,1168,1170,1173],{"class":506,"line":1162},12,[504,1164,1165],{"class":691},"    APIKey     ",[504,1167,695],{"class":585},[504,1169,698],{"class":557},[504,1171,1172],{"class":514},"env:\"API_KEY,required\"",[504,1174,704],{"class":557},[504,1176,1178,1180,1182,1184,1186,1188,1190],{"class":506,"line":1177},13,[504,1179,724],{"class":691},[504,1181,727],{"class":510},[504,1183,730],{"class":557},[504,1185,733],{"class":510},[504,1187,736],{"class":557},[504,1189,739],{"class":514},[504,1191,704],{"class":557},[504,1193,1195],{"class":506,"line":1194},14,[504,1196,747],{"class":557},[504,1198,1200],{"class":506,"line":1199},15,[504,1201,754],{"emptyLinePlaceholder":753},[504,1203,1205,1207,1210,1213],{"class":506,"line":1204},16,[504,1206,558],{"class":557},[504,1208,1209],{"class":561}," main",[504,1211,1212],{"class":557},"()",[504,1214,686],{"class":557},[504,1216,1218,1221,1223,1225,1227,1229,1231,1233],{"class":506,"line":1217},17,[504,1219,1220],{"class":691},"    cfg ",[504,1222,763],{"class":557},[504,1224,766],{"class":691},[504,1226,730],{"class":557},[504,1228,663],{"class":561},[504,1230,565],{"class":557},[504,1232,775],{"class":510},[504,1234,778],{"class":557},[504,1236,1238,1241,1243,1246,1249,1251,1254,1258,1261,1263,1266,1268,1270,1273,1275,1278,1280,1282,1284,1287],{"class":506,"line":1237},18,[504,1239,1240],{"class":691},"    fmt",[504,1242,730],{"class":557},[504,1244,1245],{"class":561},"Printf",[504,1247,1248],{"class":557},"(",[504,1250,824],{"class":557},[504,1252,1253],{"class":514},"listening on ",[504,1255,1257],{"class":1256},"swJcz","%s",[504,1259,1260],{"class":514},", timeout ",[504,1262,1257],{"class":1256},[504,1264,1265],{"class":691},"\\n",[504,1267,824],{"class":557},[504,1269,582],{"class":557},[504,1271,1272],{"class":691}," cfg",[504,1274,730],{"class":557},[504,1276,1277],{"class":691},"ListenAddr",[504,1279,582],{"class":557},[504,1281,1272],{"class":691},[504,1283,730],{"class":557},[504,1285,1286],{"class":691},"Timeout",[504,1288,589],{"class":557},[504,1290,1292],{"class":506,"line":1291},19,[504,1293,747],{"class":557},[495,1295,1297],{"className":497,"code":1296,"filename":459,"language":499,"meta":500,"style":500},"API_KEY=dev-secret\nTIMEOUT=10s\n",[450,1298,1299,1310],{"__ignoreMap":500},[504,1300,1301,1304,1307],{"class":506,"line":507},[504,1302,1303],{"class":691},"API_KEY",[504,1305,1306],{"class":557},"=",[504,1308,1309],{"class":514},"dev-secret\n",[504,1311,1312,1315,1317],{"class":506,"line":525},[504,1313,1314],{"class":691},"TIMEOUT",[504,1316,1306],{"class":557},[504,1318,1319],{"class":514},"10s\n",[447,1321,1322,1323,539,1325,1327,1328,970,1330,1333,1334,1336,1337,1339],{},"Run it with no shell exports at all (",[450,1324,1303],{},[450,1326,1314],{}," come from ",[450,1329,459],{},[450,1331,1332],{},"LISTEN_ADDR"," falls back to its default), or set ",[450,1335,1303],{}," in the real environment and delete ",[450,1338,459],{}," entirely: the program behaves identically either way.",[490,1341,1343],{"id":1342},"related-pages","Related pages",[1026,1345,1346,1355,1363],{},[1029,1347,1348,1351,1352,730],{},[462,1349,1350],{"href":382},"envconf: Recipes",": composing a root config from module configs, prefixed multi-instance loads, testing with ",[450,1353,1354],{},"t.Setenv",[1029,1356,1357,1359,1360,1362],{},[462,1358,204],{"href":229},": what a generated gpsystem project composes with ",[450,1361,373],{},", and the env-prefix conventions across modules.",[1029,1364,1365,1368],{},[462,1366,1367],{"href":205},"Configuration reference",": every env variable of every module, with defaults.",[1370,1371,1372],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}",{"title":500,"searchDepth":525,"depth":525,"links":1374},[1375,1376,1377,1378,1379,1380],{"id":492,"depth":525,"text":493},{"id":545,"depth":525,"text":546},{"id":872,"depth":525,"text":873},{"id":996,"depth":525,"text":997},{"id":1066,"depth":525,"text":1067},{"id":1342,"depth":525,"text":1343},"Typed environment configuration loading with struct tags.","md",null,{},{"icon":231},{"title":52,"description":1381},"b7LSGKtla81YEEB5ycdykv6-5du-R6qVa-KgTRCjXws",[1389,1391],{"title":369,"path":370,"stem":371,"description":1390,"icon":227,"children":-1},"Wiring errs into logging, Sentry and plain net\u002Fhttp handlers.",{"title":381,"path":382,"stem":383,"description":1392,"children":-1},"[object Object]",1785445890038]