Gus creator stack — full status (Link In Bio LIVE, Phases 2-8 ahead)¶
URL: https://mkdocs.justinsforge.com/memory/handoffs/gus-creator-stack-status-2026-07-08/
Date: 2026-07-08 Scope: The whole creator/affiliate stack for the Gus brands (and later JustinWieb). Phase 1 (Link In Bio) is built, deployed, and live. This is the master status: everything done and everything left, task by task and phase by phase.
Source-of-truth plan: affiliate-click-foundation. Module reference: reference_links_module.
TL;DR¶
- Phase 1 (Link In Bio) is done and live on
gusthebass.com: editor in CreatorTrack → Publish → page + click tracking + email capture on the always-on Cloudflare edge → D1 → sync into CreatorTrack + Mautic (with a welcome email + source analytics). - Next up: Phase 2 (Storefront) — planned, not started.
- Two open decisions block full multi-brand:
gusoutdoor.corouting (Shopify-fronted) and the Gus Outdoor welcome email.
Architecture (live)¶
PUBLIC (Cloudflare, always-on)
gusthebass.com/<slug> -> Worker links-edge -> page HTML from KV (page:<host>:<slug>)
gusthebass.com/r/<id> -> Worker -> KV dest lookup -> log click to D1 -> 302
gusthebass.com/c (POST) -> Worker -> validate + rate-limit -> capture to D1
KV links-map: <linkId> -> {destUrl,brand,label} ; page:<host>:<slug> -> HTML ; rl:* counters
D1 links-events: clicks + captures (append-only, ULID pk)
HOME (CreatorTrack on Console, DB lifeos)
/link-in-bio -> page list + create (Modal)
/link-in-bio/[pageId] -> block editor (header/link/affiliate-card/email-capture/text),
brand dropdown, editable slug, live phone preview, Publish
/link-in-bio/stats -> Gus stats (signups+clicks by brand/source/link)
POST /api/links, /api/links/publish -> CRUD + publish (render -> KV writes -> ensure route)
links.* (pages/blocks/contacts/clicks/captures), workspace-scoped + RLS
forge_links_sync.py (timer, 10 min) -> D1 -> links.* (ws 85) -> Mautic seg 4 (+ welcome email)
Key design choice: the bio page is served by the Worker from KV, NOT Cloudflare Pages (the apexes are proxied tunnel/Shopify CNAMEs, so a path-based Pages custom domain is impossible). Publish auto-creates a Worker route for whatever slug you set (a brand-new slug takes ~30-60s to propagate across CF's edge before it serves).
Resource ids / credentials / gotchas (for whoever continues)¶
| Thing | Value |
|---|---|
| CF account | 5b4138008d635b79e07af0c7388cd46f |
KV links-map |
eaca8ca562c3454885f2c7e3327a4f14 |
D1 links-events |
4da9b1d3-99c3-47fd-8ce3-33413372bdc4 |
| Worker | links-edge (forge/infra/links-edge) |
| gusthebass.com zone | 46a7073cb66667b9a835058e26c40230 (apex = CF tunnel) |
| gusoutdoor.co zone | 73f45aa552ff1b5dbe8374936102da1f (apex = Shopify, orange-to-orange) |
| justinwieb.com zone | 8fe40a37f7f423aa1a0661a71221f87d (apex unset; Phase 5) |
| lifeos workspace | Gus The Bass = 85 (both brands live here); Gus Outdoor Co. = 74 (legacy) |
| Mautic | CT112 192.168.86.87:8090; segment 4 "Gus The Bass"; welcome email 14 (from [email protected]); API enabled (basic auth, admin creds in ~/.forge-secrets/mautic.env); needs Host: mautic.justinsforge.com + X-Forwarded-Proto: https headers |
| Resend | gusthebass.com, gusoutdoor.co, justinwieb.com all verified senders |
| Prod publish flag | LINKS_PUBLISH_LIVE=1 in ~/.forge-secrets/creatortrack-auth.env (systemd EnvironmentFile; prod only, dev stays dry-run) |
Gotchas:
- CF token is quoted in ~/.forge-secrets/cloudflare.env. Use set -a; source ...; set +a
(strips quotes); a bare grep|cut keeps the quotes and breaks the Authorization header. The
app's lib/secrets.ts now strips quotes too. Token scopes: Workers Scripts/KV/D1/Pages edit +
zone Workers-Routes/DNS/Zone (added Workers Routes 2026-07-08).
- Deploy does NOT run migrations. scripts/forge_creatortrack_deploy.sh builds main + restarts
creatortrack-prod (:3070) only. After merging a schema change, apply migrations to prod by
hand: PGDATABASE=lifeos WORKSPACE_MIGRATIONS_DIR=db/migrations python3 ~/forge/scripts/forge_workspace_migrate.py.
(Two prod outages this session came from forgetting this — worth adding a migrate step to the
deploy script; see "Left to do".)
- Cloudflare Bot Fight Mode can 1010-challenge non-browser POSTs to /c; real browsers pass.
DONE — Phase 1, task by task (all committed + live)¶
| Plan task | Status |
|---|---|
| 1. Provision D1 + KV | done (prior session) |
2-4. Edge Worker /r + /c |
done, verified locally + live |
| 5. Deploy Worker + routes | done — gusthebass.com/{r/*,c,links} live (needed the token's Workers-Routes scope) |
| 6. Static page host | changed: served by Worker from KV, no Pages project |
7. links.* schema + RLS |
done, migration applied prod + dev |
| 8. Register app + route shell | done — Link In Bio in catalog, /link-in-bio list |
| 9. Block editor + CRUD API | done — 5 block kinds, drag reorder, autosave, live preview |
| 10. Publish pipeline | done — render → KV (page + link map) → ensure route → stamp published_at |
| 11. D1→CT sync + Mautic | done — forge_links_sync.py + timer (10 min), idempotent, source-tagged |
| 12. E2E verification | done — signup + click verified all the way to Mautic |
| 13. Register + document | done — reference_links_module.md + MEMORY.md + plan marked done |
DONE — beyond the base plan (this session)¶
- Merged
feat/link-in-bio→ CreatorTrack main; prod-deployed (:3070). - Welcome email — Mautic email 14 "Welcome to the Gus The Bass family", from
[email protected], sent once per genuinely-new signup by the sync. - Multi-brand foundation — pages keyed by host (
page:<host>:<slug>);brandHost()helper; brand dropdown (Gus The Bass / Gus Outdoor Co.) in editor + create modal that switches the page's domain; publish auto-routes any slug (ensureRoute). - Editable slug — the page URL is editable in the editor (
gusthebass.com/<slug>). - Gus stats view —
/link-in-bio/stats: signups + clicks by brand / source / link. - Real UI — replaced native
prompt/confirm/alertwith the shared Modal + toasts. - Fixes — publish 401 (unquoted CF token in the app's secrets loader); applied a latent prod migration (google-contacts) that was shipped without its schema.
- Gus The Bass workspace (85) created (holds both Gus brands).
- Dev-slot reaper hardened (tangential): never deletes a worktree with uncommitted work or one edited in the last 90 min (stops server only). Committed + pushed to forge.
LEFT TO DO¶
Open decisions (blockers)¶
gusoutdoor.corouting. Its apex is a Shopify store fronted by Shopify's Cloudflare (orange-to-orange), so the Worker routes are registered but don't intercept/links. Decide:links.gusoutdoor.cosubdomain (recommended — clean, works immediately) vs Shopify-side config. Until resolved, Gus Outdoor bio pages won't serve. (gusthebass.com is unaffected + fully working.)- Gus Outdoor welcome email. Create a "Welcome - Gus Outdoor" email (from
[email protected]) and add a brand→welcome-email map inforge_links_sync.py(currently every signup gets email 14). - Amazon Associates tag. Deferred — affiliate cards use plain URLs until Justin provides the
tag;
/rtracks regardless.
Small polish (nice-to-have)¶
- Publish toast should say "live in ~30s" for a brand-new slug (route-propagation delay).
- On slug change, clean up the old slug's KV page + Worker route (currently the old URL lingers).
- Add a migrate step to
forge_creatortrack_deploy.shso schema merges can't ship broken. - Consolidate: migrate Gus Outdoor Co. (ws 74) content into Gus The Bass (85), per Justin's "one workspace, both brands" direction.
Phase 2 — Storefront (planned, NOT started; Justin said "go")¶
links.productstable (title, image, price, destUrl+tag, brand, position).- In-app Products manager in the Link In Bio app (brand-scoped, like pages).
- Publish to
/shop: render an Amazon-style card grid to KVpage:<host>:shop, links tracked through/r/<id>; auto-route<host>/shoplike pages. - Product clicks flow into the Gus stats view (they're
/rclicks already). - Amazon PA-API auto-fill (image/price/title) — deferred, needs Amazon keys; manual entry until then.
Phase 3 — Brand websites (hand-built, NOT Michael-editable)¶
- Full
gusthebass.com+justinwieb.comsites on Cloudflare Pages (off the home host). /linksand/shop(Michael's modules) mount into them via the CF routing already established.- Use the frontend-design skill; each brand its own look.
Phase 4 — Analytics + commissions¶
- PostHog Cloud instrumentation on the pages (land → capture → click-out funnels).
- Pull Amazon Associates + Commission Junction commission reports into
links.commissions; optional Affilimate aggregation. Enrich the Gus stats view with conversions.
Phase 5 — JustinWieb second brand¶
- Point the Phase 1-4 machinery at the
justinwiebworkspace/brand; routes onjustinwieb.com. - Michael stays Gus-scoped; JustinWieb is Justin-only.
Phase 6 — Community¶
- Discord per brand + a Forge bot: bio-page "Join the Discord" → member sync to CT contacts spine, role-gated channels. Michael moderates; the bot is Justin's.
Phase 7 — Course / paywall / payments¶
- Free lead-magnet course (email-gated videos) or paid via Whop (checkout + Discord-gate + course host), or Stripe + own course page. Shopify only if physical goods. Sales → ERPNext/CT.
Phase 8 — Dub branded short domain + QR¶
- Self-hosted or cloud Dub for a branded short domain (
gus.link) + QR codes./ralready tracks; Dub is only the separate short-domain + QR surface.
Control model (load-bearing)¶
- Justin = infra: Worker, KV/D1, CF token, publish flag, sync cron, Mautic, the hand-built
brand sites. Works from the forge CLI +
wrangler+~/.forge-secrets. - Michael = CreatorTrack UI only: the Link In Bio (and later Storefront) editor, Gus-scoped by per-app permission. Never touches Cloudflare / D1 / Mautic / a terminal. A home outage stops his editing, never the live page or tracking.
How to continue¶
- Publish a page:
/link-in-bioin the Gus The Bass workspace → edit → Publish → live atgusthebass.com/<slug>(new slug: ~30-60s to propagate). - Deploy CT after code changes:
bash ~/forge/scripts/forge_creatortrack_deploy.sh(remember migrations separately for schema changes). - Deploy the Worker:
cd ~/forge/infra/links-edge && set -a; source ~/.forge-secrets/cloudflare.env; set +a && npx wrangler deploy. - Run the sync by hand:
python3 ~/forge/scripts/forge_links_sync.py --once [--dry-run]. - Everything is committed to
mainon both repos and pushed to the private GitHub backups.