[{"data":1,"prerenderedAt":265},["ShallowReactive",2],{"blog-list":3},[4,86],{"id":5,"title":6,"author":7,"body":8,"category":75,"date":76,"description":77,"extension":78,"meta":79,"navigation":80,"path":81,"readingTime":82,"seo":83,"stem":84,"__hash__":85},"blog\u002Fblog\u002Fexplicit-boundaries.md","Why explicit boundaries matter in Go","Amir Mohammad Kargar",{"type":9,"value":10,"toc":69},"minimark",[11,16,20,28,32,35,45,48,52,55],[12,13,15],"h2",{"id":14},"start-with-a-business-interface","Start with a business interface",[17,18,19],"p",{},"An HTTP handler understands status codes, request binding and response schemas. A business service understands a use case. Keeping these responsibilities separate makes it possible to introduce another transport without rewriting the use case.",[17,21,22,23,27],{},"In Gonex, business services live in ",[24,25,26],"code",{},"modules\u002FNAME\u002Fservice.go",". Small interfaces belong to the code that consumes them. The database implementation and transport mapping remain adapters around that core.",[12,29,31],{"id":30},"one-module-several-adapters","One module, several adapters",[17,33,34],{},"A module can register HTTP routes and manage resources. Generated modules expose an injectable service; generated registries construct one service shared across its adapters. This makes composition explicit and avoids scanning source at runtime.",[36,37,43],"pre",{"className":38,"code":40,"language":41,"meta":42},[39],"language-text","modules\u002Fusers\u002F\n├── module.go\n├── service.go\n└── http\u002F\n    ├── handlers.go\n    ├── schemas.go\n    ├── routes.go\n    └── openapi.go\n","text","",[24,44,40],{"__ignoreMap":42},[17,46,47],{},"HTTP versions can have independent adapters. Versioned Protobuf messages can map into the same domain values. A repository interface can be implemented in memory or with GORM.",[12,49,51],{"id":50},"resource-ownership-is-part-of-architecture","Resource ownership is part of architecture",[17,53,54],{},"Connections and background work need an owner. Gonex resources expose start and close operations. Dependencies register before consumers and close in reverse order. Cancellation must be cooperative; a lifecycle API cannot safely stop arbitrary background work that ignores its context.",[17,56,57,58,63,64,68],{},"Continue with ",[59,60,62],"a",{"href":61},"\u002Fdocs\u002Fmain\u002Fmodules\u002F","modules and lifecycle"," and the ",[59,65,67],{"href":66},"\u002Fdocs\u002Fmain\u002Fapi-reference\u002F","application API reference"," for the concrete contracts.",{"title":42,"searchDepth":70,"depth":70,"links":71},2,[72,73,74],{"id":14,"depth":70,"text":15},{"id":30,"depth":70,"text":31},{"id":50,"depth":70,"text":51},"Architecture","2026-10-20","Modules, adapters, and a business core that does not depend on a transport.","md",{},true,"\u002Fblog\u002Fexplicit-boundaries",1,{"title":6,"description":77},"blog\u002Fexplicit-boundaries","slgvpiWYNkLfR_jxlM3HewaBVGJqp9rUhl7IgzybWXw",{"id":87,"title":88,"author":7,"body":89,"category":258,"date":76,"description":259,"extension":78,"meta":260,"navigation":80,"path":261,"readingTime":82,"seo":262,"stem":263,"__hash__":264},"blog\u002Fblog\u002Fintroducing-gonex.md","Meet Gonex: a little structure, a lot of Go",{"type":9,"value":90,"toc":252},[91,95,98,101,105,108,200,217,221,224,236,240,248],[12,92,94],{"id":93},"keep-the-core-in-go","Keep the core in Go",[17,96,97],{},"Gonex is built around a straightforward idea: business services should stay readable as plain Go. HTTP schemas, database models and Protobuf messages live at the boundaries, where they translate between a transport and the application.",[17,99,100],{},"A module is the unit of composition. It declares routes, resources and readiness checks explicitly. Application startup then manages those resources, and shutdown closes them in reverse order.",[12,102,104],{"id":103},"a-useful-first-five-minutes","A useful first five minutes",[17,106,107],{},"Install the reviewed CLI snapshot and create your own API application:",[36,109,113],{"className":110,"code":111,"language":112,"meta":42,"style":42},"language-sh shiki shiki-themes light-plus light-plus dark-plus","go install github.com\u002Famkargar\u002Fgonex\u002Fcmd\u002Fgonex@3ca54b46cb42\ngonex new shop --module example.com\u002Facme\u002Fshop\ncd shop\ngo mod tidy\ngo tool gonex create module users\ngo tool gonex run\n","sh",[24,114,115,130,148,157,168,188],{"__ignoreMap":42},[116,117,119,123,127],"span",{"class":118,"line":82},"line",[116,120,122],{"class":121},"swoLU","go",[116,124,126],{"class":125},"sFD8J"," install",[116,128,129],{"class":125}," github.com\u002Famkargar\u002Fgonex\u002Fcmd\u002Fgonex@3ca54b46cb42\n",[116,131,132,135,138,141,145],{"class":118,"line":70},[116,133,134],{"class":121},"gonex",[116,136,137],{"class":125}," new",[116,139,140],{"class":125}," shop",[116,142,144],{"class":143},"stxUP"," --module",[116,146,147],{"class":125}," example.com\u002Facme\u002Fshop\n",[116,149,151,154],{"class":118,"line":150},3,[116,152,153],{"class":121},"cd",[116,155,156],{"class":125}," shop\n",[116,158,160,162,165],{"class":118,"line":159},4,[116,161,122],{"class":121},[116,163,164],{"class":125}," mod",[116,166,167],{"class":125}," tidy\n",[116,169,171,173,176,179,182,185],{"class":118,"line":170},5,[116,172,122],{"class":121},[116,174,175],{"class":125}," tool",[116,177,178],{"class":125}," gonex",[116,180,181],{"class":125}," create",[116,183,184],{"class":125}," module",[116,186,187],{"class":125}," users\n",[116,189,191,193,195,197],{"class":118,"line":190},6,[116,192,122],{"class":121},[116,194,175],{"class":125},[116,196,178],{"class":125},[116,198,199],{"class":125}," run\n",[17,201,202,203,206,207,211,212,216],{},"Request ",[24,204,205],{},"http:\u002F\u002F127.0.0.1:8080\u002Fusers"," for the starter JSON response. The terminal displays the bound server URL and correlated request logs. Continue with ",[59,208,210],{"href":209},"\u002Fdocs\u002Fmain\u002Fbuilding-api\u002F","Build a REST API"," for schemas, validation and create\u002Flist\u002Fget actions. Framework setup belongs in the separate ",[59,213,215],{"href":214},"\u002Fdocs\u002Fmain\u002Fcontribute\u002F","contributor guides",".",[12,218,220],{"id":219},"add-the-pieces-you-need","Add the pieces you need",[17,222,223],{},"The framework combines Gin routing with typed HTTP contracts and OpenAPI 3.1. Optional adapters add GORM persistence or gRPC without putting those details into business interfaces. The CLI scaffolds projects and modules while protecting handwritten code.",[17,225,226,227,231,232,216],{},"Read the ",[59,228,230],{"href":229},"\u002Fdocs\u002Fmain\u002Farchitecture\u002F","architecture guide"," to understand those boundaries, or start with the ",[59,233,235],{"href":234},"\u002Fdocs\u002Fmain\u002Fquick-start\u002F","quick start",[12,237,239],{"id":238},"an-honest-development-snapshot","An honest development snapshot",[17,241,242,243,247],{},"Gonex has not published a release yet. These pages document the main branch, and examples should be evaluated against that source. Review the ",[59,244,246],{"href":245},"\u002Fdocs\u002Fmain\u002Frelease\u002F","release policy"," for verification status and remaining checks. There are no performance or production-maturity promises here: the source and its recorded checks are the starting point.",[249,250,251],"style",{},"html pre.shiki code .swoLU, html code.shiki .swoLU{--shiki-light:#795E26;--shiki-default:#795E26;--shiki-dark:#DCDCAA}html pre.shiki code .sFD8J, html code.shiki .sFD8J{--shiki-light:#A31515;--shiki-default:#A31515;--shiki-dark:#CE9178}html pre.shiki code .stxUP, html code.shiki .stxUP{--shiki-light:#0000FF;--shiki-default:#0000FF;--shiki-dark:#569CD6}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);}",{"title":42,"searchDepth":70,"depth":70,"links":253},[254,255,256,257],{"id":93,"depth":70,"text":94},{"id":103,"depth":70,"text":104},{"id":219,"depth":70,"text":220},{"id":238,"depth":70,"text":239},"Project notes","A tour of the modular framework, its explicit boundaries, and the best place to begin.",{},"\u002Fblog\u002Fintroducing-gonex",{"title":88,"description":259},"blog\u002Fintroducing-gonex","i8trKcHXM-CeN7w0eEj5DhL3VVbw0w_d0ofJhrrZpYI",1792521640121]