Expert · Build, deploy and get hired · topic 62 of 64 · 35 min
Deploying your site
Explanation
Static hosting or a server?
Your build is static: HTML, CSS, JS and images that are the same for every visitor. A static host stores these files and sends them, often from a CDN (a network of servers in many cities, so a user in Chennai gets the files from a server nearby). A server, by contrast, runs code for each request; you need one for logins, databases and anything secret. A portfolio and most practice projects need only static hosting.
| Host | How it deploys | Good for |
|---|---|---|
| GitHub Pages | From a branch, or from a GitHub Actions workflow that builds your project | Portfolios and projects that already live on GitHub |
| Netlify | Connect a GitHub repo; it builds on every push | Static sites and SPAs, preview deploys, simple redirects |
| Vercel | Connect a GitHub repo; it builds on every push | Static sites, SPAs and React frameworks, preview deploys |
GitHub Pages
- Push your project to a GitHub repo (you learned Git and GitHub in the tools module).
- Open the repo Settings, then Pages.
- For plain HTML with no build step, choose "Deploy from a branch". For a Vite project, choose "GitHub Actions" and add a workflow that builds it.
- A project site lives at https://<username>.github.io/<repo>/, so set base: "/<repo>/" in vite.config.js.
- A repo named <username>.github.io becomes your user site at the root, and base stays "/".
# .github/workflows/deploy.yml (shortened)
name: Deploy to GitHub Pages
on:
push:
branches: [main]
permissions:
contents: read
pages: write
id-token: write
jobs:
deploy:
runs-on: ubuntu-latest
environment:
name: github-pages
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/*
- run: npm ci
- run: npm run build
- uses: actions/upload-pages-artifact@v3
with:
path: ./dist
- uses: actions/deploy-pages@v4Netlify and Vercel
Both work the same way: sign in with GitHub, import the repo, and check two settings. After that, every push to main updates the live site, and every pull request gets a preview deploy: a separate temporary site with its own link, so you (or a reviewer) can test the change before merging. Free plans exist for personal projects on GitHub Pages, Netlify and Vercel; limits and terms change, so check the current limits on the official site.
| Setting | Value for a Vite project |
|---|---|
| Build command | npm run build |
| Output (publish) directory | dist |
| Environment variables | Set VITE_ values in the dashboard (they are still public in the browser) |
| Node version | The same major version you use locally (node -v) |
Single-page app routing fallback
With React Router, a URL like /orders/42 has no real file; JavaScript draws that page. Clicking links inside the app works. But when a user refreshes or opens a shared link, the host looks for a file called orders/42, finds nothing and shows 404. The fix: tell the host to send index.html for every path that is not a real file, with status 200. Netlify and Vercel do this with a small file (below). GitHub Pages has no rewrite setting; common workarounds are copying index.html to 404.html after the build, or using hash URLs like /#/orders/42.
# Netlify: a file named _redirects in public/ (copied into dist)
/* /index.html 200
# Vercel: a file named vercel.json in the project root
{
"rewrites": [{ "source": "/(.*)", "destination": "/index.html" }]
}Custom domains, DNS and HTTPS
You can buy a domain such as ashaverma.in from a registrar (a company that sells domains, for a yearly fee). DNS is the phone book of the internet: it turns a name into an address. You add records at your registrar:
| Record | Points | Typical use |
|---|---|---|
| A | A name to an IP address (numbers) | The root domain ashaverma.in to the host |
| CNAME | A name to another name | www.ashaverma.in to your-site.netlify.app or asha.github.io |
| TXT | A name to some text | Proving to a host that you own the domain |
Copy the exact values from your host's documentation; do not guess. DNS changes can take from a few minutes to some hours to spread. GitHub Pages, Netlify and Vercel then give you an HTTPS certificate automatically, for free. On GitHub Pages, tick "Enforce HTTPS".
Rolling back
A bad deploy went live? Netlify and Vercel keep every old deploy: open the list of deploys, pick the last good one and publish (or promote) it. It takes seconds. Then fix the bug calmly in code and push. On GitHub Pages, git revert the bad commit and push; the workflow deploys the old code again.
Watch the lesson
Deploying your site · 1/8
Deploying means putting your built files on a host, so anyone can open them with a link.
Prefer a video by a teacher? Find free videos on “deploy vite react app github pages netlify vercel custom domain” on YouTube ↗
In real life: A bakery site with its own domain
Meena made a landing page for her aunt's bakery in Indore. She pushed it to GitHub, imported the repo on Netlify (build command npm run build, publish directory dist), and every push went live in about a minute. She bought a .in domain, added the CNAME record for www and the A record that Netlify showed, and HTTPS turned on by itself. Once, a broken menu image went live; she published the previous deploy, fixed the path in code and pushed again. Before every bigger change, she opens a pull request and sends the preview link to her aunt on WhatsApp.
Practice (0/3 done)
Act like a static host with a single-page-app fallback. Write a function serveFile(path, files): files is a list of file names in dist without a leading slash (like "index.html" or "assets/app-1a2b.js"). Remove the leading "/" from path. If the result is one of the files, return it; otherwise return "index.html". serveFile("/assets/app-1a2b.js", files) returns "assets/app-1a2b.js", serveFile("/orders/42", files) returns "index.html", and serveFile("/", files) returns "index.html".
Write a function rollbackTarget(deploys, currentId) for a rollback button. deploys is a list ordered newest first; each item is { id, status } where status is "ready" or "failed". Return the id of the first "ready" deploy that is OLDER than the current one (comes after it in the list). If there is none, or currentId is not in the list, return null. Example: for d5 (ready), d4 (failed), d3 (ready), rollbackTarget(list, "d5") returns "d3".
Deploy one of your projects twice: once on GitHub Pages with a GitHub Actions workflow, and once on Netlify or Vercel connected to the same repo. Then practise the everyday flow: open a pull request, check its preview, merge it, and try a rollback.
Quick quiz
Read more (free)
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.