Simple Folders

Simple Folders

Plugin from gcarstoiu

Overview

Adds folders to the Unraid Docker page. Group related containers into a folder, fold it away behind a single row that still shows every member's icon, and unfold it to see the full container rows numbered in start order. A folder's icon opens its commands: start, stop, restart, pause, resume, check for updates, update, force update, and open every WebUI. Each runs across the whole folder, one container at a time, honouring the folder's start order, its delay between starts, and reverse-order stop. Only one job runs at a time. Clicking any icon in a folded folder opens that single container's menu instead. Rearrange by dragging: a grip at the left of each row moves a container into a folder, sets where it starts, or takes it out again, and drags folders into the order you want. It works by touch too, and everything it does is also in the menus. Folders can fill themselves: give one a name pattern, or label a container simple.folders=folder, and matching containers join automatically, including ones created later. Folder start order drives Unraid's own autostart order rather than shadowing it, so containers come up at boot in the same order the folder uses. Folder icons come from a built-in set, from one of the member containers, or downloaded and stored locally so they still render with no internet. Editing or deleting a folder never stops, removes or recreates a container; deleting one only removes the grouping and its containers move to "Not in a folder". A "Classic view" switch restores the standard Unraid table at any time, and uninstalling leaves the stock page exactly as it was. Folder definitions are stored on the flash drive and survive reboots. No core Unraid file is modified.

Simple Folders

Group Docker containers into folders on the Unraid Docker page.

Fold a folder away behind a single row that still shows every member's icon, unfold it to see the full container rows in start order, and run start, stop, restart, pause, resume, update or force update across a whole folder — one container at a time, in the order you chose.

Supports Unraid 7.2 – 7.4.

Folders on the Docker page


What it does

  • Folders on the Docker page. A folded folder shows its name, its member count and an icon strip with every member — no cap, no "+3". Clicking any of those icons opens that container's own menu. Unfold to get the full rows, numbered in start order.
  • Folder-wide commands from the folder's icon or its ⋮ menu: start, stop, restart, pause/resume, check for updates, update, force update, open every WebUI. They run sequentially, honouring the folder's delay between starts and reverse-order stop. Only one job runs at a time.
  • Folders that fill themselves. Give a folder a name pattern, or label a container simple.folders=<folder>, and matching containers join automatically — including containers created later.
  • Start order that actually applies at boot. A folder's order and delay are written into Unraid's own /var/lib/docker/unraid-autostart, so the array starts containers in the same order the folder uses. No second, competing order to keep in sync.
  • Folder icons from a built-in set, from one of the member containers, or searched across Dashboard Icons and selfh.st — both libraries' published indexes, so results are real files rather than guessed names — and stored locally so they still render with no internet.
  • Drag to rearrange. Grab a row anywhere — its name, its icon, or the grip at the left: reorder a container that is in no folder (this writes Unraid's own display order, so the stock table agrees), drag one onto a folder to move it there, between two members to set where it starts in the folder, or down to "Not in a folder" to take it out. Drag a folder to reorder the folders. Pointer Events, so touch works as well as a mouse — and every one of those moves is also in the menus and the editor, which is what keyboard users have.
  • The classic Docker actions at the foot of the table: add a container, start/stop/pause/resume everything, check for and apply updates, container size. Stop and Pause confirm first.
  • Classic view. One switch puts Unraid's standard table back, untouched.

A folder unfolded, showing its containers in start order

Editing or deleting a folder never stops, removes or recreates a container. Deleting one only removes the grouping; its containers keep running and move to "Not in a folder".


Install

Community Applications — search for Simple Folders.

Manually — Plugins → Install Plugin, and paste:

https://raw.githubusercontent.com/gcarstoiu/simple.folders/main/simple.folders.plg

Then open the Docker tab.

Uninstalling

Removing the plugin restores the stock Docker page and touches no container. Folder definitions stay in /boot/config/plugins/simple.folders/ so a reinstall picks them up; delete that directory to erase them.


How it fits into Unraid

The plugin adds a page file with Menu="Docker", which emhttp renders inside the Docker tab after the stock container table. No core file is patched.

It reads containers through Unraid's own DockerClient / DockerTemplates classes and acts through Unraid's own endpoints:

What Unraid's own code we call
start / stop / restart / pause / resume dynamix.docker.manager/include/Events.php
check for updates include/DockerUpdate.php
update and force update scripts/update_container
autostart flag and start delay include/UpdateConfig.php
live CPU and memory the dockerload nchan channel

It deliberately does not parse the HTML that include/DockerContainers.php renders. That markup changed substantially between 7.2.1 and 7.4, and scraping it is the usual reason folder plugins break on an Unraid upgrade. The endpoints above were verified byte-identical across that same range.

Update and force update are the same operation — update_container always pulls and recreates, restoring each container's previous running state. The two menu items differ only in which containers they target.

Where things live

Path What
/boot/config/plugins/simple.folders/folders.json folder definitions (flash, survives reboots)
/boot/config/plugins/simple.folders/icons/ downloaded folder icons
/usr/local/emhttp/plugins/simple.folders/ the plugin itself (RAM; rebuilt each boot)
browser localStorage which folders you have open, and Classic view

Fold state is per-viewer on purpose, so two people looking at the same server do not fight over each other's open folders.


Development

No build step — the plugin is plain PHP, CSS and ES5-compatible JavaScript that runs as-is from src/.

Local harness

harness/ is a mock Unraid: stub implementations of every endpoint the plugin calls, 16 fake containers matching the design, a fake dockerload stream, and a faithful copy of Unraid's global CSRF gate — so code that forgets the token fails locally instead of on your server.

./harness/serve.sh          # http://localhost:8089

It uses a local php if there is one, otherwise php:8.3-cli-alpine in Docker (matching the PHP that Unraid 7.2–7.4 ship).

Variable Effect
HARNESS_LATENCY seconds per simulated docker action (default 0.6, 0 = instant)
HARNESS_FAIL force failures, e.g. sonarr:stop,radarr:*

Useful URLs: ?theme=white|black|azure|gray, ?folded=all, ?nostream=1 (stop the live stream so a headless browser can settle), /_reset (wipe state).

Tests

./harness/serve.sh &
./harness/test/run.sh          # all
./harness/test/run.sh filter   # just the matching ones
python3 tools/contrast.py      # WCAG check on both token sets

run.sh walks design/DESIGN_SPEC.md §15's acceptance checklist with real clicks and keystrokes, driving a headless Chrome over CDP, and writes a screenshot per state to harness/test/shots/.

Packaging

./pkg_build.sh      # -> archive/simple.folders-<version>.txz, md5 into the .plg

Bump the version in one place: the <!ENTITY version> line in simple.folders.plg.

Design

design/ holds the handoff this was built from — DESIGN_SPEC.md is the source of truth for behaviour, with the prototype and screenshots beside it.

Known deviations, all deliberate:

  • Fonts. The spec asks for IBM Plex Sans/Mono. Shipping a webfont into someone else's UI is the wrong trade, so the host theme's face is inherited and only the sans/mono distinction is kept.
  • Control contrast. The handed-over tokens put the control border and the switch "off" track at about 1.4:1 against their backgrounds, below WCAG 1.4.11's 3:1 for control boundaries. Both were darkened/lightened until they pass; tools/contrast.py enforces it.
  • Light themes. The tokens were dark-only. styles/tokens.css derives a light set for Unraid's white and azure themes.
  • Update progress. Phases come from polling the server, not from parsing update_container's log — that log is translated on non-English servers.

Picking this up again

Hard-won constraints. Each of these shipped as a bug first; none is obvious from the code alone, and all of them are easy to undo by accident.

Never parse DockerContainers.php's row HTML. It changed substantially between 7.2.1 and 7.4 and is the usual reason folder plugins break on upgrade. Read containers through DockerClient/DockerTemplates instead; those are stable across the range.

Require DockerClient.php at file scope, never inside a function. It declares $dockerManPaths, $driver, $docroot and $dockercfg at its top level and thirteen of its methods reach for them with global. An include takes the scope of whatever included it, so requiring it in a function makes them locals and every lookup resolves to null.

Asset mtimes must change between releases. autov() cache-busts on filemtime. pkg_build.sh derives the archive mtime from the version for exactly this reason — a fixed one made three releases install correctly and change nothing, because browsers kept the old JavaScript. The build refuses to run if that derivation stops varying.

Keep the unapi class on the mount and the overlay layer. Unraid guards 88 element rules with :where(:not(.unapi *)). Without it, its button rule repaints every control (uppercase, min-width: 86px, an orange border). The element reset in table.css is the second line of defence and is scoped .sf-root button (0,1,1) on purpose: component rules are .sf-root .sf-xxx (0,2,0) so they still win. A tie decided by load order is not a guarantee.

Take pointer capture only once a drag starts, not on pointerdown. Capture retargets pointerup, and a browser only fires click when press and release share a target — capturing early silently kills every click in the row.

Don't call Unraid's UserPrefs.php. It saves the display order and re-sorts unraid-autostart to match, which would undo the start order a folder owns. Order.php writes the display order alone.

Every POST is CSRF-gated by local_prepend.php (a php.ini auto_prepend_file). jQuery's $.post is patched to add the token; fetch is not, so api.js sends X-CSRF-Token. The harness reproduces this, which is the point — otherwise code passes locally and 403s on hardware.

Apply behaviour to both container sources. sf_containers() returns early for the harness fixture reader. Logic added after that early return is never exercised by the tests; the display order shipped doing nothing that way.

Where things stand

Submitted to Community Applications and awaiting manual moderator review. Until it is listed, installation is the .plg URL above, which is also how updates reach existing installs.

Open: <Support> points at GitHub issues; the Unraid convention for plugins is a forum support thread, and if one is created it should be pointed at in both templates/simple.folders.xml and ca_profile.xml. The plugin has only ever run on one server — the APIs it uses were verified identical in the 7.2.1 and 7.4.0-rc.2.1 sources, but 7.3.x hardware is untested.


Licence

GPL-2.0. See LICENSE.

The plugin interoperates with, and calls into, Unraid's GPL-2.0 Docker manager.

It bundles no third-party artwork. Container icons come from Unraid's own resolution. Folder icons are either the built-in glyph set (original to this project), a container's own icon, or a file the user chooses to download.

Icon search reads, and downloads on the user's request, from two libraries:

Library Licence
Dashboard Icons Apache-2.0
selfh.st/icons CC BY 4.0

Both permit redistribution; CC BY 4.0 requires attribution, which is given here, in Settings → Simple Folders, and beside the search itself. Individual logos remain the property of their respective owners — neither the libraries' licences nor this one grant any trademark rights.

Media gallery

1 / 2

Download Statistics

0
Total Downloads
5
This Month

Downloads by Month

Loading chart...

Related apps

Details

Repository
https://raw.githubusercontent.com/gcarstoiu/simple.folders/main/simple.folders.plg
Last Updated2026-11-14
First Seen2026-11-13