Sergio Posted April 4, 2017 Share Posted April 4, 2017 Hi guys, after several months I finally released my most complex ProcessWire project so far: https://ricardo-vargas.com About the client: Ricardo Vargas is a specialist in project management and strategy implementation. He's an accredited professional and author of several books. Since 2007, he publishes a bilingual podcast about project management with millions of episodes listened. From 2012 to 2016, he worked for the United Nations Office for Project Services (UNOPS) in Copenhagen, Denmark. He currently lives in Portugal. The previous site was developed in 2009 using Wordpress by my team at the agency I was working for. In 2011, Ricardo invited me to work with him and I started to maintain the site ever since. The front-end side was good, performance-wise, but the backend started to become horrendous to work with so in 2012 I started my quest to find a better CMS and found PW. After developing small projects and messing around with it I convinced my client/boss last year to let me develop his new website with PW. I did all the stuff (design, frontend, backend, and server ops) so if you find something buggy or strange, let me know, please! I'll appreciate! The site is currently running on Digital Ocean droplet with 2GB of RAM. Nginx and Cloudflare (for SSL mostly). I'm using forge.laravel.com to manage it. Approx. 3,000 unique users per day doing 72,421 requests (Cloudflare stats). Key features: Pages are loaded with ajax using https://github.com/miguel-perez/smoothState.js so the podcast player (Soundmanager ) can continue to play the podcast episode as the user navigates other pages. Member area where the user can see the books his own (and download their files) and also see his bookmarks and reports. I imported and the users (+ 4k) from the WP database and decided to get rid of passwords (the future!) so after some research and tests, I chose Auth0 login system. I've mentioned the member area on this topic (there are a couple of screenshots there): Modules used AdminLinksInFrontend AdminOnSteroids AdminTemplateColumns Auth0Login (Custom made) BatchChildEditor ClearCacheAdmin FieldtypeRuntimeMarkup FlickrAPI (Custom made) FormBuilder InputfieldCKEditor MarkInPageTree MarkupLoadRSS PageReferencesTab PageViews (Custom made) PduReport (Custom made) PrevNextTabs ProCache ProDrafts ProcessDatabaseBackups ProcessJumplinks ProcessSendyAPI (Custom made) ProcessWireUpgrade ReaderAreaManager (Custom made) SlideshareAPI (Custom made) TemplateLatteReplace TextformatterAccordion TextformatterHannaCode TextformatterMarkExternalLinks TextformatterMultiValue TracyDebugger UserBookmarks (Custom made) WireMailMailgun importPagesCSV 15 Link to comment Share on other sites More sharing options...
Robin S Posted April 5, 2017 Share Posted April 5, 2017 Nice work! Must be a good feeling to have such a big task completed and live. I'm always interested to hear how much time goes into larger jobs like this undertaken by a single developer: any idea how long you spent on it? I noticed a couple of minor display issues on the Books page. You can see both in the screenshot below: "Book recommendations" item seems to be missing expected content. Side column layout issue at some device widths. Edit: one more on this page... the "Powered by Goodreads" link is malformed. Again, a really great site. 2 Link to comment Share on other sites More sharing options...
szabesz Posted April 5, 2017 Share Posted April 5, 2017 Big thumbs up to Sérgio! And thank you for sharing the info of the "tools" used. Both smoothState.js and Auth0 looks "interesting" Also, I spotted that you use @tpr's TemplateLatteReplace. For the whole site? 2 Link to comment Share on other sites More sharing options...
tpr Posted April 5, 2017 Share Posted April 5, 2017 Nice to see a few of my modules in such a big project! FYI with AOS you can replace TemplateAdminColumns, and with TemplateLatteReplace filters/macros TextfomatterMultiValue and even ALIF, provided if you are not using their advanced features. 2 Link to comment Share on other sites More sharing options...
Sergio Posted April 5, 2017 Author Share Posted April 5, 2017 8 hours ago, Robin S said: Nice work! Must be a good feeling to have such a big task completed and live. I'm always interested to hear how much time goes into larger jobs like this undertaken by a single developer: any idea how long you spent on it? I noticed a couple of minor display issues on the Books page. You can see both in the screenshot below: "Book recommendations" item seems to be missing expected content. Side column layout issue at some device widths. Edit: one more on this page... the "Powered by Goodreads" link is malformed. Again, a really great site. Thanks, @Robin S! Yes, it's a great feeling! After everything was running apparently fine, it was like removing a heavy weight from the shoulders. The project took more time than as I was expecting for some reasons, it was developed in "waves" as I have to stop it for 2-3 weeks many times to handle some other of our projects. I didn't track the time but I can estimate that if done without stopping, it would have taken at least 9 months. But now that I know more about PW's advanced features, like building modules and how to create a member area, it would take 33% less time I think. The project has 66 templates and 1849 pages so far, some of them with lots of content like the ones on Consulting and Training sections, so a lot of time was spent importing content. -- Very strange you had problems in the book section rendering, could you tell me what browser you used? I'm using a Mac and also tested in Firefox on Ubuntu and Edge and IE11 on Windows 10. 2 Link to comment Share on other sites More sharing options...
Sergio Posted April 5, 2017 Author Share Posted April 5, 2017 (edited) Yes, @szabesz! Using @tpr's excellent Latte module for the whole site! Such a time saver! Take a peek on the podcast item template (ignore the indentation problems): Spoiler {block content} {include './layouts/partials/_section-header.latte'} <main class="row main-content"> <div class="{$detail_main_columns} columns"> <article> <ul class="menu simple"> <li> <small> <time itemprop="datePublished" datetime="{$page->published_at|date:'%Y-%m-%d'}"> {$page->published_at|date:'%d %b %Y'} </time> </small> </li> <li n:ifx="$page->page_views"><small>{$x|number_local:$lang} {_'views', 'General'}</small></li> </ul> <h1 class="section-h1 color-podcasts"> {$page->title|noescape} <button n:if="$user->isLoggedin()" class="color-podcasts u-op3 js-toggle-bookmark" title="{_'Add to my bookmarks', 'General'}"> <svg class="icon"><use xlink:href="{$icons}icon-bookmark"></use></svg> </button> </h1> <p n:ifx='$warning' class="warning callout u-mt24">{$x|noescape}</p> <p class='u-mt24'> {$page->intro} </p> <noscript> <p> <audio src="{$mp3_file}" controls preload="auto"></audio> </p> </noscript> <div> <a href="#" data-id="{$page->id}" data-play="auto" data-mp3="{$mp3_file}" data-title="{$page->title} – {$page->published_at|date:'%d %b %Y'}" class="button small u-text-upper bg-podcasts js-btn-play" style="display: none">Play</a> <a href="{$url_download}" class="button small hollow podcasts u-text-upper" aria-label="{_'Download MP3 audio file', 'Podcasts'}">Download</a> </div> <aside class="row u-mt24"> <div class="medium-9 columns"> {include './partials/_tag_list.latte', tags => $page->tags} </div> <div class="medium-3 columns last pmi-triangle-label"> <a href="{$podcasts->url}?filter={$page->pmi_triangle->value|lower}"> <span title="PMI Talent Triangle: {$page->pmi_triangle->title|noescape}"> <svg class="icon icon-small"> <use xlink:href="{$icons}icon-pmi-triangle"></use> </svg> <small class="pmi-triangle {$page->pmi_triangle->value|lower}">{$page->pmi_triangle->title|noescape|cutAt:' '}</small> </span> </a> </div> </aside> <aside class="u-mt48"> {if count($page->related_podcasts)} <h4 class="u-pb8 u-bb"> <svg class="icon icon-medium"> <use xlink:href="{$icons}icon-headphones"></use> </svg> {_'More on this series', 'Podcasts'} </h4> <ul n:inner-foreach="$page->related_podcasts as $r" class="no-bullet"> <li class="u-mb8"> <article> <small class="fade-half"> <time datetime="{$r->published_at|date:'%Y-%m-%d'}"> {$r->published_at|date:'%d %b %Y'} </time> </small> <a href="{$r->url}" class="color-podcasts"> <h5>{$r->title|noescape}</h5> </a> </article> </li> </ul> {/if} <aside n:if="$related_playlists->count() > 0" class="callout u-border u-mt64"> <h5 class="color-podcasts u-text-upper"> <svg class="icon"> <use xlink:href="{$icons}icon-shuffle"></use> </svg> {_'Playlists', 'Podcasts'} </h5> <p> {__p('This episode is part of the playlist', 'This episode is part of the playlists', $related_playlists->count()), 'Podcasts'}: </p> <div n:inner-foreach="$related_playlists as $r" class="row medium-up-2 large-up-3"> <div class="column"> <a href="{$r->url}" class="u-no-link"> <h5 class="color-podcasts u-h4">{$r->title|noescape}</h5> {* <div n:if='$r->images->count()'> {$r|thumbnail:200,100|noescape} </div> *} <p class="u-font-small">{trim($r->summary, "<p></p>")|noescape}</p> </a> </div> </div> </aside> {include './partials/_disqus.latte', color => 'podcasts'} </aside> </article> </div> <div class="{$detail_secondary_columns} columns u-mt8 u-mt-xs-64"> <div class="media-object u-line-height-small"> <a href="http://feedpress.me/5pmpodcast_{$lang}" target="_blank" rel="noopener noreferrer" class=""> <div class="media-object-section small"> <svg class="icon icon-medium icon-rss u-mr16"> <use xlink:href="{$icons}icon-rss2"></use> </svg> </div> <div class="media-object-section small"> <span>{_'Subscribe via RSS or Email', 'Podcasts'} <br/><small>{_'and get notified on new episodes', 'Podcasts'}</small> </span> </div> </a> </div> <div class="media-object u-line-height-small"> <a href="{$soundcloud_url}" target="_blank" rel="noopener noreferrer" class="color-podcasts"> <div class="media-object-section small"> <svg class="icon icon-medium u-mr16"> <use xlink:href="{$icons}icon-soundcloud2"></use> </svg> </div> <div class="media-object-section small"> {_'Listen to this episode <br/> on <strong>Soundcloud.com</strong>', 'Podcasts'|noescape} </div> </a> </div> <div class="u-mt24 u-mb24 callout secondary"> {include "./partials/_search-form.latte"} </div> {include './partials/_sidebar.latte'} <div class="u-mb24" n:if="$same_tags->count() > 0"> {include "./partials/_related-by-tag.latte"} </div> </div> </main> {/block} {block pagescripts} <script> $(document).ready(function(){ $('.js-btn-play').show(); }); </script> {/block} And I forgot to mention that for the frontend I'm using Foundation framework with a couple of custom spacing and helpers styles like the ones you see on some tags like "u-mt48" (utility- margin-top of 48 pixels) Edited April 5, 2017 by Sérgio Add spoiler and changed code block again Link to comment Share on other sites More sharing options...
Sergio Posted April 5, 2017 Author Share Posted April 5, 2017 7 hours ago, tpr said: Nice to see a few of my modules in such a big project! FYI with AOS you can replace TemplateAdminColumns, and with TemplateLatteReplace filters/macros TextfomatterMultiValue and even ALIF, provided if you are not using their advanced features. 1 Many thanks for all your modules, @tpr! They are excellent and helped a lot! Yep, I was planning to replace TemplateAdminColumns in all templates but had to release the project before that. I do it later. The same thing about ALIF, I started using it before AOS I think, so I just kept it there. But what can I use to replace TextfomatterMultiValue ? 1 Link to comment Share on other sites More sharing options...
szabesz Posted April 5, 2017 Share Posted April 5, 2017 11 minutes ago, Sérgio said: Yes, @szabesz! Using @tpr's excellent Latte module for the whole site! Such a time saver! Take a peek on the podcast item template (ignore the indentation problems): Thanks for Sharing! (You Might Want to Put the Code in a Spoiler Though ) the Template File's Code Reveals More That Can Currently Be Seen or May It Just Me Who Cannot Find the "Related Stuff" What happened to your reply BTW? In the meantimne it was deleted, just the code part remaining... Link to comment Share on other sites More sharing options...
Sergio Posted April 5, 2017 Author Share Posted April 5, 2017 (edited) 8 minutes ago, szabesz said: Thanks for Sharing! (You Might Want to Put the Code in a Spoiler Though ) the Template File's Code Reveals More That Can Currently Be Seen or May It Just Me Who Cannot Find the "Related Stuff" What happened to your reply BTW? In the meantimne it was deleted, just the code part remaining... I think I deleted it by mistake but thanks to you I put it back. And thanks for the tip of using spoiler! Much better indeed! I also changed the link so the new page shows all the code blocks with related stuff: https://ricardo-vargas.com/podcasts/cost-estimating-part-1-of-3/ Edited April 5, 2017 by Sérgio 1 Link to comment Share on other sites More sharing options...
tpr Posted April 5, 2017 Share Posted April 5, 2017 Beautiful code! Nice to see somebody else using Latte and in such an advanced level Am I right you're using custom filters, like |thumbnail or |number_local? If you think you have filters/macros to share, please share TextformatterMultiValue: I meant the getlines filter as a replacement. This is very new and allows only 1 or 2 items per lines (value or key+value) so if you need more items per line it will not do. ALIF: it's not AOS (which is strictly loaded in the admin) but the editlink macro. Again, it's very basic compared to ALIF or FEEL or Fredi. But if you have those modules at place I think better to leave them there to avoid unexpected side effects What do you think about adding a module option to TLR to get rid of the "noescape" filter? At least for projects where myself is the only dev/editor I don't expect malicious code Link to comment Share on other sites More sharing options...
Sergio Posted April 5, 2017 Author Share Posted April 5, 2017 11 minutes ago, tpr said: Beautiful code! Nice to see somebody else using Latte and in such an advanced level Am I right you're using custom filters, like |thumbnail or |number_local? If you think you have filters/macros to share, please share TextformatterMultiValue: I meant the getlines filter as a replacement. This is very new and allows only 1 or 2 items per lines (value or key+value) so if you need more items per line it will not do. ALIF: it's not AOS (which is strictly loaded in the admin) but the editlink macro. Again, it's very basic compared to ALIF or FEEL or Fredi. What do you think about adding a module option to TLR to get rid of the "noescape" filter? At least for projects where myself is the only dev/editor I don't expect malicious code Thanks! But I know that there's a lot of places where I can improve it. I had some problems with the plural translation on some other pages but got a workaround. I still have to update the module and start using your news filter and macros. About my custom filters/macros, I have to refactor some of them, and I guess you probably have almost all of them but with different names. Thumbnail is just a dumb filter to get the page image and resize it, I actually not using it anymore, forgot to remove the commented code from the page. Here's the number_local and cutAt: Spoiler /** * Usage: {$file->download_count|number_local:$lang} **/ $view->addFilter('number_local', function ($number, $lang, $decimal=0) { if ($lang == 'pt') { return number_format($number, $decimal, ',', '.'); } else { return number_format($number, $decimal, '.', ','); } }); /** * Extract string part at defined $character * Example: * $thumb = 'https://farm8.staticflickr.com/7494/27395968195_c50c13dd0b_q.jpg' * <img src="{$thumb|cutAt:'_q.jpg'}_m.jpg" /> **/ $view->addFilter('cutAt', function ($string, $character, $reverse = false) { if($character != '') { $phrase = explode($character, $string, 2); $word = $phrase[0]; if($reverse) { $word = $phrase[1]; } } else { $word = $string; } return $word; }); And yes, I'm planning to get rid of the "noescape" filter in the future. 1 Link to comment Share on other sites More sharing options...
Zeka Posted April 5, 2017 Share Posted April 5, 2017 Hi, @Sérgio Really nice work. Maybe you have some tips to share about ajax page load. Maybe you have met some challenges while implementing this feature. If so, could you please share them. Link to comment Share on other sites More sharing options...
Sergio Posted April 5, 2017 Author Share Posted April 5, 2017 34 minutes ago, Zeka said: Hi, @Sérgio Really nice work. Maybe you have some tips to share about ajax page load. Maybe you meet some challenges while implementing this feature. If so, could you please share them. Hi Zeka, thank you! The solution I used, the aforementioned Smoothstate.js, it's a jQuery plugin to handle page transitions, so not a fully Ajax solution. If you disable JS, the site main navigation will work just fine, what the plugin does is to only load the main content of the page between transitions. It's the quick and easiest way I know to have a nice transition without worrying about Ajax complications, you can build a normal PW site and have the plugin on top of it. But I did use a bit more Ajax on the website to have things like page views and user bookmarks being recorded in a db table. Do you want to know more about it? Link to comment Share on other sites More sharing options...
Zeka Posted April 5, 2017 Share Posted April 5, 2017 Oh.. I have been thinking that pages are loaded via ajax and Smoothstate is used only for animation. I have to look closely to this plugin as it looks awesome. Offcourse I want. If you have time to share some details, it would be great!!! Link to comment Share on other sites More sharing options...
Sergio Posted April 5, 2017 Author Share Posted April 5, 2017 Yep, it's a great plugin, but I'm not using its animations capabilities at all. Sure thing, I'll find a time to write about how to handle page views in a procached static page then! Link to comment Share on other sites More sharing options...
Robin S Posted April 5, 2017 Share Posted April 5, 2017 8 hours ago, Sérgio said: Very strange you had problems in the book section rendering, could you tell me what browser you used? I'm using a Mac and also tested in Firefox on Ubuntu and Edge and IE11 on Windows 10. I tested in Firefox and Chrome on Windows. But I would expect the same for all browsers because the issues are in the source code. Odd that you don't see them at your end - maybe I'm seeing cached content and you're not. 1. "Book recommendations" item missing expected content - probably just needs some if() conditions. 2. Side column: you have a mismatch between large/medium column classes, meaning the side column wraps under the main column but remains narrow at medium device width. 3. Goodreads link Link to comment Share on other sites More sharing options...
Sergio Posted April 5, 2017 Author Share Posted April 5, 2017 Very strange indeed! I think you have cache on your side as I see a different <main> tag on https://ricardo-vargas.com/books/recommendations/, see: Did you visited the site when it was running on beta.ricardo-vargas.com? Link to comment Share on other sites More sharing options...
Sergio Posted April 5, 2017 Author Share Posted April 5, 2017 Stop the press! @Robin S I've found the error, is on books/ root page instead! Working on it right now, many thanks! Link to comment Share on other sites More sharing options...
Robin S Posted April 5, 2017 Share Posted April 5, 2017 I am referring to the Books parent page: https://ricardo-vargas.com/books/ Edit: we posted simultaneously Link to comment Share on other sites More sharing options...
Sergio Posted April 5, 2017 Author Share Posted April 5, 2017 6 minutes ago, Robin S said: I am referring to the Books parent page: https://ricardo-vargas.com/books/ Edit: we posted simultaneously Yep! Just fixed it. Could you verify, please? https://ricardo-vargas.com/books/ Link to comment Share on other sites More sharing options...
Robin S Posted April 5, 2017 Share Posted April 5, 2017 7 minutes ago, Sérgio said: Just fixed it. Could you verify, please? https://ricardo-vargas.com/books/ Did you clear the ProCache document cache? Still seeing the missing content issue in "Book recommendations" and the malformed Goodreads link. Column layout is fixed though. Link to comment Share on other sites More sharing options...
Sergio Posted April 5, 2017 Author Share Posted April 5, 2017 Yep, now I did. Should be fixed now. Many thanks, Robin! I appreciate it! Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now