A Safer Publish Checklist for Vibe-Coded Websites
AI tools can turn a prompt into a working site in an afternoon. But the speed hides problems that a slower project finds. For example, an .env file is in the upload folder, or a real customer name is in the sample data. A form accepts anything, or anyone can open a preview link.
This checklist is the launch process to run before you share an AI-generated site with customers, coworkers, investors or the public. The examples use Cloudflare Pages, Netlify and Vercel, but the checks apply to any static host.
1. Review the generated files first
Review the file list first, not the rendered page. An agent sometimes leaves assets, JSON, CSV, screenshots, copied logs or debug files in the folder that you will upload. Every file in that folder gets a public URL, even if no page links to it.
Search the folder for these items:
.envfiles, API keys, tokens, private certificates and service-role keys.- Client names, internal metrics, screenshots or pasted notes.
- Debug pages, console logs and old exports.
- Sample data that looks real enough to confuse a visitor.
- Broken links, missing assets and files with misleading names.
Deploy only the build output, the folder that the build creates (often dist/ or build/). Never deploy the project root. Then scan that folder for secrets. Gitleaks can scan a plain folder, not only a Git repository:
brew install gitleaks
gitleaks dir -v dist
A plain text search also finds the obvious names:
grep -rniE "api[_-]?key|secret|token|password" dist
If the code is in a public GitHub repository, GitHub runs secret scanning automatically. That scan runs after the push, so it does not replace your own review.
2. Look at what the browser receives
A static site sends all of its JavaScript to every visitor. If the page calls a paid API with a key in the code, anyone can open the developer tools and copy that key. Search the built JavaScript for keys. Then open the live page and view the source. In the Network tab, look for requests that carry credentials (keys, tokens or passwords).
A static page can call public APIs. Anything that writes data, spends money or reads private records needs a server-side function or a protected backend that holds the key.
3. Decide who sees it first
Most AI-built sites need a private review round before launch. Put the gate (the password or sign-in step) on the host, not inside the page. A JavaScript password prompt hides the page, but people can still download the files. Google’s guidance says the same thing. Password-protect private content, because a noindex rule only keeps it out of search results.
| Host | How to gate a review | What to know |
|---|---|---|
| Cloudflare Pages | Cloudflare Access with one-time PIN login | Reviewers sign in with a code sent to their email. There is no shared password. |
| Netlify | Password protection | A shared password. It needs the Pro plan or higher. |
| Vercel | Deployment Protection | Vercel Authentication works on all plans, but reviewers need Vercel accounts. Password Protection needs Pro (as a paid add-on) or Enterprise. |
| GitHub Pages | None | Pages sites are public even when the repository is private. |
On Cloudflare Pages, Settings > General > Enable access policy protects only the preview deployments. Preview deployments are test copies with their own URLs. The production *.pages.dev address and any custom domain need their own Access applications. The Pages known issues page lists the steps. Preview URLs are public by default, so do not treat a random-looking preview link as private.
With email-code access, you also know who came in. In the Cloudflare Zero Trust dashboard, the Access authentication logs (under Logs) show the user email, the application and the time of each login. The log records sign-ins, not the pages that someone read.
4. Review risky flows before launch
AI-built sites often include forms, upload controls, comments, votes or signup flows. Each one is a way in for spam and abuse.
Review these items:
- Form validation (rules that reject bad input) and required fields.
- Rate limiting (a cap on submissions over time) for public submissions.
- Server-side validation for any protected action.
- File upload restrictions: type, size and where the files end up.
- Email notifications and owner alerts.
- Database access rules if the app stores visitor input.
Visitors can read and change browser code, so the important validation must run on the server. Bot protection works the same way. For example, you can add Cloudflare Turnstile to a form. But Cloudflare’s docs say that the client-side widget alone does not protect your forms. Your backend must send each token (the result from the widget) to the Siteverify API. A token is valid for five minutes and works only once.
5. Test it like a stranger
Sign out of the host. Open the site in a private browser window, on a phone and on a desktop. Then do these tests:
- Click every link and button. Open a URL that does not exist to test the 404 page.
- Open a CSS file, an image and a download by their direct URLs. On a gated site, each one must stop at the sign-in or password screen.
- Read every generated claim, number and quote. AI copy makes up details.
- Read the page title, the description and the preview text that appears when someone pastes the link into a chat.
On Cloudflare Pages, preview URLs send an X-Robots-Tag: noindex header (serving docs). To see it, run curl -I on a preview address. If you want the production site in search results, make sure that it has no leftover noindex tag.
6. Go public and watch the first days
When the review is done, change the gate on purpose. On Cloudflare Pages, remove the Access application from the production hostname. On Netlify, change the project visibility. On Vercel, change the protection scope.
Then turn on analytics. On Cloudflare Pages, open the project and go to Metrics. Select Enable under Web Analytics. Cloudflare adds the script on the next deployment.
Look for pages that nobody opens, links that return 404 and traffic that you did not expect. Fix problems in the source folder. Then deploy again to the same project, so that the URL stays the same.
Final checklist
Before you share the site, complete each item:
- Deploy only the build output.
- Scan for secrets and remove them.
- Remove private data, notes and debug files.
- Keep privileged keys out of browser code.
- Set the review gate on the host, and protect previews too.
- Make sure that the server validates forms, uploads and database actions.
- Test links, direct file URLs and the mobile layout while you are signed out.
- Make sure that generated claims and numbers are correct.
- At launch, change access on purpose.
- Turn on analytics, and save the source folder for the next update.
Free email addresses
for your AI agents
Each agent gets an address like myagent.x7k2@revdokumail.com. It can receive emails, send replies and store files.
- 3 free mailboxes, each with its own address
- 3,000 incoming and 500 sent emails a month
- 3 GB of storage for attachments and files
- Virus, malware, spam and prompt-injection filter
- Read and reply through API, MCP or CLI
You do not need a card.
Frequently Asked Questions
What should I do if an API key was already published?
First, revoke the key or rotate it (replace it with a new key) with the provider that issued it. Then remove the key from the code and deploy again. It is not enough to delete the file from the site. Copies can stay in caches, forks, downloads and the Git history. When the old key no longer works, those copies are harmless.
Related Articles

Add a Custom Domain to a Cloudflare Pages Site
Add a custom domain or www to a Cloudflare Pages site: set it up in Pages first, add the DNS record, fix stuck verification and redirect www.

What Is localhost:3000?
Your browser uses localhost:3000 to reach an app running on your own computer. Sending that address to someone else does not give them access to your app.

Move Exported Grok Website Files to Another Host
Export a Grok Build site to GitHub, deploy it on Cloudflare Pages, Netlify, Vercel or GitHub Pages, test it, then retire the grok.me copy.