[{"data":1,"prerenderedAt":592},["ShallowReactive",2],{"navigation":3,"page-\u002Fresources\u002Fweb-services":105,"surround-\u002Fresources\u002Fweb-services":587},[4,17,25,48,63,74,86],{"title":5,"path":6,"stem":7,"children":8,"icon":16,"exact":11},"Getting started","\u002Fgetting-started","1.getting-started\u002F1.index",[9,12],{"title":10,"path":6,"stem":7,"exact":11,"children":-1},"Introduction",true,{"title":13,"path":14,"stem":15,"exact":11,"children":-1},"Quickstart","\u002Fgetting-started\u002Fquickstart","1.getting-started\u002F2.quickstart","i-lucide-rocket",{"title":18,"path":19,"stem":20,"children":21,"icon":24,"exact":11},"Concepts","\u002Fconcepts","2.concepts\u002F1.index",[22],{"title":23,"path":19,"stem":20,"exact":11,"children":-1},"The Kuppit model","i-lucide-shapes",{"title":26,"path":27,"stem":28,"children":29,"icon":47,"exact":11},"Deployments","\u002Fdeployments","3.deployments\u002F1.index",[30,31,35,39,43],{"title":26,"path":27,"stem":28,"exact":11,"children":-1},{"title":32,"path":33,"stem":34,"exact":11,"children":-1},"Builds","\u002Fdeployments\u002Fbuilds","3.deployments\u002F2.builds",{"title":36,"path":37,"stem":38,"exact":11,"children":-1},"Redeploy and roll back","\u002Fdeployments\u002Fredeploy-and-rollback","3.deployments\u002F3.redeploy-and-rollback",{"title":40,"path":41,"stem":42,"exact":11,"children":-1},"Logs","\u002Fdeployments\u002Flogs","3.deployments\u002F4.logs",{"title":44,"path":45,"stem":46,"exact":11,"children":-1},"When a deployment fails","\u002Fdeployments\u002Fwhen-a-deployment-fails","3.deployments\u002F5.when-a-deployment-fails","i-lucide-cloud-upload",{"title":49,"path":50,"stem":51,"children":52,"icon":62,"exact":11},"Resources","\u002Fresources","4.resources\u002F1.index",[53,54,58],{"title":49,"path":50,"stem":51,"exact":11,"children":-1},{"title":55,"path":56,"stem":57,"exact":11,"children":-1},"Web services","\u002Fresources\u002Fweb-services","4.resources\u002F2.web-services",{"title":59,"path":60,"stem":61,"exact":11,"children":-1},"PostgreSQL","\u002Fresources\u002Fpostgresql","4.resources\u002F3.postgresql","i-lucide-boxes",{"title":64,"icon":65,"path":66,"stem":67,"children":68,"page":73,"exact":11},"Configuration","i-lucide-sliders-horizontal","\u002Fconfiguration","5.configuration",[69],{"title":70,"path":71,"stem":72,"exact":11,"children":-1},"Environment variables","\u002Fconfiguration\u002Fvariables","5.configuration\u002F1.variables",false,{"title":75,"path":76,"stem":77,"children":78,"icon":85,"exact":11},"Domains","\u002Fdomains","7.domains\u002F1.index",[79,81],{"title":80,"path":76,"stem":77,"exact":11,"children":-1},"Hostnames",{"title":82,"path":83,"stem":84,"exact":11,"children":-1},"Custom domains","\u002Fdomains\u002Fcustom-domains","7.domains\u002F2.custom-domains","i-lucide-globe",{"title":87,"path":88,"stem":89,"children":90,"icon":104,"exact":11},"Environments","\u002Fenvironments","8.environments\u002F1.index",[91,92,96,100],{"title":87,"path":88,"stem":89,"exact":11,"children":-1},{"title":93,"path":94,"stem":95,"exact":11,"children":-1},"Preview environments","\u002Fenvironments\u002Fpreview-environments","8.environments\u002F2.preview-environments",{"title":97,"path":98,"stem":99,"exact":11,"children":-1},"Named environments","\u002Fenvironments\u002Fnamed-environments","8.environments\u002F3.named-environments",{"title":101,"path":102,"stem":103,"exact":11,"children":-1},"Deleting an environment","\u002Fenvironments\u002Fdeleting-an-environment","8.environments\u002F4.deleting-an-environment","i-lucide-git-branch",{"id":106,"title":55,"badge":107,"body":108,"category":107,"description":581,"draft":73,"extension":582,"links":107,"meta":583,"navigation":11,"path":56,"seo":584,"sitemap":585,"stem":57,"__hash__":586},"docs\u002F4.resources\u002F2.web-services.md",null,{"type":109,"value":110,"toc":571},"minimark",[111,115,123,128,148,151,155,158,217,220,259,270,273,281,287,379,389,405,408,411,434,451,455,466,511,515,540,550,554,564,567],[112,113,114],"p",{},"A web service is an application built from your repository and deployed on a public hostname. It is the resource that has deployments, logs, variables and domains.",[112,116,117,118,122],{},"Every project starts with one, named ",[119,120,121],"code",{},"web",", proposed from the repository when the project is created. An environment can hold more than one web service, for example an API next to a frontend, and each has its own hostname and its own deployments.",[124,125,127],"h2",{"id":126},"adding-a-web-service","Adding a web service",[112,129,130,131,135,136,139,140,143,144,147],{},"On an environment's ",[132,133,134],"strong",{},"Overview",", choose ",[132,137,138],{},"Add resource",", then ",[132,141,142],{},"Web service",". Kuppit analyses the branch the environment deploys and proposes what to build, so a second service can point at a different ",[132,145,146],{},"Root directory"," of the same repository.",[112,149,150],{},"A service can be added to Production or a custom environment. A preview environment's services are copied from Production when the pull request opens and are removed when it closes, so nothing can be added to one by hand.",[124,152,154],{"id":153},"how-a-service-is-built","How a service is built",[112,156,157],{},"Kuppit builds a container image for every deployment, one of two ways.",[159,160,161,177],"table",{},[162,163,164],"thead",{},[165,166,167,171,174],"tr",{},[168,169,170],"th",{},"Strategy",[168,172,173],{},"When Kuppit chooses it",[168,175,176],{},"What it needs",[178,179,180,197],"tbody",{},[165,181,182,188,194],{},[183,184,185],"td",{},[132,186,187],{},"Dockerfile",[183,189,190,191,193],{},"A ",[119,192,187],{}," exists in the root directory.",[183,195,196],{},"The Dockerfile, and whatever it copies.",[165,198,199,204,207],{},[183,200,201],{},[132,202,203],{},"Automatic",[183,205,206],{},"No Dockerfile, and a Node.js application is detected.",[183,208,190,209,212,213,216],{},[119,210,211],{},"package.json"," with a recognised framework or a ",[119,214,215],{},"start"," script.",[112,218,219],{},"An automatic build supports:",[221,222,223,232,249],"ul",{},[224,225,226,229,230,216],"li",{},[132,227,228],{},"Frameworks:"," Nuxt, Next.js, Express, or plain Node.js with a ",[119,231,215],{},[224,233,234,237,238,240,241,244,245,248],{},[132,235,236],{},"Node.js:"," 24 or 22. Kuppit reads the version from ",[119,239,211],{}," ",[119,242,243],{},"engines"," or ",[119,246,247],{},".nvmrc"," and defaults to 24.",[224,250,251,254,255,258],{},[132,252,253],{},"Package managers:"," pnpm, npm or Yarn, from the lockfile or the ",[119,256,257],{},"packageManager"," field.",[112,260,261,262,265,266,269],{},"Kuppit records what it detected as the service's ",[132,263,264],{},"Build configuration",": root directory, framework, Node.js version, package manager, build command, start command and port. Each can be overridden on the service's ",[132,267,268],{},"Settings"," tab. Clearing the build command removes a detected build step.",[112,271,272],{},"When a later commit changes the shape of the repository, for example by adding a Dockerfile, Kuppit says so and asks you to inspect the latest commit before saving new settings.",[124,274,276,277,280],{"id":275},"the-port-contract","The ",[119,278,279],{},"PORT"," contract",[112,282,283,284,286],{},"Kuppit starts your container with ",[119,285,279],{}," set and routes traffic to that port. Your server must listen on it, on all interfaces:",[288,289,295],"pre",{"className":290,"code":291,"filename":292,"language":293,"meta":294,"style":294},"language-ts shiki shiki-themes material-theme-lighter github-light github-dark","const port = Number(process.env.PORT ?? 8080)\n\nserver.listen(port, '0.0.0.0')\n","server.ts","ts","",[119,296,297,343,349],{"__ignoreMap":294},[298,299,302,306,310,314,318,322,326,329,331,333,336,340],"span",{"class":300,"line":301},"line",1,[298,303,305],{"class":304},"sbsja","const",[298,307,309],{"class":308},"s_hVV"," port",[298,311,313],{"class":312},"smGrS"," =",[298,315,317],{"class":316},"sGLFI"," Number",[298,319,321],{"class":320},"su5hD","(process",[298,323,325],{"class":324},"sP7_E",".",[298,327,328],{"class":320},"env",[298,330,325],{"class":324},[298,332,279],{"class":308},[298,334,335],{"class":312}," ??",[298,337,339],{"class":338},"srdBf"," 8080",[298,341,342],{"class":320},")\n",[298,344,346],{"class":300,"line":345},2,[298,347,348],{"emptyLinePlaceholder":11},"\n",[298,350,352,355,357,360,363,366,370,374,377],{"class":300,"line":351},3,[298,353,354],{"class":320},"server",[298,356,325],{"class":324},[298,358,359],{"class":316},"listen",[298,361,362],{"class":320},"(port",[298,364,365],{"class":324},",",[298,367,369],{"class":368},"sjJ54"," '",[298,371,373],{"class":372},"s_sjI","0.0.0.0",[298,375,376],{"class":368},"'",[298,378,342],{"class":320},[112,380,381,382,384,385,388],{},"Nuxt and Next.js read ",[119,383,279],{}," themselves. Express and plain Node.js applications must read it as above. A server bound to ",[119,386,387],{},"localhost"," or to a hard-coded port does not receive traffic, and the deployment fails its health check.",[112,390,391,393,394,393,397,400,401,404],{},[119,392,279],{},", ",[119,395,396],{},"K_SERVICE",[119,398,399],{},"K_REVISION"," and ",[119,402,403],{},"K_CONFIGURATION"," are set by the runtime and cannot be used as variable names.",[124,406,26],{"id":407},"deployments",[112,409,410],{},"A deployment is one commit becoming one running revision of the service. Kuppit creates one:",[221,412,413,416,423],{},[224,414,415],{},"when you push to the branch the environment deploys,",[224,417,418,419,422],{},"when you choose ",[132,420,421],{},"Deploy"," on the service,",[224,424,425,426,429,430,433],{},"when you ",[132,427,428],{},"Redeploy"," a commit or ",[132,431,432],{},"Roll back"," to a previous deployment.",[112,435,436,437,439,440,443,444,400,447,450],{},"A new revision takes traffic only after it passes a health check. Until then the previous revision keeps serving, so a failed deployment never takes the service down. The service's ",[132,438,26],{}," tab lists the ",[132,441,442],{},"Live"," deployment, its history, and the ",[132,445,446],{},"Build",[132,448,449],{},"Runtime"," logs of each.",[124,452,454],{"id":453},"service-health","Service health",[112,456,457,458,461,462,465],{},"Service health describes whether the currently deployed service is serving successfully. It is separate from deployment status, which describes the lifecycle of an individual deployment: an environment can show a deployment ",[132,459,460],{},"Building"," while the service inside it is still ",[132,463,464],{},"Healthy",", because the previous revision is still up.",[159,467,468,478],{},[162,469,470],{},[165,471,472,475],{},[168,473,474],{},"Health",[168,476,477],{},"Meaning",[178,479,480,487,495,503],{},[165,481,482,484],{},[183,483,464],{},[183,485,486],{},"Serving production traffic.",[165,488,489,492],{},[183,490,491],{},"Starting",[183,493,494],{},"Reaching production for the first time.",[165,496,497,500],{},[183,498,499],{},"Failed",[183,501,502],{},"Nothing has reached production.",[165,504,505,508],{},[183,506,507],{},"Not deployed",[183,509,510],{},"Nothing has been deployed yet.",[124,512,514],{"id":513},"hostnames-and-domains","Hostnames and domains",[112,516,517,518,521,522,525,526,528,529,532,533,536,537,325],{},"Every web service receives a stable hostname on ",[119,519,520],{},"kuppit.app"," when it is created, of the form ",[119,523,524],{},"\u003Cproject>-\u003Cservice>-\u003Cid>.kuppit.app",". A service named ",[119,527,121],{}," drops the service part, so a project named ",[119,530,531],{},"acme"," gets ",[119,534,535],{},"acme-a1b2c3.kuppit.app",". A preview environment prefixes its name: ",[119,538,539],{},"pr-42-acme-a1b2c3.kuppit.app",[112,541,542,543,545,546,549],{},"Custom domains are attached on the service's ",[132,544,75],{}," tab. A subdomain takes a CNAME to ",[119,547,548],{},"domains.kuppit.app","; an apex domain takes an ALIAS or ANAME record. Kuppit verifies ownership with a TXT record and issues the certificate.",[124,551,553],{"id":552},"variables","Variables",[112,555,556,557,560,561,325],{},"A web service has its own variables, and inherits every variable set on its environment. Values can be literals or references to variables another resource exposes, such as a database's ",[119,558,559],{},"DATABASE_URL",". See ",[562,563,70],"a",{"href":71},[112,565,566],{},"A web service does not expose any variables of its own for other resources to reference.",[568,569,570],"style",{},"html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}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":294,"searchDepth":351,"depth":351,"links":572},[573,574,575,577,578,579,580],{"id":126,"depth":345,"text":127},{"id":153,"depth":345,"text":154},{"id":275,"depth":345,"text":576},"The PORT contract",{"id":407,"depth":345,"text":26},{"id":453,"depth":345,"text":454},{"id":513,"depth":345,"text":514},{"id":552,"depth":345,"text":553},"What a web service is, how Kuppit builds one from your repository, and what your application must do to run on it.","md",{},{"title":55,"description":581},{"loc":56},"2JB9dfZYkRuica_LUq1ldKhjAboeNv-YBKp1Z4zG2nE",[588,590],{"title":49,"path":50,"stem":51,"description":589,"children":-1},"The things your application runs or depends on, and how they connect.",{"title":59,"path":60,"stem":61,"description":591,"children":-1},"Provision a managed PostgreSQL database in an environment and connect your services to it through variables.",1788534985201]