App shell and navigation
Smart User Scripts
Per-Site Scripts with URL Matching & Timing (like Greasemonkey)
AppMintAppwrightBoth builders - the steps below are the same in each.
1What Are Smart User Scripts?#
Smart User Scripts are individual named scripts - each with its own:
🌐 URL match patterns (which pages to run on)
⏱ Run-at timing (before, during or after load)
✅ Enable/Disable toggle
They work like Greasemonkey or Tampermonkey in desktop browsers - but built right into your app.
✅ Perfect for:
- Auto-login ONLY on the /login page
- Hide ads ONLY on article pages (https://news.com/article/*)
- Watch DOM changes with MutationObserver
- Inject before page renders (document-start) to avoid flash
Key difference from Quick Injection:
Quick Injection = same CSS/JS on ALL pages
Smart User Scripts = per-script, per-URL, per-timing control
2Where to Find It#
Step 4 (Permissions) → scroll down → 🤖 Smart User Scripts card.
Tap '+ Add' to create a new script. Each script has:
- Name - shown in the manager list
- URL Match Patterns - one per line (supports * wildcard)
- Run At - document-end / document-start / document-idle
- Code - your JavaScript
- Enabled toggle
Tap any row to edit or delete a script.
3URL Match Pattern Examples#
Patterns control which pages the script runs on. Use * as a wildcard:
# Run on every page of every site
*://*/*
# Run only on example.com (any path)
https://example.com/*
# Run on ALL pages of ANY .com domain
https://*.com/*
# Run only on the /login path
https://example.com/login
https://example.com/login/*
# Run on news article pages
https://news.example.com/article/*4Run-At Timing Explained#
- document-end (default)
Runs AFTER the page finishes loading. Safe, most compatible. Use for hiding elements, adding buttons, tracking.
- document-start ⚡ (advanced)
Runs BEFORE the page renders. Injects script into the raw HTML via shouldInterceptRequest. Removes CSP headers. Use for dark-mode CSS or forcing viewport before layout paint.
- document-idle ⏱
Runs 1.5 seconds after page load. Good for catching late-loading AJAX content or modals that appear after a delay.
5Example 1: Auto-Login on /login Only#
Match: https://myapp.com/login
Run-at: document-end
// Auto-fill login form
(function() {
var email = document.querySelector('input[type=email], input[name=email]');
var pass = document.querySelector('input[type=password]');
if (email) email.value = '[email protected]';
if (pass) pass.value = 'mypassword';
// Uncomment to auto-submit:
// var form = document.querySelector('form');
// if (form) form.submit();
})();6Example 2: Hide Paywalls on Article Pages#
Match: https://news.site.com/article/*
Run-at: document-end
// Hide paywall overlay and restore scroll
(function() {
var overlay = document.querySelector('.paywall-overlay, .metered-content, #paywall');
if (overlay) overlay.remove();
document.body.style.overflow = 'auto';
document.documentElement.style.overflow = 'auto';
})();7Example 3: Watch Dynamic Content (MutationObserver)#
Match: *://*/*
Run-at: document-end
For elements that appear AFTER page load (lazy-loaded modals, ads):
// Remove any modal/popup that appears dynamically
(function() {
var sel = '.modal, .popup, .overlay, [class*="modal"], [class*="popup"]';
// Remove existing ones first
document.querySelectorAll(sel).forEach(function(el) { el.remove(); });
// Watch for new ones
var obs = new MutationObserver(function() {
document.querySelectorAll(sel).forEach(function(el) { el.remove(); });
});
obs.observe(document.body, { childList: true, subtree: true });
// Stop watching after 30 s to save battery
setTimeout(function() { obs.disconnect(); }, 30000);
})();8Example 4: Force Dark Mode Before Render (document-start)#
Match: *://*/*
Run-at: document-start
Injects CSS before the page paints - no white flash:
// Inject dark theme before page renders
(function() {
var s = document.createElement('style');
s.id = '__force_dark__';
s.textContent = [
'html { filter: invert(1) hue-rotate(180deg) !important; }',
'img,video,canvas,svg { filter: invert(1) hue-rotate(180deg) !important; }'
].join('\
');
(document.head || document.documentElement).appendChild(s);
})();9Example 5: Custom Analytics / Event Tracking#
Match: https://myshop.com/*
Run-at: document-idle
Send custom events after the page fully settles:
// Track page views + button clicks
(function() {
// Page view
console.log('[Analytics] Page: ' + location.href);
// Track all CTA button clicks
document.querySelectorAll('button, .btn, a[href]').forEach(function(el) {
el.addEventListener('click', function() {
console.log('[Analytics] Clicked: ' + (el.textContent || el.href));
// Replace with your own tracker call, e.g. gtag('event', ...)
});
});
})();10Security & Limitations#
⚡ document-start removes Content-Security-Policy headers for the matched page. Only use on sites you own or explicitly trust.
🔒 Same-Origin Policy: JS cannot access cross-origin iframes (PayPal, Stripe, Google login). This is enforced by the browser engine and cannot be bypassed.
📵 HTTPS Only: APIs like geolocation or camera in injected scripts require HTTPS.
✅ Guard against double-run: each script is guarded by a window flag so it runs only once per page.
✅ Works offline: Smart User Scripts also run in ZIP-bundled offline apps.