Build Fireflies.ai
KINDAreplaces $18/mosaves $216/yrback to the verdict
A recorder that joins a meeting as a clearly labelled participant, announces itself, captures audio, transcribes with speaker labels and word timings, produces summaries and action items where every line cites a timestamp, and deletes recordings on a schedule you configured.
Before step 1
Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.
- installfree
Why Runs the bot, the pipeline and the interface.
Get it nodejs.org, or nvm install 22. open ↗
Verify
node --version prints v22 or higher - decidean hour of advice, and it is a prerequisite rather than a formality
Why It decides whether the bot may record at all and what it must say first. Some jurisdictions require every participant's agreement, and a meeting with attendees in different places takes the strictest applicable rule.
Get it Identify where participants typically join from, take the strictest rule, and confirm with someone qualified if this is for a business. Record what you concluded and when.
Verify
A written note names the jurisdictions, the rule applied and the date - decidefree
Why Some platforms restrict or prohibit bots joining, and building against one that does means a tool you cannot use.
Get it Read the terms for the platform you use, and prefer its own recording interface where one exists, since that route is sanctioned.
Verify
The position is recorded with a date and the chosen joining method - installfree, but transcription takes real machine time
Why Citations and playback both need word-level timings, and running locally keeps colleagues' conversations off a third party.
Get it Build whisper.cpp and download a model sized for your machine. open ↗
Verify
Output contains per-word start and end times - have readyfree
Why Diarisation, audio levels and summary quality are all only judgeable against real conversation with more than two people talking over each other.
Get it Ask colleagues, explain what you are testing, and record with their agreement. One meeting should have at least four participants.
Verify
Three recordings exist with documented consent - decidefree
Why Recordings, transcripts, summaries and consent records may need different periods, and automatic deletion has to be built rather than remembered.
Get it Write it before recording anything real: what is kept, how long, and why.
Verify
The policy is written and the deletion job implements it
Data model
Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.
- meetings(id, external_id, title, platform, started_at, ended_at, host_email, consent_state, announced_at) - participants(id, meeting_id, name, email, joined_at, left_at, objected_at) - recordings(meeting_id, storage_key, encrypted, expires_at, deleted_at) - words(meeting_id, ordinal, text, start_ms, end_ms, speaker_label) · the spine everything cites - segments(id, meeting_id, start_ms, end_ms, speaker_label, text) - outputs(id, meeting_id, kind, body, cited_segment_ids_json, validated) · kind is summary, actions or decisions - A meeting where a participant objected has no recording and no transcript. The objection is the record.
Environment variables
These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.
| Variable | Needed | Example | Where the value comes from |
|---|---|---|---|
DATABASE_URLsecret | required | postgres://user:pass@localhost:5432/meetings | Meetings, transcripts and consent records. Personal data with obligations attached. |
RECORDINGS_BUCKET | required | meeting-recordings | Encrypted at rest with lifecycle expiry as a second line of defence. |
BOT_DISPLAY_NAME | required | Notetaker (recording) | How the bot appears in the participant list. It should need no explanation. |
ANNOUNCEMENT_TEXT | required | ./config/announcement.md | What the bot says on joining. Configuration so it can differ by jurisdiction. |
RECORDING_RETENTION_DAYS | required | 30 | Per your written policy. Deletion is automatic and logged. |
TRANSCRIPT_RETENTION_DAYS | required | 365 | Usually longer than the recording, and a separate decision rather than an inherited one. |
CONSENT_RETENTION_DAYS | required | 2555 | Longest, because it is the evidence the recording was disclosed. |
The build, in order
Joining visibly and announcing
The bot joins under a name that says what it is and tells the room.
Something nobody has to ask about. This is the cheapest trust you will ever buy.
Files
src/join.tsIn the first seconds, with the time stored on the meeting.
Files
src/announce.tsRecording ends, file removed. Logged and ignored is the failure mode to avoid.
Files
src/consent.ts
done when · tick each as it passeswatch out- Joining silently under an innocuous name is the behaviour that makes this category distrusted, and in several jurisdictions it is also unlawful. Name the participant so nobody has to ask, announce in the first seconds, and make objecting stop the recording rather than being logged and ignored.
Audio worth transcribing
The recording captures everyone clearly enough to transcribe.
Loudness across participants, since people join at wildly different levels.
Files
src/capture.tsAnyone who never exceeds the noise floor. Report rather than transcribe a partial meeting.
Files
src/audio-check.tsNot later. Retention set when the file exists is retention that happens.
Files
src/storage.ts
done when · tick each as it passeswatch out- A recording that captured only the loudest participant transcribes into a one-sided conversation, and nobody notices until they read the notes. Check the audio for participants who never appear above the noise floor, and report that rather than transcribing a partial meeting as though it were complete.
Transcript with speakers you can trust
Every word has a time and an attribution you can correct.
Requested explicitly. Segment level cannot support citation later.
Files
src/transcribe.tsWhere available. Guessing from audio alone is much worse.
Files
src/speakers.tsCorrecting one segment corrects that speaker throughout. Otherwise nobody corrects.
Files
src/speakers.ts
done when · tick each as it passeswatch out- Automatic speaker assignment is confidently wrong often enough that a summary attributing a commitment to the wrong person will happen, and that is a harder conversation than a missing note. Seed from the participant list, show low confidence visibly, and make correcting one speaker propagate to their other segments.
Notes that cite the recording
Every line in the summary points at a moment you can play.
Structured output so parsing is not a regular expression.
Files
src/summarise.tsA pure function, unit tested with a crafted bad citation rather than waiting for a model to produce one.
Files
src/validate.tssrc/validate.test.tsNamed in the cited text, or the action stays unassigned.
Files
src/actions.ts
done when · tick each as it passeswatch out- A model summarising a meeting will produce a decision that was discussed but not made, and an action item assigned to whoever was mentioned nearby. Both read plausibly and both cause real problems. Require citations, validate them, and require an explicit attribution in the cited text before naming an owner.
Search across meetings
You can find the meeting where something was said.
So a result links to a moment rather than a meeting.
Files
src/search.tsEnforced in the query. Sharing beyond that is a deliberate action.
Files
src/access.tsAs a non-attendee. The interface is not the test.
Files
test/access.test.ts
done when · tick each as it passeswatch out- Making every transcript searchable by everyone in an organisation turns a note-taking tool into a surveillance archive, and people change what they say in meetings once they know. Default to the attendees, make sharing deliberate, and enforce it in the query rather than the interface.
Retention, deletion and the recordproduct builder
Recordings expire automatically and a deletion request is honoured completely.
Per artefact retention. A policy that needs remembering is not automatic.
Files
src/retention.tsEvery store including the search index. Verify by searching afterwards.
Files
src/delete.tsIt is the evidence the recording was disclosed, and it outlives the recording.
Files
docs/retention.md
done when · tick each as it passeswatch out- Deleting the recording and keeping the transcript satisfies neither the policy nor the participant's expectation, since the transcript is the more readable record of what they said. Decide what each period covers, apply it to every artefact, and keep the announcement record longer because it is your evidence that the recording was disclosed.
That is the whole plan for Fireflies.ai. What it deliberately does not cover is below · check the gaps before you call it a replacement.
- Bot reliability across every meeting platform.
- Integrations into customer and project systems.
- Organisational permission structures.
- Legal advice about recording consent.
- native meeting bot reliability
- integrations with CRM/project tools
- team permissions
- shared topic tracking
- compliance controls
- A pre-meeting notice to invitees, which is better consent practice than announcing on the day
- Topic segmentation, so a long meeting can be navigated rather than read
- Follow-up detection across meetings, which is where a searchable archive starts paying
Need the files? The project pack on the verdict page hands your agent the whole brief · more meeting notes.