# Serving from a sub-path

> Two variables carry the mount point, one at build time and one at runtime, and they have to agree.

Page: https://sdk.chatfuel.com/docs/deploy/sub-path
Markdown: https://sdk.chatfuel.com/docs/deploy/sub-path.md

The client's asset URLs are written into `index.html` at build time; the server learns its mount
point at runtime. A sub-path is therefore two variables, and they have to carry the same value.

```
VITE_BASE_PATH=/app/ npm run build
BASE_PATH=/app npm start
```

That serves the app at `https://example.com/app/`.

## What each one does [#what-each-one-does]

`VITE_BASE_PATH` is Vite's `base`. It rewrites the asset URLs in `index.html`, and the router reads
it back, so every address the app builds sits below it.

`BASE_PATH` tells the server which prefix is the app. Anything outside it is a 404. A missing
trailing slash is normalized, so `/app` and `/app/` are the same value to the server, and `/app` —
the mount point without its slash — is the app's own root.

The Chatfuel proxy routes (`/chatfuel/*`) stay where they are, above the mount point.

<Callout type="info">
  Both or neither. Set one without the other and you have a deployment where the page loads and
  nothing else does.
</Callout>

## When the two disagree [#when-the-two-disagree]

A client built for `/app/` and served at the root asks for `/app/assets/...`, which is not there:
the page arrives, every script 404s, and the app never starts. The other way round is the same
failure from the other side — a client built for the root, served under `BASE_PATH=/app`, asks for
`/assets/...`, which is outside the mount point.

You cannot fix either at runtime. The URLs are already in the bundle, so the answer is a rebuild
with the value the server is running with.

## Not on Vercel [#not-on-vercel]

Vercel serves the app from the domain root and supports no sub-path at all. If you need one, run
the bundled Node server yourself — on [a box you own](/docs/deploy/node-server) or in
[Docker](/docs/deploy/docker).
