<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Duane Blake</title>
	<atom:link href="http://duaneblake.co.uk/feed/" rel="self" type="application/rss+xml" />
	<link>https://duaneblake.co.uk</link>
	<description>Front end web developer from Birmingham</description>
	<lastBuildDate>Mon, 17 Nov 2025 18:44:53 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.5</generator>
	<item>
		<title>How to Automatically Delete Old Records in Laravel</title>
		<link>https://duaneblake.co.uk/laravel/how-to-automatically-delete-old-records-in-laravel/</link>
					<comments>https://duaneblake.co.uk/laravel/how-to-automatically-delete-old-records-in-laravel/#respond</comments>
		
		<dc:creator><![CDATA[Duane Blake]]></dc:creator>
		<pubDate>Mon, 17 Nov 2025 18:44:10 +0000</pubDate>
				<category><![CDATA[Laravel]]></category>
		<guid isPermaLink="false">https://duaneblake.co.uk/?p=1245</guid>

					<description><![CDATA[<p>There may be circumstances in your application where you need to delete old or no longer needed data. This could be for reasons such as improving performance or keeping your data fresh. Laravel has a trait which is perfect for this called Prunable, which allows you to set up a command to delete records from [&#8230;]</p>
<p>The post <a href="https://duaneblake.co.uk/laravel/how-to-automatically-delete-old-records-in-laravel/">How to Automatically Delete Old Records in Laravel</a> first appeared on <a href="https://duaneblake.co.uk">Duane Blake</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>There may be circumstances in your application where you need to delete old or no longer needed data. This could be for reasons such as improving performance or keeping your data fresh. Laravel has a trait which is perfect for this called Prunable, which allows you to set up a command to delete records from the database.</p>



<figure class="wp-block-image postImg"><a href="https://duaneblake.co.uk/laravel/how-to-automatically-delete-old-records-in-laravel/"><img fetchpriority="high" decoding="async" width="600" height="200" src="https://duaneblake.co.uk/wp-content/uploads/2025/11/Automating-Database-Cleanup-with-Laravel-Prunable.png" alt="Automating Database Cleanup with Laravel Prunable" class="wp-image-1246" srcset="https://duaneblake.co.uk/wp-content/uploads/2025/11/Automating-Database-Cleanup-with-Laravel-Prunable.png 600w, https://duaneblake.co.uk/wp-content/uploads/2025/11/Automating-Database-Cleanup-with-Laravel-Prunable-300x100.png 300w" sizes="(max-width: 600px) 100vw, 600px" /></a></figure>



<span id="more-1245"></span>



<p>To use the Prunable trait in your model, you create a function called <code>prunable</code> which creates a query to fetch all the records that need to be deleted. You then create an artisan schedule which will run and delete the data from your database at set times.</p>



<pre class="wp-block-code"><code>&lt;?php

namespace App\Models;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Prunable;

class Tickets extends Model 
{
	use Prunable;
	
	public function prunable(): Builder
	{
		return static::where('completed_at', &lt;=', now()->subDays(30));
	}

}</code></pre>



<p>What the code above does is slightly different from a typical Laravel model. The first difference is pulling in the Prunable trait:</p>



<pre class="wp-block-code"><code>use Illuminate\Database\Eloquent\Prunable;</code></pre>



<p>The next step is setting up the Prunable trait to allow us to use the prunable methods in our model:</p>



<pre class="wp-block-code"><code>use Prunable;</code></pre>



<p>Now for the logic part: we create a public function, and it needs to be called <code>prunable</code>. This function builds the query for the criteria by which we wish to delete our data. In my example, it will delete all records which have a <code>completed_at</code> date of 30 days ago or more.</p>



<h2 class="wp-block-heading">Running the Prune Command</h2>



<p>Once the model is set up, you can run the following command from your terminal. This command detects all Prunable models in your application and deletes the matching records:</p>



<pre class="wp-block-code"><code>php artisan model:prune</code></pre>



<p>To automate this, I typically add an entry to routes/console.php to run the prune command daily. For example, to run it every day at 18:30:</p>



<pre class="wp-block-code"><code>Schedule::command('model:prune')->dailyAt('18:30');</code></pre>



<p>For further reading, check out the official documentation: </p>



<ul class="wp-block-list">
<li><a href="https://laravel.com/docs/eloquent#pruning-models">https://laravel.com/docs/eloquent#pruning-models</a></li>



<li><a href="https://api.laravel.com/docs/master/Illuminate/Database/Eloquent/Prunable.html">https://api.laravel.com/docs/master/Illuminate/Database/Eloquent/Prunable.html</a></li>
</ul><p>The post <a href="https://duaneblake.co.uk/laravel/how-to-automatically-delete-old-records-in-laravel/">How to Automatically Delete Old Records in Laravel</a> first appeared on <a href="https://duaneblake.co.uk">Duane Blake</a>.</p>]]></content:encoded>
					
					<wfw:commentRss></wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>My Go-To Secondary Job for each character in  Octopath Traveler 2</title>
		<link>https://duaneblake.co.uk/gaming/my-go-to-secondary-job-for-each-character-in-octopath-traveler-2/</link>
					<comments>https://duaneblake.co.uk/gaming/my-go-to-secondary-job-for-each-character-in-octopath-traveler-2/#respond</comments>
		
		<dc:creator><![CDATA[Duane Blake]]></dc:creator>
		<pubDate>Sat, 18 Oct 2025 14:02:56 +0000</pubDate>
				<category><![CDATA[Gaming]]></category>
		<category><![CDATA[rpg]]></category>
		<category><![CDATA[switch]]></category>
		<guid isPermaLink="false">https://duaneblake.co.uk/?p=1231</guid>

					<description><![CDATA[<p>Octopath Traveler 2 is, to me, a best-in-class game and one of the most complete RPGs I&#8217;ve ever played. Unless you are playing boss fights, the battles don&#8217;t last long, especially with the right build. It&#8217;s one of those games where by lining up your secondary jobs, skills, and weapons, any of the eight characters [&#8230;]</p>
<p>The post <a href="https://duaneblake.co.uk/gaming/my-go-to-secondary-job-for-each-character-in-octopath-traveler-2/">My Go-To Secondary Job for each character in  Octopath Traveler 2</a> first appeared on <a href="https://duaneblake.co.uk">Duane Blake</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Octopath Traveler 2 is, to me, a best-in-class game and one of the most complete RPGs I&#8217;ve ever played. Unless you are playing boss fights, the battles don&#8217;t last long, especially with the right build. It&#8217;s one of those games where by lining up your secondary jobs, skills, and weapons, any of the eight characters can break the game.</p>



<figure class="wp-block-image size-full postImg"><a href="https://duaneblake.co.uk/gaming/my-go-to-secondary-job-for-each-character-in-octopath-traveler-2/"><img decoding="async" width="600" height="200" src="https://duaneblake.co.uk/wp-content/uploads/2025/10/octopath.png" alt="" class="wp-image-1240" srcset="https://duaneblake.co.uk/wp-content/uploads/2025/10/octopath.png 600w, https://duaneblake.co.uk/wp-content/uploads/2025/10/octopath-300x100.png 300w" sizes="(max-width: 600px) 100vw, 600px" /></a></figure>



<span id="more-1231"></span>



<p>I&#8217;ve listed the secondary jobs I used for each character. One thing to mention is that I tried to make sure there were no duplicates in the secondary jobs. Just stating the job isn&#8217;t the full story, as skills, weapons, and overall team makeup also affect a character&#8217;s build.</p>



<h2 class="wp-block-heading">Characters</h2>



<h3 class="wp-block-heading"><strong>Hikari &#8211; Armsmaster</strong></h3>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://duaneblake.co.uk/wp-content/uploads/2025/10/hikari.png"><img decoding="async" width="600" height="200" src="https://duaneblake.co.uk/wp-content/uploads/2025/10/hikari.png" alt="" class="wp-image-1232" srcset="https://duaneblake.co.uk/wp-content/uploads/2025/10/hikari.png 600w, https://duaneblake.co.uk/wp-content/uploads/2025/10/hikari-300x100.png 300w" sizes="(max-width: 600px) 100vw, 600px" /></a></figure></div>


<p>Hikari as an Armsmaster offers so much versatility. The way I use Hikari is to find an opponent&#8217;s weakness and then exploit it. My main strategy for him was breaking the opponent. I always tended to go for Sixfold Strike to find the enemy&#8217;s weakness. Once found, I would use a mixture of learned skills and Hikari&#8217;s core skills, such as Aggressive Slash, Wild Smash, Frenzied Fire, and Divine Dual Edge. Once the enemy was broken, based on their weakness, I would then use Brand&#8217;s Blade or one of the powerful Armsmaster weapon skills.</p>



<h3 class="wp-block-heading"><strong>Throné &#8211; Merchant</strong></h3>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://duaneblake.co.uk/wp-content/uploads/2025/10/throne.png"><img loading="lazy" decoding="async" width="600" height="200" src="https://duaneblake.co.uk/wp-content/uploads/2025/10/throne.png" alt="" class="wp-image-1233" srcset="https://duaneblake.co.uk/wp-content/uploads/2025/10/throne.png 600w, https://duaneblake.co.uk/wp-content/uploads/2025/10/throne-300x100.png 300w" sizes="auto, (max-width: 600px) 100vw, 600px" /></a></figure></div>


<p>My style for Throné was pure speed with buffs and debuffs. I was often using HP Thief, Armor Corrosive, and Sidestep. Once the enemy was broken, I would either use Disguise to mimic a teammate or unleash Aeber&#8217;s Reckoning. Something I did early in the game but stopped in the late-game was using the Merchant&#8217;s Hired Help. That skill more or less just takes a massive chunk out of my opponent, and I felt it was cheating because of the amount of damage it did.</p>



<h3 class="wp-block-heading"><strong>Agnea &#8211; Inventor</strong></h3>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://duaneblake.co.uk/wp-content/uploads/2025/10/agnea.png"><img loading="lazy" decoding="async" width="600" height="200" src="https://duaneblake.co.uk/wp-content/uploads/2025/10/agnea.png" alt="" class="wp-image-1234" srcset="https://duaneblake.co.uk/wp-content/uploads/2025/10/agnea.png 600w, https://duaneblake.co.uk/wp-content/uploads/2025/10/agnea-300x100.png 300w" sizes="auto, (max-width: 600px) 100vw, 600px" /></a></figure></div>


<p>Agnea plays a similar role to Throné, buffing the team, and she can also provide support with Ruinous Kick. The reason I added Inventor to Agnea is due to her Latent Power, which allows her to apply her attack and support skills to multiple characters. So, I often used it for offering healing with Arkar&#8217;s Coil, attacking enemies with Hastening Hammer, or using Critical Scope if the enemy was broken.</p>



<h3 class="wp-block-heading"><strong>Castti &#8211; Cleric</strong></h3>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://duaneblake.co.uk/wp-content/uploads/2025/10/castri.png"><img loading="lazy" decoding="async" width="600" height="200" src="https://duaneblake.co.uk/wp-content/uploads/2025/10/castri.png" alt="" class="wp-image-1235" srcset="https://duaneblake.co.uk/wp-content/uploads/2025/10/castri.png 600w, https://duaneblake.co.uk/wp-content/uploads/2025/10/castri-300x100.png 300w" sizes="auto, (max-width: 600px) 100vw, 600px" /></a></figure></div>


<p>I used Castti as my core healer. With both Apothecary and Cleric, she had full coverage for healing and reviving teammates. In addition, with her Latent Power at max boost, I could give my team plenty of buffs, recover their health, or damage the enemy. She is also very powerful with an axe, having access to both Poison Axe and Drastic Measures.</p>



<h3 class="wp-block-heading"><strong>Osvald &#8211; Apothecary</strong></h3>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://duaneblake.co.uk/wp-content/uploads/2025/10/osvald.png"><img loading="lazy" decoding="async" width="600" height="200" src="https://duaneblake.co.uk/wp-content/uploads/2025/10/osvald.png" alt="" class="wp-image-1236" srcset="https://duaneblake.co.uk/wp-content/uploads/2025/10/osvald.png 600w, https://duaneblake.co.uk/wp-content/uploads/2025/10/osvald-300x100.png 300w" sizes="auto, (max-width: 600px) 100vw, 600px" /></a></figure></div>


<p>I know I said at the start of the article that with the right build, every character can be powerful, but I just couldn&#8217;t find a perfect build for Osvald. I feel magic attacks taper off toward the end of the game. So, I paired him with Apothecary to offer the team some healing. I chose against going with Cleric, as Apothecary gives Osvald an axe, giving him more weapon range. He does have a very useful attack, Elemental Barrage, which is useful to work out elemental weaknesses.</p>



<h3 class="wp-block-heading"><strong>Partitio &#8211; Arcanist</strong></h3>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://duaneblake.co.uk/wp-content/uploads/2025/10/parchio.png"><img loading="lazy" decoding="async" width="600" height="200" src="https://duaneblake.co.uk/wp-content/uploads/2025/10/parchio.png" alt="" class="wp-image-1237" srcset="https://duaneblake.co.uk/wp-content/uploads/2025/10/parchio.png 600w, https://duaneblake.co.uk/wp-content/uploads/2025/10/parchio-300x100.png 300w" sizes="auto, (max-width: 600px) 100vw, 600px" /></a></figure></div>


<p>Partitio is the most versatile character in the game; he thrives with any secondary job. I decided to give him Arcanist. Malice and Blessing are good for group-based dark and light attacks. But the magic in this build is Seal of Diffusion, which allows all skills that target Partitio to be applied to the whole team. So I would rotate between Rest and Sidestep, and enemies ended up not touching my characters. As mentioned in Throné&#8217;s build, I did use Hired Help when struggling but felt guilty afterwards!</p>



<h3 class="wp-block-heading"><strong>Ochette &#8211; Warrior</strong></h3>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://duaneblake.co.uk/wp-content/uploads/2025/10/ochette.png"><img loading="lazy" decoding="async" width="600" height="200" src="https://duaneblake.co.uk/wp-content/uploads/2025/10/ochette.png" alt="" class="wp-image-1238" srcset="https://duaneblake.co.uk/wp-content/uploads/2025/10/ochette.png 600w, https://duaneblake.co.uk/wp-content/uploads/2025/10/ochette-300x100.png 300w" sizes="auto, (max-width: 600px) 100vw, 600px" /></a></figure></div>


<p>Similar to Hikari, the way I used Ochette was for breaking characters with all the beasts that she&#8217;s captured. Once an enemy was broken and if I had 4 BP, I would then use powerful captured monsters or skills like <strong>Brand&#8217;s Blade</strong>. The Warrior job is used to give her more strength and access to powerful sword skills.</p>



<h3 class="wp-block-heading"><strong>Temenos &#8211; Conjurer</strong></h3>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://duaneblake.co.uk/wp-content/uploads/2025/10/terminous.png"><img loading="lazy" decoding="async" width="600" height="200" src="https://duaneblake.co.uk/wp-content/uploads/2025/10/terminous.png" alt="" class="wp-image-1239" srcset="https://duaneblake.co.uk/wp-content/uploads/2025/10/terminous.png 600w, https://duaneblake.co.uk/wp-content/uploads/2025/10/terminous-300x100.png 300w" sizes="auto, (max-width: 600px) 100vw, 600px" /></a></figure></div>


<p>Temenos is another support character. He heals, and if we know which element the enemies are weak to, we can use the Conjurer&#8217;s skills to imbue the party&#8217;s weapons with that element, allowing them to deal extra damage and exploit weaknesses with every attack.</p>



<h2 class="wp-block-heading">Final Thoughts</h2>



<p>There are multiple builds and playstyles for this game, but I feel these builds gave me the best balance, making the game range from a fun challenge to an absolute walkthrough.</p><p>The post <a href="https://duaneblake.co.uk/gaming/my-go-to-secondary-job-for-each-character-in-octopath-traveler-2/">My Go-To Secondary Job for each character in  Octopath Traveler 2</a> first appeared on <a href="https://duaneblake.co.uk">Duane Blake</a>.</p>]]></content:encoded>
					
					<wfw:commentRss></wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to Add a Custom Font to Your Laravel Project</title>
		<link>https://duaneblake.co.uk/laravel/how-to-add-a-custom-font-to-your-laravel-project/</link>
					<comments>https://duaneblake.co.uk/laravel/how-to-add-a-custom-font-to-your-laravel-project/#respond</comments>
		
		<dc:creator><![CDATA[Duane Blake]]></dc:creator>
		<pubDate>Sun, 30 Mar 2025 07:54:03 +0000</pubDate>
				<category><![CDATA[Laravel]]></category>
		<category><![CDATA[fonts]]></category>
		<category><![CDATA[tailwindcss]]></category>
		<guid isPermaLink="false">https://duaneblake.co.uk/?p=1195</guid>

					<description><![CDATA[<p>There may be occasions when you have to use a custom font, such as a brand font, in your Laravel Project. I&#8217;m going to go through the steps for adding a custom font to your project. In this example, I&#8217;m using the Laravel Starter kit with Livewire, but it should also work with React and [&#8230;]</p>
<p>The post <a href="https://duaneblake.co.uk/laravel/how-to-add-a-custom-font-to-your-laravel-project/">How to Add a Custom Font to Your Laravel Project</a> first appeared on <a href="https://duaneblake.co.uk">Duane Blake</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>There may be occasions when you have to use a custom font, such as a brand font, in your Laravel Project. I&#8217;m going to go through the steps for adding a custom font to your project.</p>



<figure class="wp-block-image size-full postImg"><a href="https://duaneblake.co.uk/laravel/how-to-add-a-custom-font-to-your-laravel-project/"><img loading="lazy" decoding="async" width="600" height="200" src="https://duaneblake.co.uk/wp-content/uploads/2025/03/Post.png" alt="" class="wp-image-1197" srcset="https://duaneblake.co.uk/wp-content/uploads/2025/03/Post.png 600w, https://duaneblake.co.uk/wp-content/uploads/2025/03/Post-300x100.png 300w" sizes="auto, (max-width: 600px) 100vw, 600px" /></a></figure>



<span id="more-1195"></span>



<p>In this example, I&#8217;m using the Laravel Starter kit with Livewire, but it should also work with React and Vue starter kits.</p>



<ol class="wp-block-list">
<li>In your Laravel application directory, create a new folder in resources called fonts. Once created, add your fonts to that folder.</li>



<li>Open the <span style="text-decoration: underline;">resources/js/app.js</span> file and place the code below. The code makes Vite aware that we have our fonts installed.</li>
</ol>



<pre class="wp-block-code"><code>import.meta.glob(&#91;

'../fonts/**',

]);</code></pre>



<ol class="wp-block-list" start="3">
<li>We now need to import the font into a stylesheet. In the following file, resources/css/app.css, use the font-face rule and replace FONTNAME with the name of your font.</li>
</ol>



<pre class="wp-block-code"><code>@font-face {
    font-family: 'FONTNAME';
    src: url('../fonts/FONTNAME.woff2') format('woff2'),
         url('../fonts/FONTNAME.otf') format('otf');
    font-weight: normal;
    font-style: normal;
}</code></pre>



<ol class="wp-block-list" start="4">
<li>I&#8217;m using Tailwindcss with the font installed in our application. We are going to create a new utility for our new font. Under the theme layer where your custom Taillwind settings are saved, add the following.</li>
</ol>



<pre class="wp-block-code"><code>    --font-FONTNAME: 'FONTNAME', sans-serif;</code></pre>



<ol class="wp-block-list" start="5">
<li>With that all added, go to your template, add the font to the required selector, and the page will render it correctly.</li>
</ol>



<pre class="wp-block-code"><code>&lt;h1 class="font-FONTNAME text-3xl"&gt;Hello World&lt;/h1&gt;</code></pre>



<p>That&#8217;s how to add a custom font to a Laravel application If you want to read more about this you go to the Laravel documentation  &#8211; <a href="https://laravel.com/docs/12.x/vite#blade-processing-static-assets">Processing Static Assets With Vite</a></p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="How to Add a Custom Font to Your Laravel Project" width="500" height="281" src="https://www.youtube.com/embed/A_rMPVQSohs?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure><p>The post <a href="https://duaneblake.co.uk/laravel/how-to-add-a-custom-font-to-your-laravel-project/">How to Add a Custom Font to Your Laravel Project</a> first appeared on <a href="https://duaneblake.co.uk">Duane Blake</a>.</p>]]></content:encoded>
					
					<wfw:commentRss></wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Beyond WordPress: First Thoughts on Using Statamic as a CMS.</title>
		<link>https://duaneblake.co.uk/wordpress/beyond-wordpress-first-thoughts-on-using-statamic-as-a-cms/</link>
					<comments>https://duaneblake.co.uk/wordpress/beyond-wordpress-first-thoughts-on-using-statamic-as-a-cms/#respond</comments>
		
		<dc:creator><![CDATA[Duane Blake]]></dc:creator>
		<pubDate>Thu, 20 Feb 2025 11:26:52 +0000</pubDate>
				<category><![CDATA[Wordpress]]></category>
		<category><![CDATA[Laravel]]></category>
		<category><![CDATA[Statamic]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">https://duaneblake.co.uk/?p=1188</guid>

					<description><![CDATA[<p>With all the issues with WordPress and WP Engine, I thought it would be a good opportunity to look at a couple of other CMS. For a while now, I&#8217;ve not been keen on the direction that WordPress has been heading in the past few releases, so I used this as a perfect opportunity to [&#8230;]</p>
<p>The post <a href="https://duaneblake.co.uk/wordpress/beyond-wordpress-first-thoughts-on-using-statamic-as-a-cms/">Beyond WordPress: First Thoughts on Using Statamic as a CMS.</a> first appeared on <a href="https://duaneblake.co.uk">Duane Blake</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>With all the issues with WordPress and WP Engine, I thought it would be a good opportunity to look at a couple of other CMS. For a while now, I&#8217;ve not been keen on the direction that WordPress has been heading in the past few releases, so I used this as a perfect opportunity to look at some other CMS.</p>



<figure class="wp-block-image size-full postImg"><a href="https://duaneblake.co.uk/wordpress/beyond-wordpress-first-thoughts-on-using-statamic-as-a-cms/"><img loading="lazy" decoding="async" width="600" height="200" src="https://duaneblake.co.uk/wp-content/uploads/2025/02/from-wordpress-tostatamic.png" alt="" class="wp-image-1189" srcset="https://duaneblake.co.uk/wp-content/uploads/2025/02/from-wordpress-tostatamic.png 600w, https://duaneblake.co.uk/wp-content/uploads/2025/02/from-wordpress-tostatamic-300x100.png 300w" sizes="auto, (max-width: 600px) 100vw, 600px" /></a></figure>



<span id="more-1188"></span>



<p>When looking for a new CMS to use, I&#8217;ve used Sanity, Joomla, Ghost, Drupal, and a few others. My main requirements were to be in the PHP ecosystem and have a true CMS experience. As much as I use Markdown, I manage several different sites for people with many different skill levels. I don&#8217;t want to train them to understand Markdown.</p>



<p>After looking around, I landed on either Statamic or Filament. They are both in the Laravel ecosystem. Although Filament isn&#8217;t a true CMS, the form builder can quickly spin up a CMS. However, Statamic is a CMS first, as I watched the demo videos. I feel confident that I could give that to my users, and they would easily be able to pick it up.</p>



<p>Statamic has been on my radar for a while, but what put me off was the price. I always thought WordPress was free; I&#8217;m not paying for a CMS. But the reality is that WordPress isn&#8217;t free, as by the time you buy advanced custom fields, WP forms, and a couple of other forms, the cost starts to add up. With Statamic, there is no fee if the site has only one user and only one form. Otherwise, there is a fee of $275 for the first year, and then the annual renewal fee is a much more reduced.</p>



<p>Installing Statamic and getting up and running takes much longer than the famous 5-minute WordPress install. The website suggests using the installer, which I couldn&#8217;t get to work due to a user error on my part. So, I installed it into a Laravel project.</p>



<p>I spent some time reading the documents and watching some videos on <a href="https://laracasts.com/series/learn-statamic-with-jack" title="">Laracast</a>  Statamic. If I&#8217;m being honest, there is quite a learning curve to getting the site up and running for users to start using.</p>



<p>Another aspect I like is the flat file CMS, which has the option to use or migrate to a traditional database. The CMS allows for plugins similar to those in WordPress. They seem to be a lot more mature than WordPress. The one I used on the demo site I built was one of the first-party ones, which allows the site to be generated as a Static Site, which is helpful for me for the marketing campaign site use.</p>



<p>When I looked at Statamic in the past, I could never understand why it was using Antlers&#8217; template system instead of Blade for templating. Now, using Antlers&#8217; templating system, it&#8217;s a very mature, powerful, and easy-to-understand system. A lot of the functions that I want to use are built in without the need to write some crazy PHP function to pull some data. Additionally, the blade option is still there if you are interested in using it.</p>



<p>Overall, There is a learning curve to get used to it, but the upside more than makes up for it. The templating system is so much easier to use than WordPress. The CMS is intuitive and straightforward for users. I  feel confident giving it to my users to manage the site. It is built on top of Laravel, so I can plug it into my existing Laravel projects or extend out any functionality if I need to.</p>



<h2 class="wp-block-heading">Further Information</h2>



<ul class="wp-block-list">
<li><a href="https://www.youtube.com/@FromWordPressToStatamic" title="From WordPress to Statamic Youtube Channel">From WordPress to Statamic Youtube Channel</a></li>



<li><a href="https://laracasts.com/series/learn-statamic-with-jack" title="">Learn Statamic with Jack</a></li>



<li><a href="https://www.youtube.com/watch?v=_IJ2G7I-U_A" title="Statamic Roundtable with Jack McDade, John O'Nolan, Caleb Porzio, &amp; Adam Wathan">Statamic Roundtable with Jack McDade, John O&#8217;Nolan, Caleb Porzio, &amp; Adam Wathan</a></li>
</ul><p>The post <a href="https://duaneblake.co.uk/wordpress/beyond-wordpress-first-thoughts-on-using-statamic-as-a-cms/">Beyond WordPress: First Thoughts on Using Statamic as a CMS.</a> first appeared on <a href="https://duaneblake.co.uk">Duane Blake</a>.</p>]]></content:encoded>
					
					<wfw:commentRss></wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Games I completed in 2024</title>
		<link>https://duaneblake.co.uk/gaming/games-i-completed-in-2024/</link>
					<comments>https://duaneblake.co.uk/gaming/games-i-completed-in-2024/#respond</comments>
		
		<dc:creator><![CDATA[Duane Blake]]></dc:creator>
		<pubDate>Mon, 30 Dec 2024 18:22:31 +0000</pubDate>
				<category><![CDATA[Gaming]]></category>
		<category><![CDATA[games]]></category>
		<guid isPermaLink="false">https://duaneblake.co.uk/?p=1159</guid>

					<description><![CDATA[<p>As we come to the end of the year, I wanted to reflect on some of the games I have completed. This year was a lot different for me, as I usually go back and replay games I completed before. But there is not one game on this list I have completed before. I&#8217;m also [&#8230;]</p>
<p>The post <a href="https://duaneblake.co.uk/gaming/games-i-completed-in-2024/">Games I completed in 2024</a> first appeared on <a href="https://duaneblake.co.uk">Duane Blake</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>As we come to the end of the year, I wanted to reflect on some of the games I have completed. This year was a lot different for me, as I usually go back and replay games I completed before. But there is not one game on this list I have completed before. I&#8217;m also trying to focus on finishing games from my backlog, as every year, it seems to get bigger and not go down. So, there are quite a few older titles on this list.</p>



<figure class="wp-block-image size-full postImg"><a href="https://duaneblake.co.uk/gaming/games-i-completed-in-2024/"><img loading="lazy" decoding="async" width="600" height="200" src="https://duaneblake.co.uk/wp-content/uploads/2025/01/games-completed-in-2024.png" alt="" class="wp-image-1180" srcset="https://duaneblake.co.uk/wp-content/uploads/2025/01/games-completed-in-2024.png 600w, https://duaneblake.co.uk/wp-content/uploads/2025/01/games-completed-in-2024-300x100.png 300w" sizes="auto, (max-width: 600px) 100vw, 600px" /></a></figure>



<span id="more-1159"></span>



<h2 class="wp-block-heading">Unicorn Overlord</h2>



<figure class="wp-block-image size-full"><a href="https://duaneblake.co.uk/wp-content/uploads/2025/01/Unicorn-Overlord.png"><img loading="lazy" decoding="async" width="600" height="200" src="https://duaneblake.co.uk/wp-content/uploads/2025/01/Unicorn-Overlord.png" alt="" class="wp-image-1168" srcset="https://duaneblake.co.uk/wp-content/uploads/2025/01/Unicorn-Overlord.png 600w, https://duaneblake.co.uk/wp-content/uploads/2025/01/Unicorn-Overlord-300x100.png 300w" sizes="auto, (max-width: 600px) 100vw, 600px" /></a></figure>



<p>Unicron Overlord is on my list of favourite games of all time. Given the various races, classes, and unit types to experiment with, I loved building my specific team and optimising my strategy. It&#8217;s one of those games where I kept telling myself, “Just one more map&#8221;. The developers&#8217; passion for this project shines through, from the world-building of the lore to the artwork of the characters. Vanillaware has done a phenomenal job with the thought that went into this project to make a best-of-class tactical RPG. I sunk just over 220 hours into the game and plan to tackle another run on the hardest difficulty, True Zenoiran, either next year or the following year.</p>



<h2 class="wp-block-heading">Star Wars Force Unleashed</h2>



<figure class="wp-block-image size-full"><a href="https://duaneblake.co.uk/wp-content/uploads/2025/01/Force-Unleased.png"><img loading="lazy" decoding="async" width="600" height="200" src="https://duaneblake.co.uk/wp-content/uploads/2025/01/Force-Unleased.png" alt="" class="wp-image-1167" srcset="https://duaneblake.co.uk/wp-content/uploads/2025/01/Force-Unleased.png 600w, https://duaneblake.co.uk/wp-content/uploads/2025/01/Force-Unleased-300x100.png 300w" sizes="auto, (max-width: 600px) 100vw, 600px" /></a></figure>



<p>I went to Disney World this year and got the Star Wars bug after going on the Rise of the Resistance and Smugglers Run. I got this game as part of the Star Wars Heritage pack on the Nintendo Switch. I first played this game on the Xbox 360, and I played through it several times, trying to collect all of the Holocrons. Playing the Switch version, I kept thinking I couldn&#8217;t remember this, and the game seemed a bit more button-bashy. I decided to look into it and realised that the game was based on the Wii version.</p>



<p>Overall, I thought the game was just okay. It gets repetitive in parts as the combat is a lot more primitive compared to the 360 and PS3 versions. It&#8217;s a shame they ported that version of the game and decided not to go with the 360 version.</p>



<h2 class="wp-block-heading">Mirrors Edge</h2>



<figure class="wp-block-image size-full"><a href="https://duaneblake.co.uk/wp-content/uploads/2025/01/mirros-edge.png"><img loading="lazy" decoding="async" width="600" height="200" src="https://duaneblake.co.uk/wp-content/uploads/2025/01/mirros-edge.png" alt="" class="wp-image-1169" srcset="https://duaneblake.co.uk/wp-content/uploads/2025/01/mirros-edge.png 600w, https://duaneblake.co.uk/wp-content/uploads/2025/01/mirros-edge-300x100.png 300w" sizes="auto, (max-width: 600px) 100vw, 600px" /></a></figure>



<p>I have already written my thoughts on this game. <a href="https://duaneblake.co.uk/gaming/thoughts-on-mirrors-edge-catalyst/" title="You can read it here">You can read it here</a>. But a quick summary is a short and enjoyable experience focused on its unique mechanics. I think it had another sequel. They could have ironed out all the shortcomings.</p>



<h2 class="wp-block-heading">Detroit Being Human</h2>



<figure class="wp-block-image size-full"><a href="https://duaneblake.co.uk/wp-content/uploads/2025/01/Detroid-being-Human.png"><img loading="lazy" decoding="async" width="600" height="200" src="https://duaneblake.co.uk/wp-content/uploads/2025/01/Detroid-being-Human.png" alt="" class="wp-image-1165" srcset="https://duaneblake.co.uk/wp-content/uploads/2025/01/Detroid-being-Human.png 600w, https://duaneblake.co.uk/wp-content/uploads/2025/01/Detroid-being-Human-300x100.png 300w" sizes="auto, (max-width: 600px) 100vw, 600px" /></a></figure>



<p>A lot of games say they offer branching storylines, but the reality is that there are a few different dialogue options. Then, it just leads to the same outcome. The game is set in the future with tensions between androids and humans. In the game, you play as three different android characters and how their storylines tangle together. The developers Quantic Dream did a phenomenal job with the visuals as they built out a futuristic depiction of Detroit. The game soundtrack is one of the best scores from a game I have recently heard.  My main letdown for the games is quick time events, as there are several of them at key parts of the story. If you are not fast on your fingers, you could fail the mission and not get the perfect endings. It is a game I will revisit in the future.</p>



<h2 class="wp-block-heading">Fire Emblem Engage</h2>



<figure class="wp-block-image size-full"><a href="https://duaneblake.co.uk/wp-content/uploads/2025/01/Fire-Emble-Engage.png"><img loading="lazy" decoding="async" width="600" height="200" src="https://duaneblake.co.uk/wp-content/uploads/2025/01/Fire-Emble-Engage.png" alt="" class="wp-image-1164" srcset="https://duaneblake.co.uk/wp-content/uploads/2025/01/Fire-Emble-Engage.png 600w, https://duaneblake.co.uk/wp-content/uploads/2025/01/Fire-Emble-Engage-300x100.png 300w" sizes="auto, (max-width: 600px) 100vw, 600px" /></a></figure>



<p>I have been a massive Fire Emblem fan since playing Awakening on the Nintendo DS. This game features characters from previous instalments, making seeing familiar faces like Robin and Lucina enjoyable. However, this is my least favourite out of all the Fire Emblem games I have played. For example, the art design. While it doesn&#8217;t have as much replay value as Three Houses due to its house system, I recommend that anyone looking to play a Fire Emblem game on the Switch choose Three Houses. The way the story works when doing multiple play-throughs allows you to see different storylines.</p>



<h2 class="wp-block-heading">Infamous first light</h2>



<figure class="wp-block-image size-full"><a href="https://duaneblake.co.uk/wp-content/uploads/2025/01/infamous.png"><img loading="lazy" decoding="async" width="600" height="200" src="https://duaneblake.co.uk/wp-content/uploads/2025/01/infamous.png" alt="" class="wp-image-1163" srcset="https://duaneblake.co.uk/wp-content/uploads/2025/01/infamous.png 600w, https://duaneblake.co.uk/wp-content/uploads/2025/01/infamous-300x100.png 300w" sizes="auto, (max-width: 600px) 100vw, 600px" /></a></figure>



<p>Infamous First Light was my introduction to the Infamous series, and I chose it because I wanted a game with a shorter playtime to tackle from my backlog. As a standalone DLC, you begin with many powers already unlocked, which makes both combat and traversal around the map much easier. The gameplay reminded me a lot of Saints Row 4 in certain parts. I believe that playing the earlier games would have helped me appreciate the story and lore more. It’s a solid game if you’re looking for a brief, action-packed superhero experience, but it’s best enjoyed with some knowledge of the series.</p>



<h2 class="wp-block-heading">Steam World Dig 2</h2>



<figure class="wp-block-image size-full"><a href="https://duaneblake.co.uk/wp-content/uploads/2025/01/Steamworld-dig-2.png"><img loading="lazy" decoding="async" width="600" height="200" src="https://duaneblake.co.uk/wp-content/uploads/2025/01/Steamworld-dig-2.png" alt="" class="wp-image-1162" srcset="https://duaneblake.co.uk/wp-content/uploads/2025/01/Steamworld-dig-2.png 600w, https://duaneblake.co.uk/wp-content/uploads/2025/01/Steamworld-dig-2-300x100.png 300w" sizes="auto, (max-width: 600px) 100vw, 600px" /></a></figure>



<p>I played the first game on the Vita. In the storyline, you control Dorthy, who is searching for the protagonist from the first game. The SteamWorld series features an appealing art style and charming dialogue. This game improves on many mechanics from the original, making them more accessible. I enjoyed the gameplay loop of digging down, returning to the surface, and cashing in my treasures with the merchant for coins, which I used to buy upgrades and items.</p>



<h2 class="wp-block-heading">Mario + Rabbids Sparks of Hope</h2>



<figure class="wp-block-image size-full"><a href="https://duaneblake.co.uk/wp-content/uploads/2025/01/mario-rabids.png"><img loading="lazy" decoding="async" width="600" height="200" src="https://duaneblake.co.uk/wp-content/uploads/2025/01/mario-rabids.png" alt="" class="wp-image-1161" srcset="https://duaneblake.co.uk/wp-content/uploads/2025/01/mario-rabids.png 600w, https://duaneblake.co.uk/wp-content/uploads/2025/01/mario-rabids-300x100.png 300w" sizes="auto, (max-width: 600px) 100vw, 600px" /></a></figure>



<p>Mario + Rabbids Sparks of Hope is another game where I played the previous game. The game builds on the tactical gameplay of the original. The original was more of a gird-based system similar to the Xcom games. The game sequel allows for more unrestricted movement within a character’s range, allowing flexibility and strategy in approaching each map. Since the game targets a younger audience, you may find it easier if you have much experience playing tactical RPGs.</p><p>The post <a href="https://duaneblake.co.uk/gaming/games-i-completed-in-2024/">Games I completed in 2024</a> first appeared on <a href="https://duaneblake.co.uk">Duane Blake</a>.</p>]]></content:encoded>
					
					<wfw:commentRss></wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to Update Input Values Dynamically based on another input with Laravel and Livewire</title>
		<link>https://duaneblake.co.uk/laravel/how-to-update-input-values-dynamically-based-on-another-input-with-laravel-and-livewire/</link>
					<comments>https://duaneblake.co.uk/laravel/how-to-update-input-values-dynamically-based-on-another-input-with-laravel-and-livewire/#respond</comments>
		
		<dc:creator><![CDATA[Duane Blake]]></dc:creator>
		<pubDate>Sat, 13 Apr 2024 13:14:27 +0000</pubDate>
				<category><![CDATA[Laravel]]></category>
		<guid isPermaLink="false">https://duaneblake.co.uk/?p=1138</guid>

					<description><![CDATA[<p>One of the things I love about modern development tools and frameworks is how they make it so easy to do simple features. Years ago, these sorts of things I’m about to show would be some jQuery gymnastic with a prayer that it works in IE. Updating another value based on input in Livewire is [&#8230;]</p>
<p>The post <a href="https://duaneblake.co.uk/laravel/how-to-update-input-values-dynamically-based-on-another-input-with-laravel-and-livewire/">How to Update Input Values Dynamically based on another input with Laravel and Livewire</a> first appeared on <a href="https://duaneblake.co.uk">Duane Blake</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>One of the things I love about modern development tools and frameworks is how they make it so easy to do simple features. Years ago, these sorts of things I’m about to show would be some jQuery gymnastic with a prayer that it works in IE. Updating another value based on input in Livewire is a simple process with modern frameworks like Livewire and Laravel.</p>



<figure class="wp-block-image size-full postImg" id="https://duaneblake.co.uk/?p=1138"><a href="/laravel/how-to-update-input-values-dynamically-based-on-another-input-with-laravel-and-livewire/"><img loading="lazy" decoding="async" width="600" height="200" src="https://duaneblake.co.uk/wp-content/uploads/2024/04/Dynamically-chang-input-values-with-Laravel-and-Livewire.png" alt="Livewire mascot" class="wp-image-1139" style="object-fit:cover" srcset="https://duaneblake.co.uk/wp-content/uploads/2024/04/Dynamically-chang-input-values-with-Laravel-and-Livewire.png 600w, https://duaneblake.co.uk/wp-content/uploads/2024/04/Dynamically-chang-input-values-with-Laravel-and-Livewire-300x100.png 300w" sizes="auto, (max-width: 600px) 100vw, 600px" /></a></figure>



<span id="more-1138"></span>



<p>I will demonstrate how updating a specific field in Livewire dynamically changes the value of another field. Using a blog as an example, you automatically create the slug based on that title when you create a title.</p>



<p>I will assume that you have already created a component and added it to your view. In my case, I have a Laravel component called Post. In the Post template, we are going to add two Properties, one called title and the other called slug.</p>



<pre class="wp-block-code"><code>public $title;
public $slug;</code></pre>



<p>Now go to the blade template with both the properties we created above. Are going to be added to the form with an input using wire:model attribute</p>



<pre class="wp-block-code"><code>&lt;form class="space-y-5"&gt;
    &lt;div&gt;
        &lt;label class="block mb-2" for="title"&gt;Title&lt;/label&gt;
        &lt;input type="text" name="title" id="title" wire:model.live="title" /&gt;
    &lt;/div&gt;
    &lt;div&gt;
        &lt;label class="block mb-2" for="slug"&gt;Slug&lt;/label&gt;
        &lt;input type="text" name="slug" id="slug" wire:model="slug" /&gt;
    &lt;/div&gt;
&lt;/form&gt;</code></pre>



<p>With that setup, we will work on the reactive part of the form. Back to the Post.php template, we will use the <a href="https://livewire.laravel.com/docs/lifecycle-hooks#update" title="updated method on the Lifecycle hook">updated method on the Lifecycle hook</a>. So, the method runs every time our title property is updated.</p>



<p>What the code does below we look to see if the title property has been updated. If it has, we get the slug property using the Laravel slug helper and convert it into a URL.</p>



<pre class="wp-block-code"><code>public function updated($property)
{
   if ($property == 'title') {
      slug = Str::of($this-&gt;title)-&gt;slug;
   }
}</code></pre>



<p>Now, go back to the blade template, and we&#8217;re going to update the title tag so it changes live.</p>



<pre class="wp-block-code"><code>&lt;input type="text" name="title" id="title" wire:model.live="title" /&gt;</code></pre>



<p>Anytime you change the title input, the slug will get updated. It&#8217;s so impressive how Livewire makes this technique easy to do. However, making the change using live can result in many Network requests. My preferred method is Blur, which only runs when someone&#8217;s tabs are out of the field.</p>



<pre class="wp-block-code"><code>&lt;input type="text" name="title" id="title" wire:model.blur="title" /&gt;</code></pre>



<p>An alternative way would be to return to our Post.php file and change the updated function to updateTitle. Livewire is clever enough to know we are changing the title property, making the code much cleaner.</p>



<pre class="wp-block-code"><code>public function updatedTitle()
{
   $this-&gt;slug = Str::of($this-&gt;title)-&gt;slug;
}</code></pre>



<p>In summary, this is how you can reactively update another text input using the example of a blog title and post. I hope you found some use for this in your projects. Below is a video of the code above.</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="How to Update an Input Values Dynamically based on another input with Laravel and Livewire" width="500" height="281" src="https://www.youtube.com/embed/L53VzrwqjBI?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure><p>The post <a href="https://duaneblake.co.uk/laravel/how-to-update-input-values-dynamically-based-on-another-input-with-laravel-and-livewire/">How to Update Input Values Dynamically based on another input with Laravel and Livewire</a> first appeared on <a href="https://duaneblake.co.uk">Duane Blake</a>.</p>]]></content:encoded>
					
					<wfw:commentRss></wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Thoughts on Mirrors Edge Catalyst</title>
		<link>https://duaneblake.co.uk/gaming/thoughts-on-mirrors-edge-catalyst/</link>
					<comments>https://duaneblake.co.uk/gaming/thoughts-on-mirrors-edge-catalyst/#respond</comments>
		
		<dc:creator><![CDATA[Duane Blake]]></dc:creator>
		<pubDate>Mon, 25 Mar 2024 13:21:17 +0000</pubDate>
				<category><![CDATA[Gaming]]></category>
		<guid isPermaLink="false">https://duaneblake.co.uk/?p=1131</guid>

					<description><![CDATA[<p>I recently picked up Mirrors Edge during one of the recent Xbox store sales. At the time of its launch, I was interested in playing it because I liked the idea of a parkour first-person game. History The game was initially released in 2016, developed by Dice, and published by EA. It&#8217;s a reboot of [&#8230;]</p>
<p>The post <a href="https://duaneblake.co.uk/gaming/thoughts-on-mirrors-edge-catalyst/">Thoughts on Mirrors Edge Catalyst</a> first appeared on <a href="https://duaneblake.co.uk">Duane Blake</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>I recently picked up Mirrors Edge during one of the recent Xbox store sales. At the time of its launch, I was interested in playing it because I liked the idea of a parkour first-person game.</p>



<figure class="wp-block-image size-full postImg"><a href="https://duaneblake.co.uk/wp-content/uploads/2024/03/mirror-edge-article.png"><img loading="lazy" decoding="async" width="600" height="200" src="https://duaneblake.co.uk/wp-content/uploads/2024/03/mirror-edge-article.png" alt="Faith running from some secruity" class="wp-image-1132" srcset="https://duaneblake.co.uk/wp-content/uploads/2024/03/mirror-edge-article.png 600w, https://duaneblake.co.uk/wp-content/uploads/2024/03/mirror-edge-article-300x100.png 300w" sizes="auto, (max-width: 600px) 100vw, 600px" /></a></figure>



<span id="more-1131"></span>



<h2 class="wp-block-heading">History</h2>



<p>The game was initially released in 2016, developed by Dice, and published by EA. It&#8217;s a reboot of the original Mirror Edge game, first released in 2008. According to what I found reading up, the game sold between 1.7 million and 2 million in the first three months of release. But I imagine many more people have played the game now since it has been on sale multiple times and is on the EA game pass. Also a good amount of time has passed since its launch which should increase that number.</p>



<h2 class="wp-block-heading">About the game</h2>



<p>The game is a first-person Parkour game where you run, jump, slide, swing and crawl through the futuristic metropolitan city with high-rise buildings.  You play Faith Connors, a runner in the fictional City of Glass. A runner is a messenger who delivers packages or information. The game starts with Faith leaving juvenile detention. After spending two years in detention, she wants to return to running to pay off a debt. On her first run back Faith discovers an encrypted hard drive containing some information a top seceret corporate project called Reflection. Without spoiling the game, you find out what&#8217;s on the hard drive and how it relates to her history.</p>



<h2 class="wp-block-heading">What I liked</h2>



<ul class="wp-block-list">
<li>Runner Vision is like a GPS you would find in a game like GTA or Saints Row. A red line highlights the path you have to take. I found it both good and bad.  The good as it shows you the route to go when playing the game. Bad as it became a crutch for me as I relied on it to much and didn’t experiment in finding my own route to get to my destination.  </li>



<li>Once you get used to the movements and have enough of the upgrade, you can parkour around the rooftops. The game city is a playground for traversing it, and you find yourself entering a mini-flow state, jumping around the city.</li>
</ul>



<h2 class="wp-block-heading">What I didn’t like</h2>



<ul class="wp-block-list">
<li>The storyline won’t win any awards. The writing is very predictable and plays on multiple genre stereotypes. The characters are very one-dimensional and lack depth.</li>



<li>Side missions &#8211; The map looks something like Ubisoft games such as Assassin&#8217;s Creed and Far Cry where there are multiple missions and loads of collectables. Such as GridLeak, Computer chips and audio files. The side missions are not memorable and are just really padding with missions such as Fragile Delivery, where you have to deliver a package to a different location on the map and prevent the package from getting any damage. Which didn’t give me much motivation to complete it as the story mode is quite generous for its in-game currency</li>
</ul>



<h2 class="wp-block-heading">Final Thoughts</h2>



<p>The game feels like a perfect Xbox Game Pass game, which isn’t an insult. It&#8217;s the sort of game that&#8217;s worth playing and enjoyable in parts, as it&#8217;s very short if you stick to the story mode and doesn’t overstay its welcome. I think if the game managed to get another sequel and build on what it had done, refining and polishing what this game has already done would be a further step to making a unique and different game series.</p><p>The post <a href="https://duaneblake.co.uk/gaming/thoughts-on-mirrors-edge-catalyst/">Thoughts on Mirrors Edge Catalyst</a> first appeared on <a href="https://duaneblake.co.uk">Duane Blake</a>.</p>]]></content:encoded>
					
					<wfw:commentRss></wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Using the Chat GPT API to create a Tweet from content on a URL</title>
		<link>https://duaneblake.co.uk/laravel/using-the-chat-gpt-api-to-create-a-tweet-from-content-on-a-url/</link>
					<comments>https://duaneblake.co.uk/laravel/using-the-chat-gpt-api-to-create-a-tweet-from-content-on-a-url/#respond</comments>
		
		<dc:creator><![CDATA[Duane Blake]]></dc:creator>
		<pubDate>Thu, 30 Mar 2023 06:06:47 +0000</pubDate>
				<category><![CDATA[Laravel]]></category>
		<guid isPermaLink="false">https://duaneblake.co.uk/?p=1117</guid>

					<description><![CDATA[<p>With all the talk going around with Chat GPT and the latest development with AI. I decided to spend some time looking at using the API to create a very small MVP. The aim was to spend a couple of hours building a app. Where a user provides a URL and then selects from a [&#8230;]</p>
<p>The post <a href="https://duaneblake.co.uk/laravel/using-the-chat-gpt-api-to-create-a-tweet-from-content-on-a-url/">Using the Chat GPT API to create a Tweet from content on a URL</a> first appeared on <a href="https://duaneblake.co.uk">Duane Blake</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>With all the talk going around with Chat GPT and the latest development with AI. I decided to spend some time looking at using the API to create a very small MVP. The aim was to spend a couple of hours building a app. Where a user provides a URL and then selects from a list of predefined tones from the site, the site would then generates the tweet on that link with the chosen tone.</p>



<figure class="wp-block-image size-full postImg"><a href="/?p=1117"><img loading="lazy" decoding="async" width="600" height="200" src="https://duaneblake.co.uk/wp-content/uploads/2023/03/chat-gpt-ai.png" alt="Using the Chat GPT API to create a Tweet from content on a URL" class="wp-image-1119" srcset="https://duaneblake.co.uk/wp-content/uploads/2023/03/chat-gpt-ai.png 600w, https://duaneblake.co.uk/wp-content/uploads/2023/03/chat-gpt-ai-300x100.png 300w" sizes="auto, (max-width: 600px) 100vw, 600px" /></a></figure>



<span id="more-1117"></span>



<p>My first point of call was what I was going to build the app in I’m familiar with building apps in WordPress, Laravel, VueJs and most recently Svelte. I decided to go with Laravel as WordPress isn’t suitable for something like this. If in the future I decided to develop the app I would need authentication options. So I decided to go with Laravel. As its got all scaffolding for user auth if I use Jetstream or Breeze.</p>



<p>Outside of building the routes and the controller, the first thing I needed to build was a form to capture the user URL and an option for the tone of the tweet. Which will be a choice of three different options Clickbait, Sincere and Homously.</p>



<pre class="wp-block-code"><code>&lt;form method="POST" action="{{route('tweets')}}" class="space-y-6"&gt;
    &lt;div&gt;
        @csrf
        &lt;label for="url" class="block mb-2 sr-only"&gt;Enter Url&lt;/label&gt;
        @error('url')
        &lt;span class="mt-2 text-sm text-tomaoto-500"&gt;{{ $message }}&lt;/span&gt;
        @enderror
        &lt;input type="url" name="url" placeholder="Enter your webpage url" class="py-3 px-4 rounded-sm w-full border-0 bg-iron-25 placeholder-iron-500 ring-1 ring-inset ring-iron-500 focus:ring-2 focus:ring-inset focus:ring-pumpkin-800" /&gt;
    &lt;/div&gt;
    &lt;div class="flex"&gt;
        &lt;div&gt;
            &lt;label for="tone" class="block leading-6 "&gt;Tone&lt;/label&gt;
            &lt;select id="tone" name="tone" class="py-3 px-4 mt-2 block w-52 rounded-sm border-0 bg-iron-25 placeholder-iron-500 ring-1 ring-inset ring-iron-500 focus:ring-2 focus:ring-inset focus:ring-pumpkin-800"&gt;
                &lt;option value="clickbait"&gt;Clickbait&lt;/option&gt;
                &lt;option value="humorously"&gt;Humorously&lt;/option&gt;
                &lt;option value="sincere"&gt;Sincere&lt;/option&gt;
            &lt;/select&gt;
        &lt;/div&gt;
        &lt;div class="ml-8 self-end"&gt;
            &lt;button type="submit" class="self-end rounded-md bg-pumpkin-500 py-3 px-7 text-sm font-semibold text-white shadow-sm transition-all hover:bg-pumpkin-700 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-pumpkin-800"&gt;Create Tweet&lt;/button&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/form&gt;</code></pre>



<p>Onto the controller, once the form has been submitted, I need to validate that the URL has been submitted and is in a format of a URL then assign a variable to the inputs. As I would need to pass these to the result page.</p>



<pre class="wp-block-code"><code>$validated = $request-&gt;validate(&#91;
      'url' =&gt; 'required|url'
]);

$url = $validated&#91;'url'];
$tone = $request&#91;'tone'];</code></pre>



<p>I&#8217;m using <a href="https://laravel.com/docs/10.x/http-client" title="">Laravel HTTP</a> client to fetch the data from the URL. The HTTP response returns all the HTML code. From what I&#8217;ve been reading if you provide that content it increases the cost of the API  call. As all the HTML tags would generate more tokens.  Also there is a limit on the amount of text that can be read in one request.  To reduce the amount of text provided to the Open AI.  I decided to remove certain HTML tags from being submitted to the API.  Such as script, style and a few other tags from the page.</p>



<pre class="wp-block-code"><code>$response = Http::get($url);

$dom = new DOMDocument('1.0', 'UTF-8');
$internalErrors = libxml_use_internal_errors(true);
$dom-&gt;loadHTML($response-&gt;body());
$tags_to_remove = array('script', 'style', 'nav', 'footer', 'header', 'form', 'aside');
foreach ($tags_to_remove as $tag) {
    $element = $dom-&gt;getElementsByTagName($tag);
    foreach ($element  as $item) {
        $item-&gt;parentNode-&gt;removeChild($item);
    }
}

$html = $dom-&gt;saveHTML();</code></pre>



<p>Now that I have removed all the unnecessary tags. I am going to remove the all tags and just leave the content. Then remove all the whitespace using the Laravel <a href="https://laravel.com/docs/10.x/helpers#method-str-squish" target="_blank" rel="noreferrer noopener">Str:squish</a> helper.</p>



<pre class="wp-block-code"><code>$content = Str::squish(strip_tags($html));</code></pre>



<p>The next thing I needed to do is get an API key for Open AI. When I signed up you’re given a $5 credit which will be perfect to use on this demo project. To work with Open AI I will be using the fantastic Laravel composer package which does all the heavy lifting called <a href="https://github.com/openai-php/laravel" title="Openai-php">Openai-php</a>. From reading the documentation on the Open AI website. They have several different models which I can use. I’m using gpt-3.5-turbo model as that&#8217;s the cheapest model which helps me stay under the $5 trial limit.</p>



<pre class="wp-block-code"><code>$results = OpenAI::chat()-&gt;create(&#91;
	'model' =&gt; 'gpt-3.5-turbo',
	'messages' =&gt; &#91;
		&#91;'role' =&gt; 'user', 'content' =&gt; "Write tweet as $tone based on the following  $content"],
	]
]);

$answer = $results&#91;'choices']&#91;0]&#91;'message']&#91;'content'];</code></pre>



<p>Once the form has been submitted to the page we return the $answer, $url, and $tone to the user. Then display the information to the user.</p>



<pre class="wp-block-code"><code>&lt;div&gt;
	&lt;h1 class="text-5xl text-iron-800 font-semibold "&gt;Great!&lt;/h1&gt;
	&lt;p class="text-lg mt-6"&gt;Your tweet for the webpage &lt;a href="{}" class="underline text-pumpkin-500 hover:no-underline hover:text-pumpkin-700"&gt;{{$url}}&lt;/a&gt; as been written in tone of {{$tone}}.&lt;/p&gt;
  &lt;div class="bg-white overflow-hidden py-10"&gt;
		&lt;textarea class="w-full h-56 py-3 px-4 rounded-sm border-0 bg-iron-25 placeholder-iron-500 ring-1 ring-inset ring-iron-500 focus:ring-2 focus:ring-inset focus:ring-pumpkin-800" readonly&gt;{{$answer}}&lt;/textarea&gt;
	&lt;/div&gt;
&lt;/div&gt;</code></pre>



<h2 class="wp-block-heading">Demo</h2>



<p>The video below shows a quick demo of how the code works.</p>



<figure class="wp-block-video"><video controls src="https://duaneblake.co.uk/wp-content/uploads/2023/03/tweet-from-blog.mp4"></video></figure>



<h2 class="wp-block-heading">Further Improvements</h2>



<ul class="wp-block-list">
<li>Since I&#8217;m using Laravel Jetstream for Auth, the user is logging in so I can easily store the previous requests in the database. Then present them in a dashboard for the user.</li>



<li>Convert it over to Livewire there are a couple benefits of moving over to Livewire such as loading animations</li>



<li>Since there is a token limit the API has issues when a page has to much content.  I would need to find a way of splitting up or summarising the request.</li>



<li>Not too sure if the Twitter API still works with all the changes happening there but you could post the Tweet to the user account.</li>
</ul>



<h2 class="wp-block-heading">Further information</h2>



<p>As I was writing up this blog post Syntax.fm released a good podcast called <a href="https://syntax.fm/show/593/coding-with-the-open-ai-chat-gpt-api" title="Coding with the Open AI / Chat GPT API">Coding with the Open AI / Chat GPT API</a> about using the API</p>



<h2 class="wp-block-heading">Final thoughts</h2>



<p>I was surprised by how quick and easy to get up and running with the API to build something. Granted the code can be improved and refactored. I just wanted to build something in a quick couple of hours and see how easy it was to build something.</p>



<p>Also, the cost of the API is a lot cheaper than I thought it would be I was expecting it to be loads and building the app I only reached $0.50 and I was doing loads of requests.</p><p>The post <a href="https://duaneblake.co.uk/laravel/using-the-chat-gpt-api-to-create-a-tweet-from-content-on-a-url/">Using the Chat GPT API to create a Tweet from content on a URL</a> first appeared on <a href="https://duaneblake.co.uk">Duane Blake</a>.</p>]]></content:encoded>
					
					<wfw:commentRss></wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		<enclosure url="https://duaneblake.co.uk/wp-content/uploads/2023/03/tweet-from-blog.mp4" length="5767864" type="video/mp4" />

			</item>
		<item>
		<title>Changing the default validation message on an HTML input tag</title>
		<link>https://duaneblake.co.uk/front-end/changing-the-default-validation-message-on-an-html-input-tag/</link>
					<comments>https://duaneblake.co.uk/front-end/changing-the-default-validation-message-on-an-html-input-tag/#respond</comments>
		
		<dc:creator><![CDATA[Duane Blake]]></dc:creator>
		<pubDate>Sun, 12 Mar 2023 14:24:48 +0000</pubDate>
				<category><![CDATA[Front End]]></category>
		<guid isPermaLink="false">https://duaneblake.co.uk/?p=1096</guid>

					<description><![CDATA[<p>Using HTML validation is a good extra protection for using server-side validation. However, I found the validation message used doesn’t always provide the user with enough context about what is wrong with the issue. I’m going to describe how to change this message. First, we create a standard input where we ask for a username [&#8230;]</p>
<p>The post <a href="https://duaneblake.co.uk/front-end/changing-the-default-validation-message-on-an-html-input-tag/">Changing the default validation message on an HTML input tag</a> first appeared on <a href="https://duaneblake.co.uk">Duane Blake</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Using HTML validation is a good extra protection for using server-side validation. However, I found the validation message used doesn’t always provide the user with enough context about what is wrong with the issue. I’m going to describe how to change this message.</p>



<figure class="wp-block-image size-full postImg"><a href="https://duaneblake.co.uk/?p=1096"><img loading="lazy" decoding="async" width="600" height="200" src="https://duaneblake.co.uk/wp-content/uploads/2023/03/html-validation-message.png" alt="" class="wp-image-1101" srcset="https://duaneblake.co.uk/wp-content/uploads/2023/03/html-validation-message.png 600w, https://duaneblake.co.uk/wp-content/uploads/2023/03/html-validation-message-300x100.png 300w" sizes="auto, (max-width: 600px) 100vw, 600px" /></a></figure>



<span id="more-1096"></span>



<p>First, we create a standard input where we ask for a username for a user.</p>



<pre class="wp-block-code"><code>&lt;input id="username"  type="text" name="username" /&gt; </code></pre>



<p>Now we will add the required attribute to the form</p>



<pre class="wp-block-code"><code>&lt;input id="username"  type="text" name="username" required /&gt; </code></pre>



<p>This is the standard message which the browser returns.  &#8220;Please fill in this field&#8221;</p>



<figure class="wp-block-image size-full"><a href="https://duaneblake.co.uk/wp-content/uploads/2023/02/standard-browser-validation.png"><img loading="lazy" decoding="async" width="295" height="85" src="https://duaneblake.co.uk/wp-content/uploads/2023/02/standard-browser-validation.png" alt="Browser Validation asking the user to fill in the field" class="wp-image-1097"/></a></figure>



<p>To change the validation message we will be using the oninvalid attribute. We will then use the setCustomValidity method. To create our own validation message. In this case, it will be “Please fill in your username”</p>



<pre class="wp-block-code"><code>&lt;input id="username"  type="text" name="username" required 
oninvalid="this.setCustomValidity('Please fill in your username')" /> html</code></pre>



<p>As you can see from the screenshot below the error message is more help for the user rather than the stock browser message which is returned.</p>



<figure class="wp-block-image size-full"><a href="https://duaneblake.co.uk/wp-content/uploads/2023/02/custom-browser-validation.png"><img loading="lazy" decoding="async" width="277" height="84" src="https://duaneblake.co.uk/wp-content/uploads/2023/02/custom-browser-validation.png" alt="Custom brower validation for a form input" class="wp-image-1098"/></a></figure>



<p>The links below from MDN go into further details how you could set this attribute from within a Javascript function rather than on each input.</p>



<p><a href="https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/oninvalid">https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/oninvalid</a></p>



<p><a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/setCustomValidity">https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/setCustomValidity</a></p><p>The post <a href="https://duaneblake.co.uk/front-end/changing-the-default-validation-message-on-an-html-input-tag/">Changing the default validation message on an HTML input tag</a> first appeared on <a href="https://duaneblake.co.uk">Duane Blake</a>.</p>]]></content:encoded>
					
					<wfw:commentRss></wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Preventing Search engines indexing pages on your site</title>
		<link>https://duaneblake.co.uk/seo-101/preventing-search-engines-indexing-pages-on-your-site/</link>
					<comments>https://duaneblake.co.uk/seo-101/preventing-search-engines-indexing-pages-on-your-site/#respond</comments>
		
		<dc:creator><![CDATA[Duane Blake]]></dc:creator>
		<pubDate>Tue, 31 Jan 2023 07:17:52 +0000</pubDate>
				<category><![CDATA[Seo 101]]></category>
		<guid isPermaLink="false">https://duaneblake.co.uk/?p=1083</guid>

					<description><![CDATA[<p>They may be situations when you may not want Search engines such as Google and Bing to index pages on your website. For example login pages, testing sites or basket pages. I’m going to list how to do this using the Robot.txt file and add a meta tag to the page. Robots.txt The robots.txt is [&#8230;]</p>
<p>The post <a href="https://duaneblake.co.uk/seo-101/preventing-search-engines-indexing-pages-on-your-site/">Preventing Search engines indexing pages on your site</a> first appeared on <a href="https://duaneblake.co.uk">Duane Blake</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>They may be situations when you may not want Search engines such as Google and Bing to index pages on your website. For example login pages, testing sites or basket pages. I’m going to list how to do this using the Robot.txt file and add a meta tag to the page.</p>



<figure class="wp-block-image size-full postImg"><a href="https://duaneblake.co.uk/?p=1083"><img loading="lazy" decoding="async" width="600" height="200" src="https://duaneblake.co.uk/wp-content/uploads/2022/09/Preventing-Search-engines-indexing-pages-on-your-site.png" alt="Preventing Search engines indexing pages on your site" class="wp-image-1084" srcset="https://duaneblake.co.uk/wp-content/uploads/2022/09/Preventing-Search-engines-indexing-pages-on-your-site.png 600w, https://duaneblake.co.uk/wp-content/uploads/2022/09/Preventing-Search-engines-indexing-pages-on-your-site-300x100.png 300w" sizes="auto, (max-width: 600px) 100vw, 600px" /></a></figure>



<span id="more-1083"></span>



<h2 class="wp-block-heading">Robots.txt</h2>



<pre class="wp-block-code"><code>Disallow: /login
Disallow: /register</code></pre>



<p>The robots.txt is an optional text file which lives in the root of your website directory. The Robots.txt file is used to suggest search engine crawlers which page to access on your site.</p>



<p>Using the robots.txt method for the pages you don’t want to show up in the search engine.  In the txt file add a new line which says Disallow followed by the URL that shouldn’t be indexed. So it looks like the example above. </p>



<p>One thing worth mentioning is documented in <a href="https://developers.google.com/search/docs/crawling-indexing/robots/intro" title="Google Search Central">Google Search Central</a>.  You shouldn&#8217;t rely on just this method as if a page has been linked to another page. Google may still index the URL even though it has visited the page.   Google suggest also using the following method we are looking at which is noindex tag.</p>



<h2 class="wp-block-heading">Meta tags</h2>



<pre class="wp-block-code"><code>&lt;META NAME="robots" CONTENT="noindex,nofollow"&gt;</code></pre>



<p>On the pages, you don’t want to index if you add the following code on the page. Into the head tag of your website. The code tells search engine robots not to index the page, which is done by noindex. The nofollow tells the search not to follow any of the links on the page. Depending on your circumstance you may be able to omit this.</p>



<h2 class="wp-block-heading">Further reading</h2>



<ul class="wp-block-list">
<li><a href="https://developers.google.com/search/docs/advanced/robots/intro" target="_blank" rel="noreferrer noopener">https://developers.google.com/search/docs/advanced/robots/intro</a></li>
</ul><p>The post <a href="https://duaneblake.co.uk/seo-101/preventing-search-engines-indexing-pages-on-your-site/">Preventing Search engines indexing pages on your site</a> first appeared on <a href="https://duaneblake.co.uk">Duane Blake</a>.</p>]]></content:encoded>
					
					<wfw:commentRss></wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
