[{"data":1,"prerenderedAt":654},["ShallowReactive",2],{"navigation_docs":3,"section-navigation-docs":130,"-docs-domains":164,"-docs-domains-surround":561,"doc-previews":566},[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":67,"body":166,"description":554,"extension":555,"links":556,"meta":557,"navigation":558,"path":68,"seo":559,"stem":69,"__hash__":560},"docs\u002Fdocs\u002F07.domains.md",{"type":167,"value":168,"toc":540},"minimark",[169,178,181,189,194,213,224,227,230,234,245,248,253,264,318,322,328,368,377,383,387,394,397,401,404,473,480,484,487,490,494,510,517,521],[170,171,172,173,177],"p",{},"A service is private by default. It answers inside its ",[174,175,176],"a",{"href":96},"environment"," and nowhere else. A domain is what changes that: it gives the service a public hostname, terminates HTTPS in front of it, and routes traffic to the port it listens on.",[170,179,180],{},"There are two kinds of domains. A platform domain is one click and works immediately, and a service has one of them. A custom domain is a hostname you own, which takes two DNS records and a few minutes, and a service can have as many as it needs.",[170,182,183,184,188],{},"Both need the service to have a ",[174,185,187],{"href":186},"\u002Fdocs\u002Fservices#ports","port",". A service that does not listen on one has nothing to route to.",[190,191,193],"h2",{"id":192},"platform-domains","Platform domains",[170,195,196,197,201,202,201,205,208,209,212],{},"Open the service, go to ",[198,199,200],"strong",{},"Settings"," → ",[198,203,204],{},"Networking",[198,206,207],{},"Platform Domain",", and click ",[198,210,211],{},"Generate Domain",". You get something like:",[214,215,220],"pre",{"className":216,"code":218,"language":219},[217],"language-text","vouch-development-ee6tz.lucity.app\n","text",[221,222,218],"code",{"__ignoreMap":223},"",[170,225,226],{},"The name is built from the service, the environment, and a short random suffix that keeps it unique across the platform. DNS resolution and HTTPS both work pretty much instantly: there are no records to add and no certificate to wait for.",[170,228,229],{},"This is the right choice for development environments, for previews, and for anything internal where the URL does not need to be memorable. When you want a hostname of your own, add a custom domain alongside it: the platform domain keeps working, so nothing breaks while you set the other one up.",[190,231,233],{"id":232},"custom-domains","Custom domains",[170,235,236,237,201,239,201,241,244],{},"Under ",[198,238,200],{},[198,240,204],{},[198,242,243],{},"Custom Domains",", enter the hostname you want and Lucity shows you the DNS records to add at your provider, with the exact values ready to copy.",[170,246,247],{},"Every custom domain needs two records: one that proves you control the domain, and one that points traffic at the platform. Which routing record you add depends on whether you are pointing a subdomain or the domain itself.",[249,250,252],"h3",{"id":251},"subdomain","Subdomain",[170,254,255,256,259,260,263],{},"For ",[221,257,258],{},"api.example.com",", ",[221,261,262],{},"www.example.com",", or anything else below the domain:",[265,266,267,283],"table",{},[268,269,270],"thead",{},[271,272,273,277,280],"tr",{},[274,275,276],"th",{},"Type",[274,278,279],{},"Host",[274,281,282],{},"Value",[284,285,286,302],"tbody",{},[271,287,288,294,299],{},[289,290,291],"td",{},[221,292,293],{},"TXT",[289,295,296],{},[221,297,298],{},"_lucity-verify.example.com",[289,300,301],{},"A challenge string unique to your workspace and domain",[271,303,304,309,313],{},[289,305,306],{},[221,307,308],{},"CNAME",[289,310,311],{},[221,312,258],{},[289,314,315],{},[221,316,317],{},"lb.lucity.app",[249,319,321],{"id":320},"apex-domain","Apex domain",[170,323,255,324,327],{},[221,325,326],{},"example.com"," itself, with nothing in front of it:",[265,329,330,340],{},[268,331,332],{},[271,333,334,336,338],{},[274,335,276],{},[274,337,279],{},[274,339,282],{},[284,341,342,354],{},[271,343,344,348,352],{},[289,345,346],{},[221,347,293],{},[289,349,350],{},[221,351,298],{},[289,353,301],{},[271,355,356,361,365],{},[289,357,358],{},[221,359,360],{},"A",[289,362,363],{},[221,364,326],{},[289,366,367],{},"The platform's IP address, shown with the record",[170,369,370,371,373,374,376],{},"An apex domain uses an ",[221,372,360],{}," record because DNS does not allow a ",[221,375,308],{}," at the root of a zone. Everything else about it works the same way.",[170,378,379,380,382],{},"Notice that the ",[221,381,293],{}," record is identical in both cases: it goes on the domain, not on the hostname you are adding. One of them covers every hostname under that domain, so the second and third you add need only their own routing record.",[190,384,386],{"id":385},"verification-and-certificates","Verification and certificates",[170,388,389,390,393],{},"Lucity picks up a record as soon as your DNS provider is serving it, without waiting for caches elsewhere to expire. The check runs every couple of minutes on its own, and the ",[198,391,392],{},"Check"," button next to the domain runs it immediately.",[170,395,396],{},"Once both records verify, two things happen. The route goes live, so the hostname reaches your service. And a certificate is requested from Let's Encrypt, which usually takes a few seconds and occasionally a minute. HTTPS starts working on that hostname when the certificate is issued, and renews itself from then on.",[190,398,400],{"id":399},"troubleshooting","Troubleshooting",[170,402,403],{},"Each domain shows a DNS state and a TLS state, and between them they say what is holding things up.",[265,405,406,416],{},[268,407,408],{},[271,409,410,413],{},[274,411,412],{},"State",[274,414,415],{},"What it means",[284,417,418,429,439,449,460],{},[271,419,420,426],{},[289,421,422,423],{},"DNS ",[198,424,425],{},"pending",[289,427,428],{},"Neither record has been seen yet. Normal for the first few minutes after you add them.",[271,430,431,436],{},[289,432,422,433],{},[198,434,435],{},"misconfigured",[289,437,438],{},"One record is right and the other is not. Almost always the TXT record on the wrong name, or a routing record that does not resolve to the expected target.",[271,440,441,446],{},[289,442,422,443],{},[198,444,445],{},"error",[289,447,448],{},"The lookup itself failed, usually a nameserver problem on the domain rather than a wrong record.",[271,450,451,457],{},[289,452,453,454],{},"TLS ",[198,455,456],{},"provisioning",[289,458,459],{},"The certificate has been requested and is not issued yet.",[271,461,462,466],{},[289,463,453,464],{},[198,465,445],{},[289,467,468,469,472],{},"Issuance failed. Check that the domain still resolves to the platform, and that a ",[221,470,471],{},"CAA"," record is not blocking Let's Encrypt.",[170,474,475,476,479],{},"The most common cause of a domain that never verifies is a ",[198,477,478],{},"proxying DNS provider",". If your provider hides the target behind its own network, such as Cloudflare with the orange cloud switched on, a lookup of your hostname returns their addresses instead of the CNAME target, and the check cannot confirm that traffic reaches Lucity. Set the record to DNS-only.",[190,481,483],{"id":482},"removing-a-domain","Removing a domain",[170,485,486],{},"The X next to a domain removes it. The route disappears straight away and the hostname stops reaching your service, though whatever you put in DNS stays there until you delete it too.",[170,488,489],{},"Removing a custom domain also removes its certificate. Add the same hostname again later and a fresh one is issued, so there is no benefit to leaving a domain attached to a service you are no longer serving from it.",[190,491,493],{"id":492},"under-the-hood","Under the hood",[170,495,496,497,503,504,509],{},"Domains are ",[174,498,502],{"href":499,"rel":500},"https:\u002F\u002Fgateway-api.sigs.k8s.io",[501],"nofollow","Gateway API"," objects. Each custom domain gets its own listener and its own ",[174,505,508],{"href":506,"rel":507},"https:\u002F\u002Fcert-manager.io",[501],"cert-manager"," certificate in your environment's namespace, with an HTTPRoute pointing at your service. Platform domains attach to a shared listener with a wildcard certificate already in place, which is why they need no issuance step.",[170,511,512,513,516],{},"That is all standard Kubernetes, so an ",[174,514,515],{"href":100},"ejected"," project keeps its routing and its certificates without Lucity in the picture.",[190,518,520],{"id":519},"next-steps","Next steps",[522,523,524,530,535],"ul",{},[525,526,527,529],"li",{},[174,528,51],{"href":52}," for the port a domain routes to",[525,531,532,534],{},[174,533,95],{"href":96}," for keeping production hostnames separate from development ones",[525,536,537,539],{},[174,538,55],{"href":56}," for what happens to traffic during a release",{"title":223,"searchDepth":541,"depth":541,"links":542},2,[543,544,549,550,551,552,553],{"id":192,"depth":541,"text":193},{"id":232,"depth":541,"text":233,"children":545},[546,548],{"id":251,"depth":547,"text":252},3,{"id":320,"depth":547,"text":321},{"id":385,"depth":541,"text":386},{"id":399,"depth":541,"text":400},{"id":482,"depth":541,"text":483},{"id":492,"depth":541,"text":493},{"id":519,"depth":541,"text":520},"Put a service on the internet. Use a platform hostname for quick tests, or a domain you own.","md",null,{},true,{"title":67,"description":554},"NHcfZVYvkHHxm-4qwwGm9n4tHCSBhLO0FMs2uJEWXlo",[562,564],{"title":63,"path":64,"stem":65,"description":563,"children":-1},"Configuration for your services: service variables, shared variables, and dynamic variables.",{"title":71,"path":72,"stem":73,"description":565,"children":-1},"Managed PostgreSQL databases, replicated and backed up, connected to your services without copying credentials.",[567,570,572,575,578,581,584,587,590,593,596,599,602,604,606,608,609,610,611,613,615,617,619,621,623,625,627,629,631,633,635,637,639,642,646,650],{"path":6,"title":568,"description":569},"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":571,"title":9,"description":556},"\u002Fdocs\u002Fguides\u002F.navigation",{"path":16,"title":573,"description":574},"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":576,"description":577},"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":579,"description":580},"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":582,"description":583},"Deploy an Astro site","Deploy an Astro site on Lucity, static by default and server rendered when you add an adapter.",{"path":32,"title":585,"description":586},"Deploy an Express API","Deploy an Express API on Lucity. Three requirements, none of them platform-specific.",{"path":36,"title":588,"description":589},"Deploy a FastAPI service","Deploy a FastAPI service on Lucity. Detection is picky about layout, and the fix is one setting.",{"path":40,"title":591,"description":592},"Deploy a Django project","Deploy a Django project on Lucity, with migrations that run themselves and static files that do not.",{"path":44,"title":594,"description":595},"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":597,"description":598},"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":600,"description":601},"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":603},"Services are the deployable units of a project: what they are, how they are configured, and how they scale.",{"path":56,"title":55,"description":605},"How a deployment goes live on Lucity, and the ways to trigger one.",{"path":60,"title":59,"description":607},"How Lucity turns your source code into a container image.",{"path":64,"title":63,"description":563},{"path":68,"title":67,"description":554},{"path":72,"title":71,"description":565},{"path":76,"title":75,"description":612},"S3-compatible buckets for uploads, exports and anything else your service needs to keep.",{"path":80,"title":79,"description":614},"Persistent disks for services that need to keep state on the filesystem.",{"path":84,"title":83,"description":616},"A Redis®-compatible key-value store for caching, sessions and queues.",{"path":88,"title":87,"description":618},"Workspaces represent your organization in Lucity, with their own members, isolation and billing.",{"path":92,"title":91,"description":620},"Projects group services, databases and the environments they run in.",{"path":96,"title":95,"description":622},"Development, staging, production: isolated copies of the same application.",{"path":100,"title":99,"description":624},"Download a project as a Helm chart and run it on a Kubernetes cluster of your own.",{"path":104,"title":103,"description":626},"The GraphQL API behind the dashboard, with an interactive playground.",{"path":108,"title":107,"description":628},"Deploy and manage your services from a terminal or a CI pipeline.",{"path":112,"title":111,"description":630},"Deploy and manage your services from Claude Code, Codex, Cursor or any other MCP client.",{"path":116,"title":115,"description":632},"CPU and memory for every service, and disk usage for every volume.",{"path":120,"title":119,"description":634},"What your services print while they run, and the output of every deployment step.",{"path":124,"title":123,"description":636},"Plans, resource usage, the free trial, and what happens when a payment fails.",{"path":128,"title":127,"description":638},"Run the whole platform on a Kubernetes cluster you own, using the same two Helm charts we run ourselves.",{"path":640,"title":641,"description":556},"\u002Flegal\u002F.navigation","Legal",{"path":643,"title":644,"description":645},"\u002Flegal\u002Fdata-processing-agreement","Data Processing Agreement","How Lucity processes personal data on your behalf.",{"path":647,"title":648,"description":649},"\u002Flegal\u002Fprivacy-policy","Privacy Policy","How Lucity handles your data.",{"path":651,"title":652,"description":653},"\u002Flegal\u002Fterms-of-use","Terms of Use","Terms governing your use of Lucity.",1791216728007]