[{"data":1,"prerenderedAt":810},["ShallowReactive",2],{"navigation_docs_en":3,"-en-framework-overview":448,"-en-framework-overview-surround":805},[4,45,120,157,173,203,233,259,271,287,307,326,339,356,373,386,398,425],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":44},"Getting Started","i-lucide-rocket","\u002Fen\u002Fgetting-started","en\u002F01.getting-started",[10,15,20,25,30,35,40],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fen\u002Fgetting-started\u002Fintroduction","en\u002F01.getting-started\u002F1.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Installation","\u002Fen\u002Fgetting-started\u002Finstallation","en\u002F01.getting-started\u002F2.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":24},"Your first module","\u002Fen\u002Fgetting-started\u002Ffirst-module","en\u002F01.getting-started\u002F3.first-module","i-lucide-package-plus",{"title":26,"path":27,"stem":28,"icon":29},"Project structure","\u002Fen\u002Fgetting-started\u002Fproject-structure","en\u002F01.getting-started\u002F4.project-structure","i-lucide-folder-tree",{"title":31,"path":32,"stem":33,"icon":34},"The shop sample application","\u002Fen\u002Fgetting-started\u002Fsample-app","en\u002F01.getting-started\u002F5.sample-app","i-lucide-shopping-cart",{"title":36,"path":37,"stem":38,"icon":39},"Coming from Laravel","\u002Fen\u002Fgetting-started\u002Fcoming-from-laravel","en\u002F01.getting-started\u002F6.coming-from-laravel","i-lucide-arrow-right-left",{"title":41,"path":42,"stem":43,"icon":39},"Coming from Symfony","\u002Fen\u002Fgetting-started\u002Fcoming-from-symfony","en\u002F01.getting-started\u002F7.coming-from-symfony",false,{"title":46,"icon":47,"path":48,"stem":49,"children":50,"page":44},"CLI Reference","i-lucide-terminal","\u002Fen\u002Fcli","en\u002F02.cli",[51,55,60,65,70,75,80,85,90,95,100,105,110,115],{"title":52,"path":53,"stem":54,"icon":47},"Overview","\u002Fen\u002Fcli\u002Foverview","en\u002F02.cli\u002F1.overview",{"title":56,"path":57,"stem":58,"icon":59},"add compose \u002F add docker","\u002Fen\u002Fcli\u002Fadd-compose","en\u002F02.cli\u002F10.add-compose","i-lucide-container",{"title":61,"path":62,"stem":63,"icon":64},"add mail","\u002Fen\u002Fcli\u002Fadd-mail","en\u002F02.cli\u002F11.add-mail","i-lucide-mail-plus",{"title":66,"path":67,"stem":68,"icon":69},"add notification","\u002Fen\u002Fcli\u002Fadd-notification","en\u002F02.cli\u002F12.add-notification","i-lucide-bell-plus",{"title":71,"path":72,"stem":73,"icon":74},"add realtime","\u002Fen\u002Fcli\u002Fadd-realtime","en\u002F02.cli\u002F13.add-realtime","i-lucide-radio-tower",{"title":76,"path":77,"stem":78,"icon":79},"add seeder","\u002Fen\u002Fcli\u002Fadd-seeder","en\u002F02.cli\u002F14.add-seeder","i-lucide-sprout",{"title":81,"path":82,"stem":83,"icon":84},"new project","\u002Fen\u002Fcli\u002Fnew-project","en\u002F02.cli\u002F2.new-project","i-lucide-folder-plus",{"title":86,"path":87,"stem":88,"icon":89},"new module","\u002Fen\u002Fcli\u002Fnew-module","en\u002F02.cli\u002F3.new-module","i-lucide-blocks",{"title":91,"path":92,"stem":93,"icon":94},"add surface","\u002Fen\u002Fcli\u002Fadd-surface","en\u002F02.cli\u002F4.add-surface","i-lucide-layers-2",{"title":96,"path":97,"stem":98,"icon":99},"add domain","\u002Fen\u002Fcli\u002Fadd-domain","en\u002F02.cli\u002F5.add-domain","i-lucide-box",{"title":101,"path":102,"stem":103,"icon":104},"add handler","\u002Fen\u002Fcli\u002Fadd-handler","en\u002F02.cli\u002F6.add-handler","i-lucide-webhook",{"title":106,"path":107,"stem":108,"icon":109},"new migration","\u002Fen\u002Fcli\u002Fnew-migration","en\u002F02.cli\u002F7.new-migration","i-lucide-file-plus",{"title":111,"path":112,"stem":113,"icon":114},"worker generators","\u002Fen\u002Fcli\u002Fworker-generators","en\u002F02.cli\u002F8.worker-generators","i-lucide-cog",{"title":116,"path":117,"stem":118,"icon":119},"add db","\u002Fen\u002Fcli\u002Fadd-db","en\u002F02.cli\u002F9.add-db","i-lucide-database-zap",{"title":121,"icon":99,"path":122,"stem":123,"children":124,"page":44},"Framework","\u002Fen\u002Fframework","en\u002F03.framework",[125,128,133,138,142,147,152],{"title":52,"path":126,"stem":127,"icon":99},"\u002Fen\u002Fframework\u002Foverview","en\u002F03.framework\u002F1.overview",{"title":129,"path":130,"stem":131,"icon":132},"Application lifecycle","\u002Fen\u002Fframework\u002Fapp","en\u002F03.framework\u002F2.app","i-lucide-power",{"title":134,"path":135,"stem":136,"icon":137},"Server","\u002Fen\u002Fframework\u002Fserver","en\u002F03.framework\u002F3.server","i-lucide-server",{"title":139,"path":140,"stem":141,"icon":114},"Worker","\u002Fen\u002Fframework\u002Fworker","en\u002F03.framework\u002F4.worker",{"title":143,"path":144,"stem":145,"icon":146},"Realtime","\u002Fen\u002Fframework\u002Frealtime","en\u002F03.framework\u002F5.realtime","i-lucide-radio",{"title":148,"path":149,"stem":150,"icon":151},"Migrations","\u002Fen\u002Fframework\u002Fmigrations","en\u002F03.framework\u002F6.migrations","i-lucide-file-stack",{"title":153,"path":154,"stem":155,"icon":156},"Social login","\u002Fen\u002Fframework\u002Fsocial-login","en\u002F03.framework\u002F7.social-login","i-lucide-log-in",{"title":158,"icon":159,"path":160,"stem":161,"children":162,"page":44},"Reference","i-lucide-book-open","\u002Fen\u002Freference","en\u002F04.reference",[163,168],{"title":164,"path":165,"stem":166,"icon":167},"Configuration","\u002Fen\u002Freference\u002Fconfiguration","en\u002F04.reference\u002F1.configuration","i-lucide-settings",{"title":169,"path":170,"stem":171,"icon":172},"External dependencies","\u002Fen\u002Freference\u002Fdependencies","en\u002F04.reference\u002F2.dependencies","i-lucide-package",{"title":174,"icon":175,"path":176,"stem":177,"children":178,"page":44},"Concepts","i-lucide-lightbulb","\u002Fen\u002Fconcepts","en\u002F05.concepts",[179,184,189,193,198],{"title":180,"path":181,"stem":182,"icon":183},"Architecture","\u002Fen\u002Fconcepts\u002Farchitecture","en\u002F05.concepts\u002F1.architecture","i-lucide-layers",{"title":185,"path":186,"stem":187,"icon":188},"Error model","\u002Fen\u002Fconcepts\u002Ferror-model","en\u002F05.concepts\u002F2.error-model","i-lucide-shield-alert",{"title":164,"path":190,"stem":191,"icon":192},"\u002Fen\u002Fconcepts\u002Fconfiguration","en\u002F05.concepts\u002F3.configuration","i-lucide-settings-2",{"title":194,"path":195,"stem":196,"icon":197},"Codegen pipeline","\u002Fen\u002Fconcepts\u002Fcodegen-pipeline","en\u002F05.concepts\u002F4.codegen-pipeline","i-lucide-file-json",{"title":199,"path":200,"stem":201,"icon":202},"Design patterns","\u002Fen\u002Fconcepts\u002Fdesign-patterns","en\u002F05.concepts\u002F5.design-patterns","i-lucide-puzzle",{"title":204,"icon":205,"path":206,"stem":207,"children":208,"page":44},"auth","i-lucide-shield-check","\u002Fen\u002Fauth","en\u002F06.auth",[209,214,219,224,229],{"title":210,"path":211,"stem":212,"icon":213},"Authentication","\u002Fen\u002Fauth\u002Foverview","en\u002F06.auth\u002F1.overview","i-lucide-key-round",{"title":215,"path":216,"stem":217,"icon":218},"RBAC","\u002Fen\u002Fauth\u002Frbac","en\u002F06.auth\u002F2.rbac","i-lucide-users",{"title":220,"path":221,"stem":222,"icon":223},"Policies","\u002Fen\u002Fauth\u002Fpolicy","en\u002F06.auth\u002F3.policy","i-lucide-gavel",{"title":225,"path":226,"stem":227,"icon":228},"Using auth standalone","\u002Fen\u002Fauth\u002Fstandalone","en\u002F06.auth\u002F4.standalone","i-lucide-plug",{"title":230,"path":231,"stem":232,"icon":156},"Social login with goth, standalone","\u002Fen\u002Fauth\u002Fsocial-standalone","en\u002F06.auth\u002F5.social-standalone",{"title":234,"icon":235,"path":236,"stem":237,"children":238,"page":44},"dbx","i-lucide-database","\u002Fen\u002Fdbx","en\u002F07.dbx",[239,242,246,250,255],{"title":52,"path":240,"stem":241,"icon":235},"\u002Fen\u002Fdbx\u002Foverview","en\u002F07.dbx\u002F1.overview",{"title":243,"path":244,"stem":245,"icon":228},"pgx","\u002Fen\u002Fdbx\u002Fpg","en\u002F07.dbx\u002F2.pg",{"title":247,"path":248,"stem":249,"icon":183},"bun","\u002Fen\u002Fdbx\u002Fbunx","en\u002F07.dbx\u002F3.bunx",{"title":251,"path":252,"stem":253,"icon":254},"Transactions","\u002Fen\u002Fdbx\u002Ftransactions","en\u002F07.dbx\u002F4.transactions","i-lucide-git-merge",{"title":256,"path":257,"stem":258,"icon":79},"Seeders","\u002Fen\u002Fdbx\u002Fseed","en\u002F07.dbx\u002F5.seed",{"title":260,"icon":192,"path":261,"stem":262,"children":263,"page":44},"envconf","\u002Fen\u002Fenvconf","en\u002F08.envconf",[264,267],{"title":52,"path":265,"stem":266,"icon":192},"\u002Fen\u002Fenvconf\u002Foverview","en\u002F08.envconf\u002F1.overview",{"title":268,"path":269,"stem":270,"icon":192},"Recipes","\u002Fen\u002Fenvconf\u002Frecipes","en\u002F08.envconf\u002F2.recipes",{"title":272,"icon":188,"path":273,"stem":274,"children":275,"page":44},"errs","\u002Fen\u002Ferrs","en\u002F09.errs",[276,279,283],{"title":52,"path":277,"stem":278,"icon":188},"\u002Fen\u002Ferrs\u002Foverview","en\u002F09.errs\u002F1.overview",{"title":280,"path":281,"stem":282,"icon":188},"API","\u002Fen\u002Ferrs\u002Fapi","en\u002F09.errs\u002F2.api",{"title":284,"path":285,"stem":286,"icon":188},"Integration","\u002Fen\u002Ferrs\u002Fintegration","en\u002F09.errs\u002F3.integration",{"title":288,"icon":289,"path":290,"stem":291,"children":292,"page":44},"events","i-lucide-workflow","\u002Fen\u002Fevents","en\u002F10.events",[293,297,302],{"title":294,"path":295,"stem":296,"icon":146},"Events","\u002Fen\u002Fevents\u002Foverview","en\u002F10.events\u002F1.overview",{"title":298,"path":299,"stem":300,"icon":301},"Outbox","\u002Fen\u002Fevents\u002Foutbox","en\u002F10.events\u002F2.outbox","i-lucide-inbox",{"title":303,"path":304,"stem":305,"icon":306},"Scheduling","\u002Fen\u002Fevents\u002Fscheduler","en\u002F10.events\u002F3.scheduler","i-lucide-calendar-clock",{"title":308,"icon":309,"path":310,"stem":311,"children":312,"page":44},"httperr","i-lucide-globe","\u002Fen\u002Fhttperr","en\u002F11.httperr",[313,316,321],{"title":52,"path":314,"stem":315,"icon":309},"\u002Fen\u002Fhttperr\u002Foverview","en\u002F11.httperr\u002F1.overview",{"title":317,"path":318,"stem":319,"icon":320},"Error responses","\u002Fen\u002Fhttperr\u002Ferror-responses","en\u002F11.httperr\u002F2.error-responses","i-lucide-octagon-alert",{"title":322,"path":323,"stem":324,"icon":325},"Validation","\u002Fen\u002Fhttperr\u002Fvalidation","en\u002F11.httperr\u002F3.validation","i-lucide-badge-check",{"title":327,"icon":328,"path":329,"stem":330,"children":331,"page":44},"logx","i-lucide-scroll-text","\u002Fen\u002Flogx","en\u002F12.logx",[332,335],{"title":52,"path":333,"stem":334,"icon":328},"\u002Fen\u002Flogx\u002Foverview","en\u002F12.logx\u002F1.overview",{"title":336,"path":337,"stem":338,"icon":47},"Monolog formatter","\u002Fen\u002Flogx\u002Fmonolog","en\u002F12.logx\u002F2.monolog",{"title":340,"icon":341,"path":342,"stem":343,"children":344,"page":44},"mail","i-lucide-mail","\u002Fen\u002Fmail","en\u002F13.mail",[345,348,352],{"title":52,"path":346,"stem":347,"icon":341},"\u002Fen\u002Fmail\u002Foverview","en\u002F13.mail\u002F1.overview",{"title":349,"path":350,"stem":351,"icon":341},"SMTP","\u002Fen\u002Fmail\u002Fsmtp","en\u002F13.mail\u002F2.smtp",{"title":353,"path":354,"stem":355,"icon":341},"MJML","\u002Fen\u002Fmail\u002Fmjml","en\u002F13.mail\u002F3.mjml",{"title":357,"icon":358,"path":359,"stem":360,"children":361,"page":44},"notify","i-lucide-bell","\u002Fen\u002Fnotify","en\u002F14.notify",[362,365,369],{"title":52,"path":363,"stem":364,"icon":358},"\u002Fen\u002Fnotify\u002Foverview","en\u002F14.notify\u002F1.overview",{"title":366,"path":367,"stem":368,"icon":358},"Database channel","\u002Fen\u002Fnotify\u002Fdatabase","en\u002F14.notify\u002F2.database",{"title":370,"path":371,"stem":372,"icon":358},"Broadcast channel","\u002Fen\u002Fnotify\u002Fbroadcast","en\u002F14.notify\u002F3.broadcast",{"title":374,"icon":375,"path":376,"stem":377,"children":378,"page":44},"paginate","i-lucide-list-ordered","\u002Fen\u002Fpaginate","en\u002F15.paginate",[379,382],{"title":52,"path":380,"stem":381,"icon":375},"\u002Fen\u002Fpaginate\u002Foverview","en\u002F15.paginate\u002F1.overview",{"title":383,"path":384,"stem":385,"icon":39},"Cursor pagination","\u002Fen\u002Fpaginate\u002Fcursor","en\u002F15.paginate\u002F2.cursor",{"title":387,"icon":183,"path":388,"stem":389,"children":390,"page":44},"queue","\u002Fen\u002Fqueue","en\u002F16.queue",[391,394],{"title":52,"path":392,"stem":393,"icon":375},"\u002Fen\u002Fqueue\u002Foverview","en\u002F16.queue\u002F1.overview",{"title":395,"path":396,"stem":397,"icon":183},"Tasks","\u002Fen\u002Fqueue\u002Ftasks","en\u002F16.queue\u002F2.tasks",{"title":399,"icon":400,"path":401,"stem":402,"children":403,"page":44},"storage","i-lucide-hard-drive","\u002Fen\u002Fstorage","en\u002F17.storage",[404,407,411,415,420],{"title":52,"path":405,"stem":406,"icon":400},"\u002Fen\u002Fstorage\u002Foverview","en\u002F17.storage\u002F1.overview",{"title":408,"path":409,"stem":410,"icon":400},"Disk API","\u002Fen\u002Fstorage\u002Fdisk-api","en\u002F17.storage\u002F2.disk-api",{"title":412,"path":413,"stem":414,"icon":400},"Memory and local disk","\u002Fen\u002Fstorage\u002Flocal","en\u002F17.storage\u002F3.local",{"title":416,"path":417,"stem":418,"icon":419},"S3","\u002Fen\u002Fstorage\u002Fs3","en\u002F17.storage\u002F4.s3","i-lucide-cloud",{"title":421,"path":422,"stem":423,"icon":424},"Testing","\u002Fen\u002Fstorage\u002Ftesting","en\u002F17.storage\u002F5.testing","i-lucide-flask-conical",{"title":426,"icon":427,"path":428,"stem":429,"children":430,"page":44},"telemetry","i-lucide-activity","\u002Fen\u002Ftelemetry","en\u002F18.telemetry",[431,434,438,443],{"title":52,"path":432,"stem":433,"icon":427},"\u002Fen\u002Ftelemetry\u002Foverview","en\u002F18.telemetry\u002F1.overview",{"title":435,"path":436,"stem":437,"icon":328},"Logging","\u002Fen\u002Ftelemetry\u002Flogging","en\u002F18.telemetry\u002F2.logging",{"title":439,"path":440,"stem":441,"icon":442},"OpenTelemetry","\u002Fen\u002Ftelemetry\u002Fopentelemetry","en\u002F18.telemetry\u002F3.opentelemetry","i-lucide-radar",{"title":444,"path":445,"stem":446,"icon":447},"Sentry","\u002Fen\u002Ftelemetry\u002Fsentry","en\u002F18.telemetry\u002F4.sentry","i-lucide-bug",{"id":449,"title":52,"body":450,"description":798,"extension":799,"links":800,"meta":801,"navigation":802,"path":126,"seo":803,"stem":127,"__hash__":804},"docs_en\u002Fen\u002F03.framework\u002F1.overview.md",{"type":451,"value":452,"toc":790},"minimark",[453,471,476,578,600,604,645,649,652,677,689,704,714,718,735,739,786],[454,455,456,460,461,466,467,470],"p",{},[457,458,459],"code",{},"github.com\u002Fgp-system\u002Fframework"," is a thin chassis on top of ",[462,463,465],"a",{"href":464},"\u002Fen\u002Fconcepts\u002Farchitecture#module-map","14 standalone Go modules",": each module (error handling, config loading, the database layer, the async stack, auth, mail, notifications, storage, telemetry, ...) is its own repository and its own ",[457,468,469],{},"go.mod",", versioned independently of the rest, usable on its own in any Go program. What's left in the framework is a scaffolding CLI and four runtime chassis packages that compose those modules into a running service.",[472,473,475],"h2",{"id":474},"whats-in-the-framework","What's in the framework",[477,478,479,492],"table",{},[480,481,482],"thead",{},[483,484,485,489],"tr",{},[486,487,488],"th",{},"Package",[486,490,491],{},"What it does",[493,494,495,508,533,545,557],"tbody",{},[483,496,497,505],{},[498,499,500],"td",{},[462,501,502],{"href":130},[457,503,504],{},"app",[498,506,507],{},"the signal-driven graceful-shutdown process lifecycle every other chassis package sits on: drain, closers (LIFO), telemetry flush",[483,509,510,517],{},[498,511,512],{},[462,513,514],{"href":135},[457,515,516],{},"server",[498,518,519,520,523,524,523,527,523,530],{},"the chi-based HTTP chassis: ",[457,521,522],{},"Config",", ",[457,525,526],{},"Run",[457,528,529],{},"RegisterFunc",[457,531,532],{},"StrictValidator",[483,534,535,542],{},[498,536,537],{},[462,538,539],{"href":140},[457,540,541],{},"worker",[498,543,544],{},"the background-processing chassis: asynq server + outbox relay + schedule runner, one binary",[483,546,547,554],{},[498,548,549],{},[462,550,551],{"href":144},[457,552,553],{},"realtime",[498,555,556],{},"the centrifuge-based WebSocket\u002FSSE gateway that pushes notifications to connected clients",[483,558,559,566],{},[498,560,561],{},[462,562,563],{"href":53},[457,564,565],{},"cmd\u002Fgpsystem",[498,567,568,569,523,571,523,573,523,575,577],{},"the scaffolding CLI: ",[457,570,81],{},[457,572,86],{},[457,574,91],{},[457,576,101],{},", and the rest of the generators",[454,579,580,581,584,585,588,589,592,593,596,597,599],{},"Two more framework-generated (not standalone-module) topics live alongside them, because they don't have a module home of their own: ",[462,582,583],{"href":149},"migrations"," (the ",[457,586,587],{},"cmd\u002Fmigrate"," convention, built on ",[457,590,591],{},"dbx\u002Fpg",") and ",[462,594,595],{"href":154},"social login"," (OAuth2 provider wiring generated on top of the ",[457,598,204],{}," module).",[472,601,603],{"id":602},"a-framework-that-composes-not-wraps","A framework that composes, not wraps",[454,605,606,607,611,612,523,615,618,619,622,623,626,627,631,632,523,635,523,638,641,642,644],{},"The framework does not hide the modules behind an interface, a container or a facade: it ",[608,609,610],"strong",{},"composes"," them. ",[457,613,614],{},"server.Run",[457,616,617],{},"worker.Run"," and ",[457,620,621],{},"realtime.Run"," each wire a chosen subset of the 14 modules into a runnable process, and the CLI generates that wiring so you rarely write it by hand, but the wiring itself stays plain, explicit Go code in your ",[457,624,625],{},"main.go",". This is the same ",[462,628,630],{"href":629},"\u002Fen\u002Fconcepts\u002Farchitecture#centralize-dont-abstract","\"centralize, don't abstract\""," principle the whole project is built on: raw types from the underlying libraries (",[457,633,634],{},"chi.Router",[457,636,637],{},"*asynq.Task",[457,639,640],{},"centrifuge.Node",") are visible in the framework's own API rather than wrapped away. The ",[462,643,180],{"href":181}," page has the full module map this thin layer sits on top of.",[472,646,648],{"id":647},"install","Install",[454,650,651],{},"For the CLI:",[653,654,659],"pre",{"className":655,"code":656,"language":657,"meta":658,"style":658},"language-sh shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","go install github.com\u002Fgp-system\u002Fframework\u002Fcmd\u002Fgpsystem@latest\n","sh","",[457,660,661],{"__ignoreMap":658},[662,663,666,670,674],"span",{"class":664,"line":665},"line",1,[662,667,669],{"class":668},"sBMFI","go",[662,671,673],{"class":672},"sfazB"," install",[662,675,676],{"class":672}," github.com\u002Fgp-system\u002Fframework\u002Fcmd\u002Fgpsystem@latest\n",[454,678,679,680,523,682,523,684,523,686,688],{},"For using the chassis packages (",[457,681,504],{},[457,683,516],{},[457,685,541],{},[457,687,553],{},") in a project:",[653,690,692],{"className":655,"code":691,"language":657,"meta":658,"style":658},"go get github.com\u002Fgp-system\u002Fframework@latest\n",[457,693,694],{"__ignoreMap":658},[662,695,696,698,701],{"class":664,"line":665},[662,697,669],{"class":668},[662,699,700],{"class":672}," get",[662,702,703],{"class":672}," github.com\u002Fgp-system\u002Fframework@latest\n",[454,705,706,707,710,711,713],{},"Scaffolding a new project with ",[457,708,709],{},"gpsystem new project"," adds this dependency to the generated ",[457,712,469],{}," automatically, so you rarely run the second command by hand; it matters mainly if you're wiring a chassis package into an existing, hand-rolled project.",[472,715,717],{"id":716},"why-use-the-framework-at-all","Why use the framework at all",[454,719,720,721,523,723,523,725,727,728,730,731,734],{},"Nothing here is required. Every one of the 14 modules works standalone, in any Go program, with no framework installed: ",[457,722,591],{},[457,724,204],{},[457,726,387],{},", and the rest have zero dependency on ",[457,729,459],{},". The framework exists to save you from hand-wiring lifecycle, telemetry bootstrap, HTTP routing, and worker\u002Ftask dispatch yourself, and from writing the TypeSpec→OpenAPI→server-code generators that turn a spec into a runnable surface. If you don't want that (say, you're bolting one module onto an existing service), skip the framework and import the modules you need directly; see ",[462,732,733],{"href":12},"Getting started"," for how the pieces fit together either way.",[472,736,738],{"id":737},"where-to-next","Where to next",[740,741,742,752,757,762,767,775,780],"ul",{},[743,744,745,747,748,751],"li",{},[462,746,129],{"href":130},": the shared ",[457,749,750],{},"app.Run"," skeleton.",[743,753,754,756],{},[462,755,134],{"href":135},": the HTTP chassis.",[743,758,759,761],{},[462,760,139],{"href":140},": the background-processing chassis.",[743,763,764,766],{},[462,765,143],{"href":144},": the WebSocket\u002FSSE gateway.",[743,768,769,771,772,774],{},[462,770,148],{"href":149},": the ",[457,773,587],{}," convention.",[743,776,777,779],{},[462,778,153],{"href":154},": OAuth2 provider wiring.",[743,781,782,785],{},[462,783,784],{"href":53},"CLI overview",": the scaffolding commands.",[787,788,789],"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 .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":658,"searchDepth":791,"depth":791,"links":792},2,[793,794,795,796,797],{"id":474,"depth":791,"text":475},{"id":602,"depth":791,"text":603},{"id":647,"depth":791,"text":648},{"id":716,"depth":791,"text":717},{"id":737,"depth":791,"text":738},"What stays in the thin gpsystem framework and how it composes the standalone modules.","md",null,{},{"icon":99},{"title":52,"description":798},"kdA-670Yd8aaITZVuIfh_CLJ_p3U_WngndKkazSQkjE",[806,808],{"title":116,"path":117,"stem":118,"description":807,"icon":119,"children":-1},"Add a named database connection to a module, with its own pool and connector.",{"title":129,"path":130,"stem":131,"description":809,"icon":132,"children":-1},"The app package: the signal-driven graceful shutdown every gpsystem binary sits on.",1787346808664]