Jump to content

Search the Community

Showing results for 'find'.

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Forums

  • Welcome to ProcessWire
    • News & Announcements
    • Showcase
    • Wishlist & Roadmap
  • Community Support
    • Getting Started
    • Tutorials
    • FAQs
    • General Support
    • API & Templates
    • Modules/Plugins
    • Themes and Profiles
    • Multi-Language Support
    • Security
    • Jobs
  • Off Topic
    • Pub
    • Dev Talk

Product Groups

  • Form Builder
  • ProFields
  • ProCache
  • ProMailer
  • Login Register Pro
  • ProDrafts
  • ListerPro
  • ProDevTools
  • Likes
  • Custom Development

Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


AIM


MSN


Website URL


ICQ


Yahoo


Jabber


Skype


Location


Interests

  1. We send everything through Amazon SES. You can limit it to specific regions, and you won’t find a cheaper way to send bulk emails. It’s $0.10 per 1,000 emails. And the deliverability is top-notch. And no fixed monthly fees — just pay as you go.
  2. Hi @adrian When uploading and inserting an image into a field (e.g., a TinyMCE "body" field) with this module active, any UTF-8 characters (like Greek letters) in other Textarea fields on the same page (e.g., a plain text "seo_description" field) are unexpectedly converted into HTML entities (e.g., "α" becomes "&alpha;" ) and saved to the database. I asked Gemini to provide a solution. Steps to Reproduce: Create a page with a TinyMCE field (body) and a standard Textarea field (seo_description). Enter UTF-8 characters (e.g., Greek text) into the "seo_description" field and save. Upload and insert an image into the "body" field. Save the page. Check the "seo_description" field or the database; the UTF-8 text has been converted to HTML entities. Root Cause Analysis: The issue stems from the "replaceRteLinks" method, which is triggered to update image URLs after a rename. Scope Logic: The method fetches all fields of type FieldtypeTextarea and FieldtypeTextareaLanguage and processes them using DOMDocument, regardless of whether the field actually contains the image URL. Encoding Handling: DOMDocument::saveHTML() natively converts extended characters into HTML entities. Because it processes unrelated fields, it permanently alters their raw text in the database. Proposed Solution: Updating the "replaceRteLinks" method to strictly check if the field contains the target URL before processing it, and utilizing ProcessWire's native sanitizer to restore entities converted by DOMDocument. Here is the patched method: private function replaceRteLinks($newFilename, $oldFilename) { $textareaFields = $this->wire('fields')->find("type=FieldtypeTextarea|FieldtypeTextareaLanguage"); $fieldsStr = $textareaFields->implode('|', 'name'); $oldRelativeUrl = str_replace($this->wire('config')->paths->root, '', $oldFilename); $oldRelativeUrlSansExt = str_replace(pathinfo($oldFilename, PATHINFO_EXTENSION), '', $oldRelativeUrl); foreach($this->wire('pages')->find("$fieldsStr%=$oldRelativeUrlSansExt, include=all") as $p) { foreach($textareaFields as $taf) { // FIX 1: Only parse the field if it actually contains the image URL. if($p->$taf != '' && strpos((string)$p->$taf, $oldRelativeUrlSansExt) !== false) { // FIX 2: Explicitly declare UTF-8 for the DOMDocument $pagedom = new DOMDocument('1.0', 'UTF-8'); libxml_use_internal_errors(true); // add <cun> as fake root element $pagedom->loadHTML('<?xml encoding="utf-8" ?><cun>' . $p->$taf . '</cun>', LIBXML_HTML_NODEFDTD | LIBXML_HTML_NOIMPLIED | LIBXML_SCHEMA_CREATE); $pagedom = $this->replaceRteLink($pagedom, $newFilename, $oldFilename, 'a', 'href'); $pagedom = $this->replaceRteLink($pagedom, $newFilename, $oldFilename, 'img', 'src'); // remove fake root element $html = str_replace(['<cun>', '</cun>', '<?xml encoding="utf-8" ?>'], '', $pagedom->saveHtml()); // FIX 3: Restore UTF-8 characters converted to entities by DOMDocument $html = $this->wire('sanitizer')->unentities($html); $p->of(false); $p->$taf = $html; libxml_clear_errors(); $p->save($taf); } } } }
  3. The client hosting company has a cap on emails per hour that is fine for now but we might exceed it eventually. Can anyone recommend a paid SMTP service that scales in tems of volume and works well with the stock ProcessWire SMTP module? I just want something that will plug and play but inputting the SMTP credentials rather than having to authorise an app, etc. I have used Mailgun before so that is an option and found the module in the PW directory works. I just find some SMTP services don't always work right away so I wondered if there are any you can recommend. The server is based in the UK so something that has a server nearby would be a bonus for lower latency. Thanks. 🙂
  4. Something I've adopted for my PW sites is putting environment-specific DB credentials and configuration in a separate file, /site/config.local.php: /** * Installer: Database Configuration * */ $config->dbHost = '127.0.0.1'; $config->dbName = 'db'; $config->dbUser = 'default'; $config->dbPass = 'default'; $config->dbPort = '3306'; /** * Installer: HTTP Hosts Whitelist * */ $config->httpHosts = array( 'my-local-domain.test'); And then including that file into /site/config.php: /*** INSTALLER CONFIG ********************************************************************/ // DB Config, Hosts Whitelist include dirname(__FILE__) . '/config.local.php'; I find this makes it easier to push changes when using version control (i.e. git) across different environments, and keep the credentials and other sensitive information excluded from the repo. On some managed hosts like Cloudways, you can pull and push DB changes from staging to/from production applications, as well as branch changes from git. Obviously this doesn't help when you make DB changes locally, though. Otherwise, I will either export/import the entire DB via the Database Backups module, or Pages Import/Export (under Admin > Modules, Core modules) depending on the kind of changes. After using Vercel and Netlify for static-based websites, it does make me wish there was a quicker way to push/pull DB changes, but perhaps that extra bit of friction is good so you don't inadvertently disrupt your production data. Definitely something I can improve in my own workflow! Managing local/remote image assets Occasionally I've added this code snippet to /site/ready.php, that allows for your local installation to pull down the asset from prod, which can save you some time. I'm also generally curious to know more about other folks' deployment strategies – could be a potentially useful thing to collect and make more visible in the PW docs, too.
  5. psy

    SeoMaestro

    Still using Seomaestro. Discovered a scenario where it missed pages in the sitemap that used urlsegments. In my case, it was the blog module authors page. It should also handle paginated pages but untested. Hope this helps. $wire->addHookAfter('SeoMaestro::sitemapItems', function(HookEvent $event) { $items = $event->return; $pages = wire('pages'); $users = wire('users'); $roles = wire('roles'); $config = wire('config'); $seen = []; foreach($items as $item) { if(!empty($item->loc)) { $seen[rtrim($item->loc, '/')] = true; } } $getSeoSettings = function(Page $page) { foreach($page->template->fieldgroup as $field) { if(!$field->type instanceof FieldtypeSeoMaestro) { continue; } $seo = $page->get($field->name); if(!$seo || !$seo->sitemap->include) { return null; } return [ 'priority' => $seo->sitemap->priority, 'changefreq' => $seo->sitemap->changeFrequency, ]; } return null; }; $appendItem = function($url, $lastmod, array $settings) use (&$items, &$seen) { $key = rtrim($url, '/'); if(isset($seen[$key])) { return; } $item = new \SeoMaestro\SitemapItem(); $item->set('loc', $url); $item->set('lastmod', date('c', (int) $lastmod)); $item->set('priority', $settings['priority']); $item->set('changefreq', $settings['changefreq']); $items[] = $item; $seen[$key] = true; }; $appendPaginatedItems = function(Page $page, $totalItems, $perPage, $lastmod) use ($config, $getSeoSettings, $appendItem) { $settings = $getSeoSettings($page); if(!$settings) { return; } $totalPages = (int) ceil($totalItems / $perPage); if($totalPages < 2) { return; } for($pageNum = 2; $pageNum <= $totalPages; $pageNum++) { $appendItem( $page->httpUrl . $config->pageNumUrlPrefix . $pageNum . '/', $lastmod ?: $page->modified, $settings ); } }; $blogPostsPage = $pages->get('template=blog-posts'); if($blogPostsPage->id) { $latestPost = $pages->get("template=blog-post, sort=-modified"); $appendPaginatedItems( $blogPostsPage, $pages->count("template=blog-post"), 8, $latestPost->id ? $latestPost->modified : $blogPostsPage->modified ); } foreach($pages->find('template=blog-category, include=hidden') as $categoryPage) { $latestPost = $pages->get("template=blog-post, blog_categories=$categoryPage, sort=-modified"); $appendPaginatedItems( $categoryPage, $pages->count("template=blog-post, blog_categories=$categoryPage"), 10, $latestPost->id ? $latestPost->modified : $categoryPage->modified ); } $authorsPage = $pages->get('template=blog-authors'); $authorSettings = $authorsPage->id ? $getSeoSettings($authorsPage) : null; if($authorsPage->id && $authorSettings) { $authorRole = $roles->get('blog-author'); foreach($users->find("roles=$authorRole, sort=title") as $author) { $authorSlug = wire('sanitizer')->pageName($author->title); if(!$authorSlug) { continue; } $postCount = $pages->count("template=blog-post, created_users_id=$author"); if(!$postCount) { continue; } $authorUrl = $authorsPage->httpUrl . $authorSlug . '/'; $latestPost = $pages->get("template=blog-post, created_users_id=$author, sort=-modified"); $lastmod = $latestPost->id ? $latestPost->modified : ($author->modified ?: $authorsPage->modified); $appendItem($authorUrl, $lastmod, $authorSettings); $totalPages = (int) ceil($postCount / 10); if($totalPages < 2) { continue; } for($pageNum = 2; $pageNum <= $totalPages; $pageNum++) { $appendItem( $authorUrl . $config->pageNumUrlPrefix . $pageNum . '/', $lastmod, $authorSettings ); } } } $event->return = $items; });
  6. On a side note, because of the ProcessWire 'way' of handling images, it helps to think about the purpose of the images your page will have. As teppo flagged. So I usually have 1 x carousel images or a hero image field 1 x general images field i might display in the content 1 x something else The reason for doing this is that you can keep all your images and image field settings appropriate for the image purpose etc. Especially if you have clients adding or removing images. I find having just one image field can be an issue if they accidentally remove something or add an image which should not be part of the hero banner etc. Later on you might want to also look at tagging images and calling them onto your front-end pages https://processwire.com/modules/textformatter-image-tags/ But I'd recommend getting used to the basics first. An example of how I use image tagging might be. I have a product field with a lot of general images one of them in particular is used as a preview thumb on a product overview page so i'll tag that image 'preview' or whatever you want really. Lets us know how it goes
  7. I am about to put my first ProcessWire-powered website onto a live server, and I was searching the website and forum on how to do this. Maybe I used the wrong search-terms, but I did not find anything on how this should be done. I can obviously just throw all the files on the server through FTP, and put the database in place using PhpMyAdmin. Then change the DB-credentials in config.php and I think it should work, but I don't know what the recommended way is to push a website from your local/dev-environment to a live webserver.
  8. I recommend not subscribing to a Plaid plan at kimi.com. I wanted to cancel my subscription, but there was no such option, so I had to delete the account, as that was the only option I could find. I wrote to support, but they never replied. I removed my saved credit card on Stripe's interface, but I still receive a message every other day: "...payment to MOONSHOT AI PTE. LTD. was unsuccessful We attempted to charge your card for your MOONSHOT AI PTE. LTD. subscription again, but were unsuccessful. Please update your billing information to continue your subscription." For a theoretically deleted account...
  9. There may be a time where you need to create a page reference field using the Select inputfield and it's selecting repeater pages. Let's say I have a repeater field called "order_line_items" and I want to create a page reference field called "order_line_item" that allows me to select a repeater item (which is a page) of the "order_line_items" repeater field. Repeater pages are a bit different from regular pages in that their "parent" is a container admin page associated with the page in which it exists (dig into /admin/repeaters/order_line_items/ in your page tree to see what I mean). So when you are configuring your page reference field, you can't really choose a Parent. However when configuring your field, your instinct would be to choose the Template of "repeater_order_line_items". Then because you need extra precision in what pages are actually available for selection (rather than all of them across all pages), your instinct will be to implement custom PHP code: $wire->addHookAfter('InputfieldPage::getSelectablePages', function($event) { if($event->object->hasField == 'order_line_item') { $event->return = $event->pages->find('your selector here'); } }); The problem with that approach is that even though you have defined the custom PHP code and the select field correctly shows the selectable repeater pages in the select field, behind-the-scenes, ProcessWire has still loaded EVERY SINGLE REPEATER that has the "repeater_order_line_items" template (you can see this is TracyDebugger's pages loaded list)! Your site will definitely be slower as a result, dramatically so if you have thousands or tens of thousands of repeater pages of that template. I hit this issue years ago (2018) and I thought it was a bug. I discussed it with Ryan and it's technically not a bug, but kind of the way ProcessWire works, which is beyond this tutorial. While you can circumvent this using the PageAutocomplete field, I don't like the ergonomics of that field in certain situations. I want the good-old select field. The solution to this is to NOT select anything for the "Template" when configuring your field. So in my example, I chose "repeater_order_line_items", but instead, it should be left blank. Now the field will just rely on the code portion and all the unnecessary page loads will be eliminated.
  10. The toughest challenge so far? Being our own client. Actually, the website we launched back then was just a placeholder, and the plan was to quickly replace it with a proper portfolio website. But as is often the case, it ended up taking a little longer than expected. A year later, we’ve finally done it: Our new website is live! https://konkat.studio/ The goal of the new website is to showcase our work and better communicate our services. The site is bilingual and was built using ProcessWire and PageGrid. More on that later. In addition to the website, we’ve also evolved our visual identity and logo. KONKAT (from concatenation) stands for linking individual elements into a functional whole. Our new branding makes this connection visible. In our case, we combine strategy, design, and technology into a unified process. The logo mark communicates this as well; as most of you probably know, the += operator in JavaScript joins elements and assigns the result. It took us some iterations to get the design right, but once the design was done, development was pretty straightforward. Most of the time was spent preparing the content for the projects, and that is also where PageGrid was super useful since it allowed us to design the layout and content of each project individually. Backend view: Managing project content and layouts with PageGrid. PageGrid also significantly sped up development, as we built all other pages using only its core blocks. For the projects overview, for instance, we used the datalist block to automatically generate the listing from our project pages, working perfectly out of the box without any custom logic. We also added some custom code where it made sense, e.g. the scroll animation on the homepage was just a bit easier to achieve with custom code (it uses native CSS sticky). Backend view: Using Pagegrid's inline editing to update some text on the english version auf our services page. Another great thing is that PageGrid takes care of lazy loading images and videos (using the famous lazysizes js plugin) and is caching its content automatically. As a result, we got a 100 on the Google Lighthouse test on desktop and 99 on mobile without any extra optimizations (we are not using Markup Cache or ProCache for this site). Backend view: Editing a thumbnail on the homepage If you have any further questions regarding our workflow or process, feel free to ask. I will do my best to answer them. Also, please let us know if you find any bugs, since the website is brand new, there are probably some we haven't caught yet! We also welcome any feedback you may have. Best, Jan & Diogo (KONKAT)
  11. Think I got it working, but not sure which of these steps were needed. Posting in case others find it helpful. I uncommented RewriteBase / in .htaccess I truncated the cache in the database with Phpadmin6 (I'd avoid this one if the others work first!) Using Tracy Debugger > Clear sessions, cookies & module refresh. A normal browser cache clear didn't work for me.
  12. Maybe I'm not doing it right.... $this->addHookAfter('LazyCron::every5Minutes', function(HookEvent $event) { PageRender::renderPage(bfd_mailer_cron.php); echo "mailer sent"; }; On the other hand, I'm trying with an OVH cron job. As soon as I enter this on the mailer page $features = $pages->find('parent=/events/|/the-eyes/, bfd_day.name=$todayday, bfd_month.name=$todaymonth'); the job doesn't work. I presume it doesn't understand the ProcessWire api.... And then I'm not sure if this is the right way to do what I actually want, sending a ProcessWire page once a day at 10am to one or several email adresses. It used to work with a OVH cron job for years but I guess there's been a few changes between PHP 5 and 8.2 that are in the way.
  13. Hello @grewr11 Thanks for pointing out this issue. I have removed the sanitizer for names on the "Name" field, because usernames are allowed to have numbers in it. This was a thinking mistake. Now it should work as expected. Please replace the following file to get it working: https://github.com/juergenweb/FrontendComments/blob/main/FrontendCommentForm.php I have discovered another issue, with WireMail and localhost, so please replace the following file too: https://github.com/juergenweb/FrontendComments/blob/main/Notifications.php You will find all information about the changes in the changelog.md. I haven't worked on this module in a long time, so there could be more problems. Please report any problems, I will try to solve them as soon as possible. Jürgen
  14. Hello, we've been working on a module to convert Microsoft Protected Links (Safe Links) so they display as their original URL. Protected links leak the email address of the person who copied the link into the page (eg. https://aus01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.antarctica.gov.au&data=05|02|EMAILADDRESS%40example.com...) This is not ideal, and we find more and more protected links turning up now that most of the Microsoft product offerings use protected links (Teams, Office, Copilot etc.) TextFormatter modules typically only reformat the text on output, leaving the page content containing the protected link. Is it acceptable for a Text Formatter module to save the formatted string back to the page? Maybe as an optional configuration in the module settings? Or, is it better to achieve this using a standard module?
  15. Hi, I am trying to collect the page titles of a parent and its children, but this code won;t work: <?php // collect titles for parent + children $titles = [$page->title]; // parent title foreach($page->children as $child) { $titles[] = $child->title; // child titles } // build a selector value like: title="A|B|C" $titleSelector = implode('|', array_unique($titles)); // now find all Championship_results whose winner_name page // has a title matching ANY of those titles, sorted by year descending $champwinx = $pages->find( "template=Championship_results, winner_name.title=$titleSelector, sort=-year" ); ?> It produces this error: any suggestions re a fix appreciated Error: Exception: Unknown Selector operator: '[empty]' -- was your selector value properly escaped? field='G', value='Miss|Temple-Dobell', selector: 'template=Championship_results, winner_name.title=Ravenscroft, G (Miss)|Temple-Dobell, G (Mrs), sort=-year' (in wire/core/Selectors.php line 222)
  16. Ah! My bad I misread your first post. I don't think I have a local setup with a non-namespaced TracyDebugger but if I do find one, I'll try to update and let you know if anything goes wrong.
  17. @mattgs Like Adrian, I also consider myself very environmentally conscious. I've not spent much time learning AI in part because I thought it was problematic for a lot of reasons. But I don't think we're likely to stop these AI companies so that's why I thought I should try things out with a company that seems to have more ethics than the others. Anthropic seems to have a mission for AI safety and sustainability. I hope it's legit. And as far as I can tell, the other companies don't, which I find concerning. But I'm also not as up-to-speed as you are on the on the issues you brought up, so I'll have to look closer as well as check out the video you mentioned (do you have a link?). I'm also aware that a project like ProcessWire gets executed millions upon millions of times every month (or day?) throughout the world, and every execution consumes energy. So I've always been very interested in optimization and making ProcessWire use as little time and energy as possible to do its work. The updates that we've been focusing on here are aimed directly at that. So perhaps AI is using a little energy to find optimizations and bugs in PW, but that single brief code review session reduces the energy usage of every ProcessWire execution going forward. This is a case where AI is likely saving a lot more energy than it consumes, indirectly by making ProcessWire use less energy. Some of the optimizations and bugs its found have been there since the beginning, and likely would have never been identified otherwise.
  18. Ok done. MCP Module now support local->remote publishing. I guess there's not a big demand for this, but I find it really useful.
  19. @teppo Thanks, good to hear the more I use it, the more I'll be blown away. I've been using AI ever since ChatGTP first came out, but primarily just for technical questions and such. For instance, a couple months ago Claude helped me figure out how to reduce static pressure in our HVAC system by rebuilding (DIY) the return plenum and filter rack, and it was super helpful. I posed the same questions to GPT and Gemini but they weren't nearly as helpful. This week is the first that I've gotten into collaboration with the actual code. Adrian showed me all the things Claude Code had recommended for the PageFinder, and I found myself really liking what it had found and suggested... Seemed like we were on the same page, just like with the HVAC work. The other thing is that I've found it a little overwhelming with all these models (GPT, Grok, Gemini, Claude, etc.) with big changes almost weekly, and if these companies were ethical and ones I'd even want to be putting money towards. Then I learned about why they created Anthropic in the first place, and last week heard how they were sticking to their ethics and wouldn't cross their red lines despite government pressure. Sounds like integrity to me, something that is hard to find with big companies. That opened my comfort level and clarified for me that Anthropic's Claude Code was a good place to dive deeper with this stuff.
  20. The more you use it, the more you’ll be blown away. At least that’s how it has gone for me and most devs I know. Since Opus 4.x, Claude has completely transformed my workflow 🙂 I enjoy “manual” coding too, but AI coding has plus sides. Going from rough idea to usable feature is blazing fast, testing and prototyping has been so much fun, and AI tends to find issue (and opportunities!) humans would never spot. Also with Claude taking some of the load off my shoulders I often find myself working on multiple things at the same time… though I guess not everyone will see that as a good thing 🫣 Oh, and docs and tests! Claude is great for that stuff. It needs human guidance for both, though, as it tends to get confused about what actually matters. AI docs are often easy to spot: many words, little (or no) meaning. Admittedly sometimes this way of doing things tends to feel less like coding and more like managing a team of skilful but a little naive devs that often need help with ideation, architecture, testing, and just plain common sense 😅
  21. This week on the dev branch we've got several commits with various core improvements and fixes. @adrian has been using Claude Code to suggest core optimizations (focused mostly on the PageFinder) and so he sent the suggestions to me. (PageFinder is the brains behind the $pages->find() method, and many others). I took the suggestions and coded them into our PageFinder, but didn't want to mess with what was already working well, so put them in a new class named PageFinder2, at least temporarily. If running the latest dev branch, you can enable PageFinder2 by adding the following to your /site/config.php: $config->PageFinder('version', 2); The most significant changes are: using subqueries for subselectors rather than separate independent queries; Reusing PageFinder instances (keeping a pool of typically 1-3 PageFinders rather than creating a new one for each $pages->find() operation); and lots of in_array() calls have been converted to isset() lookups, which should technically be faster (still the case in PHP8?, I'm not sure). There were some other changes as well. Theoretically these changes should make PageFinder even faster than it already is. I did quite a bit of testing and found that for the most part it performs the same as PageFinder v1. But then I came across a rather complex selector that translated to a much faster PageFinder operation, nearly twice as fast, and that convinced me it was worthwhile. While PageFinder v2 is not consistently faster than v1, there are some situations where it can be a lot faster. I'm not totally clear on what those situations are just yet, but I'll be doing more testing. In other situations it also can use a lot fewer queries, though that doesn't necessarily translate to a performance difference. But on the whole, all of Claude's suggestions were quite good, regardless of performance improvements. I was pretty impressed with what Claude Code had suggested, so decided to install it on my computer too. I've found it's particularly good at finding bugs. I'll ask it to do a code review on a core file, and it always has good suggestions. It uses ProcessWire terminology too. For instance it pointed me to an object that wasn't properly "wired to the ProcessWire instance", and that's something you'd only ever hear in ProcessWire land. Claude code also helped with improvements to our DatabaseQuery* classes, PagesVersions module, Wire base class, NullPage class, and minor updates to the PagesLoader* classes. I'm not having it write any code just yet, but am having it suggest where improvements can be made. I like to code. I asked it how it knew so much about ProcessWire, and it said that it stays up-to-date with the forums, the website, API docs, and GitHub repo. Thanks to @adrian and @Jan V. for recommending it to me (Jan V. uses it to manage this webserver), I can see how it's going to be a big help to ProcessWire with its suggestions and ideas, I'm already learning a lot from it. And if you get a chance to try the updated PageFinder, please let me know how it works for you. Thanks for reading and have a great weekend!
  22. Thanks for the links @AndZyk! I'll have to read through them to see if this does what I want. I was able to change the actual classes that are applied by the dropdown, but then it obviously did not show up in the editor, so that is the part I'm hoping to find an answer for.
  23. That's a great find @gmclelland - I never use markup regions so wouldn't have noticed this at all. Ever. I compared the new details with the existing skill, this was the result: I guess we should add it. Right?
  24. It's not about adding every new learning into a new skill. It's about updating existing skills with new learnings. For example: in case a modules skill always returns an error when creating backend pages, that skills needs an update and I feed the learnings back into that skill. Yes, but I honestly don't like to have too much external requirements in my projects. I'd like to test Context+ (https://contextplus.vercel.app/) yet the overall setup is way too much hassle. For super big projects maybe, but for all those smaller to medium sized projects that's way off my comfort zone. I tried Gastown, SpecKit, OpenSpecs, Beads, BMAD ... whatever else there was. They always came with some kind of setup and bloat. Taking a day or two off meant I couldn't even remember I installed and used that tool in my projects or forgot to start a new task in a certain way. Skills are always there. They live in my OpenCode config folder now. They are portable, too. Way easier and no headaches. At least for me. Of Course everyone else has their own prefered way of doing things and may have the capactity to remember each tool and setup for each project. I don't. 😂 Way too many things. Way too little hours per day for that. 🙈 I try to solve the knowledge gap that most LLMs have in regards to ProcessWire. There isn't that much of training data for ProcessWire as there is for NextJS, React, Symphony, Laravel, and of course Java and C++. LLMs know the basics or "invent" new ways of doing core things, like URL hooks. PHP itself was never a real problem - just to make this clear. I found that skills are a great way to solve this - for me. I can use way cheaper models, like Kimi K2.5 or Minimax M2.5, with way better outcome using skills. Sure I could just burn through my $200+ Claude Code/Cursor plan but babysitting that agent to fix issues it isn't even aware off while it would repeat those same mistakes over and over again with a smile the next time - I was tired of that. That's why I played a lot with the JS-tools out there. Paying less money and investing less time for a way better outcome. I could run 10 agents in parallel that check each others work and fix issues, report back and forth, and could then somewhat get what I was looking for but it never felt right and looking at the code often even scared me. My skills contain about 80-90% of ProcessWire knowledge. Not perfect in every aspect, maybe sometimes even outdated examples or older PHP code (<8.x) but the results turn out to be great. For me at least it is: SKILLS, plus AGENTS.md thats referencing those skills, concepts/specs/PRDs For now. Maybe next week there is another concept that lives locally without any big setup in a folder that does everything I want and need. I don't know. What's your (daily) workflow? What's ruining your day to day work? What annoys you when working on something? My benefit is: I don't need $200 Claude/Cursor plans to get something done. I don't need Opus/Sonnet 4.6, Codex 5.3-x-whatever-they-named-it. I get MVPs up and running in ProcessWire like it was a NextJS/React project. Look into the ProcessWire skills here and you will notice that it's actually just the documentation - which is missing or is incomplete in so many LLMs. Sometimes with additional details, other code examples, or sometimes it's a missing part of the docs like for URL Hooks - as they actually only exist as a blog post right now - yet I can use them now without issues. That's what I tried to fix and for the moment this fixes it. Is that the best way to go? I don't think so. But I am lazy and tired. And this works. For me. I don't want to learn yet another tool or framework to get things done. Just to learn another framework and tool tomorrow and next week. I don't need 10-20 agents per project to run 24/7. I'm not trying to rebuild SAP/Sage or Asana/Trello/Jira. But let's find out how my (lazy) approach might help you or give you ideas.
  25. I can guarantee from experience all these work together fine. This could be another logic for your what you are trying to achieve, although I don't see anything wrong in your snippet! Just figuring out that if you are getting started you might find these examples useful: // assuming section is the name of the repeater $projects = $pages->find("template=project, section.images.tags=gallery"); foreach ($projects as $project) { $title = $project->project_header->first()->project_title; // Maybe something like this to get images from any of the repeaters? $images = new WireArray(); $project->section->each(function($images) use(&$images){ $images->import($item->images->findTag("gallery")); }; foreach ($images as $img) { echo "<a href='{$project->url}' title='{$title}'>"; echo $img->render(); echo "</a>"; } }
×
×
  • Create New...