Leaderboard
Popular Content
Showing content with the highest reputation on 03/25/2025 in all areas
-
Hey everyone! Finally I have time to post a detailed developer walkthrough for PAGEGRID. I have the feeling that many people don't know how flexible PAGEGRID actually is as a developer tool. I think this is mainly due to the fact that most videos are showing the no-code features of PAGEGRID. But since these features are completely optional and PAGEGRID has a lot more to offer, I've put together a video walkthrough to show you exactly what I mean. My hope is that it'll give you a clearer picture of how PAGEGRID can fit into your projects and help you decide if it's the right tool for you. Please take a look at the video below! I think you'll be surprised at what PAGEGRID can do. PAGEGRID's core concepts (video summary): Your markup: Unlike many other site builders PAGEGRID gives you complete control over the markup and structure of your frontend. You can use PAGEGRID to build specific sections or parts of your custom coded website or you can use it as a full-blown site Builder that can work without any coding. Everything is a page: PAGEGRID items are ProcessWire pages that are defined through native ProcessWire templates and fields. Control what clients can edit: PAGEGRID offers an intuitive editor experience that's easy to learn for clients. Editing and design features can be controlled through ProcessWire’s native roles and permission system. Your CSS: You can use your code editor to write CSS or you can bring your own CSS framework. PAGEGRID makes no assumptions about your CSS code. And it’s not just for Grids, display properties like Flexbox, Block or Inline-Block are also supported. Nesting: A powerful feature of PAGEGRID is nesting and while this feature is completely optional it's quite useful for a lot of cases. You can define a block as a container and can define what kind of templates are accepted for the children. This can be used for layout purposes or to group items together, another example might be a slider or gallery block that the user can add items to or basically any repeatable content that you might want to put inside a block. Developer walkthrough: Developer Documentation: https://page-grid.com/docs/#/developer/ How to create a custom block: Documentation for creating blocks: https://page-grid.com/docs/#/developer/blocks Try PAGEGRID for free PAGEGRID is not free. However, you can try PAGEGRID on your local machine or on a test server as long as you need to make sure it is the right tool for your next project. … and when you’re convinced, buy your license. Installation PAGEGRID (FieldtypePageGrid) is listed in the modules directory, you can install it like any other module. See the install guide for more information. Recent Updates (2025) Performance improvements (markup cache integration) (march) Quick add feature (february) Symbols and Patterns (january)2 points
-
@bernhard That was very helpful, thank you for taking the time to explain more. I definitely don't want to replicate past ideas or force RC into trying to be something it isn't! This is an interesting idea. I'm understanding your approach better now and I think that my concept was too focused on having the RockDateRangePicker field do "too much". I'll share a little more about what I got wrong when using RC. When I opened the original event and saw the RDRP field it was confusing since it automatically shows the date and "Recurring" is checked, to indicate that this is a recurring event, but the contents of the RDRP field do not match the schedule/recurrence that the event was created with. If I uncheck "Recurring" and save the event page, nothing is changed with the other events, so I was confused on what the purpose of the Recurring button, schedule, list of dates, etc. was for. Even though you labeled it "Create Additional Events", I was focused on the UI since it presents things to interact with. The other part where I stumbled was the "This event is part of a recurring series" message. It made me think that clicking on "Click here to edit the main event" had something to do with the recurrences since it showed the other buttons below the date field. Since this occurrence isn't the "main" event, would it be a good idea to remove the "Recurring" and "Range" buttons and only allow for setting/editing the time? I used Thunderbird for my email/calendar client and took a look at how the UI works. I had never thought about it before and it's also more simple than the suggestion I was making, and might be more inline with RC's approach. I made a quick video and if managing recurrences could be something like this it would work really well. The Thunderbird UI, date selection, calendar style, etc. can all be ignored of course. Here are the steps I took: Create an event that occurs every Tuesday Edit the event and change it so that it occurs every Wednesday Move one of the occurrences in the series to Thursday Edit the event to change it back so it occurs every Monday calendar_events.mp4 What is interesting is that moving the one occurrence to Thursday "detached" it from the schedule. It is still a part of the main event, but the date is no longer managed by the recurrence rule. So I was able to change back from every Wednesday to every Monday and that individual occurrence was not changed. Any further edits to the schedule, like changing it to Monday of every other week, would also not affect the occurrence I moved to Thursday. Maybe the "generator" UI only appears when you create the event and then afterwards it only lets you edit the recurrence rule without displaying or managing any of the individual pages. Thunderbird does not have any "central" manager for all events the way that Recurme did or in the way that I was suggesting. It only allows you to adjust the schedule and doesn't let the user get involved any deeper than that when dealing with the schedule. Like RC, the calendar UI is used to manage individual occurrences. Interested in your thoughts. This is different than what I was originally thinking and perhaps this style is more compatible with RC's approach. RC has the great approach by using pages as the way to store and retrieve data since it doesn't "fight" the ProcessWire style. I definitely don't want to stray from the formula 😎1 point
-
They will be ready soon. Update/additional details to make things clear: While I was pretty happy with the first iteration of my ProcessWire rules (from Grok and others) they seemed to be too large in total for Cursor and Windsurf to handle them each time. Right now I'm splitting that one rule file into smaller chunks so that whenever a PW-specific topic comes up, the IDE can find a single file with details (or I mention that file to make sure). Especially in regards to modules, which is a larger topic, or URL hooks which is only a blog post and therefore was probably never in any training data (I'm assuming here, as ChatGPT and Sonnet all imagined their own version of that that could have been). For those wondering: I always added snippets/recipes/examples to each section to make sure the IDE uses the code I want to see as a result later on. Sure, with placeholders and relying most of the time on basic PHP code, yet PW is a different animal. Neither Cursor, nor Windsurf are really keen about what's going on. The sample/training data was probably way too little at all. Hallucinations were way too common and ... you could imagine. How I found these issues: I have two larger and more complex projects on the desk right now and it didn't work out as expected and I had write most of the code by myself on a basic level with inline docs and @TODO comments, and just asked the IDE/AI to make it follow PHP's best practices - such as error handling (which didn't work most of the time, as PW has it's own way - kind of). So...: While I'm still super happy with the outline of rules created by Grok3, the IDE/AI needed and needs more input and details about PW most of the time. It helps to have snippets, like RockMigrations by @bernhard provides - which was still off for quite some times but were easy to fix manually.1 point
-
Did this thread cursed me? (jk) Monday first hour and I have a site that's going through very odd gateway timeouts 🤣 EDIT: Indeed, server load! PHP hits hard, always have a cache layer! 😄1 point
-
I'm a bit short in time right now so I might have to write a follow-up to give you a real and more complete answer here. But in the meantime - a short summary: each and every client/side project of mine get's a click-dummy of the final product to see how it could work out, what's needed and so on. I use Astro JS for that as it's super flexible to work with, I can deploy it somewhere at Netlify, Vercel, or Cloudflare. Each commit is a new build. I can share it with everyone - frontend and backend-wise. It's more or less just HTML, CSS, JS - some parts of it might have a TailwindCSS or AlpineJS flavor but still super basic. And the big plus: ALL build steps (TailwindCSS, AlpineJS, ...) are already in place. If needed I can connect it to an API to fetch articles, news, or whatever kind of data to make it look more real or to go super fast - especially when migrating from WordPress where there is a RestAPI or GraphQL almost always in place already. For sideprojects I connect to api.domain.tld, grab JSON and render out either pages or just parts of the project on-build. for side projects in very early stages that would be the state for the next 3 to 6 months to see if the project get's some kind of traffic - for client projects this is the base to start the real work. from there I take all the component and move them from .astro to .twig - the difference is so minimal I could use Regex to make the changes most of the time. feeding all layouts, components, partials, blocks, however we want to call those code snippets into ProcessWire is pretty easy, when you know where things have to go and most of the time you only change the parts that define the source - so from a JS fetch() to a $pages->find('...') - and of course you have to build out the ProcessWire backend stuff, hooks, automation, and whatever you need or want. Some would say there are a lot of unnecessary steps in this process and they could be right, but I prefer to test projects early on and hate to look at Figma files or Illustrator screenshots. So there is that. I always worked that way and that will probably never change. On the technical site you have think about 2 systems running side by side. Astro JS on Netlify, Vercel, Cloudflare or a VPS with NodeJS and ... lots of other stuff ProcessWire with database and everything it needs on a sub-domain. You could fit everything onto one server but it can be quite painful to get this up and running so I use a regular hosting provider for ProcessWire and one of those mentioned above for Astro JS. The output is, most of the time, 100% static and build on-demand with data and content available at that moment. You could make it more dynamic with AlpineJS or HTMX but only for small parts, and not for articles and news - as those wouldn't exist within the static build. As this turned out to be broader as expected please feel free to ask about more details where needed.1 point
-
Put those posts here in the Dev Talk in their own topical threads. I personally love those posts and looks behind the scenes. So... a +1 from me here.1 point
-
Thanks @markus-th and @wbmnfktr. You've given me good feedback to consider. I had an issue today with the headless WordPress site I referenced above that has me thinking about this differently. In short, the WPGraphQL plugin broke from an update and I decided to try converting what I had over to REST with Claude AI. In addition to a lengthy prompt I fed it JSON of all of the custom fields and GraphQL queries I was using on the site. That worked really well and only required minor fixes to completely rebuild what I already had. ProcessWire has great documentation, has been around for a long time, and can export templates and fields in JSON format. I just need structured data of each page, nothing wild. I'm going to see how well the machine can generate what I need and if it seems repeatable. If anyone cares I can post how it goes. If you're tired of the "LoOk aT WhAt i MaDe wItH Ai mOm!" posts, then I'll keep it to myself 😉1 point
-
Like last week, I’m still working on all the same things: PW site, client stuff here and there, and even the HVAC stuff. They replaced our heating/air systems on Wednesday, but not everything is working quite as it should, but that’s another story that's still ongoing. A couple weeks ago folks were asking about CSS variables/properties for the new AdminThemeUikit look. I’m not that familiar with that part of CSS yet, but luckily the people coming up with this design are. And it turns out they are indeed using CSS variables/properties for this. I think this means you’ll be able to override them with your own colors, perhaps in the AdminThemeUikit module settings, or with a CSS file, I’m not yet sure, but will find out more in the next week. I’ve seen a few different color schemes specified using it, and they are really nice. Thanks for reading and enjoy the weekend!1 point
-
Ever felt like your ProcessWire emails look like they're stuck in 1999? You know the drill - sending emails is super easy with WireMail: $m = new WireMail(); $m->from('foo@bar.com'); $m->to('xxx@yyy.com'); $m->subject('Hello there!'); $m->bodyHTML('<h1>This is great!</h1><p>I am an ugly mail...</p>'); $m->send(); But let's be honest - they look about as pretty as a website built with Microsoft FrontPage! 😅 🪄 Enter the Mail Pimp Hook! Drop this magical hook into your /site/ready.php (or even better Site.module.php), and watch your emails transform from ugly ducklings into beautiful swans: <?php $wire->addHookBefore('WireMail::send', function(HookEvent $event) { // double check that we got a wiremail instance // this also tells the IDE what $mail is (to get IntelliSense) $mail = $event->object; if (!$mail instanceof WireMail) return; // get current mail body $html = $mail->get('bodyHTML'); if (!$html) return; // get email layout markup $layoutFile = wire()->config->paths->templates . 'mails/default.html'; if (!is_file($layoutFile)) return; // replace ##content## with actual mail content $html = str_replace( '##content##', $html, wire()->files->render($layoutFile) ); // write new body to mail $mail->bodyHTML($html); }); The HTML Just create a beautiful MJML template at /site/templates/mails/default.mjml, put ##content## where your email content should go, convert it to HTML and BOOM! 💥 Every email gets automatically wrapped in your gorgeous template. No more CSS wrestling matches, no more "Why does this look different in Outlook?" headaches. Just pure email beauty, automagically! ✨ Now your clients will think you spent days crafting those emails, when in reality, you're sipping coffee while your hook does all the heavy lifting. Work smarter, not harder! 🚀 #ProcessWire #EmailMagic #NoMoreUglyEmails PS: This is the MJML template that I used: <mjml> <mj-head> <mj-attributes> <mj-all font-family="Tahoma" /> <mj-text line-height="140%" /> </mj-attributes> </mj-head> <mj-body background-color="#efefef"> <mj-section background-color="#ffffff" background-repeat="repeat" padding-bottom="30px" padding-top="30px" text-align="center" > <mj-column> <mj-image align="center" padding="25px" src="xxx" target="_blank" width="200px" alt="Logo" ></mj-image> <mj-text>##content##</mj-text> </mj-column> </mj-section> <mj-section> <mj-column> <mj-text font-size="10px" color="#a0a0a0" align="center" > powered by <a href="https://www.baumrock.com/" style="color: #158f66" >baumrock.com</a > </mj-text> </mj-column> </mj-section> </mj-body> </mjml> VSCode has an extension to get a live preview and export MJML to HTML: And here are some other free templates: https://mjml.io/templates I use https://www.base64-image.de/ to add the logo to my mail template as src="data:image/jpeg;base64,/9j/4QAWRXhpZgAATU0AKgAAAA..." to avoid headaches with image paths, remote assets blocking etc.1 point
-
Nice. Just wanted to mention Cerberus as an alternative to MJML if you want to use email-friendly HTML templates directly.1 point
-
Verify Links Periodically verifies that external links are working and not leading to an error page. Requires the following core modules to be installed: PagePaths LazyCron How it works The module identifies links on a page when the page is saved and stores the URLs in a database table. For the purposes of this module a "link" is an external URL in any of the following... FieldtypeURL fields, and fields whose Fieldtype extends it (e.g. ProFields Verified URL) URL columns in a ProFields Table field URL subfields in a ProFields Combo field URL subfields in a ProFields Multiplier field ...and external href attributes from <a> tags in any of the following... Textarea fields where the "Content Type" is "Markup/HTML" (e.g. CKEditor and TinyMCE fields) CKEditor and TinyMCE columns in a ProFields Table field CKEditor and TinyMCE subfields in a ProFields Combo field The link URLs stored in the database table are then checked in batches via LazyCron and the response code for each URL is recorded. Configuration On the main module config screen you can define settings that determine the link verification rate. You can choose the frequency that the LazyCron task will execute and the number of links that are verified with each LazyCron execution. The description line in this section informs you approximately how often all links in the site will be verified based on the number of links currently detected and the settings you have chosen. The module verifies links using curl_multi_exec which is pretty fast in most cases so if your site has a lot of links you can experiment with increasing the number of links to verify during each LazyCron execution. You can also set the timeout for each link verification and customise the list of user agents if needed. In the Process module config there's a field allowing you to exclude URLs that start with a given string. This only applies to the "Error responses only" listing, and can be useful to avoid seeing false-positive error statuses for domains that you know provide inaccurate responses (more about this below). Usage Visit Setup > Verify Links to view a paginated table showing the status of the links that have been identified in your site. The table rows are colour-coded according to the response code: Potentially problematic response = red background Redirect response = orange background OK response = green background Link has not yet been checked = white background Where you see a 403 response code it's recommended to manually verify the link by clicking the URL to see if the page loads or not before treating it as a broken link. That's because some servers have anti-scraping firewalls that issue a 403 Forbidden response to requests from IP ranges that correspond to datacentres rather than to individual ISP customers and this will cause a "false positive" as a broken link. For each link the "Page" column contains a link to edit the page and the "View" column contains a link to view the page on the front-end. You can use the "Column visibility" dropdown to include a "Redirect" column in the table, which shows the redirect URL where this is available. You can use the "Custom Search Builder" to filter the table by particular column values, e.g. for a particular response code. To see only links that have an error response code (400 or higher, or 0), use the flyout menu to visit Setup > Verify Links > Error responses only. For those who can't wait The module identifies links as pages are saved and verifies links on a LazyCron schedule. If you've installed the module on an existing site and you don't want to wait for this process to happen organically you can use the ProcessWire API to save pages and verify links en masse. // Save all non-admin, non-trashed pages in the site // If your site has a very large number of pages you may need to split this into batches $items = $pages->find("has_parent!=2|7, template!=admin, include=all"); foreach($items as $item) { $item->of(false); $item->save(); } // Verify the given number of links from those that VerifyLinks has identified // Execute this repeatedly until there are no more white rows in the Verify Links table // You can try increasing $number_of_links if you like $vl = $modules->get('VerifyLinks'); $number_of_links = 20; $vl->verifyLinks($number_of_links); Advanced There are hookable methods but most users won't need to bother with these: VerifyLinks::allowForField($field, $page) - Allow link URLs to be extracted from this field on this page? VerifyLinks::isValidLink($url) - Is this a valid link URL to be saved by this module? VerifyLinks::extractHtmlLinks($html) - Extract an array of external link URLs from the supplied HTML string https://github.com/Toutouwai/VerifyLinks https://processwire.com/modules/verify-links/1 point