Reference

What to check before you put a static site online

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.

A .env file was published

What you see

dist/
  .env
  index.html
  assets/index-a3f1c2.js

The whole file is downloadable by anyone who visits. Rotate every value in it, then keep .env out of the folder your build copies verbatim — usually public/.

Your code reads process.env.API_KEY, and nothing sets it

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.

Vite replaces process.env with an empty object, so this value is simply undefined in the browser — no error, no warning, the request just goes out without it and the API answers 401. Read it through import.meta.env.VITE_something instead, or define it in vite.config.

The fix

const apiKey = import.meta.env.VITE_API_KEY;

process.env.API_KEY is still live in the output

What you see

Uncaught ReferenceError: process is not defined
    at index-a3f1c2.js:1:2043

Browsers have no process object, so this line throws the moment the page loads — usually a blank screen. In Vite, values the browser needs must be read through import.meta.env and named VITE_something.

The fix

const apiKey = import.meta.env.VITE_API_KEY;

The output points at your own machine

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";

No index.html in the output

What you see

dist/
  assets/index-a3f1c2.js
  assets/index-9b2e01.css

A 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.

The title is still the template default

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 page has no 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>

No meta description

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." />

No viewport meta tag

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" />

No Open Graph tags

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" />

No icon of your own

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" />

The <html> tag has no lang attribute

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">

No robots.txt

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.xml

One script is 2.4 MB

What 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'));

One asset is 4.0 MB

What you see

dist/assets/hero-8f2a1b.png   4,102.11 kB

Large 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.

Let it find yours

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

See also

Build errors and how to fix themThe 13 build failures we see most often in AI-generated React projects — the exact npm, Vite and tsc output, what each one means, and the fix.