A site rarely looks cheap because of the design. It looks cheap because of the states nobody designed.
A mockup shows one version of a page: content loaded, images in place, nothing failing. Production shows you the other versions. Text that arrives before the image and shoves the layout down. An empty list with no explanation of why it's empty. A form that rejects your input without saying which field. A button you press twice because nothing acknowledged the first press. Each of those is a small moment where the visitor stops trusting the thing, and trust is what people are reading when they say "this looks cheap."
The mechanics are simple. Every screen that loads data has at least four states: loading, empty, error, and loaded. Most projects only build the fourth one, because it's the only one sitting in the design file. The rest get improvised by whoever is implementing the page that afternoon. That's also why cheapness shows up unevenly. One page feels solid, the next one feels like a different company made it.
So we review those states explicitly: what does this page look like with no data, with slow data, with failed data, with text twice as long as the design assumed. It costs an hour per screen, and it's the difference between a site that feels built and a site that feels assembled.
If you're looking at your own site right now, try it on a bad connection and submit a form wrong on purpose. That's probably the version your visitors see more often than you'd think.