[{"data":1,"prerenderedAt":1346},["ShallowReactive",2],{"navigation_docs_en":3,"-en-concepts-configuration":342,"-en-concepts-configuration-surround":1341},[4,45,61,96,132,166,196,217,241,265],{"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},"Reference","i-lucide-book-open","\u002Fen\u002Freference","en\u002F10.reference",[51,56],{"title":52,"path":53,"stem":54,"icon":55},"Configuration","\u002Fen\u002Freference\u002Fconfiguration","en\u002F10.reference\u002F1.configuration","i-lucide-settings",{"title":57,"path":58,"stem":59,"icon":60},"External dependencies","\u002Fen\u002Freference\u002Fdependencies","en\u002F10.reference\u002F2.dependencies","i-lucide-package",{"title":62,"icon":63,"path":64,"stem":65,"children":66,"page":44},"Concepts","i-lucide-lightbulb","\u002Fen\u002Fconcepts","en\u002F2.concepts",[67,72,77,82,86,91],{"title":68,"path":69,"stem":70,"icon":71},"Architecture","\u002Fen\u002Fconcepts\u002Farchitecture","en\u002F2.concepts\u002F1.architecture","i-lucide-layers",{"title":73,"path":74,"stem":75,"icon":76},"Application lifecycle","\u002Fen\u002Fconcepts\u002Fapplication-lifecycle","en\u002F2.concepts\u002F2.application-lifecycle","i-lucide-power",{"title":78,"path":79,"stem":80,"icon":81},"Error model","\u002Fen\u002Fconcepts\u002Ferror-model","en\u002F2.concepts\u002F3.error-model","i-lucide-shield-alert",{"title":52,"path":83,"stem":84,"icon":85},"\u002Fen\u002Fconcepts\u002Fconfiguration","en\u002F2.concepts\u002F4.configuration","i-lucide-settings-2",{"title":87,"path":88,"stem":89,"icon":90},"Codegen pipeline","\u002Fen\u002Fconcepts\u002Fcodegen-pipeline","en\u002F2.concepts\u002F5.codegen-pipeline","i-lucide-file-json",{"title":92,"path":93,"stem":94,"icon":95},"Design patterns","\u002Fen\u002Fconcepts\u002Fdesign-patterns","en\u002F2.concepts\u002F6.design-patterns","i-lucide-puzzle",{"title":97,"icon":98,"path":99,"stem":100,"children":101,"page":44},"HTTP & Routing","i-lucide-globe","\u002Fen\u002Fhttp","en\u002F3.http",[102,107,112,117,122,127],{"title":103,"path":104,"stem":105,"icon":106},"The server core","\u002Fen\u002Fhttp\u002Fserver","en\u002F3.http\u002F1.server","i-lucide-server",{"title":108,"path":109,"stem":110,"icon":111},"The Fiber engine","\u002Fen\u002Fhttp\u002Ffiber","en\u002F3.http\u002F2.fiber","i-lucide-zap",{"title":113,"path":114,"stem":115,"icon":116},"The chi engine","\u002Fen\u002Fhttp\u002Fchi","en\u002F3.http\u002F3.chi","i-lucide-route",{"title":118,"path":119,"stem":120,"icon":121},"Error responses","\u002Fen\u002Fhttp\u002Ferror-responses","en\u002F3.http\u002F4.error-responses","i-lucide-octagon-alert",{"title":123,"path":124,"stem":125,"icon":126},"Validation","\u002Fen\u002Fhttp\u002Fvalidation","en\u002F3.http\u002F5.validation","i-lucide-badge-check",{"title":128,"path":129,"stem":130,"icon":131},"Pagination","\u002Fen\u002Fhttp\u002Fpagination","en\u002F3.http\u002F6.pagination","i-lucide-list-ordered",{"title":133,"icon":134,"path":135,"stem":136,"children":137,"page":44},"Database","i-lucide-database","\u002Fen\u002Fdatabase","en\u002F4.database",[138,142,147,151,156,161],{"title":139,"path":140,"stem":141,"icon":134},"Overview","\u002Fen\u002Fdatabase\u002Foverview","en\u002F4.database\u002F1.overview",{"title":143,"path":144,"stem":145,"icon":146},"pgx","\u002Fen\u002Fdatabase\u002Fpgx","en\u002F4.database\u002F2.pgx","i-lucide-plug",{"title":148,"path":149,"stem":150,"icon":71},"bun","\u002Fen\u002Fdatabase\u002Fbun","en\u002F4.database\u002F3.bun",{"title":152,"path":153,"stem":154,"icon":155},"Transactions","\u002Fen\u002Fdatabase\u002Ftransactions","en\u002F4.database\u002F4.transactions","i-lucide-git-merge",{"title":157,"path":158,"stem":159,"icon":160},"Migrations","\u002Fen\u002Fdatabase\u002Fmigrations","en\u002F4.database\u002F5.migrations","i-lucide-file-stack",{"title":162,"path":163,"stem":164,"icon":165},"Seeders","\u002Fen\u002Fdatabase\u002Fseeding","en\u002F4.database\u002F6.seeding","i-lucide-sprout",{"title":167,"icon":168,"path":169,"stem":170,"children":171,"page":44},"Async & Background","i-lucide-workflow","\u002Fen\u002Fasync","en\u002F5.async",[172,176,181,186,191],{"title":173,"path":174,"stem":175,"icon":131},"Queue","\u002Fen\u002Fasync\u002Fqueue","en\u002F5.async\u002F1.queue",{"title":177,"path":178,"stem":179,"icon":180},"Events","\u002Fen\u002Fasync\u002Fevents","en\u002F5.async\u002F2.events","i-lucide-radio",{"title":182,"path":183,"stem":184,"icon":185},"Outbox","\u002Fen\u002Fasync\u002Foutbox","en\u002F5.async\u002F3.outbox","i-lucide-inbox",{"title":187,"path":188,"stem":189,"icon":190},"Scheduling","\u002Fen\u002Fasync\u002Fscheduler","en\u002F5.async\u002F4.scheduler","i-lucide-calendar-clock",{"title":192,"path":193,"stem":194,"icon":195},"Worker","\u002Fen\u002Fasync\u002Fworker","en\u002F5.async\u002F5.worker","i-lucide-cog",{"title":197,"icon":198,"path":199,"stem":200,"children":201,"page":44},"Security","i-lucide-shield-check","\u002Fen\u002Fsecurity","en\u002F6.security",[202,207,212],{"title":203,"path":204,"stem":205,"icon":206},"Authentication","\u002Fen\u002Fsecurity\u002Fauthentication","en\u002F6.security\u002F1.authentication","i-lucide-key-round",{"title":208,"path":209,"stem":210,"icon":211},"RBAC","\u002Fen\u002Fsecurity\u002Frbac","en\u002F6.security\u002F2.rbac","i-lucide-users",{"title":213,"path":214,"stem":215,"icon":216},"Policies","\u002Fen\u002Fsecurity\u002Fpolicies","en\u002F6.security\u002F3.policies","i-lucide-gavel",{"title":218,"icon":219,"path":220,"stem":221,"children":222,"page":44},"Observability","i-lucide-activity","\u002Fen\u002Fobservability","en\u002F7.observability",[223,226,231,236],{"title":139,"path":224,"stem":225,"icon":219},"\u002Fen\u002Fobservability\u002Foverview","en\u002F7.observability\u002F1.overview",{"title":227,"path":228,"stem":229,"icon":230},"Logging","\u002Fen\u002Fobservability\u002Flogging","en\u002F7.observability\u002F2.logging","i-lucide-scroll-text",{"title":232,"path":233,"stem":234,"icon":235},"OpenTelemetry","\u002Fen\u002Fobservability\u002Fopentelemetry","en\u002F7.observability\u002F3.opentelemetry","i-lucide-radar",{"title":237,"path":238,"stem":239,"icon":240},"Sentry","\u002Fen\u002Fobservability\u002Fsentry","en\u002F7.observability\u002F4.sentry","i-lucide-bug",{"title":242,"icon":243,"path":244,"stem":245,"children":246,"page":44},"Storage & Mail","i-lucide-hard-drive","\u002Fen\u002Fstorage-mail","en\u002F8.storage-mail",[247,251,256,261],{"title":248,"path":249,"stem":250,"icon":243},"Storage","\u002Fen\u002Fstorage-mail\u002Fstorage","en\u002F8.storage-mail\u002F1.storage",{"title":252,"path":253,"stem":254,"icon":255},"Email","\u002Fen\u002Fstorage-mail\u002Fmail","en\u002F8.storage-mail\u002F2.mail","i-lucide-mail",{"title":257,"path":258,"stem":259,"icon":260},"Notifications","\u002Fen\u002Fstorage-mail\u002Fnotifications","en\u002F8.storage-mail\u002F3.notifications","i-lucide-bell",{"title":262,"path":263,"stem":264,"icon":180},"Realtime","\u002Fen\u002Fstorage-mail\u002Frealtime","en\u002F8.storage-mail\u002F4.realtime",{"title":266,"icon":267,"path":268,"stem":269,"children":270,"page":44},"CLI Reference","i-lucide-terminal","\u002Fen\u002Fcli","en\u002F9.cli",[271,274,279,284,289,294,299,303,308,313,318,323,328,333,337],{"title":139,"path":272,"stem":273,"icon":267},"\u002Fen\u002Fcli\u002Foverview","en\u002F9.cli\u002F1.overview",{"title":275,"path":276,"stem":277,"icon":278},"add db","\u002Fen\u002Fcli\u002Fadd-db","en\u002F9.cli\u002F10.add-db","i-lucide-database-zap",{"title":280,"path":281,"stem":282,"icon":283},"add compose \u002F add docker","\u002Fen\u002Fcli\u002Fadd-compose","en\u002F9.cli\u002F11.add-compose","i-lucide-container",{"title":285,"path":286,"stem":287,"icon":288},"add mail","\u002Fen\u002Fcli\u002Fadd-mail","en\u002F9.cli\u002F12.add-mail","i-lucide-mail-plus",{"title":290,"path":291,"stem":292,"icon":293},"add notification","\u002Fen\u002Fcli\u002Fadd-notification","en\u002F9.cli\u002F13.add-notification","i-lucide-bell-plus",{"title":295,"path":296,"stem":297,"icon":298},"add realtime","\u002Fen\u002Fcli\u002Fadd-realtime","en\u002F9.cli\u002F14.add-realtime","i-lucide-radio-tower",{"title":300,"path":301,"stem":302,"icon":165},"add seeder","\u002Fen\u002Fcli\u002Fadd-seeder","en\u002F9.cli\u002F15.add-seeder",{"title":304,"path":305,"stem":306,"icon":307},"new project","\u002Fen\u002Fcli\u002Fnew-project","en\u002F9.cli\u002F2.new-project","i-lucide-folder-plus",{"title":309,"path":310,"stem":311,"icon":312},"new module","\u002Fen\u002Fcli\u002Fnew-module","en\u002F9.cli\u002F3.new-module","i-lucide-blocks",{"title":314,"path":315,"stem":316,"icon":317},"add surface","\u002Fen\u002Fcli\u002Fadd-surface","en\u002F9.cli\u002F4.add-surface","i-lucide-layers-2",{"title":319,"path":320,"stem":321,"icon":322},"add core","\u002Fen\u002Fcli\u002Fadd-core","en\u002F9.cli\u002F5.add-core","i-lucide-box",{"title":324,"path":325,"stem":326,"icon":327},"add handler","\u002Fen\u002Fcli\u002Fadd-handler","en\u002F9.cli\u002F6.add-handler","i-lucide-webhook",{"title":329,"path":330,"stem":331,"icon":332},"new migration","\u002Fen\u002Fcli\u002Fnew-migration","en\u002F9.cli\u002F7.new-migration","i-lucide-file-plus",{"title":334,"path":335,"stem":336,"icon":195},"worker generators","\u002Fen\u002Fcli\u002Fworker-generators","en\u002F9.cli\u002F8.worker-generators",{"title":338,"path":339,"stem":340,"icon":341},"upgrade templates","\u002Fen\u002Fcli\u002Fupgrade-templates","en\u002F9.cli\u002F9.upgrade-templates","i-lucide-refresh-cw",{"id":343,"title":52,"body":344,"description":1334,"extension":1335,"links":1336,"meta":1337,"navigation":1338,"path":83,"seo":1339,"stem":84,"__hash__":1340},"docs_en\u002Fen\u002F2.concepts\u002F4.configuration.md",{"type":345,"value":346,"toc":1327},"minimark",[347,365,372,377,406,507,551,569,573,580,764,797,839,886,889,1063,1092,1096,1107,1212,1248,1258,1262,1295,1299,1323],[348,349,350,351,355,356,360,361,364],"p",{},"In gpsystem, loading configuration is a single step: ",[352,353,354],"strong",{},"environment variables loaded into a typed Go struct, once, at process start."," There is no ",[357,358,359],"code",{},"config()"," helper and no config cache: the struct is the cache, and a mistyped key is not a runtime ",[357,362,363],{},"null"," but a compile error.",[348,366,367,368,371],{},"This is the 12-factor \"config from the environment\" principle: configuration is read ",[352,369,370],{},"at process start, from the environment",", and the binary is identical in every environment (dev, staging, production); only the env differs.",[373,374,376],"h2",{"id":375},"the-envconf-package","The envconf package",[378,379,384],"pre",{"className":380,"code":381,"language":382,"meta":383,"style":383},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import \"github.com\u002Fgp-system\u002Fgpsystem\u002Fenvconf\"\n","go","",[357,385,386],{"__ignoreMap":383},[387,388,391,395,399,403],"span",{"class":389,"line":390},"line",1,[387,392,394],{"class":393},"s7zQu","import",[387,396,398],{"class":397},"sMK4o"," \"",[387,400,402],{"class":401},"sBMFI","github.com\u002Fgp-system\u002Fgpsystem\u002Fenvconf",[387,404,405],{"class":397},"\"\n",[378,407,409],{"className":380,"code":408,"language":382,"meta":383,"style":383},"func Load[T any]() (T, error)\nfunc MustLoad[T any]() T                       \u002F\u002F panics with the name of the bad\u002Fmissing variable\nfunc LoadPrefixed[T any](prefix string) (T, error)\n",[357,410,411,448,471],{"__ignoreMap":383},[387,412,413,416,420,423,427,430,433,436,438,441,445],{"class":389,"line":390},[387,414,415],{"class":397},"func",[387,417,419],{"class":418},"s2Zo4"," Load",[387,421,422],{"class":397},"[",[387,424,426],{"class":425},"sHdIc","T",[387,428,429],{"class":401}," any",[387,431,432],{"class":397},"]()",[387,434,435],{"class":397}," (",[387,437,426],{"class":401},[387,439,440],{"class":397},",",[387,442,444],{"class":443},"spNyl"," error",[387,446,447],{"class":397},")\n",[387,449,451,453,456,458,460,462,464,467],{"class":389,"line":450},2,[387,452,415],{"class":397},[387,454,455],{"class":418}," MustLoad",[387,457,422],{"class":397},[387,459,426],{"class":425},[387,461,429],{"class":401},[387,463,432],{"class":397},[387,465,466],{"class":401}," T",[387,468,470],{"class":469},"sHwdD","                       \u002F\u002F panics with the name of the bad\u002Fmissing variable\n",[387,472,474,476,479,481,483,485,488,491,494,497,499,501,503,505],{"class":389,"line":473},3,[387,475,415],{"class":397},[387,477,478],{"class":418}," LoadPrefixed",[387,480,422],{"class":397},[387,482,426],{"class":425},[387,484,429],{"class":401},[387,486,487],{"class":397},"](",[387,489,490],{"class":425},"prefix",[387,492,493],{"class":443}," string",[387,495,496],{"class":397},")",[387,498,435],{"class":397},[387,500,426],{"class":401},[387,502,440],{"class":397},[387,504,444],{"class":443},[387,506,447],{"class":397},[348,508,509,510,517,518,521,522,525,526,529,530,535,536,539,540,543,544,546,547,550],{},"The package builds on ",[511,512,516],"a",{"href":513,"rel":514},"https:\u002F\u002Fgithub.com\u002Fcaarlos0\u002Fenv",[515],"nofollow","caarlos0\u002Fenv"," v11: struct fields bind to variable names via ",[357,519,520],{},"env:\"...\""," tags, ",[357,523,524],{},"envDefault"," supplies defaults, and ",[357,527,528],{},"env:\"...,required\""," makes a variable mandatory. Before parsing, on a best-effort basis, ",[511,531,534],{"href":532,"rel":533},"https:\u002F\u002Fgithub.com\u002Fjoho\u002Fgodotenv",[515],"godotenv"," loads the working directory's ",[357,537,538],{},".env"," file if present: it ",[352,541,542],{},"never overrides an existing env variable",", so ",[357,545,538],{}," only fills in what the environment did not provide. For local development you export nothing (generated projects ship a ",[357,548,549],{},".env.example","), and in production the real environment (systemd unit, K8s ConfigMap\u002FSecret) wins.",[348,552,553,556,557,560,561,564,565,568],{},[357,554,555],{},"MustLoad"," is the first line of ",[357,558,559],{},"main()",": a missing ",[357,562,563],{},"required"," variable fails with the ",[352,566,567],{},"variable's name",", at startup. No service ever boots half-configured only to reveal what's missing on the first request.",[373,570,572],{"id":571},"struct-composition","Struct composition",[348,574,575,576,579],{},"Kit packages export env-tagged config structs, and the application composes them into a single struct with ",[357,577,578],{},"envPrefix",". The shop project's generated configuration:",[378,581,584],{"className":380,"code":582,"filename":583,"language":382,"meta":383,"style":383},"package config\n\nimport (\n    \"github.com\u002Fgp-system\u002Fgpsystem\u002Fdbx\"\n    \"github.com\u002Fgp-system\u002Fgpsystem\u002Fevents\u002Foutbox\"\n    \"github.com\u002Fgp-system\u002Fgpsystem\u002Fserver\"\n    \"github.com\u002Fgp-system\u002Fgpsystem\u002Fworker\"\n    \u002F\u002F gpsystem:imports\n)\n\ntype Config struct {\n    Server server.Config\n    DB     dbx.Config `envPrefix:\"DB_\"`\n    Worker worker.Config\n    Outbox outbox.Config `envPrefix:\"OUTBOX_\"`\n    \u002F\u002F gpsystem:config\n}\n","internal\u002Fplatform\u002Fconfig\u002Fconfig.go",[357,585,586,594,600,607,618,628,638,648,654,659,664,679,695,719,732,752,758],{"__ignoreMap":383},[387,587,588,591],{"class":389,"line":390},[387,589,590],{"class":397},"package",[387,592,593],{"class":401}," config\n",[387,595,596],{"class":389,"line":450},[387,597,599],{"emptyLinePlaceholder":598},true,"\n",[387,601,602,604],{"class":389,"line":473},[387,603,394],{"class":393},[387,605,606],{"class":397}," (\n",[387,608,610,613,616],{"class":389,"line":609},4,[387,611,612],{"class":397},"    \"",[387,614,615],{"class":401},"github.com\u002Fgp-system\u002Fgpsystem\u002Fdbx",[387,617,405],{"class":397},[387,619,621,623,626],{"class":389,"line":620},5,[387,622,612],{"class":397},[387,624,625],{"class":401},"github.com\u002Fgp-system\u002Fgpsystem\u002Fevents\u002Foutbox",[387,627,405],{"class":397},[387,629,631,633,636],{"class":389,"line":630},6,[387,632,612],{"class":397},[387,634,635],{"class":401},"github.com\u002Fgp-system\u002Fgpsystem\u002Fserver",[387,637,405],{"class":397},[387,639,641,643,646],{"class":389,"line":640},7,[387,642,612],{"class":397},[387,644,645],{"class":401},"github.com\u002Fgp-system\u002Fgpsystem\u002Fworker",[387,647,405],{"class":397},[387,649,651],{"class":389,"line":650},8,[387,652,653],{"class":469},"    \u002F\u002F gpsystem:imports\n",[387,655,657],{"class":389,"line":656},9,[387,658,447],{"class":397},[387,660,662],{"class":389,"line":661},10,[387,663,599],{"emptyLinePlaceholder":598},[387,665,667,670,673,676],{"class":389,"line":666},11,[387,668,669],{"class":397},"type",[387,671,672],{"class":401}," Config",[387,674,675],{"class":397}," struct",[387,677,678],{"class":397}," {\n",[387,680,682,686,689,692],{"class":389,"line":681},12,[387,683,685],{"class":684},"sTEyZ","    Server ",[387,687,688],{"class":401},"server",[387,690,691],{"class":397},".",[387,693,694],{"class":401},"Config\n",[387,696,698,701,704,706,709,712,716],{"class":389,"line":697},13,[387,699,700],{"class":684},"    DB     ",[387,702,703],{"class":401},"dbx",[387,705,691],{"class":397},[387,707,708],{"class":401},"Config",[387,710,711],{"class":397}," `",[387,713,715],{"class":714},"sfazB","envPrefix:\"DB_\"",[387,717,718],{"class":397},"`\n",[387,720,722,725,728,730],{"class":389,"line":721},14,[387,723,724],{"class":684},"    Worker ",[387,726,727],{"class":401},"worker",[387,729,691],{"class":397},[387,731,694],{"class":401},[387,733,735,738,741,743,745,747,750],{"class":389,"line":734},15,[387,736,737],{"class":684},"    Outbox ",[387,739,740],{"class":401},"outbox",[387,742,691],{"class":397},[387,744,708],{"class":401},[387,746,711],{"class":397},[387,748,749],{"class":714},"envPrefix:\"OUTBOX_\"",[387,751,718],{"class":397},[387,753,755],{"class":389,"line":754},16,[387,756,757],{"class":469},"    \u002F\u002F gpsystem:config\n",[387,759,761],{"class":389,"line":760},17,[387,762,763],{"class":397},"}\n",[378,765,768],{"className":380,"code":766,"filename":767,"language":382,"meta":383,"style":383},"cfg := envconf.MustLoad[config.Config]()\n","cmd\u002Fshop\u002Fmain.go",[357,769,770],{"__ignoreMap":383},[387,771,772,775,778,781,783,785,787,790,792,794],{"class":389,"line":390},[387,773,774],{"class":684},"cfg ",[387,776,777],{"class":397},":=",[387,779,780],{"class":684}," envconf",[387,782,691],{"class":397},[387,784,555],{"class":418},[387,786,422],{"class":397},[387,788,789],{"class":401},"config",[387,791,691],{"class":397},[387,793,708],{"class":401},[387,795,796],{"class":397},"]()\n",[348,798,799,800,803,804,807,808,811,812,811,815,818,819,821,822,811,825,811,828,831,832,811,835,838],{},"The composition rule is simple: ",[352,801,802],{},"a package names its own fields, the embedder decides the prefix."," ",[357,805,806],{},"dbx.Config","'s fields are ",[357,809,810],{},"HOST",", ",[357,813,814],{},"PORT",[357,816,817],{},"USER",", ...: under ",[357,820,715],{}," they become ",[357,823,824],{},"DB_HOST",[357,826,827],{},"DB_PORT",[357,829,830],{},"DB_USER",". Structs embedded without a prefix (",[357,833,834],{},"server.Config",[357,836,837],{},"worker.Config",") read standard top-level names.",[348,840,841,842,844,845,848,849,852,853,852,856,859,860,435,863,811,866,811,869,811,872,875,876,878,879,811,882,885],{},"The nesting goes deeper: ",[357,843,834],{}," itself contains ",[357,846,847],{},"telemetry.Config",", which bundles the ",[357,850,851],{},"otelx"," + ",[357,854,855],{},"logx",[357,857,858],{},"sentryx"," configs (all unprefixed, because these are ",[352,861,862],{},"industry-standard names",[357,864,865],{},"OTEL_SERVICE_NAME",[357,867,868],{},"OTEL_DEV_MODE",[357,870,871],{},"LOG_LEVEL",[357,873,874],{},"SENTRY_DSN",") that every OTel\u002FSentry-compatible tool expects as-is). ",[357,877,837],{}," in turn prefixes its Redis and scheduler configs (",[357,880,881],{},"REDIS_ADDR",[357,883,884],{},"SCHEDULER_TIMEZONE",").",[348,887,888],{},"The shop's env surface therefore looks like this (excerpt):",[378,890,894],{"className":891,"code":892,"filename":538,"language":893,"meta":383,"style":383},"language-sh shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","# server.Config: no prefix\nLISTEN_ADDR=:3000\nSHUTDOWN_TIMEOUT=10s\n\n# telemetry (embedded in server.Config): standard names\nOTEL_SERVICE_NAME=shop\nOTEL_DEV_MODE=true\nLOG_FORMAT=monolog\nSENTRY_DSN=\n\n# dbx.Config: under the DB_ prefix\nDB_HOST=localhost\nDB_USER=shop\nDB_PASSWORD=secret\nDB_NAME=shop\n\n# worker.Config: WORKER_* and REDIS_*\nWORKER_CONCURRENCY=10\nREDIS_ADDR=localhost:6379\n\n# outbox.Config: under the OUTBOX_ prefix\nOUTBOX_POLL_INTERVAL=1s\n","sh",[357,895,896,901,912,922,926,931,940,949,959,966,970,975,984,992,1002,1011,1015,1020,1031,1041,1046,1052],{"__ignoreMap":383},[387,897,898],{"class":389,"line":390},[387,899,900],{"class":469},"# server.Config: no prefix\n",[387,902,903,906,909],{"class":389,"line":450},[387,904,905],{"class":684},"LISTEN_ADDR",[387,907,908],{"class":397},"=",[387,910,911],{"class":714},":3000\n",[387,913,914,917,919],{"class":389,"line":473},[387,915,916],{"class":684},"SHUTDOWN_TIMEOUT",[387,918,908],{"class":397},[387,920,921],{"class":714},"10s\n",[387,923,924],{"class":389,"line":609},[387,925,599],{"emptyLinePlaceholder":598},[387,927,928],{"class":389,"line":620},[387,929,930],{"class":469},"# telemetry (embedded in server.Config): standard names\n",[387,932,933,935,937],{"class":389,"line":630},[387,934,865],{"class":684},[387,936,908],{"class":397},[387,938,939],{"class":714},"shop\n",[387,941,942,944,946],{"class":389,"line":640},[387,943,868],{"class":684},[387,945,908],{"class":397},[387,947,948],{"class":714},"true\n",[387,950,951,954,956],{"class":389,"line":650},[387,952,953],{"class":684},"LOG_FORMAT",[387,955,908],{"class":397},[387,957,958],{"class":714},"monolog\n",[387,960,961,963],{"class":389,"line":656},[387,962,874],{"class":684},[387,964,965],{"class":397},"=\n",[387,967,968],{"class":389,"line":661},[387,969,599],{"emptyLinePlaceholder":598},[387,971,972],{"class":389,"line":666},[387,973,974],{"class":469},"# dbx.Config: under the DB_ prefix\n",[387,976,977,979,981],{"class":389,"line":681},[387,978,824],{"class":684},[387,980,908],{"class":397},[387,982,983],{"class":714},"localhost\n",[387,985,986,988,990],{"class":389,"line":697},[387,987,830],{"class":684},[387,989,908],{"class":397},[387,991,939],{"class":714},[387,993,994,997,999],{"class":389,"line":721},[387,995,996],{"class":684},"DB_PASSWORD",[387,998,908],{"class":397},[387,1000,1001],{"class":714},"secret\n",[387,1003,1004,1007,1009],{"class":389,"line":734},[387,1005,1006],{"class":684},"DB_NAME",[387,1008,908],{"class":397},[387,1010,939],{"class":714},[387,1012,1013],{"class":389,"line":754},[387,1014,599],{"emptyLinePlaceholder":598},[387,1016,1017],{"class":389,"line":760},[387,1018,1019],{"class":469},"# worker.Config: WORKER_* and REDIS_*\n",[387,1021,1023,1026,1028],{"class":389,"line":1022},18,[387,1024,1025],{"class":684},"WORKER_CONCURRENCY",[387,1027,908],{"class":397},[387,1029,1030],{"class":714},"10\n",[387,1032,1034,1036,1038],{"class":389,"line":1033},19,[387,1035,881],{"class":684},[387,1037,908],{"class":397},[387,1039,1040],{"class":714},"localhost:6379\n",[387,1042,1044],{"class":389,"line":1043},20,[387,1045,599],{"emptyLinePlaceholder":598},[387,1047,1049],{"class":389,"line":1048},21,[387,1050,1051],{"class":469},"# outbox.Config: under the OUTBOX_ prefix\n",[387,1053,1055,1058,1060],{"class":389,"line":1054},22,[387,1056,1057],{"class":684},"OUTBOX_POLL_INTERVAL",[387,1059,908],{"class":397},[387,1061,1062],{"class":714},"1s\n",[1064,1065,1067,1068,1071,1072,811,1075,1078,1079,811,1082,811,1085,1088,1089,691],"note",{"title":1066},"No GPSYSTEM_* namespace","The kit ",[352,1069,1070],{},"deliberately does not"," introduce its own env namespace. Where an industry-standard name exists (",[357,1073,1074],{},"OTEL_*",[357,1076,1077],{},"SENTRY_*","), it uses that; where none does, short prefixed names (",[357,1080,1081],{},"DB_*",[357,1083,1084],{},"REDIS_*",[357,1086,1087],{},"WORKER_*","). Your deployment looks like any other OTel-instrumented app's. The full per-package variable table: ",[511,1090,1091],{"href":53},"Configuration reference",[373,1093,1095],{"id":1094},"your-own-fields","Your own fields",[348,1097,1098,1099,1102,1103,1106],{},"App-specific configuration goes into the same struct, below the ",[357,1100,1101],{},"\u002F\u002F gpsystem:config"," anchor, so future generator additions (e.g. ",[357,1104,1105],{},"add worker"," retrofitting an older project) don't collide with it:",[378,1108,1110],{"className":380,"code":1109,"language":382,"meta":383,"style":383},"type Config struct {\n    Server server.Config\n    DB     dbx.Config `envPrefix:\"DB_\"`\n    \u002F\u002F ...\n    JWT           auth.Config `envPrefix:\"JWT_\"`                       \u002F\u002F JWT_SECRET, JWT_ACCESS_TOKEN_TTL, ...\n    StripeKey     string      `env:\"STRIPE_API_KEY,required\"`\n    OrderCapacity int         `env:\"ORDER_CAPACITY\" envDefault:\"100\"`\n}\n",[357,1111,1112,1122,1132,1148,1153,1176,1192,1208],{"__ignoreMap":383},[387,1113,1114,1116,1118,1120],{"class":389,"line":390},[387,1115,669],{"class":397},[387,1117,672],{"class":401},[387,1119,675],{"class":397},[387,1121,678],{"class":397},[387,1123,1124,1126,1128,1130],{"class":389,"line":450},[387,1125,685],{"class":684},[387,1127,688],{"class":401},[387,1129,691],{"class":397},[387,1131,694],{"class":401},[387,1133,1134,1136,1138,1140,1142,1144,1146],{"class":389,"line":473},[387,1135,700],{"class":684},[387,1137,703],{"class":401},[387,1139,691],{"class":397},[387,1141,708],{"class":401},[387,1143,711],{"class":397},[387,1145,715],{"class":714},[387,1147,718],{"class":397},[387,1149,1150],{"class":389,"line":609},[387,1151,1152],{"class":469},"    \u002F\u002F ...\n",[387,1154,1155,1158,1161,1163,1165,1167,1170,1173],{"class":389,"line":620},[387,1156,1157],{"class":684},"    JWT           ",[387,1159,1160],{"class":401},"auth",[387,1162,691],{"class":397},[387,1164,708],{"class":401},[387,1166,711],{"class":397},[387,1168,1169],{"class":714},"envPrefix:\"JWT_\"",[387,1171,1172],{"class":397},"`",[387,1174,1175],{"class":469},"                       \u002F\u002F JWT_SECRET, JWT_ACCESS_TOKEN_TTL, ...\n",[387,1177,1178,1181,1184,1187,1190],{"class":389,"line":630},[387,1179,1180],{"class":684},"    StripeKey     ",[387,1182,1183],{"class":443},"string",[387,1185,1186],{"class":397},"      `",[387,1188,1189],{"class":714},"env:\"STRIPE_API_KEY,required\"",[387,1191,718],{"class":397},[387,1193,1194,1197,1200,1203,1206],{"class":389,"line":640},[387,1195,1196],{"class":684},"    OrderCapacity ",[387,1198,1199],{"class":443},"int",[387,1201,1202],{"class":397},"         `",[387,1204,1205],{"class":714},"env:\"ORDER_CAPACITY\" envDefault:\"100\"",[387,1207,718],{"class":397},[387,1209,1210],{"class":389,"line":650},[387,1211,763],{"class":397},[348,1213,1214,1217,1218,435,1221,811,1224,1227,1228,1231,1232,435,1235,1227,1238,1241,1242,1244,1245,1247],{},[511,1215,516],{"href":513,"rel":1216},[515]," parses all the usual types: ",[357,1219,1220],{},"time.Duration",[357,1222,1223],{},"10s",[357,1225,1226],{},"168h","), ",[357,1229,1230],{},"[]string"," (comma-separated), ",[357,1233,1234],{},"map[string]int",[357,1236,1237],{},"critical:6,default:3",[357,1239,1240],{},"bool",", numbers: you can see all of them live on ",[357,1243,834],{},"'s and ",[357,1246,837],{},"'s fields.",[1249,1250,1251,1254,1255,1257],"tip",{},[357,1252,1253],{},"LoadPrefixed[dbx.Config](\"ANALYTICS_DB_\")"," loads a second config with its own variable set, so one process can talk to a separate analytics database without extending the main ",[357,1256,708],{}," struct.",[373,1259,1261],{"id":1260},"configuration-as-an-explicit-dependency","Configuration as an explicit dependency",[348,1263,1264,1265,1267,1268,435,1271,1274,1275,811,1278,1274,1281,1284,1285,1288,1289,1291,1292,1294],{},"In gpsystem, configuration materializes once in ",[357,1266,559],{}," and travels onward ",[352,1269,1270],{},"as an explicit parameter",[357,1272,1273],{},"cfg.Server"," to ",[357,1276,1277],{},"fiberx.Run",[357,1279,1280],{},"cfg.DB",[357,1282,1283],{},"pg.MustNewPool",", and to the modules via the ",[357,1286,1287],{},"Dependencies"," struct). A service never touches the environment at runtime. What it receives is the boot-time snapshot, freely constructible in tests. A mistyped field is a compile error, and a missing ",[357,1290,563],{}," env variable is an error at boot, with the variable's name, never a silent ",[357,1293,363],{}," at runtime.",[373,1296,1298],{"id":1297},"related-pages","Related pages",[1300,1301,1302,1308,1315],"ul",{},[1303,1304,1305,1307],"li",{},[511,1306,1091],{"href":53},": every env variable of every kit package, with defaults.",[1303,1309,1310,1312,1313,691],{},[511,1311,73],{"href":74},": what happens after ",[357,1314,555],{},[1303,1316,1317,1319,1320,1322],{},[511,1318,25],{"href":26},": from ",[357,1321,549],{}," to the first boot.",[1324,1325,1326],"style",{},"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 .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}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 .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 .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 pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}",{"title":383,"searchDepth":450,"depth":450,"links":1328},[1329,1330,1331,1332,1333],{"id":375,"depth":450,"text":376},{"id":571,"depth":450,"text":572},{"id":1094,"depth":450,"text":1095},{"id":1260,"depth":450,"text":1261},{"id":1297,"depth":450,"text":1298},"Typed configuration from environment variables: envconf, struct composition and the .env file.","md",null,{},{"icon":85},{"title":52,"description":1334},"uXahEMxy8d_lqJlgeoc-spRKOGOy4k7dk05TsybfPZA",[1342,1344],{"title":78,"path":79,"stem":80,"description":1343,"icon":81,"children":-1},"RFC 9457 problem details everywhere, with errs errors carrying stacks, codes and client-safe messages underneath.",{"title":87,"path":88,"stem":89,"description":1345,"icon":90,"children":-1},"TypeSpec → OpenAPI 3.0 → strict, typed server code: for Fiber and chi alike.",1784668706712]