[{"data":1,"prerenderedAt":909},["ShallowReactive",2],{"navigation_docs":3,"section-navigation-docs":130,"-docs-guides-express":164,"-docs-guides-express-surround":817,"doc-previews":822},[4,8,50,54,58,62,66,70,74,78,82,86,90,94,98,102,106,110,114,118,122,126],{"title":5,"path":6,"stem":7},"Quickstart","\u002Fdocs\u002Fquickstart","docs\u002F01.quickstart",{"title":9,"path":10,"stem":11,"children":12},"Guides","\u002Fdocs\u002Fguides","docs\u002F02.guides\u002Findex",[13,14,18,22,26,30,34,38,42,46],{"title":9,"path":10,"stem":11},{"title":15,"path":16,"stem":17},"Next.js","\u002Fdocs\u002Fguides\u002Fnextjs","docs\u002F02.guides\u002F1.nextjs",{"title":19,"path":20,"stem":21},"Nuxt","\u002Fdocs\u002Fguides\u002Fnuxt","docs\u002F02.guides\u002F2.nuxt",{"title":23,"path":24,"stem":25},"SvelteKit","\u002Fdocs\u002Fguides\u002Fsveltekit","docs\u002F02.guides\u002F3.sveltekit",{"title":27,"path":28,"stem":29},"Astro","\u002Fdocs\u002Fguides\u002Fastro","docs\u002F02.guides\u002F4.astro",{"title":31,"path":32,"stem":33},"Express","\u002Fdocs\u002Fguides\u002Fexpress","docs\u002F02.guides\u002F5.express",{"title":35,"path":36,"stem":37},"FastAPI","\u002Fdocs\u002Fguides\u002Ffastapi","docs\u002F02.guides\u002F6.fastapi",{"title":39,"path":40,"stem":41},"Django","\u002Fdocs\u002Fguides\u002Fdjango","docs\u002F02.guides\u002F7.django",{"title":43,"path":44,"stem":45},"Laravel","\u002Fdocs\u002Fguides\u002Flaravel","docs\u002F02.guides\u002F8.laravel",{"title":47,"path":48,"stem":49},"Go","\u002Fdocs\u002Fguides\u002Fgo","docs\u002F02.guides\u002F9.go",{"title":51,"path":52,"stem":53},"Services","\u002Fdocs\u002Fservices","docs\u002F03.services",{"title":55,"path":56,"stem":57},"Deployments","\u002Fdocs\u002Fdeployments","docs\u002F04.deployments",{"title":59,"path":60,"stem":61},"Builds","\u002Fdocs\u002Fbuilds","docs\u002F05.builds",{"title":63,"path":64,"stem":65},"Variables","\u002Fdocs\u002Fvariables","docs\u002F06.variables",{"title":67,"path":68,"stem":69},"Domains","\u002Fdocs\u002Fdomains","docs\u002F07.domains",{"title":71,"path":72,"stem":73},"PostgreSQL","\u002Fdocs\u002Fpostgres","docs\u002F08.postgres",{"title":75,"path":76,"stem":77},"Object storage","\u002Fdocs\u002Fobject-storage","docs\u002F09.object-storage",{"title":79,"path":80,"stem":81},"Volumes","\u002Fdocs\u002Fvolumes","docs\u002F10.volumes",{"title":83,"path":84,"stem":85},"Key-value store","\u002Fdocs\u002Fredis","docs\u002F11.redis",{"title":87,"path":88,"stem":89},"Workspaces","\u002Fdocs\u002Fworkspaces","docs\u002F12.workspaces",{"title":91,"path":92,"stem":93},"Projects","\u002Fdocs\u002Fprojects","docs\u002F13.projects",{"title":95,"path":96,"stem":97},"Environments","\u002Fdocs\u002Fenvironments","docs\u002F14.environments",{"title":99,"path":100,"stem":101},"Eject","\u002Fdocs\u002Feject","docs\u002F15.eject",{"title":103,"path":104,"stem":105},"API","\u002Fdocs\u002Fapi","docs\u002F16.api",{"title":107,"path":108,"stem":109},"CLI","\u002Fdocs\u002Fcli","docs\u002F17.cli",{"title":111,"path":112,"stem":113},"Claude Plugin & MCP","\u002Fdocs\u002Fclaude-plugin","docs\u002F18.claude-plugin",{"title":115,"path":116,"stem":117},"Metrics","\u002Fdocs\u002Fmetrics","docs\u002F19.metrics",{"title":119,"path":120,"stem":121},"Logs","\u002Fdocs\u002Flogs","docs\u002F20.logs",{"title":123,"path":124,"stem":125},"Billing","\u002Fdocs\u002Fbilling","docs\u002F21.billing",{"title":127,"path":128,"stem":129},"Self-hosting","\u002Fdocs\u002Fself-hosting","docs\u002F22.self-hosting",[131,132,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163],{"title":5,"path":6,"stem":7},{"title":9,"path":10,"stem":11,"children":133},[134,135,136,137,138,139,140,141,142,143],{"title":9,"path":10,"stem":11},{"title":15,"path":16,"stem":17},{"title":19,"path":20,"stem":21},{"title":23,"path":24,"stem":25},{"title":27,"path":28,"stem":29},{"title":31,"path":32,"stem":33},{"title":35,"path":36,"stem":37},{"title":39,"path":40,"stem":41},{"title":43,"path":44,"stem":45},{"title":47,"path":48,"stem":49},{"title":51,"path":52,"stem":53},{"title":55,"path":56,"stem":57},{"title":59,"path":60,"stem":61},{"title":63,"path":64,"stem":65},{"title":67,"path":68,"stem":69},{"title":71,"path":72,"stem":73},{"title":75,"path":76,"stem":77},{"title":79,"path":80,"stem":81},{"title":83,"path":84,"stem":85},{"title":87,"path":88,"stem":89},{"title":91,"path":92,"stem":93},{"title":95,"path":96,"stem":97},{"title":99,"path":100,"stem":101},{"title":103,"path":104,"stem":105},{"title":107,"path":108,"stem":109},{"title":111,"path":112,"stem":113},{"title":115,"path":116,"stem":117},{"title":119,"path":120,"stem":121},{"title":123,"path":124,"stem":125},{"title":127,"path":128,"stem":129},{"id":165,"title":166,"body":167,"description":810,"extension":811,"links":812,"meta":813,"navigation":814,"path":32,"seo":815,"stem":33,"__hash__":816},"docs\u002Fdocs\u002F02.guides\u002F5.express.md","Deploy an Express API",{"type":168,"value":169,"toc":802},"minimark",[170,174,179,199,270,274,285,523,526,530,533,540,608,611,620,624,638,709,712,719,723,726,772,775,779,798],[171,172,173],"p",{},"Express has no build step, no framework conventions and no opinions about deployment, which means the platform has less to detect. Three things make an Express app deployable here, and all three are things you would want anyway.",[175,176,178],"h2",{"id":177},"one-a-start-script","One: a start script",[171,180,181,182,186,187,190,191,194,195,198],{},"Detection looks for a ",[183,184,185],"code",{},"start"," script in ",[183,188,189],{},"package.json",", then a ",[183,192,193],{},"main"," field, then ",[183,196,197],{},"index.js",". A project with none of those produces no start command, and the service will build but never run.",[200,201,206],"pre",{"className":202,"code":203,"language":204,"meta":205,"style":205},"language-json shiki shiki-themes gruvbox-dark-medium gruvbox-dark-medium gruvbox-dark-medium","{\n  \"scripts\": {\n    \"start\": \"node index.js\"\n  }\n}\n","json","",[183,207,208,217,236,258,264],{"__ignoreMap":205},[209,210,213],"span",{"class":211,"line":212},"line",1,[209,214,216],{"class":215},"si-ur","{\n",[209,218,220,223,227,230,233],{"class":211,"line":219},2,[209,221,222],{"class":215},"  \"",[209,224,226],{"class":225},"slqHI","scripts",[209,228,229],{"class":215},"\"",[209,231,232],{"class":215},":",[209,234,235],{"class":215}," {\n",[209,237,239,242,244,246,248,251,255],{"class":211,"line":238},3,[209,240,241],{"class":215},"    \"",[209,243,185],{"class":225},[209,245,229],{"class":215},[209,247,232],{"class":215},[209,249,250],{"class":215}," \"",[209,252,254],{"class":253},"sIi04","node index.js",[209,256,257],{"class":215},"\"\n",[209,259,261],{"class":211,"line":260},4,[209,262,263],{"class":215},"  }\n",[209,265,267],{"class":211,"line":266},5,[209,268,269],{"class":215},"}\n",[175,271,273],{"id":272},"two-listen-on-the-port-you-are-given","Two: listen on the port you are given",[171,275,276,277,280,281,284],{},"Lucity sets ",[183,278,279],{},"PORT"," in the container. Read it, and keep a local default so ",[183,282,283],{},"npm run dev"," still works:",[200,286,290],{"className":287,"code":288,"language":289,"meta":205,"style":205},"language-js shiki shiki-themes gruvbox-dark-medium gruvbox-dark-medium gruvbox-dark-medium","import express from 'express';\n\nconst app = express();\nconst port = process.env.PORT || 3000;\n\napp.get('\u002F', (request, response) => {\n  response.json({ message: 'Deployed on Lucity' });\n});\n\napp.listen(port, () => console.log(`listening on ${port}`));\n","js",[183,291,292,317,323,345,376,380,423,457,467,472],{"__ignoreMap":205},[209,293,294,298,301,304,307,311,314],{"class":211,"line":212},[209,295,297],{"class":296},"sJHtc","import",[209,299,300],{"class":253}," express",[209,302,303],{"class":296}," from",[209,305,306],{"class":215}," '",[209,308,310],{"class":309},"sQLXx","express",[209,312,313],{"class":215},"'",[209,315,316],{"class":215},";\n",[209,318,319],{"class":211,"line":219},[209,320,322],{"emptyLinePlaceholder":321},true,"\n",[209,324,325,329,332,336,339,343],{"class":211,"line":238},[209,326,328],{"class":327},"sjx4h","const",[209,330,331],{"class":253}," app",[209,333,335],{"class":334},"s3drp"," =",[209,337,300],{"class":338},"sX5TD",[209,340,342],{"class":341},"spvMa","()",[209,344,316],{"class":215},[209,346,347,349,352,354,357,360,363,365,367,370,374],{"class":211,"line":260},[209,348,328],{"class":327},[209,350,351],{"class":253}," port",[209,353,335],{"class":334},[209,355,356],{"class":253}," process",[209,358,359],{"class":215},".",[209,361,362],{"class":253},"env",[209,364,359],{"class":215},[209,366,279],{"class":253},[209,368,369],{"class":296}," ||",[209,371,373],{"class":372},"s1Tsi"," 3000",[209,375,316],{"class":215},[209,377,378],{"class":211,"line":266},[209,379,322],{"emptyLinePlaceholder":321},[209,381,383,386,388,391,394,396,399,401,404,407,410,412,415,418,421],{"class":211,"line":382},6,[209,384,385],{"class":253},"app",[209,387,359],{"class":215},[209,389,390],{"class":338},"get",[209,392,393],{"class":341},"(",[209,395,313],{"class":215},[209,397,398],{"class":309},"\u002F",[209,400,313],{"class":215},[209,402,403],{"class":215},",",[209,405,406],{"class":215}," (",[209,408,409],{"class":253},"request",[209,411,403],{"class":215},[209,413,414],{"class":253}," response",[209,416,417],{"class":215},")",[209,419,420],{"class":327}," =>",[209,422,235],{"class":215},[209,424,426,429,431,433,435,438,441,443,445,448,450,453,455],{"class":211,"line":425},7,[209,427,428],{"class":253},"  response",[209,430,359],{"class":215},[209,432,204],{"class":338},[209,434,393],{"class":341},[209,436,437],{"class":215},"{",[209,439,440],{"class":341}," message",[209,442,232],{"class":215},[209,444,306],{"class":215},[209,446,447],{"class":309},"Deployed on Lucity",[209,449,313],{"class":215},[209,451,452],{"class":215}," }",[209,454,417],{"class":341},[209,456,316],{"class":215},[209,458,460,463,465],{"class":211,"line":459},8,[209,461,462],{"class":215},"}",[209,464,417],{"class":341},[209,466,316],{"class":215},[209,468,470],{"class":211,"line":469},9,[209,471,322],{"emptyLinePlaceholder":321},[209,473,475,477,479,482,484,487,489,492,494,497,499,502,504,507,510,513,515,518,521],{"class":211,"line":474},10,[209,476,385],{"class":253},[209,478,359],{"class":215},[209,480,481],{"class":338},"listen",[209,483,393],{"class":341},[209,485,486],{"class":253},"port",[209,488,403],{"class":215},[209,490,491],{"class":215}," ()",[209,493,420],{"class":327},[209,495,496],{"class":253}," console",[209,498,359],{"class":215},[209,500,501],{"class":338},"log",[209,503,393],{"class":341},[209,505,506],{"class":215},"`",[209,508,509],{"class":309},"listening on ",[209,511,512],{"class":215},"${",[209,514,486],{"class":253},[209,516,517],{"class":215},"}`",[209,519,520],{"class":341},"))",[209,522,316],{"class":215},[171,524,525],{},"A hardcoded port is the single most common reason an Express service never becomes healthy: the process runs, the platform checks the port it assigned, nothing answers.",[175,527,529],{"id":528},"three-a-health-check-that-means-something","Three: a health check that means something",[171,531,532],{},"By default the platform opens a TCP connection to your port and calls that healthy. That catches a crashed process, but not an app that is up and failing every request.",[171,534,535,536,232],{},"Add a route that answers cheaply, then point the service's health check at it in ",[537,538,539],"a",{"href":52},"service settings",[200,541,543],{"className":287,"code":542,"language":289,"meta":205,"style":205},"app.get('\u002Fhealthz', (request, response) => response.status(200).send('ok'));\n",[183,544,545],{"__ignoreMap":205},[209,546,547,549,551,553,555,557,560,562,564,566,568,570,572,574,576,578,580,583,585,588,590,592,595,597,599,602,604,606],{"class":211,"line":212},[209,548,385],{"class":253},[209,550,359],{"class":215},[209,552,390],{"class":338},[209,554,393],{"class":341},[209,556,313],{"class":215},[209,558,559],{"class":309},"\u002Fhealthz",[209,561,313],{"class":215},[209,563,403],{"class":215},[209,565,406],{"class":215},[209,567,409],{"class":253},[209,569,403],{"class":215},[209,571,414],{"class":253},[209,573,417],{"class":215},[209,575,420],{"class":327},[209,577,414],{"class":253},[209,579,359],{"class":215},[209,581,582],{"class":338},"status",[209,584,393],{"class":341},[209,586,587],{"class":372},"200",[209,589,417],{"class":341},[209,591,359],{"class":215},[209,593,594],{"class":338},"send",[209,596,393],{"class":341},[209,598,313],{"class":215},[209,600,601],{"class":309},"ok",[209,603,313],{"class":215},[209,605,520],{"class":341},[209,607,316],{"class":215},[171,609,610],{},"Keep it honest but light. Checking the database on every probe turns a slow query into a restart loop; checking nothing at all means a broken app stays in rotation.",[171,612,613,619],{},[537,614,618],{"href":615,"rel":616},"https:\u002F\u002Fgithub.com\u002Fzeitlos\u002Fexpress-example",[617],"nofollow","zeitlos\u002Fexpress-example"," is these three things and nothing else.",[175,621,623],{"id":622},"connecting-a-database","Connecting a database",[171,625,626,627,630,631,634,635,232],{},"Add a ",[537,628,629],{"href":72},"PostgreSQL database"," and link ",[183,632,633],{},"DATABASE_URL"," to its ",[183,636,637],{},"fqdn-uri",[200,639,641],{"className":287,"code":640,"language":289,"meta":205,"style":205},"import { Pool } from 'pg';\n\nconst pool = new Pool({ connectionString: process.env.DATABASE_URL });\n",[183,642,643,666,670],{"__ignoreMap":205},[209,644,645,647,650,653,655,657,659,662,664],{"class":211,"line":212},[209,646,297],{"class":296},[209,648,649],{"class":215}," {",[209,651,652],{"class":253}," Pool",[209,654,452],{"class":215},[209,656,303],{"class":296},[209,658,306],{"class":215},[209,660,661],{"class":309},"pg",[209,663,313],{"class":215},[209,665,316],{"class":215},[209,667,668],{"class":211,"line":219},[209,669,322],{"emptyLinePlaceholder":321},[209,671,672,674,677,679,682,684,686,688,691,693,695,697,699,701,703,705,707],{"class":211,"line":238},[209,673,328],{"class":327},[209,675,676],{"class":253}," pool",[209,678,335],{"class":334},[209,680,681],{"class":327}," new",[209,683,652],{"class":338},[209,685,393],{"class":341},[209,687,437],{"class":215},[209,689,690],{"class":341}," connectionString",[209,692,232],{"class":215},[209,694,356],{"class":253},[209,696,359],{"class":215},[209,698,362],{"class":253},[209,700,359],{"class":215},[209,702,633],{"class":253},[209,704,452],{"class":215},[209,706,417],{"class":341},[209,708,316],{"class":215},[171,710,711],{},"One pool per process, created at startup, not per request. With more than one replica, remember that each has its own pool: the connection limit that matters is pool size times replicas.",[171,713,714,715,718],{},"Sessions and rate limiting want a ",[537,716,717],{"href":84},"key-value store"," rather than in-memory state, for the same reason. Anything held in memory belongs to one replica and disappears when it rolls.",[175,720,722],{"id":721},"migrations","Migrations",[171,724,725],{},"There is no framework convention here, so pick one and put it in the start script:",[200,727,729],{"className":202,"code":728,"language":204,"meta":205,"style":205},"{\n  \"scripts\": {\n    \"start\": \"node migrate.js && node index.js\"\n  }\n}\n",[183,730,731,735,747,764,768],{"__ignoreMap":205},[209,732,733],{"class":211,"line":212},[209,734,216],{"class":215},[209,736,737,739,741,743,745],{"class":211,"line":219},[209,738,222],{"class":215},[209,740,226],{"class":225},[209,742,229],{"class":215},[209,744,232],{"class":215},[209,746,235],{"class":215},[209,748,749,751,753,755,757,759,762],{"class":211,"line":238},[209,750,241],{"class":215},[209,752,185],{"class":225},[209,754,229],{"class":215},[209,756,232],{"class":215},[209,758,250],{"class":215},[209,760,761],{"class":253},"node migrate.js && node index.js",[209,763,257],{"class":215},[209,765,766],{"class":211,"line":260},[209,767,263],{"class":215},[209,769,770],{"class":211,"line":266},[209,771,269],{"class":215},[171,773,774],{},"Running with every start means every replica attempts it, so the tool you use has to be safe to run concurrently. Most are; check yours.",[175,776,778],{"id":777},"next-steps","Next steps",[780,781,782,788,793],"ul",{},[783,784,785,787],"li",{},[537,786,51],{"href":52}," for health checks, resources and replicas",[783,789,790,792],{},[537,791,83],{"href":84}," for sessions, caching and queues",[783,794,795,797],{},[537,796,119],{"href":120}," for what your app prints in production",[799,800,801],"style",{},"html pre.shiki code .si-ur, html code.shiki .si-ur{--shiki-light:#A89984;--shiki-default:#A89984;--shiki-dark:#A89984}html pre.shiki code .slqHI, html code.shiki .slqHI{--shiki-light:#689D6A;--shiki-default:#689D6A;--shiki-dark:#689D6A}html pre.shiki code .sIi04, html code.shiki .sIi04{--shiki-light:#83A598;--shiki-default:#83A598;--shiki-dark:#83A598}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 .sJHtc, html code.shiki .sJHtc{--shiki-light:#FB4934;--shiki-default:#FB4934;--shiki-dark:#FB4934}html pre.shiki code .sQLXx, html code.shiki .sQLXx{--shiki-light:#B8BB26;--shiki-default:#B8BB26;--shiki-dark:#B8BB26}html pre.shiki code .sjx4h, html code.shiki .sjx4h{--shiki-light:#FE8019;--shiki-default:#FE8019;--shiki-dark:#FE8019}html pre.shiki code .s3drp, html code.shiki .s3drp{--shiki-light:#8EC07C;--shiki-default:#8EC07C;--shiki-dark:#8EC07C}html pre.shiki code .sX5TD, html code.shiki .sX5TD{--shiki-light:#FABD2F;--shiki-default:#FABD2F;--shiki-dark:#FABD2F}html pre.shiki code .spvMa, html code.shiki .spvMa{--shiki-light:#EBDBB2;--shiki-default:#EBDBB2;--shiki-dark:#EBDBB2}html pre.shiki code .s1Tsi, html code.shiki .s1Tsi{--shiki-light:#D3869B;--shiki-default:#D3869B;--shiki-dark:#D3869B}",{"title":205,"searchDepth":219,"depth":219,"links":803},[804,805,806,807,808,809],{"id":177,"depth":219,"text":178},{"id":272,"depth":219,"text":273},{"id":528,"depth":219,"text":529},{"id":622,"depth":219,"text":623},{"id":721,"depth":219,"text":722},{"id":777,"depth":219,"text":778},"Deploy an Express API on Lucity. Three requirements, none of them platform-specific.","md",null,{},{"title":31},{"title":166,"description":810},"1lJgZJFyleB4oyTiYff5BlgVIF1cyFNZDQ5f54z_REs",[818,820],{"title":27,"path":28,"stem":29,"description":819,"children":-1},"Deploy an Astro site on Lucity, static by default and server rendered when you add an adapter.",{"title":35,"path":36,"stem":37,"description":821,"children":-1},"Deploy a FastAPI service on Lucity. Detection is picky about layout, and the fix is one setting.",[823,826,828,831,834,837,839,840,842,845,848,851,854,856,858,860,862,864,866,868,870,872,874,876,878,880,882,884,886,888,890,892,894,897,901,905],{"path":6,"title":824,"description":825},"Deploy your first service","Deploy an app to Lucity, put it on a public domain, and connect a PostgreSQL database and an object storage bucket in about fifteen minutes.",{"path":827,"title":9,"description":812},"\u002Fdocs\u002Fguides\u002F.navigation",{"path":16,"title":829,"description":830},"Deploy a Next.js app","Deploy a Next.js app on Lucity, with a database, environment variables that behave, and no Dockerfile.",{"path":20,"title":832,"description":833},"Deploy a Nuxt app","Deploy a Nuxt app on Lucity. Nitro output, runtime config, and a database, with no preset to pick.",{"path":24,"title":835,"description":836},"Deploy a SvelteKit app","Deploy a SvelteKit app on Lucity. One adapter change stands between a fresh project and a running service.",{"path":28,"title":838,"description":819},"Deploy an Astro site",{"path":32,"title":166,"description":810},{"path":36,"title":841,"description":821},"Deploy a FastAPI service",{"path":40,"title":843,"description":844},"Deploy a Django project","Deploy a Django project on Lucity, with migrations that run themselves and static files that do not.",{"path":44,"title":846,"description":847},"Deploy a Laravel application","Deploy a Laravel application on Lucity, with migrations, caches and a queue worker, and no server to configure.",{"path":48,"title":849,"description":850},"Deploy a Go service","Deploy a Go service on Lucity. Compiled in the build, shipped as a binary, nothing else in the image.",{"path":10,"title":852,"description":853},"Deploy your framework","Deploy guides for the frameworks people actually ship: Next.js, Nuxt, SvelteKit, Astro, Express, FastAPI, Django, Laravel, and Go.",{"path":52,"title":51,"description":855},"Services are the deployable units of a project: what they are, how they are configured, and how they scale.",{"path":56,"title":55,"description":857},"How a deployment goes live on Lucity, and the ways to trigger one.",{"path":60,"title":59,"description":859},"How Lucity turns your source code into a container image.",{"path":64,"title":63,"description":861},"Configuration for your services: service variables, shared variables, and dynamic variables.",{"path":68,"title":67,"description":863},"Put a service on the internet. Use a platform hostname for quick tests, or a domain you own.",{"path":72,"title":71,"description":865},"Managed PostgreSQL databases, replicated and backed up, connected to your services without copying credentials.",{"path":76,"title":75,"description":867},"S3-compatible buckets for uploads, exports and anything else your service needs to keep.",{"path":80,"title":79,"description":869},"Persistent disks for services that need to keep state on the filesystem.",{"path":84,"title":83,"description":871},"A Redis®-compatible key-value store for caching, sessions and queues.",{"path":88,"title":87,"description":873},"Workspaces represent your organization in Lucity, with their own members, isolation and billing.",{"path":92,"title":91,"description":875},"Projects group services, databases and the environments they run in.",{"path":96,"title":95,"description":877},"Development, staging, production: isolated copies of the same application.",{"path":100,"title":99,"description":879},"Download a project as a Helm chart and run it on a Kubernetes cluster of your own.",{"path":104,"title":103,"description":881},"The GraphQL API behind the dashboard, with an interactive playground.",{"path":108,"title":107,"description":883},"Deploy and manage your services from a terminal or a CI pipeline.",{"path":112,"title":111,"description":885},"Deploy and manage your services from Claude Code, Codex, Cursor or any other MCP client.",{"path":116,"title":115,"description":887},"CPU and memory for every service, and disk usage for every volume.",{"path":120,"title":119,"description":889},"What your services print while they run, and the output of every deployment step.",{"path":124,"title":123,"description":891},"Plans, resource usage, the free trial, and what happens when a payment fails.",{"path":128,"title":127,"description":893},"Run the whole platform on a Kubernetes cluster you own, using the same two Helm charts we run ourselves.",{"path":895,"title":896,"description":812},"\u002Flegal\u002F.navigation","Legal",{"path":898,"title":899,"description":900},"\u002Flegal\u002Fdata-processing-agreement","Data Processing Agreement","How Lucity processes personal data on your behalf.",{"path":902,"title":903,"description":904},"\u002Flegal\u002Fprivacy-policy","Privacy Policy","How Lucity handles your data.",{"path":906,"title":907,"description":908},"\u002Flegal\u002Fterms-of-use","Terms of Use","Terms governing your use of Lucity.",1791216729216]