← Blog

How to Build a Claude-Powered Meeting Notes App

2026-11-06 · 5 min read · SubToAPI Team

Building a Claude-powered meeting notes app comes down to four parts: getting a transcript into text, sending it to Claude with a prompt that produces consistent structure, extracting action items and decisions as structured data, and storing the result somewhere searchable. None of this requires a large team — a working prototype can be built in an afternoon if you pick the right pieces.

This guide walks through the architecture, the prompt design decisions that actually matter, and how to turn raw Claude output into something your app can render and query reliably, rather than a wall of unstructured text.

What the app actually needs to do

A meeting notes app built on Claude typically needs to:

Claude is good at the summarization and extraction steps. The engineering work is mostly in transcript handling and making the output structured enough for your UI to consume without brittle string parsing.

Step 1: Get a clean transcript

If you're not building your own speech-to-text pipeline, use an existing transcription service and normalize its output before sending it to Claude. At minimum, strip filler words sparingly (don't over-clean — "um" and false starts sometimes matter for context) and attach speaker labels if available:

[Speaker 1] Let's start with the Q3 roadmap.
[Speaker 2] Before that, can we revisit the pricing decision from last week?

Speaker labels dramatically improve Claude's ability to attribute action items correctly ("Speaker 2 will follow up on pricing by Friday") instead of guessing.

Step 2: Chunk long meetings

Claude handles long context well, but a 90-minute meeting transcript can still run tens of thousands of tokens once you include timestamps and speaker tags. Two practical approaches:

  1. Single call for meetings under ~45 minutes. Just send the whole transcript in one request.
  2. Rolling summary for longer meetings. Summarize in 15-minute chunks, carry forward a running summary, and feed that plus the new chunk into each subsequent call. This keeps latency and cost predictable and avoids losing early context.

For most teams, start with approach one and only add chunking once you see real meetings that exceed your context budget.

Step 3: Design the prompt for structured notes

Vague prompts ("summarize this meeting") produce inconsistent formatting across meetings, which makes your UI fragile. Be explicit about the output shape:

You are generating structured meeting notes from a transcript.

Return your response as:
1. A 2-3 sentence summary of the meeting's purpose and outcome
2. Key discussion points (bulleted)
3. Decisions made (bulleted, with who made each decision)
4. Action items as a list of objects: { "owner": string, "task": string, "due": string or null }

Transcript:
{{transcript}}

For the action items section specifically, you get far more reliable parsing if you ask Claude to use tool use (function calling) rather than free text. Define a schema like:

{
  "name": "extract_action_items",
  "description": "Extract action items from a meeting transcript",
  "input_schema": {
    "type": "object",
    "properties": {
      "action_items": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "owner": { "type": "string" },
            "task": { "type": "string" },
            "due_date": { "type": ["string", "null"] }
          },
          "required": ["owner", "task"]
        }
      }
    },
    "required": ["action_items"]
  }
}

This guarantees valid, parseable JSON back instead of hoping Claude's bullet formatting matches a regex. See /docs/tools for details on defining and handling tool calls.

Step 4: Call the API

If you're routing requests through SubToAPI, the call looks like a standard Messages request with your sub_live_ key:

curl https://api.subtoapi.app/v1/messages \
  -H "Authorization: Bearer $SUBTOAPI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4",
    "max_tokens": 1024,
    "tools": [ /* action_items schema here */ ],
    "messages": [
      { "role": "user", "content": "Transcript:\n[Speaker 1] ..." }
    ]
  }'

See /docs/messages for the full request/response shape and /docs/quickstart if you're setting up your first key. SubToAPI gives each app or environment its own sub_live_ key and tracks usage per key, which matters once you have separate dev, staging, and production meeting-notes pipelines sharing one Claude plan.

Step 5: Stream notes live (optional)

For a "notes appear while the meeting happens" experience, stream Claude's response token-by-token instead of waiting for the full summary:

const response = await fetch("https://api.subtoapi.app/v1/messages", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.SUBTOAPI_KEY}`,
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    model: "claude-sonnet-4",
    max_tokens: 1024,
    stream: true,
    messages: [{ role: "user", content: transcriptChunk }]
  })
});

Streaming is more useful for live-updating summaries during long calls than for the final structured action items, which you'll usually want to generate once the meeting ends and the full transcript is available. Details on handling the stream are in /docs/streaming.

Step 6: Store and make notes searchable

Once you have structured output, store it as rows (meeting_id, summary, decisions, action_items) rather than flat markdown. This lets you build obvious follow-up features cheaply: "show me all open action items assigned to me," "search past decisions about pricing," or weekly digest emails — all without re-calling Claude.

Tying it together for a team

If multiple people on your team are building or maintaining this app, usage visibility matters once you're past the prototype. SubToAPI's dashboard shows per-key usage so you can see which environment or feature (live summaries vs. end-of-meeting extraction) is driving cost, and team seats on the Team (€19/seat) or Scale (€49/seat) plans let you manage keys without sharing one shared secret across the team. The Solo plan (€9) is enough to get a single app from prototype to production. Check /pricing for the full breakdown, or start with a free trial at /signup.

Questions

Do I need Claude's largest context model for long meetings? Not necessarily. A rolling-summary approach (summarize in chunks, carry a running summary forward) works well for very long meetings and keeps costs lower than sending the entire transcript in one call.

How do I stop Claude from hallucinating action items that weren't said? Keep the prompt grounded in the transcript explicitly ("only include action items that were explicitly stated") and use tool use with a strict schema — it reduces free-text drift and makes missing fields (like a null due date) explicit rather than invented.

Should I generate notes after the meeting or stream them live? Stream a rolling summary during the call for a live "notes so far" view, but run the full action-item extraction once at the end against the complete transcript — it's more accurate than stitching together partial extractions.

Turn your Claude access into an HTTPS API

SubToAPI gives you application API keys, streaming, tool use and usage insights on top of your existing Claude access — set up in minutes.

Start free  Read the quickstart →