vbtnl_Connect to AI
How-to guides4 min read

How to host an app built with Claude or Codex

host ai appdeploy claude code appcodex deployvibe coding hostingmcppostgres

Claude or Codex wrote your app. It works on your laptop. Now you want other people to open it.

Before you pick a host, check four things in the code: the app has one start command, it listens on the port from PORT, it reads secrets from environment variables, and it keeps data in a database, not in files. If these are fine, the app will run almost anywhere.

Then you have a choice. You can put it on a host yourself. Or you can let the agent do it from the same chat, through an MCP server like vbtnl. This guide shows both, with a full example at the end.

Why it works on your laptop but not online

Your app works locally because of things only your laptop has:

  • The address is localhost. Nobody else can open it.
  • The keys are in a .env file, or even in the code.
  • Data is saved to a file, like data.json or an SQLite file. Most hosts delete these files on every restart.
  • You start the app by hand. If it crashes at night, it stays down.

To host the app, you fix these four things and give it a public HTTPS address.

Checklist: is your app ready?

Ask your agent to check the project against this list. You can paste the list into the chat.

  1. One start command that runs the app without your help. For example uvicorn main:app --host 0.0.0.0 --port $PORT or npm start.
  2. It listens on 0.0.0.0 and the port from PORT. If the app listens on 127.0.0.1:8000, the host can't reach it.
  3. Dependencies are in a file: requirements.txt for Python, package.json for Node.js.
  4. Secrets come from environment variables, not from a file in the project.
  5. Data is in a database. Postgres is a safe choice.
  6. A health check: an address like /health that answers 200, so you can see that the app is alive.

Three ways to put it online

What you doGood when
A VPSRent a server. Install the runtime, a web server, a certificate and a process manager. Copy the code.You want full control and you know Linux.
A git-based platformPush the code to a repository. Connect it to the platform. Set the build and the variables in a dashboard.You already use git.
An MCP hosting serverAdd the host to Claude or Codex once. The agent writes the files on the server, runs them and publishes.The agent wrote the app, and you want it to finish the job.

The first two work well, and your agent can help you with them. But there is one problem: the agent can't see the server. When the deploy fails, you copy the logs from a dashboard into the chat, then copy the agent's commands back.

With an MCP hosting server, the agent has tools for the server itself. It can write a file, run a command, read the logs, publish and roll back. So it can try, see the error and fix it without you in the middle.

Example: a waitlist page with a database

Here is the full path on vbtnl with Claude Code. With Codex it works the same way.

Step 1. Connect vbtnl

bash
claude mcp add --transport http vbtnl https://api.vbtnl.com/mcp

Then type /mcp in Claude Code, pick vbtnl and log in. For Codex and other apps, see the docs.

Step 2. Ask for the app

Code
Build a waitlist page on vbtnl: an email form, a counter of people who joined,
and a Postgres database for the emails.

The agent does this, step by step:

  1. create_project creates a project with a draft address and a production address.
  2. add_database adds Postgres: one database for the draft and another one for production.
  3. write_files writes the code on the server.
  4. exec opens the draft to check that it works.
  5. It sends you the draft address, like waitlist-dev.vbtnl.site.

The code

The agent writes its own version, but it will be close to this. There are three small files.

vbtnl.json tells vbtnl how to start the app:

json
{
  "stack": "python",
  "start": "uvicorn main:app --host 0.0.0.0 --port $PORT",
  "database": "postgres"
}

requirements.txt:

Code
fastapi
uvicorn
psycopg[binary]
python-multipart

main.py:

python
import os
from contextlib import asynccontextmanager

import psycopg
from fastapi import FastAPI, Form
from fastapi.responses import HTMLResponse

DATABASE_URL = os.environ["DATABASE_URL"]

PAGE = """<!doctype html>
<title>Waitlist</title>
<h1>Something new is coming</h1>
<form method="post" action="/join">
  <input type="email" name="email" placeholder="Your email" required>
  <button>Join the waitlist</button>
</form>
<p>{count} people joined so far.</p>"""


@asynccontextmanager
async def lifespan(app: FastAPI):
    # Create the table once, when the app starts.
    with psycopg.connect(DATABASE_URL) as conn:
        conn.execute(
            "create table if not exists waitlist ("
            "email text primary key, joined_at timestamptz not null default now())"
        )
    yield


app = FastAPI(lifespan=lifespan)


@app.get("/", response_class=HTMLResponse)
def home():
    with psycopg.connect(DATABASE_URL) as conn:
        count = conn.execute("select count(*) from waitlist").fetchone()[0]
    return PAGE.format(count=count)


@app.post("/join", response_class=HTMLResponse)
def join(email: str = Form(...)):
    with psycopg.connect(DATABASE_URL) as conn:
        conn.execute(
            "insert into waitlist (email) values (%s) on conflict do nothing",
            (email.strip().lower(),),
        )
    return "<p>You are on the list. <a href='/'>Back</a></p>"


@app.get("/health")
def health():
    return {"ok": True}

Compare it with the checklist. One start command. It listens on 0.0.0.0 and $PORT. Dependencies are in a file. The database address comes from DATABASE_URL. The data is in Postgres. And there is /health. You don't set PORT or DATABASE_URL yourself, vbtnl does it.

Step 3. Check the draft, then publish

Open the draft address. Join the waitlist with a test email. Ask for changes if you want them: the draft restarts about a second after each change. When you like it, write:

Code
Ship it.

The agent publishes the app. It goes live at an address like waitlist.vbtnl.site, with its own empty production database.

Already have the app on your laptop?

You don't need to start again. Open the agent in the project folder and write:

Code
Put this project on vbtnl. Check it against the hosting rules first:
port from $PORT, secrets from environment variables, data in Postgres.

The agent reads your files, fixes what doesn't fit, copies them into a project and sends you a draft address. The keys from your .env become project secrets. Give the values in the chat when the agent asks, and they will never be written to a file.

If the app saves data to a local file, ask the agent to move it to Postgres before you publish. In production, files written by the app are lost on restart.

After the app is live

  • Something broke after a change. Write "roll back". Every publish is saved as a version, and going back takes one step.
  • You want to know why it fails. Ask the agent to read the logs. It can read both the app logs and the build logs.
  • You need something on a schedule. Just ask: "every Monday at 9:00 UTC email me the number of signups". A project can have up to 10 schedules.
  • You want your own domain. On paid plans production can use your domain, with HTTPS.

Your users' data and the AI

Everything a tool sends back to the agent goes to your AI provider. So on vbtnl the agent can't read the production database, and production logs come to it with personal data hidden. It sees the structure of the production database, but not the values. It works with draft data instead. Only the account owner can give it more access.

Check this with any host you choose. If the agent has full access to production, it reads your users' emails every time it looks for a bug.

What it costs

One app is free. The free plan has one project with a 1 GB Postgres database, 0.5 vCPU and 1.25 GB of RAM, and an address on vbtnl.site. You don't need a card. Paid plans start at $19 a month. You get more projects, more CPU and memory, and your own domains. See pricing.

Questions

Can Claude deploy an app by itself?

Yes, if it has tools for a host. Claude and Codex can't reach a server alone. An MCP server gives them these tools. When vbtnl is connected, the agent creates the project, writes the files, runs them and publishes.

Do I need git or GitHub?

No. The agent writes the files directly into the project on the server. You can download the whole project as a .zip any time and put it in a repository if you want.

Does it work with Claude on the web, not only Claude Code?

Yes. Add vbtnl as a custom connector in the Claude settings and ask in a normal chat. See Connect Claude and Claude Desktop.

What languages can I use?

Python 3.12, Node.js 22, or a static site with plain HTML, CSS and JavaScript. There is no GPU and no custom ports.

Is the code mine?

Yes. It is normal Python or Node.js. Nothing in the code ties it to vbtnl: the app reads PORT and DATABASE_URL, like on most hosts.

Can I host a bot instead of a website?

Yes. See Deploy a Telegram bot for free with Claude Code.

More answers are in the FAQ and the docs.

← back to how-to guides