# ECM mirror setup · same pattern as `console.pattayatogether.com` **What:** activate `https://ecm.pattayatogether.com/` using **the same deployment pattern** that already serves `https://console.pattayatogether.com/` — a GitHub Pages repo with a CNAME file. The only reason this needs a second repo is GitHub Pages' hard one-CNAME-per-repo limit, not anything specific to ECM. **How:** push `docs/ecm/*` to a sibling repo `Thailand-Together-ECM` whose Pages serves it under `ecm.pattayatogether.com`. A GitHub Actions workflow keeps the sibling in sync automatically — you push to this repo, the mirror runs, the second repo updates, Pages rebuilds, the subdomain reflects the change. **Cost:** $0. Same plan as `console.pattayatogether.com`. **Time end-to-end:** ~7 minutes (3 minutes script, 2 minutes Pages click, 2 minutes DNS row). --- ## Evidence this matches the existing console pattern ``` $ cat ./CNAME ./docs/CNAME console.pattayatogether.com console.pattayatogether.com $ ls ./.nojekyll ./docs/.nojekyll ./.nojekyll ./docs/.nojekyll $ git log --oneline -- docs/CNAME ead5fd6 Create CNAME $ git log --oneline -- CNAME d7df929 Add CNAME for custom domain console.pattayatogether.com ``` That's all `console.pattayatogether.com` is — a CNAME committed to the repo + Pages enabled in Settings + a CNAME row at Cloudflare DNS. There is no GH Action that deploys Pages; it's a built-in Pages auto-build. (The repo's `.github/workflows/deploy.yml` only fires the Hostinger webhook for the Laravel app at `platform.pattayatogether.com`.) So `ecm.pattayatogether.com` follows the **identical** pattern in a sibling repo. --- ## Bootstrap (run once · 6 automated steps · 1 command) Prerequisites: ```bash brew install gh # if needed gh auth login # if needed; choose 'github.com', SSH, your account ``` Then from the source repo root: ```bash bash scripts/ecm-init-pages-mirror.sh ``` What that script does (see file for the implementation): | Step | Action | Where | |------|--------|-------| | 1 | Confirm `gh` auth + identify source/target repos | local | | 2 | `gh repo create montienvic-dotcom/Thailand-Together-ECM --public` (idempotent) | github.com | | 3 | Generate ed25519 deploy key in `/tmp` | local | | 4 | Register the public key as a deploy key (write) on the new repo | github.com | | 5 | Store the private key as `ECM_PAGES_DEPLOY_KEY` secret on the source repo | github.com | | 6 | Trigger `mirror-ecm-pages.yml` so the new repo gets its first content drop | github.com | After step 6, the new repo contains an exact copy of `docs/ecm/*` plus the right CNAME and `.nojekyll`. --- ## Two manual steps (≈ 4 minutes) ### A · Enable Pages on the new repo 1. Visit `https://github.com/montienvic-dotcom/Thailand-Together-ECM/settings/pages` 2. **Source:** Deploy from a branch 3. **Branch:** `main` · `/ (root)` 4. **Save** GitHub will issue a Let's Encrypt cert in 1–2 minutes after the DNS step below resolves. ### B · Cloudflare DNS row In the Cloudflare dashboard for `pattayatogether.com`: 1. **DNS · Records · Add record** 2. **Type:** `CNAME` 3. **Name:** `ecm` 4. **Target:** `.github.io` (e.g. `montienvic-dotcom.github.io`) 5. **Proxy status:** **DNS only** (grey cloud) — flip to Proxied (orange) after Pages issues the cert 6. **Save** Resolution typically takes < 1 minute on Cloudflare. --- ## Verify it works ```bash # DNS resolves dig +short ecm.pattayatogether.com # → .github.io. # HTTPS responds curl -I https://ecm.pattayatogether.com/ # → HTTP/2 200 # → server: GitHub.com # Same content as console diff <(curl -s https://console.pattayatogether.com/ecm/index.html) \ <(curl -s https://ecm.pattayatogether.com/index.html) # → (empty diff) ``` In the browser, open `https://ecm.pattayatogether.com/` — you should land on the same router as `https://console.pattayatogether.com/ecm/`. The 70-doc corpus, login flow, status page, and Worker-API integration all behave identically because the contents are byte-for-byte the same. --- ## Ongoing: how updates flow after bootstrap Edit any file under `docs/ecm/*` in this repo, commit, push: ``` git add docs/ecm/... git commit -m "ecm: change something" git push origin main ``` The GitHub Actions workflow `mirror-ecm-pages.yml` fires automatically on changes to `docs/ecm/**`. It rsyncs the directory into a staging area, plants `ecm.pattayatogether.com` as the CNAME, and pushes the result to the second repo's `main`. Pages rebuilds and `https://ecm.pattayatogether.com/` reflects the change in 1–2 minutes. Manual mirror trigger (e.g. force a republish): ```bash gh workflow run mirror-ecm-pages.yml --repo montienvic-dotcom/Thailand-Together ``` Inspect mirror health: ```bash gh run list --workflow=mirror-ecm-pages.yml --repo montienvic-dotcom/Thailand-Together --limit 5 ``` --- ## Roll back ```bash # remove the secret so the workflow exits cleanly gh secret delete ECM_PAGES_DEPLOY_KEY -R montienvic-dotcom/Thailand-Together # (optional) delete the second repo gh repo delete montienvic-dotcom/Thailand-Together-ECM --yes ``` `console.pattayatogether.com/ecm/` continues to serve unchanged in either case. The mirror workflow simply no-ops when the secret is absent. --- ## Comparison to other paths | Path | Pattern | Same as console? | Operator action | |------|---------|-----------------|-----------------| | **C · this guide** | Second GitHub Pages repo + CNAME | **YES** — identical pattern | `bash scripts/ecm-init-pages-mirror.sh` + 2 panel clicks | | A · CF Worker URL rewrite | Worker rewrites `ecm.pattayatogether.com/*` → `console.../ecm/*` | No — different mechanism | CF Worker deploy + DNS row | | B · Hostinger subdomain | Static files in `~/domains/.../public_html/ecm` | No — different host | hPanel subdomain + SFTP | | D · Worker API | Adds backend (`/api/*`) on `console.pattayatogether.com` | Adds backend; UI URL unchanged | wrangler deploy | For **same-as-console subdomain activation**, Path C (this guide) is the answer. Path D (Worker API) is independent and complementary — you can run both.