bernhard Posted October 4, 2019 Share Posted October 4, 2019 Hi everybody, having worked mostly in the backend for the last weeks and having an upcoming project where I need some frontend stuff soon, I played around with a new concept of creating frontend themes for ProcessWire. That idea is not new... Nico built WireThemes back in 2014 and @teppo has recently launched WireFrame. I've also built two websites using this module (screencast) but that turned out to be too complicated and it was also working only with the uikit frontend framework. But still, it feels like I'm doing a lot of unnecessary work with every frontend project: Getting the framework Setting up the design Setting up the menu Setting up the correct dependencies (scripts, fonts, icons, etc) Setting up the config (markup regions etc) Setting up site settings (logo upload etc) etc, etc A lot of this stuff is the same for every site, so I'd really like to have a solution that is plug&play where I just have to do the customizations and not reinvent the wheel over and over again with every project. Also, I'd like to have everything in place so that I can just git clone a theme and share one theme across multiple projects (just think about the site header with favicon, seo and social tags!). Meet RockThemes ? As you can see in the video, the process is quite straightforward. Just install RockThemes and copy your theme to the templates folder (and set $config->theme to point to that folder, which was already in place in the video). The current status is quite promising: Themes stay entirely in the templates folder One year ago I decided to create themes as PW modules. That makes things complicated because assets are blocked by .htaccess from direct public access! Now themes live in /site/templates and assets are easily accessible for the public. The module uses Markup Regions by default They are great and offer so much flexibility and power. They are perfect for such a module ? The template files stay clean and easy, eg the footer file of the theme: <region pw-replace="footer"> <p>Powered by <a href="http://processwire.com">ProcessWire CMS</a> / <a href="/admin/">Admin Login</a></p> </region> Or the basic-page template (that gets the date from the site profile's template file and just populates the regions): <?php namespace ProcessWire; $sidebar = null; include("../basic-page.php"); ?> <region pw-replace="mainleft"> <h1><?= $page->title ?></h1> <?= $content ?> </region> <region pw-replace="mainright"><?= $sidebar ?></region> Themes are extendable This means that you can build one default master theme that you share across your projects and then create one custom theme per project that only contains the files that you need to change. The module supports any CSS framework I've built a base module that can be extended for every framework. The base module will consist functions that every project needs (eg for rendering favicon markup or SEO tags). The framework version will then extend this module with framework specific functions like rendering a menu or rendering paginations. Switching layouts is as easy as changing one file default.php <div class="uk-container"> <section id="header"></section> <hr> <section id="main"> <div class="uk-grid-divider" uk-grid> <div class="uk-width-expand"> <div id="breadcrumbs"></div> <div id="mainleft"></div> </div> <div class="uk-width-1-3@m" id="mainright" pw-optional></div> </div> </section> <hr> <section id="footer"></section> </div> colorful.php <section class="uk-background-primary uk-light"> <div class="uk-container" id="header"></div> </section> <section class="uk-background-muted"> <div class="uk-container"> <div id="breadcrumbs" class="uk-margin-top"></div> </div> </section> <section class="uk-section-small" uk-height-viewport="expand: true"> <div class="uk-container" id="mainleft"></div> </section> <section class="uk-background-muted uk-section-small" pw-optional> <div class="uk-container" id="mainright" pw-optional></div> </section> <section class="uk-section uk-background-secondary"> <div class="uk-container" id="footer"></div> </section> All other files are unchanged! This of course only works if the regions are named exactly the same. That would lead to the challenge of having the same region names across our themes. I guess that's the case for all CMSs that have theming support? I can remember the times when I worked with joomla (content-top, top, header-a etc). Would it make sense to create a master layout that can be used for almost every project? What regions are you using in your projects? I think such a frontend framework could open up a lot of possibilities. It would for example be a lot easier to develop helper modules for the frontend (think of RockTabulator or something like FREDI) because we would finally have at least a very basic standard how things are done (eg how to add assets to the <head>). It could also be easier to work on projects in a team, because everybody would know how things work. Though, I'm still not sure if such a module would make sense for the public at all. I'd be especially curious what @teppo thinks about that and how you see that approach compared to WireFrame (I wanted to use it before I started this module, but it did not feel right for me). Maybe that's exactly the problem: When it comes to frontend framework / theming approaches things just don't feel right, because everybody is so used to his workflows. So what do you guys think? Would such a module make sense to you? Would you be using it? If yes, what would be necessary features? What would be no-go's? 13 3 Link to comment Share on other sites More sharing options...
OllieMackJames Posted October 5, 2019 Share Posted October 5, 2019 Hello @bernhard, What I think? Briliant, I like your thinking here! It would definitely make sense to me, in fact I have 2 sites I would like merged into one system that allows use of all functionailty of the two sites with ease of changing the look and feel front end, but with proven abck end system in place Necessary features? - Repeater matrix list of reusable sections to easily build pages - Easy way of changing the look and feel of a whole site by changing as few things as possible Good stuff Bernhard! 1 Link to comment Share on other sites More sharing options...
teppo Posted October 5, 2019 Share Posted October 5, 2019 Hey Bernhard! A few initial observations and notes – I will have to dig into your post deeper and check the video when I'm back home. On a trip at Spain at the moment, and the network connection here is... limited ? First of all I still find the idea of themes intriguing, but it's also a complex matter, and there are different aspects to consider. For an example WordPress has (as most here probably know) made great effort to support themes – yet in reality you cannot just switch between themes as you want (which is, in my opinion, a key point in the themes vs. starting profiles discussion) if you have something "out of the ordinary" going on: custom fields, custom views, plugins generating markup, etc. Wireframe doesn't actually try to solve the theming part. In fact it's quite the opposite: it's a framework that provides sensible structure for sites built with ProcessWire – one that separates the implementation into different files/classes ("business logic" vs. views vs. layouts and so on) in a meaningful way, allows for reusability, and continues to make sense even if/when the site scales. While it can be easy to make visual changes to a site built with wireframe – as long as it's used in its entirety, in which case making changes to a single layout file is often all you need – that's really the extent of it. The kind of things you've mentioned, like getting the framework and setting things up, are in that context resolved with site profiles: if you find yourself repeating these tasks over and over, you should build a site profile where you've got the defaults nailed down – or, if you find you often just swap the logo etc. then add a settings area and a custom field for it. The "official" Wireframe boilerplate is one of those, and here at Avoine we've got our own "boilerplate" specifically tailored for the type of sites we work with (and what you've listed are (some of the) things we've covered in it). Long story short: I think we're solving different problems, and as such I wouldn't draw too many lines between those two solutions ? I do agree that you're onto something here, though, and see a need for that. The way you've described RockThemes sounds pretty close to how WordPress works, although I've not had the chance to dig into all the details yet. For an example I don't have a good idea about how much you're planning to let a specific theme override vs. how much you plan to keep things "set in stone". That, I think, is actually one of the most important factors here: figuring out how much you can/should standardise stuff, and if one can "break loose" of the theme by overriding it in a way that changes it radically. ... and that, of course, depends on how far you want to go in terms of "themeability": if one wants to switch a theme and it should always "just work", you might go as far as define basic views and features (such list and archive views etc.) so that theme authors know what to provide markup/logic and styles for. On the other hand if it's enough that the layout is interchangeable and all content types (templates) that don't follow some specific convention (title and body fields, or something like that) will need per-site markup, then a much simpler approach is going to be quite enough. My "a few initial observations" got a bit out of hand, but I'll definitely check the video etc. later. And sorry if I've missed any important points here ? 7 Link to comment Share on other sites More sharing options...
LostKobrakai Posted October 7, 2019 Share Posted October 7, 2019 On 10/5/2019 at 7:11 PM, teppo said: ... and that, of course, depends on how much you want to go in terms of "themeability": if one wants to switch a theme and it should always "just work", you might go as far as define basic views and features (such list and archive views etc.) so that theme authors know what to provide markup/logic and styles for. On the other hand if it's enough that the layout is interchangeable and all content types (templates) that don't follow some specific convention (title and body fields, or something like that) will need per-site markup, then a much simpler approach is going to be quite enough. That's what I was thinking about as well. Theming I'd divide up in 3 parts, which need to be handled: Getting data out of the persistance layer in a format, which is well defined to theme developers. Without knowing the data upfront I'm not sure how one would build a UI for it. Ways for theme code to format that data into markup snippets. A flexible way to compose those snippets into a whole page. (Having a way to handle http inputs (form submissions, get parameters, …) 2 Link to comment Share on other sites More sharing options...
bernhard Posted October 7, 2019 Author Share Posted October 7, 2019 Hi @teppo! Thx for your elaborate answer ? On 10/5/2019 at 7:11 PM, teppo said: First of all I still find the idea of themes intriguing, but it's also a complex matter, and there are different aspects to consider. For an example WordPress has (as most here probably know) made great effort to support themes – yet in reality you cannot just switch between themes as you want (which is, in my opinion, a key point in the themes vs. starting profiles discussion) if you have something "out of the ordinary" going on: custom fields, custom views, plugins generating markup, etc. Wireframe doesn't actually try to solve the theming part. In fact it's quite the opposite: it's a framework that provides sensible structure for sites built with ProcessWire – one that separates the implementation into different files/classes ("business logic" vs. views vs. layouts and so on) in a meaningful way, allows for reusability, and continues to make sense even if/when the site scales. While it can be easy to make visual changes to a site built with wireframe – as long as it's used in its entirety, in which case making changes to a single layout file is often all you need – that's really the extent of it. Thx, this sounds like the name of my module and the headline of this topic is somewhat misleading. Actually my take is closer to WireFrame than to WordPress Themes. Or maybe it is something in between. On 10/5/2019 at 7:11 PM, teppo said: The kind of things you've mentioned, like getting the framework and setting things up, are in that context resolved with site profiles: if you find yourself repeating these tasks over and over, you should build a site profile where you've got the defaults nailed down – or, if you find you often just swap the logo etc. then add a settings area and a custom field for it. The "official" Wireframe boilerplate is one of those, and here at Avoine we've got our own "boilerplate" specifically tailored for the type of sites we work with (and what you've listed are (some of the) things we've covered in it). Well. I don't like site profiles ? Actually, I hate them ? Site profiles are so rigid and one-way. What if I developed a new project, started with my great profile and implemented a new feature (like new SEO markup that was not supported yet. I'd have to implement that feature on my site, then I'd have to update my site profile if I wanted to use this feature for future projects. And then? What happens to the 10 sites that I've built using this site profile during the last year? I'd have to update all of them one by one. What I want is to implement a feature once and then just do a git pull to update all instances. Maybe I'm overengineering, though... On 10/5/2019 at 7:11 PM, teppo said: Long story short: I think we're solving different problems, and as such I wouldn't draw too many lines between those two solutions ? I think our approaches are quite close. I might have only been missing the site-profile part when I played around with WireFrame. So I ended up with a blank site and thought: "Ok, that's not too much of help or not really what I wanted." The idea of RockThemes is to provide a framework on the one hand (with a helper class just like ryan has the uikit helper functions file), but in addition to that themes could also provide basic page blocks that one needs over and over again. In contrast to WordPress Themes this could be files that are completely decoupled from the site's field setup. An uikit slider for example could look like this: /site/templates/themeMaster/blocks/slider.php <?php // defaults if(!isset($images)) $images = $page->images; ?> <div class="uk-position-relative uk-visible-toggle uk-light" tabindex="-1" uk-slider> <ul class="uk-slider-items uk-child-width-1-2 uk-child-width-1-3@s uk-child-width-1-4@m"> <?php foreach($images as $image): ?> <li> <img src="<?= $image->url ?>" alt=""> <div class="uk-position-center uk-panel"><h1>Foo</h1></div> </li> <?php endforeach; ?> </ul> <a class="uk-position-center-left uk-position-small uk-hidden-hover" href="#" uk-slidenav-previous uk-slider-item="previous"></a> <a class="uk-position-center-right uk-position-small uk-hidden-hover" href="#" uk-slidenav-next uk-slider-item="next"></a> </div> This block (that can be shared across different projects and simply updated via git push/pull) could then be rendered in the theme like this: /site/templates/themeFoo/home.php <region id="main-slider"> <?= $theme->parent->render("blocks/slider.php", [ 'images' => $page->your_image_field, ]); ?> </region> This means that it would not be a problem at all if pages had different field names. 2 hours ago, LostKobrakai said: Getting data out of the persistance layer in a format, which is well defined to theme developers. Without knowing the data upfront I'm not sure how one would build a UI for it. Ways for theme code to format that data into markup snippets. A flexible way to compose those snippets into a whole page. (Having a way to handle http inputs (form submissions, get parameters, …) I guess some of that is obsolet now? I think you also got the impression that I'm talking about WP-like themes? 2 Link to comment Share on other sites More sharing options...
teppo Posted October 7, 2019 Share Posted October 7, 2019 Thanks Bernhard! I might've indeed read your post somewhat wrong. Now that I've re-read it along with your comments (and watched the video), I think I have a better idea of what RockThemes is all about. I can even see some similarities with wireframe, although I'd still argue that they are few, and they seem to mostly apply to the view layer – or a part of it ? The word "theme" might've thrown me a bit off, yet now that I'm reading your post for the third time or so, I'm still not sure what else to call it. Correct me if I'm wrong, but technically you're talking about having the template files (/site/templates/*.php) populate a content variable, and the theme pretty much defines what "wraps" that site-specific content? Still not entirely sure I got this right, so I may be completely on the wrong tracks ? By the way: as a bit of a disclaimer please don't take anything I say here as disencouragement. That is not my intention. I think your idea has plenty of merit, and it's thrilling to see projects like RockThemes that, in some ways, challenge the status quo. 6 hours ago, bernhard said: Site profiles are so rigid and one-way. What if I developed a new project, started with my great profile and implemented a new feature (like new SEO markup that was not supported yet. I'd have to implement that feature on my site, then I'd have to update my site profile if I wanted to use this feature for future projects. And then? What happens to the 10 sites that I've built using this site profile during the last year? I'd have to update all of them one by one. What I want is to implement a feature once and then just do a git pull to update all instances. Maybe I'm overengineering, though... Trust me, I've been there. Your concern is perfectly valid and familiar. Site profiles are intended as starting points, and they don't scale beyond that ? One solution to your problem from my point of view: if you have a feature that you want to use on multiple sites either as-is (or perhaps with some modifiable settings), bundle it into a module. Menu generation, metadata output, favicon generation... this sounds like three separate modules to me. Or one module that does it all if that makes more sense, but at least in my experience separate modules tend to make more sense as they provide more flexibility. If it's all bundled into one package, you tend to run into problems if you want to modify your metadata generation method – but the modification only applies to, say, five out of those ten sites. Not to mention the two that require an entirely different solution, etc. The point is that in my experience it's better not to bundle too many assumptions into one package. "One module, one concern" ? (A bit off-topic, but the "small modules" approach can sometimes result in a more work when it comes to updates. That, in turn, can be resolved by using a module manager, or – my personal preference – Composer. Or, alternatively, Git submodules.) 6 hours ago, bernhard said: I think our approaches are quite close. I might have only been missing the site-profile part when I played around with WireFrame. So I ended up with a blank site and thought: "Ok, that's not too much of help or not really what I wanted." Even after re-reading your post, I still think that the purposes are somewhat different. Let me elaborate on that a bit... ? For me one key point about wireframe is the separation of the business logic ("code", which is implemented as the methods of the Controller classes) from the presentation layer (the "dumb" views, partials, and layouts). The amount of markup generation features in wireframe is also exactly zero: it provides structure and "connects the dots" between different components, but the rest of the implementation is entirely up to the site in question. One example (I'm trying hard not to go too deep into my own "vision" here) are the sites I've built with the predecessor of wireframe that didn't have a "human-readable" UI. API first (or "headless") sites, that is. I've also built sites that didn't even have an API – only code that was triggered behind the scenes by scheduled scripts – though admittedly that's a rare use case. In wireframe controllers and various view components are all optional, which means that there may be sites that use them all, as well as sites with just a backend or just a front-end – not to mention that a site with a front-end may still use just a part of the view layer: all templates could use a single layout file for rendering, but they might as well not use a layout file at all and instead rely on template-specific view files for all their rendering needs ? 6 hours ago, bernhard said: The idea of RockThemes is to provide a framework on the one hand (with a helper class just like ryan has the uikit helper functions file), but in addition to that themes could also provide basic page blocks that one needs over and over again. In contrast to WordPress Themes this could be files that are completely decoupled from the site's field setup. An uikit slider for example could look like this: /site/templates/themeMaster/blocks/slider.php <?php // defaults if(!isset($images)) $images = $page->images; ?> <div class="uk-position-relative uk-visible-toggle uk-light" tabindex="-1" uk-slider> <ul class="uk-slider-items uk-child-width-1-2 uk-child-width-1-3@s uk-child-width-1-4@m"> <?php foreach($images as $image): ?> <li> <img src="<?= $image->url ?>" alt=""> <div class="uk-position-center uk-panel"><h1>Foo</h1></div> </li> <?php endforeach; ?> </ul> <a class="uk-position-center-left uk-position-small uk-hidden-hover" href="#" uk-slidenav-previous uk-slider-item="previous"></a> <a class="uk-position-center-right uk-position-small uk-hidden-hover" href="#" uk-slidenav-next uk-slider-item="next"></a> </div> This block (that can be shared across different projects and simply updated via git push/pull) could then be rendered in the theme like this: /site/templates/themeFoo/home.php <region id="main-slider"> <?= $theme->parent->render("blocks/slider.php", [ 'images' => $page->your_image_field, ]); ?> </region> This means that it would not be a problem at all if pages had different field names. Right – this makes sense, I think. I don't think I've yet seen in your examples how one would extend a theme, but I'm assuming that the general concept is that you've got one theme that you copy from project to project, and then for each project that differs from the base theme in any way you create another, site-specific theme that you customise? If that's correct, this reminds me of WordPress' themes and child themes. In that context the idea is that you can update the parent theme and your site will stay intact because all the modifications are in the child theme. (This, of course, doesn't always work because the child theme may override something that changes / breaks when the parent theme is updated, new version of the parent theme may add or change a feature that the site relies on / doesn't need, etc.) On the other hand RockThemes itself is more like a "theme frameworks" in that it provides the base implementation for themes to build on, and possibly a number of general purpose helper features, components / blocks (?), etc. Hard to say what those would actually be without seeing the module, so I could be on the wrong tracks again, of course. I'll have to give this a few more moments to really sink in, after which I might have more questions / suggestions. Anyway, If I'm following you correctly, I like what you're doing here but wouldn't personally go this way – partly because I'm already invested in wireframe (obviously), but also because this doesn't seem to solve the issues I mostly struggle with (such as the part about separation of concerns). The issues with updating stuff, on the other hand, I've managed to resolve via other means, so for me that's mostly a non-issue ? 3 Link to comment Share on other sites More sharing options...
bernhard Posted October 8, 2019 Author Share Posted October 8, 2019 Hi Teppo, thx a lot for your thoughts ? 12 hours ago, teppo said: The word "theme" might've thrown me a bit off, yet now that I'm reading your post for the third time or so, I'm still not sure what else to call it. Correct me if I'm wrong, but technically you're talking about having the template files (/site/templates/*.php) populate a content variable, and the theme pretty much defines what "wraps" that site-specific content? Still not entirely sure I got this right, so I may be completely on the wrong tracks ? Almost ? Technically it's 2 parts: 1) The module (framework) that lives in /site/modules and provides helper functions (just like the pw admin), eg $theme->assets->render() that could render all js scripts and css styles in the head (that can be populated easily in all your templates via $theme->assets->add("assets/main.css"); $theme->assets->add("assets/main.js"); 2) The theme files that live in /site/templates/yourtheme and provide all the markup generation blocks (the basic setup is very similar to the default site profile). These files can easily be pulled from github. 3) Optional: Theme customizations, eg /site/templates/mythemechanges that only provide those files that are different from the master theme (eg a custom logo). Technically building themes is even possible at infinite recursion levels (themeMaster, themeChild1, themeChild2, themeChildN) where the first existing file is taken, starting from themeChildN (whenever it is requested as $theme->getFile("blocks/foo.php"); It's not about populating a $content variable in the theme files. It's more about providing the presentation layer (views) that can be shared across projects. The logic still has to be built into every single project, but with the huge difference that it will be as simple as that most of the time: <region pw-replace="header"> <?= $theme->render("blocks/menu.php") ?> </region> In the example above I'm just using the $content variable of the default site profile, but that just shows how flexible this approach is and that's by no means a necessity! ? In other words: In the example above I'm using the business logic of the default site profile just by including _func.php and the current template file and I'm using 2 presentation layers, first the default uikit theme (the bright one) and then the second theme with the default and secondary uikit colors. 12 hours ago, teppo said: One solution to your problem from my point of view: if you have a feature that you want to use on multiple sites either as-is (or perhaps with some modifiable settings), bundle it into a module. Menu generation, metadata output, favicon generation... this sounds like three separate modules to me. Or one module that does it all if that makes more sense, but at least in my experience separate modules tend to make more sense as they provide more flexibility. Trust me, I've been there ? ? And I disagree (but also not meant in a bad way). ProcessWire gives us the freedom to build things the way we want and that's what we all love it for, don't we? ? The problem that I see with those markup generation modules is that they are either opinionated about the output (only support one framework) or don't look good or are just not easy to use. I'm building all my sites with uikit, so it's tedious to create a menu like this: $options = [ 'active-class' => 'uk-active', 'child-item-template' => '<li {class}>{title}</li>', ... ]; $modules->get('WhatSoEver')->render($options); Why? Because I'm not clever enough to always remember the correct markup/syntax and the module has other defaults (because the module author might not use uikit) and I'm doing this waste of time (and fun) over and over again... Actually I've not done too much frontend stuff, but I try to avoid repeating work as much as possible ? But you got a valid point here and I'll think about that more closely (what should be part of themes and what should be a separate module). 13 hours ago, teppo said: Even after re-reading your post, I still think that the purposes are somewhat different. Well, that's a good thing as it means that we are not building the same thing twice ? But I'm still not sure about it. See the explanation about the $content variable above. Isn't that separation of concerns in the way you mean it? It would also be easy to provide a similar feature to RockThemes that calls a Controller file before it renders the template/block (or view, if you want to call it like that). Eg you could have the template file /site/templates/yourtheme/blocks/header.php <region pw-replace="header"> <div uk-grid> <div><?= $logo ?></div> <div><?= $menu ?></div> </div> </region> And then you could have a controller file /site/templates/yourtheme/blocks/headerController.php: <?php namespace ProcessWire; class headerController extends themeController { public function renderMenu() { return '<ul><li>...</li></ul>'; } public function renderLogo() { return '<a href="..."><img src="..."></a>'; } } I think I like that concept... But I have to think about it ? 13 hours ago, teppo said: In wireframe controllers and various view components are all optional, which means that there may be sites that use them all, as well as sites with just a backend or just a front-end – not to mention that a site with a front-end may still use just a part of the view layer: all templates could use a single layout file for rendering, but they might as well not use a layout file at all and instead rely on template-specific view files for all their rendering needs ? Same with RockThemes ? 13 hours ago, teppo said: Right – this makes sense, I think. I don't think I've yet seen in your examples how one would extend a theme, but I'm assuming that the general concept is that you've got one theme that you copy from project to project, and then for each project that differs from the base theme in any way you create another, site-specific theme that you customise? If that's correct, this reminds me of WordPress' themes and child themes. In that context the idea is that you can update the parent theme and your site will stay intact because all the modifications are in the child theme. (This, of course, doesn't always work because the child theme may override something that changes / breaks when the parent theme is updated, new version of the parent theme may add or change a feature that the site relies on / doesn't need, etc.) On the other hand RockThemes itself is more like a "theme frameworks" in that it provides the base implementation for themes to build on, and possibly a number of general purpose helper features, components / blocks (?), etc. Hard to say what those would actually be without seeing the module, so I could be on the wrong tracks again, of course. Yes, that sounds like finally we are talking the same language ? Extending themes could either be done just by replacing a content block (by just placing a file with the same name in your child theme) or - don't forget about we are still using ProcessWire ? - hooks! <?php $theme->addHookAfter("render(blocks/footer.php)", function($event) { $event->return .= "<div class='uk-text-center'>Hello World added by Hook</div>"; }); Or something like this: <?php $theme->addHook("HeaderController::renderFoo", function($event) { $event->return = 'BAR!'; }); Would be great to hear what you think about all that, thx! ? Have a great week everybody! PS: Another story that would make a lot of sense once we have some kind of standard in the frontend just like we have in the backend ($config->scripts->add(...)) would be some kind of site builder features. I've talked about that with @Jonathan Lahijani as he has put huge effort on that topic during the last year. 3 Link to comment Share on other sites More sharing options...
Recommended Posts