Inject your own CSS styles, JavaScript code and action buttons into any page
JustZix lets you automatically inject your own CSS and JavaScript into selected pages, and also define action buttons (shortcuts that run code snippets on demand).
https://justzix.com/*. You can enable/disable a whole folder with one click.Each rule and each group can get its own list of additional URL patterns (chip input). When the list is empty, the element works everywhere the folder pattern matches. When you set e.g. https://justzix.com/admin/*, the element only works on admin subpages.
| Folder pattern | Rule patterns | Works on |
|---|---|---|
https://justzix.com/* | (empty) | the whole justzix.com domain |
https://justzix.com/* | https://justzix.com/admin/* | the /admin/ section only |
https://justzix.com/* | https://justzix.com/produkty/*https://justzix.com/koszyk | product subpages + cart only |
*://localhost:*/* | *://localhost:3000/* | port 3000 only (dev) |
For new users JustZix has a built-in interactive tutorial that walks you step by step through building a complete solution — from a folder, through a group and a rule set, to CSS/JS code and an action button. Hints appear as bubbles next to successive elements of the panel.
How to launch it:
In the "Tutorial centre" window you pick a tutorial and click Start. During the tutorial:
Access it via a right click on the extension icon → "Options", or a click on the icon → the "Edit panel" button.
A small round button appears automatically on pages that match any folder. By default it shows the label ZIX, but each folder can have its own label.
Folder label: in the folder bar, at the far left (next to the color picker) there is a text field for the button label. Enforced limits: max 3 characters, always UPPERCASE (the conversion to uppercase happens immediately while typing). The field accepts letters and digits — examples: ZIX, QA, DEV, ADM, X. When several folders match, the label is taken from the first one that has it set; the rest are ignored (an empty field = fallback to ZIX).
State by color (brand palette):
Folder color: if you set the color picker on a folder, the floating button on matching pages takes on that color. The "mixed" and "off" states automatically modulate the saturation. When several folders match, the color of the first one with a color set is used.
When you enter the edit panel the extension opens the Dashboard — a home page with a summary of your library and quick shortcuts. Previously the panel automatically selected the first folder in the list; now you see an overview instead.
The Dashboard is reachable through a click on the logo in the sidebar and through the "home" icon on the breadcrumb bar of every editor (folder, group, rule). The Dashboard header itself also has a "home" icon — clicking it refreshes the data (reloads the library from storage and re-renders the Dashboard from scratch).
The Dashboard is laid out in fixed rows of cards:
chrome.storage.local usage and the date of the last cloud backup.The "Latest examples" and "From the blog" cards fetch their content from the project website; when the endpoint is unavailable (e.g. offline), both cards are hidden. The extension version is re-checked fresh on every dashboard open.
The left panel in edit mode shows folders in a hierarchy — you can expand each folder to see its rules and jump to editing a specific one.
| Element | Action |
|---|---|
| Expand arrow | Expands/collapses the list of rules or groups (remembered between sessions) |
| Clicking a folder name (collapsed) | Selects the folder, opens the Folder editor and expands its groups/rules |
| Clicking an already-selected folder | Toggle: collapses (another click expands again) — the same for a group |
| Clicking a group name (collapsed) | Selects the group, opens the Group editor and expands its rules |
| Clicking a rule name | Opens the single-rule view (Rule editor) |
| Checkbox next to a folder | Enables/disables the whole folder (cascades to the groups and their active rules) |
| Checkbox next to a group | Enables/disables the group (cascades to its active rules) |
| Checkbox next to a rule | Independently controls a single rule |
| Status ●/○ next to a folder/group/rule | Active: ● active, ○ inactive (forced off) |
| C J A U next to a rule | Content labels: C = has CSS, J = has JavaScript, A = has actions, U = has its own URL patterns. They appear only when the relevant field is non-empty. |
| The color stripe on the left | The folder color is drawn with box-shadow inset — it does not shift the folder name position (folders with and without a color are aligned) |
| Drag & drop handle | Grab it with the mouse and drag to reorder |
expandedFolders, expandedGroups).
Hover over a folder, group or rule — a drag & drop handle appears on the left side. Grab it with the mouse and drag:
The vertical bar between the sidebar and the editor hides the left panel — useful when you need more room for the editor. The state is remembered between sessions. After showing/hiding it, CodeMirror automatically updates its width.
Below each editor (CSS, JS, action code) there is a horizontal bar with a handle for dragging vertically. Grab it with the mouse and pull down to enlarge the editor. Minimum height 80px, no maximum — the page scrolls naturally with the content.
Above each CodeMirror code editor — CSS and JavaScript in the rule card, and "JS code" in the action editor — there is a search bar: a text field and a button with a magnifying-glass icon.
n / total.| Shortcut | Action |
|---|---|
Enter | Search (a new query) or jump to the next result (when the query is unchanged) |
Shift+Enter | Previous result |
Ctrl+Alt+→ / Ctrl+Alt+← | Next / previous result — works from the editor and from the search field |
Ctrl+Alt+F | From the code editor, moves focus to the search field |
Esc | Clears the search field |
A URL pattern defines which pages a folder activates on.
| Pattern | Matches |
|---|---|
https://justzix.com/admin | Only that exact URL |
https://justzix.com/* | All pages on justzix.com |
https://*.justzix.com/* | All subdomains and pages |
*://localhost:*/* | All local apps |
https://example.com/admin/* | Only the /admin/ section and subpages |
*example* | Any URL containing "example" |
?id=123) and the hash (#section), unless you include them in the pattern.
Each rule has two independent flags:
| Flag | Meaning |
|---|---|
| Active ● | Whether this rule is controlled by the folder toggle and the group toggle (both levels cascade to active rules). Enabling a folder or a group enables all active rules inside it. |
| Enabled ✓ | The current state: whether the rule is injected into pages right now. |
Folder toggle → changes "enabled" for all active rules in its groups
Group toggle → changes "enabled" for all active rules in that group
Rule toggle → changes "enabled" for that rule only
Rules with Active: NO (badge ○) are skipped by cascades — you control them manually only, independently of the folder and group state.
Active: NO • Enabled: controlled manually
The rule does not react to enabling the whole folder. You control it manually only. Ideal for experimental modifications you don't want to enable in bulk.
Active: YES • Enabled: YES
The standard setting. Enabling/disabling the folder also controls this rule.
Active: YES • Enabled: NO
The rule is "wired" to the folder, but currently disabled. The next click of the folder's main toggle activates it again.
| Action | Effect |
|---|---|
| Left click | Toggle all matching folders (enable/disable) |
| Right click | Opens a panel with a list of folders and rules |
| Drag | Moves the position (remembered per window) |
In the drop-down panel (right click) you can:
actionBar.enabled (persistent, propagates to the edit panel)The panel only shows active rules (●) — independent ones (○) are hidden for brevity. When a folder has only one group named "Default", the group header is omitted — only the rules are shown.
Clicking the JustZix icon in Chrome's extension toolbar opens the popup widget — a compact control panel for the current tab. From the top:
actionBar.enabled).In a single workspace you can have several action bars — each with its own name, orientation, background color, its own set of buttons and an independent position per browser window. A bar can be assigned to a folder, a group or a single rule (this determines visibility and cascade).
In the folder, group or rule editor there is an "Action bars (N)" button. Clicking it opens the bar management modal. In the modal:
barId).Each action in the "Actions" tab of the rule card has an "Action bar" dropdown — you pick the target bar from the list of bars visible for that rule (the rule's own bars + group bars + folder bars).
While dragging a bar, the extension detects the edges of neighboring bars and the floating button within a distance of ≤ 12 px. A sticky visual indicator appears, and after you release, the bars join into a connection group. Then:
__float as a pseudo-bar).Right click on the bar's drag handle → context menu:
In bar edit mode this menu is muted; a right click on a label then gives the "Delete label" option.
For permanently enabling/disabling action bars (without F5), the extension offers three entry points, all mapped to the same actionBar.enabled in storage — a change from one place propagates to the edit panel and the other UIs:
actionBar.enabled.actionBar.enabled = false — the bar is not rendered at all, the state syncs between devices (sync), it is visible in the edit panel.barsHidden[barId] = true per browser window — the bar disappears until F5 / the window is closed. Enabling it from the popup/floating panel automatically clears this runtime hide.The action bar edit mode is turned on in three ways: with the Ctrl+Alt+S shortcut (works from anywhere on the page), with the toggle in the extension's popup widget, and from Chrome's context menu (right click → "Action bar edit mode"). An info bar appears at the top of the screen; using any of the toggles again exits the mode.
In edit mode the normal behavior of elements is suspended (a click doesn't run code, fields don't take focus) — instead, the elements can be arranged and resized:
Ctrl+click = add/remove from the selection; a click on an empty area or Esc = deselect all. Shift+drag over an empty area = range selection (a rectangle).Delete key removes all selected labels at once; a right click on a label gives the "Delete label" option; there is also a "Delete" button in the label editor. Action elements are deleted in the edit panel (they belong to rules).flow): it removes custom positions and sizes of elements and all labels (with a confirmation).Ctrl+Z undoes the last change (a move, a resize, adding/editing/deleting a label, a reset). The history covers the current editing session.The edit mode is "hard": moving and resizing snap to an 8 px grid, an element cannot be pulled outside the bar or placed on top of another — on a collision both elements (the one being moved and the one underneath) get a red frame, and after you release, the element returns to its previous spot. The bar cannot be shrunk so far that an element ends up outside it; when a new element or a label doesn't fit in the bar, the bar canvas automatically grows. A right click on the bar in edit mode does not show the "hide/disconnect bar" menu.
Bar layout modes: a bar starts in flow mode (classic flexbox — elements one after another, vertically or horizontally). The first move or resize of an element converts the bar to custom mode (a canvas with free positioning) — visually unchanged, because the current layout is snapshotted as the starting point.
custom mode (bar.layoutMode, bar.size, action.layout, action.size) are saved permanently and synced between devices — unlike the bar's "floating" position on the page, which stays per browser window.
Each action has a type — chosen with a dropdown at the start of each action in the rule card. 6 types are available:
| Type | UI | When it runs code |
|---|---|---|
| BUTTON | A clickable button with a label of max 6 characters | a user click |
| SELECT static | A custom bar-styled dropdown — options configured in a modal | picking an option (value = option.value) |
| SELECT js | A native <select> — your code populates the options and attaches a handler | ONCE on render ($el = <select>) |
| INPUT | A text field with a placeholder (single line) | change (Enter or blur) |
| SLIDER | An <input type="range"> slider with a label + value display | change (mouse release / Enter), value = a number |
| TEXTAREA | A multi-line field — Enter is a legit newline (does NOT run code) | change (blur — leaving the field) |
| TOGGLE3 | A 3-state segmented control (radio-like) — 3 mini-buttons, one active | a click on an inactive state, value = the active state.value, plus stateIdx and stateLabel in scope |
Static text labels are not an action type — you add them directly on the bar in edit mode (see "Bar edit mode" → labels).
value, $el (DOM element), $action ({ id, label, type, el }); for TOGGLE3 additionally stateIdx (0-2) and stateLabel.Clicking "Options (N)" in a SELECT-type action card opens a modal:
<select>).{ name, value }. name = what the user sees, value = what reaches JS as the value variable.<option> background (js variant)action.id with a copy button + a sample JS selector.::placeholder pseudo-element cannot be styled inline).min < max.(min+max)/2.change (mouse release / Tab / Enter). value = the numeric value.\n for newlines).change (blur, NOT Enter — Enter in a textarea is a legit newline). The user leaves the field → the value is saved and the code runs. value = a string with newlines.value). Default labels: OFF / MID / ON.colorText).value (state.value, fallback to state.label), stateIdx (0-2), stateLabel, $el (the container div).The choice / value / slider position / textarea content / active toggle3 state are automatically remembered per action. After F5 the value comes back; after closing the tab and reopening it (on a page matching the rule) too. A singleton per action.id — one value, independent of the specific URL.
Value format in memory per type:
Storage:
sessionStorage — synchronous, F5-safe, per tab.chrome.storage.local.actionMemory[id] — cross-tab, durable.No cross-device sync: the memory stays local. Two computers can have different values (e.g. a different per-user filter).
sessionStorage is readable by the page's scripts (same origin). For sensitive data don't use INPUT — instead write the value directly in the rule's "JS code" field.
Each action has an immutable action.id (format a_<base36>_<random>). In the rule card, next to each action, there is a badge with the row number — clicking it copies the full ID to the clipboard, and the tooltip shows the full ID.
In user JS, refer to it via data-jz-action-id:
const el = document.querySelector('[data-jz-action-id="a_mp1deeq3_uimd8l"]');
el.value = 'new value';
el.dispatchEvent(new Event('change'));
Or through the window.JZ helpers — see Calling actions programmatically from JS.
Right click on any page → JustZix:
Ctrl+Alt+S shortcut and the popup toggle.actionBar.enabled state.The window submenus rebuild on: tabs.onActivated, tabs.onUpdated (a URL change), and storage.onChanged for folders/groups/rules/actionBars/cssPanes/jsPanes/jsConsoles/outputConsoles/floatingHidden. The TEMP submenu is static (always 4 items).
The extension offers four types of floating windows injected into pages, alongside the action bars. Each window is assigned to a folder, a group or a rule (it inherits visibility cascade-style, just like action bars) and appears on pages matching by URL.
Management: in the folder / group / rule editor you will find a "Windows ▾ (N)" button. Clicking it expands a menu with the 4 types — you pick a type, a modal opens with a list of windows for that level (plus windows inherited from higher levels). You add, name, color and delete them.
| Type | Color | Used for |
|---|---|---|
| CSS pane | green | A CSS textarea injected live as a <style> |
| JS pane | amber | A JS textarea executed on a code change |
| JS Console | purple | A REPL — you type code, Ctrl+Enter runs it, the output is below |
| Output Console | emerald | A read-only preview of the page's logs (console.* + errors) |
A floating window with a text field for CSS. Every change (after a short pause) updates the injected <style> — you see the effect live. The content is remembered per browser tab (it survives F5, disappears when the tab is closed). Ideal for quickly testing CSS without saving it in a rule.
A text field for JavaScript executed in the page context. The code runs after a change (with a delay) or manually with the ▶ Run button / the Ctrl+Enter shortcut. Execution errors are shown in a red bar below the code. When the code is changed since the last run, the Run button glows yellow (the "dirty" state).
A full-fledged console in the page. You type code in the bottom field, Ctrl+Enter (or ▶) runs it, the result is appended to the log area above. Features:
console.log/warn/error/info calls during execution are shown in the log (colored by type).The input, output and history are remembered per tab. The console executes code in the page's MAIN world — you have access to all of the page's variables and functions.
A read-only log preview — it automatically captures everything that happens on the page: console.log/warn/error/info/debug, uncaught exceptions, unhandled Promise rejections, network traffic and pushes to dataLayer, as well as your own logger window.JUSTZIX.*. Unlike the JS Console (where you type code yourself) — here the logs flow on their own.
The window is split into 6 tabs, each with an entry counter (a badge):
| Tab | Content |
|---|---|
| All | All entries from all sources, in chronological order |
| JZconsole | Only your logger window.JUSTZIX.* |
| Console | Only the standard console.log/info/warn/error/debug from the page |
| Network | The page's network requests (via chrome.webRequest) |
| Errors | Uncaught exceptions and Promise rejections — with expandable details |
| DataLayer | Pushes to window.dataLayer (GTM) + a live preview of the object |
Between the tabs and the search field there is a filter bar that changes depending on the selected tab:
log, info, warn, error, debug. Uncheck a level → those lines disappear from the preview.Below the filter bar there is a permanently visible search field. It filters the entries of the active tab live (substring match, case-insensitive). Esc clears the field.
console.* entries are collapsed by default — they show a short preview (e.g. [PickupMap][2026-05-16T15:25Z] AUTO_SELECTION_SKIPPED: {reason: 'Lower priority source', …}). A click expands the full arguments (objects/arrays as an expandable JSON tree), analogous to the DevTools console.
Network captures requests via chrome.webRequest (the webRequest permission in the manifest). Each entry shows, among others, the method, URL, status, resource type, size, duration, remote address (Remote address) and initiator (Initiator). The request buffer is maintained in the background, so entries from before the window was opened also appear.
The DataLayer window is split into two columns:
dataLayer.push(...) calls in event order.window.dataLayer object as an indexed (0:, 1:, …) expandable JSON tree — you drill into nested data, analogous to the object inspector in DevTools. The snapshot updates after every push. The right column header has expand all / collapse all buttons — they work recursively on the whole tree.Clicks on JustZix's own UI (expanding tree nodes, window buttons) do not reach this tab. If the page were collecting click events (e.g. GTM auto-event), a click on the window would generate a push to dataLayer and reset the tree's expansion — the extension recognizes such pushes and does not report them (the page's real window.dataLayer remains untouched).
The Output Console exposes a global API for logging from your code (JS pane, actions, page code):
JUSTZIX.log('a regular log');
JUSTZIX.warn('a warning');
JUSTZIX.error(new Error('an error')); // shows a stack trace
JUSTZIX.info({ obj: 1, arr: [2,3] });
JUSTZIX.debug('details'); // hidden by default (filter)
Available aliases:
window.JUSTZIX — the main one, always workswindow.__JUSTZIX__ — an alias that is always availablewindow.JZ — an alias only if the page has no window.JZ of its own (some pages, e.g. Google Ads, take that name)After the Output Console appears, you will see a welcome line in the log telling you which alias is available on that page.
console.log/warn/error/info/debug(...) from the page — they also pass through to the normal DevTools console (we don't block them)window.JUSTZIX.*(...) — your dedicated channel (it does not go to DevTools)throw new Error(...)) — shown in red with the error locationPromise.reject(...) without a .catchfetch/XHR request errors do not go to the Errors tab (they are not JS exceptions) — you will find them in the Network tab by the 4xx/5xx status. We don't catch CSP violations or Chrome's internal warnings.
Ctrl+Shift+H opens a draggable quick-help window — a guide to using JustZix on the page: global shortcuts, in-window shortcuts, the Output Console, mouse handling of windows, action bar edit mode and logging to the Output Console. It works on any page. You drag the window by its header; Esc / a click outside / × / another Ctrl+Shift+H closes it.
Colors: in the management modal (the edit panel) each window has a color picker — the header dot, the header background and text, the body background and text, the color of the action buttons.
Font and size: right click on the header bar of the window → a menu with a font choice (Consolas, Menlo, Monaco, Courier New and other monospace) and a size (10–24 px).
You drag each window by its header bar. When an edge gets close to another window / action bar / floating button (≤ 12 px), a magnetic attraction appears — the windows snap into a group. Dragging a snapped group moves all the elements together. Positions are remembered per browser window.
Each window has 8 resize handles: 4 in the corners (changing width and height at once) and 4 on the edges (changing only one axis). The dragged handle keeps the opposite edge in place. Range: width 180–1200 px, height 120–900 px. The new size (pane.size) is saved — for persistent windows it is synced between devices, for TEMP windows per tab.
Scrolling with the mouse wheel inside a window scrolls only that window's content — the page underneath does not scroll. This also applies when the window's area reaches the end of its scroll, or when the cursor is over a non-scrollable part (the header, the filter bar).
Every window (both temporary TEMP and persistent ones) has a × close button in the right corner of the header. TEMP get hidden (open again from the page context menu or a shortcut), persistent — disabled (re-enable with a checkbox in the popup). Double-click on the header bar:
When a window edge gets close to another JustZix window (12 px threshold), a red edge appears on the snap side (on both windows). Releasing the cursor in this position performs the snap — the windows then move as a group. All extension windows participate in this mechanism: action bars, FAB, persistent panes (CSS/JS/Console/Output), TEMP, and the AI Helper.
You can create a temporary window on any page — even one for which you have no folder at all. TEMP panes are a quick ad-hoc tool: you test CSS/JS on a foreign page without configuring rules.
TEMP pane features:
<style> is updated immediately.Creating / closing (toggle):
AI Helper is an AI assistant built into the extension that helps you prepare and deploy a CSS/JS solution for a specific task on the current page. The model can examine the page, test code live in TEMP windows and — after your approval — create a ready-made folder, group and rule.
In the sidebar's Settings menu, the "AI Helper" item opens a configuration modal:
chrome.storage.local). A key goes to other devices only when you check the "sync" checkbox next to it — then it is synced through the JustZix cloud (the same channel the extension uses to sync folders, groups and rules). Keys without the checkbox checked never leave the device. API calls go through the extension's service worker, so the key does not reach the page context.
The AI Helper window is a floating window (per tab, like TEMP windows — draggable, resizable with 8 handles, with a closing cross, a single instance). You open / close it:
In the window: a provider choice (when you have more than one key) and a model choice (the list is fetched live), the conversation history, a button to clear the conversation, and a text field (send it with the button or Ctrl+Enter). The model automatically gets the context of the current page — the URL, the title and an HTML fragment.
AI Helper conducts the conversation according to a set workflow:
query_page tool (selectors, DOM structure) before writing code.read_temp_pane and read_console tools it checks whether the tested code reports no errors before showing you the result.The model uses tools through a simple text protocol (a @@JZ_TOOL@@ … @@END@@ block) that works identically for OpenAI, Anthropic and Gemini. Tool calls and their results are shown in the window as separate "chips". Available tools:
| Tool | Action |
|---|---|
query_page | Returns the number of selector matches and the HTML of up to 5 elements |
list_structure | Returns the existing folders / groups / rules along with their ids |
open_temp_pane | Opens a TEMP temporary window (CSS or JS) |
set_temp_pane_code | Inserts code into a TEMP window — used for live testing |
read_temp_pane | Checks the TEMP window — for JS runs the code and returns an error or success |
read_console | Opens a TEMP Output Console window and returns the page's captured console entries |
create_folder | Creates a folder + a default group (requires confirmation) |
create_group | Creates a group in a folder (requires confirmation) |
create_rule | Creates a rule with CSS/JS code (requires confirmation) |
create_bar | Creates an action bar attached to a folder/group/rule (requires confirmation) |
create_action | Creates an action (button/select/input/slider/textarea/toggle3) on a bar (requires confirmation) |
request_user_input | Shows the user an inline form in the chat window (text / number / color / select / checkbox fields) and waits for the response |
list_bars / list_actions / list_panes / list_all | Return lists of existing action bars / actions / windows (CSS/JS/Console/Output) — optionally filtered by parent |
read_folder / read_group / read_rule / read_bar / read_action | Return the full data of a specific entity (before a planned change) |
update_folder / update_group / update_rule / update_bar / update_action | Modify an existing entity — requires confirmation (with a field diff) |
create_css_pane / create_js_pane / create_js_console / create_output_console | Create a persistent front-end window (requires confirmation) |
read_*_pane / read_*_console + update_*_pane / update_*_console | Read and change the metadata of persistent windows (name, color, position, size, styling) |
read_pane_code / update_pane_code | Read and insert CSS/JS code in a persistent window (per browser tab) — requires confirmation |
screenshot_page | Capture of the current page view as an image — JustZix UI is automatically hidden; for vision-capable models |
read_temp_pane + read_console), ask you for data through an inline form (request_user_input), and take page screenshots (screenshot_page) as images attached to the next request.
A right-click on the AI Helper header bar opens a menu with the options "Bring forward" / "Send backward" (change the order of JustZix windows when they overlap), "Disconnect from: X" (when AI Helper is snapped to another window), and "Appearance…". The "Appearance…" panel lets you style four roles in the conversation separately: your messages, AI replies, tool results, inline forms — each with its own font, size, text color and background. Values are saved per device.
The AI Helper window participates in the same snap mechanism as action bars, persistent windows (CSS / JS / Console / Output) and TEMP windows. Dragging an edge close to another JustZix window (12 px threshold) → magnetic attraction, a red edge indicates the snap side on both windows. Snapped windows move as a group.
When windows overlap, the "Bring forward" / "Send backward" options in the context menu of every window (right-click on the header) make a one-shot jump — the window goes above / below all overlapping neighbours, no need to click repeatedly.
The screenshot_page tool captures the current page view and sends it to the model as an image. The entire JustZix UI is automatically hidden before capture (FAB, action bars, AI Helper, persistent panes, TEMP). A buffer of 3 most recent screenshots, attached one-shot to the next request (after sending — removed from the buffer to save tokens). Requires a vision-capable model (e.g. gpt-4o, claude-3+/4, gemini-1.5+/2). Below the tool result chip in the chat, a thumbnail is shown — click for full-screen modal view.
| Shortcut | Action |
|---|---|
Ctrl+Alt+G | Create / close a TEMP CSS pane |
Ctrl+Alt+H | Create / close a TEMP JS pane |
Ctrl+Alt+J | Create / close a TEMP JS Console |
Ctrl+Alt+K | Create / close a TEMP Output Console |
Ctrl+Alt+I | Open the edit panel (separate window), first active rule on this page, CSS tab |
Ctrl+Alt+O | As above, JS tab |
Ctrl+Alt+P | As above, Actions tab |
Ctrl+Alt+\ | Open / close the AI Helper window |
Ctrl+Alt+S | Action bar edit mode — enable / disable |
Ctrl+Z | Undo the last change (only in bar edit mode) |
Delete | Delete the selected labels (only in bar edit mode) |
Esc | Deselect all elements (only in bar edit mode) |
Ctrl+Shift+L | Clear the active tab of every Output Console |
Ctrl+Shift+H | Quick help — shortcuts and in-page windows (works globally) |
| Shortcut | Action | Window |
|---|---|---|
Ctrl+Enter | Run the code / send the message | JS pane, JS Console, AI Helper |
↑ / ↓ | Command history | JS Console (input) |
Ctrl+L | Clear the output | JS Console |
Esc | Clear the search field | Output Console |
| Shortcut | Action |
|---|---|
Ctrl+Alt+F | Focus the search field above the editor |
Ctrl+Alt+→ / Ctrl+Alt+← | Next / previous search result |
Enter / Shift+Enter | Search / next / previous result (in the search field) |
Ctrl+Alt+I / O / P | Switch the active rule's tab to CSS / JS / Actions (when the rule card is rendered) |
Ctrl+Alt+G/H/J/K are keys next to each other (Vim layout), all free in every browser and system. Ctrl+Alt+L is deliberately skipped — on Linux it locks the screen. Ctrl+Alt+S (edit mode) and Ctrl+Alt+\ (AI Helper) are in the same modifier family. The Output Console shortcuts (Ctrl+Shift+...) don't collide, because they differ in their modifier.
The extension offers five export formats (full, partial, folder, group, rule) with automatic file-type detection on import, to avoid accidentally overwriting data.
In the sidebar's Settings menu: Export settings. The modal opens two modes:
Partial export files are named justzix-partial-DATE.json (vs. justzix-backup-DATE.json for a full one), and inside they have a partial: true flag and a groups[] field.
In the folder bar: Export — opens a modal with a tree of groups and rules (analogous to a partial export, but limited to that folder). Only the selected rules and the groups they belong to are exported — empty groups don't go into the file.
The justzix-folder format — the file contains a groups[] field with the hierarchy of the folder's groups and rules.
In the group bar: Export — a modal with a list of the group's rules (checkboxes). The file: justzix-grupa-<name>-<date>.json, the justzix-group format.
In the rule view: Export rule — it downloads the file immediately (no modal). The justzix-rule format, named: justzix-zestaw-<name>-<date>.json.
justzix-full — a full backup of everythingjustzix-full with partial: true — selected elements from the main exportjustzix-folder — a single folder with a selection treejustzix-group — a group + selected rulesjustzix-rule — a single ruleAfter loading a file / pasting JSON, the extension automatically recognizes the type and shows a colored detection panel:
| Color | Meaning | Action |
|---|---|---|
| Teal | A valid full backup | Shows the number of folders/rules, the export date, an overwrite warning |
| Purple | A partial backup (partial: true) | A mode choice: Merge with the current ones or Replace everything |
| Orange | The wrong file type for this modal | A message pointing to the correct modal, the Import button blocked |
| Red | A JSON parsing error / an invalid format | The Import button blocked |
1 / nadpisz — overwrite the existing folders (this removes their groups and rules)2 / kopia (default) — import as copies with new IDs, "(import)" in the folder name, no loss of existing dataIn the folder bar: Import. It checks for conflicts by ID and name:
In the group bar: Import — accepts 3 formats:
justzix-group — inserts all the group's rules from the filejustzix-folder — inserts all the rules from all the folder's groupsjustzix-rule — inserts a single ruleAll the rules from the file go into the current group with new IDs (the operation is always an "add copy" — no conflicts).
In the rule view: Import rule — accepts only justzix-rule. A prompt with 3 options:
1 / zastap — replace the content of the current rule (id and groupId kept)2 / kopia (default) — add as a new rule next to the current one, in the same group, with an "(import)" suffixSettings → Cloud sync opens the sync account modal. The extension keeps your library (folders, groups, rules, actions, action bars, in-page windows) in the justzix.com cloud and keeps it consistent across devices. Sync works only when signed in — without an account the extension works locally only.
When signing in, the extension compares the local data with the data in the cloud:
| Choice | What it does |
|---|---|
| Use the cloud data | Clears the local library and rebuilds the account state from the server |
| Send my local data | The local data becomes canonical — it deletes what was in the cloud |
| Merge | Combines both sets — adds the missing entities, keeping the existing ones |
You can also Cancel — the extension then signs out and changes nothing.
After the first reconciliation, sync runs in the background: the extension pushes changes and pulls new entities about once a minute. A change made on one device shows up on the others after a short while. The status dot next to the "Cloud sync" item shows whether the account is connected.
The Status tab of the sync modal shows the account state and provides action buttons:
Counters of the entities held on the account: folders, groups, rules, actions, action bars, in-page windows. Only reachable entities in the tree are counted (a group must have an existing folder, a rule — a group, a bar/window — an existing parent) — consistent with the Dashboard counters. They refresh when the panel is opened and after a manual sync.
A device-local log of the most recent syncs. The page shows the last 10 entries; the "View full history" button opens a window with the full list (up to 100 entries). Each entry contains:
The log is local — it is not synchronized between devices. An entry is created after every sync tick that actually changed something; a manual "Sync now" always leaves an entry, even with zero changes.
Usage statistics (CSS applications, JS executions, window displays) are synced as separate per-device entities — the Dashboard tile sums them across all paired devices. The theme and language are synced as a shared account setting and applied the next time the panel is opened on another device.
An alternative to sending a JSON file over a messenger. You issue a public link with a lifetime (1h / 6h / 12h / 24h / 48h) and hand it to the recipient. The justzix.com backend keeps the payload in the cloud until it expires, then it is deleted.
It requires a signed-in sync account (Sync). The token itself is a public secret — anyone with the link can download it, so don't send it over public channels if the content is sensitive.
JZS-XXXX-XXXX-XXXX-XXXX (16 Crockford base32 characters, ~80-bit entropy). The whole URL https://www.justzix.com/s/JZS-... is also accepted — the extension parses and normalizes it (the confusing letters I/L→1, O→0, U→V).
Exceeding a limit = an error with a message. Revoke unused links in the My shares panel.
The "Share URL" button is in four entry points, next to "Download file":
justzix-full type)justzix-folder type)justzix-group type)justzix-rule type)A click opens the link-generation modal: a subject + a summary of what you are sharing, a radio with the TTL (24h by default), "Generate link". On success the modal switches to a result view with two copyable values:
https://www.justzix.com/s/JZS-... — to send to someone without the extension (it shows a landing page)JZS-XXXX-XXXX-XXXX-XXXX — to paste into the recipient's extension in "Import from URL"Each has its own "Copy" button. The expiration time is also shown in the local time zone.
Settings → My shares (a separate modal, not part of synchronization — these are two different features). It shows a list of active links: a counter in the header X/20 active · Y MB / 50 MB, and for each share a card with:
X folders · Y groups · Z rules · N lines of JS · A KBRevoking does not undo content that has already been downloaded. If someone managed to download the payload, they have it locally. A share is a "best-effort time-limit", not DRM.
Settings → Import from URL (between "Import settings" and "Cloud sync", the chain icon). The modal has two steps:
Step 1 — input. You paste the link or the token only. Client-side validation: the token is extracted from the URL, normalized Crockford-base32, the 16 characters + the format are checked. A wrong format → a message with a hint about the correct format.
Step 2 — preview. The extension shows a share summary:
If the share contains JavaScript (jsLines > 0) — a red warning banner appears with a "Show JavaScript code" link. It opens an overlay with the full JS code of each rule and action — review it before importing, because the code will run on matching pages.
Step 3 — import. A click on "Import" → the backend returns the full payload → the extension creates new entities with always-fresh IDs (it never overwrites existing ones by ID):
| Type | What happens |
|---|---|
justzix-rule | Creates a new folder + a "Default" group + the imported rule |
justzix-group | Creates a new folder + the imported group + rules |
justzix-folder | Adds it as a new top-level folder |
justzix-full | Merge: appends all folders/groups/rules with fresh IDs |
The new container name: <sender-name or "Import"> <PL date> — you can then rename / move it freely.
| Error | Message |
|---|---|
| An invalid token | "The token is invalid. Check whether you copied the whole link." |
404 not_found | "This link has expired or was revoked by the sender. Ask for a new one." |
429 rate_limited | "Too many attempts. Wait a moment and try again." |
| 5xx / network | "A server problem. Try again." |
The backend does not distinguish a 404 "never existed" from a 404 "expired / revoked" — deliberately, so as not to reveal whether the token ever existed.
You can call any action (from the "Actions" tab in the rule card) programmatically from the rule's JS or from another action's code. The global namespace window.JZ is installed in the MAIN world automatically before every user-JS execution.
| Call | What it does |
|---|---|
JZ.click(labelOrId) | Clicks programmatically. Semantics per action type: BUTTON → el.click(). SELECT static (a button with a dropdown) → el.click() (opens the popup; the user picks an option manually). SELECT js (a native <select>) → sets value to the first non-disabled option and dispatches change. INPUT / TEXTAREA / SLIDER → el.click() — note: it does not change the value or fire the change handler. To set the value: const el = JZ.action('LBL'); el.value = 'X'; el.dispatchEvent(new Event('change')). TOGGLE3 — el.click() hits the container; to activate a specific state use el.querySelector('.jz-toggle3-state[data-jz-state-idx="1"]').click(). Returns true/false. |
JZ.value(labelOrId) | A uniform getter of the current value. INPUT / TEXTAREA → the native el.value. SLIDER → wrap.dataset.jzValue (wrap is a DIV, the renderer sets the data attr from the initial value + on input/change). SELECT(js) → the native el.value. SELECT(static) → el.dataset.jzValue (the renderer sets it on every choice). TOGGLE3 → el.dataset.jzValue (the active state.value; fallback to state.label). BUTTON → null. An element not found → null. |
JZ.setValue(labelOrId, value) | A programmatic setter. INPUT/TEXTAREA → el.value = String(v) + dispatches input+change. SLIDER → sets the native <input.jz-action-slider> + dispatches. SELECT(js) → el.value = String(v) + dispatches change. SELECT(static) + TOGGLE3 → sends a CustomEvent 'jz-set-value', the content.js listener does the full flow (memory + UI + runs the code). TOGGLE3 lookup: by state.value → fallback to state.label → fallback to the numeric idx 0-2. BUTTON → false. Returns true/false. |
JZ.action(labelOrId) | Returns the action element (button / select / input / textarea / slider / toggle3 container) or null. Lookup: first by data-jz-action-id, then case-insensitive by data-jz-key (the UPPERCASE label). Works for all 6 action types. |
JZ.actionById(id) | Lookup only by the stable action.id (e.g. 'a_mp1deeq3_uimd8l'). Recommended for actions without a label or when you want certainty. |
JZ.actions() | An array of all visible action elements (button + select + input + textarea + slider + toggle3) on the current page. |
JZ.labels() | An array of the original labels (the case is kept as you typed it). |
// === Reading ===
const filter = JZ.value('FILT'); // INPUT/TEXTAREA — string
const opacity = JZ.value('OPAC'); // SLIDER — string numeric ("75")
const mode = JZ.value('MODE'); // SELECT static — string (option.value)
const theme = JZ.value('THM'); // TOGGLE3 — state.value of the active state
// === Setting ===
JZ.setValue('FILT', 'new value'); // INPUT/TEXTAREA — string + dispatch input+change
JZ.setValue('OPAC', 75); // SLIDER — clamp to min/max, dispatch input+change
JZ.setValue('SRT', 'prod'); // SELECT(js) — native select + dispatch change
JZ.setValue('MODE', 'staging'); // SELECT static — content.js does the flow (memory + UI + code)
JZ.setValue('THM', 'dark'); // TOGGLE3 — lookup by state.value (fallback to label, then idx)
JZ.setValue('THM', 2); // TOGGLE3 — equivalent; a numeric idx works too
| Call | What it does |
|---|---|
JZ.bars() | All the .jz-actions-bar containers (ActionBars) visible on the page. |
JZ.barById(id) | The bar element by data-jz-bar-id. |
JZ.floatingBtn() | The main floating button #justzix-floating-btn or null (when hidden). |
JZ.click / JZ.action is case-insensitive by label, but exact by the stable action.id. For actions without a label (typically INPUT) use JZ.actionById('a_...').
In an action's "JS code" field you automatically have variables available — injected as const by the background service worker before execution:
| Variable | What it contains | When available |
|---|---|---|
$el | The DOM element of this action (input / select / button / textarea / toggle3 container) | always, when action.id exists |
$action | { id, label, type, el } | always |
value | The current value per type: SELECT static → option.value; INPUT/TEXTAREA → the field content; SLIDER → a number; TOGGLE3 → the state.value of the active state (fallback to state.label when value is empty). | SELECT static, INPUT, TEXTAREA, SLIDER, TOGGLE3. SELECT js: the code runs ONCE on render — value is empty. |
stateIdx | An integer 0-2 — the index of the active state (the state the click started from). | TOGGLE3 only |
stateLabel | A string — the label of the active state (max 5 characters). | TOGGLE3 only |
In the configuration modal of a SELECT- and INPUT-type action, the "Stable action ID" panel shows the full action.id with a copy button and a sample JS selector (document.querySelector('[data-jz-action-id="..."]')). Below the list of BUTTONs you see JZ.click('LBL') chips — clicking a chip copies the snippet to the clipboard.
visible: true, the bar is visible in the tree + the page URL matches the rules).JZ.click() returns false, JZ.action() returns null.JZ.click().// The "AUTO" action code
JZ.click('LOAD'); // click the LOAD action (e.g. loads data)
setTimeout(() => JZ.click('PROC'), 500); // 500ms later PROC (processes)
setTimeout(() => JZ.click('SAVE'), 1500); // 1500ms later SAVE (saves)
After a dynamic element appears, click the action that removes it:
// Rule JS code — an observer for a modal that appears dynamically
const observer = new MutationObserver(() => {
if (document.querySelector('.cookie-banner')) {
JZ.click('CCK'); // click the action that removes the banner
observer.disconnect();
}
});
observer.observe(document.body, { childList: true, subtree: true });
// JZ.click on an INPUT doesn't change the value — use the pattern with a 'change' dispatch:
const el = JZ.action('SRCH'); // or JZ.actionById('a_mp1deeq3_uimd8l')
if (el) {
el.value = 'new filter';
el.dispatchEvent(new Event('change'));
}
If you prefer to work with the DOM directly (e.g. you change a style, you don't call):
// Lookup by the stable ID (recommended — resistant to a label change):
const el = document.querySelector('[data-jz-action-id="a_mp1deeq3_uimd8l"]');
// Lookup by label (case-insensitive — UPPERCASE in data-jz-key):
const btn = document.querySelector('[data-jz-key="MYBT"]');
btn.style.opacity = '0.5'; // dim it
btn.dataset.busy = 'true'; // a custom attribute
Where the action elements live in the DOM:
| Action type | Container | Element selector |
|---|---|---|
| BUTTON | .jz-actions-bar[data-jz-bar-id="..."] | .jz-action-btn[data-jz-action-id="..."] |
| SELECT (static) | .jz-actions-bar | .jz-action-select[data-jz-action-variant="static"] (a button with a popup; data-jz-value = the currently selected value) |
| SELECT (js) | .jz-actions-bar | .jz-action-select.jz-variant-js (a native <select>) |
| INPUT | .jz-actions-bar | .jz-action-input[data-jz-action-id="..."] |
| SLIDER | .jz-actions-bar | .jz-action-slider-wrap[data-jz-action-id="..."] (the wrap); the slider itself: .jz-action-slider (a native <input type="range">) |
| TEXTAREA | .jz-actions-bar | .jz-action-textarea[data-jz-action-id="..."] |
| TOGGLE3 | .jz-actions-bar | .jz-action-toggle3[data-jz-action-id="..."] (the container; data-jz-value = the active state.value); state buttons: .jz-toggle3-state[data-jz-state-idx="0|1|2"], the active one has the class .active |
All elements have a data-jz-action-id attribute (a unique stable identifier). The .jz-actions-bar selector is safe — it does not collide with the page's DOM.
data-jz-key) works for all action types. Every action element has both data-jz-label (the original case) and data-jz-key (UPPERCASE). For certainty (e.g. when the label may change) use the stable data-jz-action-id or JZ.actionById().
The "Search" field filters the folder tree. Matching logic:
The match is case-insensitive, yellow highlighting shows the match location.
After you click the extension icon in Chrome's toolbar, a popup widget with a large green/gray "Plugin enabled" toggle appears. In the disabled mode no CSS/JS is injected on any page, regardless of the folder settings. The floating button is then disabled (Halt Red, opacity 0.7). The state survives a Chrome restart.
A button next to the URL pattern field — it inserts protocol://host/* from the active tab. Creating a folder in 2 seconds. The extension's options page address is skipped — the most recent external tab is taken.
Inline to the right of the URL field, the information "Matches X open tabs" or a warning appears. It catches typos immediately.
A snapshot of CSS and JS is created 3 seconds after the last edit (debounce). The limit is 5 versions — the oldest gets pushed out. When restoring a version, the current content is added to the history as the newest snapshot, so you can always undo the undo.
In the header of the rule card there is a field for tags — type them separated by commas. They appear as small labels in the sidebar next to the rule name. The search also finds by tags.
Each folder can have its own label on the floating button (max 3 letters, UPPERCASE) and a color (a color picker). The label and color help you visually recognize which project is active on a given page.
Each action button counts how many times it has been clicked. It helps you see which ones are really used.
Below the CSS editor a bar with a list of syntax problems is shown:
/* ... */})} (with a line number)This is simple syntax validation — it does not check the correctness of properties/values. CSS with an error is still injected (the browser simply skips the invalid rules).
In the single-folder Import modal, after loading the file, a list of rules with metrics appears:
File content (3 rules):
Auto-login CSS: 0L • JS: 4L JS
Hide cookie banner CSS: 8L • JS: 0L
Debug GTM CSS: 0L • JS: 12L • 2 actions (8L) JS
A warning with the number of JS lines, if any are present. Clicking the JS button shows the full code for review before the import.
Each JS rule is executed separately, with its own try/catch. An error in one rule does not block the execution of others. Errors are logged in the console with the rule/action name and a full stack trace.
A memory usage indicator in the sidebar's Settings menu (e.g. 1.2 MB / 10 MB). Red above 80%.
A checkbox above the list — it hides rules marked as independent (○) and shows only those active in the folder (●). It helps weed out "manual" rules when a folder has many of them. It reacts immediately to toggle changes.
The extension has a fixed key in the manifest (the Firefox build — a fixed gecko.id), which means the extension's ID is immutable between updates — the data (folders, rules, settings) is preserved. JustZix is shipped for four browsers: Chrome, Edge, Opera and Firefox.
In the Settings menu (next to the version number) a green "A new version is available" banner appears when the server publishes a newer package than the installed one. The banner contains a download link. The check is silent — with no network the banner simply does not show.
chrome://extensions/ (Edge: edge://extensions/) find the extension and click the refresh icon on the tileThe Firefox build is loaded via about:debugging → "This Firefox" → "Load Temporary Add-on" (pointing at manifest.json in the justzix_firefox/ folder). An update = reloading after overwriting the files.
"key" field in the manifest (Chromium) / gecko.id (Firefox)/* Hide typical ads */
.ad, .ads, .advertisement,
.banner-ad, [class*="ad-banner"],
[id*="google_ads"] {
display: none !important;
}
/* Hide the cookie banner */
.cookie-banner, #cookie-notice {
display: none !important;
}
html {
filter: invert(0.92) hue-rotate(180deg);
}
img, video, picture, iframe, [style*="background-image"] {
filter: invert(1) hue-rotate(180deg);
}
The trick: invert the whole page and re-invert the images. It works surprisingly well on most pages.
/* Color all elements with data-testid */
[data-testid] {
outline: 2px dashed #f59e0b !important;
outline-offset: -2px;
}
[data-testid]::before {
content: attr(data-testid);
position: absolute;
background: #f59e0b;
color: white;
font-size: 10px;
padding: 2px 4px;
z-index: 9999;
}
/* Increase the readability of admin tables */
table.admin-list td, table.admin-list th {
padding: 8px 12px !important;
font-size: 14px !important;
}
/* A sticky table header */
table.admin-list thead {
position: sticky;
top: 0;
background: white;
z-index: 10;
}
/* Alternating rows */
table.admin-list tbody tr:nth-child(odd) {
background: #f9fafb;
}
/* Pages often have a rigid max-width 1200px - force the width */
.container, .main-content, main {
max-width: 95% !important;
width: 95% !important;
}
body::before {
content: "DEV ENVIRONMENT";
position: fixed;
top: 0;
left: 0;
right: 0;
background: #dc2626;
color: white;
text-align: center;
padding: 4px;
font-weight: bold;
z-index: 999999;
font-family: 'Roboto Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
}
body { padding-top: 28px !important; }
Great for the pattern https://dev.example.com/* so you don't mix up environments.
// For dev only! Never store real passwords
window.addEventListener('load', () => {
const login = document.querySelector('input[name="login"]');
const pass = document.querySelector('input[name="password"]');
if (login) login.value = 'admin@dev.local';
if (pass) pass.value = 'devpass123';
});
// Intercept dataLayer.push (GTM)
const origPush = window.dataLayer?.push;
if (origPush) {
window.dataLayer.push = function(...args) {
console.log('%c[GTM]', 'color:#16a34a;font-weight:bold', args);
return origPush.apply(window.dataLayer, args);
};
}
// Intercept gtag
const origGtag = window.gtag;
if (origGtag) {
window.gtag = function(...args) {
console.log('%c[GA4]', 'color:#2563eb;font-weight:bold', args);
return origGtag.apply(window, args);
};
}
Ideal for debugging an analytics configuration in production without touching the code.
// Every 500ms for 10s, check and click "Accept" buttons
let attempts = 0;
const interval = setInterval(() => {
if (++attempts > 20) return clearInterval(interval);
const buttons = [...document.querySelectorAll('button, a')];
const target = buttons.find(b =>
/akceptuj|zgoda|accept all/i.test(b.textContent || '')
);
if (target) {
target.click();
clearInterval(interval);
}
}, 500);
document.addEventListener('keydown', (e) => {
// Ctrl+Shift+S - save the form
if (e.ctrlKey && e.shiftKey && e.key === 'S') {
e.preventDefault();
document.querySelector('button[type="submit"]')?.click();
}
// Ctrl+Shift+E - go to editing (an untested example)
if (e.ctrlKey && e.shiftKey && e.key === 'E') {
e.preventDefault();
document.querySelector('a.edit-link')?.click();
}
});
// Skip annoying confirm and beforeunload while testing
window.confirm = () => true;
window.alert = (msg) => console.log('[suppressed alert]', msg);
window.onbeforeunload = null;
window.addEventListener('beforeunload', e => {
e.stopImmediatePropagation();
}, true);
// Remember - plain CSS can't do this when the parent has display:none
window.addEventListener('load', () => {
const target = document.querySelector('.important-info');
const newParent = document.querySelector('.sidebar');
if (target && newParent) {
newParent.prepend(target);
}
});
// Show all hidden input type="hidden"
document.querySelectorAll('input[type="hidden"]').forEach(input => {
const wrapper = document.createElement('div');
wrapper.style.cssText = 'background:#fef3c7;padding:4px;font-size:11px;font-family:monospace;border:1px dashed #f59e0b;';
wrapper.innerHTML = `${input.name}: ${input.value}`;
input.parentNode.insertBefore(wrapper, input);
});
Label: CLR Color: red
document.querySelectorAll('input, textarea, select').forEach(el => {
if (el.type === 'hidden') return;
if (el.type === 'checkbox' || el.type === 'radio') {
el.checked = false;
} else {
el.value = '';
}
el.dispatchEvent(new Event('change', { bubbles: true }));
});
Label: FILL Color: green
const data = {
email: 'test@example.com',
phone: '600000000',
firstName: 'Jan',
lastName: 'Testowy',
street: 'Testowa 1',
city: 'Warszawa',
zip: '00-001'
};
Object.keys(data).forEach(name => {
const el = document.querySelector(`[name="${name}"]`);
if (el) {
el.value = data[name];
el.dispatchEvent(new Event('input', { bubbles: true }));
el.dispatchEvent(new Event('change', { bubbles: true }));
}
});
Label: CART Color: orange
// For a typical shop — click the first "add to cart"
const btn = document.querySelector('.add-to-cart, [data-action="add-to-cart"]');
if (btn) btn.click();
else alert('Add-to-cart button not found');
Label: COPY Color: purple
navigator.clipboard.writeText(location.href).then(() => {
console.log('Copied:', location.href);
});
Label: TKN Color: yellow
// Extracts a JWT token from localStorage / cookies for debugging
const token = localStorage.getItem('authToken')
|| document.cookie.match(/token=([^;]+)/)?.[1];
if (token) {
navigator.clipboard.writeText(token);
alert('Token copied. First characters: ' + token.slice(0, 20) + '...');
} else {
alert('No token');
}
Label: SQL Color: blue
// Intercept all fetch calls and show them in the console
const origFetch = window.fetch;
window.fetch = async function(...args) {
console.log('%c[FETCH]', 'color:#2563eb', args[0]);
const res = await origFetch.apply(this, args);
return res;
};
console.log('Fetch logging enabled. Every call will appear in the console.');
Label: ENV Color: gray
const info = {
url: location.href,
userAgent: navigator.userAgent.split(' ').pop(),
cookies: document.cookie.split(';').length,
localStorage: Object.keys(localStorage).length,
framework: window.React ? 'React' : window.Vue ? 'Vue' : window.jQuery ? 'jQuery' : 'unknown'
};
alert(JSON.stringify(info, null, 2));
Each project has its own folder with its own URL pattern. You can have folders:
https://dev.justzix.com/* with a red "DEV" bannerIn the right-hand panel, private folders can be quickly enabled/disabled. Exporting a single folder lets you share the configuration with a team.
On every dev/staging environment, add a banner and auto-login. One CSS rule (the banner) and one JS one (the auto-fill). You create a separate folder for each environment, it merges with a simple checkbox.
An action panel with buttons: FILL (test data), CART (a test purchase), CLR (clear the form), STATE (show the app state in an alert). No programmer, no console, one click.
Favorite blogs/docs with better readability — a wider container, the font, dark mode. Each page in a separate folder, "Active" left always on.
One rule per domain with JS that intercepts dataLayer.push and gtag. You enable it when a client reports an analytics problem, without touching the page's code.
The pattern *://*.justzix.com/admin/* and CSS that fixes tables, lists, forms. Plus a "Test filter" action that automatically sets the filters for a typical workflow.
An RO (read-only) action injects CSS that hides all "Delete", "Save", "Send" buttons — a temporary "read-only mode" so you don't make a mistake.
// Hide dangerous buttons
document.querySelectorAll(
'button[type="submit"], .delete-btn, .danger-btn, [class*="delete"]'
).forEach(b => b.style.display = 'none');
console.warn('READ-ONLY MODE enabled');
[JustZix] JS error!important or more specific selectors.css-1abcd that change. Use attributes ([data-testid]) or stable selectorsThe extension has a fixed key in the manifest — subsequent updates preserve the data. If the data disappeared anyway:
chrome://extensions/ use the refresh button, don't remove and reinstallThis is normal — the positions are per browser window and stored in session memory (chrome.storage.session). After the window is closed the positions disappear, in a new window you start from the defaults. A position survives navigation between tabs in the same window.
Yes — a partial export contains only the selected folders and rules plus the visibility settings related to them. It does not contain the positions of floating panels (they are per window) or other global preferences. For a full backup use the "Everything" mode.
The "Merge" mode matches folders by ID. If the imported file had an ID conflicting with an existing folder (e.g. the same file had already been imported once), a prompt appears: 1 overwrite / 2 copy (default, safe) / Cancel. Choosing 2 gives you copies with new IDs and an "(import)" suffix in the folder name — you lose nothing.
The expand arrow appears only if the folder has rules. An empty folder has a grayed-out dot instead of an arrow. The expansion state of each folder is remembered in chrome.storage.local.
Those buttons are in the folder bar (at the top of the editing area), next to the "Delete folder" button. Don't confuse them with the buttons in the Settings menu, which concern the whole settings.
The JS of rules and actions runs in the page context via a layered strategy resilient to strict Content Security Policy rules. Most pages — including large sites such as Facebook — work right away, with no configuration.
Pages with a very strict CSP (some banks, corporate sites) may block execution. For JS to run on every page, enable the "Allow user scripts" option for JustZix: open chrome://extensions, go to the JustZix details and turn on the toggle (older browsers also require developer mode). When a page blocks execution, the JavaScript window / JS Console shows a relevant message.
JustZix — manual