JustZix — user manual

Inject your own CSS styles, JavaScript code and action buttons into any page

Table of contents

Concept and core terms

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).

Data hierarchy

Folder
The top level — a group of rules for a single URL pattern. For example, a "justzix.com" folder with the pattern https://justzix.com/*. You can enable/disable a whole folder with one click.
Group
An intermediate level between folder and rules — it helps organize larger projects (e.g. "Admin", "Frontend", "QA"). Every folder has at least one group. A group has its own toggle that cascades to its active rules.
Rule
A single modification: a chunk of CSS, a chunk of JS, plus a list of action buttons and optionally its own URL patterns that limit it to specific subpages. Each rule belongs to one group.
CSS
Styles applied on the fly — changes are visible immediately after saving, with no page reload.
JavaScript
Code executed once on every load of a page that matches the pattern. It needs a page reload to run again.
Action buttons
They run JavaScript only after a click, in a floating bar. Great for diagnostic tools and frequent operations.

URL patterns at the rule and group level

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 patternRule patternsWorks 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)
Per-rule URL patterns are an additional filter — they do not replace the folder pattern. A rule activates only when the URL matches both: the folder pattern and at least one of the rule patterns (if any are set).

Tutorial — interactive introduction

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:

Interface and navigation

Edit mode

Access it via a right click on the extension icon → "Options", or a click on the icon → the "Edit panel" button.

Floating button (on matching pages)

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.

Dashboard

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:

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.

Navigation

ElementAction
Expand arrowExpands/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 folderToggle: 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 nameOpens the single-rule view (Rule editor)
Checkbox next to a folderEnables/disables the whole folder (cascades to the groups and their active rules)
Checkbox next to a groupEnables/disables the group (cascades to its active rules)
Checkbox next to a ruleIndependently controls a single rule
Status ●/○ next to a folder/group/ruleActive: ● active, ○ inactive (forced off)
C J A U next to a ruleContent 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 leftThe 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 handleGrab it with the mouse and drag to reorder
Default state after a fresh install: all folders and groups are collapsed. The first click expands, another click on the same element collapses. The expansion state is remembered between sessions (storage expandedFolders, expandedGroups).

Reordering (drag & drop)

Hover over a folder, group or rule — a drag & drop handle appears on the left side. Grab it with the mouse and drag:

Folders

Groups

Rules

Drag & drop respects the selection — if you drag the currently selected rule between folders, the selection follows it, and the target folder automatically expands.
When you are viewing a single rule, a bar with a "Show all in folder" link appears at the top of the editor so you can quickly return to the whole-folder view.

Sidebar toggle

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.

Editor resize

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.

Shortcuts

ShortcutAction
EnterSearch (a new query) or jump to the next result (when the query is unchanged)
Shift+EnterPrevious result
Ctrl+Alt+→ / Ctrl+Alt+←Next / previous result — works from the editor and from the search field
Ctrl+Alt+FFrom the code editor, moves focus to the search field
EscClears the search field

URL patterns

A URL pattern defines which pages a folder activates on.

PatternMatches
https://justzix.com/adminOnly 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"
Hint: matching ignores the query string (?id=123) and the hash (#section), unless you include them in the pattern.

Rule states (Active / Enabled)

Each rule has two independent flags:

FlagMeaning
ActiveWhether 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.
EnabledThe current state: whether the rule is injected into pages right now.

Toggle cascade

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.

Practical examples

An always-manual rule

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.

A rule always enabled with the folder

Active: YES • Enabled: YES

The standard setting. Enabling/disabling the folder also controls this rule.

A temporarily disabled 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.

Floating button and panel

ActionEffect
Left clickToggle all matching folders (enable/disable)
Right clickOpens a panel with a list of folders and rules
DragMoves the position (remembered per window)

In the drop-down panel (right click) you can:

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.

Hiding the floating button for a page: in the extension's popup widget — click the JustZix icon next to the address bar and press the "eye-off" icon next to the folder name. Restore it with the "Restore floating button" link in the same place.

Clicking the JustZix icon in Chrome's extension toolbar opens the popup widget — a compact control panel for the current tab. From the top:

Action bars (ActionBars)

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).

Creating and editing a bar

In the folder, group or rule editor there is an "Action bars (N)" button. Clicking it opens the bar management modal. In the modal:

Visibility inherited downward

Assigning an action to a bar

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).

Snapping bars (snap & connect)

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:

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.

Show/hide bars — from 3 places

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:

  1. Floating panel (right click on the main JustZix floating button) — an "Action bars" section below the list of folders/groups/rules. A checkbox per bar shows the persistent state. Click → toggle actionBar.enabled.
  2. Popup widget (clicking the extension icon next to the address bar) — an "Action bars" section below the folder list. Plus a small "eye-off" icon per folder — it hides the floating button for the current page (restore it with the "Restore floating button" link).
  3. chrome.contextMenus (right click on the page → JustZix → Action bars) — a dynamic submenu with a checkbox per bar. The list is rebuilt per active tab and on every state change.
Persistent vs runtime hide:
The positions of all bars (and of the floating button) are saved per browser window in session memory. Each window has its own positions, independent of the others. They reset when the window is closed or Chrome is restarted.

Bar edit mode — free layout

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:

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.

Positions and sizes in 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.

Action types: BUTTON / SELECT / INPUT / SLIDER / TEXTAREA / TOGGLE3

Each action has a type — chosen with a dropdown at the start of each action in the rule card. 6 types are available:

TypeUIWhen it runs code
BUTTONA clickable button with a label of max 6 charactersa user click
SELECT staticA custom bar-styled dropdown — options configured in a modalpicking an option (value = option.value)
SELECT jsA native <select> — your code populates the options and attaches a handlerONCE on render ($el = <select>)
INPUTA text field with a placeholder (single line)change (Enter or blur)
SLIDERAn <input type="range"> slider with a label + value displaychange (mouse release / Enter), value = a number
TEXTAREAA multi-line field — Enter is a legit newline (does NOT run code)change (blur — leaving the field)
TOGGLE3A 3-state segmented control (radio-like) — 3 mini-buttons, one activea 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).

Common fields

SELECT — options modal

Clicking "Options (N)" in a SELECT-type action card opens a modal:

INPUT — configuration modal

SLIDER — configuration modal

TEXTAREA — configuration modal

TOGGLE3 — configuration modal

Persistent memory (SELECT, INPUT, SLIDER, TEXTAREA, TOGGLE3)

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:

No cross-device sync: the memory stays local. Two computers can have different values (e.g. a different per-user filter).

Security: 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.

Stable action ID

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:

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).

In-page windows (CSS / JS / Consoles)

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.

TypeColorUsed for
CSS panegreenA CSS textarea injected live as a <style>
JS paneamberA JS textarea executed on a code change
JS ConsolepurpleA REPL — you type code, Ctrl+Enter runs it, the output is below
Output ConsoleemeraldA read-only preview of the page's logs (console.* + errors)

CSS pane

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.

JS pane

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).

JS Console (REPL)

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:

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.

Output Console

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.

Six tabs with counters

The window is split into 6 tabs, each with an entry counter (a badge):

TabContent
AllAll entries from all sources, in chronological order
JZconsoleOnly your logger window.JUSTZIX.*
ConsoleOnly the standard console.log/info/warn/error/debug from the page
NetworkThe page's network requests (via chrome.webRequest)
ErrorsUncaught exceptions and Promise rejections — with expandable details
DataLayerPushes to window.dataLayer (GTM) + a live preview of the object

Contextual filter bar

Between the tabs and the search field there is a filter bar that changes depending on the selected tab:

Search

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 logs — collapsible like in DevTools

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 tab

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.

DataLayer tab

The DataLayer window is split into two columns:

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).

Custom logger — window.JUSTZIX

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:

After the Output Console appears, you will see a welcome line in the log telling you which alias is available on that page.

What is captured

fetch/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.

Quick help — Ctrl+Shift+H

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.

Customizing the window appearance

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).

Dragging, snapping and connecting

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.

Resizing a 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 inside a window

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).

Right click on the window header

Close button and double-click on the header

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:

Snapping and edge highlight

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.

TEMP panes — temporary windows

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:

Creating / closing (toggle):

AI Helper — AI assistant

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.

API key configuration

In the sidebar's Settings menu, the "AI Helper" item opens a configuration modal:

Key security: API keys are by default stored only in this device's local memory (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.

Chat window

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.

Agent workflow

AI Helper conducts the conversation according to a set workflow:

  1. It asks for details — the URL scope, the folder/group/rule names, colors, the exact goal.
  2. It examines the page with the query_page tool (selectors, DOM structure) before writing code.
  3. It inserts the prepared CSS/JS code into a TEMP temporary window, which you see live on the page.
  4. It verifies errors on its own — with the read_temp_pane and read_console tools it checks whether the tested code reports no errors before showing you the result.
  5. It asks you to check the result and explicitly asks whether the test succeeded.
  6. When the test failed — it fixes the code and tests again.
  7. Only after your confirmation does it persist the solution: it creates a folder → a group → a rule set, and if needed also an action bar and actions. Each entity creation requires a separate confirmation in the extension.

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:

ToolAction
query_pageReturns the number of selector matches and the HTML of up to 5 elements
list_structureReturns the existing folders / groups / rules along with their ids
open_temp_paneOpens a TEMP temporary window (CSS or JS)
set_temp_pane_codeInserts code into a TEMP window — used for live testing
read_temp_paneChecks the TEMP window — for JS runs the code and returns an error or success
read_consoleOpens a TEMP Output Console window and returns the page's captured console entries
create_folderCreates a folder + a default group (requires confirmation)
create_groupCreates a group in a folder (requires confirmation)
create_ruleCreates a rule with CSS/JS code (requires confirmation)
create_barCreates an action bar attached to a folder/group/rule (requires confirmation)
create_actionCreates an action (button/select/input/slider/textarea/toggle3) on a bar (requires confirmation)
request_user_inputShows 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_allReturn lists of existing action bars / actions / windows (CSS/JS/Console/Output) — optionally filtered by parent
read_folder / read_group / read_rule / read_bar / read_actionReturn the full data of a specific entity (before a planned change)
update_folder / update_group / update_rule / update_bar / update_actionModify an existing entity — requires confirmation (with a field diff)
create_css_pane / create_js_pane / create_js_console / create_output_consoleCreate a persistent front-end window (requires confirmation)
read_*_pane / read_*_console + update_*_pane / update_*_consoleRead and change the metadata of persistent windows (name, color, position, size, styling)
read_pane_code / update_pane_codeRead and insert CSS/JS code in a persistent window (per browser tab) — requires confirmation
screenshot_pageCapture of the current page view as an image — JustZix UI is automatically hidden; for vision-capable models
AI Helper can create, read and modify the full structure of the extension (folders / groups / rules / bars / actions / persistent windows), verify errors in the tested code on its own (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.

AI Helper window appearance

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.

Snapping with other windows and Z-order

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.

Page screenshot (for vision models)

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.

Keyboard shortcuts

Global (work from anywhere on the page)

ShortcutAction
Ctrl+Alt+GCreate / close a TEMP CSS pane
Ctrl+Alt+HCreate / close a TEMP JS pane
Ctrl+Alt+JCreate / close a TEMP JS Console
Ctrl+Alt+KCreate / close a TEMP Output Console
Ctrl+Alt+IOpen the edit panel (separate window), first active rule on this page, CSS tab
Ctrl+Alt+OAs above, JS tab
Ctrl+Alt+PAs above, Actions tab
Ctrl+Alt+\Open / close the AI Helper window
Ctrl+Alt+SAction bar edit mode — enable / disable
Ctrl+ZUndo the last change (only in bar edit mode)
DeleteDelete the selected labels (only in bar edit mode)
EscDeselect all elements (only in bar edit mode)
Ctrl+Shift+LClear the active tab of every Output Console
Ctrl+Shift+HQuick help — shortcuts and in-page windows (works globally)

Inside a window (when it has focus)

ShortcutActionWindow
Ctrl+EnterRun the code / send the messageJS pane, JS Console, AI Helper
/ Command historyJS Console (input)
Ctrl+LClear the outputJS Console
EscClear the search fieldOutput Console

Code editors (the edit panel)

ShortcutAction
Ctrl+Alt+FFocus the search field above the editor
Ctrl+Alt+→ / Ctrl+Alt+←Next / previous search result
Enter / Shift+EnterSearch / next / previous result (in the search field)
Ctrl+Alt+I / O / PSwitch the active rule's tab to CSS / JS / Actions (when the rule card is rendered)
Why these combinations? 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.

Export and import

The extension offers five export formats (full, partial, folder, group, rule) with automatic file-type detection on import, to avoid accidentally overwriting data.

Export — full or selected elements

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.

Exporting a single folder (with a selection)

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.

Exporting a group

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.

Exporting a single rule

In the rule view: Export rule — it downloads the file immediately (no modal). The justzix-rule format, named: justzix-zestaw-<name>-<date>.json.

Five file formats:

Import — automatic type detection (the full-import modal)

After loading a file / pasting JSON, the extension automatically recognizes the type and shows a colored detection panel:

ColorMeaningAction
TealA valid full backupShows the number of folders/rules, the export date, an overwrite warning
PurpleA partial backup (partial: true)A mode choice: Merge with the current ones or Replace everything
OrangeThe wrong file type for this modalA message pointing to the correct modal, the Import button blocked
RedA JSON parsing error / an invalid formatThe Import button blocked

Partial import modes (the purple panel)

Importing a single folder

In the folder bar: Import. It checks for conflicts by ID and name:

Importing a group

In the group bar: Import — accepts 3 formats:

All the rules from the file go into the current group with new IDs (the operation is always an "add copy" — no conflicts).

Importing a single rule

In the rule view: Import rule — accepts only justzix-rule. A prompt with 3 options:

A full import overwrites all the settings (unless it is a partial backup with the "Merge" mode). Do an export before an import, to have a backup.

Practical uses of a partial export

Cloud sync

Settings → 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.

Account and sync key

First sync — conflict resolution

When signing in, the extension compares the local data with the data in the cloud:

ChoiceWhat it does
Use the cloud dataClears the local library and rebuilds the account state from the server
Send my local dataThe local data becomes canonical — it deletes what was in the cloud
MergeCombines both sets — adds the missing entities, keeping the existing ones

You can also Cancel — the extension then signs out and changes nothing.

Ongoing sync

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.

Ghost protection. A folder previously deleted on one device could "resurrect itself" when signing in on the next one. The extension now fetches the list of deleted entities (tombstones) from the server and does not push back something that was deleted elsewhere.

Status tab — cloud library, history, actions

The Status tab of the sync modal shows the account state and provides action buttons:

Cloud library

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.

Sync history

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.

What syncs and what does not

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.

Sharing by link (Shares)

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.

Token format

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).

Account limits

Exceeding a limit = an error with a message. Revoke unused links in the My shares panel.

Creating a link (sender)

The "Share URL" button is in four entry points, next to "Download file":

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:

Each has its own "Copy" button. The expiration time is also shown in the local time zone.

The "My shares" panel

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:

Revoking 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.

Importing from a link (recipient)

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):

TypeWhat happens
justzix-ruleCreates a new folder + a "Default" group + the imported rule
justzix-groupCreates a new folder + the imported group + rules
justzix-folderAdds it as a new top-level folder
justzix-fullMerge: 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.

Recipient errors

ErrorMessage
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.

Calling actions programmatically from JS

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.

API — actions

CallWhat it does
JZ.click(labelOrId)Clicks programmatically. Semantics per action type: BUTTONel.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 / SLIDERel.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')). TOGGLE3el.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).

Example — reading and setting values

// === 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

API — bars and the floating button

CallWhat 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).
The lookup in 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_...').

Context vars in action code

In an action's "JS code" field you automatically have variables available — injected as const by the background service worker before execution:

VariableWhat it containsWhen available
$elThe DOM element of this action (input / select / button / textarea / toggle3 container)always, when action.id exists
$action{ id, label, type, el }always
valueThe 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.
stateIdxAn integer 0-2 — the index of the active state (the state the click started from).TOGGLE3 only
stateLabelA string — the label of the active state (max 5 characters).TOGGLE3 only

Snippet in the UI

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.

Requirements

Example — an AUTO action that runs a sequence

// 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)

Example — rule JS reacting to the DOM

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 });

Example — setting an INPUT value programmatically

// 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'));
}

Direct DOM access

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 typeContainerElement 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.

Lookup by label (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().

Selected features

Sidebar search

The "Search" field filters the folder tree. Matching logic:

The match is case-insensitive, yellow highlighting shows the match location.

Global switch

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.

Insert URL from the tab

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.

Live URL validation

Inline to the right of the URL field, the information "Matches X open tabs" or a warning appears. It catches typos immediately.

Rule change history

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.

Tags and searching by tags

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.

Folder label and color

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.

Action click statistics

Each action button counts how many times it has been clicked. It helps you see which ones are really used.

CSS validation

Below the CSS editor a bar with a list of syntax problems is shown:

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).

JS preview on import

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.

Try/catch JS isolation

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.

Storage quota

A memory usage indicator in the sidebar's Settings menu (e.g. 1.2 MB / 10 MB). Red above 80%.

The "Active only" filter

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.

Updating the extension

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.

New-version notification

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.

Update procedure (Chrome / Edge / Opera)

  1. Download the new update ZIP
  2. Unpack it overwriting the same folder where the previous version was
  3. In chrome://extensions/ (Edge: edge://extensions/) find the extension and click the refresh icon on the tile
  4. The extension reloads with the new files, the data stays

Firefox

The 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.

What can cause data loss: Always do an export before any operation on the extension. If you use cloud sync — the data is also in the account cloud.

CSS examples

CSS Hiding ads and banners
/* 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;
}
CSS Dark mode for a page with no dark-mode support
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.

CSS Highlighting elements for tests / e2e
/* 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;
}
CSS A more readable admin panel
/* 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;
}
CSS A wider content container
/* Pages often have a rigid max-width 1200px - force the width */
.container, .main-content, main {
  max-width: 95% !important;
  width: 95% !important;
}
CSS Making the dev environment obvious (a colored banner)
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.

JavaScript examples

JS Auto-filling login fields (dev environment)
// 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';
});
JS Logging analytics events to the console
// 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.

JS Auto-skipping intro / cookies / ads
// 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);
JS Adding keyboard shortcuts
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();
  }
});
JS Disabling alerts / confirm / beforeunload
// 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);
JS Moving an element to another place in the DOM
// 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);
  }
});
JS Showing hidden fields / elements
// 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);
});

Action button examples

ACTION CLR — clear the form

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 }));
});
ACTION FILL — fill in test data

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 }));
  }
});
ACTION CART — add a test product to the cart

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');
ACTION COPY — copy the page URL to the clipboard

Label: COPY   Color: purple

navigator.clipboard.writeText(location.href).then(() => {
  console.log('Copied:', location.href);
});
ACTION TKN — show the authentication token

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');
}
ACTION SQL — show API requests in the console

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.');
ACTION ENV — show environment info

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));

Usage scenarios

1. Working with multiple clients / projects

Each project has its own folder with its own URL pattern. You can have folders:

In the right-hand panel, private folders can be quickly enabled/disabled. Exporting a single folder lets you share the configuration with a team.

2. A development environment with a visual marker

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.

3. Tools for a product manager / QA

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.

4. Modifying public pages

Favorite blogs/docs with better readability — a wider container, the font, dark mode. Each page in a separate folder, "Active" left always on.

5. Debugging analytics / GTM

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.

6. Working on admin panels

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.

7. Safe testing in production

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');

Common problems and solutions

The JavaScript didn't run

The CSS isn't working

The floating button doesn't appear

I lost data after a plugin update

The extension has a fixed key in the manifest — subsequent updates preserve the data. If the data disappeared anyway:

The button/panel positions reset

This 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.

A partial export skipped some global settings

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.

A partial import overwrote a folder that didn't exist before

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 folder tree doesn't expand

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.

I don't see the folder Export/Import button

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.

AI Helper isn't responding

A conflict with the Content Security Policy

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