- MetaZola2021-05-20T00:00:00+00:00https://www.fullstackstanley.com/tags/meta/atom.xmlNew website for 20212021-05-20T00:00:00+00:002021-05-20T00:00:00+00:00https://www.fullstackstanley.com/articles/new-website/<p>As is customary for web developer blogs, I spend more time building the website than I do blogging.</p>
<span id="continue-reading"></span><figure class="figure ">
<img src="/images/new-site.png"
alt="The new website available in light and dark mode">
<figcaption>The new website available in light and dark mode</figcaption>
</figure>
<p>That said, there were a few issues with my previous site that made me want a refresh.</p>
<ul>
<li>Comments weren't always loading.</li>
<li>No call to actions or even social links!</li>
<li>Formatting wasn't always quite right, especially with syntax highlighting.</li>
<li>Ability to link up series' of articles (Like dev.to).</li>
<li>Add warning disclaimer to old posts.</li>
</ul>
<figure class="figure ">
<img src="/images/new-article-page.png"
alt="A preview of how old posts and series' look">
<figcaption>A preview of how old posts and series' look</figcaption>
</figure>
<p>Anyway, I've rebuilt the site with <a href="https://getzola.org">Zola</a> and <a href="https://tailwindui.com">TailwindUI</a> and I'm pretty pleased with it.</p>
<p>I'm promoting my apps a bit more with it and my social media presence.</p>
<p>As a bonus, it has a native dark mode!</p>
<h2 id="the-old-website">The old website</h2>
<p>Just for kicks, here's what the old website looked like. It was made with a template and used Nuxt.js + CraftCMS for the headless CMS.</p>
<figure class="figure ">
<img src="/images/old-site.png"
alt="The old website">
<figcaption>The old website</figcaption>
</figure>
<p>And here's the first website! This one was built with Middleman, a Ruby static site generator. Back in 2013.</p>
<figure class="figure ">
<img src="/images/first-site.png"
alt="The first iteration of Full Stack Stanley">
<figcaption>The first iteration of Full Stack Stanley</figcaption>
</figure>
Making moderation easy2015-04-06T00:00:00+00:002015-04-06T00:00:00+00:00https://www.fullstackstanley.com/articles/making-moderation-easy/<p>For just over a year I've been working on a website called Eurekar. To describe it briefly, it's a cool little website which has news articles for cars, a fairly complex article search and another search for UK car dealerships.</p>
<span id="continue-reading"></span>
<p>I have built an insane amount of content management systems in Laravel but what makes Eurekar unique is that the content is pulled from an external XML feed rather than created first hand in the CMS.</p>
<p>My first thoughts that were that having the content brought in from an external system would make things easier. If the content is made elsewhere then there is no need for an administration area. Unfortunately, due to the feed being out of my control the opposite is true and moderation has become more crucial than ever.</p>
<p>Some of the hurdles this brings include:</p>
<ul>
<li>Keeping the website's content up to date with the feed.</li>
<li>XML data not having the ideal structure.</li>
<li>Difficulty importing certain characters from the XML into MySQL.</li>
<li>Parsing XML data in general.</li>
</ul>
<p>There is two other issues that were by the far the most difficult to deal with. </p>
<ol>
<li>We often get articles with the same images because different authors can write articles about the same cars. Because of this they use same press release images. It can look silly having the same thumbnail show up 2-3 times in a list of articles so it's important that they show different images.</li>
<li>On a similar note, on certain pages such as the home page we didn't want multiple articles showing for the same cars so as to show a wider variety.</li>
</ol>
<p>As all of these issues cropped up it gradually became clear that being able to moderate the website easily was incredibly important.</p>
<h2 id="editing-article-content">Editing Article Content</h2>
<p>The XML feed is fetched every 30 minutes with a cron job that uses PHP's SimpleXML extension to parse it. We have to run a bunch of character replacements on this feed so that we don't get any issues with certain symbols. Even with this in place the £ symbol occasionally manages to elude me which is why I wanted editing articles to be incredibly quick and simple.</p>
<p>If you take a look at this page as an example <a href="http://eurekar.co.uk/articles/2015-04-03/mercedes-scores-a-triple">Mercedes scores a triple</a> Below is a screen shot of how it looks when logged in as an administrator.</p>
<p><img src="https://i.imgur.com/EvJxSGp.png" alt="Quick edit" /></p>
<p>On the left side there are 2 buttons: Quick Edit and Full Edit. Full Edit takes you to the admin area for editing all of the content of the article. Then there's quick edit which uses jQuery to bring up the right side of the image. Here a user can edit the title and the content on the same page which is perfect for fixing minor grammatical errors. The save button returns the administrator back to the normal page after the content is updated.</p>
<h2 id="editing-image-order">Editing Image Order</h2>
<p>Very often an image of a car boot gets uploaded first from the feed and therefore becomes the image that shows up on all of the article thumbnails. Obviously this isn't ideal. A car boot is not what our readers are initially interested in. What make matters more difficult is that articles sometimes have the same images and we wanted to avoid showing duplicates images on pages which listed articles.</p>
<p>There are two parts to this solution. The easiest part was allowing administrators to reorder images.</p>
<p><img src="https://i.imgur.com/1TCGmuD.png" alt="Image reorder" /></p>
<p>The above screenshot is how the image gallery looks as an administrator. The green button uses HTML5 drag and drop to sort image ordering and is updated via an AJAX request when an image is dropped from the mouse drag. The pause button toggles the image being viewable as a thumbnail on a list of articles (I'll get to why this is important in a moment). The bin button deletes the image entirely which is useful when a low quality image is uploaded.</p>
<p>Now to the more challenging problem: preventing duplicate images from being shown on a list of articles. Eurekar has many sections which list articles. Some articles might have the same preferred first image (If the images came from the same press release) but they may not always appear in the same sections.</p>
<p>In an ideal situation the next article which wants to use the same image needs to skip to the next image in it's gallery. This is why image reordering and the pause toggle button from earlier are important. This is how we can make sure the best images get rotated on the website.</p>
<p>This is probably the most irregular code I've had to create in Laravel and in honesty I am not 100% happy with how I implemented it. Here's a snippet of code which generates JSON for our "View More" AJAX requests. This code sits in a repository and is called by methods for different sections of the website.</p>
<pre data-lang="php" style="background-color:#2b303b;color:#c0c5ce;" class="language-php "><code class="language-php" data-lang="php"><span>
</span><span style="color:#ab7967;"><?php
</span><span style="color:#b48ead;">protected function </span><span style="color:#8fa1b3;">generateJSON</span><span>($</span><span style="color:#bf616a;">articles</span><span>, $</span><span style="color:#bf616a;">hide_from</span><span>)
</span><span>{
</span><span> $</span><span style="color:#bf616a;">c </span><span>= </span><span style="color:#b48ead;">new </span><span>\Illuminate\Database\Eloquent\</span><span style="color:#ebcb8b;">Collection</span><span>;
</span><span> $</span><span style="color:#bf616a;">image_index </span><span>= </span><span style="color:#d08770;">0</span><span>;
</span><span> $</span><span style="color:#bf616a;">used_images </span><span>= [];
</span><span> </span><span style="color:#b48ead;">foreach</span><span>($</span><span style="color:#bf616a;">articles </span><span>as $</span><span style="color:#bf616a;">article</span><span>) {
</span><span> </span><span style="color:#b48ead;">foreach</span><span>($</span><span style="color:#bf616a;">article</span><span>-></span><span style="color:#bf616a;">images </span><span>as $</span><span style="color:#bf616a;">image</span><span>) {
</span><span> </span><span style="color:#b48ead;">if</span><span>(</span><span style="color:#96b5b4;">in_array</span><span>($</span><span style="color:#bf616a;">image</span><span>-></span><span style="color:#bf616a;">filename</span><span>, $</span><span style="color:#bf616a;">used_images</span><span>)) {
</span><span> $</span><span style="color:#bf616a;">image_index</span><span>++;
</span><span> } </span><span style="color:#b48ead;">else </span><span>{
</span><span> $</span><span style="color:#bf616a;">used_images</span><span>[] = $</span><span style="color:#bf616a;">image</span><span>-></span><span style="color:#bf616a;">filename</span><span>;
</span><span> </span><span style="color:#b48ead;">break</span><span>;
</span><span> }
</span><span> }
</span><span> </span><span style="color:#b48ead;">if</span><span>($</span><span style="color:#bf616a;">image_index </span><span>>= $</span><span style="color:#bf616a;">article</span><span>-></span><span style="color:#bf616a;">images</span><span>-></span><span style="color:#bf616a;">count</span><span>()) {
</span><span> </span><span style="color:#b48ead;">foreach</span><span>($</span><span style="color:#bf616a;">article</span><span>-></span><span style="color:#bf616a;">images</span><span>-></span><span style="color:#bf616a;">slice</span><span>(</span><span style="color:#d08770;">0</span><span>, $</span><span style="color:#bf616a;">image_index</span><span>) as $</span><span style="color:#bf616a;">image</span><span>) {
</span><span> </span><span style="color:#b48ead;">if</span><span>($</span><span style="color:#bf616a;">key </span><span>= </span><span style="color:#96b5b4;">array_search</span><span>($</span><span style="color:#bf616a;">image</span><span>-></span><span style="color:#bf616a;">filename</span><span>, $</span><span style="color:#bf616a;">used_images</span><span>) !== </span><span style="color:#d08770;">false</span><span>) {
</span><span> </span><span style="color:#96b5b4;">unset</span><span>($</span><span style="color:#bf616a;">used_images</span><span>[$</span><span style="color:#bf616a;">key</span><span>]);
</span><span> }
</span><span> }
</span><span> $</span><span style="color:#bf616a;">image_index </span><span>= </span><span style="color:#d08770;">0</span><span>;
</span><span> }
</span><span> $</span><span style="color:#bf616a;">blurb </span><span>= </span><span style="color:#bf616a;">word_slice</span><span>($</span><span style="color:#bf616a;">article</span><span>-></span><span style="color:#bf616a;">content</span><span>, </span><span style="color:#d08770;">490</span><span>);
</span><span> $</span><span style="color:#bf616a;">c</span><span>-></span><span style="color:#bf616a;">add</span><span>([
</span><span> '</span><span style="color:#a3be8c;">id</span><span>' => $</span><span style="color:#bf616a;">article</span><span>-></span><span style="color:#bf616a;">id</span><span>,
</span><span> '</span><span style="color:#a3be8c;">title</span><span>' => $</span><span style="color:#bf616a;">article</span><span>-></span><span style="color:#bf616a;">title</span><span>,
</span><span> '</span><span style="color:#a3be8c;">slug</span><span>' => $</span><span style="color:#bf616a;">article</span><span>-></span><span style="color:#bf616a;">slug</span><span>,
</span><span> '</span><span style="color:#a3be8c;">url</span><span>' => </span><span style="color:#bf616a;">route</span><span>('</span><span style="color:#a3be8c;">articles.show</span><span>', $</span><span style="color:#bf616a;">article</span><span>-></span><span style="color:#bf616a;">slug</span><span>),
</span><span> '</span><span style="color:#a3be8c;">content</span><span>' => $</span><span style="color:#bf616a;">article</span><span>-></span><span style="color:#bf616a;">content</span><span>,
</span><span> '</span><span style="color:#a3be8c;">blurb</span><span>' => $</span><span style="color:#bf616a;">blurb</span><span>,
</span><span> '</span><span style="color:#a3be8c;">published_at</span><span>' => $</span><span style="color:#bf616a;">article</span><span>-></span><span style="color:#bf616a;">published_at</span><span>-></span><span style="color:#bf616a;">toDateTimeString</span><span>(),
</span><span> '</span><span style="color:#a3be8c;">filename</span><span>' => $</span><span style="color:#bf616a;">article</span><span>-></span><span style="color:#bf616a;">images</span><span>[$</span><span style="color:#bf616a;">image_index</span><span>]-></span><span style="color:#bf616a;">filename</span><span>,
</span><span> '</span><span style="color:#a3be8c;">full_image</span><span>' => </span><span style="color:#ebcb8b;">Config</span><span>::</span><span style="color:#bf616a;">get</span><span>('</span><span style="color:#a3be8c;">assets.aws</span><span>').</span><span style="color:#ebcb8b;">Config</span><span>::</span><span style="color:#bf616a;">get</span><span>('</span><span style="color:#a3be8c;">assets.image-medium</span><span>').$</span><span style="color:#bf616a;">article</span><span>-></span><span style="color:#bf616a;">images</span><span>[$</span><span style="color:#bf616a;">image_index</span><span>]-></span><span style="color:#bf616a;">filename</span><span>,
</span><span> '</span><span style="color:#a3be8c;">thumbnail</span><span>' => </span><span style="color:#ebcb8b;">Config</span><span>::</span><span style="color:#bf616a;">get</span><span>('</span><span style="color:#a3be8c;">assets.aws</span><span>').</span><span style="color:#ebcb8b;">Config</span><span>::</span><span style="color:#bf616a;">get</span><span>('</span><span style="color:#a3be8c;">assets.image-small</span><span>').$</span><span style="color:#bf616a;">article</span><span>-></span><span style="color:#bf616a;">images</span><span>[$</span><span style="color:#bf616a;">image_index</span><span>]-></span><span style="color:#bf616a;">filename</span><span>,
</span><span> '</span><span style="color:#a3be8c;">hide_from</span><span>' => $</span><span style="color:#bf616a;">hide_from</span><span>,
</span><span> ]);
</span><span> }
</span><span> </span><span style="color:#b48ead;">return </span><span>[
</span><span> '</span><span style="color:#a3be8c;">total</span><span>' => $</span><span style="color:#bf616a;">articles</span><span>-></span><span style="color:#bf616a;">getTotal</span><span>(),
</span><span> '</span><span style="color:#a3be8c;">from</span><span>' => $</span><span style="color:#bf616a;">articles</span><span>-></span><span style="color:#bf616a;">getFrom</span><span>(),
</span><span> '</span><span style="color:#a3be8c;">to</span><span>' => $</span><span style="color:#bf616a;">articles</span><span>-></span><span style="color:#bf616a;">getTo</span><span>(),
</span><span> '</span><span style="color:#a3be8c;">articles</span><span>' => $</span><span style="color:#bf616a;">c</span><span>-></span><span style="color:#bf616a;">toArray</span><span>(),
</span><span> ];
</span><span>}
</span></code></pre>
<p>A paginated collection of articles is passed through to the method as well as a second paramater which isn't important to this problem - it is just a value which I need to pass to the JSON.</p>
<p>On line 4 I made a custom collection with <code>\Illuminate\Database\Eloquent\Collection</code> which is going to hold all of the data for the JSON API.</p>
<p>On lines 5-6 I've initiated 2 variables: <code>image_index</code> and <code>used_images</code> which will be a list of images that have been used so that I can keep track of when I need to show a the next image.</p>
<p>Through lines 7-38 I'm looping through all of the articles and then looping through every image in each article. If the image exists in the <code>used_images</code> array then I skip to the next image. If it doesn't exist then I add it to <code>used_images</code> and break the images loop.</p>
<p>The next if statement checks if the <code>image_index</code> is more than the amount of images available. This means there's no more images left to go through so I use <code>array_search</code> to remove all of the current articles images from the <code>used_images</code> array and set the index back to the beginning. This resets the images used for a certain selection and allows them to be rotated through again.</p>
<p>After all that hard work all that's left is to add the article, its main image and a few other useful attributes to the custom collection which will then be sent off as a JSON response.</p>
<h2 id="editing-article-listings">Editing article listings</h2>
<p>Lastly we wanted to be able to show more variety on certain pages of the website. This problem arose due to author's releasing articles about the same car at the same time. Meaning we occasionally get 3 Suzuki Celerio articles hogging the front page which isn't ideal. The only circumstance where we want 3 or more Suzuki Celerios to show in a list of articles is if a user searched for that car model specifically.</p>
<p>My solution for this is to have hide buttons for each article in an article list. Take for example the home page latest news shown below:</p>
<p><img src="https://i.imgur.com/XTul45t.png" alt="Hiding news" /></p>
<p>Each section of the website has a boolean field which dictates whether it can be shown on its page. When hide is pressed in a section then it can no longer be in the article listing for that section. There is a separate admin page to revert this change incase of hider's remorse.</p>
<h2 id="final-thoughts">Final Thoughts</h2>
<p>There's a lot of work that goes into making a good admin area and what I've shown you is just a tiny glimpse of the overall system.</p>
<p>I realise there is a severe lack of code in this article but I hope that you've at least found it insightful and that I've given you some ideas to work in to your own systems.</p>
February '15: Top Developer Tools and Services2015-02-28T00:00:00+00:002015-02-28T00:00:00+00:00https://www.fullstackstanley.com/articles/february-15-top-developer-tools-and-services/<p>Here we are at the last week of February and I haven't done my monthly edition of Top Developer Tools and Services. Shame on me.</p>
<span id="continue-reading"></span>
<p>I've spent many nights pondering over what I should put on this month's list and what I should omit for another month. I have just this moment decided to limit this edition to browser extensions.</p>
<p>Although I am an Opera/Chrome user I hardly feel it's fair to leave out Firefox users so I will try to post alternatives just for you guys as well.</p>
<p>If I had to pick five extensions I couldn't live without, five extensions to be stuck on an island with, they would be these listed below.</p>
<h2 id="lastpass">LastPass</h2>
<p>LastPass is my life saver for managing passwords.</p>
<p>There are so many websites that require authentication now. To think just one small website that doesn't adhere to modern password hashing practices could lead to you losing your email accounts, spamming your friends on social media and fraudulent purchases seems completely unfair. </p>
<p>For this reason LastPass absolutely has to be on my list.</p>
<ul>
<li><a href="https://chrome.google.com/webstore/detail/lastpass-free-password-ma/hdokiejnpimakedhajhdlcegeplioahd">Chrome</a></li>
<li><a href="https://addons.mozilla.org/en-us/firefox/addon/lastpass-password-manager/">Firefox</a></li>
</ul>
<h2 id="ublock-umatrix">µBlock/µMatrix</h2>
<p>µBlock is a lightweight ad blocker that works really well. I'm really glad this extension came along as I always get confused as to which variation of AdBlock I'm supposed to be using. They all seem to let various ads through anyway.</p>
<p>µBlock is for people that want an ad blocker that just works and µMatrix allows more refined control.</p>
<ul>
<li><a href="https://chrome.google.com/webstore/detail/%C2%B5block/cjpalhdlnbpafiamejdnhcphjbkeiagm?hl=en">µBlock - Chrome</a></li>
<li><a href="https://chrome.google.com/webstore/detail/%C2%B5matrix/ogfcmafjalglgifnmanfmnieipoejdcf?hl=en">µMatrix - Chrome</a></li>
<li><a href="https://github.com/gorhill/uBlock">µBlock - Firefox</a></li>
</ul>
<h2 id="stayfocusd">StayFocusd</h2>
<p>This little extension pushes me to work on my own projects outside of work - or at least stop me from browsing Reddit all night on my computer. </p>
<p>Jokes aside, I really do see an increase in my productivity in my personal projects thanks to this extension.</p>
<ul>
<li><a href="https://chrome.google.com/webstore/detail/stayfocusd/laankejkbhbdhmipfmgcngdelahlfoji?hl=en">Chrome</a></li>
<li><a href="https://addons.mozilla.org/en-us/firefox/addon/leechblock/">Firefox - LeechBlock</a></li>
</ul>
<h2 id="jsonview-var-dumpling">JsonView / Var_dumpling</h2>
<p>I group these together as they do pretty much the same thing for different languages. JSON viewer for seeing nicely highlighted JSON and var_dumpling for for formatting PHP <code>var_dump</code>s.</p>
<ul>
<li><a href="https://chrome.google.com/webstore/detail/jsonview/chklaanhfefbnpoihckbnefhakgolnmc/reviews?hl=en">Chrome- JSONView</a></li>
<li><a href="https://chrome.google.com/webstore/detail/vardumpling/aikblkmigebodlhkdepmfmgdgmbokkdn?hl=en">Chrome - var_dumpling</a></li>
<li><a href="https://addons.mozilla.org/en-Us/firefox/addon/jsonview/">Firefox - JSONView</a></li>
<li><a href="https://github.com/alexnaspo/var_dumpling">Firefox - var_dumpling</a></li>
</ul>
<h2 id="postman">Postman</h2>
<p>I've mentioned this extension in several articles already and I seriously love it. If you create, maintain or consume API's you need this extension in your life.</p>
<p>Unfortunately, this extension doesn't work with Opera (my current browser) but I love it that much that I will open Chrome just to use it.</p>
<ul>
<li><a href="https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=en">Chrome</a></li>
<li><a href="https://addons.mozilla.org/en-us/firefox/addon/restclient/">Firefox - RESTClient</a></li>
<li><a href="https://addons.opera.com/en-gb/extensions/details/restman/?display=en">Opera - RestMan</a></li>
</ul>
<h2 id="bonus-opera-extension-for-chrome">Bonus: Opera extension for Chrome</h2>
<p>Opera 12 was possibly the best browser of it's time. This browser had functionality that Chrome couldn't dream of and Firefox had half baked extensions for. Then Opera 15 was announced and I was essentially forced to switch to Chrome due to the lack of features.</p>
<p>Don't get me wrong - I actually really like Chrome now. It has some incredible developer tools. But I've always keeped my eye on Opera's development. Recently I decided to make the switch back to Opera (At the time of writing they are now on Opera 27) and quite frankly I couldn't have done it without <a href="https://addons.opera.com/en-gb/extensions/details/download-chrome-extension-9/">Download Chrome Extension</a>.</p>
<p>This extension lets you download Chrome extensions from the Chrome store just like you were on Chrome itself! I have only had one issue and that's with Postman App which I now open Chrome to use when I need to.</p>
January ’15: Top Developer Tools and Services2015-01-15T00:00:00+00:002015-01-15T00:00:00+00:00https://www.fullstackstanley.com/articles/january-15-top-developer-tools-and-services/<p>Now that I'm increasing the amount of blogs that I write I want to start giving credit to stuff that I use every day.</p>
<p>These aren't always going to be programming or web related. Many of them are to do with organisation and learning. I may even throw in some fun stuff, too!</p>
<h2 id="mailcatcher"><a href="http://mailcatcher.me/">Mailcatcher</a></h2>
<p>First off the bat: Mailcatcher. A Ruby gem for testing emails on your local machine. It works by catching the emails sent through a local SMTP server and comes with a simple-but-awesome GUI for previewing your emails.</p>
<p>As a bonus it already comes installed with <a href="https://puphpet.com/">PuPHPet</a> which I use to set up my PHP stacks.</p>
<p>If you don’t use PHP or PuPHPet it’s still a breeze to install. So if you’re a developer that makes applications with emails I really recommend you give it a shot.</p>
<span id="continue-reading"></span><h2 id="gollum"><a href="https://github.com/gollum/gollum">Gollum</a></h2>
<p>Gollum is a wiki system built on top of Git. It’s incredibly minimalistic and requires you to know markdown but as a programmer it’s literally all I need.</p>
<p>I set up sections for all the languages and tools I learn. Subsections for areas that require a lot of notes and sometimes subsections just for specific versions of languages/frameworks.</p>
<p>Personally I find writing down what I learn really helps reinforce what I’ve learned. As a bonus, when I come to start using the tool with a project I now have documentation written in a way I can understand perfectly all on my local machine.</p>
<h2 id="asana"><a href="https://asana.com/">Asana</a></h2>
<p>When I came to start using this I was looking for a tool to manage tasks at my job. I’ve used other solutions like Trello and Spiceworks but left feeling unsatisfied. I really enjoy Asana’s user interface and in combination with Toggl I have all my requirements met.</p>
<h2 id="toggl"><a href="https://www.toggl.com/">Toggl</a></h2>
<p>Toggl by itself is a pretty good timer app but quite frankly I would not bother with it if the Chrome Toggl extension, <a href="https://chrome.google.com/webstore/detail/toggl-button/oejgccbfbmkkpaidnkphaiaecficdnfn?hl=en">Toggl Button</a> didn’t exist.</p>
<p>Toggl button injects Toggl timers in to various websites including Asana and Github. </p>
<p>The timer functionality is the only issue I have with Asana so this extension makes me incredibly happy. I just wish they would make extensions for other browsers so that everyone can appreciate it! </p>
<h2 id="balsamiq-79"><a href="https://balsamiq.com/">Balsamiq</a> ($79)</h2>
<p>Whenever I'm creating a new web application I create mock ups of how I want the interface to be structured. Balsamiq is my go to tool for this purpose.</p>
<p>A much younger version of myself would think it’s a complete waste of time. I’d much rather get stuck in to the code and get the app completed as soon as possible.</p>
<p>Present me knows better. The time it takes to make a few scribbles in Balsamiq is negligible and comes with three major added bonuses:</p>
<ol>
<li>It allows me to plan the flow of the application’s GUI</li>
<li>It allows me to think about how I’m going to structure the code once I start it.</li>
<li>It flags up potential speed bumps. More often than not I’ll think of an issue or two that would have never occurred to me until I had hit them. This let’s me plan my way around them and is a huge time saver.</li>
</ol>
<h2 id="that-s-all-for-this-month">That’s all for this month</h2>
<p>I’ve gotta pace myself y’know? There are so many languages, tools and services that I use that it’s really unfair to highlight the above five but I’m doing it anyway!</p>
<p>I’ll post some more in February. I may even dig in to my favourite programming languages!</p>