Home / Product / Atlas and Studio
Updated Jun 15, 2026 · Affirmology_CloudStudio_BuildSpec_v1.md
Date: June 15, 2026. For: The Claude Code session building the cloud studio. Purpose: A complete handoff. Everything below was decided with Jeff. Build from this. Where it says "inspect the existing code," do that before assuming signatures.
Take the Affirmology agent pipeline that currently runs on Jeff's laptop and put it in the cloud so it runs 24/7 and is usable from his phone. The primary milestone, due before a Tennessee trip in roughly two weeks, is: Jeff opens a web page on his phone, enters birth data, taps generate, and a few minutes later gets back a finished MP3 plus the Sacred Audio Report PDF, without his laptop being involved at all. The page lives at studio.affirmology.ai, is mobile-first, and also works well on desktop.
Lives today at /Users/jeffreyparker/CLAUDE/AFFIRMOLOGY/affirmology-agent/. Read its cli.py and README first; treat that as ground truth over this summary.
Known shape:
- cli.py is the single entry point. Takes a person's birth data, runs deterministic chart engines (astrology, Human Design, Gene Keys, numerology), writes facts files, optionally generates the spoken script, optionally renders audio via ElevenLabs, optionally mixes voice and music with FFmpeg, optionally emits the Sacred Audio Report PDF via WeasyPrint.
- Output contract: client-facing files (final MP3, Sacred Audio Report PDF) at a per-person folder root; backend audit files in a backend/ subfolder.
- Rough cost and time: about 60 cents and about 3 minutes of compute per full render.
Do not rewrite the pipeline. Wrap it. The web studio calls into it.
Three pieces:
A. Front-end - studio.affirmology.ai (Cloudflare Pages, static HTML/CSS/JS)
- Mobile-first responsive. Must look and feel great on a phone first, then scale up cleanly to a full desktop layout. Jeff explicitly wants both.
- Apply the Affirmology brand design system. Read and follow the affirmology-design skill. This must not look like generic AI output.
- Screens/components:
- A birth-data form: name, birth date, birth time (with an "unknown time" option), birth location (city search or lat/long).
- Render options: toggles for script, audio, PDF (default all on).
- A generate button that calls the API and shows live job status (queued, running, done, error) with a friendly progress state, since a render takes minutes.
- A result view: inline audio player for the MP3, download buttons for MP3 and PDF.
- A recent-renders list so Jeff can re-grab past outputs from his phone.
- Talks to the API over HTTPS. Store the API base URL and an auth token in config. Handle CORS.
B. API + worker - on Render (Python web service wrapping the pipeline)
- Framework: FastAPI (or Flask) plus a background job mechanism. Volume is tiny (one user plus a small team), so keep job handling simple: a background task/thread with job state persisted to a small store (SQLite on a Render persistent disk is fine). Do not over-engineer with Celery unless needed.
- Endpoints (adjust names as sensible):
- POST /api/render - body has birth data and options; enqueues a job; returns {job_id}.
- GET /api/jobs/{job_id} - returns status, progress, and on completion the URLs to the MP3 and PDF in object storage.
- GET /api/jobs - recent jobs for the recent-renders list.
- GET /api/health - health check.
- On job completion, upload the MP3 and PDF to R2 (or Drive) and return public or signed URLs. Do not serve large files directly from the app container long-term.
- Auth: the subdomain is public, so gate it. A shared bearer token / single password for Jeff and the small team is enough for now. Put the token in an env var; the front-end sends it. Do not build full user accounts yet.
- System dependencies: FFmpeg and WeasyPrint need OS-level libraries (pango, cairo, libffi, etc.). The reliable way to get these on Render is a Dockerfile for this service. Build the image with FFmpeg and WeasyPrint's system deps installed. Do not fight Render's default buildpack on this.
C. Object storage (Cloudflare R2 preferred) - One bucket for rendered media. The API writes finished MP3s and PDFs here and hands back URLs.
Two repos (keeps concerns clean and lets the team clone knowledge without pulling the app):
affirmology-studio/ (the app - deploy to Render + Cloudflare Pages)
├── api/ FastAPI app wrapping the pipeline
│ ├── main.py
│ ├── jobs.py background job runner + status store
│ ├── storage.py R2/Drive upload helpers
│ └── Dockerfile FFmpeg + WeasyPrint system deps
├── agent/ (Phase 2) Claude Agent SDK worker + Telegram
├── web/ static front-end for studio.affirmology.ai
│ ├── index.html
│ ├── styles.css Affirmology design system
│ └── app.js
├── affirmology-agent/ the existing pipeline (moved or git submodule)
├── render.yaml Render service definitions
└── README.md
jpl-knowledge/ (separate repo - shared with the team)
├── AFFIRMOLOGY/ ... the MD knowledge docs only
├── WIN TOGETHER/ ...
└── .gitignore ignore *.mp3 *.png *.pdf *.mov etc. (media lives in R2/Drive)
Note on the knowledge repo: include text and MD only. Gitignore heavy binaries; those belong in R2/Drive. This is what Colin and Sol will clone.
render.yaml: one web service (the API, built from the Dockerfile), persistent disk for the SQLite job store and any scratch space.ANTHROPIC_API_KEYELEVENLABS_API_KEYSTUDIO_AUTH_TOKEN (the shared gate token)R2_ACCOUNT_ID, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, R2_BUCKET (or Drive equivalents)web/ directory.studio.affirmology.ai → Cloudflare Pages (the front-end). Add the custom domain in the Pages project; affirmology.ai DNS is on Cloudflare so this is a few clicks.api.studio.affirmology.ai (CNAME to the Render service) or on the Render-provided URL. Configure CORS on the API to allow the studio origin.Not required for the trip milestone, but build the repo so it slots in.
- An always-on worker built on the Claude Agent SDK, running on Render.
- It reads the jpl-knowledge repo from disk so it knows Jeff's projects.
- Tools wired in: a "render audio" tool that calls the studio API from Phase 1; plus Gmail, Calendar, Airtable, MailerLite, GitHub as they come online.
- Front door: a Telegram bot so Jeff can send voice notes from anywhere and get conversational replies and finished files back. (Telegram is the default channel; confirm with Jeff before building if anything changed.)
- This is "Cowork, but always-on and reachable from the phone." The knowledge lives with the agent on the server, not on the phone.
studio.affirmology.ai, Jeff can submit birth data and trigger a render.jpl-knowledge.This cloud spec is the authoritative INFRASTRUCTURE/build plan for the studio and supersedes the laptop+Tailscale approach as the target. The existing laptop demo (demo.affirmology.ai, served by the GitHub-connected affirmology-site worker, with the API worker proxying to the laptop FastAPI over Tailscale Funnel) keeps running as the interim live demo until the cloud studio ships. The FEATURE design of the studio (everything chart-driven, categories/structures, the reflect-back step, the team build-report with technique footer, the comfort vote, A/B and multi-person feedback, the leaderboard, the techniques layer) lives in Affirmology_Studio_Spec_v1.md and layers on top of this cloud MVP. Build order: ship the Phase-1 cloud MVP (phone -> birth data -> render -> MP3+PDF, no laptop) first, then layer the studio features. The chart-engine already had the Manifesting Generator fix and corpus grounding wired; script_generator.generate_script already accepts a concept structure directive. Reuse all of it.