Quick Answer

Static sites go on a static host and take minutes. Anything with a backend needs a host that runs a process, plus a separate managed database. The first deployment usually fails on hardcoded localhost URLs, missing environment variables, or a port your code chose instead of reading from the environment.

Why a live link matters more than you think

Put yourself on the other side. Someone is looking at forty applications. Your resume says you built a booking system. Their options are to clone your repository, install the dependencies, set up a database and run it — or to click a link.

Nobody does the first one. A live URL is the difference between a claim and a demonstration, and it is usually one afternoon of work on a project you have already finished.

There is a second reason, which matters more in the long run. Deployment is where you discover that your code assumed things about its environment — a database on your own machine, a port that happened to be free, a file path with your username in it. Every one of those is a real lesson, and none of them appear while you develop locally.

Three kinds of project, three kinds of hosting

What you need depends entirely on what your project is, and beginners often reach for far more than they need.

  • Static site — HTML, CSS and JavaScript with no server code. This includes most portfolio sites, and React or Vue apps that only call external APIs. These deploy free, quickly, and permanently on static hosts such as GitHub Pages, Netlify or Cloudflare Pages. Usually you connect the repository and it deploys on every push.
  • Backend application — anything with Node, Django, Flask or Spring running server-side. This needs a host that keeps a process alive. Free tiers exist, generally with the catch that the app sleeps when idle and takes a few seconds to wake.
  • Database — usually a separate managed service rather than something you install on the app host. Free tiers are common for Postgres and MongoDB at small sizes.

Providers and their free-tier limits change frequently, so check the current terms rather than trusting any tutorial, including this one. The categories above are stable; the specific offers are not.

Three things to fix before you deploy

Almost every first deployment fails for one of these, and all three are quicker to fix beforehand.

1. Hardcoded localhost URLs. Your frontend calls http://localhost:5000/api, which means "this machine" — so in the browser it points at the visitor's computer, where nothing is running. Read the base URL from configuration instead, with localhost only as the development default.

2. The port. Hosts tell your app which port to listen on through an environment variable. An app that insists on 3000 will not receive traffic:

const PORT = process.env.PORT || 3000;
app.listen(PORT);

3. Secrets in the repository. Database passwords and API keys must come from environment variables set in the host's dashboard, never from a committed file. If you have already committed one, treat it as compromised and rotate it — deleting it in a later commit leaves it readable in history. See what recruiters look at on your GitHub for how to check.

What breaks on the first deploy, and how to read it

The build succeeds and the site returns an error. This is normal. The skill is knowing where to look.

  • Blank page, console shows 404 on assets. Usually a path assumption — the app expects to be at the domain root and is served from a subfolder, or the other way round.
  • "Application failed to respond". Almost always the port problem above.
  • Works, but the API calls fail with CORS errors. Your backend needs to allow requests from the deployed frontend's domain, which is not the same as localhost.
  • Database connection refused. The connection string still points at your machine, or the database requires SSL in production and your client is not using it.
  • Slow first load, then fine. The free tier put your app to sleep. Expected behaviour, not a bug — but worth mentioning if you demo it live.

Read the deploy logs. Every host shows them, they usually name the problem in plain language, and beginners consistently guess instead of reading them.

Making it presentable

Once it is live, a few minutes of polish changes how it reads:

  • Put the live URL at the top of the repository README, and in the GitHub "About" panel.
  • Seed some realistic demo data. An empty app looks broken, and a reviewer will not sign up to see it work.
  • If it needs login, provide demo credentials in the README. A login wall with no way through is the same as no link at all.
  • Check it on a phone. Most people who click your link will be on one.

That last point catches out a lot of projects that look fine on a laptop and are unusable on a 360-pixel-wide screen.

Frequently Asked Questions

Do I need to buy a domain? No. Free hosts give you a subdomain that works perfectly well for a portfolio project. A custom domain is a small nice-to-have, not a requirement, and it is the last thing to spend money on.
Why does my app work locally but not after deploying? Most often a hardcoded localhost URL, a port that is not read from the environment, or a missing environment variable. The deploy logs will usually tell you which — read them before changing code.
Is a free tier good enough for a portfolio project? Yes. The usual limitation is that the app sleeps when idle and takes a few seconds to wake. That is acceptable for something a recruiter opens once, and it does not affect how the project reads.
Should I use Docker for a student project? Only if you want to learn Docker, which is a reasonable goal in itself. It is not required to deploy, and adding it before you understand the basic deployment usually creates a second problem to debug alongside the first.
How do I keep my database credentials safe? Set them as environment variables in the host's dashboard and read them in code. Never commit them. Add the config file to .gitignore from the start, because removing a secret later does not remove it from git history.