Skip to content

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.co routing (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/alert with 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)

  1. gusoutdoor.co routing. 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.co subdomain (recommended — clean, works immediately) vs Shopify-side config. Until resolved, Gus Outdoor bio pages won't serve. (gusthebass.com is unaffected + fully working.)
  2. Gus Outdoor welcome email. Create a "Welcome - Gus Outdoor" email (from [email protected]) and add a brand→welcome-email map in forge_links_sync.py (currently every signup gets email 14).
  3. Amazon Associates tag. Deferred — affiliate cards use plain URLs until Justin provides the tag; /r tracks 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.sh so 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")

  1. links.products table (title, image, price, destUrl+tag, brand, position).
  2. In-app Products manager in the Link In Bio app (brand-scoped, like pages).
  3. Publish to /shop: render an Amazon-style card grid to KV page:<host>:shop, links tracked through /r/<id>; auto-route <host>/shop like pages.
  4. Product clicks flow into the Gus stats view (they're /r clicks already).
  5. 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.com sites on Cloudflare Pages (off the home host).
  • /links and /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 justinwieb workspace/brand; routes on justinwieb.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. /r already 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-bio in the Gus The Bass workspace → edit → Publish → live at gusthebass.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 main on both repos and pushed to the private GitHub backups.