Leaderboard
Popular Content
Showing content with the highest reputation on 04/02/2026 in all areas
-
Hey everyone, on a recent client project we had to deal with a large number of Markdown files that needed to end up as regular HTML content on ProcessWire pages. Converting them manually or piping them through external tools wasn't an option – too many files, too tedious, and the content had to be stored as actual HTML in rich textfields, not just formatted at runtime. So we built a small module that handles this directly inside ProcessWire. How it works The module creates a file upload field (md_import_files) and a Repeater field (md_import_items) with a standard title field and a richtext body field (md_import_body) inside. The body field automatically uses TinyMCE if installed, otherwise CKEditor. You add both fields (md_import_files,md_import_items) to any template, upload your .md files, hit save – each file gets converted to HTML via PW's core TextformatterMarkdownExtra and stored as a separate Repeater item. The source filename goes into the items title, processed files are removed from the upload automatically. Template output The Repeater items are regular PW pages, so output is straightforward: foreach ($page->md_import_items as $item) { echo "<section>"; echo "<h2>{$item->title}</h2>"; echo "<div>{$item->md_import_body}</div>"; echo "</section>"; } Tag mappings One thing we needed right away: control over how certain Markdown elements end up in HTML. For example, #headings in Markdown become <h1> – but on most websites <h1> is reserved for the page title. The module has a simple config (Modules → Configure → Markdown Importer) where you define tag mappings, one per line: h1:h2 h2:h3 strong:b blockquote:aside hr:br This performs a simple 1:1 tag replacement after conversion, preserving all attributes. Works well for standalone or equivalent elements like headings, inline formatting, blockquotes, or void elements like hr:br. Note that it doesn't handle nested structures – mapping table:ul for example would only replace the outer <table> tag while leaving thead, tr, td etc. untouched. Requirements ProcessWire 3.0.0+ FieldtypeRepeater (core) TextformatterMarkdownExtra (core) GitHub: github.com/frameless-at/MarkdownImporter Modules Directory: https://processwire.com/modules/markdown-importer/ Happy to hear if anyone finds this useful or has suggestions for improvements. Cheers, Mike4 points
-
Sooo, I'm still alive and in August, I will start on a new job and project that probably brings me back to work with the cool and great Processwire. :D 7 years ago I was forced to change job and ended in a cool new place doing front-end dev not using PW anymore. So unfortunately I didn't really use or follow PW in that time except once a year doing something tiny bits on the handful of websites I am responsible for. I'm sorry if I just disappeared "over night" and maybe left some things behind I was doing for PW, and didn't spend time looking out for them. The reason is, I also was very frustrated with a lot of things with the job and life at that time and 2019 was also when I started painting again digitally, as maybe some of you know. I went full hyper focus mode, everyday almost for 2-3 years in my spare time and since then slowed down. I was able to make a small career with it, and made a lot of new connections and experiences which was awesome. I will continue to work on making art and illustrations as I have a lot of new freedom with the new job too combine a lot of my skills. Finally I can work from home full time. A little dream come true. Thanks for still being here and keeping this small but awesome community alive! I have to catch up now! :D Cheers Soma1 point
-
This week I worked with Claude Code on refactoring the core WireHooks class to improve it in various ways. I do this work because I like to code, so am of course handling that part. But Claude has been very helpful in finding issues as well as reviewing all my code before it gets committed. In this case, Claude found several bugs that are now fixed, and also saved me from introducing more when I added new features. Working with Claude Code reminds me of 1989 when I was in high school learning Turbo Pascal and building a BBS, and getting help from a neighbor and good friend that was doing the same. I learned so much then and now it feels like that time again. But man have things come a long way since then. I asked Claude about helping with the ProcessWire issues and requests GitHub repos, and now it's solving issue reports, replying to them and committing fixes. For simple fixes that involve a line or two, I'm going to let it handle the the whole thing. It's posting under my GitHub account, but it identifies itself as Claude in replies and and in commits. That way it's easy to tell what it does under my account. I had it just cover a couple of issue reports today as a test (see 2195 and 2192), but will be having it do a lot more going forward. Back to the WireHooks class, I asked Claude about writing a commit message for the WireHooks updates, and wow, check this out: Bug fixes in WireHooks: - conditionalArgMatch(): Fix Selector mutation bug where the shared Selector object stored in hook options was permanently mutated after the first call, causing argMatch hooks (e.g. addHook('WireLog::save(=errors)')) to stop matching after their first invocation. - getHooks(): Remove key variable from foreach to prevent shadowing $method param. - getHooks(): Replace array_merge() in loops with direct array append. - addHook(): Prevent 'noAddHooks' option from leaking into stored hook options. - isHookedOrParents(): Use $className string consistently in cache key writes, rather than $class which may be a Wire object. - runHooks(): Scope $useHookReturnValue inside foreach so it resets per hook. - runHooks(): Use strict null comparison ($toObject === null). Bug fixes in HookEvent: - arguments(): Allow setting an argument value to null (use func_num_args() > 1 instead of $value !== null check). - arguments(): Use array_key_exists() instead of isset() for null-correct lookup. - getArgumentNames(): Guard ReflectionMethod instantiation with method_exists() to avoid uncaught ReflectionException for dynamically-added hook methods. - __toString(): Fix argument list building (was appending to string instead of array), add null/bool display, avoid PHP fatal for objects without __toString(). New features in WireHooks: - cancelHooks: Now accepts string values 'before' or 'after' (in addition to boolean true) to cancel only hooks of a given type. For example, a before hook can set $event->cancelHooks = 'after' to cancel remaining after hooks without affecting the hooked method call. - Custom event data carry-forward: Custom data set on a HookEvent (via $event->customKey = $value) is now carried forward to subsequent HookEvent instances within the same runHooks() call. This allows before hooks to pass data to after hooks without using external variables. - getHooks('*'): Supports wildcard method to return all hooks for all objects. Available in debug mode only (uses allStaticHooks/allLocalHooks aggregates). - allStaticHooks: Now tracked alongside allLocalHooks when debug mode is on. - addHooks() comment fix: "If there is a parenthesis" corrected to "no parenthesis". - addHook() exception messages improved with additional context. - runHooks() docblock updated to include 'either' type. - hookTimer() PHPDoc: @param String corrected to lowercase string. New features in HookEvent: - $defaults static property: Defines the canonical set of standard HookEvent fields, used to distinguish custom data from built-in event properties. - $eid property: Each HookEvent instance gets a unique sequential event ID. - set() override: Tracks non-default keys set on the event in $customKeys. - getCustomData(): Returns only the custom (non-default) data set on the event, used internally by runHooks() for the carry-forward feature. - cancelHooks property updated to support bool|string type. Anyway, I know a lot of you here are deep into the AI stuff, and I'm just getting started, so none of this is surprising. But it sure is a pleasure collaborating with Claude Code on this stuff and it brings back that coding wonder and excitement from 1989. Some Claude and Claude Code podcasts I've enjoyed listening to or watching this week include one from AI for Humans Claude is Cooking, Wednesday's AI Daily Brief on How to use Claude's new upgrades, and the Get Educated AI video of how to setup Claude to use your computer and web browser, etc. (though I've not tried this just yet!). Lastly, last week I put together a ProcessWire powered JSON feed of bike tours, and the client prompted that they wanted a map and look what Claude Code did, I'm impressed!1 point
-
Thanks, great suggestions. Being still kind of new to this, I've found myself overwhelmed by all agents tools and options. So having Claude code as the base is what I feel helped me to finally get into this stuff. It's like my key into this world. And I think it's working so well right now that I'm not concerned about whether a file is named Claude or agents, but it's good to know about for sure. If we start adding this type of file to the core then no doubt we'd want it to be an agents file, so that a broader audience can benefit from it. At the moment I'm loving the commit messages, claude attributions and GitHub replies. Feels like I have a coworker working with me at my computer all day now, which is something I've never had. but if it gets to be too much it's definitely helpful to know that this stuff is configurable. New PW AI updates coming tomorrow too.1 point
-
I'm happy to see you found your workflow using Claude Code. 🙂 A few things I'd suggest to make it a bit more future-proof and less focussed on one tool (Claude/Claude Code). I'm not sure if you use a CLAUDE.md file yet but in case you do or when you start using it, do this: In CLAUDE.md just add: @AGENTS.md And then write your instructions in/to AGENTS.md. The reason is simple: CLAUDE.md just works for Claude, but AGENTS.md works for almost any other AI agent. This way, either in a CLAUDE.md or AGENTS.md, you can customize comments in issues, like: ## GitHub issue and PR comments When responding in GitHub issue or PR comments: - Be concise, direct, and helpful. - Start with the answer first. - Use short paragraphs or bullets when useful. - Avoid unnecessary disclaimers, hedging, or repetition. - If the user asks for a change, give the exact action or code needed. - If more context is needed, ask one clear follow-up question. - Keep the tone professional, friendly, and technical. - Do not write long explanations unless explicitly requested. - Always add this as the last line in comments: [🤖 Answered by Joshi - Ryan's custom AI Agent.] Another thing you could change is updating the Claude settings.json to disable or customize the attribution line in commits and pull requests. https://code.claude.com/docs/en/settings https://code.claude.com/docs/en/settings#attribution-settings1 point
-
This is caused by the TracyDebugger - I have forgotten to remove this call after Debugging. Please go to the Form.php and find the following line and remove it: bd($this->formErrors); Then this error will be gone. I have removed the TracyCall on Github too. This is strange, because it has nothing to do with the PHP code. Please take a look at your CSS classes. On my site the color is white. Yes, this is a browser security behavior and independent which browser you will use - file upload fields will always be empty after submission (whether successfully or not). I will test it with file upload fields and see if I can reproduce the issues. For now, please remove the bd() call first.1 point
-
Hey everyone! I just released a new module called InviteAccess. It's something I built for my own workflow and figured it might be useful for others too. The problem: when handing off a staging site to a client or a design agency, you either open it to the world or reach for HTTP Basic Auth — which works but isn't pretty and requires server config. I wanted something in between: a proper gate page that looks like it belongs to the project, with separate codes for each team. What it does InviteAccess hooks into ProcessPageView::execute (before any template rendering) and blocks all frontend requests until a valid invite code is entered. Logged-in ProcessWire users always pass through automatically. You define codes in the module config, one per line: SUMMER2025|Summer Campaign AGENCY-PREVIEW|Agency Team CLIENT-ACCESS|Client Preview The label after the pipe shows up in the access log, so you can see exactly which team accessed the site and when. Features Multiple invite codes with optional labels Session-based auth — enter once, stays valid for a configurable number of hours JSON access log with timestamp, IP, user agent, URL — last 50 entries shown right in the admin config panel Light / Dark / Auto theme switcher on the gate page (saved in localStorage, reacts to OS preference) Accent color setting — red, blue, green or black Configurable allowed pages that bypass the gate entirely CSRF protection, hash_equals() for timing-safe comparison, Cloudflare-aware IP detection The gate page uses ApfelGrotezk font and a design inspired by processwire main page itself — warm gray background, white card, mobile-first. Screenshots Installation cd site/modules git clone https://github.com/mxmsmnv/InviteAccess.git Then Modules → Refresh → Install → Configure. GitHub: https://github.com/mxmsmnv/InviteAccess Happy to hear any feedback or suggestions!1 point
-
Yes, that is the purpose of this variable: To add additional values to the validator. You can add several values as an array to the validator. To get a specific value from this array, you only have call it by its key (fe $params[2] will return the array value on the position with the key 2). You will find a lot of examples on how to write custom rules inside the CustomRules.php file. There you can study how to use the $params variable to test conditions with it.1 point
-
Hello @da² I have added a new method to trigger an error message to a field manually: setErrorMessageToField() Here is a small example on how to use it: $form = new \FrontendForms\Form('testform'); $form->setMaxAttempts(0); $form->setMaxTime(0); $form->setMinTime(0); $firstname = new \FrontendForms\InputText('firstname'); $firstname->setLabel('Firstname'); $firstname->setRule('required')->setCustomFieldName('The first name'); $form->add($firstname); $button = new \FrontendForms\Button('submit'); $button->setAttribute('value', 'Send'); $form->add($button); if ($form->isValid()) { $form->setErrorMessageToField($firstname, 'This is my custom message'); } echo $form->render(); If the "default validation" was successful, then the error message will be displayed under the "firstname" field in this case. You can use it to make another validations inside the isValid() function to check the submitted form values against other conditions. If the conditions fail then you can output this manually triggered error message like written above. To use the new method, you have to replace the file site\modules\FrontendForms\Formelements\Form.php with the one from Github or you simply add the new function to your Form.php. Please let me know if this helps.1 point
-
It is obvious that AI/LLMs/agents, etc..., should be used for development with frameworks the developer already has at least a basic understanding of, and the agent should not be allowed to generate code the developer cannot understand, otherwise the whole project will fail in the end. These are new tools, they are constantly changing, and we need to learn how to utilize them best. I am trying to find the optimal balance between tinkering, learning, and doing actual work. This has always been the case whenever I started using a new piece of software or system for the first time. There is no change in that regard.1 point
-
I try not to worry about things I cannot control, and AI falls squarely in that category for me. It's here, it's not going anywhere, and every senior person I know in tech is embracing it rather than fighting it. I use it daily now and it makes me more productive. That's the reality. The people protesting or boycotting it aren't going to slow it down, they're just going to fall behind. That said, I don't think caring about the environmental and societal side means you have to opt out. If anything, the opposite. People who use AI and care about how it's built and powered are the ones with any real influence over where it goes. I'd genuinely have no hesitation donating to make AI development better and more responsible, that feels like a more direct lever than abstaining. Ryan put it well: sitting out doesn't improve anything. Use it, push for better, and concentrate on what's within your own family four walls.1 point
-
Hey, welcome back @Soma! Great to see you here (again). So, I'm my self are away from PW since around 2022-08. I only followed a bit by reading some of Ryan's blog posts and @teppo's ProcessWire Weekly. Well, maybe this summer I'll be able to work more with PW again and participate here in the forum. 💬1 point
-
I have started to familiarize myself with the codebase and later on I will take a closer look at all the issues mentioned here and at GitHub. I am not planning to update nor fork the module in any way though, I am thinking of refactoring it completely, and in the end release it under a new name. The first version of this "new" module should be "compatible" with MarkupActivityLog, meaing it is going to rely on the very same database table in the very same manner. However, this first version should tackle the most important issues and it will be PW 3+ and PHP 7.1+ only. Also, being refactored, it is going to use more up-to-date PW features under the hood. In short, I will be working on a successor module to MarkupActivityLog. Note: there is no time-frame for this project at the moment ?1 point