The best way to deploy an HTML website and API to the cloud
One server, two jobs beats two dashboards and a CORS config for most small apps. A straight comparison of bundling HTML and API together versus splitting them, with the exact commands for each.
By Platform Super Admin • • Deployments
# The best way to deploy an HTML website and API to the cloud
**Published:** August 10, 2026
**Category:** Deployments · Fundamentals
**Reading time:** 6 minutes
**Author:** NEXUS AI Team
---
**Short answer:** if your HTML and your API are small enough to ship together, put them in one server (a static folder plus a few routes) and deploy that as a single container. It is one URL, no CORS, no second bill, and it fits on a free tier. Split them into two separately-hosted services only when you actually need independent scaling or a different tech stack for each side. This post covers both paths, with the commands for each.
---
## The three ways people actually do this
**1. One server, two jobs.** An Express, FastAPI, or Flask app that serves your `index.html` (and any CSS/JS) as static files from one route, and your API as JSON routes on the same port. One deploy, one URL, one process. This is the right default for a portfolio site, an internal tool, a small SaaS MVP, or anything where the frontend and backend ship together.
**2. Two hosts, one app.** The HTML lives on a static host (a CDN edge network), the API lives on a separate compute host, and the frontend calls the API's URL over HTTPS with CORS enabled. This is the classic Vercel/Netlify-plus-Render/Railway pattern. It buys you independent scaling and a CDN for the static assets, at the cost of two dashboards, two bills, and a CORS config to maintain.
**3. Raw cloud primitives.** S3 or Cloud Storage plus a CDN in front for the HTML, then Lambda/Cloud Functions or a VM for the API. Full control, the most setup work, and you own the plumbing (TLS certs, IAM, deploy scripts) yourself.
Most people asking "what's the best way to deploy my HTML site and API" have something closer to option 1 in mind and don't need the operational overhead of options 2 or 3 yet.
| | Setup time | Cost to start | Scaling | Best for |
|---|---|---|---|---|
| One server, two jobs | ~5 minutes | Free tier fits | Vertical, then horizontal | MVPs, internal tools, small apps |
| Two hosts, one app | ~15–30 minutes | Two free tiers, or one paid | Independent per side | Apps that outgrew #1 |
| Raw cloud primitives | Hours to days | Pay-as-you-go | Fully manual | Teams with existing cloud infra |
---
## Option 1: deploy HTML + API together as one container
This is the fastest path and the one this section walks through end to end using NEXUS AI, which auto-detects a static folder next to an API server and builds a single production Dockerfile for it — no Dockerfile required on your side.
### Project layout
```text
my-app/
public/
index.html
style.css
app.js
server.js ← serves /public and the /api routes
package.json
```
```js
// server.js
const express = require("express");
const path = require("path");
const app = express();
app.use(express.static(path.join(__dirname, "public")));
app.use(express.json());
app.get("/api/health", (req, res) => res.json({ status: "ok" }));
app.get("/api/items", (req, res) => {
res.json([{ id: 1, name: "First item" }]);
});
const port = process.env.PORT || 3000;
app.listen(port, () => console.log(`Listening on ${port}`));
```
### Deploy it
Install the CLI and log in:
```bash
curl -fsSL https://nexusai.run/install.sh | bash # Linux
curl -fsSL https://nexusai.run/install-mac.sh | bash # macOS
nexus auth login
```
Push the repo to GitHub, then deploy:
```bash
nexus deploy source \
--repo https://github.com/you/my-app.git \
--name my-app \
--provider docker \
--framework express \
--wait
```
NEXUS AI builds a production image, opens a public HTTPS URL through Traefik, and streams build logs while it works. When it finishes, `https://my-app.nexusai.run` serves the HTML at `/` and JSON at `/api/*` from the same origin. No CORS headers needed because it is one origin.
If your HTML has no server logic at all (pure static, no API in the same process), skip the Express wrapper and deploy the folder directly:
```bash
nexus deploy source \
--repo https://github.com/you/my-static-site.git \
--name my-static-site \
--provider docker \
--framework static \
--wait
```
NEXUS AI detects the plain `index.html` and serves it with nginx.
### Add environment variables and a custom domain
```bash
nexus secret create DATABASE_URL "postgres://..." --project my-app
nexus domain add my-app yourdomain.com
nexus domain verify my-app <domain-id>
```
That covers the common case: one small app, one deploy, one bill, free tier eligible.
---
## Option 2: split the static site and the API into two services
Reach for this once the frontend and backend genuinely need to scale, deploy, or fail independently — a marketing site that gets Hacker-News-front-page traffic spikes while the API stays flat, or a frontend team shipping on a different cadence than the backend team.
Deploy the API on its own:
```bash
nexus deploy source \
--repo https://github.com/you/my-api.git \
--name my-api \
--provider docker \
--framework express \
--wait
```
Deploy the static HTML as a second service in the same project (this needs a plan with more than one active deployment — see the FAQ below):
```bash
nexus deploy source \
--repo https://github.com/you/my-frontend.git \
--name my-frontend \
--provider docker \
--framework static \
--wait
```
Point the frontend's fetch calls at the API's public URL, and enable CORS on the API for the frontend's origin:
```js
// my-api/server.js
const cors = require("cors");
app.use(cors({ origin: "https://my-frontend.nexusai.run" }));
```
```js
// my-frontend/app.js
fetch("https://my-api.nexusai.run/api/items")
.then((r) => r.json())
.then(render);
```
Each service now scales, redeploys, and rolls back independently:
```bash
nexus deploy scale my-api 3
```
You can also mix providers here: keep the static frontend on a CDN-first host (Vercel, Netlify, GitHub Pages) for free and put only the API on NEXUS AI. Point the frontend's `NEXT_PUBLIC_API_URL` (or equivalent) at the NEXUS AI URL and enable CORS the same way.
---
## FAQ
**Do I need to write a Dockerfile for a plain HTML site?**
No. NEXUS AI detects an `index.html` with no build manifest and serves it with nginx automatically. If you have a build step (Vite, React, Vue), it detects the framework and runs the production build instead.
**My API needs a database. Does that change the deploy?**
No extra service to wire up separately. Add `--services postgresql` (or `mysql`, `mongodb`, `redis`) to the same `nexus deploy source` command and NEXUS AI provisions the database alongside your app in the same deploy, with `DATABASE_URL` injected automatically.
**Can I use a custom domain instead of the `.nexusai.run` subdomain?**
Yes, on any paid plan. `nexus domain add <deployment> yourdomain.com`, then verify the DNS record NEXUS AI gives you.
**Is there a free tier?**
Yes. The Free plan includes one active deployment on the NEXUS AI managed cloud, no credit card required — enough for the single-server pattern in Option 1. Running the two-service split in Option 2 on NEXUS AI for both halves needs a plan that allows more than one active deployment (Pro and above); running just the API on NEXUS AI Free while the static frontend sits on a separate free static host works within the Free plan.
**Does this handle HTTPS automatically?**
Yes. Every deployment gets a public HTTPS URL through Traefik by default, and custom domains get certificates provisioned automatically once DNS verification passes.
**Can I deploy from the GitHub UI instead of the CLI?**
Yes. Connect your GitHub account from the NEXUS AI dashboard, select a repo and branch, and enable auto-deploy so every push to that branch redeploys automatically.
**What if I'd rather describe the app in plain English and skip writing server.js myself?**
Use the AI App Builder instead: describe the HTML site and the API you want in chat, review the generated files and live preview, then deploy from the same dashboard.
---
For an app with a real database, background workers, and file storage in addition to the HTML + API pair, see [From v0 prototype to production database in 5 minutes](https://nexusai.run/blog/from-v0-prototype-to-production-database-in-5-minutes) and [Deploy a full-stack Python app with Postgres, Redis, and workers in 5 minutes](https://nexusai.run/blog/deploy-full-stack-python-postgres-redis-workers-5-minutes).
[Start free.](https://nexusai.run/register)