Home / Archive / More in this area

Affirmology Demo Launch Plan v1

Archived version Updated May 21, 2026 · Affirmology_DemoLaunchPlan_v1.md

Summary. Goal: Stand up affirmology.ai/demo so an investor or partner can enter their birth data, watch their report appear, listen to their personalized audio, and get the same package emailed to them. All driven by the existing Python agent in affirmology-agent/.

Affirmology Demo Launch Plan v1

Goal: Stand up affirmology.ai/demo so an investor or partner can enter their birth data, watch their report appear, listen to their personalized audio, and get the same package emailed to them. All driven by the existing Python agent in affirmology-agent/.

Scope (locked): Investor / partner demo, not public launch. No payments, no accounts, no abuse protection beyond a basic rate cap. Polish over throughput.


The Stack (Locked Today)

Four moving pieces, each chosen for the shortest path from your existing assets to a live affirmology.ai/demo URL.

  1. Cloudflare Pages hosts the intake form and the results page. Domain is already at Cloudflare, custom routing at affirmology.ai/demo and affirmology.ai/demo/r/[id] is one DNS-free config change, free tier covers 100x our needs.
  2. Railway hosts the Python agent as a FastAPI service behind a public URL. Same code that already runs locally in affirmology-agent/, dockerized once, deployed in five minutes. ~$5 to $20 per month for this volume.
  3. Cloudflare R2 stores the generated audio (MP3) and report (PDF or markdown). Same Cloudflare account, no egress fees, signed URLs for delivery.
  4. Go High Level owns the contact record and the email automation. The agent pings a GHL inbound webhook with the contact data and the R2 file URLs. GHL fires the email template with the audio link and the report attached.

The result HTML page on Cloudflare Pages and the GHL email are two delivery channels for the same payload. The user sees their report and audio inline immediately. They also have it waiting in their inbox.


The Flow, End to End

  1. User lands on affirmology.ai/demo. Static page served from Cloudflare Pages. Sees the intake form styled in the established Affirmology aesthetic (cream #faf6ee, gold #b38a3a, Cormorant Garamond headlines, Inter body, JetBrains Mono accents from Brief v7).
  2. User fills first name, optional middle, last name, birth date, birth time, time zone, and birth location, plus email. Submits.
  3. JavaScript on the page POSTs the form to the Railway agent's /api/runs endpoint. The agent returns a run_id immediately and starts work in the background. The page redirects to affirmology.ai/demo/r/[run_id].
  4. The agent does the existing four-engine calculation (astrology, Human Design, Gene Keys, numerology), generates the four reports, runs the verifier, then calls ElevenLabs for the audio, then mixes the music bed, then uploads audio plus PDF to R2.
  5. The results page polls /api/runs/[id] every 3 seconds. While pending, it shows a calm progress sequence ("Calculating your chart", "Composing your script", "Recording your voice", "Mixing your audio"). When complete, it injects the report markdown rendered as HTML and shows the audio player with the signed R2 URL.
  6. In parallel with step 5, the agent POSTs the same payload to a GHL inbound webhook. GHL creates or updates the contact, stores the audio URL and the report URL as custom fields, and triggers the "Demo Delivered" email automation that emails the user the audio link and the report.
  7. Optional gate: the results page can require the audio to play (or play to completion) before revealing a follow-on CTA. Implementation note in component 2 below.

Component 1: Intake Page

Path: affirmology.ai/demo/index.html Lives in: Cloudflare Pages project Fields: First name (required), Middle name (optional), Last name (required), Birth date (date picker), Birth time (time picker, with a "I do not know" toggle that disables time and surfaces a warning about degraded rising sign and houses), Time zone (auto-detected from browser, editable), Birth location (text input with city autocomplete via a free geocoder), Email (required). Submit handler: Fetch POST to the Railway agent's /api/runs. On success, window.location to the results page with the returned run_id. Visual direction: Pull the existing Brief v7 CSS variables and typography directly so the demo page reads as a sibling of the deck and the executive summary. Treat the form as a single centered column on cream, with the gold accent reserved for the submit button and the section dividers. No competing visual ornament. The form is the page.

Component 2: Results Page

Path: affirmology.ai/demo/r/[run_id] (Cloudflare Pages function or static + client routing) Initial state: Branded waiting state with the four-step progress indicator and a soft animated ornament (the gold ✦ from Brief v7, breathing). Polling: Client polls /api/runs/[id] every 3 seconds for status. Status values: queued, computing_chart, generating_script, recording_audio, mixing, delivered, failed. Delivered state: Renders the markdown report inline using a small client-side markdown library (marked.js) styled with the same Cormorant headers and Inter body. The audio player sits in a sticky bar at the top or bottom of the viewport with the user's first name above it ("Sol, here is your soul's song"). The audio file is served from R2 via a signed URL. Optional "listen to unlock" mechanism: The page can hide a final CTA section (Book a deeper session, See the methodology, etc.) until the audio's ended event fires, or until 80% of the audio has been played. Simple JavaScript listener on the <audio> element. We add this in v2 if you want it for the in-room demo experience.

Component 3: Agent API on Railway

Wraps: The existing affirmology-agent Python package. Stack: FastAPI + uvicorn, dockerized. Background work via a simple in-process worker (sufficient for demo volume; no Redis or Celery needed yet). Endpoints: - POST /api/runs accepts the form payload, validates, starts a background task, returns { run_id, status: "queued" }. - GET /api/runs/{run_id} returns current status plus, once delivered, the report markdown, the signed audio URL, and any verification flags. - POST /api/webhook/ghl (optional, for testing GHL handoff in isolation). Background task does: compute_chart (existing) → generate_reports (existing) → verify_report (existing) → generate_script (Phase 2 work, partly stubbed today) → synthesize_audio (ElevenLabs, new) → mix_audio (FFmpeg, new) → upload_to_r2 (new) → notify_ghl (new) → mark delivered. Deploy: railway up from the affirmology-agent directory after adding a Dockerfile and a web service config. Environment variables for ANTHROPIC_API_KEY, ELEVENLABS_API_KEY, ELEVENLABS_VOICE_ID, R2_ACCESS_KEY, R2_SECRET_KEY, R2_BUCKET, GHL_WEBHOOK_URL.

Component 4: GHL Webhook and Email Automation

Inbound webhook: Create a workflow in GHL that starts on "Inbound Webhook". Map the JSON fields the agent will send: first_name, last_name, email, birth_date, birth_time, birth_location, audio_url, report_url, run_id. On trigger, Create or Update Contact, store the new fields as custom fields, then fire the "Demo Delivered" email template. Email template: Cream + gold, matches the page. Subject: "Your Affirmology, ready". Body includes the audio link (button), the report link (button), and a single follow-on CTA ("Book a deeper session with Jeff"). HTML and plain-text version both. You configure this in the GHL UI: I cannot click into your GHL account, but I will give you the exact field names the agent will send and a copy-paste workflow recipe so the setup takes 15 minutes.

Component 5: Storage on Cloudflare R2

Bucket: affirmology-demo-renders Objects per run: runs/{run_id}/audio.mp3, runs/{run_id}/report.pdf, runs/{run_id}/report.md, runs/{run_id}/chart.json. Access: Signed URLs valid for 30 days, generated server-side in the agent. No public bucket. Why R2 over S3: Same Cloudflare account as the domain, zero egress, simpler IAM, free for the demo's volume.


Build Order

The order matters because each step is independently verifiable and each one unblocks the next.

  1. Intake + results HTML, mocked. Build both pages, wire them to a fake /api/runs that returns a canned report and a placeholder audio after 30 seconds. This is the demo we can show on a laptop tomorrow if needed, and it locks the visual direction before any backend work. About one focused session.
  2. Dockerize and deploy the existing agent to Railway. No new functionality. Just compute_chart and generate_reports exposed behind POST /api/runs and GET /api/runs/{id}. The audio in the response is still the placeholder. This proves the deploy story and gives us a real URL to point the page at. About one focused session.
  3. ElevenLabs synthesis + FFmpeg mix. Replace the placeholder audio with the real pipeline. Use the existing Affirmology_Script_v5.md as the script template for v1; Phase 2 of the architecture doc swaps in the personalized script generator later. About one to two sessions.
  4. R2 upload + signed URLs. Move the audio and the report off local disk and onto R2. About half a session.
  5. GHL webhook integration. Agent POSTs to GHL on delivered. You build the email automation in the GHL UI in parallel. About half a session for me, 15 minutes for you in GHL.
  6. DNS routing for affirmology.ai/demo. Point the Cloudflare Pages project at the subpath. About 10 minutes once the page is built.

Total time to a live demo: 4 to 6 focused sessions. Most of the surface area is glue, not original code, because Phase 1 of the agent already exists.


What You Own vs What I Build

You (manual setup, one-time): - Create the Railway account and connect it to a new GitHub repo for affirmology-agent (or upload directly). - Create the Cloudflare Pages project, point it at the demo/ folder I will deliver, configure the affirmology.ai/demo route. - Create the Cloudflare R2 bucket and generate API credentials. - Get an ElevenLabs API key on the Creator tier and pick a voice (Sarah, Charlotte, Brian, or Will from your demo build plan). - Build the GHL inbound webhook workflow and the email template using the recipe I will provide. - Hand me the resulting URLs and tokens (over a secure channel) so I can wire the agent's .env.

I build: - The intake and results HTML, CSS, and JS. Self-contained, no framework. - The FastAPI wrapper around the existing Python agent. - The Dockerfile and Railway service config. - The ElevenLabs and FFmpeg integration. - The R2 upload helper and signed-URL generator. - The GHL webhook POST in the agent. - The GHL workflow recipe and field mapping doc. - A README that ties the deploy steps together.


Open Decisions to Resolve Before Build

These are the calls I need from you before or during the first build session. None block writing v1 of the HTML page.

  1. Voice. Which ElevenLabs voice is the demo default? Pick one of Sarah, Charlotte, Brian, Will, or share a voice ID you have already auditioned.
  2. Music bed. Do we use the existing Heavenly Circuit.mp3 in the repo as the v1 bed for every demo, or do you want me to wire a small library and a mood-matching rule first? For an investor demo, one bed is plenty.
  3. The "listen to unlock" gate on the results page. Yes for v1 (more theatrical for a live demo) or no for v1 (cleaner, less friction)?
  4. Email sender identity in GHL. What from-name and from-email do you want on the "Demo Delivered" email? jeff@jeffparker.love or a new hello@affirmology.ai?
  5. Submission cap. Do we cap submissions per email per day at the demo URL? Recommended: 3 per email per 24 hours, no auth, soft rate limit by IP.
  6. What goes on the results page footer. A single follow-on CTA, your contact info, or nothing? Cleanest for an investor demo is one button: "Book a deeper session."

Next Concrete Step

The intake and results HTML, mocked, in the established Affirmology visual language. One file each, dropped into AFFIRMOLOGY/CLAUDE OUTPUTS/Affirmology/ for review. The mock agent returns a canned report and the existing Heavenly Circuit.mp3 after a simulated 30-second render so you can feel the experience end to end on your laptop today.

Say the word and I will build it next.