Storytelling Program — POC Dashboard
POC

Pre-Go-Live Setup Checklist

Complete every item below before running acceptance tests. Your progress is saved automatically in this browser.

0 of 0 items complete
✓ All items complete — you're ready to run acceptance tests.
Reset checklist

Work through each test below. Expand a card, follow the steps, mark each one done, then record your verdict. When you're done with all five, enter your name and submit.

During POC: SMS messages are logged but not actually sent to phones. All Slack notifications start with [POC]. Both are expected.

Test 1 — Cal.com Intake Booking
Booking → Airtable sourcing record + Slack notification
  1. 1Open cal.com/cap-storytelling/intake in a browser.
  2. 2Book a time slot using a test name (e.g., "Acceptance Test Booking") and any email address.
  3. 3Complete the booking through to the confirmation page.
  4. 4Wait up to 60 seconds, then check Airtable → Sourcing Pipeline for the new record.
  5. 5Check #storytelling-ops Slack for a [POC] notification about the booking.
What you should seeNew record in Sourcing Pipeline with Lead Source = cal.com and your test name. In #storytelling-ops, a message like:
[POC] 📅 New intake booking: Acceptance Test Booking
Scheduled: 2026-06-10T14:00:00Z
Airtable Record: recXXXXXXXX
Test 2 — OpenSign Release Form
Form sent → status update → signed → release confirmed → 3-day SMS reminder
  1. 1In OpenSign, send your release form template to a test email you control. Note the document ID.
  2. 2Wait 60 seconds. Check Airtable → Storytellers: the matching record's Release Status should be "sent".
  3. 3Open the email, click the OpenSign signing link, and complete the signature.
  4. 4Wait 60 seconds. Check Airtable: Release Status = "signed", Has Signed Release = checked.
  5. 5For the SMS follow-up test: ask Shar to manually trigger the follow-up check against a record with a sent date older than 3 days.
What you should seeAfter step 2: Release Status = "sent" + [POC] Slack "Release form sent." After step 4: status = "signed", Has Signed Release checked + [POC] Slack "Release form signed." After step 5: [POC] Slack "Release form follow-up reminders sent: 1" (no real SMS in POC).
Test 3 — Granola Intake Notes
Granola saves to Drive → PII scan → Airtable record created
  1. 1Start a Zoom or Google Meet call with Granola running. (A call with yourself on two devices works fine.)
  2. 2Speak a few sentences about a fictional healthcare or housing story. Don't include real personal info.
  3. 3End the call and wait 1–2 minutes for Granola to produce its summary.
  4. 4Finalize/save the summary in Granola and confirm the file appears in the designated Google Drive folder.
  5. 5Wait 2 minutes. Check Airtable → Storytellers for a new record with the Intake Notes Drive URL filled in.
What you should seeNew record in Airtable Storytellers with Intake Notes Drive URL populated. [POC] Slack: "New intake notes processed: [filename]." If PII was flagged instead: a record in PII Review Queue + a warning Slack message — this is also correct behavior.
Test 4 — Critical Mentions Lead Sourcing
RSS poll → Claude classification → leads in Airtable + Slack
  1. 1Open Critical Mentions and find a recent result (past 24 hours) that looks like a good storyteller lead. Note the headline.
  2. 2Ask Shar to trigger a manual RSS poll right now (rather than waiting for the next hourly run).
  3. 3Wait 2–3 minutes, then check Airtable → Sourcing Pipeline for new records with Lead Source = "critical_mentions".
  4. 4Check #storytelling-ops Slack for a [POC] notification showing how many leads were added.
What you should seeNew records in Sourcing Pipeline with Lead Source = "critical_mentions", an Issue Area, and a Potential Score. [POC] Slack: "X new lead(s) added from Critical Mentions." If no leads appear, the items may have scored low — note the headline and flag it so the scoring can be tuned.
Test 5 — PII Review Queue
Review flagged content and mark it approved, redacted, or discarded
  1. 1Open Airtable → PII Review Queue.
  2. 2If there's a record with Review Status = "pending" (from Test 3 or earlier), open it. Otherwise ask Shar to create a test record.
  3. 3Read the "Raw Content Summary" field — it describes what was flagged without showing the actual sensitive text.
  4. 4Change the Review Status to "approved", "redacted", or "discarded".
What you should seeThe record updates immediately. If you set the status to approved, an Airtable automation will create a new stub record in the Storytellers table within seconds — you then fill in the name, phone, and issue areas from the Drive notes. No automation fires for redacted or discarded.

Results Summary

TestStatusNotes
Test 1 — Cal.comPending
Test 2 — OpenSignPending
Test 3 — GranolaPending
Test 4 — Critical MentionsPending
Test 5 — PII Review QueuePending
Last updated: —
Sourcing Pipeline — Total
— added today
Unsigned Release Forms
release_status = sent
PII Review — Pending
awaiting staff review
Critical Mentions Leads
added in last 24 hours
Approved & Partner-Visible
vetted + release signed

Storytelling Program Automation — Stories Team Guide

Who this is for: Stories team members who will use and test the new storytelling system.
What this covers: What to set up before go-live, how to seed the database with initial data, and how to confirm that each automation is working correctly.

No technical background needed. If something does not go as described, see Something Looks Wrong at the bottom.

What the System Does

The automation stack handles four things that the Stories team currently does by hand:

  1. Cal.com bookings create database records automatically. When a prospective storyteller books an intake interview through Cal.com, a new record appears in Airtable immediately — no manual entry needed.
  2. OpenSign release forms are tracked automatically, with SMS reminders. When you send a release form, the system watches for it to be signed. If it is not signed within three days, the system automatically texts the storyteller a reminder. When it is signed, the record updates instantly.
  3. Granola interview notes are processed and stored automatically. After you finish an intake interview, Granola saves your notes to a designated Google Drive folder. The system picks them up, checks them for sensitive information, and creates an Airtable record with the Drive link attached — without you having to copy anything.
  4. Critical Mentions surfaces new storyteller leads automatically. The system checks your Critical Mentions keyword feeds every hour. Relevant mentions are analyzed by AI and high- and medium-potential leads are added to Airtable's sourcing pipeline, with a summary posted to Slack.

All four automations run on their own once set up. The Stories team manages the Airtable database — the automation fills it.


Before Go-Live: Your Setup Checklist

The following items are yours to complete before acceptance testing begins.

Airtable

  • Confirm you have been added as a user on the Team plan. You should receive an email invitation from Airtable.
  • Confirm you can see the base called "Storytelling Program" after accepting the invitation.
  • Familiarize yourself with the nine tables: Storytellers, Sourcing Pipeline, Vetting Log, Partner Requests, Press Pipeline, Products & Lands, Retention Check-ins, PII Review Queue, and Config.
  • Set up the PII approval automation — when a PII Review Queue record is approved, Airtable should automatically create a Storyteller stub. Steps below.

PII Approval Automation — Setup Steps

This is a one-time configuration inside Airtable. It takes about five minutes.

  1. In the Storytelling Program base, click Automations in the top toolbar.
  2. Click + New automation.
  3. Set the trigger to "When a record matches conditions", table: PII Review Queue, condition: Review Status is approved.
  4. Add action: "Create record", table: Storytellers. Map fields:
    • Intake Notes Drive URL → Source Identifier (the Drive file ID from the queue record)
    • Vetting Status → set to pending
    • Release Status → set to unsigned
  5. Optionally add a second action: "Update record" on the PII Review Queue record — set Reviewed At to the current time.
  6. Name the automation "PII Approved → Create Storyteller" and turn it on.
After approval, the new Storyteller stub will appear in seconds. Open it and fill in the storyteller's name, phone, issue areas, and other details from the Granola notes in Drive.

Cal.com

  • Create or confirm the intake interview event type at cal.com/cap-storytelling/intake — this is the link you will send to prospective storytellers.
  • Confirm with Shar that the Cal.com webhook is connected and active.

OpenSign

  • Create your standard release form template in OpenSign — the document you send every storyteller before they can be used in any external capacity.
  • Send a test document to yourself to confirm the account is active and delivery works.
  • Confirm with Shar that the OpenSign webhook is connected and active.

Granola

  • Install Granola on the computer(s) the Stories team uses for intake interviews.
  • Configure Granola to save notes to the designated Google Drive folder. In Granola settings, look for "Save to Google Drive" and point it to that folder.
  • Make sure everyone knows to inform storytellers at the start of every call that it is being recorded and transcribed for internal use only. This is required.

Critical Mentions

  • Build and save your keyword searches in Critical Mentions — these should cover the issue areas and geographic terms most relevant to the storyteller program.
  • Confirm with Shar that your RSS feeds are connected to the system.

Slack

  • Confirm you are in #storytelling-ops. This is where all system activity notifications will appear.
  • Ping Shar if the channel does not exist — they will create it.

Seeding the Database

Already done. All storyteller records from the Stories team's existing Airtable tables have been synced into this base as of June 6, 2026. You do not need to add initial records manually — your real data is already here.

Going forward — adding new records

For any new storyteller who comes in outside of the automated flows, just create a record directly in Airtable:

  1. Open Airtable and go to the Storytellers table.
  2. Click the + at the bottom of the table to add a new row.
  3. Fill in at minimum: first name, last name, phone number (in the format +12025551234), state, issue areas, and set SMS opt-in to checked.
  4. Set Release Status to unsigned and Vetting Status to pending.

The automated flows (Cal.com, Granola, Critical Mentions) will continue adding new records on their own — manual entry is only needed for one-off additions.


Acceptance Testing

Run these tests in order. Each test tells you exactly what to do, what you should see if it is working, and what to note if it is not.

During POC testing: Text messages will not actually be delivered to phones — they will appear as log entries. Slack messages will appear with a [POC] label. This is intentional and expected.

Test 1 — Cal.com Intake Booking

What this tests: When a prospective storyteller books an intake interview, a new record automatically appears in Airtable and a Slack notification fires.

Steps:

  1. Open cal.com/cap-storytelling/intake in a browser.
  2. Book a time slot using a test name (e.g., "Acceptance Test Booking") and a real or fake email address.
  3. Complete the booking all the way through to the confirmation page.

What you should see within 60 seconds:

  • In Airtable → Sourcing Pipeline: a new record with Lead Source = cal.com, the name you used, and the scheduled time filled in.
  • In #storytelling-ops Slack: a message like [POC] 📅 New intake booking: Acceptance Test Booking followed by the scheduled time and Airtable record ID on separate lines.

What to note if it does not work:

  • Screenshot the Cal.com confirmation page.
  • Note the exact time you completed the booking.
  • Check whether the record appeared in Airtable at all — even without the Slack notification.

Test 2 — OpenSign Release Form

What this tests: When you send a release form, Airtable updates. When it is signed, the record updates again. If it is not signed within three days, an SMS reminder fires.

Part A — Form sent:

  1. In Airtable, find one of the test storyteller records you created during seeding.
  2. In OpenSign, send your standard release form to a test email address you control.
  3. Note the document ID shown in OpenSign after sending.

What you should see within 60 seconds:

  • In Airtable → Storytellers: the record's Release Status changes to sent and the OpenSign Document ID field is populated.
  • In #storytelling-ops Slack: [POC] Release form sent: [name].

Part B — Form signed:

  1. Open the email inbox you sent the test form to.
  2. Open the OpenSign signing link and sign the document.

What you should see within 60 seconds:

  • In Airtable → Storytellers: Release Status changes to signed and Has Signed Release is now checked.
  • In #storytelling-ops Slack: [POC] Release form signed: [name].

Part C — SMS reminder (3-day follow-up):

Ask Shar to trigger the follow-up check manually against a record with Release Status = sent and a sent date older than three days.

What you should see:

  • In #storytelling-ops Slack: [POC] Release form follow-up reminders sent: 1.
  • No real SMS is sent in POC mode — that is expected.

Test 3 — Granola Intake Notes

What this tests: After a Granola-captured interview, notes saved to the designated Drive folder automatically become an Airtable record.

  1. Start a Zoom or Google Meet call with Granola running in the background. (A call with yourself on two devices is fine.)
  2. Speak a few sentences — anything will do, but do not include real personal information.
  3. End the call and wait 1–2 minutes for Granola to produce its summary.
  4. Review the summary in Granola and click to finalize/save it. Confirm the file appears in the designated Google Drive folder.
  5. Wait 2 minutes. Check Airtable → Storytellers for a new record with the Intake Notes Drive URL field populated.

What you should see:

  • New record in Airtable Storytellers with Intake Notes Drive URL filled in.
  • In #storytelling-ops Slack: [POC] New intake notes processed: [filename].

What if content is flagged for PII review:

  • In Airtable → PII Review Queue: a new record with Review Status = pending.
  • In #storytelling-ops Slack: [POC] ⚠️ PII review required: [filename].

This is the system working correctly. Open the PII Review Queue record, review what was flagged, and set the status to approved or discarded.


Test 4 — Critical Mentions Lead Sourcing

What this tests: The system polls your Critical Mentions feeds every hour, classifies mentions with AI, and adds high- and medium-potential leads to Airtable.

  1. In Critical Mentions, identify a recent result (from the past 24 hours) that looks like a good storyteller lead. Note the headline.
  2. Ask Shar to manually trigger one poll cycle right now.
  3. Wait 2–3 minutes, then check Airtable → Sourcing Pipeline for new records with Lead Source = critical_mentions.
  4. Check #storytelling-ops Slack for a [POC] notification showing how many leads were added.

What you should see:

  • New records in Sourcing Pipeline with Lead Source = critical_mentions, an Issue Area, and a Potential Score (high or medium).
  • In Slack: [POC] X new lead(s) added from Critical Mentions.

If the item was scored low: It will not appear in Airtable — that is correct behavior. Note the headline and flag it so the scoring can be tuned.


Test 5 — PII Review Queue

What this tests: The Stories team's ability to review and resolve flagged content.

  1. Open Airtable → PII Review Queue.
  2. If there are records with Review Status = pending (from Test 3 or otherwise), open one. Otherwise ask Shar to create a test record.
  3. Read the Raw Content Summary field — this describes what was flagged, not the actual sensitive content.
  4. Change the Review Status field to one of:
    • approved — the content is fine to use
    • redacted — the content had something removed
    • discarded — do not use this content

What you should see: The record updates immediately. If you set the status to approved, an Airtable automation creates a new stub record in the Storytellers table within seconds — you then fill in the name, phone, and issue areas from the Drive notes. No automation fires for redacted or discarded.


Acceptance Sign-Off

For each test, record the following and share the results with Shar:

TestDid it work?Notes / What you saw
Test 1 — Cal.com intakePass / Fail / Partial
Test 2A — OpenSign sentPass / Fail / Partial
Test 2B — OpenSign signedPass / Fail / Partial
Test 2C — SMS follow-upPass / Fail / Partial
Test 3 — Granola notesPass / Fail / Partial
Test 4 — Critical Mentions leadsPass / Fail / Partial
Test 5 — PII review queuePass / Fail / Partial

Any Fail or Partial results will be looked into before go-live.


Something Looks Wrong

Who to contact: Reach out in #storytelling-tech on Slack.

What to include:

  1. Which test step you were on
  2. The exact time you performed the action
  3. A screenshot of what you expected to see
  4. A screenshot of what you actually saw

Things that are not errors:

  • Slack messages prefixed with [POC] — intentional during POC.
  • No SMS received on a phone — SMS is logged only in POC mode.
  • A delay of up to 60 seconds before records appear in Airtable — normal.
  • No new Critical Mentions leads — correct if there are no relevant new mentions in the feed.

Things that are actual errors:

  • No Airtable record after more than 5 minutes.
  • No Slack notification after more than 5 minutes.
  • An error message appearing in Airtable or Slack.
  • Granola notes not appearing in the Drive folder after 5 minutes.
Table What it's for Filled by
Storytellers Master record for every storyteller — bio, demographics, district, vetting and release status, contact info Automation + staff
Sourcing Pipeline Incoming leads before they become storytellers — Cal.com bookings, Critical Mentions hits, manual referrals Automation + staff
Vetting Log Record of every vetting check — LexisNexis, social media review, findings, outcome Staff
Partner Requests Inbound requests from partner orgs for storyteller matches — issue area, district, media tier, deadline Staff
Press Pipeline Active press pitches — outlet, reporter, pitch status, interview date, media prep links Staff
Products & Lands Completed placements — publication, date, URL, content type, audience reach Staff
Retention Check-ins Scheduled check-ins to keep storytellers engaged — due date, status, updated issue areas Automation + staff
PII Review Queue Interview notes flagged by Comprehend for sensitive content — held here until staff approves, redacts, or discards Automation; resolved by staff
Config System-level settings — used by automations, not for day-to-day editing Tech
#storytelling-ops
Stories team · activity notifications
  • New Cal.com intake booking
  • Release form sent / signed
  • Release form follow-up reminders sent
  • Granola notes processed
  • ⚠️ PII review required
  • New Critical Mentions leads added
  • Inbound SMS from a storyteller
#storytelling-tech
Tech (Shar) · system health only
  • Lambda errors
  • Cron job failures
  • API error rate alerts
CAL Booking confirmed → Sourcing Pipeline record + Slack
SIGN Release form sent → Release Status = sent + Slack
SIGN Release form signed → Release Status = signed, Has Signed Release checked + Slack
SMS Unsigned after 3 days → text reminder sent automatically (daily cron)
GRA Granola notes saved to Drive → Comprehend scan → Storyteller record created or PII queue entry + Slack
CM Critical Mentions RSS polled hourly → Claude scores each item → high/medium leads written to Sourcing Pipeline + Slack
PII PII queue record approved → Airtable automation creates Storyteller stub instantly
Release Status
unsigned — not yet sent sent — awaiting signature signed — complete expired — lapsed, resend needed
Vetting Status
pending — not yet vetted approved — cleared flagged — issue found hold — paused, check back
Lead Status
new — just arrived in_outreach — contacted no_response — no reply yet converted — became storyteller declined — passed
PII Review Status
pending — awaiting staff review approved — ok to use; auto-creates storyteller redacted — used with edits discarded — do not use
Cal.com — intake interview booking page; sends webhook on confirmation
OpenSign — release form sending and signature collection; sends webhooks on status changes
Granola — records and summarizes calls in the background; saves notes to Google Drive automatically
Critical Mentions — media monitoring; saved keyword searches produce RSS feeds the system polls hourly
AWS Comprehend — scans intake notes for sensitive content (names, SSNs, addresses) before anything is stored
Claude (AWS Bedrock) — scores Critical Mentions leads for storyteller potential; never receives PII
AWS End User Messaging — sends SMS reminders for unsigned release forms via toll-free number +1-855-560-6294
Google Drive — stores Granola summaries; the system watches the intake folder for new files
Airtable — everything lives here; the system reads from and writes to it across all four automations

Use Cases

Six concrete scenarios showing exactly what the automation handles — and what it hands back to the team.

1 — From Article to Airtable

Critical Mentions · AI Scoring · Airtable

Maria is a housing advocate in Phoenix who shares her story about a proposed HUD rule change in a local news article. Critical Mentions picks up the article at 9 AM on a Tuesday. By 9:05, Claude has read the full piece, scored Maria as a high-potential lead, tagged her under the Housing issue area, and written her into the Sourcing Pipeline in Airtable — headline, article URL, rationale, and all. A Slack notification lands in #storytelling-ops.

No one on the Stories team was monitoring the news at 9 AM. No one had to. When they open Slack mid-morning, Maria is already there waiting for outreach.

Time between article publication and lead in Airtable: five minutes. Staff time required: zero.

2 — The Booking That Created Its Own Record

Cal.com · Airtable · Slack

A team member reaches out to Maria, shares a Cal.com link, and asks her to book a 30-minute intake interview. Maria picks a slot for Thursday at 2 PM. The moment she clicks Confirm, a webhook fires to the system. Within seconds, a new Sourcing Pipeline record appears in Airtable with Maria's name, email, and scheduled time pre-filled. A Slack notification confirms the booking.

The team member never opens Airtable to enter anything. They simply show up to the Thursday call prepared — the record is already there.

Manual data entry for booking confirmation: none. The calendar and the database stay in sync automatically.

3 — The Interview That Wrote Itself

Granola · Google Drive · Comprehend · Airtable

Thursday's call with Maria runs on Granola in the background. The team member focuses on the conversation — Granola handles the rest. When the call ends, Granola generates a structured summary and saves it to the designated Google Drive folder. The system picks it up within two minutes.

AWS Comprehend scans the notes for sensitive information. The content is clean. The system creates a Storytellers record in Airtable, attaches the Drive link, and posts a Slack confirmation. By the time the team member closes their laptop after the call, Maria has a complete intake record — notes, Drive link, and all — waiting for review.

Time spent copying notes from Granola into Airtable: zero. The system moves the information so the team doesn't have to.

4 — The Flag That Protected Everyone

Granola · Comprehend · PII Review Queue · Airtable

A team member finishes an intake call with James, a Medicaid enrollee in rural Georgia. The conversation was candid — James shared details about a family member's diagnosis, a Social Security number mentioned in passing, and a home address. Granola saves the notes to Google Drive as usual. The system picks them up within two minutes.

This time, AWS Comprehend flags the content: names, a government ID number, and a street address detected. Instead of writing the notes into Airtable, the system holds them. It creates a record in the PII Review Queue with Review Status set to pending, a plain-language summary of what was flagged (entity types, not the sensitive values themselves), and posts a ⚠️ alert to #storytelling-ops: "PII review required: James intake call."

A team member opens the queue record, reads the summary, and decides the content is fine to use — James had consented and the details are relevant. They set Review Status to approved. Airtable's automation fires instantly, creating a storyteller stub for James. The team fills in his contact details and the intake process continues as normal.

Sensitive content never reaches Airtable or AI inputs without a human seeing it first. The system stops automatically — the team decides what happens next.

5 — The Unsigned Release

OpenSign · SMS · Airtable

After the interview, a team member sends Maria a standard release form through OpenSign. The system logs the send, updates her Release Status to sent, and stamps the date. Life gets busy. Maria means to sign it but forgets.

Three days later, at 9 AM, the system runs its daily follow-up check. It finds Maria's record: release sent, unsigned, three days ago. It sends her a text reminder automatically — no staff action required. Maria signs that afternoon. The webhook fires, her Release Status updates to signed, Has Signed Release is checked, and a Slack message confirms the change.

Follow-up reminders sent by hand: zero. Unsigned forms that slip through the cracks: also zero.

6 — The Policy Moment

Critical Mentions · AI Scoring · Airtable · Slack

On a Wednesday morning, Congress introduces a surprise immigration bill. Coverage spikes across local and national outlets. Critical Mentions picks up dozens of new mentions across the immigration keyword feed between 8 AM and noon. The system polls every hour. By lunchtime, Claude has read and scored every relevant result — filtering out op-eds, think-pieces, and pundit commentary, and surfacing only the articles quoting or featuring real people with lived immigration experiences.

The team opens Slack at noon to find a digest: 11 new high- or medium-potential leads added to the Sourcing Pipeline since morning, each with a headline, source URL, issue area tag, and Claude's one-line rationale for the score. The team immediately begins outreach. Without the system, scanning for those leads manually would have taken most of the afternoon — by which time the news cycle would already be moving on.

The system turns a fast-moving news cycle into an advantage instead of a bottleneck.

Storytelling Program Automation
Executive Brief  ·  CAP/AF  ·  June 2026
Page 1 of 2

The Stories team connects real people affected by policy — on healthcare, housing, immigration, and other issue areas — with press, partners, and advocacy campaigns. Finding, vetting, and managing those relationships has been entirely manual: staff scanning news for leads, tracking outreach in spreadsheets, chasing release form signatures, and manually logging interview notes.

This system automates the four most time-consuming steps:

  1. Intake booking (Cal.com) — When a prospective storyteller books an intake interview, a record appears in the database automatically. No staff data entry.
  2. Release form tracking (OpenSign + SMS) — When a release form is sent, the system watches for it to be signed. If unsigned after three days, it texts the storyteller a reminder automatically.
  3. Interview notes (Granola + Google Drive) — After an intake call, meeting notes are automatically ingested, scanned for sensitive information, and linked to the storyteller record — without staff copying anything.
  4. Lead sourcing (Critical Mentions + AI) — The system checks keyword feeds every hour. Relevant mentions are analyzed by AI and high- and medium-potential leads are added to the pipeline, with a summary posted to Slack.

Staff time shifts from data entry to judgment — reviewing leads, vetting storytellers, and managing relationships.

Maria is a housing advocate in Phoenix who reads about a proposed HUD rule change and shares her story in a local news article. Critical Mentions picks up the article at 9 AM. By 9:05, Claude has read it, scored Maria as a high-potential lead, and added her to the sourcing pipeline in Airtable with a summary and issue area tag. A Slack notification lands in the Stories team channel.

A team member reviews the lead, reaches out to Maria, and invites her to book an intake interview through a Cal.com link. Maria books for Thursday. The moment she confirms, a sourcing record is created automatically.

Thursday's call runs on Granola. When it ends, the meeting summary is saved to Google Drive and the system picks it up within minutes, scans it for any sensitive content, and creates a storyteller record with the notes attached. A release form goes out through OpenSign that afternoon. Maria signs it the next morning — the record updates instantly. She is now vetted, released, and ready to be matched with press or partner requests.

Total staff time on data entry for Maria's onboarding: approximately zero.


CAP/AF operates one centralized system. Partner organizations license access to the vetted storyteller pool — they do not receive a separate platform instance. The marginal cost of adding a licensee is near zero; all variable costs are borne by CAP/AF and are largely fixed regardless of how many partners access the database.

CAP/AF Annual Operating Cost

PlatformPurposeCost / Year
AirtableCentral database (Enterprise, 10 users)$6,300
Cal.comIntake booking (10 users)$1,440
GranolaInterview notes (~5 seats)$1,080
OpenSignRelease forms (flat)$120
AWSEC2, Lambda, Comprehend + Claude via Bedrock (25 CM searches, ~88 items/hr)~$1,400
MaintenanceOngoing enhancements (~60 hrs/yr)$6,000
Partner portalHosting & authentication~$900
Total annual operating cost~$17,200

Slack, Google Drive, and Critical Mentions are existing licenses — no additional cost.

Licensing Economics — Story Pool Access

Partner OrganizationsCAP/AF Annual CostCost per Partner
0 (CAP/AF only)~$17,200 / yr
5 partners~$17,200 / yr~$3,440
15 partners~$17,500 / yr~$1,165
30 partners~$18,000 / yr~$600

Minor AWS increases at higher partner counts reflect greater API and query volume. Platform license costs do not change.

Prepared by Digital Technology  ·  CAP/AF Shar Ghavami  ·  sghavami@americanprogress.org  ·  June 2026
Cost Model & Fair Market Value
Storytelling Program Automation  ·  CAP/AF  ·  June 2026
Page 2 of 2
~$8K
One-time build cost
(AI-assisted)
~$90K
5-year total cost
of ownership
Return on investment
over 5 years

All development was AI-assisted (vibe coding). The R&D line reflects actual human hours — traditional development of equivalent scope would require 150–200 hours (~$15,000–$20,000). AI assistance compressed build time by approximately 90%.

WorkApproachHrsCost
Requirements analysisTraditional40$4,000
AI-assisted R&D — architecture, design, development, testingAI-assisted10$1,000
Operationalization & go-live (setup, seeding, config)Traditional20$2,000
Partner portal developmentAI-assisted10$1,000
Total one-time investment~80~$8,000

Labor at $100/hr. Traditional equivalent: ~$20,000–$25,000.

Cost CategoryYr 1Yr 2Yr 3–5Total
Dev & operationalization$8,000$8,000
Platform licenses$10,300$10,300$10,300/yr$51,500
Maintenance & enhancements$3,000$6,900$6,900/yr$30,600
Annual total~$21,300~$17,200~$17,200/yr~$90,100

Year 1 maintenance lower (new system). Years 2–5 include portal operating (~$900/yr).

Market Comparison

A comparable vendor-built solution — custom CRM with automation, AI integration, and a partner portal — typically costs $150,000–$300,000 to build and $30,000–$50,000/year to operate. The 5-year vendor equivalent runs $300,000–$550,000.

This system was built for ~$8,000 — roughly 1/20th of market rate — by combining existing AWS infrastructure with AI-assisted development.

Value Delivered

The system eliminates approximately 8–10 hours/week of staff data-entry work. At $100/hour over 50 working weeks: $40,000–$50,000/year in recovered staff capacity — the system pays for itself within the first year.

5-year value of recovered capacity: $200,000–$250,000 vs. 5-year TCO of ~$86,000.

Constraints to Plan Around

Storyteller pipeline — Value grows with vetted storytellers. Intake throughput is gated by staff interview capacity, not the technology.

Partner portal — Current partner view is read-only Airtable. A dedicated web portal is scoped for Year 1 using AI-assisted development (~$1,000 build, ~$900/yr operating).

Uptime — Webhooks run on AWS Lambda (99.9% SLA). Scheduled jobs on a dedicated server; if it goes down, tasks pause briefly — no data is lost.

Bottom line: Built at 1/20th of comparable market cost through AI-assisted development, this system delivers $200,000–$250,000 in 5-year staff capacity value against a total cost of ownership of ~$90,000 — a roughly 2.5–3× return. It establishes a replicable model for licensing story pool access to partner organizations at near-zero marginal cost per licensee.
Prepared by Digital Technology  ·  CAP/AF Shar Ghavami  ·  sghavami@americanprogress.org  ·  June 2026

Goals & KPIs

Sourcing goals by district (Sage's target: 2 storytellers per priority issue per district) measured against the current storyteller bank, plus the donor KPI set. Snapshot as of July 15, 2026 — regenerated on demand.

162
Storytellers in priority districts
58
District×issue goals met (of 125)
3
Districts with no storytellers yet
25
Priority districts tracked

Sourcing goals by district

cell = # storytellers · target 2 · met 1 0
District# storytellersMedicaidSNAPePTCTariffsUtilities
AZ-01840201
AZ-02310013
AZ-06864202
CO-03110000
CO-05200001
CO-081191202
IA-011063323
IA-02100111
IA-031485563
MI-04600014
MI-071032203
MI-10950203
NC-11820000
OH-07300133
OH-10220022
OH-15200002
PA-01632022
PA-071262436
PA-081344729
PA-101140111
TX-15000000
TX-23000000
TX-35000000
WI-01534112
WI-031766463

Donor KPIs

MetricValue
Reach — traditional media lands≈ 34.7M 2026 YTD · press lands with a reach value (partial)
Reach — new/digital media≈ 5.2M 2026 YTD (partial)
$ behind earned media lands— — only 8 lands have ad spend; source too sparse to total
Unique storytellers landed with press20 2026 YTD
Unique storytellers used by digital20 2026 YTD
Unique storytellers used by partners— — needs Sage's org-classification rule
Unique storytellers used by political entities (candidates, PACs, American Bridge, Porchlight)— — needs Sage's org rule
Storytellers activated38 2026 YTD
Storytellers with multiple product types12 2026 YTD

Reading it: each cell is the count of storytellers in that district tagged with that issue; green = target of 2 met, amber = 1, red = 0. TX-15/23/35 have no storytellers yet — a real sourcing gap. Donor KPIs (reach, $ behind lands, unique storytellers landed) stay "pending" until storyteller ↔ product/land links exist and Sage confirms the counting rule; then they compute here too.

Weekly Progress — Sage's June 22 / 29 Requests

Every point from the June 22/29 change-log block, with how it was resolved and — where Sage left a Week 7/14 note — exactly what happens next and who owns it. As of July 15, 2026 (test environment; real sends stay off until go-live).

Done built & working In progress building, or one UI tidy left Needs a step a UI click or external setup Not feasible / parked Sage owns · Shar owns

Lexis — where I landed (please read)

Digging into automating the Lexis step, the useful realization is that "Lexis" is doing two different jobs for us — with very different costs and feasibility. Before we shop for a tool, I think we should decide how much of each we actually need.

  • (A) Reputational / public-footprint check — what has this person said or done publicly that could come back on CAP? (Old posts, past statements, news coverage, their social accounts.)
  • (B) Formal records — criminal history, litigation, liens, bankruptcies.
OptionCoversAutomatable?Rough costThe catch
LexisNexis (Accurint / Nexis Diligence)A + BEnterprise API onlyHigh — annual contract + per-search, with minimumsPermissible-purpose (GLBA/DPPA) gating + a sales cycle
Thomson Reuters CLEAR / TLOxpA + BEnterpriseComparable to LexisSame compliance gating
Background-check services (Checkr, Certn, Sterling)BYes — clean APIs~$15–50 per checkFCRA-regulated: needs consent + adverse-action; built for hiring
Public-footprint scan (Claude + a news API)A onlyYes — we have most of the plumbingNear-freeDoesn't touch court/criminal records
Court records (PACER, CourtListener, UniCourt)part of BYes; some freeFree to modestFederal-heavy coverage; state courts patchy

My recommendation: for the people we feature — volunteer storytellers, not employees — almost all the real risk lives in (A), and that's the part we can automate right now, cheaply: a Claude-driven scan of their news/web/social footprint that writes a plain-language summary and flags into the vetting log, with a person making the call. It reuses the Critical Mentions plumbing we already have. (B) — true criminal/court records — is the expensive, compliance-heavy piece, and it's the main thing Lexis is for. If we don't strictly need that depth on a volunteer storyteller, we may not need a Lexis replacement at all.

For Sage — two questions so I take the right path: (1) what is this vetting mainly protecting against — reputational / public statements (A), or do we genuinely need formal criminal/court records (B)? (2) Want me to pull firm, current pricing on the top one or two options, or is this enough to decide direction? If it's mostly (A), we're basically there for near-zero cost.

Storytellers tab

Sage's pointResolutionStatusResponse — what happens & who
List in mothership order, with assigned numbersnumber_assigned = the mothership's ID number, on all matched records.DoneShar Done — I pulled your new "ID number" column into number_assigned on all 809 records. To see them in that order, sort a view by it (Airtable only sets record order through a view, not the API).
Why two columns for first & last name?Kept both, plus a combined full_name.Answered
Add all the mothership columns (even if empty)All added (bio, vetted_by, best_for, lexis/social fields, product_interests, etc.).Done
"Product interests" multi-choice (mothership options)Multi-select with the mothership options.DoneSage Share that form's response sheet with me, and I'll wire the checked options to auto-fill product_interests — same setup as the SMS opt-in below.
"Best for" multi-choice (mothership options)Multi-select with the mothership options.Done
SMS opt-in auto-populates from the two Google FormsField exists; form→Airtable link needed.Needs a stepSage share the two forms' response sheets (or grant our service account access), then Shar I build a small sync that matches by email and sets the opt-in. About 2–3 days once I have access.
Media experience = mothership optionsCollapsed to Beginner / Intermediate / Advanced.DoneShar Done — I re-seeded it to just Beginner / Intermediate / Advanced (folded moderate & trained into intermediate, experienced & TV-ready into advanced). I'll clear the leftover old options in the field editor.
How is last contact date measured?From the legacy engagement date, then stamped on each contact.Answered
Difference between legacy_tier and storyteller_tier?storyteller_tier = current; legacy_tier = imported.Needs a stepShar Got it — I'll delete legacy_tier in the field editor (their API can't delete fields). Nothing else uses it.
issue_areas match the mothership exactlyMothership options on the field; 813 records remapped.DoneShar Done — the mothership options are on the field and all 813 records are remapped. I'll clear the 12 old lowercase options in the UI.
leadership_interests as multi-select, not a listOptions ready; field-type change is UI-only.Needs a stepShar You're right — it's a manual field-type change (their API can't convert a field's type). I'll switch it to multi-select with the 6 mothership options in the editor.
Add lexis-vetted checkbox (auto from vetting log)record_sync copies it from a linked vetting-log row.Done
Add lexis-flags specifics (auto from vetting log)record_sync copies it from a linked vetting-log row.Done
"Raw notes" = verbatim Q&A, not bio summariesRe-seeded from the mothership's real Raw notes field.DoneShar Fixed — good catch. The seed had pulled the Bio field; I re-loaded raw_notes from the mothership's actual "Raw notes" field on 808 records, so they're verbatim now.
Talking-points / intake-notes Drive links — manual or auto?intake_notes auto-set by Granola; talking_points manual.Answered

Sourcing pipeline

Sage's pointResolutionStatusResponse — what happens & who
Claude / Critical Mentions identify each districtLeads auto-district-stamped.Done
We don't need immigration storiesExcluded by the six-tag gate.Done
Suggested-name column at the beginningNow its own column.DoneShar Done — I added a suggested_name column and pointed Critical Mentions at it (it had been writing the name into notes).
Claude + Lexis to find contact infoNo Lexis API available.Not feasibleSage/Shar There's no Lexis API for us, so I can't automate it through Lexis at any price. See the Lexis section at the top of this tab for the full options + my recommendation — the short version is we can automate the reputational check cheaply now, and the formal-records piece is the vendor + cost call we'd make together.
Add phone-number columnAdded.Done
Add email columnAdded.Done
Add social-media-account columnAdded.Done
Add article-date column, auto by ClaudeAdded; auto-stamped from the feed item's date.Done
Issue areas match the storytellers mothership dbUses the six priority tags (your later call).Done (superseded)
Edit Critical Mention inputs for these policies & messengers25 district searches + six-tag classifier.Done

Vetting log · Partner requests · Press pipeline

Sage's pointResolutionStatusResponse — what happens & who
Vetting log: outcomes flow into storyteller columnsrecord_sync copies a linked, completed row's outcomes.Done
Vetting log: add "best for" columnAdded.Done
Partner requests: "partner-org-name" mixed with lexis flagsCleaned on our side.DoneShar Fixed on our side — the mess is in the mothership itself: its Requests "Partner" column has lexis flags pasted into it. I moved 76 of those flag values out of partner_org_name into notes so the field is clean. A full fix means cleaning that column in the mothership too.
Partner requests: media tier = national / state / districtCorrect options added.Done · UI tidyShar The right options are in; I'll remove the old regional/local in the editor and it'll read clean.
Partner requests: request status match the mothershipMothership Progress options added.Done · UI tidyShar Effectively done — the mothership status options are added; I'll delete the old ones in the UI (a couple of minutes).
Press pipeline: entries populate the storyteller core recordrecord_sync appends a linked land to placements.Done
Press pipeline: pitch-status options (her 7)Added.Done · UI tidy
Press pipeline: national + state tracker per stateGrouped Airtable views.Needs a step

Products & lands · Retention · Partner tracker

Sage's pointResolutionStatusResponse — what happens & who
Products: content-type multi-choice (her list)Her options added.Done · UI tidy
Products: issue area matches the storytellers dbMatches.Done
Products: add impressions, $ spendAdded impressions and ad_spend.Done
Products: auto Slack update on published productproduct_publish_notify posts each land + thank-you nudge.Done
Retention: new-story-notes auto-populate raw notes / biorecord_sync appends a linked check-in's notes.DoneShar Yes, shipped — it runs when an associate links the check-in to the storyteller (new storyteller field); the notes then append to their raw notes automatically.
Retention: column for leadership-pipeline updatesAdded.Done
Partner tracker: pull from the Partner onboarding sheetParked per your note.ParkedSage Parked per your note — nothing to do right now.
Partner tracker: add org type (multi-choice)Added.Done
Partner tracker: add "Gaps" (long-text)Added.Done
Partner tracker: national + state tracker per stateGrouped Airtable views.Needs a step

Pitching tracker · Distribution · Misc

Sage's pointResolutionStatusResponse — what happens & who
Pitching tracker shouldn't exist — fold into press pipelineDelete the table in the UI.Needs a step
Distribution projects: no editsNothing needed.Done
Granola for phone calls / Zoom, not just Teams?Zoom/Meet/Teams direct; phone via speaker + record.AnsweredSage For Zoom/Meet/Teams, Granola joins the call directly. For a phone screen it can't dial in, so the practical way is phone on speaker next to the computer with Granola capturing + transcribing. Happy to sit with the team to lock in the exact setup.
Timeline for a searchable partner systemThe partner portal is live.Done
Reminder to associates to thank storytellers on a land/publishBuilt into product_publish_notify.Done
KPI dashboard updatesTables built; dashboard is a UI Interface.Dashboard UI

To ADD

Sage's pointResolutionStatusResponse — what happens & who
Populate existing records from the Google FormNeeds the form wired to Airtable.Needs a stepSage For now, enter responses manually. To make it automatic, share the form's response sheet with me and Shar I'll build the sync (same as the SMS opt-in).
"For donors" KPI tableCreated + seeded (9 KPIs).Table done · dashboard UI
Goals tracker (per-district targets, press lands, vetted/week) + dashboardTable + "2 of each" targets seeded (25 districts).Table done · dashboard UIShar The table and the "2 of each" targets are set. What's left is the visual goals dashboard (an Airtable Interface) — I'll build that in the UI around go-live.

Summary: every column and dropdown is in place; the mothership ID-number order, verbatim raw notes, collapsed media tiers, and the partner-org-name cleanup from Sage's 7/14 notes are done; the vetting/press/retention records now auto-flow onto the storyteller record. What's left is a handful of Airtable UI tidies (retiring old options, one field-type conversion, views + Interface dashboards, deleting the old pitching tracker), two external integrations (Google Form → Airtable, the published-products Slack channel), and one not-feasible item (Lexis).

What's left — who owns what

For Sage — a few things need you

  • For SageGoogle Form → Airtable (product_interests, the SMS opt-in, and populating existing records from the intake form). The fields all exist; to auto-fill them, open each intake form → Responses → link/create its Google Sheet → Share that sheet with our service account (I'll send you the address), or just send me the sheet link. Then I build a small sync that matches by email and fills the fields — about 2–3 days once I have access. Until then, entering responses by hand works.
  • For Sageturn on photo collection. I built the upload pipeline (a submitted photo auto-attaches to the right storyteller by email). To switch it on: in Airtable open the photo_submissions table → + Add view → FormShare form → copy the link and send it to me (I'll set it as the destination the request email points to). And give the photo-request email copy a quick read. (Adding a view needs Airtable "creator" access — if you don't have it, tell me and I'll add it in one click.)
  • For Sagenational/state trackers + the goals/KPI dashboard. The data's all there, and the portal's "Goals & KPIs" tab already shows it live. If you also want it inside Airtable, that's a team UI step: create grouped views (group by state / district) and an Interface dashboard. Tell me how you'd like them grouped and I'll write out the exact clicks — or we lean on the portal view and skip it.
  • For Sagethree open questions to close the last items: (1) issue_areas cleanup — the field now mirrors the mothership exactly, which means its duplicates/typos too ("Health care" vs "Healthcare", "Social security" vs "Social Security", a stray "Racial justce"). Merge them into a clean canonical list, or keep them exactly as the mothership has them? (2) $ behind earned media — is ad spend tracked anywhere reliable? Only 8 of ~1,800 lands carry a value, mostly free-text, so I can't total it. (3) partners vs political entities — I need your rule for which orgs count as a partner vs a political entity (candidates, PACs, American Bridge, Porchlight) to compute those two donor KPIs.

On me (Shar)

  • SharOpenSign signature test. The release-form webhook is built and verified end-to-end; I just need to confirm the signature format against one real signed document and it's done.
  • SharSMS text reminders — pending regulatory approval. The carrier 10DLC registration that lets us text is in progress and gated by a compliance review we don't control, so SMS launches simulated and flips on once it clears. Everything else can go live without it.
  • Sharthe Airtable field tidies from your 7/14 notes (retiring old dropdown options, converting leadership_interests to multi-select, deleting the old pitching tracker). These are manual field-editor clicks their API can't do; I'm working through them.

Let's decide together

  • For Sage & Sharthe published-products Slack channel. The auto-announcement is built; before I point it anywhere I want to understand how you'd like the flow to work in Slack (which channel, what it says, who gets tagged). Let's lock it in at our next meeting.

Feature Status

A whole-system, feature-level snapshot: what's working, what's in progress, what's waiting on a decision, and what's still ahead — with who leads each piece.

As of July 12, 2026 Environment Test (POC) — nothing sends to storytellers yet Target go-live week of July 20
11
Done & working
2
In progress
5
Blocked
3
Not started
Shar · Technical — builds, tests & deploys Sage · Config & business — decisions, content & setup

Done & working

11 features · verified in test
FeatureWhat it doesLead
Storyteller databaseCentral record of every storyteller and partner request. 813 storytellers and 321 partner requests migrated from the legacy base.Shar
Media monitoringScans local news every hour for stories on the six priority issues in target districts, auto-tags each, and flags likely messengers.Shar
Notes → demographicsGranola interview notes are captured automatically; suggested demographics are queued for staff to approve — never written without a human review.Shar
Intake schedulingA Cal.com booking automatically creates a sourcing lead with the person's name, time, and contact. (Prod booking page is a Sage setup item.)Shar
Partner portalThe web view partners use to browse approved storytellers, now pointed at the new database.Shar
Onboarding emailSends a welcome email automatically once a storyteller's vetting is marked complete. (Real sends begin at go-live.)Shar
Impact scoringAI rates each approved storyteller's readiness for partners and press, as a score and a high / medium / low tier.Shar
Re-vetting & retention alertsFlags storytellers overdue for re-vetting or a check-in so staff can follow up.Shar
Partner outreach draftsTurns a pasted partner request into a ready-to-edit outreach draft for staff.Shar
Weekly pitch trackerPosts a weekly press-pipeline summary to the team Slack channel.Shar
Activity notificationsLive updates to the ops and tech Slack channels as bookings, signings, and leads come in.Shar

In progress

2 features
FeatureWhat it does · what's leftLead
Media tag tuningRefining the six tags and district keywords against real results to cut noise — off-topic stories, press releases, out-of-area items.SageShar
Release-form trackingSigning status auto-updates the record (sent → signed), matching by document or signer email. Connection is built; needs one live OpenSign test to confirm the signature format.Shar

Blocked — waiting on a decision or setup

5 features
FeatureWhat it does · what it's waiting onLead
Text messages (SMS)Unsigned-form reminders, retention check-ins, and logging of storytellers' replies. Built and tested — waiting on carrier 10DLC registration, which needs the business support mailbox.SharSage
Photo collectionAutomatically emails storytellers who have no photo, asking them to submit one. Built and tested — needs an upload location and sign-off on the message wording.Sage
Legacy impact data1,811 rows of legacy "Placements" impact / circulation data are not yet migrated. Decision needed: does the team rely on it in the new system?Sage
Extra intake fieldsProduct- and leadership-interest fields for storyteller records. Needs the list of options to use.Sage
Production go-liveFlip the whole system from test to live so real emails, scoring, and syncing run. Targeted for the week of July 20.SharSage

Not started — planned / future

3 features
FeatureWhat it doesLead
Branded email + opt-outA polished, branded email template with one-click unsubscribe, for the full email program. Planned for the pre-launch hardening pass.Shar
Searchable photo bankAuto-tagging storyteller photos (person, setting, quality) to make the partner image bank searchable. Future enhancement.Shar
Reporting dashboardsKPI charts and program dashboards on top of the database. Future.SharSage

How to read this. "Done & working" means built and verified in the test environment — real messages to storytellers stay off until go-live. The remaining blockers are external (carrier registration), business decisions (Sage), or the scheduled production cutover.