[{"data":1,"prerenderedAt":997},["ShallowReactive",2],{"navigation_docs":3,"section-navigation-docs":130,"-docs-guides-django":164,"-docs-guides-django-surround":905,"doc-previews":910},[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":898,"extension":899,"links":900,"meta":901,"navigation":902,"path":40,"seo":903,"stem":41,"__hash__":904},"docs\u002Fdocs\u002F02.guides\u002F7.django.md","Deploy a Django project",{"type":168,"value":169,"toc":889},"minimark",[170,174,179,265,284,288,299,344,347,354,363,370,374,387,390,404,546,549,595,606,610,621,624,728,734,738,757,814,824,828,864,868,885],[171,172,173],"p",{},"Django deploys here with one command derived automatically and two things you have to decide yourself: where static files come from, and which hostnames the project trusts. Everything else is the framework working as it always does.",[175,176,178],"h2",{"id":177},"start-from-a-fresh-project","Start from a fresh project",[180,181,186],"pre",{"className":182,"code":183,"language":184,"meta":185,"style":185},"language-bash shiki shiki-themes gruvbox-dark-medium gruvbox-dark-medium gruvbox-dark-medium","python -m venv .venv && source .venv\u002Fbin\u002Factivate\npip install django gunicorn\ndjango-admin startproject liftoff .\npip freeze > requirements.txt\n","bash","",[187,188,189,220,235,250],"code",{"__ignoreMap":185},[190,191,194,198,202,206,209,213,217],"span",{"class":192,"line":193},"line",1,[190,195,197],{"class":196},"sX5TD","python",[190,199,201],{"class":200},"s1Tsi"," -m",[190,203,205],{"class":204},"sQLXx"," venv",[190,207,208],{"class":204}," .venv",[190,210,212],{"class":211},"si-ur"," &&",[190,214,216],{"class":215},"sjx4h"," source",[190,218,219],{"class":204}," .venv\u002Fbin\u002Factivate\n",[190,221,223,226,229,232],{"class":192,"line":222},2,[190,224,225],{"class":196},"pip",[190,227,228],{"class":204}," install",[190,230,231],{"class":204}," django",[190,233,234],{"class":204}," gunicorn\n",[190,236,238,241,244,247],{"class":192,"line":237},3,[190,239,240],{"class":196},"django-admin",[190,242,243],{"class":204}," startproject",[190,245,246],{"class":204}," liftoff",[190,248,249],{"class":204}," .\n",[190,251,253,255,258,262],{"class":192,"line":252},4,[190,254,225],{"class":196},[190,256,257],{"class":204}," freeze",[190,259,261],{"class":260},"s3drp"," >",[190,263,264],{"class":204}," requirements.txt\n",[171,266,267,270,271,275,276,279,280,283],{},[187,268,269],{},"requirements.txt"," matters more than it looks: it is how the ",[272,273,274],"a",{"href":60},"builder"," recognizes the project as Python and finds ",[187,277,278],{},"gunicorn",". Push the result to GitHub and connect it as described in the ",[272,281,282],{"href":6},"quickstart",".",[175,285,287],{"id":286},"the-command-lucity-derives","The command Lucity derives",[171,289,290,291,294,295,298],{},"Detection keys on ",[187,292,293],{},"manage.py"," plus Django in your dependencies. The start command it writes reads your ",[187,296,297],{},"WSGI_APPLICATION"," setting and comes out as:",[180,300,302],{"className":182,"code":301,"language":184,"meta":185,"style":185},"python manage.py migrate && gunicorn --bind 0.0.0.0:${PORT:-8000} liftoff.wsgi:application\n",[187,303,304],{"__ignoreMap":185},[190,305,306,308,311,314,316,319,322,325,328,332,335,338,341],{"class":192,"line":193},[190,307,197],{"class":196},[190,309,310],{"class":204}," manage.py",[190,312,313],{"class":204}," migrate",[190,315,212],{"class":211},[190,317,318],{"class":196}," gunicorn",[190,320,321],{"class":200}," --bind",[190,323,324],{"class":204}," 0.0.0.0:",[190,326,327],{"class":211},"${",[190,329,331],{"class":330},"sIi04","PORT",[190,333,334],{"class":260},":-",[190,336,337],{"class":330},"8000",[190,339,340],{"class":211},"}",[190,342,343],{"class":204}," liftoff.wsgi:application\n",[171,345,346],{},"Read that literally, because two consequences catch people out.",[171,348,349,353],{},[350,351,352],"strong",{},"Migrations run on every start."," Not on every deploy: on every container start, including a restart and each replica coming up. Django's migrate is safe to repeat, so this is usually what you want. It also means a broken migration blocks the rollout instead of quietly leaving the schema behind.",[171,355,356,362],{},[350,357,358,359,361],{},"No ",[187,360,297],{},", no start command."," Remove or rename that setting and detection produces nothing, and the service has nowhere to start from. Either keep the setting, or set your own start command in the service settings.",[171,364,365,366,369],{},"If you want something else entirely, a worker pool tuned differently or ",[187,367,368],{},"collectstatic"," in the chain, override the start command and Lucity uses yours verbatim.",[175,371,373],{"id":372},"static-files-are-not-handled-for-you","Static files are not handled for you",[171,375,376,377,379,380,383,384,283],{},"Nothing runs ",[187,378,368],{},". A project deployed as-is serves its own views correctly and 404s on ",[187,381,382],{},"\u002Fstatic\u002F*"," in production, which is a confusing failure because it works locally with ",[187,385,386],{},"DEBUG = True",[171,388,389],{},"The simplest fix is WhiteNoise, which serves static files from the app process:",[180,391,393],{"className":182,"code":392,"language":184,"meta":185,"style":185},"pip install whitenoise\n",[187,394,395],{"__ignoreMap":185},[190,396,397,399,401],{"class":192,"line":193},[190,398,225],{"class":196},[190,400,228],{"class":204},[190,402,403],{"class":204}," whitenoise\n",[180,405,408],{"className":406,"code":407,"language":197,"meta":185,"style":185},"language-python shiki shiki-themes gruvbox-dark-medium gruvbox-dark-medium gruvbox-dark-medium","# settings.py\nMIDDLEWARE = [\n    'django.middleware.security.SecurityMiddleware',\n    'whitenoise.middleware.WhiteNoiseMiddleware',\n    # ...\n]\n\nSTATIC_ROOT = BASE_DIR \u002F 'staticfiles'\nSTORAGES = {\n    'staticfiles': {'BACKEND': 'whitenoise.storage.CompressedManifestStaticFilesStorage'},\n}\n",[187,409,410,416,428,442,453,459,465,472,495,506,540],{"__ignoreMap":185},[190,411,412],{"class":192,"line":193},[190,413,415],{"class":414},"sIIdi","# settings.py\n",[190,417,418,422,425],{"class":192,"line":222},[190,419,421],{"class":420},"s-RIx","MIDDLEWARE",[190,423,424],{"class":260}," =",[190,426,427],{"class":211}," [\n",[190,429,430,433,436,439],{"class":192,"line":237},[190,431,432],{"class":211},"    '",[190,434,435],{"class":204},"django.middleware.security.SecurityMiddleware",[190,437,438],{"class":211},"'",[190,440,441],{"class":211},",\n",[190,443,444,446,449,451],{"class":192,"line":252},[190,445,432],{"class":211},[190,447,448],{"class":204},"whitenoise.middleware.WhiteNoiseMiddleware",[190,450,438],{"class":211},[190,452,441],{"class":211},[190,454,456],{"class":192,"line":455},5,[190,457,458],{"class":414},"    # ...\n",[190,460,462],{"class":192,"line":461},6,[190,463,464],{"class":211},"]\n",[190,466,468],{"class":192,"line":467},7,[190,469,471],{"emptyLinePlaceholder":470},true,"\n",[190,473,475,478,480,483,486,489,492],{"class":192,"line":474},8,[190,476,477],{"class":420},"STATIC_ROOT",[190,479,424],{"class":260},[190,481,482],{"class":420}," BASE_DIR",[190,484,485],{"class":260}," \u002F",[190,487,488],{"class":211}," '",[190,490,491],{"class":204},"staticfiles",[190,493,494],{"class":211},"'\n",[190,496,498,501,503],{"class":192,"line":497},9,[190,499,500],{"class":420},"STORAGES",[190,502,424],{"class":260},[190,504,505],{"class":211}," {\n",[190,507,509,511,513,515,518,521,523,526,528,530,532,535,537],{"class":192,"line":508},10,[190,510,432],{"class":211},[190,512,491],{"class":204},[190,514,438],{"class":211},[190,516,517],{"class":211},":",[190,519,520],{"class":211}," {",[190,522,438],{"class":211},[190,524,525],{"class":204},"BACKEND",[190,527,438],{"class":211},[190,529,517],{"class":211},[190,531,488],{"class":211},[190,533,534],{"class":204},"whitenoise.storage.CompressedManifestStaticFilesStorage",[190,536,438],{"class":211},[190,538,539],{"class":211},"},\n",[190,541,543],{"class":192,"line":542},11,[190,544,545],{"class":211},"}\n",[171,547,548],{},"Then put the collection step in your start command, before gunicorn:",[180,550,552],{"className":182,"code":551,"language":184,"meta":185,"style":185},"python manage.py migrate && python manage.py collectstatic --noinput && gunicorn --bind 0.0.0.0:${PORT:-8000} liftoff.wsgi:application\n",[187,553,554],{"__ignoreMap":185},[190,555,556,558,560,562,564,567,569,572,575,577,579,581,583,585,587,589,591,593],{"class":192,"line":193},[190,557,197],{"class":196},[190,559,310],{"class":204},[190,561,313],{"class":204},[190,563,212],{"class":211},[190,565,566],{"class":196}," python",[190,568,310],{"class":204},[190,570,571],{"class":204}," collectstatic",[190,573,574],{"class":200}," --noinput",[190,576,212],{"class":211},[190,578,318],{"class":196},[190,580,321],{"class":200},[190,582,324],{"class":204},[190,584,327],{"class":211},[190,586,331],{"class":330},[190,588,334],{"class":260},[190,590,337],{"class":330},[190,592,340],{"class":211},[190,594,343],{"class":204},[171,596,597,598,601,602,605],{},"For user uploads, WhiteNoise is the wrong tool. Those belong in a ",[272,599,600],{"href":76},"bucket",", configured through ",[187,603,604],{},"django-storages"," with the S3 credentials Lucity injects. The container filesystem does not survive a rollout.",[175,607,609],{"id":608},"let-django-accept-its-own-domain","Let Django accept its own domain",[171,611,612,613,616,617,620],{},"Generate a ",[272,614,615],{"href":68},"domain"," and Django will reject requests to it until the hostname is in ",[187,618,619],{},"ALLOWED_HOSTS",". Forms will also fail CSRF validation until the origin is trusted.",[171,622,623],{},"Read both from the environment rather than hardcoding, so the same image works in every environment:",[180,625,627],{"className":406,"code":626,"language":197,"meta":185,"style":185},"ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', '').split(',')\nCSRF_TRUSTED_ORIGINS = [f'https:\u002F\u002F{host}' for host in ALLOWED_HOSTS if host]\n",[187,628,629,681],{"__ignoreMap":185},[190,630,631,633,635,639,641,644,646,649,652,654,656,658,661,664,667,670,672,674,676,678],{"class":192,"line":193},[190,632,619],{"class":420},[190,634,424],{"class":260},[190,636,638],{"class":637},"spvMa"," os",[190,640,283],{"class":211},[190,642,643],{"class":637},"environ",[190,645,283],{"class":211},[190,647,648],{"class":330},"get",[190,650,651],{"class":211},"(",[190,653,438],{"class":211},[190,655,619],{"class":204},[190,657,438],{"class":211},[190,659,660],{"class":211},",",[190,662,663],{"class":211}," ''",[190,665,666],{"class":211},").",[190,668,669],{"class":330},"split",[190,671,651],{"class":211},[190,673,438],{"class":211},[190,675,660],{"class":204},[190,677,438],{"class":211},[190,679,680],{"class":211},")\n",[190,682,683,686,688,691,695,698,701,704,706,708,711,714,717,720,723,726],{"class":192,"line":222},[190,684,685],{"class":420},"CSRF_TRUSTED_ORIGINS",[190,687,424],{"class":260},[190,689,690],{"class":211}," [",[190,692,694],{"class":693},"sJHtc","f",[190,696,697],{"class":204},"'https:\u002F\u002F",[190,699,700],{"class":200},"{",[190,702,703],{"class":637},"host",[190,705,340],{"class":200},[190,707,438],{"class":204},[190,709,710],{"class":693}," for",[190,712,713],{"class":637}," host ",[190,715,716],{"class":693},"in",[190,718,719],{"class":420}," ALLOWED_HOSTS",[190,721,722],{"class":693}," if",[190,724,725],{"class":637}," host",[190,727,464],{"class":211},[171,729,730,731,733],{},"Then set ",[187,732,619],{}," to your generated hostname. Add the custom domain to the same variable when you point one at the service.",[175,735,737],{"id":736},"connecting-the-database","Connecting the database",[171,739,740,741,744,745,748,749,752,753,756],{},"Add a ",[272,742,743],{"href":72},"PostgreSQL database",", then link ",[187,746,747],{},"DATABASE_URL"," to its ",[187,750,751],{},"fqdn-uri"," and let ",[187,754,755],{},"dj-database-url"," do the parsing:",[180,758,760],{"className":406,"code":759,"language":197,"meta":185,"style":185},"import dj_database_url\n\nDATABASES = {'default': dj_database_url.config(conn_max_age=600)}\n",[187,761,762,770,774],{"__ignoreMap":185},[190,763,764,767],{"class":192,"line":193},[190,765,766],{"class":693},"import",[190,768,769],{"class":637}," dj_database_url\n",[190,771,772],{"class":192,"line":222},[190,773,471],{"emptyLinePlaceholder":470},[190,775,776,779,781,783,785,788,790,792,795,797,800,802,805,808,811],{"class":192,"line":237},[190,777,778],{"class":420},"DATABASES",[190,780,424],{"class":260},[190,782,520],{"class":211},[190,784,438],{"class":211},[190,786,787],{"class":204},"default",[190,789,438],{"class":211},[190,791,517],{"class":211},[190,793,794],{"class":637}," dj_database_url",[190,796,283],{"class":211},[190,798,799],{"class":330},"config",[190,801,651],{"class":211},[190,803,804],{"class":330},"conn_max_age",[190,806,807],{"class":260},"=",[190,809,810],{"class":200},"600",[190,812,813],{"class":211},")}\n",[171,815,816,819,820,823],{},[187,817,818],{},"psycopg[binary]"," belongs in your requirements alongside it. Because the value is a ",[272,821,822],{"href":64},"dynamic variable"," rather than a pasted string, a rotated password reaches the app without you editing anything.",[175,825,827],{"id":826},"before-you-call-it-production","Before you call it production",[829,830,831,838,847,861],"ul",{},[832,833,834,837],"li",{},[187,835,836],{},"DEBUG"," should read from the environment and default to off. A stack trace on a public URL is a bad day.",[832,839,840,843,844,283],{},[187,841,842],{},"SECRET_KEY"," belongs in a variable, not in ",[187,845,846],{},"settings.py",[832,848,849,852,853,856,857,860],{},[187,850,851],{},"SESSION_COOKIE_SECURE"," and ",[187,854,855],{},"CSRF_COOKIE_SECURE"," should be on. Everything Lucity serves is HTTPS, so there is no cost to it. Run ",[187,858,859],{},"python manage.py check --deploy"," to see the rest of the list.",[832,862,863],{},"Long migrations block the rollout. For a big one, run it once against the database and deploy after.",[175,865,867],{"id":866},"next-steps","Next steps",[829,869,870,875,880],{},[832,871,872,874],{},[272,873,71],{"href":72}," for backups, the query console and connection details",[832,876,877,879],{},[272,878,75],{"href":76}," for media uploads",[832,881,882,884],{},[272,883,51],{"href":52}," for resources, health checks and replicas",[886,887,888],"style",{},"html pre.shiki code .sX5TD, html code.shiki .sX5TD{--shiki-light:#FABD2F;--shiki-default:#FABD2F;--shiki-dark:#FABD2F}html pre.shiki code .s1Tsi, html code.shiki .s1Tsi{--shiki-light:#D3869B;--shiki-default:#D3869B;--shiki-dark:#D3869B}html pre.shiki code .sQLXx, html code.shiki .sQLXx{--shiki-light:#B8BB26;--shiki-default:#B8BB26;--shiki-dark:#B8BB26}html pre.shiki code .si-ur, html code.shiki .si-ur{--shiki-light:#A89984;--shiki-default:#A89984;--shiki-dark:#A89984}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 .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 .sIi04, html code.shiki .sIi04{--shiki-light:#83A598;--shiki-default:#83A598;--shiki-dark:#83A598}html pre.shiki code .sIIdi, html code.shiki .sIIdi{--shiki-light:#928374;--shiki-light-font-style:italic;--shiki-default:#928374;--shiki-default-font-style:italic;--shiki-dark:#928374;--shiki-dark-font-style:italic}html pre.shiki code .s-RIx, html code.shiki .s-RIx{--shiki-light:#D3869B;--shiki-light-font-weight:bold;--shiki-default:#D3869B;--shiki-default-font-weight:bold;--shiki-dark:#D3869B;--shiki-dark-font-weight:bold}html pre.shiki code .spvMa, html code.shiki .spvMa{--shiki-light:#EBDBB2;--shiki-default:#EBDBB2;--shiki-dark:#EBDBB2}html pre.shiki code .sJHtc, html code.shiki .sJHtc{--shiki-light:#FB4934;--shiki-default:#FB4934;--shiki-dark:#FB4934}",{"title":185,"searchDepth":222,"depth":222,"links":890},[891,892,893,894,895,896,897],{"id":177,"depth":222,"text":178},{"id":286,"depth":222,"text":287},{"id":372,"depth":222,"text":373},{"id":608,"depth":222,"text":609},{"id":736,"depth":222,"text":737},{"id":826,"depth":222,"text":827},{"id":866,"depth":222,"text":867},"Deploy a Django project on Lucity, with migrations that run themselves and static files that do not.","md",null,{},{"title":39},{"title":166,"description":898},"wn5hnxSLVD5LlaDMozaDaFqiPeU-1htIgDLTnmZcVdY",[906,908],{"title":35,"path":36,"stem":37,"description":907,"children":-1},"Deploy a FastAPI service on Lucity. Detection is picky about layout, and the fix is one setting.",{"title":43,"path":44,"stem":45,"description":909,"children":-1},"Deploy a Laravel application on Lucity, with migrations, caches and a queue worker, and no server to configure.",[911,914,916,919,922,925,928,931,933,934,936,939,942,944,946,948,950,952,954,956,958,960,962,964,966,968,970,972,974,976,978,980,982,985,989,993],{"path":6,"title":912,"description":913},"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":915,"title":9,"description":900},"\u002Fdocs\u002Fguides\u002F.navigation",{"path":16,"title":917,"description":918},"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":920,"description":921},"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":923,"description":924},"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":926,"description":927},"Deploy an Astro site","Deploy an Astro site on Lucity, static by default and server rendered when you add an adapter.",{"path":32,"title":929,"description":930},"Deploy an Express API","Deploy an Express API on Lucity. Three requirements, none of them platform-specific.",{"path":36,"title":932,"description":907},"Deploy a FastAPI service",{"path":40,"title":166,"description":898},{"path":44,"title":935,"description":909},"Deploy a Laravel application",{"path":48,"title":937,"description":938},"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":940,"description":941},"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":943},"Services are the deployable units of a project: what they are, how they are configured, and how they scale.",{"path":56,"title":55,"description":945},"How a deployment goes live on Lucity, and the ways to trigger one.",{"path":60,"title":59,"description":947},"How Lucity turns your source code into a container image.",{"path":64,"title":63,"description":949},"Configuration for your services: service variables, shared variables, and dynamic variables.",{"path":68,"title":67,"description":951},"Put a service on the internet. Use a platform hostname for quick tests, or a domain you own.",{"path":72,"title":71,"description":953},"Managed PostgreSQL databases, replicated and backed up, connected to your services without copying credentials.",{"path":76,"title":75,"description":955},"S3-compatible buckets for uploads, exports and anything else your service needs to keep.",{"path":80,"title":79,"description":957},"Persistent disks for services that need to keep state on the filesystem.",{"path":84,"title":83,"description":959},"A Redis®-compatible key-value store for caching, sessions and queues.",{"path":88,"title":87,"description":961},"Workspaces represent your organization in Lucity, with their own members, isolation and billing.",{"path":92,"title":91,"description":963},"Projects group services, databases and the environments they run in.",{"path":96,"title":95,"description":965},"Development, staging, production: isolated copies of the same application.",{"path":100,"title":99,"description":967},"Download a project as a Helm chart and run it on a Kubernetes cluster of your own.",{"path":104,"title":103,"description":969},"The GraphQL API behind the dashboard, with an interactive playground.",{"path":108,"title":107,"description":971},"Deploy and manage your services from a terminal or a CI pipeline.",{"path":112,"title":111,"description":973},"Deploy and manage your services from Claude Code, Codex, Cursor or any other MCP client.",{"path":116,"title":115,"description":975},"CPU and memory for every service, and disk usage for every volume.",{"path":120,"title":119,"description":977},"What your services print while they run, and the output of every deployment step.",{"path":124,"title":123,"description":979},"Plans, resource usage, the free trial, and what happens when a payment fails.",{"path":128,"title":127,"description":981},"Run the whole platform on a Kubernetes cluster you own, using the same two Helm charts we run ourselves.",{"path":983,"title":984,"description":900},"\u002Flegal\u002F.navigation","Legal",{"path":986,"title":987,"description":988},"\u002Flegal\u002Fdata-processing-agreement","Data Processing Agreement","How Lucity processes personal data on your behalf.",{"path":990,"title":991,"description":992},"\u002Flegal\u002Fprivacy-policy","Privacy Policy","How Lucity handles your data.",{"path":994,"title":995,"description":996},"\u002Flegal\u002Fterms-of-use","Terms of Use","Terms governing your use of Lucity.",1791216729361]