maximus Posted May 2 Posted May 2 Hi everyone, I've been running this module in production a spirits catalog with 12,000+ products — for several months. Today I'm releasing it publicly. GitHub: https://github.com/mxmsmnv/Collections The problem ProcessWire's page tree is brilliant for site structure. It's painful for data management. When you have thousands of pages as records — products, listings, vacancies, menu items — you hit the same walls on every project: no table view, no inline filters, no bulk actions, no export, no REST API, no role scoping per dataset. Every PW developer has solved some version of this. Collections solves it once. Screenshots What it does Gives any ProcessWire template a configurable admin table — live search, dropdown filters, inline status toggles, bulk actions, CSV/JSON export, and a REST API — all configured through a UI, without writing code. Admin UI: Configurable columns per collection with custom labels Live search with 300ms debounce across multiple fields including Page references Dropdown filters for FieldtypePage and FieldtypeOptions fields Inline publish/unpublish toggle via AJAX Bulk actions: publish, unpublish, delete with CSRF protection CSV and JSON export with active filters preserved Role-based permissions matrix — scope each role per collection "View in Collection" button injected into the page edit form REST API: Bearer token, query param, HTTP Basic, and PW session auth API key management with expiration dates and per-key capability scopes SHA-256 hashed keys, usage tracking, rate limiting (100 req/min) WireCache support for GET responses ProFields support: Table, Textareas, Multiplier, Repeater Matrix, Combo — including dot-notation for subfields (address.city, blocks.hero.title, prices.*.amount) Field types: Text, Textarea, Integer, Float, Checkbox, URL, Email, Date, Image, File, FieldtypeFileB2, FieldtypePage, FieldtypeOptions, MapMarker, Color Requirements: ProcessWire 3.0.244+, PHP 8.2+ There's a thread from 2013 asking for exactly this: Module Idea: Flat Listings — here it is, 12 years later. Known issues are tracked on GitHub — the module is stable for production use, active development continues. 21 1
Peter Knight Posted May 2 Posted May 2 Brilliant implementation as usual. Ditto - I find when creating modules that tables are almost always the most important working view and the data model I have to fight and customise the most. I’d love to see this incorporated into the core and more modules too. 2
szabesz Posted May 2 Posted May 2 4 hours ago, Peter Knight said: I’d love to see this incorporated into the core and more modules too. Since it partially solves what Lister Pro is about, we cannot expect something like this in the core. Anyway, thank you @maximus for sharing this module, I will surely try it out. 2
gmclelland Posted May 2 Posted May 2 Thanks for sharing this! It looks really helpful. Does the Collections link in the top nav behave like a dropdown menu with all the collections listed when hovered?
maximus Posted May 2 Author Posted May 2 Not yet — currently it renders as a single top-level link. A dropdown listing all collections on hover is a reasonable UX improvement and I'll add it to the roadmap. The main challenge is that collections lists can get long, so it'll need some thought around grouping or truncation. 4
jacmaes Posted May 3 Posted May 3 @maximus Thanks for all your modules, you're on a roll! I've tested this module and opened an issue. It's probably a misunderstanding on my part, but when you get a chance, could you take a look at it? Thanks! 1
maximus Posted May 4 Author Posted May 4 Hi @jacmaes, thanks for the kind words and for taking the time to test! Both issues you reported are fixed in v1.9.2 (released today). Quick summary: Unix timestamps for start_date / end_date — datetime fields are now auto-detected by field type and formatted automatically, no manual column type override needed. Filter dropdown doing nothing — two bugs were at play: the Apply button wasn't showing up on select change (DOM queried before ready), and the query string was encoding [ / ] as %5B%5D which PHP couldn't parse as an array. Both fixed. Full details in the changelog. Let me know if anything else comes up! 2
jacmaes Posted May 4 Posted May 4 Wonderful, thanks @maximus! I can confirm that these two issues are fixed. I've added a follow-up to my Github issue as the sorting order by date does not seem to work.
maximus Posted Tuesday at 04:17 AM Author Posted Tuesday at 04:17 AM Thank you very much for your feedback and for your contribution to helping us refine the module! I'll try to make some adjustments in the coming days. The module has been in development since February 2026, so stable operation was paramount. If you have any issues or suggestions for improvement, I'm always happy to help! 1
elabx Posted Tuesday at 04:51 PM Posted Tuesday at 04:51 PM This looks amazing. Thanks for sharing! 1
iank Posted Thursday at 09:29 AM Posted Thursday at 09:29 AM Hi @maximus, I've been trying it out this module too and really like it! I have a couple of suggestions, if that's OK? Pages that don't have template view files (<templatename>.php) still show a view icon in the collection list, resulting in a 404 when clicked. This could be solved by adding a $page->viewable() check to the $showViewLink boolean. When a template's "Can this template be used for new pages?" setting ("noParents") is set to -1 (only one page) or 1 (no new pages), the "Add [collectionItem]" button still shows. Maybe a canAddNew() method of the Collection class to hide the button in those circumstances? [this worked for me, though there may be a more elegant way, or that suits your coding style]: /** * Whether the admin "Add" button should be shown for this collection. * Mirrors ProcessPageAdd's logic on Template::noParents: * 1 → template disallows new pages * -1 → singleton; only allowed while no page using it exists yet */ public function canAddNew(): bool { $template = wire('templates')->get($this->template); if (!$template || !$template->id) return false; $noParents = (int) $template->noParents; if ($noParents === 1) return false; if ($noParents === -1) { return $template->getNumPages() === 0; } return true; } //and then in collection-list.php: <?php if ($canCreate && $collection->canAddNew()): $addTemplate = $wire->templates->get($collection->template); $addUrl = $adminUrl . 'page/add/?template_id=' . $addTemplate->id; ?> Anyway, thanks for the great module! 1
maximus Posted Friday at 11:59 PM Author Posted Friday at 11:59 PM Both issues are fixed in v1.9.3 just released! @jacmaes - the sort direction bug is fixed. Root cause: the default sort direction parameter was always 'asc' (a non-empty string), so the fallback to the collection's configured direction was never reached. Now when no explicit sort is in the URL, both the sort field and direction come from the collection settings. @iank - both your suggestions are implemented, and your code was pretty much used as-is, thanks for that! View icon is now hidden for pages where $page->viewable() returns false Added canAddNew() to the Collection class that checks noParents — hides the Add button when set to "no new pages" or when it's a singleton and a page already exists And thanks to @elabx for the kind words! 1
wbmnfktr Posted yesterday at 01:15 PM Posted yesterday at 01:15 PM I might repeat myself here but: 🤯 The idea and concept of collections in addition to the interface. That's a great one! 2
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now