Skip to content

Instantly share code, notes, and snippets.

@mhdcodes
Created January 26, 2026 19:10
Show Gist options
  • Select an option

  • Save mhdcodes/dfee1074815ca68c9206c5a4c669a30e to your computer and use it in GitHub Desktop.

Select an option

Save mhdcodes/dfee1074815ca68c9206c5a4c669a30e to your computer and use it in GitHub Desktop.
Photopea No Ads
// ==UserScript==
// @name Photopea No Ads
// @version 1.0.0
// @description Remove ads sidebar and maximize canvas workspace in Photopea by spoofing viewport width
// @icon https://www.photopea.com/promo/icon512.png
// @author Claude (based on ml98's approach)
// @namespace http://tampermonkey.net/
// @license MIT
// @match https://www.photopea.com/*
// @match https://vecpea.com/*
// @grant unsafeWindow
// @run-at document-idle
// ==/UserScript==
(function () {
"use strict";
String.prototype.split=(f=>function(){return f.apply(this.replace('photopea','vectorpea'),arguments)})(String.prototype.split);
function maximizeWorkspace() {
// Find the app container and its child
const appContainer = document.querySelector(".app");
const appChild = document.querySelector(".app > div");
if (!appContainer || !appChild) {
console.log("Photopea containers not found yet, retrying...");
return false;
}
// Calculate the width of the ad sidebar
const adWidth = appContainer.offsetWidth - appChild.offsetWidth;
console.log("Ad sidebar width detected:", adWidth);
// Override window.innerWidth to include the ad width
// This tricks Photopea into thinking the viewport is wider
// causing it to push ads off-screen
Object.defineProperty(unsafeWindow, "innerWidth", {
get() {
return parseInt(visualViewport.width) + adWidth;
},
configurable: true,
});
// Trigger a resize event so Photopea recalculates its layout
unsafeWindow.dispatchEvent(new Event("resize"));
console.log("Photopea workspace maximized!");
return true;
}
// Use MutationObserver to detect when Photopea's app container loads
const observer = new MutationObserver((mutations) => {
for (const mutation of mutations) {
for (const node of mutation.addedNodes) {
// Check if the added node is part of Photopea's app structure
if (node.nodeType === 1 && node.matches(".app *")) {
console.log("Photopea app detected, maximizing workspace...");
// Disconnect observer once we've found the app
observer.disconnect();
// Small delay to ensure DOM is fully rendered
setTimeout(() => {
if (maximizeWorkspace()) {
// Success - workspace maximized
} else {
// Fallback: try again after a longer delay
setTimeout(maximizeWorkspace, 500);
}
}, 100);
return;
}
}
}
});
// Start observing the document body for changes
observer.observe(document.body, {
childList: true,
subtree: true,
});
// Fallback: If app is already loaded, maximize immediately
setTimeout(() => {
const appExists = document.querySelector(".app > div");
if (appExists) {
console.log("Photopea already loaded, maximizing workspace...");
observer.disconnect();
maximizeWorkspace();
}
}, 1000);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment