This project automatically processes meeting transcription files, summarizes them using configurable OpenRouter models (Claude by default), and creates organized meeting notes in Notion complete with the original transcript attached for download.
The system:
- Monitors transcription files in the
source/directory - Processes the latest transcription file automatically
- Generates a summary via OpenRouter for each configured model (Claude by default)
- Creates well-formatted meeting notes in your Notion database and attaches the full transcript as a downloadable file
- Tracks processing results and provides tools for reprocessing failed files
- Deno installed
- Notion account with API access
- OpenRouter account with an API key (grants access to the models you want to use)
Create a .env file in the project root:
OPENROUTER_API_KEY=your_openrouter_api_key_here
NOTION_API_KEY=your_notion_api_key_here
NOTION_MEETING_DATABASE_ID=your_meeting_minutes_database_id_here
NOTION_USER_ID=your_notion_user_id_here
NOTION_PROJECT_UPDATES_DATABASE_ID=your_project_updates_database_id_here # required for project-updates flowOptional – Nextcloud Collectives: To push the same meeting summary to a Nextcloud Collectives page, add:
NEXTCLOUD_BASE_URL=https://your-nextcloud.example.com
NEXTCLOUD_USERNAME=your-username
NEXTCLOUD_APP_PASSWORD=your-app-password
NEXTCLOUD_COLLECTIVE_ID=1
NEXTCLOUD_COLLECTIVE_PARENT_PAGE_ID=85481Use numeric IDs in .env for reliable matching. To get them, from the project root run:
deno run --allow-read --allow-net --allow-env scripts/list-collectives.tsThis prints each collective’s id and name. Then run with a collective id to list pages (and their ids):
deno run --allow-read --allow-net --allow-env scripts/list-collectives.ts 1Set NEXTCLOUD_COLLECTIVE_ID and NEXTCLOUD_COLLECTIVE_PARENT_PAGE_ID to the numeric ids (no names or slugs). Create an app password in Nextcloud Settings → Security.
Temporary – skip Notion: Set SKIP_NOTION=1 (or true/yes) to push only to Nextcloud Collectives; Notion env vars are not required. Nextcloud must be configured when using this. Remove or set to 0 to re-enable Notion.
Both flows currently use the same summary model (Claude). To tweak them, edit FLOW_CONFIGS in main.ts and rerun.ts.
Transscripts/
├── source/ # Place transcription files here
├── functions/ # Core functionality modules
├── main.ts # Main processing script
├── rerun.ts # Reprocess specific transcriptions
├── find-by-date.ts # Find files by date range
├── run.sh # Shell wrapper for main script
├── rerun.sh # Shell wrapper for rerun script
├── prompt.md # Meeting notes prompt
├── project_updates_prompt.md # Project update prompt
├── generated_summaries/ # Cached markdown summaries by flow (auto-generated)
├── processed_files.json # Processing log (auto-generated)
└── .env # Environment variables
Process the latest transcription file:
./run.sh
# or
deno run --allow-all main.ts# Default meeting notes flow
./run.sh meeting
# Project updates flow
./run.sh project-updates./run.sh without arguments defaults to the meeting flow.
./rerun.sh --help
# or
deno run --allow-all rerun.ts --help./rerun.sh --list
# Shows the 10 most recently created transcription files./rerun.sh --failed
# Shows files that failed to process previously# Process files from a specific date
./rerun.sh "20250127"
# Project update flow reprocessing
./rerun.sh --flow project-updates "20250127"
# Process a specific file by date and time
./rerun.sh "20250127 1502"
# Process any file containing "transcription"
./rerun.sh "transcription"If multiple files match your search term, you'll be prompted to select which one to process.
Generated summaries are cached locally as markdown files in:
generated_summaries/<flow>/<transcription-file-base-name>.md
- If a cache file exists,
rerun.tsreuses it and skips the OpenRouter summarization call. - If no cache file exists, the script generates a new summary and saves it to the cache.
main.tsalso writes cache files, so reruns can reuse summaries from normal runs.
Use the date finder utility to locate transcription files within specific time ranges:
# Show today's files
deno run --allow-all find-by-date.ts --today
# Show yesterday's files
deno run --allow-all find-by-date.ts --yesterday
# Show files from the last 7 days
deno run --allow-all find-by-date.ts --week
# Show files from the last 30 days
deno run --allow-all find-by-date.ts --month
# Show files from a specific date
deno run --allow-all find-by-date.ts 2025-01-27
deno run --allow-all find-by-date.ts 20250127
# Show files from a date range
deno run --allow-all find-by-date.ts 2025-01-20..2025-01-27
deno run --allow-all find-by-date.ts 20250120..20250127Transcription files should follow this naming pattern:
YYYYMMDD HHMM Transcription.txt
Examples:
20250127 1502 Transcription.txt20250128 0930 Transcription.txt
The system automatically maintains a log of processed files in processed_files.json. This includes:
- File path and name
- Processing timestamp
- Success/failure status
- Notion document URL (if successful)
This log enables:
- Tracking which files have been processed
- Identifying failed processing attempts
- Avoiding duplicate processing
- Quick access to generated Notion documents
- Missing Environment Variables: Ensure all required API keys are set in
.env - File Not Found: Check that transcription files are in the
source/directory - API Rate Limits: The system will show appropriate error messages for API issues
- Invalid File Format: Ensure transcription files are readable text files
If processing fails:
- Check the error message in the console output
- Use
./rerun.sh --failedto see failed files - Fix any issues (API keys, file permissions, etc.)
- Reprocess using
./rerun.sh "filename_pattern"
Edit prompt.md to customize how each model summarizes your meetings. The prompt should include instructions for:
- Summary structure and format
- Key information to extract
- Tone and style preferences
The system uses macOS notifications. Modify the showNotification function in functions/showNotification.ts to customize notification behavior.
Modify the document title format in main.ts or rerun.ts:
const documentTitle = "Meeting Notes - " + new Date().toLocaleDateString();If you get permission errors, ensure scripts are executable:
chmod +x run.sh rerun.shThe scripts require these Deno permissions:
--allow-read: Read transcription files and configuration--allow-write: Write processing logs--allow-net: API calls to OpenRouter and Notion--allow-env: Access environment variables--allow-run: Execute notification commands
Using --allow-all grants all necessary permissions.
- OpenRouter API: Verify your API key has access to the requested models and sufficient credits
- Notion API: Ensure your Notion integration has access to the target database
- Rate Limits: The system will retry failed requests with appropriate delays
- Core processing logic is in
functions/directory - Main workflow is in
main.ts - Reprocessing logic is in
rerun.ts - Each function is modular and can be imported independently
Test individual components:
# Test file discovery
deno run --allow-all -e "
import { getLatestFile } from './functions/getLatestFile.ts';
console.log(await getLatestFile('/Users/nilsborg/Repos/meeting-summaries-to-notion/source'));
"
# Test prompt loading
deno run --allow-all -e "
import { loadPrompt } from './functions/loadPrompt.ts';
console.log(await loadPrompt('./prompt.md'));
"This project is for personal use. Ensure you comply with the terms of service for all integrated APIs (Anthropic, Notion, OpenAI).