Jump to content

RockFrontend Site Profile - Quickly setup new Websites with RockFrontend + UIkit (optional) + TailwindCSS (optional)


Recommended Posts

I've been working on this site profile over the last month and we got several updates to the site profile exporter thx to @ryan that make maintaining site profiles a lot smoother.

It's not 100% battle tested yet, but if anybody wants to help finding bugs and improving the docs (by asking questions, which indicates where docs are missing), here you go: https://github.com/baumrock/site-rockfrontend

It's a quite interesting setup that I came up with on my latest project. I'll share more info another day, if there is interest, but for my latest RockMonthly newsletter I didn't want to hold that information back and also I wanted to have a place where people can discuss.

  • Like 5
Link to comment
Share on other sites

  • 2 weeks later...

Hello Bernhard,

basic-page.php and home.php are empty template files.
Are they only needed (even empty) if custom page class(es) php files that are related to them exist?
Because latte files are used here I'm a bit confused about the (possible) role of these template files.

In this site profile, in which use case(s) would they not stay empty?
Could you please give one (or more) example(s)?

Thanks in advance!

NB: I don't want to use tailwind, but I'm curious about _tailwind.css, I think it's the first time I see the "_" prefix on a css file name.

 

  • Like 1
Link to comment
Share on other sites

Thx @Christophe that's some good questions 🙂 

I've updated the profile to hopefully answer all of them: https://github.com/baumrock/site-rockfrontend/commit/be55adae28ffe6a7aac83944284820f17afdaabf

18 hours ago, Christophe said:

NB: I don't want to use tailwind (for several reasons, one of them is that there are resets used but uikit uses normalize already, doesn't it? (I would perhaps prefer modern-normalize or another "at-rest" for the moment project related to one of the css grids evengelists (I don't remember her name right now)), BUT I'm curious about _tailwind.css, I think it's the first time I see the "_" prefix on a css file name.

You don't need to use tailwind. If you don't want to use it just remove the _tailwind.css file. If you find anything happening that should not be let me know and I'll fix it.

  • Like 1
Link to comment
Share on other sites

Hello Bernhard,

A bit of context before the questions below in the message.

I want to display a list of children of the parent pages that are using the template "parent-page".
So, I have created parent-page.php (empty for the moment) in /site/templates.
And ParentPagePage.php in /site/classes in which I have this (where I tested different things):

<?php

namespace ProcessWire;
 
class ParentPagePage extends Page
{
public function listchildren()
{
return "Clickable list of children";
}
}

I had more elaborate code(s) in the return statement, but things weren't working so I just put a string in it to keep it simple.
(I've just noticed that vscode and intelephense are writing "Undefined type 'ProcessWire\Page'." in the PROBLEMS tab.)

So I had :

  • Method DefaultPage::listchildren does not exist or is not callable in this context on pages that do not use the parent-page template (and use the basic-page template).
  • Method HomePage::listchildren does not exist or is not callable in this context on the homepage.

For the error messages and blank page(s) to disappear it seems that it is mandatory to use this in main.latte:

{if $page->template == 'parent-page'}
{$page->listchildren()}
{/if}

and not just {$page->listchildren()}.

At one point with custom page classes I think I was hoping it would also remove the need for that if condition.

In /site/templates/sections/main.latte I currently have the code that follows - at the end of the message now (we apparently can't escape having to use the |noescape filter).
I simplified the code to only define and check $image (the code borrowed from another website was also defining and checking $images, so not only the first image, I don't remember why/if it was needed).

SO, my question(s) is how could this code be simplified, in part in order to have cleaner code in this main.latte file?
Which parts of the code should be in main.latte, which ones in ParentPagePage.php and which ones perhaps in parent-page.php?
How would you organize/separate them in the different files?
Also, can $image and $thumb be defined elsewhere? Etc.

Thanks again in advance!

I tried yesterday with simpler children list codes (without images and uikit markup), but it seemed complicated and not clean.
And now it's more complicated.
I've tried with code directly inside the return statement, and also with a variable and then returning the variable.

$thumb is currently defined if $image exists. If I used <img n:if="..." src="... it would be changed. But perhaps it wouldn't be important if it wasn't defined inside the {if}...{/if}.

<main>
<div class="uk-container">
<h1>{$page->title}</h1>
{$page->body|noescape}

{if $page->template == 'parent-page'}
{$page->listchildren()}
{/if} 

<div n:if="$page->template == 'parent-page'" class='uk-child-width-1-3@m uk-grid-match uk-margin-small-top uk-margin-medium-bottom uk-text-center' uk-grid>
<div n:foreach="$page->children() as $child">
<div class='uk-card uk-card-small uk-card-default uk-card-body'>
<a class="h2" href="{$child->url}"> 
{var $image = $child->images->first()}
{if $image}
{var $thumb = $image->size(200, 150)}
<img src="{$thumb->url}" width="{$thumb->width}" height="{$thumb->height}" alt="{$image->description}" />
{/if}
<h2>{$child->title|noescape}</h2>
</a>
</div>
</div>
</div>
  
</div>
</main>
Edited by Christophe
Problems with the display of code. Still tabulation issue.
Link to comment
Share on other sites

Hi @Christophe

7 minutes ago, Christophe said:

(I've just noticed that vscode and intelephense are writing "Undefined type 'ProcessWire\Page'." in the PROBLEMS tab.)

Unfortunately we don't have Code Intellisense or autocomplete in latte files at the moment 😞 See https://github.com/smuuf/vscode-latte-lang/issues/5

9 minutes ago, Christophe said:

So I had :

  • Method DefaultPage::listchildren does not exist or is not callable in this context on pages that do not use the parent-page template (and use the basic-page template).
  • Method HomePage::listchildren does not exist or is not callable in this context on the homepage.

You are adding the method "listchildren()" to your ParentPagePage, nowhere else. That means you can all this method only on pages that have the template "parent-page".

11 minutes ago, Christophe said:

At one point with custom page classes I think I was hoping it would also remove the need for that if condition.

Why should it do that? You are calling a method of an object. If that does not exist it is expected to throw an error. You CAN do what you describe though. Sometimes it is useful and I'm doing that as well. You could add that method to your DefaultPage.php and there return an empty sting. That would make $page->listchildren() return "" by default, which means it does not throw an error. For some page types you can then implement a different logic:

DefaultPage.php                   --> listchildren() { return ""; }
FooPage.php extends DefaultPage   --> listchildren() { return "foo!"; }
BarPage.php extends DefaultPage   --> listchildren() { return "BAR"; }

// in any template
echo $page->listchildren();

 

16 minutes ago, Christophe said:

SO, my question(s) is how could this code be simplified, in part in order to have cleaner code in this main.latte file?
Which parts of the code should be in main.latte, which ones in ParentPagePage.php and which ones perhaps in parent-page.php?
How would you organize/separate them in the different files?
Also, can $image and $thumb be defined elsewhere? Etc.

Thanks again in advance!

That it totally up to you. Same with regular ProcessWire templates. It's up to us devs how we organise things and everybody does it differently.

I can only say what I came up with and what works great for all kings of projects (from very simple to very complex ones):

  • layout.latte for main markup
  • /site/templates/sections/... for all sections
  • /site/templates/partials/... for all partials

Details:

layout.latte --> holds the html markup skeleton of the page, eg:

<html>
  <head>...</head>
  <body>
    <header>...</header>
    <main>...</main>
    <footer>...</footer>
  </body>
</html>

Then all my template files are usually empty (like home.php, basic-page.php, foo.php, bar.php).

Next, I divide my design into sections. A section is a portion of the page that goes from the very left to the very right and has an undefined height/content.

You can then add those sections to your main markup file like this:

<html>
  <head>...</head>
  <body>
    <header>
      {include "sections/topbar.latte"}
      {include "sections/navbar.latte"}
    </header>
    <main>
      {include "sections/breadcrumbs.latte"}
      {include "sections/content.latte"}
      {include "sections/content-footer.latte"}
    </main>
    <footer>
      {include "sections/footer.latte"}
    </footer>
  </body>
</html>

This is often all I need, because I build all the available sections in RockPageBuilder and then I can simply add them to the pages as I need them. But it works without RockPageBuilder as well. You then just need to code all your page layouts depending on the page template. If all those pages share the same breadcrumbs and content-footer it could look like this:

<html>
  <head>...</head>
  <body>
    <header>
      {include "sections/topbar.latte"}
      {include "sections/navbar.latte"}
    </header>
    <main>
      {include "sections/breadcrumbs.latte"}
      {if $page->template == 'foo'}
        {include "sections/content-foo.latte"}
      {elseif $page->template == 'bar'}
        {include "sections/content-bar.latte"}
      {else}
        {include "sections/content.latte"}
      {/if}
      {include "sections/content-footer.latte"}
    </main>
    <footer>
      {include "sections/footer.latte"}
    </footer>
  </body>
</html>

You could also use a dynamic approach:

<html>
  <head>...</head>
  <body>
    <header>
      {include "sections/topbar.latte"}
      {include "sections/navbar.latte"}
    </header>
    <main>
      {include "sections/breadcrumbs.latte"}
      {include "content/" . $page->template . ".latte"}
      {include "sections/content-footer.latte"}
    </main>
    <footer>
      {include "sections/footer.latte"}
    </footer>
  </body>
</html>

It's just regular PHP inside the latte tags, so you could also do is_file() checks etc:

<html>
  <head>...</head>
  <body>
    <header>
      {include "sections/topbar.latte"}
      {include "sections/navbar.latte"}
    </header>
    <main>
      {include "sections/breadcrumbs.latte"}
      
      {var $file = "content/" . $page->template . ".latte"}
      {if is_file($file)}{include $file}{/if}
      
      {include "sections/content-footer.latte"}
    </main>
    <footer>
      {include "sections/footer.latte"}
    </footer>
  </body>
</html>

Obviously you'd need to create those files. Here I'm placing them into a new folder called "content", which would be /site/templates/content/foo.latte for example.

Next, partials:

If you have repeating markup inside your sections you can outsource them into the partials folder. For example let's say you want to show a blog overview page that shows all single blog items as cards.

You'd have a section like "blog-overview.latte" like this:

// blog-overview.latte
<div uk-grid>
  <div n:foreach="$page->children() as $item">
    <div class="uk-card">
      <h3>{$item->title}</h3>
      <p>{$item->teaser()}</p>
    </div>
  </div>
</div>

This example is very simple and if you only use your cards here, then it's easier to leave them here. If you are using the exact same cards on two or three places then you can create partials for them:

// blog-overview.latte
<div uk-grid>
  {foreach $page->children() as $item}
    {include "partials/card.latte", item: $item}
  {/foreach}
</div>

// /site/templates/partials/card.latte
<div>
  <div class="uk-card">
    <h3>{$item->title}</h3>
    <p>{$item->teaser()}</p>
  </div>
</div>
  • Like 2
Link to comment
Share on other sites

Hello Bernhard,

Thank you again! It was very instructive.
No doubt includes are essential.

I didn't know if I had to post it here or in the RockFrontend module topic.
I'm converting and redesigning an old ProcessWire website for a non-profit association.
It contains 3 FormBuilder forms.

In _init.php, I have this code now (the same I had but I made changes so that it works with only one template):

// FormBuilder

if($page->template == "form-page" && $page->id == 1061) $form = $forms->render("contact");
else if($page->template == "form-page" && $page->id == 1059) $form = $forms->render("benevolat");
else if($page->template == "form-page" && $page->id == 1060) $form = $forms->render("soutien");
else $form = null;

And in /site/templates/sections/main.latte, I have this line among other things:

{$form|noescape}

(I can"t escape again from having to use the |noescape filter...)

In the old website, in _head.php and in _foot.php I have respectively:

if($form) {
echo $form->styles;}

if($form) {
echo $form->scripts;
}

How could something like the following work? (with the condition that $form exists or that $page->template == 'form-page')?
In _init.php,

// RockFrontend

$rf = rockfrontend();

$rf->styles()
// add the base uikit theme
->add('/site/templates/uikit/src/less/uikit.theme.less')
// add default folders like /sections and /partials
->addDefaultFolders()
// add FormBuilder styles on condition
->addIf($form->styles, $form)
// minify on production
->minify($config->debug ? false : true);

$rf->scripts()
// load uikit
->add('/site/templates/uikit/dist/js/uikit.min.js', 'defer')
// load custom javascript of this project
->add('/site/templates/scripts/main.js', 'defer')
// add FormBuilder scripts on condition
->addIf($form->scripts, $form, 'defer')
// minify on production
->minify($config->debug ? false : true);
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...