Blog / Technical Guides

Create a Google Drive Folder for Every New Project Automatically

By Keyona Meeks, Founder, ReRev Labs · Oct 31, 2026 · 9 min read

The short answer: Keep a template folder with the subfolders and starter files every project needs. Add a Sheet with one row per project and a "Create folder" column. A small Apps Script reads the rows marked Yes, makes a new folder inside a parent folder, copies the template into it, and writes the folder link and the time back to the row. It does not share the folder with anyone. I tested the script with a mock in Node and have not run it in Google, so run the test steps first.

By the end of this post, you'll be able to:

  • Set up a template folder and a project Sheet.
  • Install a script that creates a project folder from the template.
  • Get the folder link written back to the Sheet.
  • Know what the script does not do, and what to check.

Every new project starts the same way. Someone makes a folder, adds the same six subfolders, copies in the same checklist and pastes the link somewhere. It takes ten minutes and is done slightly differently each time. This is a good first script because it is the same every time, and a wrong result is easy to see.

What do you need before you start?

  • A template folder in Drive with the structure you want, such as 01 Contracts, 02 Drawings, 03 Photos, and any starter files. Keep it small.
  • A parent folder where all the project folders will live.
  • A Google Sheet with a tab named Projects and these headings in row 1: Project, Create folder, Status, Folder link, Created at.

Each folder has an ID, and the script needs both. I could not confirm from the pages I read where Drive shows it, so look it up in Google's Drive help.

How does the script work?

For each row where Create folder is Yes, the Folder link is empty and the Status does not start with ERROR, the script:

  1. Checks that no folder with that name already exists in the parent folder.
  2. Creates the folder.
  3. Copies every file and subfolder from the template into it.
  4. Writes the folder's link, the time and the word Done into the row.

If anything fails, it writes ERROR: and the message in the Status column and leaves the row alone until you clear the status.

It handles at most three rows per run, and stops with an error if the template holds more than 200 files and folders. Both numbers are limits I chose, not Google's.

What does Google's documentation say about the methods?

I read the Drive reference pages for Folder and File as excerpts on October 30, 2026. The lines the script relies on:

  • createFolder(name): "Creates a folder in the current folder with the given name."
  • getFolders(): "Gets a collection of all folders that are children of the current folder."
  • getFiles(): "Gets a collection of all files that are children of the current folder."
  • getUrl(): "Gets the URL that can be used to open the Folder in a Google App like Drive or Docs."
  • makeCopy(name, destination): "Creates a copy of the file in the destination directory and names it with the name provided."

Source: Class Folder and Class File.

Two things I could not confirm. None of the Folder methods I read copies a whole folder, which is why the script copies files one at a time and rebuilds subfolders. I read most of that table but not all of it, so a method may exist that I missed. And the pages say nothing about what sharing a copied file gets. Check the copies' sharing yourself.

What is the script?

// Create a Drive folder for each new project row, copied from a template folder.
// Sheet tab "Projects" needs these headings in row 1 (any order):
//   Project | Create folder | Status | Folder link | Created at
const SHEET_NAME = 'Projects';
const TEMPLATE_FOLDER_ID = 'PASTE_TEMPLATE_FOLDER_ID';
const PARENT_FOLDER_ID = 'PASTE_PARENT_FOLDER_ID';
const MAX_ROWS_PER_RUN = 3;
const MAX_ITEMS_PER_COPY = 200;
const COL = {
  project: 'Project',
  go: 'Create folder',
  status: 'Status',
  link: 'Folder link',
  created: 'Created at'
};

function createProjectFolders() {
  const lock = LockService.getScriptLock();
  if (!lock.tryLock(10000)) { return; }
  try {
    const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(SHEET_NAME);
    if (!sheet) { throw new Error('No tab named ' + SHEET_NAME); }
    const values = sheet.getDataRange().getValues();
    const head = values[0].map(function (h) { return String(h).trim(); });
    const at = {};
    Object.keys(COL).forEach(function (k) { at[k] = head.indexOf(COL[k]); });
    const missing = Object.keys(COL).filter(function (k) { return at[k] < 0; });
    if (missing.length) {
      throw new Error('Missing columns: ' + missing.map(function (k) { return COL[k]; }).join(', '));
    }
    const template = DriveApp.getFolderById(TEMPLATE_FOLDER_ID);
    const parent = DriveApp.getFolderById(PARENT_FOLDER_ID);
    let done = 0;
    for (let i = 1; i < values.length && done < MAX_ROWS_PER_RUN; i++) {
      const row = values[i];
      const name = String(row[at.project]).trim();
      const go = String(row[at.go]).trim().toLowerCase();
      const hasLink = String(row[at.link]).trim() !== '';
      const status = String(row[at.status]).trim();
      if (!name || go !== 'yes' || hasLink || status.indexOf('ERROR') === 0) { continue; }
      done++;
      const rowNum = i + 1;
      try {
        if (folderNameExists_(parent, name)) {
          throw new Error('a folder named "' + name + '" already exists in the parent folder');
        }
        const created = parent.createFolder(name);
        const counter = { n: 0 };
        copyInto_(template, created, counter);
        sheet.getRange(rowNum, at.link + 1).setValue(created.getUrl());
        sheet.getRange(rowNum, at.created + 1).setValue(new Date());
        sheet.getRange(rowNum, at.status + 1).setValue('Done');
      } catch (err) {
        sheet.getRange(rowNum, at.status + 1).setValue('ERROR: ' + err.message);
      }
    }
  } finally {
    lock.releaseLock();
  }
}

function folderNameExists_(parent, name) {
  const it = parent.getFolders();
  while (it.hasNext()) {
    if (it.next().getName() === name) { return true; }
  }
  return false;
}

function copyInto_(source, target, counter) {
  const files = source.getFiles();
  while (files.hasNext()) {
    counter.n++;
    if (counter.n > MAX_ITEMS_PER_COPY) { throw new Error('template has more than ' + MAX_ITEMS_PER_COPY + ' items'); }
    const f = files.next();
    f.makeCopy(f.getName(), target);
  }
  const folders = source.getFolders();
  while (folders.hasNext()) {
    counter.n++;
    if (counter.n > MAX_ITEMS_PER_COPY) { throw new Error('template has more than ' + MAX_ITEMS_PER_COPY + ' items'); }
    const sub = folders.next();
    copyInto_(sub, target.createFolder(sub.getName()), counter);
  }
}

function setupProjectFolderTrigger() {
  ScriptApp.getProjectTriggers().forEach(function (t) {
    if (t.getHandlerFunction() === 'createProjectFolders') { ScriptApp.deleteTrigger(t); }
  });
  ScriptApp.newTrigger('createProjectFolders').timeBased().everyMinutes(10).create();
}

Replace the two PASTE_ values with your folder IDs.

How do you install it?

  1. Open the Apps Script editor from your Sheet. I could not confirm the menu path from the pages I read, so follow Google's current help for Sheets scripts.
  2. Paste the script and save.
  3. In the function list choose createProjectFolders and run it once. Google asks you to allow the script to use your Sheet and your Drive. Read the list. Approve it only if you agree. Google says scopes are "determined automatically by scanning the script code," which I checked in an earlier review.
  4. Run setupProjectFolderTrigger once. It removes only its own earlier trigger and adds one that runs every ten minutes. Google's documentation lists 1, 5, 10, 15 and 30 as the allowed values for everyMinutes, per an earlier review.

Google's documentation on installable triggers says they "always run under the account of the person who created them." So the folders are made in the account that ran step 4. If that person leaves, the trigger can stop.

How do you test it?

  1. Make a template with two files and one subfolder, and a Sheet with three test rows: one Yes, one No, one blank.
  2. Run createProjectFolders by hand.
  3. Open the parent folder. Only the Yes row should have a new folder, with the files and subfolder inside.
  4. Check the row: Status says Done, and the link opens the folder.
  5. Run it again. Nothing new should appear.
  6. Add a second row with the same name as an existing folder. You should see an ERROR in Status and no new folder.
  7. Delete the test folders and rows.

What did my mock test cover?

I wrote a Node harness that stands in for the Sheet, Drive, the lock and the trigger service, and ran 23 checks. They covered: the Yes row creates a folder with the files and subfolder copied; No and blank rows are left alone; a second run does not duplicate; a duplicate name writes an error and is not retried; no more than three rows per run; a failure partway through copying records an error and writes no link; a busy lock skips the run; a missing column throws and still releases the lock; a row that already has a link is skipped; and the trigger setup removes only its own trigger and sets ten minutes. All 23 passed.

That proves the logic against my assumptions about Google's behavior. It does not prove the script runs in Google. The mock cannot tell me how fast makeCopy runs, how the lock behaves, or what the copies' sharing looks like.

What happens if a copy fails halfway?

The new folder stays, partly filled, and the row says ERROR. The script does not delete it. Delete the partial folder by hand, clear the Status cell and run again. I did that on purpose, because a script that deletes folders is one you should write and test with more care than this post covers.

Should the script share the folder?

Not in this version. Sharing is where a small script becomes a risk. Google's reference lists methods that add editors and viewers, and I read their one-line descriptions, such as "Adds the given user to the list of editors for the Folder." Adding a person is an action that cannot be taken back once they have seen the files. Set sharing on the parent folder in Drive, where you can see it, and check what the new folders inherit. I did not confirm inheritance from the pages I read.

Where does an LLM fit in this?

Not here. Making a folder from a template is a rule, and rules do the same thing every time. An LLM can help you write or change the script, and it can suggest a folder structure. A person should read the code and run the tests. My stance: AI writes the code, plain automation runs it, and an LLM shows up only where the input is messy and a person checks the result.

What limits should you check?

Google publishes quotas for Apps Script. On October 30, 2026 I noted "Script runtime | 6 min / execution" on the quotas page in an earlier review. A big template copied file by file could run into that. Keep the template small. The page also says "All quotas are subject to elimination, reduction, or change at any time, without notice."

Where this has limits

  • I did not run this script in Google. The mock test used my own stand-ins for Google's services.
  • The Folder reference page was read as an excerpt. I could not rule out a folder-copy method.
  • Sharing and permissions of the copies are unconfirmed. Check them.
  • The quota and trigger lines are from an earlier review. Check the live pages.
  • Large templates may time out. Keep it small.
  • A failed copy leaves a partial folder. You delete it.
  • No ReRev prices and no promises about results.

If you want help setting this up, see our AI operations service or tell us what your team sets up by hand. Do not send client files, passwords or login details.

Frequently asked questions

Can Google Drive create a folder automatically for each new project?

Yes, with a small Apps Script that reads a Sheet and creates the folder. This post gives a script and a test.

Can Apps Script copy a whole folder?

The Folder methods I read do not include a copy. The script copies files with makeCopy and rebuilds the subfolders. I may have missed a method.

The script writes the folder's URL into the Folder link column.

Will it share the folder with my client?

No. This version does not share anything. Set sharing yourself in Drive.

What if the script fails halfway?

It writes an error in the row and leaves the partial folder. Delete it, clear the Status and run again.

Do I need to know how to code?

You need to paste a script, set two IDs and run the test. A person should still read the script before it runs.

Read next: Construction document control in Google Drive decides what goes inside the folders this script creates, and automating client onboarding is the same pattern for a service business.