# Deploy

> Host the site on Cloudflare Pages, Netlify, Docker or Node, set the right environment values and connect your domain.

## Choose a render mode

Set `RENDER_MODE` in `.env`. The default suits most sites.

| Mode | Pages are built | Hosting | When |
| --- | --- | --- | --- |
| static (default) | at build time | Cloudflare Pages, Netlify, nginx | most sites |
| hybrid | at build time, plus server endpoints | Node.js | the site needs its own server endpoints, such as a contact form |
| server | on each request | Node.js behind a CDN | thousands of pages, or content that must update within minutes |

The page code is the same in every mode. The template's `README.md` says if it needs a server.

## Build locally first

```bash
pnpm build
```

This needs your Sanity settings from [Connect Sanity](https://templates.artizanteknoloji.com/en/docs/connect-sanity). If it passes on your computer, the host will build the same output.

## Static: Cloudflare Pages or Netlify

Connect your private repository to the host and use these build settings:

| Setting | Value |
| --- | --- |
| Build command | pnpm build |
| Output directory | dist/client |
| Node.js version | 22 |

Add the build environment values. Copy them from your `.env`:

```bash
PUBLIC_SITE_URL=https://example.com
PUBLIC_SANITY_PROJECT_ID=abc12345
PUBLIC_SANITY_DATASET=production
PUBLIC_SANITY_API_VERSION=2026-08-01
```

The build writes the host's redirect and header files (`_redirects`, `_headers`) for you, so don't edit them by hand.

## Static: Docker (nginx)

```bash
docker build -f Dockerfile.static \
  --build-arg PUBLIC_SITE_URL=https://example.com \
  --build-arg PUBLIC_SANITY_PROJECT_ID=abc12345 \
  -t my-site .
docker run -p 8080:8080 my-site
```

The image runs nginx without root privileges on port 8080. Its health check is `/api/health`.

## Hybrid or server: Docker (Node.js)

```bash
docker build -f Dockerfile.node \
  --build-arg RENDER_MODE=hybrid \
  --build-arg PUBLIC_SITE_URL=https://example.com \
  --build-arg PUBLIC_SANITY_PROJECT_ID=abc12345 \
  -t my-site .
docker run -p 3000:3000 my-site
```

The server listens on port 3000 and its health check is `/api/health`. Give the container a stop grace period of at least 10 seconds so requests in progress can finish during a deploy.

Without Docker, build and start it directly:

```bash
pnpm build
HOST=0.0.0.0 pnpm start
```

## Values that are fixed at build time

`RENDER_MODE` and every value that starts with `PUBLIC_` are built into the site. On platforms that separate build and runtime settings, add them as **build** values. If you only set them at runtime, the build silently uses the defaults. After changing one, rebuild.

## Publish and rebuild

A static site shows new content after it is rebuilt. To rebuild on every publish:

1. Create a deploy hook in your host (Cloudflare Pages and Netlify both provide one) and copy its URL.
2. In [sanity.io/manage](https://www.sanity.io/manage), open your project → **API** → **Webhooks** and add a webhook:
  - **URL:** the deploy hook
  - **Trigger on:** create, update, delete
  - **Drafts:** off
  - **Projection:** `{_id, _type}`

For `hybrid` and `server`, point the webhook at `https://example.com/api/revalidate` instead and set its secret to the `SANITY_WEBHOOK_SECRET` from your `.env`. In `hybrid`, also set `DEPLOY_HOOK_URL` on the server so a publish triggers a rebuild. The comments in `.env.example` list the values for each host.

## Connect your domain

1. Add the domain in your host's settings and follow its DNS instructions.
2. Set `PUBLIC_SITE_URL` to the domain, with `https://`, and rebuild.
3. Let Sanity accept requests from the domain:

```bash
pnpm sanity:setup --project abc12345 --site-url https://example.com
```

## Contact forms on a static site

A static site has no server endpoint of its own. If your template includes a contact form, its `README.md` and `.env.example` show the options: send the form to an external form service, or switch to `RENDER_MODE=hybrid`.

---

https://templates.artizanteknoloji.com/en/docs/deploy
