Precisely blocks project cards by text on websim.com and collapses empty grid gaps.
// ==UserScript==
// @name REMOVE SLOP PROJECTS
// @namespace http://tampermonkey.net
// @version 3.3
// @description Precisely blocks project cards by text on websim.com and collapses empty grid gaps.
// @author Killy
// @match https://websim.com/*
// @match https://www.websim.com/*
// @match https://websim.ai/*
// @match https://www.websim.ai/*
// @grant none
// @run-at document-end
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// Enter your keywords/phrases here (all lowercase)
const blockList = [
"numberblocks",
"colorblocks",
"alphablocks",
"numberslop",
"sprunki",
"Untitled",
"Sandbox",
"Playground",
"Effects",
"klasky csupo"
];
const isHomePage = () => {
const path = window.location.pathname;
return path === '/' || path === '/index.html';
};
const blockProjects = () => {
if (!isHomePage()) return;
// Select elements we haven't checked yet
const selectors = ['a', 'h1', 'h2', 'h3', 'span', 'p']
.map(tag => `${tag}:not([data-wb-checked])`)
.join(', ');
const titles = document.querySelectorAll(selectors);
titles.forEach(el => {
el.setAttribute('data-wb-checked', 'true');
const text = el.textContent.trim().toLowerCase();
if (!text) return;
const matchesBlock = blockList.some(phrase => text.includes(phrase));
if (matchesBlock) {
// Base target: the link itself
let containerToHide = el.closest('a') || el;
let current = containerToHide;
// Walk up the DOM tree to find the main layout grid.
// By finding the parent grid, we know 'current' is the exact slot leaving the empty gap.
while (current.parentElement && current.parentElement.tagName !== 'BODY' && current.parentElement.tagName !== 'MAIN') {
const parentClass = current.parentElement.className || '';
// Look for standard grid containers (WebSim uses Tailwind CSS)
if (typeof parentClass === 'string' && (parentClass.includes('grid ') || parentClass.includes('grid-cols') || parentClass.match(/\bgrid\b/))) {
containerToHide = current; // We found the exact grid cell!
break;
}
current = current.parentElement;
}
// Hide the ENTIRE grid cell to collapse the space completely
containerToHide.style.display = 'none';
}
});
};
// --- Debounce Utility ---
const debounce = (func, wait) => {
let timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), wait);
};
};
const debouncedBlockProjects = debounce(blockProjects, 150);
// Run on initial page load
blockProjects();
// Monitor for infinite scroll and URL changes
const observer = new MutationObserver((mutations) => {
if (!isHomePage()) return;
const hasNewNodes = mutations.some(mutation => mutation.addedNodes.length > 0);
if (hasNewNodes) {
debouncedBlockProjects();
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
console.log("WebSim Gap-Collapsing Blocker Active.");
})();