You paid someone to build the app. It works. Then you open it on your phone one evening and the login screen looks like three other login screens you have seen this month: the same rounded card, the same soft gradient behind it, the same encouraging line under the heading. The thought arrives on its own. Was this vibe coded, and would you be able to tell?

Most of what gets written about how you can tell if an app is vibe-coded answers with taste. Purple gradients, emoji used as icons, a card around every paragraph. Taste is a real signal and it is also the cheapest thing in an app to repaint, so a confident designer defeats every item on that kind of list in an afternoon. The tells worth knowing are the ones a builder leaves behind because its own documentation says it leaves them behind.

The address bar, the sign-up email and the addresses the app’s requests go to usually name the builder that made it. Six vendors document those defaults on their own pages. None of them tells you whether anyone ever checked what the app does.

Every domain, file name, response header and email address on this page was read out of the vendor’s own documentation on 25 August 2026 and is written here the way that documentation writes it. No app was opened, nothing was run against a live site, and where a vendor does not publish the detail, this page records the absence rather than guessing at it.

The address bar, the sign-up email and the page title

Builder or hostDefault published addressBrowser tab on an unedited buildWhere the sign-up email comes fromWhat its own responses give awayWhat the repository holds
Lovable[url-subdomain].lovable.app, and the docs say the project URL cannot be removedNot on the pages readNot on the pages readNot on the pages readPrivate repositories by default on every plan, commits authored by lovable-dev[bot], a lovable-fallback branch after a deletion
Base44myapp.base44.app, given to every app at creationNot on the pages readNot on the pages readNot on the pages readNo page describing a repository layout for exported code
BoltA random bolt.host name, created at first publishNot on the page readNot on the page readNot on the page readNot on the page read
Replit<your-live-app-subdomain-name>.replit.appNot on the pages readNot on the pages readNot on the pages read.replit and replit.nix, both hidden in the filetree until you show hidden files
Vercel<project-name>-<unique-hash>-<scope-slug>.vercel.app for a commit, plus a branch form and a CLI formNot on the pages readNot on the pages readserver: Vercel, x-vercel-id and x-vercel-cache on deployment responsesNot on the pages read
Netlify[name-of-your-site].netlify.appNot on the page readNot on the page readNot on the page readNot on the page read

Every cell above was read on 25 August 2026 from the vendor page cited for it in this section and the next one, and a cell that says “not on the pages read” means exactly that: the vendor documents plenty, and this particular detail was not on the page in question that day. Signs an app was built with AI usually get sold as a list of visual habits, and the six rows above are the documented kind instead. Four of the six vendors publish nothing about what an unedited build puts in the browser tab or where its email comes from, which is why those two tells are sourced further down from the template and the email service rather than from the builder.

Start with the address, because it costs nothing to look at. Lovable’s deploy documentation says that “By default, your app is published to [url-subdomain].lovable.app, using your project’s URL subdomain.” The same page says share previews are the only links with an expiry, seven days by default, so a lovable.app address that someone sent months ago and still loads is a published app rather than a preview of one. Its custom-domain page is blunter than most vendors get: it says there is currently “no way to remove” a project’s xxx.lovable.app URL. A Lovable app can wear your domain and still answer at the one it was born with.

The rest follow the same shape. Base44’s custom-domain page opens by saying that “Every Base44 app is live on a free built-in URL (myapp.base44.app) from the moment you create it”, and says it again further down, under its heading on changing the app URL, as a free built-in domain you can personalize anytime. Bolt’s publish page says that “The first time you publish your site, Bolt automatically creates a random bolt.host URL name for you.” Replit’s custom-domains page writes the deployment address as <your-live-app-subdomain-name>.replit.app. Netlify’s domains glossary defines a Netlify subdomain as “the default domain with the form [name-of-your-site].netlify.app given to each site”.

Vercel is the one worth reading slowly, because its addresses carry more than a name. Vercel’s generated-URLs page documents three shapes: <project-name>-<unique-hash>-<scope-slug>.vercel.app for a specific commit, <project-name>-git-<branch-name>-<scope-slug>.vercel.app for a branch, and <project-name>-<scope-slug>.vercel.app from the command line. The middle one prints the git branch name in public. If the address you were sent has -git- in it and a branch name you recognise, you are looking at a preview of somebody’s work in progress, not the app your customers use. The same page documents a fourth shape for a deployment made on a team, <project-name>-<author-name>-<scope-slug>.vercel.app, which names the member who deployed it.

Now the page title, which is the tell people miss because it sits in the browser tab where nobody looks. Apps scaffolded from the React template that ships with Vite start life with a fixed title: the create-vite React template has <title>Vite + React</title> in its index.html. Changing it is a one-line edit that a person writing the app by hand does in the first ten minutes, because they are staring at the tab all day. An agent asked for features has no reason to touch it. A live app titled Vite + React in the browser tab is not proof of anything on its own, and it is a strong hint that nobody has been through the file that title lives in.

Official Vite React template source with the default Vite + React browser title highlighted on line 7

Next.js apps leave a different kind of trace, and the honest version is narrower than the one usually repeated. The not-found reference, read at version 16.3.4 with a last-updated date of 10 July 2026, says the framework “automatically injects <meta name="robots" content="noindex" /> for pages that return a 404 status code”, and that a route-level not-found file returns a 200 status for streamed responses and 404 for non-streamed ones. What that page does not print anywhere is the wording of the default not-found screen, so this page will not tell you what text to look for. The checkable facts are the injected robots tag and the status-code behaviour.

The sign-up email is the third free tell, and it has to be described as behaviour rather than as an address. Supabase’s custom SMTP guide says the default authentication email service is “not meant for production use”, puts its current limit at two messages an hour, states that Supabase Auth “will refuse to deliver messages to addresses that are not part of the project’s team”, and adds that “We urge all customers to set up custom SMTP server for all other use cases”. As of 25 August 2026 that guide does not print the address those default messages arrive from, so there is no domain here for a reader to match. What the reader can recognise is the behaviour: sign-up emails that reach the owner and nobody else, or that dry up after two in an hour. That is what an unconfigured default looks like from outside.

Where an app does send real email, one address does the identifying. Resend’s Node.js quickstart uses 'Acme <onboarding@resend.dev>' as the from address in its example and tells readers plainly not to use onboarding@resend.dev as the from address in production code, because it is a test-only address. A welcome email that arrives from the sample address in the quickstart means the code went to production with the tutorial value still in it.

One more absence belongs here, because its opposite gets asserted a lot. None of the vendor pages read for this article, which is every Lovable, Base44, Bolt, Replit, Vercel and Netlify page linked above, documents a meta name="generator" tag on published apps. That is a statement about eight pages read on one day, not a claim that no builder emits one.

There is a reason the taste-based lists exist, and owners feel it themselves. One owner of a Replit app, whose functions all worked the way they were meant to, still wrote this about how the thing looked:

”… the UI/UX still feels generic and a bit AI-generated.”

That is a real signal about a real app. It is also unfalsifiable, which is the whole problem with starting there. The tells below can be checked by anyone, including someone who disagrees with you about gradients.

The network tab, the repository and the response headers

Every browser has a network tab that lists the addresses a page talks to while it loads. That is the only thing you need to know about the mechanics here, because the addresses themselves are the interesting part, and they are documented.

Supabase writes its REST endpoint as https://<project_ref>.supabase.co/rest/v1/ in its API guide, and its Edge Functions land at https://[YOUR_PROJECT_ID].supabase.co/functions/v1/hello-world according to the functions quickstart. The project reference in front of .supabase.co is unique to one project, so those requests do not just say Supabase, they say which Supabase. The same two values appear in the code that starts the client: the initialization reference shows createClient('https://xyzcompany.supabase.co', 'your-publishable-key'), a project URL and a key, both of which the browser has to know. Seeing them is normal and expected. Whether the project URL and key you can see in those requests are a problem depends on which key it is, and that question has its own answer.

Firebase is just as legible. Firebase’s REST API guide states that “All REST API endpoints exist under the base URL https://firestore.googleapis.com/v1/”, with document paths in the form /projects/YOUR_PROJECT_ID/databases/(default)/documents/cities/LA. Requests to firestore.googleapis.com mean Firestore, and the project id sits in the path.

The response headers name the host without any of the app’s own code being involved. Vercel’s response-headers reference documents server: Vercel, which “Shows where the request came from” and which the page notes “can be overridden by other proxies (e.g., Cloudflare)”. It documents x-vercel-id, which carries the list of Vercel regions a request hit and the region the function ran in, and x-vercel-cache, which returns one of HIT, MISS, STALE, PRERENDER, REVALIDATED or BYPASS. The same page says these headers “can be viewed from the Browser’s Dev Tools or using an HTTP client such as curl -I <DEPLOYMENT_URL>”. This is the sturdiest tell on the page, because an owner who cannot read code cannot remove it. It belongs to the host.

Then the repository, if you have access to one. Replit apps carry two files that exist nowhere else: Replit’s workspace configuration page says “The .replit file controls your Replit App’s behavior. It uses the toml configuration format”, and describes replit.nix as the place system packages are listed in a deps array prefixed with pkgs.. The same page notes that both files are hidden by default and appear only when you choose to show hidden files in the filetree, which is why people who have looked in a Replit repository sometimes swear they were not there.

Lovable signs its own work. Lovable’s git integration page says commits it makes are “authored by the Lovable GitHub app identity: lovable-dev[bot]” on github.com and GitHub Enterprise Cloud, and are co-attributed to the user who triggered them using GitHub’s noreply email format. It syncs the repository’s default branch, “usually main”, and if a synced branch is deleted on GitHub it moves the project to a branch called lovable-fallback. A commit history that alternates between a bot author and one human name is a record of who was driving.

The same page carries the fact that stops people over-reading a silence: “Repositories created by Lovable are private by default, on every plan.” So being told there is no repository to look at says nothing about how the app was built. That is the default setting on every plan, and a private repository is what most owners of a working Lovable app have.

Base44 is the gap in this section, stated as a gap. Its documentation home read on 25 August 2026 lists a developer platform, a backend service and a CLI reference, and links no page describing what an exported Base44 codebase contains, so there is no documented file name to look for the way there is with Replit.

What is my app built with?

The app’s own address, its network requests and its repository files answer that question for most AI-built apps. builtwith.com and Wappalyzer read the front end of a public page and name libraries, frameworks and analytics. Neither one names the agent that typed the code, and neither sees what runs on the server.

Two different people ask this question and they need different halves of the answer. The owner asking what their own app is built with usually has more access than they realise: the builder’s dashboard, the hosting account, the email service, the invoices. The fastest honest route for an owner runs through the monthly charges, because every service named in this article bills somebody, and a card statement names the stack in plain English before any lookup tool does.

The person looking at somebody else’s app has only the outside, which is where the address, the headers and the requests do their work. That is also where the third-party tools stop being much use. They are good at the layer they read, which is the public front end of a public web page, and they cannot tell you which builder’s agent produced the components, whether a human rewrote them afterwards, or what the server does with a request once it arrives.

The related question people type is who made the app rather than what made it, and it deserves a straight answer: nothing above names a person. An app store listing names the account something was published under. A domain record names a registrant, when a privacy service is not standing in for one. Neither is a record of who wrote the code. The closest thing to a name in any of the documentation read here is Lovable’s co-attribution of bot commits to the account that triggered them, and that is visible only to someone who can already see a repository that is private by default.

What none of this tells you

You can finish every tell on this page, come out certain the app was built on Lovable and deployed to Vercel, and still know nothing about whether it works under a second user. Across the fixed study of 26 AI-built applications AxonBuild audited in June and July 2026, 22 came out red, 4 amber and none green, and what 26 audited AI-built apps actually contained sets out the bands and the method behind them. Those 26 apps averaged 52.1 out of 100, the lowest scoring 29 and the highest 81, and that top scorer was a thin dashboard whose only findings were unfinished work.

Every ranked list of vibe coding tells eventually arrives at exposed keys. The audits put that near the bottom. Secrets and credentials was the strongest pillar across the 21 third-party apps in that study, averaging 84 out of 100, while reliability was the weakest at 31 out of 100. Six of those 21 apps did ship a real secret, and three of the six had it permanently in git history, which is the kind of finding that stays expensive. Rare and severe is a different thing from common, and a list ordered by drama gets that backwards.

The pattern that actually recurs is quieter and harder to see from outside. Controls that were built but never wired up turn up again and again across the study: rate-limit buckets never attached to anything, error boundaries never mounted, a safety rulebook that no running code reads. The code exists. It is in the repository, it reviews well, and it never executes.

The tells name what got built. The audits keep finding things that got built and never ran.

The tells sort the same way, by how easily each one disappears.

TellWhat makes it disappear
The look of the interfaceAny designer with an afternoon, or the next prompt
The Vite + React browser tabOne line in index.html
The default published addressPointing a custom domain at the app, though Lovable’s docs say its own project URL stays
The sign-up email addressConfiguring a real mail service, which is a step the docs tell people to take anyway
The requests to a backend hostBy moving off that backend, or by putting your own domain or a proxy in front of it so the browser talks to your address instead
The host’s response headersRarely by the owner, because the host sets them, though a proxy such as Cloudflare in front of the host can overwrite them

The erasable end of that list is all taste and the durable end is all infrastructure, which is a warning about how much the whole exercise is worth. The app most likely to defeat every tell here is one somebody cared enough about to polish, and polish is a fact about the surface. None of these tells is a test, and the twenty minutes of browser work that actually tests something is written out step by step elsewhere.

Who ships a vibe-coded app on purpose

Plenty of people know exactly what their app is and ship it anyway, with their eyes open. One owner wrote this about a workflow they built for their own small business:

”… It might be vibe coded slop, but it’s just an internal tool and it works perfectly.”

They are right, and the reasoning is the part worth copying. An internal tool used by four people who all know each other, holding nothing a stranger wants, has a blast radius the size of one team’s afternoon. The same code with a payment form and a customer list attached is a different object with the same source. Being AI-built is a fact about how the thing was made. Whether anything checks what it does is a fact about what it will do next, and only the second one has a price attached.

The fear this page’s readers are actually carrying is a social one. A thread on r/website in August 2026 was titled “Do you trust AI-looking websites?”, and that title is closer to the real question than any of the tells are. People searching for how to spot a vibe coded website are usually asking what their own customers will think once they can see it. One founder listed the look of the interface, alongside quality and trial length, as a reason people did not stay. That is a real cost, and it is a marketing cost, payable in signups. A rate limiter that was written and never attached sends a different kind of bill.

So the answer to “was this vibe coded” is worth having, and it is worth about as much as knowing which contractor poured a foundation. It names the method. It does not inspect the concrete.

What to do with the answer

Three routes lead out of here, and which one you take depends on what you were worried about when you started looking.

If the worry is whether the app holds up, the work is a short sequence anyone can run in a browser on their own app, with no code involved and nothing installed. If the worry is the person you hired, the next move is a conversation. Knowing which builder made it does not tell you what to say to the person you paid, and the questions that separate a straight answer from a stalling one are a conversation of their own. The separate question of whether it matters that the person you paid used AI at all has its own answer.

If what is behind the question is customer data or card payments, then the security question, which is a different one, is worth reading on its own terms rather than inferred from an address bar. And if the app already works and your worry is that it will stop working the next time somebody prompts it, building a test that proves the thing keeps working is the durable version of everything on this page.

Common questions about spotting a vibe-coded app

How can I find out who developed an app?

You usually cannot, from the outside. An app store listing names the account that published the app, and a domain record names whoever registered the address unless a privacy service stands in for them, and neither of those is a record of who wrote the code. The tells on this page name a builder and a host, which is a different fact: lovable.app, bolt.host or x-vercel-id tell you what the app was made with, not whose hands were on it.

Does a lovable.app or vercel.app address prove an app was vibe-coded?

No. It proves which platform serves the app. Vercel hosts a large number of applications written entirely by hand, and a lovable.app address means the project was created in Lovable without saying how much of the code a human later rewrote. Read a default address as evidence of the tooling, then look at the repository and the requests for how much of the original scaffolding is still in place.

Can you tell an app was built with AI just by looking at it?

Sometimes, and never reliably. The visual signs people list, meaning generic layouts, decorative gradients, emoji standing in for icons, are real patterns and they are the cheapest thing in the app to change. Any owner who hires a designer defeats all of them while changing nothing underneath. Looking is where most advice on how to spot a vibe coded app stops, and it is the weakest evidence available.

Is there a tool that detects AI-generated code?

Tools that read the code itself and estimate whether a machine wrote it do exist, and they answer a narrower question than this page does: whether the text was generated, not what the running app is made of. That distinction matters more than it sounds, because a codebase can be entirely hand-typed and still have no tests, no rate limits and no error handling, which is the failure this page’s readers are usually worried about.

Does it matter if my app was built with AI?

Not by itself. Across the fixed study of 26 AI-built applications audited in June and July 2026, the band an app landed in tracked what the code did rather than which tool typed it, and 22 of the 26 came out red. What matters is whether anybody has checked the parts a demo never touches: a second user’s data, a failed payment, a request that arrives ten thousand times in a minute.

What does it mean if my sign-up emails come from an address I do not recognise?

It usually means the email service is still on its factory settings. Resend’s quickstart uses onboarding@resend.dev and tells developers not to ship that address to production, so seeing it on a real welcome email means that instruction was missed. Supabase’s default authentication mail is capped at two messages an hour and refuses to deliver to anyone outside the project team, so an app that only emails its owner has never had a real mail service connected.

Can I tell what my app is built with without asking the developer?

Yes, in most cases. The published address names the builder or the host, the requests the app makes name the database and the mail service, and the response headers name the platform serving it. builtwith.com and Wappalyzer will add the front-end libraries on a public page. What none of that reaches is server-side code, so treat the result as an inventory of services rather than a full picture.

Does moving to a custom domain hide what the app was built with?

Partly, and less than owners expect. A custom domain removes the most visible tell, and the requests the app makes to its backend host and the headers its platform returns are untouched by the change. Lovable’s custom-domain documentation goes further and says the default project URL cannot be removed at all, so on that platform the original address remains alongside the new one.

Is being vibe-coded a reason to rebuild the app?

No. A rebuild is justified by what the app fails to do, not by how the first version was typed, and most of the findings in the 26-app study were repairs rather than reasons to start again. Reading the code and judging it is a job for a person, and it is a real job even when you cannot read a line of it yourself. That judgement is what decides between repairing and rebuilding.