# Retiring aiandhumn.com → asqvox.com — Full Runbook

> **Two phases, one place:**
> - **Phase 1 — noindex — APPLY NOW.** Committed at `d3c8ba2`; the VPS apply steps are below.
>   Stops aiandhumn duplicating / competing with asqvox in search while asqvox is being built.
> - **Phase 2 — 301 cutover — PARKED.** Apply only once **asqvox.com is live and serving the
>   same pages at the same URLs.** Transfers SEO authority to asqvox and removes the duplicate.

Goal: retire aiandhumn.com in favour of asqvox.com without splitting SEO authority or leaving
duplicate content across the two domains.

---

## Where this sits in the sequence

| Phase | State | Mechanism | Why |
|---|---|---|---|
| **1 — NOW** ✅ | aiandhumn live, asqvox not ready | `X-Robots-Tag: noindex` (crawlable) — commit `d3c8ba2` | Stop aiandhumn competing with asqvox while asqvox is built. Deindexes aiandhumn. |
| **2 — CUTOVER** (this doc) | asqvox live, mirrors the pages | **301** aiandhumn → asqvox | Transfers authority to asqvox + removes the duplicate. **Strictly better than noindex** — do this the moment asqvox is ready. |
| **3 — HOLD** | 301 in place | Keep the 301 + the aiandhumn TLS cert alive **≥ 6–12 months** | Google needs months to fully migrate signals. **Do not take aiandhumn offline early.** |
| **4 — RETIRE** | signals migrated | DNS teardown / let domain lapse | Only after Search Console shows the migration settled. |

**A 301 replaces the noindex** — once aiandhumn 301-redirects, it serves no content, so the
noindex header is moot. You simply swap the noindex-proxy config for the redirect config below.

---

## Phase 1 — noindex (APPLY NOW)

Committed at `d3c8ba2`. This makes aiandhumn stop competing with / duplicating asqvox in search
(deindexes it over days-to-weeks). **nginx + docroot only — no container rebuild.** Run on the
VPS as root:

```bash
# 0. Pull the committed configs onto the shared checkout
cd /opt/aiw/src && git checkout main && git pull origin main

# 1. (baseline) capture current prod headers BEFORE — apex should have NO x-robots-tag today
for u in https://aiandhumn.com/ https://aiandhumn.com/about https://app.aiandhumn.com/login; do
  echo "== $u =="; curl -sI "$u" | grep -iE 'HTTP/|x-robots-tag'
done
curl -s https://aiandhumn.com/robots.txt

# 2. Install the updated robots.txt at the apex docroot (stays crawlable; Sitemap line dropped)
install -m 644 -o aiandhumn -g aiandhumn \
  /opt/aiw/src/deploy/cpanel-docroots/aiandhumn/robots.txt \
  /home/aiandhumn/public_html/robots.txt

# 3. Install the updated nginx user-includes (apex + app)
cp /opt/aiw/src/deploy/cpanel-nginx/aiandhumn/aiandhumn.com/proxy.conf \
   /etc/nginx/conf.d/users/aiandhumn/aiandhumn.com/proxy.conf
cp /opt/aiw/src/deploy/cpanel-nginx/aiandhumn/app.aiandhumn.com/proxy.conf \
   /etc/nginx/conf.d/users/aiandhumn/app.aiandhumn.com/proxy.conf

# 4. Test + reload (no container rebuild)
nginx -t && systemctl reload nginx
```

**Verify:**

```bash
curl -sI https://aiandhumn.com/           | grep -i x-robots-tag   # noindex, nofollow
curl -sI https://aiandhumn.com/about      | grep -i x-robots-tag   # noindex, nofollow
curl -sI https://aiandhumn.com/pricing    | grep -i x-robots-tag   # noindex, nofollow
curl -sI https://app.aiandhumn.com/login  | grep -i x-robots-tag   # noindex, nofollow
curl -sI https://app.aiandhumn.com/signup | grep -i x-robots-tag   # noindex, nofollow
curl -s  https://aiandhumn.com/robots.txt                          # Allow: /  (NO Sitemap line)
```

Then (optional, speeds removal): in **Google Search Console** → aiandhumn.com property, use
*Removals* to temporarily hide URLs while the noindex propagates. Monitor **Pages → Indexed**
dropping over the following weeks.

**Phase 1 rollback** (re-allow indexing) — revert commit `d3c8ba2`, then re-install the files:

```bash
cd /opt/aiw/src && git revert --no-edit d3c8ba2 && git push origin main
# then re-run steps 2-4 above to install the reverted robots.txt + proxy.confs and reload.
```

---

## Phase 2 — 301 cutover (PARKED — asqvox.com must be live first)

## Prerequisites (all must be true before applying)

- [ ] **asqvox.com is LIVE** (apex marketing + `app.asqvox.com`) and serving the **same URL
      structure** as aiandhumn — it's a rebrand of the same codebase, so paths match 1:1
      (`/about` → `/about`, `/pricing` → `/pricing`, `/billing/checkout` → same, etc.).
- [ ] asqvox has a **valid TLS cert** (AutoSSL issued) and its own sitemap/robots (indexable).
- [ ] aiandhumn's **AutoSSL cert is still renewing** (the `.well-known` passthrough below keeps
      it valid — required to serve HTTPS 301s).
- [ ] **Google Search Console** properties exist for **both** aiandhumn.com and asqvox.com
      (needed for the Change-of-Address step).

---

## The configs — install the parked repo files (single source of truth)

The Phase-2 redirects are committed in the repo, ready to install. **Install these files
verbatim** — do NOT hand-write the redirects here. (An earlier draft of this section inlined
bare `return 301 …$request_uri;` blocks; those are now OUT OF DATE — the apex needs a
`/pricing` override, below — so the parked files are authoritative.) Each **replaces** the
current live file wholesale. The `(?!\.well-known/)` lookahead keeps ACME HTTP-01 challenges
falling through to cPanel so aiandhumn's cert keeps renewing; one location handles apex **and**
www; `$request_uri` preserves the full path + query.

| Live include (`/etc/nginx/conf.d/users/aiandhumn/…`) | Install from (`deploy/cpanel-nginx/…`) | 301 target |
|---|---|---|
| `aiandhumn.com/proxy.conf` (apex + www) | `aiandhumn-301-to-asqvox.conf` | `asqvox.com` |
| `app.aiandhumn.com/proxy.conf` | `app.aiandhumn-301-to-asqvox.conf` | `app.asqvox.com` |
| `widget.aiandhumn.com/proxy.conf` *(optional, safe)* | `widget.aiandhumn-301-to-asqvox.conf` | `widget.asqvox.com` |
| `cafe.aiandhumn.com/proxy.conf` *(optional, low priority)* | one-liner (below) | `cafe.asqvox.com` |

**⚠️ The apex carries a `/pricing` override.** asqvox currently serves the **site-v0 waitlist
fork, which removed `/pricing`** — so `aiandhumn-301-to-asqvox.conf` diverts `/pricing` (+ its
trailing-slash form) to `/waitlist` instead of path-preserving into a 404. Every other indexed
path still 301s to the same path on asqvox. **Remove that override when `MARKETING_PKG` flips
back to `beta-v1`** (pricing page restored) — see that file's header.

**Widget (optional, safe):** the bundle is a static GET, so browsers follow the 301 and existing
`<script src="https://widget.aiandhumn.com/aiw-voice-widget.js">` embeds keep working — still,
customers should re-point to `widget.asqvox.com` long-term.

**Cafe (optional):** client demo, already noindex — redirect only for consistency, same one-line
`return 301 https://cafe.asqvox.com$request_uri;` pattern inside the `(?!\.well-known/)` lookahead.

**⚠️ Do NOT 301 `api.aiandhumn.com`** — see the next section (it must keep serving until every
customer re-points their embed).

Rollback target for each file is the Phase-1 noindex version pinned at `d3c8ba2` (see Rollback).

---

## ⚠️ Do NOT blindly 301 the API (`api.aiandhumn.com`)

The widget is embedded on **customer sites** and calls `api.aiandhumn.com` (POST `/api/sessions`,
webhooks, CORS preflight). A blanket 301 there will **break live widgets**:

- 301 on a **POST** does not reliably preserve method/body across HTTP clients.
- CORS **preflight (OPTIONS)** + the reflected-origin logic don't survive a cross-host redirect.
- The backend URL is baked into each customer's `<script data-backend-url>` — they must re-point it.

**Handle the API as an operational cutover, not a redirect:** keep `api.aiandhumn.com` serving
(proxying to the backend) until every customer has re-pointed their embed to `api.asqvox.com`,
then retire it. Track this in the broader **`deploy/NEW-PROD-ENV-RUNBOOK.md`**, not here.

---

## Apply (at cutover)

```bash
cd /opt/aiw/src && git checkout main && git pull origin main

# Back up the current (Phase-1 noindex) live files first — instant rollback if needed.
cp /etc/nginx/conf.d/users/aiandhumn/aiandhumn.com/proxy.conf{,.noindex.bak}
cp /etc/nginx/conf.d/users/aiandhumn/app.aiandhumn.com/proxy.conf{,.noindex.bak}

# Install the parked redirect configs (apex + app; add widget/cafe if wanted).
cp /opt/aiw/src/deploy/cpanel-nginx/aiandhumn-301-to-asqvox.conf \
   /etc/nginx/conf.d/users/aiandhumn/aiandhumn.com/proxy.conf
cp /opt/aiw/src/deploy/cpanel-nginx/app.aiandhumn-301-to-asqvox.conf \
   /etc/nginx/conf.d/users/aiandhumn/app.aiandhumn.com/proxy.conf
# optional — widget (safe) + cafe:
cp /opt/aiw/src/deploy/cpanel-nginx/widget.aiandhumn-301-to-asqvox.conf \
   /etc/nginx/conf.d/users/aiandhumn/widget.aiandhumn.com/proxy.conf

nginx -t && systemctl reload nginx
```

Then, in **Google Search Console**:
1. Confirm asqvox.com is verified and its sitemap is submitted.
2. On the **aiandhumn.com** property → Settings → **Change of Address** → select asqvox.com.
   (This requires the 301 to be live first — GSC validates it.)

---

## Verify

```bash
curl -sI https://aiandhumn.com/pricing       # 301 · Location: https://asqvox.com/pricing
curl -sI https://www.aiandhumn.com/about     # 301 · Location: https://asqvox.com/about
curl -sI http://aiandhumn.com/               # 301 → https://asqvox.com/   (http too)
curl -sI https://app.aiandhumn.com/dashboard # 301 · Location: https://app.asqvox.com/dashboard
# AutoSSL passthrough still works (NOT redirected to asqvox):
curl -sI https://aiandhumn.com/.well-known/acme-challenge/probe
```

Path-preservation check: every aiandhumn path should land on the **same path** on asqvox
(valid because it's the same codebase). Spot-check a few deep links.

---

## Rollback

The interim noindex config (committed at `d3c8ba2`) is the rollback target:

```bash
git show d3c8ba2:deploy/cpanel-nginx/aiandhumn/aiandhumn.com/proxy.conf \
  > /etc/nginx/conf.d/users/aiandhumn/aiandhumn.com/proxy.conf
git show d3c8ba2:deploy/cpanel-nginx/aiandhumn/app.aiandhumn.com/proxy.conf \
  > /etc/nginx/conf.d/users/aiandhumn/app.aiandhumn.com/proxy.conf
nginx -t && systemctl reload nginx
```

---

## Don't-forget list for the broader migration (pointers, not covered here)

These live in `deploy/NEW-PROD-ENV-RUNBOOK.md` — the 301 is only the SEO half:
- OAuth redirect URIs (Google + LinkedIn) for asqvox hosts
- Backend env URLs (`APP_PUBLIC_BASE_URL`, `APP_FRONTEND_URL`, `WIDGET_ALLOWED_ORIGINS`)
- SMTP `FROM`, DNS, cert issuance for all asqvox subdomains
- Customer widget re-pointing (`data-backend-url`) before retiring `api.aiandhumn.com`
- asqvox canonical tags / sitemap self-referencing asqvox
```
