Meeting audit dashboard that shows what recurring meetings cost

By General Input

See every standing meeting ranked by what it really costs, who does all the talking, and which ones finish with nothing decided.

Integrations

  • Fireflies.ai
  • Google Sheets
  • Slack Bot

Type

App

Categories

  • Operations
  • Finance

Build me a meeting audit dashboard that our ops lead and chief of staff open ahead of each quarterly review, to answer one question: which of our recurring meetings still deserve to exist. It runs on Fireflies.ai for the meeting data, Google Sheets for the decision record that survives between reviews, and Slack Bot for sharing the outcome. This is a surface a person opens and works in, not something that runs on a schedule.

At the top I pick a period, with presets for last quarter, the last ninety days, and the last six months, plus a custom range. Load every meeting in that window with Fireflies.ai List Transcripts using the fromDate and toDate filters. The limit maxes out at 50 and pagination is offset based through skip, so advance skip by the limit until a page comes back short, and follow every page or long periods will quietly under-report. Pull this list once per period and cache it app-side, because the whole design has to respect Fireflies rate limits: 50 requests per day on Free and Pro, 60 per minute on Business and Enterprise. Show real progress while a period loads.

Group the transcripts into recurring series by meeting title. Normalize before matching: trim whitespace, lowercase, and strip the noise that makes one standing meeting look like twenty different ones, such as trailing dates, week or sprint numbers, and bracketed suffixes like Weekly or Recurring. Show each series label next to its occurrence count so it is obvious when grouping went wrong, and let me merge two series into one, split one apart, or rename a series label by hand. Store those manual corrections app-side keyed to the series identity so they stick for future periods and I only ever fix a series once.

The main view is one row per series. Every row carries the series name, how many times it met in the period, total recorded hours, total person-hours, estimated cost, the talk time split across speakers, the share of occurrences that finished with no action items at all, the attendee count, and whatever I decided about this series in a previous review. Person-hours is the number that makes the argument, so make it prominent: for each occurrence multiply the recorded duration by the number of distinct human attendees, then sum across the period. Check what unit Fireflies returns duration in before converting to hours rather than assuming seconds. De-duplicate attendees by email, and exclude the Fireflies notetaker itself from attendee counts, since it is not a person whose time is being spent.

I set an hourly rate once in settings and the dashboard puts an estimated cost on every series: person-hours multiplied by the rate. Let me override the rate for an individual series when the room is unusually senior or junior. Show the cost for the selected period and also a projected annual cost based on the observed cadence, because the annual figure is usually what actually ends a meeting.

Talk time and action items only exist on the full transcript, which means Fireflies.ai Get Transcript once per meeting, and that is expensive under the rate limits. Do not fetch them for the whole period up front. Enrich one series at a time, on demand, when I expand a row or hit Analyze on it, then cache the result app-side keyed to the transcript id so no transcript is ever fetched twice. Tell me how many requests an enrichment will cost before it runs, and keep a visible counter of what has been spent today. From each transcript, use the per speaker analytics to compute each speaker's share of talk time, and read the action items off the summary. Fireflies returns action items as a text block rather than a structured list, so treat empty, whitespace, and a literal none as zero action items, and only flag an occurrence as having produced nothing when it genuinely came back with nothing.

Sort worst first by default. Compute an audit score per series combining the three signals that make a meeting a candidate for the axe: how much it costs in person-hours, how lopsided the talk time is with the top speaker's share measured against a threshold I can set and defaulting to seventy percent, and what share of its occurrences ended with no action items. The standing meeting burning twelve person-hours a month with one person talking eighty percent of the time and producing nothing should sit at the top of the list without me sorting anything. Let me switch the sort to plain cost, total hours, or talk time dominance, and show the individual signals as badges on the row so the ranking is never a black box.

Two filters matter, and both need defaults that match how this is really used. Exclude one-to-one meetings by default, since talk time balance means nothing when there are two people in the room, with a toggle to bring them back in. Identify one-to-ones as two distinct human attendees once the notetaker is excluded. Second, apply a minimum occurrence filter so a series only appears once it has met three or more times, with the threshold adjustable, so genuinely new or ad hoc meetings are not put on trial.

Every series gets an Audit this meeting button that kicks off a background agent. The agent reads that series' transcripts across its history with Get Transcript, not only the occurrences inside the selected period, and writes a recommendation back into the app so the row can display it. The recommendation is one of five verdicts: keep as is, shorten, drop to fortnightly, cut the attendee list to these named people, or cancel. Underneath the verdict it lays out the evidence as direct quotes from the meetings, each labeled with the date it came from, so I can defend the call to whoever owns that meeting. When the verdict is to cut the attendee list, it has to name who should stay and who should drop, based on who actually spoke and who was named in the action items. Show the audit as running and then landed on the row itself, keep the previous audit visible until a new one finishes, and let me re-run an audit later. Cap how many transcripts a single audit reads and say so in the output, so one click on a long running series does not burn the whole day's rate limit.

On each series I record my own decision, using the same five verdicts as the agent plus a free text note and whether I agreed with the recommendation. Saving a decision appends a row to a Google Sheet with Google Sheets Append Values: decision date, who decided, series name, period audited, occurrences, total hours, person-hours, estimated cost, top speaker share, share of occurrences with no action items, the agent's recommendation, my decision, and my note. Let me point at an existing spreadsheet, or offer to create one with the right headers on first use. Read that sheet back with Google Sheets Get Values whenever the dashboard loads, so every series shows what was decided about it in previous reviews right beside what it still costs today. That readback is the whole point of keeping the record: the most damning thing on this dashboard is a meeting I said I would shorten last quarter that is still ninety minutes long.

Give me a button that posts the audit summary to our leadership channel with Slack Bot Send a Message. The summary covers the period reviewed, total hours and cost across all qualifying series, the worst offenders by cost, the decisions made in this session, and the hours and money that come back if those decisions stick. Let me pick the channel, preview the message, and edit it before it sends. Never post automatically.

Settings hold the hourly rate and any per series overrides, the minimum occurrence threshold, the talk time dominance threshold, the one-to-one toggle, my manual series merges and renames, the tracking spreadsheet, and the default Slack channel. On design: this dashboard exists to turn a vague feeling that there are too many meetings into a number and a quote that someone has to argue with. Lead with the worst-first table and the headline cost, and keep configuration out of the way until it is asked for.

Related prompts

Explore more prompts
Call overdue Xero customers with an AI collections agentLocal listing health board for every location you manageLet support send one-off Loops emails without an engineerA brand asset library your marketing team actually searchesTurn Mailjet email clicks into ranked HubSpot follow-upsClean out the Looker dashboards and Looks nobody opensStop cold emails to anyone with a live deal in PipedriveLiveKit live operations console for room moderationWake up dormant Keap leads with a researched reasoniMessage campaign console with pre-flight checks and delivery board