A static build has no server behind it, so whatever is wrong in these files is wrong for every visitor. React2Static runs all of the following against your own build output before you ship. Here is the whole list, with the fix for each.
The package names, paths and sizes in the examples below are only examples — the builder fills in the ones from your own project.
What you see
dist/
.env
index.html
assets/index-a3f1c2.jsThis file (it's named .env) can hold your passwords and keys, and right now any visitor can download it. Treat everything in it as leaked — go to each service and make new keys. Then ask the AI tool that built your project to move the .env file out of the "public" folder so it doesn't get published again.
What you see
const apiKey = process.env.API_KEY;
fetch(url, { headers: { Authorization: `Bearer ${apiKey}` } });
// Vite turns process.env into {} — the header goes out as
// "Bearer undefined" and the API answers 401. No error in the console.Your published site quietly fails to load its data — nothing shows an error, it just doesn't work. Paste this to the AI tool that built your project: "A setting read from process.env is empty in the browser, so requests go out without it. Read it through import.meta.env (name starting VITE_), or set it in vite.config." That tells it what to fix.
The fix
const apiKey = import.meta.env.VITE_API_KEY;What you see
Uncaught ReferenceError: process is not defined
at index-a3f1c2.js:1:2043This is the usual reason a published page comes up completely blank. You don't need to fix it by hand — paste this to the AI tool that built your project: "The app reads settings with process.env, which doesn't work in the browser. Switch to import.meta.env, with names starting VITE_." That tells it exactly what to change.
The fix
const apiKey = import.meta.env.VITE_API_KEY;What you see
const API = "http://localhost:3000/api";It contains http://localhost:3000/api. That address only exists on the computer this was built on, so the request fails for every visitor. Point it at a public URL.
The fix
const API = "https://api.example.com";What you see
dist/
assets/index-a3f1c2.js
assets/index-9b2e01.cssA static host serves index.html as the entry page. Without one, visitors get a file listing or a 404. Check what your build actually writes.
What you see
<title>Vite + React + TS</title>It currently reads “Vite + React + TS”. That is the text search results and shared links will show. Change it in index.html.
The fix
<title>Your product name — what it does, in one line</title>The browser tab and every search result use the <title> tag. Add one in index.html.
The fix
<title>Your product name — what it does, in one line</title>Search engines fall back to whatever fragment they can scrape. One clear sentence in <meta name="description"> is what decides whether people click.
The fix
<meta name="description" content="One clear sentence about what this page is for." />Phones will render the page at desktop width and zoom out, so everything looks tiny. Add <meta name="viewport" content="width=device-width, initial-scale=1"> to index.html.
The fix
<meta name="viewport" content="width=device-width, initial-scale=1" />Shared to a chat app or a social feed, your link shows as a bare URL with no title or image. Add og:title, og:description and og:image.
The fix
<meta property="og:title" content="Your product name" />
<meta property="og:description" content="One clear sentence." />
<meta property="og:image" content="https://example.com/og.png" />What you see
<link rel="icon" type="image/svg+xml" href="/vite.svg" />The browser tab and bookmarks show a blank sheet, or the template logo you inherited. Add your own favicon and link it from index.html.
The fix
<link rel="icon" href="/favicon.ico" sizes="any" />Screen readers use it to pick a pronunciation and browsers use it to offer translation. Add lang="en", or whichever language the page is in.
The fix
<html lang="en">Crawlers will index the site anyway, but robots.txt is where you point them at your sitemap. We can add one at the Ship step.
The fix
User-agent: *
Allow: /
Sitemap: https://example.com/sitemap.xmlWhat you see
dist/assets/index-a3f1c2.js 2,418.55 kB │ gzip: 731.20 kB
(!) Some chunks are larger than 500 kB after minification.On a phone connection that is seconds of blank screen before anything appears. Splitting the heavy parts out with dynamic import() usually cuts the first load a long way.
The fix
const Editor = lazy(() => import('./Editor'));What you see
dist/assets/hero-8f2a1b.png 4,102.11 kBLarge images and fonts hold up the first paint. Converting images to WebP and resizing them to the size actually displayed usually removes most of the weight.
Drop your ZIP into the builder. It runs the real build in your browser, and when something breaks it points at the line that matters instead of handing you the whole log.
Open the builder