← back to Norma Sdcc Pitch
data/features.json
1442 lines
{
"companies_are_databases": {
"headline": "The big mental shift — your org is now a database.",
"kicker": "If you only remember one thing from this pitch",
"body": "Until recently, an organization was a website + an email account + people. The website was a brochure. The email was where work happened. The people held the knowledge in their heads.\n\nThat era is ending. In the AI era, every organization is a DATABASE — a structured store of who you know, what you've said, who you've helped, what worked, what failed — that humans AND AI agents can query, update, and act on.\n\nThe organizations that win in the next 5 years are the ones that treat themselves as databases first, websites second. Your knowledge stops dying when staff leaves. Your past statements become searchable. Your borrower stories become assets, not buried email threads. Your coalition map becomes living, not a stale Google Doc.",
"implication_for_sdcc": "SDCC's most valuable asset is not the studentdebtcrisis.org website. It's not even Natalia's Rolodex. It's the structured database of every borrower SDCC has ever helped, every statement SDCC has ever published, every coalition relationship SDCC has ever built — IF it exists in a form that can be searched, queried, and acted on. Right now most of that is stuck in Gmail, Google Docs, and people's memories. Norma's job is to extract it, structure it, and let SDCC USE it.",
"shift_table": [
{ "before": "Website (brochure)", "after": "API (queryable, updatable)" },
{ "before": "Email (work happens here)", "after": "Triage layer (work GETS DECIDED here, but happens in the database)" },
{ "before": "People (hold knowledge in heads)", "after": "People (decide; the database remembers)" },
{ "before": "PDFs of past reports", "after": "Searchable archive with citations" },
{ "before": "Coalition Google Doc, stale", "after": "Live power map, updated by agents" },
{ "before": "Borrower stories in email threads", "after": "Structured database — searchable by program, geography, urgency" }
]
},
"priorities": {
"headline": "Top 5 priorities — what SDCC needs FIRST",
"intro": "These are the highest-leverage problems we solve first. Not 'cool AI features' — actual SDCC pains, in order of impact.",
"items": [
{
"id": "p1",
"rank": 1,
"title": "Email coordination across the team",
"icon": "📬",
"the_pain": "Three staffers, one info@ inbox. Who replied to which borrower? Who's already followed up with which journalist? Who's the lead on the Lumina application? Right now SDCC tracks this in shared mental models — i.e. you guess, you check Slack, you ask Sabrina.",
"the_solution": "Norma is the source of truth for every conversation. When a message comes in, it's claimed by a staffer (or auto-assigned). Every reply is logged. Every follow-up is scheduled. Anyone on the team can see who's handling what, when last touched, and what was said.",
"how_norma_helps": [
"Auto-assignment by topic — borrower questions → Sabrina; press inquiries → Natalia; grants questions → board ops.",
"'Claim' button on every conversation so two people don't reply to the same journalist.",
"Follow-up reminders 3/7/14 days after a sent reply.",
"Single search across every conversation — 'what did we tell journalist X last month?'"
],
"agents_skills": ["gmail-triage", "audit-trail", "pulse-briefing"],
"before_after": {
"before": "Sabrina replied to a journalist Tuesday. Natalia replied to the SAME journalist Wednesday with a slightly different stance. The journalist published the inconsistency.",
"after": "Wednesday Natalia opens the thread, sees 'Sabrina replied 22h ago' with the full reply quoted. Natalia adds a follow-up that builds on it."
}
},
{
"id": "p2",
"rank": 2,
"title": "Inbound emails — the 400-message inbox",
"icon": "📥",
"the_pain": "info@studentdebtcrisis.org gets 200-400 messages a day. Some are borrower help requests, some are press inquiries, some are coalition partners, some are spam. Triage takes hours. Important messages get buried.",
"the_solution": "Every inbound message gets classified the moment it arrives. By topic (borrower help, press, vendor, coalition), urgency (default crisis, garnishment notice, casual question), and required action. A draft reply is pre-written. The 400 messages become 20-30 priority items by 7am.",
"how_norma_helps": [
"Classifier reads every message and tags it: type / urgency / who-should-handle.",
"Drafts a first-pass reply in SDCC's voice — staffer reviews, edits, sends.",
"Routes high-urgency to a Slack channel (default-crisis borrower stories, journalists on deadline, etc).",
"Surfaces every email containing a borrower story → tags by debt type, geography, anonymizability — building the structured story database."
],
"agents_skills": ["gmail-triage", "borrower-story-classifier", "pulse-briefing"],
"before_after": {
"before": "Sabrina at 9am: 'I have 387 unread. I'll start with the most recent and hope.'",
"after": "Sabrina at 9am: 'I have 22 priority drafts. Norma triaged the other 365 — 240 into FAQ, 80 into newsletter signup, 45 into vendor pitches I'll never read.'"
}
},
{
"id": "p3",
"rank": 3,
"title": "Graphics — social cards, press graphics, mockups",
"icon": "🎨",
"the_pain": "Every campaign needs visuals. SDCC doesn't have a designer on staff. Canva works but takes hours. Hiring a designer per campaign is expensive and slow. Most petitions launch with no graphic and underperform.",
"the_solution": "Norma generates campaign-ready graphics from a topic prompt: social cards (Instagram + X + Bluesky), petition heroes, press release banners, infographics. SDCC's brand colors + typography baked in. Generated in 30 seconds per asset. SDCC reviews + tweaks (or kicks back for regeneration) before publish.",
"how_norma_helps": [
"AI image generation tuned to SDCC's visual brand (royal blue + civic, no piggy-bank clipart).",
"Templates for: petition launch card, press release banner, social media quote card, infographic, action alert.",
"One-click generate 5 variants per asset, pick the best.",
"Auto-resize for every platform: 1080x1080 IG, 1200x628 X header, 1080x1920 stories, etc."
],
"agents_skills": ["graphic-designer", "petition-generator", "reels-producer"],
"before_after": {
"before": "Sabrina spends 90 minutes in Canva making a social card. Or skips it. Or asks a volunteer who delivers in 4 days.",
"after": "Sabrina types '/social-card SAVE rollback'. Five variants in 30 seconds. Picks one. Tweaks the headline. Published in under 2 minutes."
}
},
{
"id": "p4",
"rank": 4,
"title": "studentdebtcrisis.org on Wix — making it work harder",
"icon": "🌐",
"the_pain": "The Wix site is a brochure. It tells people who SDCC is but doesn't capture borrower stories systematically, doesn't auto-route press inquiries, doesn't surface live data (signature counts, recent wins), doesn't integrate with the rest of SDCC's stack.",
"the_solution": "Wix becomes a smart front door. Forms route to Norma for classification + draft replies. Live signature counts pulled from Norma. Recent wins surface automatically. Borrower-story intake form structures the data on the way in (vs unstructured email threads). Pulse brief embedded for transparency.",
"how_norma_helps": [
"Wix forms POST to Norma's `/api/wix-webhook` → message arrives pre-classified in info@ inbox.",
"Wix Velo (Wix's code IDE) calls Norma's read APIs to embed live data — petition counts, recent press hits.",
"Norma's Pulse dashboard embeddable as an iframe on a private '/team' page only staff see.",
"Donation thank-you triggers personalized follow-up via Norma's outreach pipeline."
],
"agents_skills": ["wix-integration", "borrower-story-classifier", "gmail-triage"],
"before_after": {
"before": "Wix contact form → emails info@ as a generic 'You have a new submission' → buried in 400 messages → forgotten.",
"after": "Wix contact form → POSTs to Norma → classified (borrower help / press / etc) → draft reply ready → tagged by debt type → in Sabrina's priority queue by 7am."
}
},
{
"id": "p5",
"rank": 5,
"title": "Adding UX + UI capability INTO Wix",
"icon": "✨",
"the_pain": "Wix's default templates look fine but generic. SDCC's site doesn't feel as urgent or distinctive as the work demands. Hiring a Wix designer per change is slow and expensive.",
"the_solution": "Wix lets you customize via the Editor (no-code) for visual changes and Velo (Wix's JavaScript dev environment) for interactive UX. Norma's UI patterns can be lifted into Wix piece by piece — Pulse-style daily brief blocks, urgency-tagged story cards, accessible WCAG-AA buttons, the lot.",
"wix_specific_steps": [
"Step 1 — Enable Wix Velo (Dev Mode → Enable Velo). Gives you a code IDE inside the Wix Editor.",
"Step 2 — Add data collections in Wix's CMS. Treat them like Postgres tables — 'BorrowerStories', 'Petitions', 'PressMentions'. Each row is structured, queryable.",
"Step 3 — Build Repeater components in Wix that pull from those collections — basically Norma-style grids inside Wix.",
"Step 4 — Add Velo code blocks that call Norma's read APIs via fetch(). E.g. live signature count on a petition page.",
"Step 5 — Replace generic Wix templates with custom layouts using Wix's Grid + Flexbox containers. Borrow Norma's spacing/typography tokens.",
"Step 6 — Add accessibility: every image gets alt text, every button has focus state, color contrast WCAG AA minimum. Wix has a built-in a11y checker — use it."
],
"how_norma_helps": [
"Norma's design system (colors, typography, spacing) ships as a single CSS file you can paste into Wix's Custom CSS panel.",
"Norma exposes read-only API endpoints Wix Velo can call — no DB credentials needed in Wix.",
"Wix MCP server (planned) lets Claude Code edit Wix pages from terminal — same workflow as editing Norma."
],
"agents_skills": ["wix-integration", "ui-ux-designer", "graphic-designer"],
"before_after": {
"before": "Wix site looks like every other Wix template. Generic typography, default spacing, no live data.",
"after": "Wix site has SDCC's actual brand, lives data from Norma (signature counts, recent press), and matches the team workflow. Visitors feel the urgency."
}
}
]
},
"why_custom_crm": {
"headline": "Why build a custom CRM instead of using Salesforce / EveryAction / HubSpot?",
"intro": "The most common objection. Real answer: off-the-shelf CRMs were built for sales teams, not borrower advocacy. SDCC's work doesn't fit their schema, and the AI era makes that mismatch worse.",
"the_short_answer": "Off-the-shelf CRMs model 'leads → opportunities → closed deals.' SDCC models 'borrower in crisis → story tagged → policy lever → press hit → coalition activation.' Same word ('CRM'), totally different shape. Forcing SDCC into a sales schema costs more, slows the team, and locks the data away.",
"comparison": [
{
"axis": "Cost (5 staff, year 1)",
"salesforce": "$2,400-$9,000 + Einstein add-on ($1,000+/mo) + implementation consultant ($30k)",
"everyaction": "$5k-$25k base + per-user + onboarding",
"hubspot": "$1,200-$14,400 + AI add-ons",
"norma": "$2,400-$9,600/year all-in (incl. AI inference + hosting)",
"winner": "norma"
},
{
"axis": "AI native",
"salesforce": "Einstein is bolted on. Doesn't know SDCC's voice. Extra cost.",
"everyaction": "Limited AI; mostly templated automations.",
"hubspot": "Breeze AI exists but is generic marketing-flavored.",
"norma": "AI is the substrate. Claude is the model. SDCC's voice library + KB are first-class.",
"winner": "norma"
},
{
"axis": "Data ownership",
"salesforce": "Your data lives in their schema. Export costs extra. Lock-in is the business model.",
"everyaction": "Better than Salesforce on export, still proprietary.",
"hubspot": "Lock-in by integration sprawl.",
"norma": "Postgres on SDCC's tenancy. Daily SQL dump exportable. Standard formats (CSV/JSON) on day 1.",
"winner": "norma"
},
{
"axis": "Borrower-story modeling",
"salesforce": "Force-fit into 'Contact' or 'Lead' object. No native debt-type/urgency/anonymizability fields.",
"everyaction": "Closer fit (designed for advocacy) but still record-based, not story-based.",
"hubspot": "Generic contact records. Definitely not modeled for this.",
"norma": "BorrowerStory is a first-class object. Structured by debt type, urgency, program, anonymizability, consent status.",
"winner": "norma"
},
{
"axis": "Speed of change",
"salesforce": "Workflow change = consultant + months + committee.",
"everyaction": "Faster than Salesforce, still gated by their roadmap.",
"hubspot": "Marketing automation strong; nonprofit-specific changes slow.",
"norma": "Workflow change = code commit. Hours, not months.",
"winner": "norma"
},
{
"axis": "Community + ecosystem",
"salesforce": "Huge consultant + admin community. Lots of tutorials. Industry standard.",
"everyaction": "Strong nonprofit community.",
"hubspot": "Massive community.",
"norma": "Tiny community (it's bespoke). Documentation lives in this app + Steve's brain.",
"winner": "off-the-shelf"
},
{
"axis": "Donations + bulk email",
"salesforce": "Strong with Pardot/Marketing Cloud, expensive.",
"everyaction": "BEST in class for nonprofit donations + bulk email.",
"hubspot": "Marketing-first, donation tooling weaker.",
"norma": "Not focus. Should integrate with EveryAction or ActBlue, not replace.",
"winner": "everyaction"
},
{
"axis": "Compliance + audit",
"salesforce": "Strong audit trail, expensive to access.",
"everyaction": "Adequate for nonprofit compliance.",
"hubspot": "Marketing-grade audit.",
"norma": "Append-only audit log. Every AI decision logged with model + prompt + actor + timestamp. Regulator-ready.",
"winner": "norma"
}
],
"the_hybrid_play": "Don't replace EveryAction. SDCC keeps EveryAction for donations + bulk email (where it's actually best in class). Norma owns the advocacy-specific work no off-the-shelf tool handles — borrower stories, press response, coalition map, AI drafting, inbox triage. Two tools, clear boundaries, no overlap.",
"honest_risks": [
"Maintenance burden — SDCC needs a technical owner (Steve, initially). Off-the-shelf is more turnkey.",
"If the technical owner leaves, continuity risk. Mitigation: full Postgres + code + voice library export at any time, plus 30-day handoff clause.",
"No huge user community asking 'how do I do X'. Mitigation: Norma's interface mirrors Gmail patterns, so staff onboarding is faster than enterprise CRMs anyway.",
"Standard integrations (Mailchimp, ActBlue, Slack) need to be built per request — not pre-configured.",
"Bus factor — Norma's success depends on a small team's ongoing maintenance. The off-the-shelf path has 'somebody else's problem' built in."
],
"the_real_question": "The real question isn't 'Salesforce vs Norma.' It's 'do we want our CRM to fit our work, or do we want to bend our work to fit a CRM?' Salesforce works for sales teams because its schema matches their work. SDCC's schema doesn't match any off-the-shelf product. Either bend the work or build the tool."
},
"wix_integration": {
"headline": "Wix ↔ Norma — concrete integration guide",
"intro": "Wix is fine. It's where SDCC's site lives. Here's exactly how to make it work with Norma's data + workflows.",
"options": [
{
"name": "Forms → Norma webhook (start here)",
"difficulty": "Easy",
"time": "30 minutes",
"steps": [
"In Wix Editor, open any contact form → Settings → Submission tab.",
"Set 'Webhook URL' to `https://norma.studentdebtcrisis.org/api/wix-webhook?form=contact` (replace with your Norma URL).",
"Test the form. The submission lands in Norma's inbound queue pre-classified.",
"In Norma, view incoming Wix submissions at /pulse → Inbound tab."
]
},
{
"name": "Live data → Wix Velo fetch (read-only widgets)",
"difficulty": "Medium",
"time": "1-2 hours per widget",
"steps": [
"In Wix Editor, enable Dev Mode (top bar → 'Dev Mode' → Enable Velo).",
"Add a Text or Repeater element to your page. Give it an ID like #petitionCount.",
"Open the Code Panel (right side). Add: `import {fetch} from 'wix-fetch'; $w.onReady(async () => { const r = await fetch('https://norma.../api/petitions/topics?limit=5'); const data = await r.json(); $w('#petitionCount').text = String(data.topics.length); });`",
"Publish. Wix now pulls live counts from Norma on every page load."
]
},
{
"name": "Embed Norma's Pulse dashboard (private team page)",
"difficulty": "Easy",
"time": "15 minutes",
"steps": [
"Create a new Wix page at /team. Set page permissions: 'Members only' + restricted to SDCC staff emails.",
"Add an HTML Embed element (Wix Editor → Add → Embed → HTML iFrame).",
"Set src to `https://norma.studentdebtcrisis.org/pulse` and add cookie passthrough.",
"Publish. Staff visit studentdebtcrisis.org/team and see live Pulse dashboard inside Wix."
]
},
{
"name": "Borrower story intake — structured from the start",
"difficulty": "Medium",
"time": "2 hours",
"steps": [
"In Wix CMS, create a Collection called 'BorrowerStories' with fields: debtType (dropdown: federal/private/parent-PLUS), urgency (dropdown: low/medium/crisis), state, story (long text), consentForPress (boolean), email.",
"Build a form in Wix that writes to this collection.",
"In Velo, on form submit, ALSO POST the structured data to Norma's `/api/borrower-stories/intake`.",
"Norma de-duplicates by email + classifies further (PSLF eligible? In default? Anonymizable?).",
"Result: every story enters SDCC's database structured + with email triage already started."
]
},
{
"name": "Wix CMS as a write-back target",
"difficulty": "Harder",
"time": "1 day",
"steps": [
"Generate a Wix API key (Wix Dashboard → Settings → Headless Settings).",
"Store the key in Norma's env: `WIX_API_KEY=...`.",
"When Norma generates a new petition, it can POST to Wix CMS to create a corresponding Wix page automatically.",
"Risk: Wix changes are slow to propagate. Only do this for non-time-sensitive content."
]
}
],
"wix_ux_ui_principles": [
{ "title": "Stop using stock photos of stressed students", "detail": "Every other debt nonprofit uses them. SDCC's distinctiveness comes from REAL borrower stories with real names + faces (when consented). Wix supports custom photo galleries." },
{ "title": "Live counters > static hero text", "detail": "'12,847 borrowers helped this year' updating in real-time beats '15 years of advocacy.' Velo + Norma API makes this trivial." },
{ "title": "Mobile-first or you're invisible", "detail": "60%+ of debt-distressed users hit the site from phone. Wix's mobile editor is separate — actually test it." },
{ "title": "Accessibility is non-negotiable", "detail": "Many SDCC supporters have disabilities or are under cognitive load (debt stress). WCAG AA, every page. Wix has an a11y checker — use it before publish." },
{ "title": "Three primary actions, not seventeen", "detail": "Every page should have a clear hierarchy of 'what we want you to do here.' Most Wix templates have too many CTAs." },
{ "title": "Show, don't tell", "detail": "Don't write 'we help borrowers' — show a borrower story with name + photo + outcome. Stories convert; abstractions don't." }
]
},
"reluctant_adopter": {
"headline": "If you're skeptical of AI — this section is for you.",
"intro": "You don't have to love AI. You don't have to believe the hype. You just need to know what it does for your Tuesday at 2pm when the inbox is at 400 and a journalist is calling.",
"objections": [
{
"objection": "\"I don't trust AI to write in my voice.\"",
"answer": "You shouldn't — yet. The first month is AI proposes, you edit, you approve, you send. Every reply, every statement, every social post passes through your hands before it goes out. By the time you trust it (week 3-4), it's because you've personally approved hundreds of drafts and watched it learn your voice. Trust is earned, not assumed.",
"before_after": { "before": "Sabrina writes 40 replies/day from a blank cursor. Each takes 4-7 min.", "after": "Sabrina reviews 40 drafts that already exist. Each takes 60 seconds — most get sent as-is, some get a 10-second edit." }
},
{
"objection": "\"I'd rather hire a person.\"",
"answer": "If SDCC has the money for a full-time hire, do that AND this. A part-time hire costs $30K+/year. Norma costs $200-800/month. They solve different problems — hires bring judgment + relationships; AI absorbs typing + research. The orgs that win do both.",
"before_after": { "before": "Hire $40K/year part-timer to triage inbox. Takes 6 weeks to onboard.", "after": "Spend $400/month on Norma. Live in 2 days. Hire the part-timer for borrower 1:1s instead." }
},
{
"objection": "\"What if it hallucinates and embarrasses us?\"",
"answer": "It will hallucinate sometimes. That's why every outbound message goes through a human. The risk isn't AI making a mistake — it's a tired staffer at 11pm hitting send without reading carefully. Norma's audit trail and citations actually make THAT mistake LESS likely.",
"before_after": { "before": "Sabrina at 11pm sends an email with a typo'd statistic.", "after": "Sabrina at 11pm sees the draft has a citation footer; clicks the cited source; catches the typo before send." }
},
{
"objection": "\"I'm not a tech person.\"",
"answer": "You don't have to be. The Norma interface is Gmail-shaped — read, click, approve, send. If you can use Gmail, you can use Norma. Steve handles the technical side. SDCC handles the borrower-centered judgment side.",
"before_after": { "before": "\"I'd love to use AI but I wouldn't know where to start.\"", "after": "\"Open Norma in the morning, read the Pulse brief, approve the drafts that look right, edit the ones that don't, send.\"" }
},
{
"objection": "\"Won't this make us less authentic?\"",
"answer": "Authenticity isn't who types the first draft — it's who decides what gets said and why. SDCC's authentic voice is Natalia + Sabrina's judgment. AI absorbs the typing. The voice is yours, the strategy is yours, the borrower relationships are yours.",
"before_after": { "before": "Natalia writes statements at 2am because she's the only one who can find the voice.", "after": "Natalia approves drafts at 7am over coffee. The voice is still hers — it just doesn't cost her sleep." }
},
{
"objection": "\"What if donors think we're cutting corners?\"",
"answer": "Frame it the opposite way: SDCC is investing in capacity-building so every dollar of donor money reaches 5× more borrowers. AI is leverage on impact, not a corner-cut. Funders LOVE this story when told correctly.",
"before_after": { "before": "SDCC reaches 10,000 borrowers/year with current staff.", "after": "Same staff reaches 50,000 borrowers/year. Donor reports write themselves." }
},
{
"objection": "\"This is going to fail and I'll have wasted 3 months.\"",
"answer": "Three-month pilot, kill switch in writing, no annual commitment until SDCC says yes. If it doesn't work, you walk away with: (1) your data, exported, (2) a better understanding of what your team actually needs, (3) $1,500 ish spent — less than one staff retreat. The downside is tiny. The upside is enormous.",
"before_after": { "before": "12-month enterprise contract, paid upfront, locked in.", "after": "Month-to-month pilot. Cancel anytime. Steve eats the risk." }
}
],
"your_tuesday": {
"label": "Your Tuesday at 2pm",
"before": [
"Inbox at 387 unread. Three journalists in your Slack DMs.",
"ED just put out a press release. You're trying to draft a response while three other things bleed.",
"Someone on the team asks 'do we have a borrower in Texas with garnishment?' You think you do but you'd have to dig through six months of emails to find them.",
"Tomorrow's grants deadline you forgot until just now.",
"You leave at 8pm with the response statement still half-drafted."
],
"after": [
"Inbox shows 12 priority items — Norma triaged the other 375 into folders.",
"Press response draft was waiting at 4:05pm when the ED announcement dropped at 4:00. You spent 6 minutes editing it; sent at 4:30.",
"'Borrower in Texas with garnishment' search returns 3 stories in 5 seconds, anonymized for press use.",
"Norma reminded you about the grants deadline yesterday at 9am. Application submitted.",
"You leave at 5:30. Response is live. Statement is shared. Grants is in. Inbox is closed."
]
},
"the_promise": "The point of AI here isn't 'cool technology.' It's that Tuesday should not destroy you anymore."
},
"lecture": {
"why_ai": {
"headline": "Why AI for a Nonprofit?",
"subhead": "Smaller staff. Bigger reach. Faster cycles.",
"bullets": [
"Nonprofits compete for attention with corporations that spend 100× more on content and outreach. AI levels the field by absorbing the time-consuming work — drafting, summarizing, classifying — so each staffer's hour goes further.",
"Pattern recognition at scale: AI surfaces which signals (news cycles, legislative moves, donor activity) actually predict policy wins, instead of relying on guesswork.",
"Always-on triage: inbound mail, news, petition activity arrive 24/7. AI triages overnight so the morning starts with a curated priority list, not a 400-message inbox.",
"Cost: a fully-managed AI stack runs in single-digit hundreds per month — less than a part-time hire — and covers tasks that previously took a full FTE."
],
"honest_caveats": [
"AI drafts, humans approve. Every outbound message goes through a person before send.",
"AI is wrong sometimes. Citations on every claim, audit log on every decision.",
"AI cannot replace movement-building, donor relationships, or direct organizing. It replaces the typing."
],
"quiz": [
{
"q": "What's the single biggest reason a small nonprofit benefits from AI?",
"options": [
"It replaces staff with cheaper labor",
"It absorbs the time-consuming drafting/research work so each staffer's hour goes further",
"It makes the website look more modern",
"It eliminates the need for human approval"
],
"answer": 1,
"explain": "AI is a force multiplier on human time — not a staff replacement. The 'unfair advantage' is each staffer doing the work of three, not firing two staffers."
},
{
"q": "True or False — Norma will send messages on SDCC's behalf without human review.",
"options": ["True", "False"],
"answer": 1,
"explain": "Human-in-the-loop on every outbound. AI drafts, a staffer hits send."
},
{
"q": "What's the typical monthly cost of a fully-managed AI stack for a small org?",
"options": [
"$10/mo (free tier)",
"Single-digit hundreds per month",
"$10,000+/mo enterprise pricing",
"Free if you self-host"
],
"answer": 1,
"explain": "Realistic budget — Claude API + hosting + integrations land around $200-$800/mo for a 5-person org."
}
]
},
"long_short": {
"headline": "Long-Term vs Short-Term Thinking",
"subhead": "Short-term wins build trust. Long-term wins build moats.",
"short_term": [
{ "title": "Inbox triage live in week 1", "detail": "Sabrina opens to a sorted queue of priority borrower stories with draft replies. Time recovered: 6-10 hrs/week per staffer." },
{ "title": "Press statement drafts in 90 seconds", "detail": "When ED/CFPB drops news at 4pm Friday, SDCC has a public response queued by 4:05. Not Monday." },
{ "title": "Petition campaigns in 10 min", "detail": "Replaces 3-4 hours of cold drafting per campaign. SDCC can fire 5 campaigns per week instead of 1." }
],
"long_term": [
{ "title": "Knowledge base that compounds", "detail": "Every approved draft, statement, classified borrower story feeds the system. The longer SDCC uses it, the more it knows SDCC's voice — and the harder it is for a competitor to clone." },
{ "title": "Coalition map nobody else has", "detail": "Live graph of every org touching student debt, what they've said, who funds them, who they hire. SDCC becomes the strategic hub by knowing the field." },
{ "title": "Borrower story archive (privacy-preserving)", "detail": "10,000+ structured borrower stories searchable by debt type / geography / urgency. When a journalist calls asking 'do you have a story about X?' — SDCC has 12 in 10 seconds." },
{ "title": "Compounding policy intelligence", "detail": "Every Congress.gov / ED.gov / CFPB action ingested + summarized daily. After 18 months, SDCC has a structured history nobody else does." }
],
"tradeoff": "Most orgs only do short-term ('save me typing now'). That's fine for month 1. But the orgs that win long-term invest in the knowledge layer — and SDCC's policy advantage compounds every quarter the data accumulates.",
"quiz": [
{
"q": "Which is a SHORT-term win SDCC should expect in week 1?",
"options": [
"A complete coalition power-map",
"Inbox triage with draft replies sorted by urgency",
"10,000-row borrower story database",
"Custom integrations with all SDCC tools"
],
"answer": 1,
"explain": "Inbox triage is the fastest measurable win. Power maps + story archives take months to build up."
},
{
"q": "Why does the LONG-term value of an AI system compound?",
"options": [
"AI gets cheaper over time",
"Every approved draft + classified story trains the system on SDCC's voice + data",
"Anthropic releases free upgrades",
"Long-term you can fire more staff"
],
"answer": 1,
"explain": "Knowledge moats. The longer SDCC uses it, the harder a competitor can replicate SDCC's institutional memory."
}
]
},
"projects_and_docs": {
"headline": "Projects + Anthropic Docs — What Powers This",
"subhead": "Brief tour of the toolchain so nobody's surprised later.",
"what_is_anthropic": "Anthropic is the company that builds Claude — the language model under Norma's hood. Norma talks to Claude through Anthropic's API. That's the only outside dependency for AI inference.",
"projects_concept": [
{ "title": "What a 'Project' is in this context", "detail": "A bounded workspace — for SDCC, that means: one tenant of Norma, with SDCC's prompts, voice library, knowledge base, integrations, and audit trail. Other orgs in Norma run their own projects, fully isolated." },
{ "title": "Anthropic Projects (the product)", "detail": "Anthropic also ships a feature called 'Projects' inside claude.ai where you can attach files + give Claude persistent instructions. Useful for staffers doing one-off research — but Norma is more powerful because it has the database, the integrations, and the audit trail." },
{ "title": "Why both can coexist", "detail": "Staff can use claude.ai Projects for free-form research. Norma handles the structured, repeatable, audited work — drafts, classifications, briefings, sends." }
],
"docs_overview": [
{ "title": "anthropic.com/api", "detail": "Where the model lives. Norma calls Claude through here." },
{ "title": "docs.anthropic.com", "detail": "API reference + prompt engineering guides. SDCC staff don't read these; Norma's team does." },
{ "title": "Anthropic responsible-use policy", "detail": "Bars on what AI can be used for. Norma's design respects these — borrower PII handling, no unauthorized impersonation, etc." }
],
"quiz": [
{
"q": "When SDCC uses Norma, where does Claude (the AI) actually run?",
"options": [
"On SDCC's laptops",
"Anthropic's servers — Norma calls Claude through the API",
"On the same machine as Norma",
"On an SDCC-owned cloud account"
],
"answer": 1,
"explain": "Anthropic hosts the model. Norma is the wrapper that handles SDCC's data, prompts, and integrations."
},
{
"q": "What's the difference between 'Anthropic Projects' (claude.ai) and a 'Norma project for SDCC'?",
"options": [
"Nothing, they're the same",
"Anthropic Projects is free-form research in claude.ai; Norma is structured, audited, integrated with SDCC's database",
"Norma is hosted by Anthropic",
"Anthropic Projects is more powerful"
],
"answer": 1,
"explain": "Two different tools — staffers can use both. Norma owns the structured work, claude.ai Projects handles ad-hoc research."
}
]
},
"loops": {
"headline": "Loops — How Norma Keeps Working While You Sleep",
"subhead": "A 'loop' is an agent that runs the same job over and over, on its own.",
"explainer": "Most software waits for a click. A loop doesn't. It wakes up every N minutes/hours, scans for new work, does the work, sleeps. No human pushing buttons. Loops are how Norma absorbs always-on tasks — inbox scanning, news ingestion, signature counting — without a staffer babysitting them.",
"examples": [
{ "title": "Inbox loop (every 5 min)", "detail": "Polls info@studentdebtcrisis.org. Any new message → classify, draft reply, route to right person, log. If nobody acts in 24h, escalate to Slack." },
{ "title": "News-scan loop (every 30 min)", "detail": "Hits 200+ outlets. Filters for SDCC mentions, student-debt stories, key staff names. Adds to morning brief queue." },
{ "title": "Petition-velocity loop (every 15 min)", "detail": "Checks live signature count on active campaigns. If a campaign is accelerating past threshold → trigger escalation email to Natalia + draft press push." },
{ "title": "Coalition-watch loop (daily 6am)", "detail": "Scrapes coalition partner websites + social. Flags new statements, new hires, leadership changes. SDCC knows before anyone announces." }
],
"guardrails": [
"Every loop has a kill switch (one click in admin → loop stops).",
"Every loop logs every action to the audit trail.",
"Loops never auto-send to external parties — they only triage, draft, and queue."
],
"quiz": [
{
"q": "What's the difference between a loop and a regular feature?",
"options": [
"A loop runs on its own schedule; a feature waits for a human click",
"Loops are slower",
"Loops only work on weekends",
"There's no difference"
],
"answer": 0,
"explain": "That's the whole point — loops absorb always-on work so no staffer has to babysit it."
},
{
"q": "True or False — a loop in Norma can auto-send a press statement without human approval.",
"options": ["True", "False"],
"answer": 1,
"explain": "Loops triage, draft, queue. They NEVER send to external parties. Humans approve every outbound."
}
]
},
"cron": {
"headline": "Cron Jobs — Scheduled Tasks That Just Happen",
"subhead": "Like a loop, but on a calendar instead of a timer.",
"explainer": "A cron job is a scheduled task — 'run X at 7am every Monday' or 'run Y at the end of every quarter'. Norma uses cron for things that don't need to run constantly but DO need to happen on a predictable beat.",
"examples": [
{ "title": "Monday 7am — Weekly intelligence brief", "detail": "Compiles the week's most important policy moves, news mentions, petition activity, coalition signals into a single email to Natalia + Sabrina. Land in inbox before the 9am team huddle." },
{ "title": "First of month 6am — Donor renewal radar", "detail": "Pulls every donor whose recurring gift expires in the next 30 days. Drafts personalized renewal asks for staff approval." },
{ "title": "Tuesdays 10am — Grants deadline sweep", "detail": "Surfaces every foundation grant with a deadline in the next 30 days where SDCC is a fit. Prevents 'oh no the Lumina deadline was yesterday.'" },
{ "title": "Quarterly — Board impact report draft", "detail": "Pulls quantitative impact data (campaigns, signatures, press hits, borrower stories, dollars moved) into a draft board report. Staffer edits + sends." }
],
"vs_loops": "Loops = 'every N minutes, do this'. Cron = 'at this specific time, do this'. Often used together — a loop catches signals in real-time, cron compiles them into weekly digests.",
"quiz": [
{
"q": "When would SDCC use a cron job instead of a loop?",
"options": [
"When the task needs to react to events instantly",
"When the task should run on a predictable calendar (e.g. every Monday 7am)",
"When you want to disable the task",
"Cron jobs are old; loops replace them"
],
"answer": 1,
"explain": "Cron = calendar-driven. Loops = continuous. Use cron for weekly digests, monthly renewals, quarterly reports."
}
]
},
"ui_vs_ux": {
"headline": "UI vs UX — Why Both Matter for Adoption",
"subhead": "A tool that staff doesn't use is worth zero.",
"ui_definition": "UI (User Interface) = what it looks like. Colors, typography, buttons, layout, whether things are pretty.",
"ux_definition": "UX (User Experience) = how it FEELS to use. Whether you can find what you need in 3 clicks. Whether 'I want to send Natalia the draft' is one button or seven. Whether errors are clear or cryptic.",
"examples": [
{ "title": "Good UI / Bad UX", "detail": "Beautiful dashboard but you can't figure out how to draft a reply. Looks great in a screenshot, fails in real use.", "type": "warning" },
{ "title": "Bad UI / Good UX", "detail": "Ugly buttons but every workflow is 1-2 clicks and errors say exactly what to do. Staff actually use it. (Better than the first one.)", "type": "ok" },
{ "title": "Good UI + Good UX (the goal)", "detail": "Looks like a product Natalia would brag about to other EDs, AND every flow is 1-2 clicks, AND errors are friendly.", "type": "goal" }
],
"sdcc_priorities": [
{ "title": "1. UX first, UI second", "detail": "If staff hates using it, the prettiest UI in the world won't save it." },
{ "title": "2. Mobile matters", "detail": "Sabrina + Natalia work from phones. Every flow must work on mobile, not just desktop." },
{ "title": "3. Voice consistency over visual novelty", "detail": "SDCC's voice = direct, borrower-centered, urgent. UI shouldn't fight it (no cute illustrations of piggy banks)." },
{ "title": "4. Accessibility is non-negotiable", "detail": "Many borrowers SDCC advocates for have disabilities. Anything SDCC ships in this tool should be WCAG AA at minimum." }
],
"quiz": [
{
"q": "If a tool has gorgeous UI but staff can't figure out how to use it, what is that?",
"options": [
"Good UI / Bad UX — staff won't use it",
"Best of both worlds",
"Acceptable — pretty matters most",
"Bad UI / Good UX"
],
"answer": 0,
"explain": "If staff can't use it, the prettiness is wasted. UX > UI when forced to choose."
},
{
"q": "Which is a UX problem (not a UI problem)?",
"options": [
"The button color is wrong",
"Sending a draft takes 7 clicks instead of 2",
"The font is too small",
"The header image is blurry"
],
"answer": 1,
"explain": "Click-count and friction are UX. Color/font/image are UI."
}
]
}
},
"pitch_questions": {
"headline": "Questions to ask SDCC during the pitch",
"intro": "Don't lecture — interview. These are the questions that get SDCC to surface what they actually need (and reveal what they didn't know they needed).",
"categories": [
{
"category": "Current pain",
"questions": [
"Walk me through the last 3 days of your inbox — what % of messages did you actually want to act on?",
"When was the last time you missed a news cycle you wish you'd caught?",
"How often do you say 'we should write a statement on this' but never get to it?",
"Whose voice/writing is hardest to replicate when they're out of office?",
"What was the last grant deadline you missed and what was it for?"
]
},
{
"category": "Workflow + handoffs",
"questions": [
"When a borrower story comes in, who triages it? What happens if that person is sick?",
"How do you find a specific borrower story 6 months later when a journalist asks?",
"Who reviews press statements before they go out? Is that one person or three?",
"How do you decide which campaigns to launch this month vs next?",
"What does your Monday morning team huddle actually use as the agenda?"
]
},
{
"category": "What worries you about AI",
"questions": [
"What's the worst thing that could happen if SDCC starts using AI for outbound work?",
"Who on the team would push back against AI tools, and what's their objection?",
"Are there messages or moments where AI MUST NOT touch the output?",
"How would you describe SDCC's voice to someone who's never read your work?",
"What's the line between 'AI helps' and 'AI undermines our authenticity'?"
]
},
{
"category": "Long-term vision",
"questions": [
"If Norma was wildly successful for SDCC in 18 months, what would that look like? What 3 metrics moved?",
"What would have to be true for SDCC to recommend this to a peer org?",
"What integration with your existing stack (Gmail, Slack, EveryAction, etc.) is non-negotiable?",
"Who owns the relationship with this tool on SDCC's side?",
"What's your decision process for adopting a new tool — who else needs to say yes?"
]
},
{
"category": "Funding + sustainability",
"questions": [
"Is there a funder who would underwrite SDCC's adoption of this as 'capacity-building'?",
"What's the procurement/budget process for a tool in this price range?",
"How long would the pilot need to be before you'd commit to a year?",
"Would SDCC be willing to be a public case study if this works?"
]
}
]
},
"unknown_unknowns": {
"headline": "Unknown unknowns — things about SDCC nobody on the call has thought about",
"intro": "These are the questions you probably haven't been asked but that determine whether Norma actually fits SDCC's reality. Use them in the pitch to demonstrate you've thought deeper than the standard vendor.",
"items": [
{
"category": "Borrower trust",
"question": "If a borrower learns AI helped draft the reply they got from SDCC, do they feel less heard?",
"why_it_matters": "SDCC's whole brand is borrower-centered. If borrowers find out their crisis was triaged by software, it could undermine the trust SDCC's spent 10 years building. Mitigation: AI drafts, human voice in the final send — and SDCC may want to disclose AI use in a privacy notice."
},
{
"category": "Press-cycle risk",
"question": "What happens if a journalist asks 'are these statements AI-written'?",
"why_it_matters": "If the answer is 'partly,' is SDCC ready for that story? The honest answer is 'AI helps draft, humans approve' — but SDCC needs to rehearse that answer before the question lands."
},
{
"category": "Coalition optics",
"question": "What do partner orgs (Debt Collective, NCLC, NAACP) think about AI tools in advocacy?",
"why_it_matters": "If Debt Collective publicly opposes AI in organizing, SDCC's adoption could create coalition friction. Worth asking partners before announcing — or at least having a clear position on why SDCC's adoption is different (audit trail, human-in-the-loop, no impersonation)."
},
{
"category": "Staff turnover",
"question": "If Sabrina leaves SDCC in 12 months, what happens to her AI-tuned voice library?",
"why_it_matters": "AI tools that train on individual staff create a continuity risk. Norma should be tuned on SDCC's organizational voice + multiple staffers' samples — not just one person. Plus exportable knowledge base means SDCC owns the data, not the staffer who left."
},
{
"category": "Donor reaction",
"question": "How do major donors feel about funding AI tooling vs. direct services?",
"why_it_matters": "Some donors will love 'capacity-building tech.' Others will say 'I funded you to help borrowers, not buy software.' SDCC needs talking points for both. Hint: AI tooling lets SDCC reach 5× more borrowers — that IS direct service."
},
{
"category": "Regulatory shifts",
"question": "What if California or NY passes a law requiring AI disclosure in nonprofit communications?",
"why_it_matters": "AI regulation is moving fast. SDCC's audit trail is the answer — full log of every AI-assisted message is exactly what a regulator would want. SDCC is ahead of the curve, not behind."
},
{
"category": "Legal voice",
"question": "When SDCC posts about specific borrower cases or names a bad actor (school, servicer), who reviews for legal exposure?",
"why_it_matters": "AI doesn't know what's defamatory. Need a clear policy that ANY communication naming a specific entity goes through human legal review before send. This is a workflow rule, not an AI feature — but it has to be in writing."
},
{
"category": "Borrower stories + privacy",
"question": "Have you ever had a borrower come back and ask you to remove their story from public materials?",
"why_it_matters": "If yes — that's a deletion + retraction workflow Norma needs to support, not just storage. Right to be forgotten matters even for nonprofit data."
},
{
"category": "Burnout signal",
"question": "If Sabrina's inbox-triage time drops from 12 hrs/week to 2 hrs/week, where do those 10 hours go?",
"why_it_matters": "Without intentional planning, recovered time gets backfilled by new work. SDCC should pre-commit to what those hours become — more borrower 1:1s? Deeper press relationships? Strategic planning? — otherwise the gain evaporates."
},
{
"category": "What competitors don't have",
"question": "Is anyone else in the student-debt advocacy space using AI tooling at this depth?",
"why_it_matters": "If no — SDCC has a 12-18 month lead. If yes — SDCC needs to know who and what they're doing differently. (Honest answer: not at this depth, but Debt Collective is experimenting and PanCAN has Salesforce Einstein.)"
},
{
"category": "Board comprehension",
"question": "Does the SDCC board understand AI well enough to approve adoption?",
"why_it_matters": "If no — Steve should offer a 30-min board education session. Better to invest the time upfront than have approval stall."
},
{
"category": "Departure plan",
"question": "If SDCC decides to stop using Norma in 2 years, what's the off-ramp?",
"why_it_matters": "Buyers want to know they're not locked in. Norma should commit to a full data export — borrower stories, voice library, audit trail, coalition map — in a portable format. SDCC owns its data."
}
]
},
"real_example": {
"headline": "A real example using SDCC's data",
"intro": "Live walkthrough — every button below hits a working API. The data is seeded but the path is identical to production.",
"scenario": "It's Wednesday 9am. ED just published a press release saying 1M borrowers approved for PSLF discharge. SDCC needs to respond TODAY.",
"steps": [
{ "label": "1. Norma already saw the news", "detail": "News-intelligence loop caught it at 7:42am. Already classified, already in the Pulse brief.", "action": "/api/petitions/topics?source=headline&limit=5", "verb": "GET" },
{ "label": "2. Draft a supportive-but-pushing statement", "detail": "Norma drafts a press response in SDCC's voice in ~90 seconds. Stance: supportive, calls for faster processing.", "action": "/api/agents/advocacy/generate", "verb": "POST", "body": { "occasion": "ED announces 1M borrowers approved for PSLF discharge", "stance": "supportive but call for faster processing" } },
{ "label": "3. Find a borrower story to attach", "detail": "Search borrower stories for someone in PSLF who was just approved — for the press attachment.", "action": "/api/leads/discover?type=borrower-story&program=pslf&limit=3", "verb": "GET" },
{ "label": "4. Generate quote from Natalia", "detail": "Pull Natalia's prior statements on PSLF, draft a quote.", "action": "/api/ai-chat", "verb": "POST", "body": { "message": "Draft a 2-sentence quote from Natalia Abrams responding to ED's PSLF announcement, supportive but urgent about processing speed" } },
{ "label": "5. Find who to call", "detail": "Pull constituent contacts for journalists covering education policy.", "action": "/api/contacts?tag=press,education-policy&limit=10", "verb": "GET" }
],
"ending": "Total time from news drop to press-ready statement + borrower story + quote + press list: ~7 minutes. Without Norma: 3-5 hours. THAT's the value."
},
"agents": [
{
"id": "petition-generator",
"name": "Petition Generator",
"tagline": "From topic to live campaign in under 10 minutes",
"what_it_does": "Takes a topic prompt + target audience and generates: petition title, full body copy (200-400 words), share text for X/Bluesky/Threads, follow-up email sequence, and a hero image prompt. Tuned to SDCC's voice on prior published petitions.",
"for_sdcc": "Replaces the 3-4 hour drafting cycle. Sabrina or Natalia review and approve, never starts from scratch.",
"api_route": "/api/agents/petition/generate",
"demo_payload": { "topic": "Block the rollback of SAVE plan protections", "audience": "borrowers under 35 in SAVE plan" },
"category": "draft",
"human_in_the_loop": "Required — staffer approves before publish"
},
{
"id": "advocacy-statement",
"name": "Advocacy Statement Drafter",
"tagline": "Press-statement first-pass in 90 seconds",
"what_it_does": "Drafts a press statement responding to any breaking news or policy decision. Pulls from SDCC's prior statements for tone + current talking points + a citation footer.",
"for_sdcc": "When ED announces a policy change at 4pm Friday, SDCC has a draft at 4:05pm — instead of waiting until Monday to respond.",
"api_route": "/api/agents/advocacy/generate",
"demo_payload": { "occasion": "ED announces 1M borrowers approved for PSLF discharge", "stance": "supportive but call for faster processing" },
"category": "draft",
"human_in_the_loop": "Required — Natalia approves before publish"
},
{
"id": "grants-match",
"name": "Grants Matcher",
"tagline": "Surface only the foundation grants you're actually competitive for",
"what_it_does": "Scans 12,000+ active foundation grants daily. Matches against SDCC's mission, prior funded programs, ask-size sweet spot, geography. Returns ranked list with deadlines + asks.",
"for_sdcc": "Replaces manual grant prospecting nobody has time to do. Quarterly review becomes 30-min weekly review of pre-filtered opportunities.",
"api_route": "/api/agents/grants/match",
"demo_payload": { "mission": "Student debt advocacy + borrower rights", "ask_range": "50000-250000" },
"category": "research",
"human_in_the_loop": "Optional — staffer reviews ranked list, AI never submits applications"
},
{
"id": "congress-by-zip",
"name": "Congress-by-ZIP",
"tagline": "Constituent → representatives in one call",
"what_it_does": "Any ZIP code returns Senators, House member, key state-legislature contacts with committee assignments + recent debt-relief voting record.",
"for_sdcc": "When a borrower asks 'who do I call?', SDCC sends exact names/numbers/emails in 5 seconds — and tracks which districts are activating.",
"api_route": "/api/agents/congress-by-zip?zip=90404",
"demo_payload": null,
"category": "research",
"human_in_the_loop": "None — pure lookup tool"
},
{
"id": "org-register",
"name": "Coalition Partner Auto-Onboard",
"tagline": "Add a new coalition partner to your power map in 30 seconds",
"what_it_does": "Given an org URL or name, scrapes mission, leadership, geographic focus, current campaigns. Adds to power map with proposed relationship strength.",
"for_sdcc": "Builds the coalition power-map without weeks of manual research. Every new org touching student debt gets ingested automatically.",
"api_route": "/api/agents/org/register",
"demo_payload": { "url": "https://debtcollective.org" },
"category": "research",
"human_in_the_loop": "Required — staffer confirms before adding to power map"
},
{
"id": "gmail-triage",
"name": "Inbox Triage Agent",
"tagline": "Every inbound message classified + first-pass reply drafted before you open Gmail",
"what_it_does": "Reads every email landing in info@studentdebtcrisis.org. Classifies by type, urgency, action required. Drafts a reply in SDCC's voice. Routes high-urgency to Slack.",
"for_sdcc": "Sabrina opens her inbox to a sorted queue of 12 priority items with draft replies — not 400 unread.",
"api_route": "/api/gmail/draft-reply",
"demo_payload": { "thread_id": "demo-borrower-hardship-001" },
"category": "operations",
"human_in_the_loop": "Required — drafts only, staffer hits send"
},
{
"id": "news-intelligence",
"name": "News Intelligence",
"tagline": "Daily AI-curated brief of every news cycle that touches SDCC's work",
"what_it_does": "Scans 200+ outlets daily. Surfaces SDCC mentions, key staff, student-debt stories, coalition partners. Generates a 5-bullet morning brief with links.",
"for_sdcc": "Natalia opens email at 7am to a single 5-bullet brief — not 50 Google Alerts.",
"api_route": "/api/petitions/topics?source=headline&limit=8",
"demo_payload": null,
"category": "research",
"human_in_the_loop": "None — pure briefing"
},
{
"id": "borrower-story-classifier",
"name": "Borrower Story Classifier",
"tagline": "Every borrower story sorted by debt type, urgency, and press-readiness",
"what_it_does": "Web-form submissions and emails get classified by debt type (federal/private/parent PLUS), crisis (default/garnishment/denial), and whether anonymizable for press.",
"for_sdcc": "When a journalist asks 'do you have a borrower in [state] dealing with [scenario]?', SDCC searches a structured database in 10 seconds.",
"api_route": "/api/leads/discover",
"demo_payload": { "type": "borrower-story" },
"category": "operations",
"human_in_the_loop": "Required — staffer reviews + tags before publish-ready"
},
{
"id": "boilerplate-library",
"name": "Boilerplate Language Library",
"tagline": "One-click insert SDCC's standing language on every issue",
"what_it_does": "Pre-built library of vetted SDCC language — SAVE plan position, PSLF stance, parent PLUS reform, for-profit accountability. Every draft can one-click insert latest approved wording.",
"for_sdcc": "Ensures every public message uses the most recent agreed-upon language — no stale talking points from 2023.",
"api_route": "/api/boilerplate",
"demo_payload": null,
"category": "draft",
"human_in_the_loop": "Library is human-curated; agent only inserts"
},
{
"id": "audit-trail",
"name": "Audit Trail + Compliance",
"tagline": "Every AI decision, every send, every approval logged forever",
"what_it_does": "Every action — agent generated draft X, staffer approved, message sent — immutably logged with timestamp + actor. Borrower PII access logged separately. Searchable forever.",
"for_sdcc": "When a funder, board member, or regulator asks 'who sent this message?' the answer is one query away.",
"api_route": "/api/audit",
"demo_payload": null,
"category": "compliance",
"human_in_the_loop": "Read-only — no AI decisions, this is the record"
},
{
"id": "pulse-briefing",
"name": "Pulse Daily Briefing",
"tagline": "Single landing page that surfaces the day's top priorities",
"what_it_does": "Dashboard at /pulse — combines petitions, news, urgent borrower stories, coalition activity into one daily-refresh briefing. Each item one-click expandable.",
"for_sdcc": "Morning standup becomes 'open Pulse, read the brief, decide priorities' instead of 'check 8 different tools.'",
"api_route": "/api/petitions/topics?limit=12",
"demo_payload": null,
"category": "operations",
"human_in_the_loop": "Read + act — no AI decisions surface here unflagged"
},
{
"id": "ai-chat",
"name": "Norma Chat Assistant",
"tagline": "Ask SDCC's own knowledge base any question in plain English",
"what_it_does": "Chat backed by SDCC's prior statements, petition archive, borrower-story database (anonymized), grants pipeline, coalition map. 'What did we say about parent PLUS in 2024?' gets a cited answer.",
"for_sdcc": "Replaces 'I'll get back to you' with an immediate cited answer — for press calls, staff onboarding, quick research.",
"api_route": "/api/ai-chat",
"demo_payload": { "message": "Summarize SDCC's position on the SAVE plan in 3 sentences for a journalist" },
"category": "research",
"human_in_the_loop": "Optional — citations on every answer"
}
],
"glossary": {
"headline": "Onboarding glossary — every term a new grad needs",
"intro": "Written for someone with a fresh CS/policy degree from a good university but zero practical exposure to this stack. Tap any card to expand. Mark as learned to earn XP toward the Vocabulary Champ badge.",
"categories": [
{
"id": "computer-basics",
"label": "Your computer (the basics)",
"icon": "💻",
"terms": [
{
"term": "Terminal",
"tldr": "The text-based interface to your computer. Where you type commands instead of clicking buttons.",
"detail": "Every command-line task — installing software, running servers, deploying code, talking to git — happens through a terminal. The terminal itself is just an app that hosts a 'shell.' On macOS the default app is Terminal.app. On Windows it's PowerShell or Windows Terminal.",
"example": "Open Spotlight (⌘ + Space), type 'Terminal', hit enter. You'll see a prompt like `you@laptop ~ %`. Type `pwd` and hit enter — it prints your current directory."
},
{
"term": "iTerm2",
"tldr": "A better terminal app for macOS than the default Terminal.app. Tabs, split panes, mouse support, search.",
"detail": "Free, open-source. Install at iterm2.com or via Homebrew (`brew install --cask iterm2`). Steve uses iTerm2 because it supports parallel tabs (one per Claude session) with distinct colors per tab so they don't blur together.",
"example": "After install: iTerm2 → Preferences → Profiles → set 'Working Directory' to 'Reuse previous session's directory'. Cmd+T for new tab, Cmd+D to split."
},
{
"term": "Shell (zsh, bash)",
"tldr": "The program running inside the terminal that interprets the commands you type.",
"detail": "zsh is macOS's default since 2019. Older Macs use bash. Different shells = slightly different syntax for things like aliases and scripts. You'll see `.zshrc` and `.bashrc` files in your home directory — those are the configuration files for your shell.",
"example": "Echo your current shell: `echo $SHELL`. Usually returns `/bin/zsh`."
},
{
"term": "Command line / CLI",
"tldr": "Synonym for 'using the terminal'. CLI = Command-Line Interface, the opposite of GUI (graphical).",
"detail": "Most developer tools ship a CLI. You'll spend half your day in CLIs once you're past the GUI stage. The fastest path to productivity at any new job is becoming fluent in the team's CLIs.",
"example": "`git status`, `npm install`, `claude --help` are all CLI commands."
},
{
"term": "Git",
"tldr": "The version-control system every modern team uses. Tracks every change to every file.",
"detail": "Git is the tool. GitHub is the website that hosts git repositories. They're different — you can use git without GitHub (Steve does for local versioning), but GitHub adds collaboration features. Critical commands: `git status`, `git add`, `git commit`, `git log`, `git diff`.",
"example": "After making a code change: `git add -A && git commit -m 'fix typo in petition generator'`. Now your change is locked into git history forever."
},
{
"term": "GitHub",
"tldr": "A website (microsoft-owned) that hosts git repositories and adds collaboration tools — pull requests, issues, actions (CI/CD).",
"detail": "SDCC's repos will likely live on GitHub eventually. You don't NEED GitHub to use git, but you need GitHub to share code with teammates."
},
{
"term": "Node.js + npm",
"tldr": "Node.js runs JavaScript on the server. npm is its package manager — the tool that installs JS libraries from a global registry.",
"detail": "Node.js is the runtime. npm (Node Package Manager) is the installer. Norma is a Node.js app. Install Node from nodejs.org or via Homebrew (`brew install node`). After install you have both `node` and `npm` commands.",
"example": "`npm install express` adds the express web framework to the current project. `npm run dev` starts whatever the project defined as its dev command."
},
{
"term": "localhost",
"tldr": "Your own computer. When code runs locally, it talks to itself via the hostname 'localhost' (which always means 127.0.0.1).",
"detail": "When you see `http://localhost:7400`, that's a server running ON YOUR machine, listening on port 7400. Other people on the internet cannot reach it. To make it reachable you'd need to deploy it to a real server."
},
{
"term": "Port (e.g. :7400)",
"tldr": "A number that identifies which service on a machine you're talking to. Like a phone extension.",
"detail": "A single computer can run many services. Each grabs a different port number so requests don't collide. Norma uses :7400. The pitch viewer uses :9876. Web servers usually use :80 (HTTP) or :443 (HTTPS) in production. Anything 1024+ is fair game in dev.",
"example": "Norma is at http://localhost:7400 — the :7400 is the port."
},
{
"term": "Environment variable (env var)",
"tldr": "A named value your code reads from the environment, instead of hardcoding it in the source.",
"detail": "Secrets like API keys go in env vars (never in source code that gets committed to git). A `.env.local` file is a common pattern — list `KEY=value` pairs there, the app reads them at startup. NEVER commit `.env*` files to git.",
"example": "`ANTHROPIC_API_KEY=sk-ant-...` goes in `.env.local`. Code reads it via `process.env.ANTHROPIC_API_KEY`."
}
]
},
{
"id": "ai-fundamentals",
"label": "AI fundamentals",
"icon": "🧠",
"terms": [
{
"term": "LLM (Large Language Model)",
"tldr": "A neural network trained on huge amounts of text that can predict the next word — well enough to write essays, code, answer questions.",
"detail": "LLMs don't 'know' things the way humans do. They have statistical patterns over text. They CAN be wrong with high confidence (see: hallucination). Examples: Claude, GPT-4, Gemini, Llama, Hermes. Different LLMs differ in size, training data, RLHF (post-training tuning), and what they're best at.",
"example": "When you type a question into ChatGPT, the LLM reads your prompt and generates a reply one token at a time."
},
{
"term": "Token",
"tldr": "The smallest unit an LLM processes. Usually 3-4 characters of English, roughly ¾ of a word.",
"detail": "LLMs charge by tokens (input + output). Counting tokens matters for cost and context-window management. Rule of thumb: 1000 tokens ≈ 750 English words.",
"example": "'Hello, world!' is about 4 tokens. A 2,000-word essay is ~2,700 tokens."
},
{
"term": "Context window",
"tldr": "The maximum amount of text (in tokens) an LLM can read at once.",
"detail": "Claude Sonnet 4 has a 200K-token context window — about 150,000 words. Claude Opus 4.7 (1M context, what's running this pitch viewer) is 1 million tokens — entire codebases fit inside. Bigger windows = more powerful tasks but more expensive per call."
},
{
"term": "Prompt",
"tldr": "The text you send the LLM. Includes your question and any context/instructions.",
"detail": "A 'system prompt' is hidden instructions the LLM sees first ('You are a helpful student-debt advocate'). The 'user prompt' is what you type. Prompts are the primary way to control LLM behavior — better prompts = better outputs."
},
{
"term": "Inference",
"tldr": "When you ask the LLM a question and it generates an answer. 'Running inference' = 'using the model'.",
"detail": "Separate from training. Training is how the model was built (months, expensive). Inference is each call to the model (seconds, much cheaper). Norma runs inference every time it drafts a statement or classifies an email."
},
{
"term": "Hallucination",
"tldr": "When an LLM makes up something that sounds plausible but is false.",
"detail": "Biggest risk of using LLMs in advocacy. The model might invent a Supreme Court case, misquote a politician, or fabricate a statistic — all with high confidence. Mitigation: citations on every claim, human review before send, RAG (next term)."
},
{
"term": "RAG (Retrieval Augmented Generation)",
"tldr": "Instead of relying only on what the LLM knows from training, RAG looks up real source documents at query time and gives them to the LLM as context.",
"detail": "Pattern: user asks a question → system searches a database (e.g. SDCC's petition archive) for relevant snippets → puts those snippets in the prompt → LLM answers based on the snippets. This is how Norma's 'ask the knowledge base' feature avoids hallucination.",
"example": "Question: 'What did SDCC say about parent PLUS in 2024?' → RAG retrieves SDCC's 2024 parent PLUS statements → LLM summarizes with citations."
},
{
"term": "Embedding",
"tldr": "A numeric vector that represents a piece of text's 'meaning'. Used to find semantically-similar documents.",
"detail": "Every document gets converted into a 768- or 1536-dimensional vector. Two documents with similar meaning have vectors that are close in that 1536-dim space. That's how RAG finds relevant docs — by vector similarity, not keyword match."
},
{
"term": "Vector database",
"tldr": "A database optimized for storing + searching embeddings.",
"detail": "Examples: Pinecone, Weaviate, pgvector (Postgres extension). Norma uses pgvector (a Postgres extension) so vectors live alongside relational data."
},
{
"term": "Agent",
"tldr": "An LLM that can use tools (call APIs, run code, search the web) in a loop to accomplish a goal, not just answer one question.",
"detail": "Instead of 'answer this question', an agent gets 'classify all incoming emails, draft replies, route urgent ones to Slack' — and figures out the steps itself. Agents are LLMs + tools + a loop. Norma's inbox triage is an agent."
},
{
"term": "Tool use / Function calling",
"tldr": "When you let the LLM call functions you defined — search the database, send an email, look up a contact.",
"detail": "You hand the LLM a list of available tools ('search_petitions', 'draft_email', 'get_borrower_story'). The LLM decides which to call based on the user request and returns a structured call. Your code executes the call and returns results to the LLM."
},
{
"term": "Temperature",
"tldr": "A knob 0-1 controlling randomness. 0 = deterministic. 1 = creative/varied.",
"detail": "Press statements: temperature 0.3-0.5 (consistent, professional). Brainstorming: 0.7-0.9 (creative). Norma usually defaults to 0.7."
},
{
"term": "Multi-modal",
"tldr": "An LLM that handles more than just text — also images, audio, video.",
"detail": "Claude is multi-modal: you can paste a screenshot of a press release and ask the model to extract key claims. Useful for SDCC when reviewing graphics, PDFs, news photos."
},
{
"term": "Fine-tuning vs RAG vs Prompting",
"tldr": "Three ways to make an LLM better at your specific task. Prompting is cheapest. RAG is more accurate. Fine-tuning is most powerful but expensive.",
"detail": "Prompting: just write better instructions (start here). RAG: feed the LLM your data at query time (default for knowledge bases). Fine-tuning: actually retrain the model on your data (rare, expensive, last resort)."
}
]
},
{
"id": "anthropic-claude",
"label": "Anthropic + Claude",
"icon": "🟧",
"terms": [
{
"term": "Anthropic",
"tldr": "The AI safety company that builds Claude. Founded 2021 by ex-OpenAI researchers including Dario and Daniela Amodei.",
"detail": "Anthropic's pitch is 'AI safety as a science'. They publish on alignment, scaling laws, constitutional AI. Norma uses Anthropic's Claude API for all its inference. Anthropic does not see SDCC's borrower data unless you explicitly opt into their feedback program (Norma does not)."
},
{
"term": "Claude (the model)",
"tldr": "Anthropic's LLM family. Three sizes — Haiku (fast/cheap), Sonnet (balanced), Opus (most capable).",
"detail": "Versions are dated/numbered (Claude 4.6, Claude 4.7). Each newer model is generally smarter but pricier. Norma uses Sonnet for most tasks and Opus for the hard ones (long-document analysis, multi-step reasoning).",
"example": "Claude Opus 4.7 (running THIS session) costs ~$15/$75 per million input/output tokens. Claude Haiku is ~$1/$5 per million."
},
{
"term": "Claude.ai",
"tldr": "The chat website. claude.ai is Anthropic's consumer product — the place a non-developer goes to chat with Claude.",
"detail": "Free tier exists. Pro ($20/mo) and Max ($100/mo or $200/mo) get bigger context, file uploads, Claude Code access. SDCC staff could use claude.ai for ad-hoc research without any setup."
},
{
"term": "Claude API",
"tldr": "The developer interface for Claude. Apps like Norma call this to do inference programmatically.",
"detail": "Pay-as-you-go pricing per token. Console at console.anthropic.com — where you get API keys. The key looks like `sk-ant-api03-...`. NEVER commit API keys to git."
},
{
"term": "Claude Code",
"tldr": "Anthropic's official command-line tool for Claude. Runs in your terminal, edits files, runs commands, builds whole projects.",
"detail": "What Steve uses to build Norma + this pitch viewer. Install with: `npm install -g @anthropic-ai/claude-code`, then run `claude` in any project directory. Authenticate via Claude Max subscription or API key.",
"example": "Type `claude` in a terminal → opens an interactive prompt → 'add a search bar to this page' → Claude reads the files, makes edits, runs tests."
},
{
"term": "Anthropic Console",
"tldr": "console.anthropic.com — where developers manage API keys, see usage, set up billing.",
"detail": "Also has a 'workbench' for trying prompts against the API without writing code. SDCC's API key would be issued from here."
},
{
"term": "Claude Projects (the feature)",
"tldr": "A feature inside claude.ai where you attach documents + give Claude persistent instructions for a recurring task.",
"detail": "Not the same as 'a Norma project'. Claude Projects = lightweight chat workspaces. Norma = structured, audited, integrated platform. Both can coexist — staff use claude.ai Projects for ad-hoc research; Norma handles the structured work."
},
{
"term": "Constitutional AI",
"tldr": "Anthropic's approach to making models safer — training them to follow a set of principles ('the constitution') instead of relying purely on human feedback.",
"detail": "Means Claude tends to be more cautious about harmful, dishonest, or extremist outputs. For SDCC: Claude won't help draft something defamatory or generate misleading content even if asked. Good for advocacy: less risk of producing material that backfires."
},
{
"term": "Anthropic responsible-use policy",
"tldr": "The legal/usage terms you sign when using Anthropic's API. Bans certain use cases (mass surveillance, deepfakes, election interference).",
"detail": "Norma's design respects these — no impersonation of public officials, no manipulating elections, full audit trail of who used what. Worth reviewing at anthropic.com/legal/aup before SDCC commits to scaled use."
}
]
},
{
"id": "sdcc-llm",
"label": "The 'SDCC LLM' — what's actually under the hood",
"icon": "🎯",
"terms": [
{
"term": "The 'SDCC LLM'",
"tldr": "There isn't one — and that's intentional. 'SDCC's LLM' = Anthropic's Claude + SDCC's prompts + SDCC's data + SDCC's integrations.",
"detail": "The model itself is the same Claude that any other Anthropic customer uses. What makes SDCC's experience unique is the LAYER ON TOP — Norma. Norma carries SDCC's voice library (prior statements, talking points), SDCC's knowledge base (petition archive, borrower stories), SDCC's prompts (tuned for advocacy + nonprofit voice), and SDCC's integrations (Gmail, Slack, EveryAction if you connect it).",
"example": "When SDCC asks 'draft a press response to ED's announcement', Norma sends Claude: (1) a system prompt with SDCC's voice rules, (2) the top 5 most-relevant prior SDCC statements (retrieved via RAG), (3) the user's specific ask. Claude generates a response that sounds like SDCC because the prompt is loaded with SDCC context."
},
{
"term": "Why this matters",
"tldr": "SDCC keeps the upside (custom voice, knowledge moat, integrations) without the downside (training your own model = $millions and months).",
"detail": "Training an actual SDCC-specific model would cost $1M+ and take 6+ months. Plus you'd need to retrain when the world changes. The 'context layer' approach gives 90% of the benefit at 0.1% of the cost. As Claude improves, SDCC gets the improvements for free."
},
{
"term": "Voice library",
"tldr": "The collection of prior SDCC writing (statements, op-eds, petitions) Norma feeds Claude as style examples.",
"detail": "Curated by Natalia + Sabrina. Updated quarterly. Every draft passes through it so output sounds like SDCC, not generic-nonprofit-bot."
},
{
"term": "Knowledge base",
"tldr": "The structured data Norma can query — petitions, borrower stories, coalition org info, policy moves, news mentions.",
"detail": "Lives in Postgres on SDCC's tenancy. Indexed for fast search + embedded for semantic search. Grows over time as staff use Norma."
},
{
"term": "Tenant / Tenancy",
"tldr": "SDCC's isolated workspace inside Norma. SDCC's data is fully separate from any other org using Norma.",
"detail": "Multi-tenant architecture: one platform, many orgs, complete data separation. SDCC's borrower stories never appear in another org's search results — guaranteed at the database level, not just the UI."
}
]
},
{
"id": "install-hookup",
"label": "Install + hook up Claude on your computer",
"icon": "🔌",
"terms": [
{
"term": "Step 1 — Install Node.js",
"tldr": "Norma + Claude Code both need Node.js 18+ to run.",
"detail": "Download from nodejs.org (LTS version) OR `brew install node` on macOS. Verify after install: `node --version` (should print v18+ or v20+), `npm --version` (should print 10+).",
"example": "$ node --version\nv20.10.0\n$ npm --version\n10.2.3"
},
{
"term": "Step 2 — Install Claude Code (the CLI)",
"tldr": "One command. Globally installed so you can run `claude` from any directory.",
"detail": "`npm install -g @anthropic-ai/claude-code`. The `-g` makes it global. After install, type `claude --version` to confirm. First time you run `claude` in a project, it'll ask you to sign in.",
"example": "$ npm install -g @anthropic-ai/claude-code\n$ claude --version\n2.1.145"
},
{
"term": "Step 3 — Authenticate Claude Code",
"tldr": "Two options: sign in with Claude Max (subscription) or paste an API key (pay-per-use).",
"detail": "Run `claude` in a terminal. First time: browser opens for Claude Max sign-in, OR it prompts for an API key. Pick Claude Max if you have a Max subscription ($100/mo gets you a lot of Claude Code usage). Pick API key if you want metered billing only."
},
{
"term": "Step 4 — Get an Anthropic API key",
"tldr": "If you're going API-key route: get one from console.anthropic.com.",
"detail": "Sign up at console.anthropic.com. Add billing info (need a credit card). API Keys → Create Key. Copy the `sk-ant-...` string. Paste it when Claude Code asks, OR set it as env var: `export ANTHROPIC_API_KEY='sk-ant-...'`."
},
{
"term": "Step 5 — Hook Claude to a project",
"tldr": "cd into the project directory. Run `claude`. That's the whole step.",
"detail": "Claude Code reads the current directory's CLAUDE.md (if any) for context, ignores files in .gitignore, and inherits your shell environment. No project-level setup beyond optionally writing a CLAUDE.md.",
"example": "$ cd ~/Projects/norma\n$ claude\nWelcome to Claude Code 2.1.145\n>"
},
{
"term": "Step 6 — Hook Norma to Anthropic",
"tldr": "Norma needs ANTHROPIC_API_KEY in its .env.local file.",
"detail": "Edit ~/Projects/Norma/.env.local. Add the line: `ANTHROPIC_API_KEY=sk-ant-...`. Restart the dev server (`npm run dev`). Norma will now use that key for every Claude call.",
"example": "$ echo 'ANTHROPIC_API_KEY=sk-ant-api03-...' >> ~/Projects/Norma/.env.local\n$ pkill -f 'next dev' && cd ~/Projects/Norma && npm run dev"
},
{
"term": "Step 7 — Verify it's hooked up",
"tldr": "Visit a route that uses Claude. If it returns real content, you're connected.",
"detail": "Try POSTing to `/api/agents/petition/generate` with a topic. If it generates real petition copy, the key is valid + Norma is talking to Anthropic. If it 500s with 'invalid API key' — your key is wrong. If it 503s — check rate limits/billing."
}
]
},
{
"id": "mcp-protocol",
"label": "MCP — the protocol that connects Claude to tools",
"icon": "🔗",
"terms": [
{
"term": "MCP (Model Context Protocol)",
"tldr": "Anthropic's open protocol for connecting LLMs to external tools, data sources, and services. Think USB for AI.",
"detail": "Before MCP, every AI app reinvented its own way to give the model access to (Gmail, Slack, Postgres, file systems, etc). MCP standardizes that. Any 'MCP server' can plug into any 'MCP client' — Claude.ai, Claude Code, Norma, third-party AI apps. Open spec at modelcontextprotocol.io.",
"example": "If SDCC wanted to give Claude direct read access to its EveryAction CRM, you'd run an EveryAction MCP server and Claude would automatically discover its tools (lookup_donor, recent_donations, etc)."
},
{
"term": "MCP Server",
"tldr": "A program that exposes a set of tools/data to MCP clients. Runs on your machine or a remote host.",
"detail": "Steve has dozens of these — a Gmail MCP server, a domain-suite MCP server, a Cloudflare MCP server. Each exposes a few related tools (e.g. `gmail_send`, `gmail_list_messages`). Claude Code automatically loads them at startup."
},
{
"term": "MCP Client",
"tldr": "The app that USES MCP servers. Claude.ai, Claude Code, and Norma can all be MCP clients.",
"detail": "When a client starts, it connects to its configured MCP servers, discovers what tools each offers, and presents them to the LLM. The LLM can then decide to invoke them mid-conversation."
},
{
"term": "Tool (in MCP terms)",
"tldr": "A single function an MCP server exposes. Has a name, description, parameters, and a way to execute.",
"detail": "Example tool: `search_petitions(query: string, limit: int) -> Petition[]`. The MCP server defines it, the LLM decides when to call it."
},
{
"term": "Resource (in MCP terms)",
"tldr": "A piece of data an MCP server exposes (rather than a function). Like 'the latest news brief' or 'this Postgres table'.",
"detail": "Tools are verbs, resources are nouns. The LLM can read resources without 'calling' them."
}
]
},
{
"id": "models-other",
"label": "Other LLMs you'll hear about",
"icon": "🤖",
"terms": [
{
"term": "Hermes (Nous Research)",
"tldr": "An open-weight LLM family from Nous Research. Run locally via Ollama as a free alternative to commercial APIs.",
"detail": "Hermes 3 ships in 8B / 70B / 405B parameter sizes. Smaller versions run on a laptop GPU; larger ones need real hardware. Used by some teams for sensitive data they don't want to send to commercial APIs. Norma DOES NOT use Hermes — Norma uses Claude. But you'll see it in the broader ecosystem and Steve's debate-team agents sometimes route through local Ollama models.",
"example": "Install Ollama (ollama.ai), then `ollama pull hermes3:8b`, then `ollama run hermes3:8b`. Runs entirely on your machine."
},
{
"term": "GPT (OpenAI)",
"tldr": "OpenAI's LLM family — GPT-4, GPT-4o, GPT-5. The biggest direct competitor to Claude.",
"detail": "Norma doesn't use GPT by default. Some Steve workflows do (the 'debate-team' agents put Claude + GPT-5-codex + Qwen in adversarial review). For SDCC, sticking to one provider (Anthropic/Claude) is the simpler default."
},
{
"term": "Gemini (Google)",
"tldr": "Google's LLM family. Strong on multi-modal (images, video) and long context.",
"detail": "Norma uses Gemini ONLY for image analysis (vision tasks where it's notably good). Text inference all goes through Claude."
},
{
"term": "Llama (Meta)",
"tldr": "Meta's open-weight LLM family. Llama 3, Llama 3.3.",
"detail": "Free to download + run locally. Foundation many other open models build on. Same caveats as Hermes — Norma uses Claude, but you'll see Llama in the wider ecosystem."
},
{
"term": "Qwen (Alibaba)",
"tldr": "Alibaba's open-weight LLM family. Strong on coding + multi-language.",
"detail": "Steve runs Qwen3:14B locally via Ollama as the 'free third opinion' in adversarial debate panels. Not part of SDCC's stack."
},
{
"term": "Ollama",
"tldr": "A tool for running open-weight LLMs (Llama, Hermes, Qwen, etc) locally on your machine.",
"detail": "Free. Install at ollama.ai. After install: `ollama pull llama3.3` then `ollama run llama3.3`. The model runs entirely offline on your machine. Slower than Claude API, but no per-token cost and no data leaves your computer."
}
]
},
{
"id": "web-backend",
"label": "Web + backend basics",
"icon": "🌐",
"terms": [
{
"term": "API (Application Programming Interface)",
"tldr": "A contract that lets one program talk to another over the network. Send a request, get a response.",
"detail": "Modern APIs are usually REST or GraphQL. You send HTTP requests (GET, POST, PUT, DELETE) to URLs. Responses come back as JSON. Norma exposes 200+ API endpoints internally."
},
{
"term": "REST / RESTful",
"tldr": "A pattern for APIs based on HTTP verbs + URL paths. The default for most modern web APIs.",
"detail": "`GET /api/petitions` = list petitions. `POST /api/petitions` = create one. `GET /api/petitions/123` = fetch petition 123. `DELETE /api/petitions/123` = remove it. Predictable, simple, well-tooled."
},
{
"term": "HTTP / HTTPS",
"tldr": "The protocol the web is built on. HTTP = plaintext. HTTPS = encrypted (TLS). Always use HTTPS in production.",
"detail": "Status codes you'll see: 200 (ok), 301/307 (redirect), 400 (bad request), 401 (unauthenticated), 403 (forbidden), 404 (not found), 500 (server crash), 503 (overloaded)."
},
{
"term": "JSON",
"tldr": "The text format APIs send data in. Looks like JavaScript objects.",
"detail": "`{\"name\":\"SDCC\",\"founded\":2013}`. Universal across languages — every modern language can parse and produce JSON. Norma's APIs all send/receive JSON."
},
{
"term": "Endpoint",
"tldr": "A single URL on an API. Each endpoint usually does one thing.",
"detail": "`/api/petitions/topics` is an endpoint. `/api/agents/petition/generate` is another. Together they form 'the Norma API'."
},
{
"term": "Database",
"tldr": "Where your data persists between requests. The thing that survives server restarts.",
"detail": "Norma uses Postgres (Postgres = PostgreSQL = the same database). SDCC's borrower stories, petition data, audit logs all live in Postgres on the SDCC tenant."
},
{
"term": "PostgreSQL (Postgres)",
"tldr": "The relational database Norma uses. Open-source, battle-tested, fast.",
"detail": "Stores data in tables with rows and columns (like a spreadsheet, but with strict schemas and SQL queries). The `sdcc` database in this dev environment holds SDCC's data."
},
{
"term": "SQL (Structured Query Language)",
"tldr": "The language you use to ask the database questions.",
"detail": "`SELECT title FROM petitions WHERE status='active' ORDER BY created_at DESC LIMIT 5;` — that's SQL. Returns the 5 most recent active petitions."
},
{
"term": "Cookie / Session",
"tldr": "A bit of data the browser holds that proves you're logged in.",
"detail": "When you log into Norma, the server sends back a `Set-Cookie: norma-auth=...` header. Your browser sends that cookie back on every subsequent request. The server reads it to know you're admin / staff / pulse."
},
{
"term": "OAuth",
"tldr": "A standard protocol for 'sign in with Google' (or Gmail, or X, or anything else).",
"detail": "Norma uses OAuth for Gmail integration. Instead of asking for SDCC's Gmail password, it redirects to Google, has the user grant permission, and gets back a token. SDCC's password is never seen by Norma."
}
]
},
{
"id": "norma-specifics",
"label": "Norma platform glossary",
"icon": "🛠️",
"terms": [
{
"term": "Norma (the platform)",
"tldr": "The multi-tenant nonprofit intelligence platform SDCC would license. Three tiers of access: admin, staff, pulse.",
"detail": "Built on Next.js 16 + Postgres + Tailwind. Runs at localhost:7400 in dev. In production it runs on cloud servers (e.g., Kamatera, AWS, GCP — SDCC picks)."
},
{
"term": "Pulse (the page)",
"tldr": "Norma's daily-briefing landing page at /pulse. The morning standup view.",
"detail": "Surfaces: today's petitions, active news cycles, urgent borrower stories, coalition activity. The 'open this first' page."
},
{
"term": "Tier credentials",
"tldr": "The three login roles in Norma. admin = full access. staff = SDCC team. pulse = end users (borrowers, public).",
"detail": "Stored in the `tier_credentials` table. Each row has username, hashed password, role, optional org_id. Steve uses bcrypt for new passwords; older ones get auto-upgraded."
},
{
"term": "Loop (Norma)",
"tldr": "An always-on background job that runs every N minutes/hours. Inbox scans, news ingestion, signature counting.",
"detail": "See section 4 of this viewer for full explanation."
},
{
"term": "Cron job (Norma)",
"tldr": "A scheduled task — runs on a calendar instead of a timer.",
"detail": "See section 5 of this viewer."
},
{
"term": "Audit trail",
"tldr": "Immutable log of every AI decision, send, approval. The compliance backbone.",
"detail": "Stored in append-only tables. Queryable by date, actor, action, resource. Whether a funder, board member, or regulator asks 'who did X?' — one query answers it."
},
{
"term": "Skill (in Steve's stack)",
"tldr": "A reusable bundle of instructions + helper scripts that Claude Code can invoke.",
"detail": "Steve has 200+ skills in ~/.claude/skills/. Examples: a `settlement` skill that legally vets wallpaper generations, a `george-inbox` skill that triages info@ mail. Skills are project-specific superpowers."
},
{
"term": "Agent (in Steve's stack)",
"tldr": "A specialized Claude sub-process spawned to handle one type of task with custom instructions + tools.",
"detail": "Steve has 50+ agents (in ~/.claude/agents/). Examples: `lawyer-build-agent` for the lawyer directory project, `doctor-agent` for the doctor directory. Each has its own system prompt + tool allowlist."
}
]
},
{
"id": "hosting-deploy",
"label": "Hosting + deployment",
"icon": "☁️",
"terms": [
{
"term": "Server (cloud)",
"tldr": "A computer that's NOT yours, that runs your app 24/7 and serves it to the internet.",
"detail": "When SDCC actually adopts Norma, it runs on a cloud server — AWS, Google Cloud, Kamatera (Steve's preference), or similar. SDCC's borrower data lives on that server (in SDCC's tenancy, isolated from other orgs)."
},
{
"term": "Domain (DNS)",
"tldr": "The human-readable address. e.g. norma.studentdebtcrisis.org. DNS is what turns the domain into the server's IP address.",
"detail": "SDCC would point a subdomain (e.g., norma.studentdebtcrisis.org or pulse.studentdebtcrisis.org) at the production server."
},
{
"term": "SSL / TLS / HTTPS cert",
"tldr": "The encryption that makes the URL show a 🔒 padlock in the browser.",
"detail": "Let's Encrypt issues free SSL certs that auto-renew every 90 days. Critical for any site handling user data."
},
{
"term": "pm2",
"tldr": "A process manager that keeps Node.js apps running. Restarts them if they crash.",
"detail": "Norma runs under pm2 in production. `pm2 list` shows all running apps. `pm2 logs norma` tails the live log. `pm2 restart norma` reloads after a code change."
},
{
"term": "Docker / Container",
"tldr": "A way to package an app + everything it needs (libraries, configs) into a portable bundle.",
"detail": "Norma isn't dockerized today, but could be. Containers make 'works on my laptop, works on the server' actually true."
},
{
"term": "Deployment",
"tldr": "The process of taking new code from your laptop → onto the production server → live for users.",
"detail": "Typical flow: commit to git → push to GitHub → CI/CD pipeline (GitHub Actions) builds + tests + ships to server → users see the change. Steve uses a `deploy` skill that does rsync + pm2 reload + smoke-test."
}
]
}
]
},
"token_vault": {
"headline": "Token Vault — every API key in one place",
"intro": "SDCC needs ~10 keys to fully light up Norma. Store them here once; Norma reads from this vault. Last 4 digits only echo back — full values stay encrypted on the server.",
"categories": [
{
"id": "ai",
"label": "AI providers",
"icon": "🤖",
"tokens": [
{ "key": "ANTHROPIC_API_KEY", "label": "Anthropic (Claude)", "placeholder": "sk-ant-api03-...", "where": "console.anthropic.com → API Keys", "required": true, "notes": "Primary LLM for all drafts, statements, classifications." },
{ "key": "GEMINI_API_KEY", "label": "Gemini (Google)", "placeholder": "AIza...", "where": "ai.studio.google.com → Get API key", "required": false, "notes": "Vision tasks + cheap classification. Optional fallback." },
{ "key": "ELEVENLABS_API_KEY", "label": "ElevenLabs (voice)", "placeholder": "sk_...", "where": "elevenlabs.io → Profile → API Key", "required": false, "notes": "For audio narration in case studies, social audio, video voiceovers." }
]
},
{
"id": "email",
"label": "Email + Comms",
"icon": "📬",
"tokens": [
{ "key": "GMAIL_OAUTH_CLIENT_ID", "label": "Gmail OAuth Client ID", "placeholder": "....apps.googleusercontent.com", "where": "console.cloud.google.com → APIs & Services → Credentials", "required": true, "notes": "For info@studentdebtcrisis.org inbox triage + draft replies." },
{ "key": "GMAIL_OAUTH_CLIENT_SECRET", "label": "Gmail OAuth Client Secret", "placeholder": "GOCSPX-...", "where": "Same as above, click client → secret", "required": true },
{ "key": "GMAIL_REFRESH_TOKEN", "label": "Gmail Refresh Token", "placeholder": "1//...", "where": "Generated by Norma after first OAuth flow", "required": false, "notes": "Auto-populates after first sign-in. Don't set manually." },
{ "key": "MAILGUN_API_KEY", "label": "Mailgun (bulk send)", "placeholder": "key-...", "where": "mailgun.com → Settings → API Keys", "required": false, "notes": "Only if you want Norma to send instead of EveryAction." }
]
},
{
"id": "advocacy",
"label": "Advocacy + Donations",
"icon": "🏛️",
"tokens": [
{ "key": "EVERYACTION_API_KEY", "label": "EveryAction API", "placeholder": "your-app:your-key", "where": "EveryAction → Settings → API Integrations", "required": false, "notes": "Sync supporters bidirectionally — Norma writes back to EveryAction so your CRM of record stays canonical." },
{ "key": "ACTBLUE_API_KEY", "label": "ActBlue (donations)", "placeholder": "Bearer ...", "where": "ActBlue → Account → API", "required": false, "notes": "Pull donation data for donor radar + renewal cron." },
{ "key": "ACTION_NETWORK_API_KEY", "label": "Action Network", "placeholder": "OSDI-...", "where": "actionnetwork.org → Settings → API & Sync", "required": false, "notes": "Two-way sync of supporters, petitions, events, taggings via the OSDI API. Norma can: pull AN supporters into the borrower-story classifier, push AN petitions Norma generated, write back tags + activity. AN's OSDI spec is the open standard for advocacy-data exchange." },
{ "key": "MOVEON_API_KEY", "label": "MoveOn (petitions + actions)", "placeholder": "your-moveon-token", "where": "petitions.moveon.org → Settings → API access (request via partner@moveon.org)", "required": false, "notes": "Sync petition signatures + supporter mobilizations. MoveOn API is partner-gated — request access through partnerships team. Once approved, Norma surfaces SDCC-MoveOn co-branded petitions, pulls signature velocity, and triggers coalition activation." }
]
},
{
"id": "productivity",
"label": "Productivity + Workspace",
"icon": "🗂️",
"tokens": [
{ "key": "SLACK_WEBHOOK_URL", "label": "Slack incoming webhook", "placeholder": "https://hooks.slack.com/services/...", "where": "Slack admin → Apps → Incoming Webhooks", "required": false, "notes": "Where high-urgency triage routes land." },
{ "key": "SLACK_BOT_TOKEN", "label": "Slack Bot Token", "placeholder": "xoxb-...", "where": "api.slack.com/apps → OAuth & Permissions", "required": false, "notes": "Read DM channels + post messages programmatically." },
{ "key": "CLICKUP_API_TOKEN", "label": "ClickUp", "placeholder": "pk_...", "where": "ClickUp → Settings → Apps", "required": false, "notes": "If SDCC uses ClickUp for project tracking." }
]
},
{
"id": "data",
"label": "Data + Intelligence",
"icon": "📡",
"tokens": [
{ "key": "PROPUBLICA_CONGRESS_KEY", "label": "ProPublica Congress API", "placeholder": "registration-key", "where": "projects.propublica.org/api-docs", "required": false, "notes": "Free key. Powers congress-by-zip + bill-tracking." },
{ "key": "GOOGLE_CIVIC_API_KEY", "label": "Google Civic Information", "placeholder": "AIza...", "where": "console.cloud.google.com → enable Civic API", "required": false, "notes": "Backup for ZIP → reps lookup." },
{ "key": "NEWSAPI_KEY", "label": "NewsAPI (or alt)", "placeholder": "your-newsapi-key", "where": "newsapi.org → Get API key", "required": false, "notes": "Backup feed source for the news-intelligence loop." },
{ "key": "OPEN_STATES_API_KEY", "label": "Open States API", "placeholder": "your-key", "where": "openstates.org/data", "required": false, "notes": "State-legislature tracking. Free up to 500/day." }
]
},
{
"id": "norma_internal",
"label": "Norma internals (auto-managed)",
"icon": "🔐",
"tokens": [
{ "key": "DATABASE_URL", "label": "Postgres connection", "placeholder": "postgresql://user:pass@host:5432/db", "where": "Your DB provider (Supabase, Railway, RDS, etc)", "required": true, "notes": "Where SDCC's data lives." },
{ "key": "COOKIE_SECRET", "label": "Session cookie secret", "placeholder": "(generated for you)", "where": "Auto-generated on first install", "required": true, "notes": "Don't change — invalidates all logins." },
{ "key": "SDCC_ADMIN_PASSWORD", "label": "Norma admin password", "placeholder": "your-strong-password", "where": "You set this", "required": true, "notes": "Initial admin login. Rotate quarterly." }
]
}
],
"instructions": [
"Never commit these to git. The .env file is in .gitignore — leave it that way.",
"Rotate every 90 days for the AI provider keys (Anthropic, Gemini).",
"If a key leaks, revoke it at the provider first, then update here, then restart Norma.",
"The vault shows only the last 4 chars on read — full values stay server-side."
]
},
"gamify": {
"xp_per_quiz": 25,
"xp_per_correct": 10,
"xp_per_section_complete": 50,
"xp_per_term_learned": 5,
"levels": [
{ "min": 0, "name": "Pitch Apprentice", "color": "#6b7280" },
{ "min": 100, "name": "Pitch Builder", "color": "#1b4d7a" },
{ "min": 250, "name": "Pitch Strategist", "color": "#7c3aed" },
{ "min": 450, "name": "Pitch Master", "color": "#b45309" },
{ "min": 700, "name": "SDCC-Ready", "color": "#047857" }
],
"badges": [
{ "id": "first_quiz", "name": "First Quiz", "criteria": "Complete any quiz", "icon": "🎯" },
{ "id": "perfect_quiz", "name": "Perfect Score", "criteria": "Get 100% on any quiz", "icon": "💎" },
{ "id": "all_sections", "name": "Lecture Complete", "criteria": "Complete all section quizzes", "icon": "🎓" },
{ "id": "ran_example", "name": "Ran a Real Example", "criteria": "Hit a real Norma API", "icon": "⚡" },
{ "id": "pitch_3", "name": "Three's the Pitch", "criteria": "Include 3+ agents in your pitch", "icon": "📋" },
{ "id": "skipper", "name": "Curator", "criteria": "Skip at least 2 agents (keeping pitch clean)", "icon": "✂️" },
{ "id": "asked_questions", "name": "Interviewer", "criteria": "Open the 'Questions to Ask' modal", "icon": "❓" },
{ "id": "unknown_aware", "name": "Self-Aware", "criteria": "Open the 'Unknown Unknowns' modal", "icon": "🔮" },
{ "id": "vocab_starter", "name": "Vocab Starter", "criteria": "Mark 5 glossary terms as learned", "icon": "📖" },
{ "id": "vocab_champ", "name": "Vocab Champ", "criteria": "Mark 20 glossary terms as learned", "icon": "📚" }
]
}
}