Discover why Lovable builds succeed yet yield blank outputs. Get tips and best practices to troubleshoot and prevent build issues.

Book a call with an Expert
Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.
Builds can report "success" but produce a blank site in Lovable when the build writes files somewhere the Lovable preview/publish runtime doesn't serve (wrong output dir or ignored by VCS), when the built index exists but is empty/contains only placeholders, when runtime routing or serverless handlers return empty bodies, or when build-time environment values (secrets/config) differ in Lovable so the app renders nothing even though the build step finished without errors.
Below are ready-to-paste Lovable prompts you can paste into your Lovable chat to have Lovable inspect the repo and produce concrete evidence for the causes above. These prompts ask Lovable to only read files/logs and report; they do not change behavior.
// Prompt: repo-build-output-check
// Please inspect the repository and produce a concise diagnostics report focused on build artifacts.
// 1) List whether any of these directories exist at repo root: build, dist, out, public, .next, out.
// For each directory that exists, list files (top-level) with sizes in bytes and last modified time.
// 2) If an index.html exists in any of those locations, print the first 400 characters of that file and the file size.
// 3) If an index.html is zero bytes or smaller than 200 bytes, highlight that as "small-index" in the report.
// Prompt: inspect-package-json-and-build-script
// Open package.json at the repo root and return:
// 1) The "scripts" section exactly as written (show build, start, dev if present).
// 2) If the build script contains a CLI flag setting an output folder (e.g., --out-dir, --dest, --output), extract that value.
// 3) State which framework the repo looks like (react-scripts, vite, next, astro, etc.) based on dependencies, and the default build output for that framework.
// Prompt: search-for-env-vars-and-build-time-deps
// Search the codebase for process.env. occurrences and list each unique variable name (e.g., process.env.API_URL).
// For each variable name, list the files where it appears (path + line number) and mark whether it looks used during build-time (in config files, vite/webpack, or top-level SSR templates) or only at runtime.
// Prompt: preview-publish-logs-summary
// Retrieve the latest Preview/Publish build logs that Lovable recorded for the last run.
// Paste the full logs, then summarize any lines that mention:
// - "built to", "output", "copying", "no files", "0 bytes", "warning", or "error".
// Highlight any log lines that suggest an output path or "no files to publish".
// Prompt: inspect-server-entrypoints
// Find likely server/SSR/api entrypoints under server/, api/, functions/, or src/server/ (also check server.js or index.js at repo root).
// For each file that handles the root route ("/") or returns HTML, paste the first 80 lines and point out any return that sends an empty string or returns a template that may be missing.
// Prompt: gitignore-and-vcs-export-check
// Open .gitignore at repo root (if present) and list entries that would match build folders (e.g., /dist, /build, /out).
// If a matching ignore exists, mark it "may-block-export". Also indicate whether the repository currently contains built artifacts in git (i.e., check if build/dist files are tracked in the repo tree).
// Prompt: recommend-github-export-if-needed
// If the diagnostics above require running a local or CI build not possible inside Lovable, state exactly which artifacts or commands need to be run outside Lovable and label that section as "outside Lovable (terminal required)". Do not run anything — only list the exact steps and files that would be produced.
This prompt helps an AI assistant understand your setup and guide you through the fix step by step, without assuming technical knowledge.
Add a top-level runtime error catcher and safe fallbacks, ensure your static entry (public/index.html) exists with a proper
process.env, import.meta.env, or NEXT_PUBLIC_.<base href="/">.
Paste each prompt below into Lovable’s chat (one at a time). Each prompt tells Lovable exactly what files to change or create so Preview will stop showing a blank page and instead surface the real error.
// Prompt A: Add a top-level Error Boundary and runtime crash catcher.
// Update src/main.tsx (or src/index.tsx if that's your entry). If the file doesn't exist, create it at src/main.tsx.
// Wrap the app render so runtime exceptions show a visible error message and also log to console.
Please update src/main.tsx with a top-level error boundary and global try/catch around initial render. Replace the file content or create it with the following (adjust import paths if your App component file is at src/App.tsx or src/App.jsx):
// src/main.tsx
import React from 'react'
import { createRoot } from 'react-dom/client'
import App from './App'
// Simple error boundary component that shows error text instead of a blank page
function ErrorBoundary({ children }: { children: React.ReactNode }) {
const [err, setErr] = React.useState<Error | null>(null)
React.useEffect(() => {
function handleUnhandled(e: any) {
setErr(e?.reason || e?.error || new Error('Unhandled error'))
console.error('Unhandled error:', e)
}
window.addEventListener('unhandledrejection', handleUnhandled)
window.addEventListener('error', handleUnhandled)
return () => {
window.removeEventListener('unhandledrejection', handleUnhandled)
window.removeEventListener('error', handleUnhandled)
}
}, [])
if (err) {
return (
<div style={{ padding: 24, fontFamily: 'system-ui' }}>
<h2>Runtime error detected</h2>
<pre>{String(err?.message || err)}</pre>
<details style={{ whiteSpace: 'pre-wrap' }}>
<summary>Console output</summary>
<p>Open developer console or check build logs for stack trace.</p>
</details>
</div>
)
}
return <>{children}</>
}
try {
const container = document.getElementById('root')
if (!container) throw new Error('root element not found (public/index.html may be missing)')
const root = createRoot(container)
root.render(
<ErrorBoundary>
<App />
</ErrorBoundary>
)
} catch (e) {
console.error('Render failed:', e)
// Replace page body with a visible message so Preview isn't blank
document.body.innerHTML = '<div style="padding:24px;font-family:system-ui"><h2>Render failed</h2><pre>' + String(e) + '</pre></div>'
}
// Prompt B: Ensure public/index.html exists and has a correct base href.
// Create public/index.html if missing. This prevents routing or missing root-element issues.
Please create or replace public/index.html with this minimal entry so the app has a predictable root element:
<!-- public/index.html -->
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<base href="/" /> <!-- ensure correct base path for client routing -->
<title>App (Preview)</title>
</head>
<body>
<div id="root"></div>
<!-- Scripts are injected by build; this file ensures #root exists -->
</body>
</html>
// Prompt C: Add safe env fallbacks to avoid crashes when Secrets are missing.
// Create src/envFallback.ts and import it from your app entry (src/main.tsx or src/App.tsx).
// This gives developer-visible warnings instead of breaking at runtime.
Please add src/envFallback.ts with safe getters and console warnings:
// src/envFallback.ts
export function getEnv(name: string, fallback = '') {
// handle Vite/NX/CRA/Next style env references
const value = (process?.env && (process.env as any)[name]) || (typeof import.meta !== 'undefined' && (import.meta as any).env?.[name]) || fallback
if (!value) {
// show a clear console message in Preview
console.warn(`Missing env var ${name} — using fallback: "${fallback}"`)
}
return value
}
Also update your code to import getEnv where you read env vars. If you can't update everywhere, add a single usage in src/main.tsx to log the keys you expect so Preview shows missing variables:
// in src/main.tsx (add near top)
import { getEnv } from './envFallback'
console.log('env check:', { API_URL: getEnv('API_URL', ''), NODE_ENV: getEnv('NODE_ENV', 'development') })
// Prompt D: Add a simple static health page to confirm build output is present.
// Create public/health.html — useful to check whether the build produced static files or routing is the issue.
Please create public/health.html:
<!-- public/health.html -->
<!doctype html>
<html>
<head><meta charset="utf-8" /><title>Health</title></head>
<body>
<h1>Build artifact exists</h1>
<p>If you can open this file in Preview/Publish, static output is present.</p>
</body>
</html>
Add quick build-time validation, a visible runtime error page, and explicit build-output/config changes so missing envs, failed bundling, or empty outputs fail loudly instead of producing a blank site. Implement these in-chat by having Lovable add a small env-check script run before build, an ErrorBoundary to surface render errors, a healthcheck/static marker file, and changing package.json build scripts so the cloud will fail fast and show errors in Preview.
Paste this into Lovable chat to create a file and update package.json. It ensures required env vars exist and exits non‑zero (so Lovable Cloud/Preview fails) if something is missing.
// scripts/ensure-env.js
const required = ['NODE_ENV', 'PUBLIC_API_URL' /* add your required names here */];
const missing = required.filter(k => !process.env[k]);
if (missing.length) {
console.error('Missing required env vars:', missing.join(', '));
process.exit(1);
}
console.log('Env validation passed');
// package.json (patch)
{
"scripts": {
"prebuild": "node scripts/ensure-env.js",
"build": "vite build" // keep your existing build command if different
}
}
Paste this into Lovable chat to create the component and wrap your app entry so runtime render errors show a useful message instead of a blank page.
// src/ErrorBoundary.jsx
import React from 'react';
export default class ErrorBoundary extends React.Component {
constructor(props){ super(props); this.state = {error: null}; }
static getDerivedStateFromError(error){ return {error}; }
componentDidCatch(error, info){ console.error('Render error', error, info); }
render(){
if(this.state.error){
return (
<div style={{padding:20}}>
<h2>Something went wrong</h2>
<pre>{String(this.state.error)}</pre>
<p>Check the server logs and Preview console for details.</p>
</div>
);
}
return this.props.children;
}
}
// src/main.jsx (patch)
// import ErrorBoundary and wrap <App />
import React from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
import ErrorBoundary from './ErrorBoundary';
createRoot(document.getElementById('root')).render(
<ErrorBoundary><App /></ErrorBoundary>
);
Paste this into Lovable chat to create a static indicator file the hosting layer can serve directly from your public/static folder.
// public/healthcheck.txt
OK
<!-- public/500.html -->
<!doctype html>
<html>
<body>
<h1>Build or runtime error</h1>
<p>Check Preview logs or the project console in Lovable for details.</p>
</body>
</html>
Paste this into Lovable chat for step-by-step actions you must perform in the Lovable UI (no terminal):
From startups to enterprises and everything in between, see for yourself our incredible impact.
Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We’ll discuss your project and provide a custom quote at no cost.