🧩 Drag, Drop, Boom: ChatGPT File Uploading Just Got Lazy!

Ever wish you could just stop hunting through folders to re-upload the same files to ChatGPT over and over?
Well, say hello to GPT FileDrop β€” a Chrome extension I whipped up that gives you a floating file sidebar right inside ChatGPT.


:sparkles: What It Does

  • Drag files into the sidebar :white_check_mark:
  • Keep up to 10 files ready to go :white_check_mark:
  • Click Upload to instantly simulate dropping them into ChatGPT :white_check_mark:
  • Never rummage for the same files again :white_check_mark:
  • Minimize the sidebar to drag it around your screen and open it back up wherever you want it set! :white_check_mark:

It’s a fun little quality-of-life upgrade for heavy testers, devs, or anyone building with ChatGPT.


:wrench: How to Use It

  1. Go to chrome://extensions/ in your Chrome browser.
  2. Toggle on Developer Mode (top-right).
  3. Click Load unpacked and select the folder where the files below live.
  4. Visit https://chatgpt.com/ β€” the sidebar should appear!

:hammer_and_wrench: Files to Create

Paste the following into separate files inside a folder:

// content.js
(function () {
  const html = `
  <div id="gpt-sidebar" class="dark" style="position: fixed; top: 20px; right: 20px; width: 220px; background: #121212; color: #f5f5f5; font-family: sans-serif; border: 1px solid #333; padding: 10px; z-index: 999999; box-shadow: 0 2px 12px rgba(0, 0, 0, 0.7); border-radius: 8px;">
    <div id="sidebar-header" style="display: flex; justify-content: space-between; align-items: center; font-weight: bold; margin-bottom: 10px; cursor: move;">
      <span>GPT FileDrop</span>
      <button id="toggle-sidebar" style="background: #333; border: none; color: #fff; cursor: pointer; font-size: 16px; padding: 0 8px; border-radius: 4px;">βˆ’</button>
    </div>
    <div id="sidebar-body">
      <div id="file-counter" style="text-align: center; font-weight: bold;">0/10</div>
      <div id="drop-zone" style="border: 2px dashed #555; padding: 10px; margin: 10px 0; text-align: center; cursor: pointer; min-height: 60px; border-radius: 6px;">Drag files here</div>
      <ul id="file-list" style="list-style: none; padding-left: 0; margin: 10px 0; max-height: 120px; overflow-y: auto;"></ul>
      <div class="button-row" style="display: flex; justify-content: space-between; margin-top: 10px; flex-wrap: wrap; gap: 4px;">
        <button id="upload-btn" style="flex: 1; background: #333; border: none; padding: 6px 10px; border-radius: 4px; color: white; cursor: pointer;">Upload</button>
        <button id="remove-btn" style="flex: 1; background: #333; border: none; padding: 6px 10px; border-radius: 4px; color: white; cursor: pointer;">Remove</button>
        <button id="clear-btn" style="flex: 1; background: #333; border: none; padding: 6px 10px; border-radius: 4px; color: white; cursor: pointer;">Clear</button>
      </div>
    </div>
  </div>`;

  const wrapper = document.createElement("div");
  wrapper.innerHTML = html;
  document.body.appendChild(wrapper);

  const dropZone = document.getElementById("drop-zone");
  const fileList = document.getElementById("file-list");
  const counter = document.getElementById("file-counter");
  const uploadBtn = document.getElementById("upload-btn");
  const clearBtn = document.getElementById("clear-btn");
  const removeBtn = document.getElementById("remove-btn");
  const toggleBtn = document.getElementById("toggle-sidebar");
  const sidebarBody = document.getElementById("sidebar-body");

  let uploadedFiles = [];
  let removeMode = false;

  dropZone.addEventListener("dragover", (e) => e.preventDefault());

  dropZone.addEventListener("drop", (e) => {
    e.preventDefault();
    const files = [...e.dataTransfer.files];

    if (uploadedFiles.length + files.length > 10) {
      dropZone.style.borderColor = "red";
      dropZone.style.backgroundImage =
        "url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0nMzAnIGhlaWdodD0nMzAnIHZpZXdCb3g9JzAgMCAzMCAzMCcgeG1sbnM9J2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJz48Y2lyY2xlIGN4PScxNScgY3k9JzE1JyByPScxNScgc3R5bGU9J2ZpbGw6bm9uZTtzdHJva2U6I2ZmMDAwMDtzdHJva2Utd2lkdGg6MiddIC8+PGxpbmUgeDE9JzgnIHkxPSc4JyB4Mj0nMjInIHkyPScyMicgc3R5bGU9J3N0cm9rZTojZmYwMDAwO3N0cm9rZS13aWR0aDoyOycgLz48L3N2Zz4=')";
      dropZone.style.backgroundRepeat = "no-repeat";
      dropZone.style.backgroundPosition = "center";
      dropZone.style.backgroundSize = "30px 30px";
      setTimeout(() => {
        dropZone.style.borderColor = "#555";
        dropZone.style.backgroundImage = "";
      }, 1500);
      return;
    }

    uploadedFiles.push(...files.slice(0, 10 - uploadedFiles.length));
    updateCounter();
    renderFileList();
  });

  function updateCounter() {
    counter.innerText = `${uploadedFiles.length}/10`;
  }

  function renderFileList() {
    fileList.innerHTML = "";
    uploadedFiles.forEach((file, index) => {
      const li = document.createElement("li");
      li.style.display = "flex";
      li.style.justifyContent = "space-between";
      li.style.alignItems = "center";
      li.style.fontSize = "12px";
      li.style.padding = "2px 0";
      li.style.borderBottom = "1px solid #333";

      const nameSpan = document.createElement("span");
      nameSpan.textContent = file.name;
      nameSpan.style.flex = "1";

      const removeBtn = document.createElement("button");
      removeBtn.textContent = "Γ—";
      removeBtn.style.background = "transparent";
      removeBtn.style.border = "none";
      removeBtn.style.color = "#f55";
      removeBtn.style.cursor = "pointer";
      removeBtn.style.fontWeight = "bold";
      removeBtn.style.marginLeft = "6px";

      removeBtn.addEventListener("click", () => {
        uploadedFiles.splice(index, 1);
        updateCounter();
        renderFileList();
      });

      li.appendChild(nameSpan);
      li.appendChild(removeBtn);
      fileList.appendChild(li);
    });
  }

  uploadBtn.addEventListener("click", () => {
    const chatInput = document.querySelector('input[type="file"]');
    if (!chatInput) {
      alert("ChatGPT upload input not found.");
      return;
    }

    const dataTransfer = new DataTransfer();
    uploadedFiles.forEach((file) => dataTransfer.items.add(file));
    chatInput.files = dataTransfer.files;

    const evt = new Event("change", { bubbles: true });
    chatInput.dispatchEvent(evt);
    console.log("Files uploaded to ChatGPT.");
  });

  clearBtn.addEventListener("click", () => {
    uploadedFiles = [];
    updateCounter();
    renderFileList();
  });

  toggleBtn.addEventListener("click", () => {
    if (sidebarBody.style.display === "none") {
      sidebarBody.style.display = "block";
      toggleBtn.innerText = "βˆ’";
    } else {
      sidebarBody.style.display = "none";
      toggleBtn.innerText = "+";
    }
  });

  // Dragging minimized sidebar
  const sidebar = document.getElementById("gpt-sidebar");
  const header = document.getElementById("sidebar-header");

  let isDragging = false;
  let offsetX = 0;
  let offsetY = 0;

  header.addEventListener("mousedown", (e) => {
    if (sidebarBody.style.display === "block") return; // only drag if minimized

    isDragging = true;
    offsetX = e.clientX - sidebar.getBoundingClientRect().left;
    offsetY = e.clientY - sidebar.getBoundingClientRect().top;
    document.body.style.userSelect = "none";
  });

  document.addEventListener("mousemove", (e) => {
    if (!isDragging) return;

    sidebar.style.left = `${e.clientX - offsetX}px`;
    sidebar.style.top = `${e.clientY - offsetY}px`;
    sidebar.style.right = "auto";
  });

  document.addEventListener("mouseup", () => {
    isDragging = false;
    document.body.style.userSelect = "auto";
  });
})();


// manifest.json
{
  "manifest_version": 3,
  "name": "ChatGPT File Drop Sidebar",
  "version": "1.2",
  "description": "Floating sidebar to drag and auto-upload files to ChatGPT.",
  "permissions": ["scripting", "activeTab"],
  "host_permissions": ["https://chatgpt.com/*"],
  "content_scripts": [
    {
      "matches": ["https://chatgpt.com/*"],
      "js": ["content.js"]
    }
  ]
}

Let me know if you try it or have ideas for fun improvements.
Now you can stop dragging files across your desktop like it’s 2003. :computer_mouse::card_index_dividers::speech_balloon: