# PURE — How to deploy to live (acquisto.biz)

**TL;DR: there is no build step and no manual deploy. You deploy by `git push`.**
Push to the branch Netlify watches → Netlify publishes the repo as-is → acquisto.biz updates in ~1–2 min.

This file is the single source of truth for "how do I get my change live." It was reconstructed
2026-06-24 and **verified against the live Netlify API** (site `acquisto`, see below). If anything here
stops matching reality, fix THIS file in the same PR.

---

## The one fact that matters

| | value |
|---|---|
| Host | **Netlify** (static hosting) |
| Netlify site name | **`acquisto`** |
| Netlify site id | `245e35a8-a530-4d31-84c3-d0e94904380d` |
| Production URL | **https://acquisto.biz** |
| Connected repo | **`github.com/puremlstech/puremls`** |
| **Production branch** | **`Testin.MikeSupabase`** ← deploy = push here |
| Build command | none (`netlify.toml` runs `echo …`) |
| Publish directory | `.` (repo root — `index.html` is at the root) |
| Branch preview URL | `https://testin-mikesupabase--acquisto.netlify.app` |

> ⚠️ The production branch is **`Testin.MikeSupabase`**, NOT `main` and NOT `pure-deploy`.
> Pushing to `main` does **nothing** to the live site. Netlify only rebuilds on a push to
> `Testin.MikeSupabase`. (Confirmed 6/15 and re-confirmed 6/24 from the Netlify project API:
> `branchVersionOfSite = testin-mikesupabase--acquisto.netlify.app`, `currentDeploy.state = current`.)

---

## Deploy methods — there is NO Zapier hop (t-insource-deploy)

`git push` is the *mechanism*, but most lanes here have **no shell / no push tool**. Use this priority
order — every option commits to `Testin.MikeSupabase`, which is the only thing that publishes:

| # | Method | Who | When |
|---|---|---|---|
| 1 | **`release.publish(label)`** via our `pure-mcp` Edge Function | any lane w/ an `x-mcp-key` | preferred — commits + logs a `pure_deploy_registry` row (auto-backup + `release.revert`) + triggers the build. Fullest audit. |
| 2 | **Composio → GitHub direct commit** (`GITHUB_CREATE_OR_UPDATE_FILE_CONTENTS`) | chat-Claude (no token needed) | self-serve default — Composio is authed as `puremlstech`. Get sha via `GITHUB_GET_REPOSITORY_CONTENT` first when updating; base64 the content; commit to `puremls` @ `Testin.MikeSupabase`. Auto-triggers Netlify. **CONFIRMED WORKING.** |
| 3 | Hand a stamped batch to **Claude Code** | Claude Code | multi-file drops, anything needing a working tree |
| 4 | **GitHub web upload** by Mike | Mike | last resort |

**Zapier is retired from the deploy path.** No deploy step routes through Zapier — it was never the
publisher (Netlify watches the repo directly) and nothing here depends on it. If you see a "deploy via
Zapier" instruction anywhere, it's stale; use method #1 or #2.

> Mechanics are identical for every method: the change must land as a commit on `Testin.MikeSupabase`
> with `index.html` at the publish root. Netlify does the rest. `release.publish` (method 1) is the
> long-term target because it adds the registry row + one-call revert; method 2 is the everyday driver.

---

## Deploy — the whole procedure

```bash
# 1. Be on the deploy branch (local branch may be named differently but must track it)
git fetch origin Testin.MikeSupabase
git rebase origin/Testin.MikeSupabase      # stay current with other lanes/sessions

# 2. Make your change, commit it
git add <files>
git commit -m "..."

# 3. Push to the production branch — THIS is the deploy
git push origin HEAD:Testin.MikeSupabase
```

That's it. Netlify auto-builds (no real build — it just publishes the root) and acquisto.biz updates.
No `npm run build`, no `dist/`, no drag-and-drop needed for normal changes.

### Verify it went out
- Netlify MCP: `netlify-project-services-reader { operation: get-project, siteId: 245e35a8-a530-4d31-84c3-d0e94904380d }`
  → check `currentDeploy.state == "ready"/"current"`.
- Or open https://acquisto.biz and hard-refresh (Cmd/Ctrl-Shift-R). JS is cached 1h with
  stale-while-revalidate, so a deploy may take a moment to show on repeat visits.

---

## Why it's static (don't reintroduce a build)

PURE is plain HTML/CSS/JS — every page is a real `*.html` file at the repo root; navigation is by
filename (`home.html`, `v5.html`, `dealspine.html`, …). `pure-gate.js` routes off the trailing
`*.html` segment. There is **no SPA path-router** and **no bundler**.

- `netlify.toml` pins `publish="."` and `command="echo …"` so Netlify never runs npm.
- A no-op `package.json` at the root is a guard so even if npm runs, `build` exits 0.
- Keep it this way. "`npm run build` ENOENT" and empty-`dist` 404s come from someone setting a
  real build command/publish dir in the Netlify UI — don't.

## Clean deep-link URLs (e.g. /deal/:id/contract)

Because the site is filename-routed, a pretty URL like `/deal/a7040f8b/contract` has no file and
would 404. Support it with a rewrite in **`_redirects`** (served 200 so the URL stays pretty):

```
/deal/*  /dealspine.html  200
```

The target page must then read `location.pathname` to know which deal/view to render. Add one
`_redirects` line per clean-route family; never add a build step to do routing.

## Short links (/r/<code>)

`/r/*` rewrites (200-proxy) to the Supabase edge function `r`, which 302-redirects to the link's
target (e.g. `/deal/<id>/contract`). The relative redirect resolves against `acquisto.biz`, so it
flows through the `/deal/*` rewrite above. See `supabase/functions/r/index.ts`.

---

## Fallback: manual deploy (only if GitHub→Netlify is ever broken)

Foolproof path = **Netlify Drop**: unzip the build, drag the FOLDER (whose immediate contents
include `index.html`) onto https://app.netlify.com/drop. Never drag the `.zip`; never drag a folder
that nests `index.html` one level deep (that's the "N files uploaded + 404" symptom).

---

## For other Claude sessions / lanes

- **To ship:** push to `Testin.MikeSupabase`. Nothing else publishes.
- **Don't** repoint Netlify to `main`/`pure-deploy` or add a build command without Mike's say-so —
  it will freeze or break the live site.
- If you believe "the deploy is broken," first check `currentDeploy.state` via the Netlify reader.
  It is almost always *not* the deploy — it's a missing `_redirects` rule, a stale browser cache,
  or a page that isn't committed at the publish root.

## Staging previews (M-19F70BA4CEC, 7/17/26)
Preview-before-publish: the `staging` branch exists for changes that should be SEEN before the world does.
1. ONE-TIME (Mike, ~2 min): Netlify → Project configuration → Build & deploy → **Branch deploys** → add `staging`.
   After that, every push to `staging` publishes to its own URL: `staging--<site-name>.netlify.app` — production (`Testin.MikeSupabase`) is untouched.
2. Flow: risky/visual change → push to `staging` → review the preview URL → merge `staging` into `Testin.MikeSupabase` to go live ("promote").
3. Keep `staging` fresh: `git checkout staging && git merge origin/Testin.MikeSupabase` before starting a preview batch.
Small/safe fixes may still ship straight to `Testin.MikeSupabase` — staging is for anything you'd want eyes on first.
