# Vercel tutorial: deploy a web app from Git or the CLI

> Learn how to deploy a web app to Vercel, use preview and production deployments, add environment variables, Functions, domains, logs, and rollbacks.

Author: [Flavio Copes](https://flaviocopes.com/about/) | Published: 2026-09-16 | Updated: 2026-08-21 | Topics: [Services](https://flaviocopes.com/tags/services/) | Canonical: https://flaviocopes.com/vercel/

[Vercel](https://vercel.com) turns a Git repository into a live web application.

Connect a repository, and Vercel builds the project on every push. You get a production site, a preview for each branch, HTTPS, a CDN, and server-side Functions without managing a server.

Vercel works with [Next.js](https://flaviocopes.com/nextjs/), [Astro](https://flaviocopes.com/astro/), SvelteKit, Nuxt, Vite, and many other frameworks. It can also deploy a plain HTML site.

In this tutorial we'll deploy an Astro site. The Vercel parts are almost identical with another framework.

## Projects and deployments

Before we deploy anything, I want to clarify two words.

A **project** is the permanent home of an application in Vercel. It holds the Git connection, domains, environment variables, and settings.

A **deployment** is one built version of that project. Every push creates a new deployment with its own URL.

The project stays. Deployments accumulate inside it.

Vercel has three default environments:

- **Local** is the app on your computer
- **Preview** is a deployment you can test before release
- **Production** is the version your users see

This separation is one of the best parts of Vercel. You can test a real deployment without touching production.

## Create an Astro project

If you already have an application, skip this section.

Create a small Astro site:

```bash
npm create astro@latest vercel-demo
```

Choose the minimal template and install the dependencies.

Then open the new directory:

```bash
cd vercel-demo
npm run dev
```

Astro prints the local URL. Open it in the browser and make sure the site works.

Always run the production build before the first deployment:

```bash
npm run build
```

This catches missing files and build-only errors on your computer.

## Deploy from Git

The usual Vercel workflow starts with GitHub, GitLab, or Bitbucket.

Push the project to a Git repository. Then:

1. Sign in to [Vercel](https://vercel.com)
2. Click **New Project**
3. Import the repository
4. Check the detected framework and build settings
5. Click **Deploy**

Vercel detects Astro and builds the site without extra configuration.

When the build finishes, you get a URL ending in `.vercel.app`. This is already a production deployment.

Now change some text and push it to a new Git branch. Vercel creates a **preview deployment** with a different URL.

Push or merge the change into the production branch, usually `main`, and Vercel creates a new production deployment.

The flow looks like this:

```text
feature branch push -> preview deployment
production branch push -> production deployment
```

Each deployment is immutable. A new push creates a new one instead of editing the old deployment.

This makes previews and rollbacks possible.

## Deploy with the Vercel CLI

You can also deploy any local directory from the terminal.

Install the [Vercel CLI](https://vercel.com/docs/cli):

```bash
npm install -g vercel
```

Log in:

```bash
vercel login
```

The current login flow opens a device authorization page in your browser.

Now run this from the project directory:

```bash
vercel
```

The first run asks which account to use and whether you want to link an existing project. Choose to create a project if this is the first deployment.

The `vercel` command creates a preview deployment.

When you are ready to publish it to production, run:

```bash
vercel --prod
```

My advice is to connect Git for normal work. Use the CLI for experiments, automation, and deployments from repositories Vercel cannot connect to directly.

## Understand the build settings

Vercel normally detects these values from your framework:

- the install command
- the development command
- the build command
- the output directory

For an Astro site, the build command is `npm run build` and the output directory is `dist`.

You can change these values under **Project Settings → Build and Deployment**.

Do this only when your project needs it. The detected defaults are usually correct.

If your app lives inside a monorepo, set its **Root Directory**. For example, an app inside `apps/site` must build from that directory instead of the repository root.

## Add environment variables

API keys and database credentials must not live in Git.

Open **Project Settings → Environment Variables** and add a value such as:

```text
NEWSLETTER_API_KEY=your-secret-key
```

Choose where the variable is available:

- Development
- Preview
- Production

Preview and production often need different values. A test database should not point at production by accident.

An environment variable change only affects new deployments. Redeploy the app after changing one.

You can also manage variables with the CLI:

```bash
vercel env add NEWSLETTER_API_KEY production
```

Pull the Development variables into a local file:

```bash
vercel env pull .env.local
```

Add `.env.local` to `.gitignore`.

Remember that variables exposed to browser code are public. Frameworks use prefixes such as `PUBLIC_` or `NEXT_PUBLIC_` for those values.

Never expose a secret with one of those prefixes.

## Add a Vercel Function

A static site cannot safely call a private API with a secret key. That code must run on the server.

Vercel can turn files inside the root `api` directory into [Vercel Functions](https://vercel.com/docs/functions).

Create `api/hello.ts`:

```ts
export default {
  async fetch(request: Request) {
    const url = new URL(request.url)
    const name = url.searchParams.get('name') || 'World'

    return Response.json({ message: `Hello ${name}!` })
  },
}
```

Deploy the project, then open:

```text
https://your-project.vercel.app/api/hello?name=Flavio
```

The response is:

```json
{
  "message": "Hello Flavio!"
}
```

The function only runs when a request reaches it. Vercel handles the server, scaling, and HTTPS.

Frameworks such as Next.js have their own route conventions. Use the framework-native approach when one exists.

To test Vercel-specific Functions and routing locally, run:

```bash
vercel dev
```

If your framework's normal development command already supports everything you use, keep using that command.

## Add a custom domain

Every project gets a `.vercel.app` address. You can [attach your own domain](https://vercel.com/docs/domains/set-up-custom-domain) from **Project Settings → Domains**.

Enter the domain, and Vercel shows the exact DNS records to add.

If Vercel manages your DNS, it can create the records for you. If Cloudflare or another provider manages it, copy the records into that provider's dashboard.

You can also inspect the required records with the CLI:

```bash
vercel domains add myapp.com my-project
vercel domains inspect myapp.com
```

Run `inspect` again after changing DNS. Vercel automatically provisions the TLS certificate after verification.

If you use both `myapp.com` and `www.myapp.com`, redirect one to the other. This gives the site one canonical address.

## Read build and runtime logs

There are two logs you'll use most often.

**Build logs** show dependency installation and the build command. Open them when a deployment fails.

**Runtime logs** show Vercel Function requests and `console.log()` output. Open them when the build succeeded but an API route fails.

You can inspect a deployment from the terminal:

```bash
vercel inspect https://your-deployment.vercel.app
```

Add `--logs` to print its build logs:

```bash
vercel inspect https://your-deployment.vercel.app --logs
```

For production runtime errors, use:

```bash
vercel logs --environment production --status-code 5xx --since 30m
```

Start with the first real error. Later failures are often just consequences of it.

## Roll back a broken deployment

Because old deployments still exist, Vercel can point production back to one of them without rebuilding.

To [return to the previous production deployment](https://vercel.com/docs/cli/rollback):

```bash
vercel rollback
```

Check its status:

```bash
vercel rollback status
```

On the Hobby plan, you can roll back to the previous production deployment. Pro and Enterprise projects can select older eligible deployments.

After a rollback, fix the bug and deploy again. Do not treat the rollback as the fix.

Notice that a rollback restores old built code. It does not roll back your database or an external API.

## Do you need a `vercel.json` file?

Usually, no.

Framework detection covers the normal build and routing setup. Add `vercel.json` only when you need platform-specific configuration such as redirects, headers, rewrites, or Function settings.

For example, this redirects an old path:

```json
{
  "redirects": [
    {
      "source": "/old-page",
      "destination": "/new-page",
      "permanent": true
    }
  ]
}
```

Keep platform configuration small. Prefer your framework's configuration when it provides the same feature.

## A practical deployment checklist

Before sending a Vercel project to real users, check these items:

1. Run the production build locally
2. Confirm Preview and Production use the right environment variables
3. Test server-side routes on a preview deployment
4. Add a custom domain and verify its redirect
5. Check build and runtime logs
6. Know how to run `vercel rollback`
7. Review the current limits and pricing for your plan

That is the core Vercel workflow.

Connect Git for automatic deployments. Use previews to test changes. Promote only working code to production, and keep the previous deployment ready if something goes wrong.
