Our Secret to Better Monday Meetings—And How You Can Steal It for Free

Let’s be honest: Monday meetings can be a drag. They often feel like a slow, repetitive start to a week that’s already demanding your full attention. At Grassr Solutions, we believe that efficiency shouldn't just be a goal for our clients; it's a principle we live by. That's why we tackled our own Monday meeting problem head-on.

The result? A simple but powerful script that transformed our weekly sync from a chore into a high-efficiency launchpad.

Today, we’re not just going to tell you about it. We’re giving it to you for free. This is the exact tool we use internally, and it’s a perfect example of our core mission: building smart, simple systems that save time and boost productivity.

The Foundation: A Single Source of Truth

First, the philosophy behind the tool. Instead of creating a new document for every weekly meeting—a practice that scatters information and buries decisions—we keep all our progress minutes in one continuous Google Doc.

This approach is a game-changer:

  • Instant Searchability: Need to find a decision from three months ago? Just hit Ctrl+F. All your history is in one place.

  • Automatic Bookmarking: By using a main heading for each week, Google Docs’ "Outline" feature creates a clickable table of contents, letting you jump to any meeting in seconds.

  • Complete Historical Context: You can easily scroll up to see how a task evolved from "To-Do" to "Done," providing unparalleled accountability.

The Magic: Automated, Fair, and Fast

Our custom script automates the tedious setup process. With one click, it prepares our document for the week, allowing us to focus on what matters.

Here’s what the script does:

  1. Sets the Date: It automatically calculates the upcoming Monday's date and inserts it as a clean, formatted Heading 1.

  2. Creates the Agenda: It lays out a standardized list for each team member, prompting for key updates: Done, In-Process, To-Do, and To-Schedule.

  3. Ensures Fair Play: This is our favorite part. The script randomizes the order of team members every single week. This simple shuffle eliminates the pressure of always going first and keeps everyone engaged because they never know when their turn is.

It’s a small tweak that fosters a more dynamic, equitable, and prepared team.

Get Your Free Meeting Script Here

Ready to upgrade your own Monday meetings? Here is the complete Google Apps Script.

/**
 * @OnlyCurrentDoc
 * Adds a custom menu to the Google Docs UI to paste the template.
 */
function onOpen() {
  DocumentApp.getUi()
      .createMenu('🌲 Grassr Solutions')
      .addItem('📝 Weekly Updates', 'weeklyUpdateTemplate')
      .addToUi();
}

/**
 * Calculates the date of the next upcoming Monday.
 * If today is Monday, it returns today's date.
 *
 * @return {Date} The date object representing the upcoming Monday.
 */
function getComingMonday() {
  const today = new Date();
  const currentDay = today.getDay(); // 0=Sunday, 1=Monday, ..., 6=Saturday

  let daysToAdd;

  if (currentDay === 1) { // If it's already Monday
    daysToAdd = 0;
  } else if (currentDay === 0) { // If it's Sunday
    daysToAdd = 1;
  } else { // If it's Tue (2) to Sat (6)
    // Calculate days needed to reach the *next* Monday
    // 7 days in a week - current day index + 1 (to get to Monday's index)
    daysToAdd = 8 - currentDay;
  }

  const targetMonday = new Date(today); // Create a copy to avoid modifying 'today'
  targetMonday.setDate(today.getDate() + daysToAdd);
  return targetMonday;
}

/**
 * Shuffles an array using the Fisher-Yates algorithm.
 * Creates a new shuffled array, leaving the original array unchanged.
 * @param {Array} array The array to shuffle.
 * @return {Array} A new array with the elements shuffled.
 */
function shuffleArray(array) {
  const newArray = [...array]; // Create a shallow copy to avoid modifying the original
  for (let i = newArray.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [newArray[i], newArray[j]] = [newArray[j], newArray[i]]; // ES6 destructuring swap
  }
  return newArray;
}


/**
 * Pastes the team update template into the active Google Document
 * at the current cursor position, using the upcoming Monday's date.
 */
function weeklyUpdateTemplate() {
  const doc = DocumentApp.getActiveDocument();
  const cursor = doc.getCursor();
  const body = doc.getBody();

  if (!cursor) {
    DocumentApp.getUi().alert('Could not find a cursor position. Please click into the document first.');
    return;
  }

  // Get the element where the cursor is. We'll insert relative to this.
  const insertionElement = cursor.getElement();
  const insertionOffset = cursor.getOffset();

  // --- Determine Insertion Point ---
  let insertionIndex;
  try {
      insertionIndex = body.getChildIndex(insertionElement);
  } catch (e) {
      Logger.log('Cursor element not directly under body. Checking parent. Error: %s', e);
      // If getChildIndex fails, the element might be nested (e.g., in a table, list).
      // Try to find the parent paragraph or list item that *is* a child of the body.
      let parent = insertionElement.getParent();
      while (parent && parent.getType() !== DocumentApp.ElementType.BODY) {
          try {
              insertionIndex = body.getChildIndex(parent);
              // Found a parent that is a child of the body, break the loop
              break;
          } catch (nestedError) {
              // This parent is also not a direct child, go up one more level
              parent = parent.getParent();
          }
      }
      // If we couldn't find a suitable parent, fallback to appending at the end.
      if (insertionIndex === undefined) {
           Logger.log('Could not determine insertion index from parents. Appending to end.');
           insertionIndex = body.getNumChildren() -1; // Insert *before* the last element (often blank para at end)
                                                      // or body.getNumChildren() to append truly at the end.
                                                      // Let's append after the found element if possible.
           // A simpler fallback might just be to always append if the initial try fails:
           // Logger.log('Cursor element not directly under body. Appending to end. Error: %s', e);
           // insertionIndex = body.getNumChildren(); // Append to end as fallback
      }
  }


  // --- Insert Content ---
  let currentInsertIndex = insertionIndex + 1; // Start inserting *after* the cursor's element index

  // 1. Insert Date Line using the coming Monday's date
  const comingMondayDate = getComingMonday(); // Get the calculated Monday date
  const formattedDate = Utilities.formatDate(comingMondayDate, Session.getScriptTimeZone(), "MMMM d, yyyy");
  const datePara = body.insertParagraph(currentInsertIndex++, "Updates on " + formattedDate + ":");
  datePara.setHeading(DocumentApp.ParagraphHeading.HEADING1);

  // Add a blank paragraph for spacing
  body.insertParagraph(currentInsertIndex++, "");

  // 2. Insert Names and Tasks List
  const names = ["Alice", "Bob", "Carl"];
  const tasks = ["Done:", "In-Process:", "To-Do:", "To-Schedule:"];
  const shuffledNames = shuffleArray(names);

  shuffledNames.forEach(name => {
    // Add numbered list item for the name
    // Ensure correct index calculation during insertion within the loop
    const nameIndex = currentInsertIndex++;
    const nameListItem = body.insertListItem(nameIndex, name);
    nameListItem.setGlyphType(DocumentApp.GlyphType.NUMBER);
    nameListItem.setNestingLevel(0); // Explicitly set top level

    // Add bulleted list items for tasks under the name
    tasks.forEach(task => {
      const taskIndex = currentInsertIndex++;
      const taskListItem = body.insertListItem(taskIndex, task);
      taskListItem.setNestingLevel(1); // Indent one level
      taskListItem.setGlyphType(DocumentApp.GlyphType.BULLET); // Explicitly set bullet
    });
  });

  const agendaIndex = currentInsertIndex++; // Get the next available index
  const agendaListItem = body.insertListItem(agendaIndex, "Agenda:");
  agendaListItem.setNestingLevel(0); // Set to top level (same as names)
  agendaListItem.setGlyphType(DocumentApp.GlyphType.NUMBER); // Make it part of the numbered list


   // Optional: Move cursor to the end of the inserted content
   // Need to get the element at the *final* currentInsertIndex - 1
   const lastElement = body.getChild(currentInsertIndex - 1);
   if (lastElement) {
       try {
           // Prefer positioning at the end of the text within the element
           if (lastElement.getType() === DocumentApp.ElementType.LIST_ITEM && lastElement.getNumChildren() > 0 && lastElement.getChild(0).getType() === DocumentApp.ElementType.TEXT) {
               doc.setCursor(doc.newPosition(lastElement.getChild(0).asText(), lastElement.getText().length));
           } else if (lastElement.getType() === DocumentApp.ElementType.PARAGRAPH) {
               doc.setCursor(doc.newPosition(lastElement.asText(), lastElement.asText().getText().length));
           } else {
               // Fallback for other element types if necessary
               doc.setCursor(doc.newPosition(lastElement, lastElement.asText().getText().length)); // May fail on non-text elements
           }
       } catch (e) {
           Logger.log('Could not set cursor position at end of inserted content. Error: %s', e);
           // If setting cursor fails, leave it where it was before insertion started
       }
   }
}

Follow these simple steps to install it in your own Google Doc.

  1. Open the Google Doc you use for meeting minutes.

  2. In the top menu, go to Extensions > Apps Script. A new tab will open with the script editor.

  3. Delete any placeholder code (like function myFunction() {...}) in the Code.gs file.

  4. Paste the entire code you copied from above into the editor.

  5. IMPORTANT: Find the line const names = ["Alice", "Bob", "Carl"]; and change the names to your actual team members.

  6. Click the Save project icon (it looks like a floppy disk). Give your project a name if prompted (e.g., "Weekly Updates").

  7. Go back to your Google Doc and refresh the page.

  8. You will now see a new menu item called 🌲 Grassr Solutions (feel free to change this to your company name).

  9. The first time you click 📝 Weekly Updates, Google will ask you to authorize the script. This is a standard security step. Follow the prompts to grant permission.

  10. Click it again, and watch the magic happen!

A Taste of the Grassr Philosophy

This simple script is a microcosm of what we do at Grassr Solutions. We take repetitive, time-consuming processes and transform them with smart, custom-built technology.

  • Automation: We built this to automate a manual task, just as we build automated reporting and HR systems for our clients.

  • Customization: You can easily change the names in the script to fit your team. This reflects our core belief that software should adapt to your business, not the other way around.

  • Collaboration: This tool is designed to make teamwork clearer and more efficient, the same goal behind the collaborative, cross-platform systems we create for businesses across the Philippines.

Let’s be clear: this script won’t reclaim hours of your week. The time you’ll save is modest—a minute here, thirty seconds there. But its true value isn't measured on a stopwatch; it's measured in mental energy.

Every Monday morning, this script removes one less hurdle for the team lead. It's one less thinking task, one less decision to make, and one less point of friction between your team and a productive start to the week. By automating the trivial, we aren't just saving time; we are saving focus.

This is the essence of the Grassr philosophy. True efficiency isn’t always about massive changes. It’s about identifying and eliminating the hundreds of small hurdles that drain your team's energy day after day.

 

We built this tool to clear a small stone from our own path.

Imagine what we could do for your business by removing the major roadblocks in your core operations.

 
Next
Next

Red Flags & Green Lights: A Consultant’s Guide to Choosing Clients That Fuel Your Growth