Home / Ops / Housekeeping and Process

Affirmology Resource Hub: Deploy + Cron Paste (for Claude Code on the Mac)

Updated Jun 26, 2026 · Affirmology_ResourceHub_DeployPaste_v1.md

Summary. For: a Claude Code session running on the Mac (filesystem access to AFFIRMOLOGY, the Cloudflare token, shell, wrangler, launchd). Status going in: the hub is ALREADY BUILT by a Cowork session. The generator, the curated taxonomy, the stylesheet, the cron wrapp

Affirmology Resource Hub: Deploy + Cron Paste (for Claude Code on the Mac)

For: a Claude Code session running on the Mac (filesystem access to AFFIRMOLOGY, the Cloudflare token, shell, wrangler, launchd). Status going in: the hub is ALREADY BUILT by a Cowork session. The generator, the curated taxonomy, the stylesheet, the cron wrapper, and the launchd job all exist in /Users/jeffreyparker/CLAUDE/AFFIRMOLOGY/resource-hub/. A full dist/ was already rendered there from 421 documents. Your job is only the Mac-only parts: a clean regenerate, the Cloudflare Pages project, the Access gate, the deploy, and the 2-hour cron.

Do not touch the locked demo (demo.affirmology.ai). No em dashes in anything you write. The site must be gated by Cloudflare Access before any content is live.


What already exists (read, do not rebuild)

resource-hub/
  generate.py        the cluster-aware static-site generator (filename-routed, incremental)
  clusters.json      curated taxonomy: categories, topic clusters, overviews, match rules
  manifest.json      generated state (hashes, titles, summaries, categories)
  assets/style.css   house style extracted from Affirmology_LaunchCRM_Playbook_v1.html
  rebuild.sh         regenerate + wrangler deploy, appends to rebuild.log
  ai.affirmology.resourcehub.plist   launchd job, every 7200s (2 hours)
  dist/              the built site (index, search, cat-*.html, doc/, raw/, assets/)

The generator groups every doc into a topic CLUSTER (not 421 flat pages), writes a synthesized overview per cluster, and keeps a client-side SEARCH over all docs so nothing is lost. Superseded versions auto-route to Archive. Secrets, code dirs, corpus/, baselines/, and build-artifact folders are excluded.


Step 1: Clean regenerate on the Mac (the sandbox could not delete; you can)

The Cowork sandbox blocks file deletion, so dist/ there may hold a few orphan pages from excluded files. On the Mac the generator cleans dist/ fully. Run:

cd /Users/jeffreyparker/CLAUDE/AFFIRMOLOGY/resource-hub
/Users/jeffreyparker/CLAUDE/AFFIRMOLOGY/affirmology-agent/.venv/bin/python -m pip install markdown
/Users/jeffreyparker/CLAUDE/AFFIRMOLOGY/affirmology-agent/.venv/bin/python generate.py

Expect a log line like built 421 docs, reprocessed ... and a per-category count. Open dist/index.html in a browser to confirm the feel before deploying.


Step 2: Create the Cloudflare Pages project + deploy token

You need a Pages-scoped token. The existing CLOUDFLARE_API_TOKEN (in affirmology-studio/.env) likely lacks Pages and Access scopes. Two clean options, pick one:

Option A (dashboard, about 10 minutes, most reliable):

  1. Go to https://dash.cloudflare.com then Workers & Pages then Create then Pages then Upload assets (direct upload, NOT Git).
  2. Name the project exactly affirmology-resources. Create it (you can upload a placeholder now; the real deploy is Step 3).
  3. Create a deploy token: My Profile then API Tokens then Create Token then template Edit Cloudflare Workers (it includes Pages), or a custom token with Account : Cloudflare Pages : Edit. Copy it.
  4. Get the account id: Workers & Pages overview, right sidebar Account ID, or run npx wrangler whoami.

Option B (wrangler):

export CLOUDFLARE_API_TOKEN="<a token with Pages:Edit>"
export CLOUDFLARE_ACCOUNT_ID="<your account id>"
npx --yes wrangler pages project create affirmology-resources --production-branch main

Then save the credentials so the cron can deploy unattended:

cat > /Users/jeffreyparker/CLAUDE/AFFIRMOLOGY/resource-hub/.deploy_env <<'EOF'
export CLOUDFLARE_API_TOKEN="<a token with Pages:Edit>"
export CLOUDFLARE_ACCOUNT_ID="<your account id>"
EOF
chmod 600 /Users/jeffreyparker/CLAUDE/AFFIRMOLOGY/resource-hub/.deploy_env

.deploy_env is a secret and is never rendered by the hub (the generator skips token and env files).


Step 3: First deploy

cd /Users/jeffreyparker/CLAUDE/AFFIRMOLOGY/resource-hub
source .deploy_env
npx --yes wrangler pages deploy dist --project-name affirmology-resources --commit-dirty=true

Note the *.pages.dev URL it prints. Do NOT share that URL. The gate goes on next, and the custom domain is what the team will use.


Step 4: Custom domain + the Access gate (this is the security step, do it before sharing)

  1. Custom domain: Pages project then Custom domains then Set up a custom domain then resources.affirmology.ai. DNS is in the same Cloudflare account, so it provisions automatically.
  2. Access application: Zero Trust then Access then Applications then Add an application then Self-hosted. - Application name: Affirmology Resources - Application domain: resources.affirmology.ai
  3. Policy: add one policy, action Allow, name Team allowlist, rule Emails with exactly these three: - jeff@jeffparker.love - solballard@gmail.com - cjacobsandassoc@gmail.com
  4. Save. Default behavior for everyone else is block.

Step 5: The 2-hour cron (launchd)

chmod +x /Users/jeffreyparker/CLAUDE/AFFIRMOLOGY/resource-hub/rebuild.sh
cp /Users/jeffreyparker/CLAUDE/AFFIRMOLOGY/resource-hub/ai.affirmology.resourcehub.plist ~/Library/LaunchAgents/
launchctl unload ~/Library/LaunchAgents/ai.affirmology.resourcehub.plist 2>/dev/null
launchctl load ~/Library/LaunchAgents/ai.affirmology.resourcehub.plist

Confirm it is loaded and run once now:

launchctl list | grep resourcehub
launchctl start ai.affirmology.resourcehub
tail -n 20 /Users/jeffreyparker/CLAUDE/AFFIRMOLOGY/resource-hub/rebuild.log

It runs at load and then every 2 hours while the Mac is awake.


Step 6: Acceptance pass (verify with evidence, then report)

  1. Gate works. Open https://resources.affirmology.ai in an incognito window: you should be blocked until Access login. Log in with an allowlisted email: you get in. A random email: denied.
  2. Home is right. The category grid shows, the Project State card sits at the top and opens Affirmology_PROJECT_STATE.md, and "Recently updated" lists the latest docs.
  3. Clustering works. Open the Video area: the "Investor Video" cluster shows its overview and groups the investor-video docs together (not scattered).
  4. Reference doc renders. Affirmology_LaunchCRM_Playbook_v1.html appears under Strategy then Launch and Go-To-Market, embedded, with a summary and related links.
  5. Cron picks up a change. Edit any doc, run launchctl start ai.affirmology.resourcehub, confirm that doc's page and timestamp update and the log shows reprocessed 1 (unchanged docs are not reprocessed).
  6. Clean. No em dashes in the generated chrome, no secret files served, demo untouched.

Report what you verified, the live URL, and the cron status back to Jeff.


Tuning the hub later (no code needed)

To re-title a topic, rewrite an overview, add a cluster, or change which docs land where, edit resource-hub/clusters.json (the title, overview, and match fields) and rerun generate.py. Match terms are lowercase substrings tested against each file's path, top to bottom, first match wins. Anything unmatched falls into that category's "More in this area" bucket, so nothing is ever dropped.