Auto-create meeting-notes Docs from calendar events
Pre-fill a notes template for every meeting in the next 24 hours and attach it to the event.
Published Jun 29, 2025
Good meetings get written down; the trouble is the writing-down never starts until someone scrambles for a blank Doc as the call begins. By then the agenda is half-forgotten and the notes start late. Northwind wanted a notes Doc ready and waiting before every meeting, with the basics already filled in.
This script looks ahead at the next 24 hours of calendar events, copies a notes template for each one, fills in the title, date and attendee list, and links the finished Doc straight into the event description. By the time anyone joins the call, the notes Doc is one click away with the header already done.
What you’ll need
- A notes template Google Doc containing the placeholders
{{title}},{{date}}and{{attendees}}wherever you want those values to appear. - A
Notes/Drive folder for the generated Docs to land in. - Both IDs to hand — the template Doc ID and the Notes folder ID.
The script
// The notes template Doc, with {{title}}, {{date}} and {{attendees}}.
const TEMPLATE = '1abcNotesTemplateId';
// The Drive folder where generated notes Docs are stored.
const NOTES_FOLDER = '1abcNotesFolderId';
// How far ahead to look for meetings, in milliseconds (24 hours).
const LOOKAHEAD_MS = 24 * 60 * 60 * 1000;
/**
* Finds every meeting in the next 24 hours, creates a pre-filled notes
* Doc for each one from the template, and links it into the event.
*/
function prepNotesForUpcoming() {
// 1. Build the time window: now until 24 hours from now.
const start = new Date();
const end = new Date(start.getTime() + LOOKAHEAD_MS);
const events = CalendarApp.getDefaultCalendar().getEvents(start, end);
if (!events.length) {
Logger.log('No meetings in the next 24 hours — nothing to do.');
return;
}
for (const event of events) {
// 2. Skip events that already have a notes Doc. The 'notes-doc'
// tag is the marker that stops duplicates on the next run.
if (event.getTag('notes-doc')) continue;
// 3. Copy the template into the Notes folder, named by date + title.
const name = `${Utilities.formatDate(event.getStartTime(), 'GMT', 'yyyy-MM-dd')} — ${event.getTitle()}`;
const file = DriveApp.getFileById(TEMPLATE)
.makeCopy(name, DriveApp.getFolderById(NOTES_FOLDER));
// 4. Open the copy and swap each placeholder for real values.
const doc = DocumentApp.openById(file.getId());
const body = doc.getBody();
body.replaceText('{{title}}', event.getTitle());
body.replaceText('{{date}}',
Utilities.formatDate(event.getStartTime(), 'GMT', 'd MMM yyyy HH:mm'));
body.replaceText('{{attendees}}',
event.getGuestList().map((g) => g.getEmail()).join(', '));
doc.saveAndClose();
// 5. Append a link to the Doc in the event description.
event.setDescription(`${event.getDescription() || ''}\n\nNotes: ${file.getUrl()}`);
// 6. Tag the event so the next run knows to skip it.
event.setTag('notes-doc', file.getId());
}
}
How it works
prepNotesForUpcomingbuilds a time window from now to 24 hours ahead and pulls every event in that range from the default calendar. If there are none, it logs a message and stops.- For each event it checks the
notes-doctag. If the tag is present, a Doc was already made on an earlier run, so the event is skipped — this is what keeps an hourly trigger from generating a new Doc every hour. - It copies the template Doc into the Notes folder, naming the copy with an ISO date prefix and the meeting title so the folder sorts chronologically.
- It opens the copy and uses
replaceTextto swap the three placeholders for the event’s title, formatted start time, and a comma-separated list of guest email addresses, then saves and closes. - It appends a
Notes: <url>line to the event description, preserving any description that was already there. - Finally it writes the new Doc’s ID into the event’s
notes-doctag, marking the event as done so it is never processed twice.
Example run
Say tomorrow’s calendar has one event: “Q3 campaign kickoff” at 10:00, with two guests. After a run, the Notes folder contains a new Doc:
2025-06-30 — Q3 campaign kickoff
Title: Q3 campaign kickoff Date: 30 Jun 2025 10:00 Attendees: [email protected], [email protected]
And the event description now ends with:
Re-run the script and nothing changes — the event already carries a
notes-doc tag, so it is skipped.
Trigger it
Run this on an hourly time-based trigger so new invites are picked up promptly:
- In the Apps Script editor open Triggers (the clock icon).
- Add a trigger for
prepNotesForUpcoming, Time-driven, Hour timer, every hour.
An hourly cadence means any meeting booked today has its notes Doc ready well
before it starts, while the notes-doc tag guarantees each event is only ever
prepared once.
Watch out for
- Event tags are personal to your calendar copy. If someone else runs the same
script against the same shared event, they will not see your
notes-doctag and may create a second Doc. Run this from one account only. - Dates are formatted in
GMT. Through British Summer Time that is an hour behind London — swap'GMT'for'Europe/London'in bothformatDatecalls if the displayed times matter. replaceTextonly touches the document body. Placeholders in the header, footer or a table caption are left untouched — keep{{title}},{{date}}and{{attendees}}in the main body of the template.- Recurring meetings produce one Doc per instance, which is usually what you want, but a daily stand-up will steadily fill the Notes folder. Prune it periodically or exclude recurring events by title.
getEventsreturns declined and tentative invites too. Add agetMyStatus()check if you only want notes for meetings you have accepted.
Related
Generate personalized study guides from notes
Reformat raw notes into structured study guides — for Northwind's internal training programme.
Updated Feb 8, 2026
Build a contract-clause assembly system
Construct Northwind agreements from a library of approved clauses — drag-drop in code.
Updated Feb 1, 2026
Translate and resolve Doc comments
Localise reviewer feedback on a shared Doc so multilingual teams can collaborate.
Updated Jan 25, 2026
Auto-archive finalized Docs to dated folders
File completed Northwind Docs by month so the active folder stays focused on in-flight work.
Updated Jan 18, 2026
Build a fillable intake form inside a Doc
Create structured intake forms with placeholder fields readers can fill — for client briefs.
Updated Jan 11, 2026