Deploy Next.js, React or Vue with AI: static site or Node app?

Which JavaScript sites go live as static files and which need a Node.js app, plus a checklist, build-time vs run-time .env values and a one-pass AI prompt.
Most websites AI writes today are JavaScript: React, Vue, Next.js or Vite. On your machine npm run dev looks perfect, and then going live raises questions. What exactly do I upload? Why does refreshing a page other than the home page give a 404? Why did my .env values vanish after the deploy?
This guide explains which way each kind of JavaScript site should go onto BrewInTH, static site or Node.js app, what the platform builds for you, a checklist before you hand it over, and a prompt that gets an AI to deploy it in one pass.
In short
✅ React / Vue built with Vite and with no server part = a static site (build locally, upload the files indist/)
✅ Next.js with API routes or server rendering = a Node.js app (send the source as a ZIP; the platform builds and runs it)
✅ A Node app needspackage.json+ a lockfile, astartscript, and must listen on thePORTvariable
✅ Values baked in at build time (VITE_*,NEXT_PUBLIC_*) and secrets read at run time live in different places
✅ You can leave the technology on "Let the platform decide"; it looks at the first files you send
Static site or Node.js app?
A static site is HTML, CSS, JavaScript and images sent straight to visitors, with no program running behind them. It is fast, cheap, and on the free plan it never sleeps, because there is no app to put to sleep.
A Node.js app is a program that keeps running and answers requests: a Next.js page that reads the database before it renders, or an API that saves data. BrewInTH takes the source as a ZIP, then builds and runs it.

How to tell which one you have
- A Vite + React/Vue project where everything runs in the browser, talks to an outside API or saves nothing → static
- Next.js with an
app/api/orpages/api/folder, server actions or a database → Node.js app - Express, Fastify, NestJS or any backend of your own → Node.js app
- Not sure? Ask the AI that built it: "Does this site need a running server, or can it be built into static files?" and let it decide.
Route 1: React / Vue (Vite) as a static site
- Have the AI run
npm run buildlocally. You get adist/folder withindex.htmland anassets/folder. - Upload the files inside
dist/to the project, withindex.htmlat the root, not underdist/. - Publish, or let the AI publish.
A static site is uploaded file by file (the AI can do it). The platform does not unpack a ZIP for a static site and does not build it, so always build locally first.
Watch out: sub-page links and 404s
A static site on BrewInTH serves files by their exact names. / opens index.html, but if the site uses React Router or Vue Router with clean addresses like /menu, clicking a link inside the site works while refreshing it or opening it directly gives a 404, because there is no file called menu.
Two easy fixes:
- Hash routing: React Router's
HashRouter(orcreateHashRouter), Vue Router'screateWebHashHistory(). Addresses become/#/menuand every page opens directly. - Go live as a Node.js app instead, with a small server that answers every non-file path with
index.html(see route 2).
A one-page site, or several pages that link to real .html files, needs nothing extra.
Route 2: Next.js and server sites as a Node.js app
For a project with a package.json, BrewInTH's build does this:
- Installs dependencies with
npm ciwhen there is apackage-lock.json, otherwisenpm install - Runs
npm run buildif there is abuildscript - Starts the app with
npm startif there is astartscript, otherwise looks forserver.js,index.jsormain.js
A standard Next.js project already has "build": "next build" and "start": "next start". The platform sets the PORT variable for the app (8080 by default) and next start reads PORT by itself, so usually nothing needs changing.

Checklist before you send it
- One ZIP with
package.json+ lockfile at the root, not wrapped in an extra project-name folder - No
node_modules,.next,distor real.env: the platform installs and builds again - A
startscript, or aserver.js/index.js - The app listens on
PORTon0.0.0.0, notlocalhost, with no hard-coded 3000 - The home page must not error: the platform checks readiness by opening
/, which must answer 200 or a redirect (to a login page, say) within 5 minutes. For an API-only app, have the AI set a health path such as/health
.env values: baked in at build, or read at run time?
This is the part that confuses people most.
- Secrets such as
DATABASE_URL, API keys orJWT_SECRETgo in the project's App settings tab (or the AI sets them). The app reads them at run time, and they never belong in the ZIP. - Values compiled into browser code, such as
VITE_API_URLorNEXT_PUBLIC_SITE_NAME, are read at build time. The build step does not read App settings, so these must be in a.env.productionfile sent with the source. Put only public values there: everyone who opens the site can see them anyway.
With a PostgreSQL database, the platform gives the app DATABASE_URL itself, so Prisma works straight away. Have the AI set table creation such as npx prisma migrate deploy as the release command: it runs before traffic moves to the new version, and if it fails the current version keeps serving.
A prompt for a one-pass deploy
Create a project on BrewInTH, choose Let the platform decide for the technology, add a database if the site stores data, then give the ready-made message with the link + token to an AI that works on your computer (Claude Code, Codex, Cursor or Windsurf), followed by this prompt:
(paste BrewInTH's ready-made message here)
Deploy the JavaScript site in this folder to BrewInTH so it really works.
1. First decide whether it needs a server.
- No (Vite + React/Vue): build locally and upload the files in dist/ as a static site.
If it uses clean-URL routing, switch to hash routing first.
- Yes (Next.js with API/SSR, Express): send a ZIP with the lockfile, without node_modules/.next/.env.
Check there is a start script and that the app listens on PORT on 0.0.0.0.
2. Put secrets in the project's App settings; put public build-time values in .env.production.
3. If it uses Prisma, set the release command to npx prisma migrate deploy.
4. After deploying, open the live site and check every page, including refreshing a sub-page, then give me the link.
"Including refreshing a sub-page" catches the 404 before your visitors do, and "first decide whether it needs a server" stops the AI from running a Vite site as an app for no reason.
Good to know
- The free plan gives an app 256 MB of RAM and 20 MB of file storage. A small Next.js app runs; if yours grows or feels slow, paid plans have more RAM (see the plans).
- Apps on the free plan sleep after a quiet spell, so the first visitor waits a moment. Static sites do not.
- Files your users upload should not live in the app's folder, where a new deploy wipes them. Have the AI turn on persistent
/datastorage or keep them in the database. - No coding agent? The Upload and go live page (BETA) accepts a ZIP of the whole folder, but for a JavaScript site that needs a build and settings, an AI working on your computer gives you far more control.
Watch the video (in Thai)
▶ From creating a project to opening the site (1:30)
Watch on YouTube
FAQ
Do I have to choose the technology?
No. Choose Let the platform decide when you create the project. The platform looks at the first files you send (package.json = Node.js, only index.html = static site) and fixes the technology from that first release.
Refreshing a sub-page gives a 404. How do I fix it?
A static site serves files by their real names. Have the AI switch to hash routing, or go live as a Node.js app that answers every path with index.html.
The deploy worked but my .env values do nothing
Values read at run time go in the App settings tab, followed by a new deploy. VITE_* and NEXT_PUBLIC_* values must be in a .env.production sent with the source, because they are baked in at build time.
Can I use pnpm or yarn?
The platform installs with npm, following package-lock.json. If your project uses another tool, have the AI create a package-lock.json with npm install and test locally before sending. A project with a bun.lock file gets the Bun runtime.
What about Nuxt or SvelteKit?
Yes. With a server, deploy it as a Node.js app: have the AI set a start script that runs the built server file and listens on PORT. Exported as static files, it deploys as a static site.
Summary
Before you put a JavaScript site online, answer one question: does it need a server? No: build locally and go live as a static site, minding the router. Yes: send a ZIP with the lockfile and let the platform build and run it as a Node.js app. Keep secrets and build-time values apart, and have the AI check every live page before you share the link.
Start your first project for free →
