<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: George Tudor</title>
    <description>The latest articles on Forem by George Tudor (@geowrgetudor).</description>
    <link>https://forem.com/geowrgetudor</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F807595%2F59f57938-7dc2-43f9-9743-7e021fbfb42c.png</url>
      <title>Forem: George Tudor</title>
      <link>https://forem.com/geowrgetudor</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/geowrgetudor"/>
    <language>en</language>
    <item>
      <title>How to manage, launch and even sell Wordpress sites using Dollie</title>
      <dc:creator>George Tudor</dc:creator>
      <pubDate>Mon, 07 Aug 2023 11:05:13 +0000</pubDate>
      <link>https://forem.com/geowrgetudor/how-to-manage-launch-and-even-sell-wordpress-sites-using-dollie-5201</link>
      <guid>https://forem.com/geowrgetudor/how-to-manage-launch-and-even-sell-wordpress-sites-using-dollie-5201</guid>
      <description>&lt;p&gt;&lt;strong&gt;Are you an agency&lt;/strong&gt; who wants to manage your clients' sites without any hustle? &lt;strong&gt;Are you a SaaS owner&lt;/strong&gt; who wants to easily sell plugins/themes? &lt;strong&gt;Are you a WaaS owner&lt;/strong&gt; who wants to sell premade sites for various niches? &lt;strong&gt;Are you someone who wants to launch a Wordpress site&lt;/strong&gt; without caring about server management, server performance and infrastructure?&lt;/p&gt;

&lt;p&gt;Well, if you fall into any of those categories, I'll show you a &lt;em&gt;tool that&lt;/em&gt; does that for you and &lt;em&gt;makes your life 100 times easier&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Dollie?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://getdollie.com/"&gt;Dollie&lt;/a&gt; is an all-in-one solution that includes powerful WP site management tools for any site (hosted on Dollie or somewhere else), a white-label private cloud, and a WordPress plugin which allows you to sell your services directly to your audience under your brand &amp;amp; domain.&lt;/p&gt;

&lt;h2&gt;
  
  
  What can you do with Dollie?
&lt;/h2&gt;

&lt;p&gt;The answer is simple. Whatever you want. Here's some of the stuff you can do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;launch new Wordpress sites in seconds&lt;/li&gt;
&lt;li&gt;one click login&lt;/li&gt;
&lt;li&gt;connect your own domain to the site&lt;/li&gt;
&lt;li&gt;launch demo sites&lt;/li&gt;
&lt;li&gt;manage any Wordpress site (no matter where it is hosted)&lt;/li&gt;
&lt;li&gt;create blueprints and deploy new Wordpress sites from an existing blueprint (ready made sites)&lt;/li&gt;
&lt;li&gt;sell blueprints under your own brand and domain. One click checkout. Allow users to create sites using your ready made blueprints - they get access to all the management tools they need. (you will need the Dollie plugin)&lt;/li&gt;
&lt;li&gt;monitor your Wordpress sites&lt;/li&gt;
&lt;li&gt;install/update/activate/deactivate/delete Wordpress plugins and themes from any of your sites&lt;/li&gt;
&lt;li&gt;update Wordpress Core&lt;/li&gt;
&lt;li&gt;access to Updates Manager so you can install/update/activate/deactivate/delete Wordpress plugins and themes on multiple sites at once&lt;/li&gt;
&lt;li&gt;access to SFTP/SSH&lt;/li&gt;
&lt;li&gt;access to Database Manager&lt;/li&gt;
&lt;li&gt;log viewer&lt;/li&gt;
&lt;li&gt;code editor&lt;/li&gt;
&lt;li&gt;daily backups&lt;/li&gt;
&lt;li&gt;security monitor&lt;/li&gt;
&lt;li&gt;seo reports&lt;/li&gt;
&lt;li&gt;activity reports&lt;/li&gt;
&lt;li&gt;and many more...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Please note that some of the features that I've listed above are only available when you have your site hosted with Dollie (for example the daily backup feature).&lt;/p&gt;

&lt;p&gt;Ok, so that's a long list and a lot to swallow, so let me show you some concrete examples so you can better understand how you can use Dollie.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you are an agency&lt;/strong&gt; and you have let's say 100 sites and you need to easily manage them, you can connect them to your Dollie account and easily manage all the updates, one-click login into any of them, have uptime monitors, reports and so on. It basically makes your life much easier.&lt;/p&gt;

&lt;p&gt;You can also bring all your sites to Dollie for better management, reports, backups and more, or you can even start using Dollie to launch new sites for new clients with just a click and not worry about servers, performance and infrastructure.&lt;/p&gt;

&lt;p&gt;Once a site is launched you can add the customer's domain and ask the customer to point his domain to the site's IP address. Dollie's system will automatically replace the original site's URL with the custom domain and generate a SSL certificate.&lt;/p&gt;

&lt;p&gt;You might also need blueprints if you have some repetitive work that needs to be done for each site.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you are a SaaS or WaaS owner&lt;/strong&gt; and you want to sell your ready made sites/products/websites, you can easily create a blueprint. A blueprint is basically a site that has everything already installed and whenever you launch a site or your customer launches a site using that blueprint, it gets exactly what's in the blueprint.&lt;/p&gt;

&lt;p&gt;If you're selling to your customer you might need a platform to do it, right? Well... you can install the Dollie plugin into your existing Wordpress site or you can have a free site on the Dollie infrastructure. That's your main site where you sell your blueprints. You can decide your own monthly/yearly pricing. Your customers will be able to subscribe and create as many sites as they need and pay you via Stripe or Paypal.&lt;/p&gt;

&lt;h2&gt;
  
  
  How expensive is Dollie?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;You can always start using Dollie for free&lt;/strong&gt;. You have a free plan that allows you to easily manage your sites (no matter where they're hosted).&lt;/p&gt;

&lt;p&gt;If you need more, like launching sites on the Dollie servers, you will have to pay $0.33/day/site. For blueprints you will have to pay $0.16/day/blueprint and for staging sites it's $0.10/day/staging site. That sums up to $10/site/month which is really cheap compared other providers and you get lots of tools on top of that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;If you need to manage multiple sites, want to sell ready made sites and/or need to launch sites and manage them easily, you can &lt;a href="https://control.getdollie.com/register"&gt;register&lt;/a&gt; and give Dollie a try.&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>sass</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Event driven Livewire components</title>
      <dc:creator>George Tudor</dc:creator>
      <pubDate>Fri, 24 Mar 2023 20:44:40 +0000</pubDate>
      <link>https://forem.com/geowrgetudor/event-driven-livewire-components-437j</link>
      <guid>https://forem.com/geowrgetudor/event-driven-livewire-components-437j</guid>
      <description>&lt;p&gt;&lt;a href="https://laravel-livewire.com/"&gt;Livewire&lt;/a&gt; is a really popular library for Laravel which I really love and use across all my projects. It provides that sweet SPA feeling while using almost no Javascript. For me... it's magic. :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Simple vs complex functionality
&lt;/h2&gt;

&lt;p&gt;Building some forms or having some small actions is pretty straightforward to do in Livewire and doesn't introduce any complexity. You just do it in one component. &lt;/p&gt;

&lt;p&gt;But &lt;strong&gt;sometimes you have to deal with multiple actions&lt;/strong&gt; that have to happen in a specific sequence or have to pass data from one to another. You can still do this inside a single component but this is not something I like to do due to various reasons. &lt;strong&gt;I believe it's better to split your code&lt;/strong&gt; into as many components as possible because it's easier to maintain them and the probably some components can also reused if you introduce some kind of abstraction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When you split your code into multiple components&lt;/strong&gt; and those components have to communicate between each other then &lt;strong&gt;you definitely need to use events&lt;/strong&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Using events in Livewire
&lt;/h2&gt;

&lt;p&gt;Livewire events are split into 2 categories: server events and browser events.&lt;/p&gt;

&lt;p&gt;We're going to talk talk strictly about server events because using those we can pass data from one component to another.&lt;/p&gt;

&lt;p&gt;You can emit server events to any other component, to a specific component, to parent components and even to the same component the event was emitted from.&lt;/p&gt;

&lt;p&gt;Let's look at a simple example that uses 2 components: one for input and one for displaying data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use Livewire\Component;

class InputForm extends Component
{
    public string $input = '';

    public function add() {
        $this-&amp;gt;validate([
            'input' =&amp;gt; 'required|string'
        ]);

        $this-&amp;gt;emit('input-form-submitted', $this-&amp;gt;input);
        $this-&amp;gt;reset(['input']);
    }

    public function render() {
        return view('livewire.input-form');
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;input-form&lt;/code&gt; view:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div&amp;gt;
    &amp;lt;input type="text" wire:model.defer="input" /&amp;gt;
    &amp;lt;button wire:click="add"&amp;gt;Add&amp;lt;/button&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So anytime we fill in our input and press the "Add" button we validate the input, emit an event and pass the input's value and then reset the &lt;code&gt;$input&lt;/code&gt; to its original value.&lt;/p&gt;

&lt;p&gt;Now in our second component we have to listen for this event and display the data into a list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use Livewire\Component;

class DataViewer extends Component
{
    public array $data = [];

    protected $listeners = [
        'input-form-submitted' =&amp;gt; 'updateData'
    ];

    public function updateData(string $data) {
        $this-&amp;gt;data[] = $data;
    }

    public function remove(int $index) {
        unset($this-&amp;gt;data[$index]);
    }

    public function render() {
        return view('livewire.data-viewer');
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;data-viewer&lt;/code&gt; view:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div&amp;gt;
    &amp;lt;ul&amp;gt;
        @foreach($data as $key =&amp;gt; $item)
            &amp;lt;li&amp;gt;
                &amp;lt;span&amp;gt;{{ $item }}&amp;lt;/span&amp;gt;
                &amp;lt;button wire:click="remove('{{ $key }}')"&amp;gt;Remove&amp;lt;/button&amp;gt;
            &amp;lt;li&amp;gt;
        @endforeach
    &amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So now, every time we detect a new event called &lt;code&gt;input-form-submitted&lt;/code&gt; in our 2nd component the &lt;code&gt;updateData&lt;/code&gt; function is getting called which appends the received data to the list.&lt;/p&gt;

&lt;p&gt;In this way we can reuse the 2nd component somewhere else, if needed.&lt;/p&gt;

&lt;p&gt;Hope you've enjoyed this quick example and you understand the whole idea of splitting components whenever a complex functionality is required.&lt;/p&gt;

</description>
      <category>livewire</category>
      <category>laravel</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Gradient animated text with Tailwind CSS</title>
      <dc:creator>George Tudor</dc:creator>
      <pubDate>Sun, 13 Nov 2022 14:34:50 +0000</pubDate>
      <link>https://forem.com/geowrgetudor/gradient-animated-text-with-tailwind-css-24a0</link>
      <guid>https://forem.com/geowrgetudor/gradient-animated-text-with-tailwind-css-24a0</guid>
      <description>&lt;p&gt;I've been working on a new project recently and I wanted to add some cool effect on my landing page's hero section's text. I've seen this effect on lots of sites this year but I've never been curious how it was made.&lt;/p&gt;

&lt;p&gt;I mainly work with Tailwind CSS because it's really easy to use and developer friendly. I'm not a designer and CSS is not my cup of tea. I prefer to make things work and look relatively good in short time rather dealing with CSS/SCSS/SASS files.&lt;/p&gt;

&lt;p&gt;So my approach was really simple and what I've needed was some keyframe and a clipped text.&lt;/p&gt;

&lt;p&gt;To achieve this we need to add our custom text animation and keyframes into &lt;code&gt;tailwind.config.js&lt;/code&gt;. We can use any keyword to define these, but since we're dealing with text I've decided to name them &lt;code&gt;text&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Note that you have to add the &lt;code&gt;animation&lt;/code&gt; and &lt;code&gt;keyframes&lt;/code&gt; definitions into your &lt;code&gt;extend&lt;/code&gt; object.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

modules.export = {
  theme: {
    extend: {
      animation: {
        text: 'text 5s ease infinite',
      },
      keyframes: {
        text: {
          '0%, 100%': {
            'background-size': '200% 200%',
            'background-position': 'left center',
          },
          '50%': {
            'background-size': '200% 200%',
            'background-position': 'right center',
          },
        },
      },
    }
  }
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now what's left to be done is to add your text wherever we want it.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&amp;lt;h1 class="animate-text bg-gradient-to-r from-teal-500 via-purple-500 to-orange-500 bg-clip-text text-transparent text-5xl font-black"&amp;gt;
    Hello World
&amp;lt;/h1&amp;gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;As you can see, we have the &lt;code&gt;animate-text&lt;/code&gt; class that is using the &lt;code&gt;tailwind.config.js&lt;/code&gt; definitions, our gradient and 2 more extra classes: &lt;code&gt;bg-clip-text&lt;/code&gt; that's clipping the background to our text and &lt;code&gt;text-transparent&lt;/code&gt; that's making exactly what it says in order to be able to see the animated background.&lt;/p&gt;

&lt;p&gt;That's all. Here's a Tailwind Playground with this in action:&lt;br&gt;
&lt;a href="https://play.tailwindcss.com/VCZwwz1e3R" rel="noopener noreferrer"&gt;https://play.tailwindcss.com/VCZwwz1e3R&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Support &amp;amp; follow me
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;a href="https://www.buymeacoffee.com/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FBuy_Me_A_Coffee-FFDD00%3Fstyle%3Dfor-the-badge%26logo%3Dbuy-me-a-coffee%26logoColor%3Dblack" alt="Buy me a coffee"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://twitter.com/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FTwitter-1DA1F2%3Fstyle%3Dfor-the-badge%26logo%3Dtwitter%26logoColor%3Dwhite" alt="Twitter"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://github.com/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FGitHub-100000%3Fstyle%3Dfor-the-badge%26logo%3Dgithub%26logoColor%3Dwhite" alt="GitHub"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://linkedin.com/in/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FLinkedIn-0077B5%3Fstyle%3Dfor-the-badge%26logo%3Dlinkedin%26logoColor%3Dwhite" alt="Linkedin"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>tailwindcss</category>
      <category>animation</category>
      <category>css</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to use Laravel Permission by Spatie in Vue</title>
      <dc:creator>George Tudor</dc:creator>
      <pubDate>Mon, 31 Oct 2022 09:44:10 +0000</pubDate>
      <link>https://forem.com/geowrgetudor/how-to-use-laravel-permission-by-spatie-in-vue-797</link>
      <guid>https://forem.com/geowrgetudor/how-to-use-laravel-permission-by-spatie-in-vue-797</guid>
      <description>&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; You can do the same as below using this package &lt;a href="https://github.com/geowrgetudor/laravel-spatie-permissions-vue" rel="noopener noreferrer"&gt;geowrgetudor/laravel-spatie-permissions-vue&lt;/a&gt;. It is a fork I made from the original package. Adds support for server-side rendering (SSR) and doesn't require installing a npm package (everything is built in).&lt;/p&gt;




&lt;p&gt;When in comes to Laravel packages, the guys at &lt;a href="https://spatie.be/" rel="noopener noreferrer"&gt;Spatie&lt;/a&gt; are probably the kings. They have hundreds of free packages you can pick from and use into your projects. Hats down for their commitment and contribution to this beautiful ecosystem.&lt;/p&gt;

&lt;p&gt;Now let's talk about permissions because if you're building a large Laravel app you definitely gonna need them. As a quick example, let's think of an admin panel built with Vue that needs different user roles where each role has specific permissions.&lt;/p&gt;

&lt;p&gt;Of course you can build all this functionality yourself, but why reinvent the wheel? There's a neat package from Spatie called &lt;a href="https://spatie.be/docs/laravel-permission/v5/introduction" rel="noopener noreferrer"&gt;spatie/laravel-permission&lt;/a&gt; which makes things really simple.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation and setup
&lt;/h2&gt;

&lt;p&gt;All you have to do is to install it and do a bit of configuration like publishing the vendor files (config and migration) plus some trait:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

composer require spatie/laravel-permission

# Publish the vendor's config file and migration
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"

# Clear your config cache so the package can pick up the published filed
php artisan config:clear

# Run the migration
php artisan migrate


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The next step is to add the package's trait to your user model and you're ready to roll:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable
{
    use HasRoles;
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;By default, the package comes with a &lt;code&gt;super-admin&lt;/code&gt; role published into your database by the default migration. You can use that of course, but you also can add your own roles and permissions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding new roles and permissions
&lt;/h2&gt;

&lt;p&gt;So let's create 2 roles and assign them some permissions. You can do this in a migration, seeder, artisan command, some UI interface, whatever suits you best.&lt;/p&gt;

&lt;p&gt;The package comes with some premade artisan commands you can use to create roles and permissions (you can check their docs for that), but for the sake of this demo, I'm going to use &lt;code&gt;tinker&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

# Create an editor role
$roleEditor = \Spatie\Permission\Models\Role::create(['name' =&amp;gt; 'editor']);

# Create a supervisor role
$roleSupervisor = \Spatie\Permission\Models\Role::create(['name' =&amp;gt; 'supervisor']);


# Now lets create permissions and assign them to our freshly created roles
$permissions = [
    'can-view-posts',
    'can-edit-posts',
    'can-publish-posts',
    'can-deleted-posts',
    'can-view-activity',
    'can-export-activity'
];

foreach($permissions as $permissionName) {
    $permission = \Spatie\Permission\Models\Permission::create(['name' =&amp;gt; $permissionName]);

    if(in_array($permissionName, ['can-view-posts', 'can-edit-posts', 'can-publish-posts', 'can-deleted-posts'])) {
        $roleEditor-&amp;gt;givePermissionTo($permission);
    } else {
        $roleSupervisor-&amp;gt;givePermissionTo($permission);
    }
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now, that we have all the permissions in place for each role, we can start using them in our controllers, services, routes, templates, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's talk about templates
&lt;/h2&gt;

&lt;p&gt;By default, this package comes with some handy Blade directives. You can use &lt;code&gt;@can&lt;/code&gt;, &lt;code&gt;@role&lt;/code&gt;, &lt;code&gt;@hasrole&lt;/code&gt;, &lt;code&gt;@hasanyrole&lt;/code&gt; and many more directives to render whatever you need based on roles and permissions. This is great, but these are only available in Blade.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How can we create something similar in Vue?&lt;/strong&gt; The process will be like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We need to expose all the roles and permissions to the frontend&lt;/li&gt;
&lt;li&gt;We need to defines some similar functions&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Luckily, you don't have to do this from scratch. You can use &lt;a href="https://www.npmjs.com/package/laravel-permission-to-vuejs" rel="noopener noreferrer"&gt;laravel-permission-to-vuejs&lt;/a&gt; which is a javascript package and &lt;strong&gt;ahmedsaoud31/laravel-permission-to-vuejs&lt;/strong&gt; which is a composer package. These 2 packages are great and are exactly what we need to use the same roles and permissions into our Vue application.&lt;/p&gt;

&lt;p&gt;First, we need to install the server side package and add another trait to our &lt;code&gt;User&lt;/code&gt; model:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

composer require ahmedsaoud31/laravel-permission-to-vuejs=dev-master


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now lets add the trait:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Spatie\Permission\Traits\HasRoles;
use LaravelAndVueJS\Traits\LaravelPermissionToVueJS;

class User extends Authenticatable
{
    use HasRoles;
    use LaravelPermissionToVueJS;
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Next, we'll need to expose the roles and permissions to the frontend. To do this we need to attach a &lt;code&gt;Laravel&lt;/code&gt; property to the &lt;code&gt;window&lt;/code&gt;. You can add this code into your main Blade template which loads everything for your frontend:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&amp;lt;script type="text/javascript"&amp;gt;
    window.Laravel = {
        csrfToken: "{{ csrf_token() }}",
        jsPermissions: {!! auth()-&amp;gt;user()?-&amp;gt;jsPermissions() !!}
    }
&amp;lt;/script&amp;gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The last step is to install the Vue javascript package, which also supports Vue 3:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npm install --save laravel-permission-to-vuejs

# Instruct Vue to use it
// ...
import LaravelPermissionToVueJS from 'laravel-permission-to-vuejs'

const app = createApp(App)
app.use(LaravelPermissionToVueJS)
// ...


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now we can use similar functions to Spatie's blade directives like &lt;code&gt;can()&lt;/code&gt; to check for a specific permission and &lt;code&gt;is()&lt;/code&gt; to check for specific roles. Here's a short example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&amp;lt;div v-if="can('can-view-posts')"&amp;gt;
    Only users with this permission can view this DIV.
&amp;lt;/div&amp;gt;

&amp;lt;div v-if="is('supervisor')"&amp;gt;
    Only users with this role can view this DIV.
&amp;lt;/div&amp;gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We can also pass multiple permissions or roles to check against. Example: &lt;code&gt;can('can-view-posts | can-edit-posts')&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That's pretty much it. Now you can enjoy using the same permissions you are using in the backend without creating a lot of mess in your Vue templates.&lt;/p&gt;

&lt;h4&gt;
  
  
  Support &amp;amp; follow me
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;a href="https://www.buymeacoffee.com/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FBuy_Me_A_Coffee-FFDD00%3Fstyle%3Dfor-the-badge%26logo%3Dbuy-me-a-coffee%26logoColor%3Dblack" alt="Buy me a coffee"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://twitter.com/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FTwitter-1DA1F2%3Fstyle%3Dfor-the-badge%26logo%3Dtwitter%26logoColor%3Dwhite" alt="Twitter"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://github.com/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FGitHub-100000%3Fstyle%3Dfor-the-badge%26logo%3Dgithub%26logoColor%3Dwhite" alt="GitHub"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://linkedin.com/in/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FLinkedIn-0077B5%3Fstyle%3Dfor-the-badge%26logo%3Dlinkedin%26logoColor%3Dwhite" alt="Linkedin"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>laravel</category>
      <category>spatie</category>
      <category>permission</category>
      <category>vue</category>
    </item>
    <item>
      <title>Why you should NEVER use Nulled Wordpress plugins and themes and why is this still a trend</title>
      <dc:creator>George Tudor</dc:creator>
      <pubDate>Sat, 29 Oct 2022 18:27:52 +0000</pubDate>
      <link>https://forem.com/staxwp/why-you-should-never-use-nulled-wordpress-plugins-and-themes-and-why-is-this-still-a-trend-5h7f</link>
      <guid>https://forem.com/staxwp/why-you-should-never-use-nulled-wordpress-plugins-and-themes-and-why-is-this-still-a-trend-5h7f</guid>
      <description>&lt;p&gt;Let's be honest, piracy has always been a trend on the internet. Software, games, movies and music have always been distributed for free via CDs, DVDs, USB Sticks and lately torrent sites.&lt;/p&gt;

&lt;p&gt;While this sounds awesome for the end consumer, businesses suffer because of this. We all got some unauthorized copies of different things back in the days... and it felt great, not gonna lie. But it all comes with a risk and that risk is called &lt;strong&gt;malware&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We, at Stax, develop &lt;a href="https://staxwp.com/"&gt;Wordpress plugins&lt;/a&gt; &amp;amp; themes. Most of our plugins and themes are released as a freemium package, meaning there's a Free version and a Pro version. That's the main trend in the Wordpress community and we'd like to stick with that.&lt;/p&gt;

&lt;p&gt;All of our Free plugins are really generous in terms of options and functionality. We try to offer as much free functionality as possible to help regular users with their daily needs. The Pro versions of some of our plugins contain a lot more functionality which helps users achieve even more.&lt;/p&gt;

&lt;p&gt;Converting Free users into Pro users is sometimes hard, but not impossible. However, some users prefer to get the Pro version of different plugins from doggy sites that offer them for free or a lot cheaper than the main developer's price.&lt;/p&gt;

&lt;p&gt;Why is this happening? Well, there are lots of reasons, but here's what my findings are:&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing
&lt;/h2&gt;

&lt;p&gt;Some plugin developers tend to price their Pro version using multiple subscription tiers. The most common practices are a yearly subscription and a lifetime offer.&lt;/p&gt;

&lt;p&gt;Unfortunately even a yearly subscription seems to be too much for an end user, specially if they need the plugin just for a short period of time or they are not sure if their business will succeed... so a big investment is not justified by these circumstances.&lt;/p&gt;

&lt;p&gt;The price itself is also an issue for some potential customers. Really popular plugins or themes creators tend to price their products higher than their competitors just because their popular. This doesn't really mean their products are better than their competitors, but they have enough exposure to leverage this opportunity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trust issues
&lt;/h2&gt;

&lt;p&gt;I think the more you know about the Wordpress ecosystem, the easier it will be to know what you want. However, uncertainties can occur on both sides.&lt;br&gt;&lt;br&gt;
Trust issues usually rise for 4 reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The user don't really know if the tool they're going to purchase will get the job done.&lt;/li&gt;
&lt;li&gt;The product doesn't have a Free version the user can try before purchasing.&lt;/li&gt;
&lt;li&gt;The product doesn't have reviews.&lt;/li&gt;
&lt;li&gt;The product's author has a bad reputation or no reputation at all.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Now let's talk about the elephant in the room&lt;/strong&gt;, those so called "nulled" sites, which are distributing Pro versions of plugins and themes for free.&lt;/p&gt;

&lt;p&gt;There's a general rule in life: "Nothing is free". If you think these Pro plugins are free, then you're wrong and naive. There's always a price your have to pay, but in this case isn't money, it's your security and privacy.&lt;/p&gt;

&lt;p&gt;Here are the top 2 problems with Nulled plugins and themes and why you should NEVER trust them:&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Malware
&lt;/h2&gt;

&lt;p&gt;The most important issue is that 99% of the time they contain malicious code. &lt;/p&gt;

&lt;p&gt;It's usually a shell script that compromises your entire server and offers it on a silver plate to the software distributor.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. What you get is not actually what you want
&lt;/h2&gt;

&lt;p&gt;Most of the times, the nulled software distributor claims to provide the latest version of the plugin or theme you are looking for. Well, in most of the cases all you will get is an old Pro version which probably is no longer compatible with the current Free version.&lt;br&gt;
But... it can get worse. You might get just a malware and that's it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Are nulled plugins and themes distributors a bad thing for the &lt;br&gt;
Wordpress community? Definitely YES! Unfortunately, there's nothing we can do about it, except to raise awareness and show users what should they expect when they go on this road.&lt;/p&gt;

&lt;p&gt;As long as end users will search for nulled software, these sites won't go away. If 10 are terminated today, 20 will appear out of thin air tomorrow.&lt;/p&gt;

&lt;p&gt;So be responsible, do your homework and think twice before falling into this trap. &lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>nulled</category>
      <category>security</category>
    </item>
    <item>
      <title>Dealing with SVG icons in Vue + Vite</title>
      <dc:creator>George Tudor</dc:creator>
      <pubDate>Mon, 24 Oct 2022 06:31:41 +0000</pubDate>
      <link>https://forem.com/geowrgetudor/dealing-with-svg-icons-in-vue-vite-an9</link>
      <guid>https://forem.com/geowrgetudor/dealing-with-svg-icons-in-vue-vite-an9</guid>
      <description>&lt;p&gt;Recently I've converted a Vue project that was using Webpack to Vite. All went smooth until I've discovered that Vite doesn't support &lt;code&gt;require()&lt;/code&gt; out of the box.&lt;br&gt;
I'm using some custom SVG icons that I'm keeping in a folder call obviously &lt;code&gt;svg&lt;/code&gt;. With Webpack it was easy to import them and I had several alternatives on how to do it. &lt;br&gt;
To load them I was using &lt;a href="https://www.npmjs.com/package/vue-inline-svg" rel="noopener noreferrer"&gt;vue-inline-svg&lt;/a&gt; plus a custom Vue component that wraps around this package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
    &amp;lt;InlineSvg
        :src="require(`@/svg/${name}.svg`)"
        class="fill-current"
    /&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
import InlineSvg from "vue-inline-svg";

export default {
    components: { InlineSvg },
    props: {
        name: {
            type: String,
            required: true,
        },
    },
};
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is just a simple custom Vue component that accepts a &lt;code&gt;prop&lt;/code&gt; called &lt;code&gt;name&lt;/code&gt; and loads &lt;code&gt;&amp;lt;InlineSvg /&amp;gt;&lt;/code&gt; under the hood.&lt;br&gt;
As a side note, &lt;strong&gt;my custom component called &lt;code&gt;icon&lt;/code&gt; is defined as a global component inside the &lt;code&gt;app.js&lt;/code&gt; file&lt;/strong&gt;, so I can use it all over the place:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Icon from "@/components/Icon.vue"; 

const app = createApp({ render: () =&amp;gt; h(App, props) })
            .component("icon", Icon);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;icon name="some-icon-name" /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;This approach was simple&lt;/strong&gt;, &lt;strong&gt;but&lt;/strong&gt; unfortunately &lt;strong&gt;it's NOT working out of the box with Vite&lt;/strong&gt;, so let's fix it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution 1: Adding back require()
&lt;/h2&gt;

&lt;p&gt;Probably the easiest way to fix this is to use &lt;a href="https://www.npmjs.com/package/vite-plugin-require" rel="noopener noreferrer"&gt;vite-plugin-require&lt;/a&gt; which adds support for &lt;code&gt;require()&lt;/code&gt; to Vite.&lt;br&gt;
You should not see any breaking changes while using this and I believe it's the most elegant way to do it if you're already using &lt;code&gt;require()&lt;/code&gt; to load your SVGs.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update:&lt;/em&gt; I've noticed a bug while using this method in Vite 3.x&lt;/p&gt;
&lt;h2&gt;
  
  
  Solution 2: Importing SVGs as components
&lt;/h2&gt;

&lt;p&gt;This is what I personally use and I think it's the most elegant way of doing it.&lt;/p&gt;

&lt;p&gt;If you are not using any SVG loader or/and a custom Vue component as a wrapper, you can use &lt;a href="https://www.npmjs.com/package/vite-svg-loader" rel="noopener noreferrer"&gt;vite-svg-loader&lt;/a&gt; which allows you to tap straight into the SVG and import it as a Vue component.&lt;br&gt;
More than that you can go a step forward and a custom wrapper over it to achieve something similar with the other 2 solutions, by making use of dynamic components.&lt;/p&gt;

&lt;p&gt;To set it up you first need to install it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i vite-svg-loader
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next you need to add this plugin to your &lt;code&gt;vite.config.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import svgLoader from 'vite-svg-loader';

export default defineConfig({
  plugins: [
    // ...
    svgLoader(),
  ],

});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can import each SVG as component, url or raw... but importing each SVG individually will make a huge mess into our project.&lt;/p&gt;

&lt;p&gt;To fix this issue, we can create a component that will dynamically load the SVG we want:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup&amp;gt;
import { defineAsyncComponent } from 'vue';

const props = defineProps({
  name: {
    type: String,
    required: true,
  },
});

const icon = defineAsyncComponent(() =&amp;gt;
  import(`../assets/svg/${props.name}.svg`)
);
&amp;lt;/script&amp;gt;

&amp;lt;template&amp;gt;
  &amp;lt;component :is="icon" class="fill-current" /&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can use this new component by importing it whenever you need it in your project or add it as a global into your &lt;code&gt;app.js&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;icon name="user" /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Solution 3: Adding your SVGs as Vue components
&lt;/h2&gt;

&lt;p&gt;While I do not recommend this, it might be helpful if you have just a few icons you need to include and reuse here and there. This is more or less a brainless approach, but it works if you're lazy.&lt;br&gt;
So what you can do is to define your SVGs into separate Vue components. Example this &lt;code&gt;Check.vue&lt;/code&gt; placed inside the &lt;code&gt;icons&lt;/code&gt; folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
    &amp;lt;svg
        xmlns="http://www.w3.org/2000/svg"
        viewBox="0 0 32 32"
        class="fill-current"
    &amp;gt;
        &amp;lt;path
            d="M 28.28125 6.28125 L 11 23.5625 L 3.71875 16.28125 L 2.28125 17.71875 L 10.28125 25.71875 L 11 26.40625 L 11.71875 25.71875 L 29.71875 7.71875 Z"
        /&amp;gt;
    &amp;lt;/svg&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we also need to have a helper component called &lt;code&gt;&amp;lt;Icon /&amp;gt;&lt;/code&gt; that we can define as global. Inside this we can make use of dynamic components and load the &lt;code&gt;.vue&lt;/code&gt; SVGs dynamically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
    &amp;lt;component :is="dynamicComponent" /&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
import { defineAsyncComponent } from "vue";

export default {
    props: {
        name: {
            type: String,
            required: true,
        },
    },

    computed: {
        dynamicComponent() {
            const name = this.name.charAt(0).toUpperCase() + this.name.slice(1);

            return defineAsyncComponent(() =&amp;gt; import(`./icons/${name}.vue`));
        },
    },
};
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To use the global component, you can do the same thing as in the legacy code I've presented in the begining:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;icon name="check" /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's pretty much it. What method do you prefer?&lt;/p&gt;

&lt;h4&gt;
  
  
  Support &amp;amp; follow me
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;a href="https://www.buymeacoffee.com/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FBuy_Me_A_Coffee-FFDD00%3Fstyle%3Dfor-the-badge%26logo%3Dbuy-me-a-coffee%26logoColor%3Dblack" alt="Buy me a coffee" width="161" height="28"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://twitter.com/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FTwitter-1DA1F2%3Fstyle%3Dfor-the-badge%26logo%3Dtwitter%26logoColor%3Dwhite" alt="Twitter" width="83" height="28"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://github.com/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FGitHub-100000%3Fstyle%3Dfor-the-badge%26logo%3Dgithub%26logoColor%3Dwhite" alt="GitHub" width="95" height="28"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://linkedin.com/in/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FLinkedIn-0077B5%3Fstyle%3Dfor-the-badge%26logo%3Dlinkedin%26logoColor%3Dwhite" alt="Linkedin" width="111" height="28"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>vite</category>
      <category>vue</category>
      <category>svg</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Migrating Laravel 9 with Inertia.js + Vue.js + Tailwind CSS from Laravel Mix (Webpack) to Vite</title>
      <dc:creator>George Tudor</dc:creator>
      <pubDate>Sun, 23 Oct 2022 14:30:31 +0000</pubDate>
      <link>https://forem.com/geowrgetudor/migrating-laravel-9-with-inertiajs-vuejs-tailwind-css-from-laravel-mix-webpack-to-vite-53dp</link>
      <guid>https://forem.com/geowrgetudor/migrating-laravel-9-with-inertiajs-vuejs-tailwind-css-from-laravel-mix-webpack-to-vite-53dp</guid>
      <description>&lt;p&gt;Back in February this year I was writing &lt;a href="https://dev.to/geowrgetudor/setting-up-laravel-with-inertiajs-vuejs-tailwind-css-21pc"&gt;this&lt;/a&gt; guide on how to setup Inertia.js + Vue.js + Tailwind CSS on a brand new Laravel 8 project.&lt;br&gt;
That guide also worked for the early releases of Laravel 9, but a few months later Laravel took a strange turn switching from Webpack to Vite in a minor release.&lt;br&gt;
While Webpack was and still is ok for anyone who's using it, I was surprise to see this sudden shift during a minor release.&lt;br&gt;
Aaaaanyway, let's move on and dig into the fun stuff.&lt;/p&gt;
&lt;h2&gt;
  
  
  What's Vite and how does it work?
&lt;/h2&gt;

&lt;p&gt;Vite is a great open-source frontend tool built by Evan You, the same guy behind Vue. It offers live reload out of the box, really user friendly and easy to understand syntax and it's faaaast. You can find more info about "why" is it great &lt;a href="https://vitejs.dev/guide/why.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Vite vs Laravel Mix (Webpack). Ease of use
&lt;/h2&gt;

&lt;p&gt;Here are just my 2 cents. I've been using Webpack since forever and I can say for sure that switching to Vite was like moving from a good apartment to a penthouse. Vite is so much easy to use.&lt;/p&gt;
&lt;h2&gt;
  
  
  Installing Vite and Vite related packages
&lt;/h2&gt;

&lt;p&gt;Before we start, let's remove all the Laravel Mix/Webpack related stuff installed in the previous guide. So we can get rid of the following packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm uninstall laravel-mix webpack-shell-plugin-next
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we need to add all the Vite related packages. By default, Laravel ships only with the &lt;code&gt;vite&lt;/code&gt; package but we need a bit more in order to support Inertia.js, Tailwind CSS and Vue.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Make sure your have Node v.16+ installed
npm install --save-dev vite laravel-vite-plugin @vitejs/plugin-vue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setting up vite.config.js
&lt;/h2&gt;

&lt;p&gt;First we need to remove the old &lt;code&gt;webpack.mix.js&lt;/code&gt; file because we no longer need it. If you have other stuff in there (not related to this guide) make sure you port them to your new &lt;code&gt;vite.config.js&lt;/code&gt; file.&lt;br&gt;
Now let's create a blank new &lt;code&gt;vite.config.js&lt;/code&gt; file and add the default scaffolding:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';

export default defineConfig({
    plugins: [
        laravel({
            input: ['resources/css/app.css', 'resources/js/app.js'],
            refresh: true,
        }),
    ],
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we have to import the Vue plugin for Vite and include it into the plugins section. We're also going to remove the &lt;code&gt;app.css&lt;/code&gt; input since we'll include the CSS in our &lt;code&gt;app.js&lt;/code&gt;.&lt;br&gt;
So our new config will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
    plugins: [
        laravel({
            input: ['resources/js/app.js'],
            refresh: true,
        }),
        vue({
            template: {
                transformAssetUrls: {
                    base: null,
                    includeAbsolute: false,
                },
            },
        }),
    ],
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Post CSS config
&lt;/h2&gt;

&lt;p&gt;Since we're importing &lt;code&gt;app.css&lt;/code&gt; directly into Vue, we're going to need a &lt;code&gt;postcss.config.js&lt;/code&gt; file to define our PostCSS plugins:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports = {
    plugins: [
        require('postcss-import'),
        require('tailwindcss')
    ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you don't have &lt;code&gt;postcss&lt;/code&gt; installed, feel free to add it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save-dev postcss-import
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Let's not forget about Ziggy
&lt;/h2&gt;

&lt;p&gt;We've used Ziggy in our previous guide and we're still going to use it now. In order for Vite to resolve it we have to define some aliases in &lt;code&gt;vite.config.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So our final version of the config will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
    plugins: [
        laravel({
            input: ['resources/js/app.js'],
            refresh: true,
        }),
        vue({
            template: {
                transformAssetUrls: {
                    base: null,
                    includeAbsolute: false,
                },
            },
        }),
    ],
    resolve: {
        alias: {
            'ziggy': '/vendor/tightenco/ziggy/src/js',
            'ziggy-vue': '/vendor/tightenco/ziggy/src/js/vue'
        },
    },
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Adding assets to our main template
&lt;/h2&gt;

&lt;p&gt;When we were using Webpack, we had include multiple lines of code in our main templating. It was looking like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;link href="{{ asset(mix('css/app.css')) }}" rel="stylesheet"&amp;gt;
&amp;lt;script src="{{ asset(mix('js/manifest.js')) }}" defer&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src="{{ asset(mix('js/vendor.js')) }}" defer&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src="{{ asset(mix('js/app.js')) }}" defer&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We had the &lt;code&gt;app.css&lt;/code&gt; file, the &lt;code&gt;manifest.js&lt;/code&gt;, &lt;code&gt;ventor.js&lt;/code&gt; and lastly our &lt;code&gt;app.js&lt;/code&gt;. While this was not bad at all, with Vite things are more simpler.&lt;br&gt;
All we have to do is to replace the previously mentioned lines with the following Blade directive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@vite('resources/js/app.js') 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Adapting your Vue files
&lt;/h2&gt;

&lt;p&gt;First you need to know that &lt;code&gt;require()&lt;/code&gt; is no longer available while using Vite. So you will need to change all your code that does that.&lt;br&gt;
So for example this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;window.Pusher = require('pusher-js');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Will become this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Pusher from 'pusher-js';
window.Pusher = Pusher;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;.vue&lt;/code&gt; file extention is required for all your imports. So this will throw an error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Icon from "@/components/Icon"; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will need to add the file extention:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Icon from "@/components/Icon.vue"; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note&lt;/em&gt; that the &lt;code&gt;@&lt;/code&gt; alias is already defined in the Laravel plugin, so you no longer have to define it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finally, let's deal with app.js
&lt;/h2&gt;

&lt;p&gt;This is our old &lt;code&gt;app.js&lt;/code&gt; file that we used in the previous guide. It won't work out of the box, so we'll have to modify it a little bit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { createApp, h } from "vue";
import { createInertiaApp, Link, Head } from "@inertiajs/inertia-vue3";
import { InertiaProgress } from "@inertiajs/progress";

import { ZiggyVue } from "ziggy";
import { Ziggy } from "./ziggy";

InertiaProgress.init();

createInertiaApp({
    resolve: async (name) =&amp;gt; {
        return (await import(`./Pages/${name}`)).default;
    },
    setup({ el, App, props, plugin }) {
        createApp({ render: () =&amp;gt; h(App, props) })
            .use(plugin)
            .use(ZiggyVue, Ziggy)
            .component("Link", Link)
            .component("Head", Head)
            .mixin({ methods: { route } })
            .mount(el);
    },
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to import &lt;code&gt;resolvePageComponent&lt;/code&gt; from the Laravel plugin and change our &lt;code&gt;resolve&lt;/code&gt; function + to change the &lt;code&gt;ZiggyVue&lt;/code&gt; import + to import our CSS. So the final version will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { createApp, h } from "vue";
import { createInertiaApp, Link, Head } from "@inertiajs/inertia-vue3";
import { InertiaProgress } from "@inertiajs/progress";
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';

import { ZiggyVue } from "ziggy-vue";
import { Ziggy } from "./ziggy";
import '../css/app.css';

InertiaProgress.init();

createInertiaApp({
    resolve: async (name) =&amp;gt; resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob('./Pages/**/*.vue')),
    setup({ el, App, props, plugin }) {
        createApp({ render: () =&amp;gt; h(App, props) })
            .use(plugin)
            .use(ZiggyVue, Ziggy)
            .component("Link", Link)
            .component("Head", Head)
            .mixin({ methods: { route } })
            .mount(el);
    },
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's pretty much it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building your app
&lt;/h2&gt;

&lt;p&gt;Last thing we need to do is to change our &lt;code&gt;package.json&lt;/code&gt;'s scripts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "dev": "vite",
    "build": "vite build"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, in order to build you will have to firstly generate the &lt;code&gt;ziggy.js&lt;/code&gt; file by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// You can find this command in the previous guide
php artisan ziggy:generate resources/js/ziggy.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you can run the &lt;code&gt;dev&lt;/code&gt; or &lt;code&gt;build&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, make sure you clear your view cache because this might cause some issues after the migrations: &lt;code&gt;php artisan view:cache&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For more info you can always check the official Laravel's migration guide &lt;a href="https://github.com/laravel/vite-plugin/blob/main/UPGRADE.md#migrating-from-laravel-mix-to-vite" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extra
&lt;/h2&gt;

&lt;p&gt;If you want to run commands during Vite compilation you can use &lt;a href="https://github.com/innocenzi/vite-plugin-run" rel="noopener noreferrer"&gt;innocenzi/vite-plugin-run&lt;/a&gt;. This will make it easy to run &lt;code&gt;php artisan ziggy:generate resources/js/ziggy.js&lt;/code&gt; whenever your routes get changed or when deploying to production.&lt;/p&gt;

&lt;h4&gt;
  
  
  Support &amp;amp; follow me
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;a href="https://www.buymeacoffee.com/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FBuy_Me_A_Coffee-FFDD00%3Fstyle%3Dfor-the-badge%26logo%3Dbuy-me-a-coffee%26logoColor%3Dblack" alt="Buy me a coffee"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://twitter.com/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FTwitter-1DA1F2%3Fstyle%3Dfor-the-badge%26logo%3Dtwitter%26logoColor%3Dwhite" alt="Twitter"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://github.com/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FGitHub-100000%3Fstyle%3Dfor-the-badge%26logo%3Dgithub%26logoColor%3Dwhite" alt="GitHub"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://linkedin.com/in/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FLinkedIn-0077B5%3Fstyle%3Dfor-the-badge%26logo%3Dlinkedin%26logoColor%3Dwhite" alt="Linkedin"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>vite</category>
      <category>laravel</category>
      <category>inertiaj</category>
      <category>vue</category>
    </item>
    <item>
      <title>Using Laravel's Illuminate Validation in any PHP project</title>
      <dc:creator>George Tudor</dc:creator>
      <pubDate>Sat, 19 Feb 2022 14:12:05 +0000</pubDate>
      <link>https://forem.com/geowrgetudor/using-laravels-illuminate-validation-in-any-php-project-4hoh</link>
      <guid>https://forem.com/geowrgetudor/using-laravels-illuminate-validation-in-any-php-project-4hoh</guid>
      <description>&lt;p&gt;I'm developing a Wordpress plugin that requires strict data for the frontend. The frontend is built with Vue.js and it's basically a multistep wizard where every step is represented by a specific Vue component.&lt;/p&gt;

&lt;h2&gt;
  
  
  A little bit of context
&lt;/h2&gt;

&lt;p&gt;I want to give the freedom to any developer that's going to use this wizard to pass any step they want in any order they want. On the backend side, each step is represented by a class that's instantiated as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;new \StaxWp\Gandalf\Core\Components\YoutubeVideo(
    [
        'title'       =&amp;gt; '',
        'description' =&amp;gt; '',
        'url'         =&amp;gt; '',
        'autoplay'    =&amp;gt; false,
    ],
    1,
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a step that contains a &lt;code&gt;title&lt;/code&gt;, a &lt;code&gt;description&lt;/code&gt;, an &lt;code&gt;url&lt;/code&gt; and an option to &lt;code&gt;autoplay&lt;/code&gt;. Every step accepts in its constructor an array of data and an int for priority. Because we're humans and we can make mistakes I need to make sure all the fields from the array have specific values.&lt;/p&gt;

&lt;p&gt;If you are familiar with Laravel, you know how the validation works. We can use the same validation outside Laravel. This is how I enforced validation rules for my step's data array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;final class YoutubeVideo extends Step {

    /**
     * YoutubeVideo constructor
     *
     * @param array   $data
     * @param integer $priority
     */
    public function __construct( array $data, int $priority = 0 ) {
        parent::__construct( $data, $priority );

        $this-&amp;gt;add_validation_rules(
            [
                'title'       =&amp;gt; 'sometimes|required|string|nullable',
                'description' =&amp;gt; 'sometimes|required|string|nullable',
                'url'         =&amp;gt; [ 'required', 'string', 'regex:/^(https?\:\/\/)?(www\.)?(youtube\.com|youtu\.be)\/watch\?v\=\w+$/' ],
                'autoplay'    =&amp;gt; 'required|boolean',
            ]
        );
    }

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This of course won't work out of the box, so first we'll need to install &lt;code&gt;illuminate/validation&lt;/code&gt; and &lt;code&gt;illuminate/translation&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up the requirements
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer require illuminate/validation
composer require illuminate/translation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we need to include the following in our class...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use Illuminate\Container\Container;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Translation\FileLoader;
use Illuminate\Translation\Translator;
use Illuminate\Validation\Factory;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;...then declare our private variable for validation and validation rules...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
* Step data validator
*
* @var Factory
*/
private $validation;

/**
* Step data validation rules
*
* @var array
*/
private $validation_rules = [];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;... and then we need instantiate our validator in the constructor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$loader           = new FileLoader( new Filesystem(), 'lang' );
$translator       = new Translator( $loader, 'en' );
$this-&amp;gt;validation = new Factory( $translator, new Container() );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'm not gonna add any localization files for the error messages because I won't display them. Everytime the validator fails I'm gonna throw an exception.&lt;/p&gt;

&lt;h2&gt;
  
  
  Actually doing the validation
&lt;/h2&gt;

&lt;p&gt;Every step is casted to array and converted to JSON and then passed to the Vue, so where do I do the validation? In the array casting function of course:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
* Get step as array
*
* @return mixed
*/
public function to_array() {
    $this-&amp;gt;validate_data();

    return get_object_vars( $this );
}

/**
* Validate step's data
*
* @return mixed
*/
protected function validate_data() {
    if ( ! empty( $this-&amp;gt;data() ) &amp;amp;&amp;amp; empty( $this-&amp;gt;validation_rules ) ) {
        throw new Exception( $this-&amp;gt;type() . ' has data but no validation rules.' );
    }

    $validator = $this-&amp;gt;validation-&amp;gt;make( $this-&amp;gt;data(), $this-&amp;gt;validation_rules );

    if ( $validator-&amp;gt;fails() ) {
        throw new Exception( $this-&amp;gt;type() . ' has an incorrect data format.' );
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By doing this I know for sure that my &lt;code&gt;$data&lt;/code&gt; array has all the required fields and each field has the required value.&lt;/p&gt;

&lt;p&gt;I hope you've found this short tutorial useful.&lt;/p&gt;

&lt;h4&gt;
  
  
  Support &amp;amp; follow me
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;a href="https://www.buymeacoffee.com/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FBuy_Me_A_Coffee-FFDD00%3Fstyle%3Dfor-the-badge%26logo%3Dbuy-me-a-coffee%26logoColor%3Dblack" alt="Buy me a coffee"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://twitter.com/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FTwitter-1DA1F2%3Fstyle%3Dfor-the-badge%26logo%3Dtwitter%26logoColor%3Dwhite" alt="Twitter"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://github.com/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FGitHub-100000%3Fstyle%3Dfor-the-badge%26logo%3Dgithub%26logoColor%3Dwhite" alt="GitHub"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://linkedin.com/in/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FLinkedIn-0077B5%3Fstyle%3Dfor-the-badge%26logo%3Dlinkedin%26logoColor%3Dwhite" alt="Linkedin"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>validation</category>
      <category>php</category>
      <category>laravel</category>
      <category>illuminate</category>
    </item>
    <item>
      <title>How to setup Wordpress coding standard rules in VS Code</title>
      <dc:creator>George Tudor</dc:creator>
      <pubDate>Fri, 18 Feb 2022 08:41:12 +0000</pubDate>
      <link>https://forem.com/staxwp/how-to-setup-wordpress-coding-standard-rules-in-vs-code-1dhi</link>
      <guid>https://forem.com/staxwp/how-to-setup-wordpress-coding-standard-rules-in-vs-code-1dhi</guid>
      <description>&lt;p&gt;I see a lot of code that's not following any standards. Especially in the Wordpress community.&lt;/p&gt;

&lt;p&gt;I don't hate it because it does the job done, but if you try to debug it or understand it you're gonna have a bad time. Unreadable code is awful.&lt;/p&gt;

&lt;p&gt;We, at &lt;a href="https://staxwp.com/" rel="noopener noreferrer"&gt;StaxWP&lt;/a&gt;, always use Wordpress coding standards in our themes and plugins. It's easy to implement it, let me show you.&lt;/p&gt;

&lt;h2&gt;
  
  
  What coding standard does Wordpress follow?
&lt;/h2&gt;

&lt;p&gt;Wordpress follows Pear coding standards but with some twists. There are some characteristics that are present only in Wordpress.&lt;/p&gt;

&lt;p&gt;Here are some examples:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

// Spatiate
$x = $foo[ $bar ]; // correct
$x = $foo[$bar]; // incorrect

// Yoda conditions
$x = 2 === $i; // correct
$x = $i === 2; // incorrect


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  So what do we do to fix these things automatically?
&lt;/h2&gt;

&lt;p&gt;We use &lt;a href="https://github.com/WordPress/WordPress-Coding-Standards" rel="noopener noreferrer"&gt;WordPress Coding Standards for PHP_CodeSniffer (WPCS)&lt;/a&gt; which uses Squizlabs' PHP codesniffer (phpcs) and beautifier &amp;amp; fixer (phpcbf) under the hood to scan and format the code.&lt;/p&gt;

&lt;p&gt;You can install WPCS globally or inside a project. I like to use it globally inside Ubuntu WSL2, but this guide will work for any setup. First we need to clone the repository in some location. I've picked the &lt;code&gt;home&lt;/code&gt; directory:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

git clone git@github.com:WordPress/WordPress-Coding-Standards.git


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Install the dependencies:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

cd WordPress-Coding-Standards
composer install


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now we have &lt;code&gt;phpcs&lt;/code&gt; and &lt;code&gt;phpcbf&lt;/code&gt; installed in &lt;code&gt;vendor/squizlabs/php_codesniffer/bin&lt;/code&gt; and we can use them in VS Code.&lt;/p&gt;

&lt;p&gt;For VS Code we're using the &lt;a href="https://marketplace.visualstudio.com/items?itemName=ValeryanM.vscode-phpsab" rel="noopener noreferrer"&gt;PHP Sniffer &amp;amp; Beautifier&lt;/a&gt; extension. We just need to install it, add the paths to &lt;code&gt;phpcs&lt;/code&gt; and &lt;code&gt;phpcbf&lt;/code&gt; and tell it what coding standards to use.&lt;/p&gt;

&lt;p&gt;After we've installed it, we go ahead and press &lt;code&gt;Ctrl/Cmd + Shift + P&lt;/code&gt; inside VS Code and search for &lt;code&gt;settings.json&lt;/code&gt;. There will be 4 different files with the same name:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Workspace Settings: referring to the current project's settings&lt;/li&gt;
&lt;li&gt;Remote Settings: referring to the user's settings but inside WSL/Docker&lt;/li&gt;
&lt;li&gt;Settings: referring to the user's settings on current machine&lt;/li&gt;
&lt;li&gt;Default Settings: containing the default settings (we don't want to touch these)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Depending on your setup you will want to set these coding standards per user or per workspace. I suggest you set them per user and overwrite them per workspace whenever you have to.&lt;/p&gt;

&lt;p&gt;So were going to open the user's settings and add the following lines:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;"files.autoSave": "onWindowChange",&lt;br&gt;
"editor.linkedEditing": true,&lt;br&gt;
"editor.tabSize": 4,&lt;br&gt;
"editor.detectIndentation": false,&lt;br&gt;
"editor.formatOnSave": true,&lt;br&gt;
"window.title": "${activeEditorLong}${separator}${rootName}",&lt;br&gt;
"phpsab.standard": "WordPress",&lt;br&gt;
"phpsab.snifferEnable": true, // disable this if you don't need suggestions&lt;br&gt;
"phpsab.executablePathCBF": "{PATH}/WordPress-Coding-Standards/vendor/squizlabs/php_codesniffer/bin/phpcbf",&lt;br&gt;
"phpsab.executablePathCS": "{PATH}/WordPress-Coding-Standards/vendor/squizlabs/php_codesniffer/bin/phpcs",&lt;br&gt;
"phpsab.snifferShowSources": true&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Make sure to replace &lt;code&gt;{PATH}&lt;/code&gt; with the correct path to your &lt;code&gt;WordPress-Coding-Standards&lt;/code&gt; folder. Also, if you are on Windows and you don't use WSL2, you will need to refer to &lt;code&gt;phpcbf.bat&lt;/code&gt; and &lt;code&gt;phpcs.bat&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now we are pretty much set. Everytime we need some other coding standard we can overwrite it in our current workspace by adding &lt;code&gt;phpsab.standard&lt;/code&gt; and specifying the standard.&lt;/p&gt;

&lt;p&gt;Here's a short example of what will happen everytime you will have some badly formatted:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbo6p5hiv6cppe3lqvlvh.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbo6p5hiv6cppe3lqvlvh.gif" alt="formatting demo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's it! Enjoy.&lt;/p&gt;

&lt;h4&gt;
  
  
  Support &amp;amp; follow me
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;a href="https://www.buymeacoffee.com/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FBuy_Me_A_Coffee-FFDD00%3Fstyle%3Dfor-the-badge%26logo%3Dbuy-me-a-coffee%26logoColor%3Dblack" alt="Buy me a coffee"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://twitter.com/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FTwitter-1DA1F2%3Fstyle%3Dfor-the-badge%26logo%3Dtwitter%26logoColor%3Dwhite" alt="Twitter"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://github.com/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FGitHub-100000%3Fstyle%3Dfor-the-badge%26logo%3Dgithub%26logoColor%3Dwhite" alt="GitHub"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://linkedin.com/in/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FLinkedIn-0077B5%3Fstyle%3Dfor-the-badge%26logo%3Dlinkedin%26logoColor%3Dwhite" alt="Linkedin"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>wordpress</category>
      <category>coding</category>
      <category>vscode</category>
      <category>wsl2</category>
    </item>
    <item>
      <title>Server side rendering with Laravel + Inertia.js + Vue.js</title>
      <dc:creator>George Tudor</dc:creator>
      <pubDate>Tue, 15 Feb 2022 05:45:03 +0000</pubDate>
      <link>https://forem.com/geowrgetudor/server-side-rendering-with-laravel-inertiajs-vuejs-13ap</link>
      <guid>https://forem.com/geowrgetudor/server-side-rendering-with-laravel-inertiajs-vuejs-13ap</guid>
      <description>&lt;p&gt;&lt;strong&gt;Notice:&lt;/strong&gt; This is a guide for Laravel with Laravel Mix which is using Webpack under the hood. Soon I'll be writing a new one for Vite.&lt;/p&gt;

&lt;p&gt;SEO is really important so you should have SSR (server side rendering) whenever you are building a SPA (single page application). This is not an issue if you are using Laravel's default templating system, which is Blade, because everything is rendered on the server and the result gets directly shipped into the browser.&lt;/p&gt;

&lt;p&gt;In our case the rendering is done on the client side so our DOM is pretty empty. To solve this problem and make our website work even without Javascript enabled we'll need to somehow render everything on and the server side and serve all the resulted HTML on page-load.&lt;/p&gt;

&lt;p&gt;Luckily Inertia ships with some tools to help us tackle this issue.&lt;/p&gt;

&lt;p&gt;Let's add the following two packages to our project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @vue/server-renderer
npm install @inertiajs/server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are not using &lt;code&gt;-D&lt;/code&gt; or &lt;code&gt;--save-dev&lt;/code&gt; flag on these 2 packages because we also need to run them on our production sever. As a general rule for &lt;code&gt;composer.json&lt;/code&gt; and &lt;code&gt;package.json&lt;/code&gt;, the packages that are installed inside &lt;code&gt;require-dev&lt;/code&gt; respectively &lt;code&gt;devDependencies&lt;/code&gt; should be used only in a development environment.&lt;/p&gt;

&lt;p&gt;Next we need to create a server configuration file called &lt;code&gt;ssr.js&lt;/code&gt; inside the same folder as our &lt;code&gt;app.js&lt;/code&gt;, meaning &lt;code&gt;resources/js&lt;/code&gt;. This file will look very similar to our &lt;code&gt;app.js&lt;/code&gt; file, but instead  of being compiled and handled by the browser, it will be handled by Node.js.&lt;/p&gt;

&lt;p&gt;Our &lt;code&gt;ssr.js&lt;/code&gt; file should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { createSSRApp, h } from "vue";
import { renderToString } from "@vue/server-renderer";
import { createInertiaApp, Link, Head } from "@inertiajs/inertia-vue3";
import createServer from "@inertiajs/server";

import { ZiggyVue } from "ziggy";
import { Ziggy } from "./ziggy";

createServer((page) =&amp;gt;
    createInertiaApp({
        page,
        render: renderToString,
        resolve: (name) =&amp;gt; require(`./Pages/${name}`),
        setup({ app, props, plugin }) {
            return createSSRApp({
                render: () =&amp;gt; h(app, props),
            })
                .use(plugin)
                .use(ZiggyVue, Ziggy)
                .component("Link", Link)
                .component("Head", Head);
        },
    })
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that instead of &lt;code&gt;createApp&lt;/code&gt; we import &lt;code&gt;createSSRApp&lt;/code&gt; from Vue and we're also wrapping our &lt;code&gt;createInertiaApp&lt;/code&gt; method inside &lt;code&gt;createServer&lt;/code&gt; method. We also no longer import Inertia's progress bar because that won't be ever used on server-side.&lt;/p&gt;

&lt;p&gt;Next we'll need one more package to fully support our Node server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install webpack-node-externals
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we'll create a separate Webpack file called &lt;code&gt;webpack.ssr.mix.js&lt;/code&gt; which will be used by our Node.js server to compile the resources.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const path = require("path");
const mix = require("laravel-mix");
const webpackNodeExternals = require("webpack-node-externals");

// Rezolve Ziggy
mix.alias({
    ziggy: path.resolve("vendor/tightenco/ziggy/dist/vue"),
});

// Build files
mix.options({ manifest: false })
    .js("resources/js/ssr.js", "public/js")
    .vue({ version: 3, options: { optimizeSSR: true } })
    .alias({ "@": path.resolve("resources/js") })
    .webpackConfig({
        target: "node",
        externals: [webpackNodeExternals()],
    })
    .version();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see our &lt;code&gt;webpack.ssr.mix.js&lt;/code&gt; file is really similar to &lt;code&gt;webpack.mix.js&lt;/code&gt;. You'll need to always remember to also update your SSR webpack file everytime you update your default webpack file with something that can be used on the server-side. Now eveything that's gonna be used by our Node.js server will be bundled to &lt;code&gt;public/js/ssr.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now let's publish the Inertia's SSR config file...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan vendor:publish --provider="Inertia\ServiceProvider"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;...and enable the SSR in &lt;code&gt;config/inertia.php&lt;/code&gt; by changing the &lt;code&gt;enabled&lt;/code&gt; flag to &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The only thing that's left to be done now is to compile and to spin up our Node.js server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx mix --mix-config=webpack.ssr.mix.js
node public/js/ssr.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything's fine you should get a similar output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Starting SSR server on port 13714...
Inertia SSR server started.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can even disable the browser's Javascript and you'll still be able to navigate through the site because everything will be rendered on the server side by the Node.js server and served to your browser on page load.&lt;/p&gt;

&lt;p&gt;That's pretty much it.&lt;/p&gt;

&lt;p&gt;You can find everything we've talk about in Part 1 &amp;amp; 2 in this &lt;a href="https://github.com/geowrgetudor/laravel-inertia-vue-ssr" rel="noopener noreferrer"&gt;repo&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Support &amp;amp; follow me
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;a href="https://www.buymeacoffee.com/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FBuy_Me_A_Coffee-FFDD00%3Fstyle%3Dfor-the-badge%26logo%3Dbuy-me-a-coffee%26logoColor%3Dblack" alt="Buy me a coffee" width="161" height="28"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://twitter.com/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FTwitter-1DA1F2%3Fstyle%3Dfor-the-badge%26logo%3Dtwitter%26logoColor%3Dwhite" alt="Twitter" width="83" height="28"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://github.com/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FGitHub-100000%3Fstyle%3Dfor-the-badge%26logo%3Dgithub%26logoColor%3Dwhite" alt="GitHub" width="95" height="28"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://linkedin.com/in/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FLinkedIn-0077B5%3Fstyle%3Dfor-the-badge%26logo%3Dlinkedin%26logoColor%3Dwhite" alt="Linkedin" width="111" height="28"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>laravel</category>
      <category>vue</category>
      <category>tailwindcss</category>
      <category>inertiajs</category>
    </item>
    <item>
      <title>Must have Wordpress plugins in 2022. This list will save you time &amp; money</title>
      <dc:creator>George Tudor</dc:creator>
      <pubDate>Sat, 12 Feb 2022 22:06:43 +0000</pubDate>
      <link>https://forem.com/geowrgetudor/must-have-wordpress-plugins-in-2022-this-list-will-save-you-time-money-k6i</link>
      <guid>https://forem.com/geowrgetudor/must-have-wordpress-plugins-in-2022-this-list-will-save-you-time-money-k6i</guid>
      <description>&lt;p&gt;Have you ever wondered how many awesome Wordpress plugins, that you can use for your business, are out there in the wild and you haven't even heard of them? Some can do those little things that you have always dreamed of and some can even save you money.&lt;/p&gt;

&lt;h2&gt;
  
  
  How can a Wordpress plugin save you money?
&lt;/h2&gt;

&lt;p&gt;When you are looking for a particular functionality and you want to have it right away on your website, you are more likely to be willing to pay for it. However, there might be a free plugin that does exactly the same thing you need. You just need to dig deeper.&lt;/p&gt;

&lt;p&gt;Although this sounds awesome, you might also have to be a bit cautious because some free plugins, that are offering the same functionality as a paid plugin, can be harmful. A free plugin might not have the same coding standards as a premium plugin, it might not have optimized database queries, it might not get future updates, etc.. So sometimes a free plugin can be a double edged sword.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enough talking, let's get down to the plugins list
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;a href="https://wordpress.org/plugins/elementor/"&gt;Elementor&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;With over 5 million downloads, Elementor is the most popular plugin out there. Using it you can basically build a website in no time and you can use it with any theme.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;a href="https://wordpress.org/plugins/wp-optimize/"&gt;WP-Optimize&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This is probably my favourite caching plugin and I prefer it over other plugins. It will help you optimize your website and it will give you a big boost in terms of loading speed which will also help your SEO.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;a href="https://wordpress.org/plugins/wordpress-seo/"&gt;Yoast SEO&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Speaking of SEO, you must have Yoast SEO. It will add all the necessary meta tags, Facebook &amp;amp; Twitter Open Graph and much more. If you really rely on SEO you definitely need this.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. &lt;a href="https://wordpress.org/plugins/wp-smushit/"&gt;Smush – Lazy Load Images&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This goes hand in hand with any caching plugin. Smush is really awesome and helps you optimize and lazy-load your images so it will inevitably boost your page speed.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. &lt;a href="https://wordpress.org/plugins/buddypress/"&gt;BuddyPress&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;If you are building a community, you can use the most popular community plugin our there. BuddyPress is awesome and it has many 3rd party addons you can use alongside. Me and my team have built an awesome plugin that let's you build BuddyPress pages using Elementor. It's called &lt;a href="https://wordpress.org/plugins/stax-buddy-builder/"&gt;BuddyPress builder for Elementor - BuddyBuilder&lt;/a&gt; and it's free.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. &lt;a href="https://wordpress.org/plugins/woocommerce/"&gt;WooCommerce&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;If you want to sell stuff online, WooCommerce is the way to go. It has everything you need and it also has lots of official plugins. The only downside of WooCommerce is that you either need a powerful theme that has a solid integration with WooCommerce or you get the pro version of Elementor and some other 3rd party plugins that have Elementor widgets and you build your pages yourself.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. &lt;a href="https://wordpress.org/plugins/wordfence/"&gt;Wordfence Security&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;In terms of security, Wordfence is really powerfull. I mostly use it to protect my sites against brute-force attacks. You might not notice anything wrong if you don't have any security plugin installed, but you will be surprised when you'll see that your login form gets bombarded.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;There are lots of other useful plugins and for sure you will find the one you need. Just make sure you give a chance to any plugin, not only highly rated plugins.&lt;/p&gt;

&lt;h4&gt;
  
  
  Support &amp;amp; follow me
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;a href="https://www.buymeacoffee.com/geowrgetudor"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MoWemOxj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/Buy_Me_A_Coffee-FFDD00%3Fstyle%3Dfor-the-badge%26logo%3Dbuy-me-a-coffee%26logoColor%3Dblack" alt="Buy me a coffee" width="162" height="28"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://twitter.com/geowrgetudor"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6ibmId_t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/Twitter-1DA1F2%3Fstyle%3Dfor-the-badge%26logo%3Dtwitter%26logoColor%3Dwhite" alt="Twitter" width="100" height="28"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://github.com/geowrgetudor"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X0Hgo7Mj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/GitHub-100000%3Fstyle%3Dfor-the-badge%26logo%3Dgithub%26logoColor%3Dwhite" alt="GitHub" width="92" height="28"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://linkedin.com/in/geowrgetudor"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bpeFljpm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.shields.io/badge/LinkedIn-0077B5%3Fstyle%3Dfor-the-badge%26logo%3Dlinkedin%26logoColor%3Dwhite" alt="Linkedin" width="107" height="28"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>wordpress</category>
      <category>plugins</category>
    </item>
    <item>
      <title>10 Laravel packages that might save your day</title>
      <dc:creator>George Tudor</dc:creator>
      <pubDate>Fri, 11 Feb 2022 08:56:22 +0000</pubDate>
      <link>https://forem.com/geowrgetudor/10-laravel-packages-that-might-save-your-day-3dl9</link>
      <guid>https://forem.com/geowrgetudor/10-laravel-packages-that-might-save-your-day-3dl9</guid>
      <description>&lt;p&gt;Here's a relatively short list with 10 Laravel packages that might help you in your current or future project. These are packages that I am or have been using or tested and I practically fall in love with them.&lt;/p&gt;

&lt;p&gt;This is not a ranking, so the order it's not relevant at all!&lt;/p&gt;

&lt;h2&gt;
  
  
  1. &lt;a href="https://github.com/protonemedia/laravel-form-components" rel="noopener noreferrer"&gt;protonemedia/laravel-form-components&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;If you're using blade and want to handle forms easily, this is the go to. You have all the components you need, support for Bootstrap, Tailwind Forms and even for Livewire. &lt;/p&gt;

&lt;p&gt;An alternative to this is the good old &lt;a href="https://github.com/LaravelCollective/html" rel="noopener noreferrer"&gt;laravelcollective/html&lt;/a&gt;, but using this is pretty primitive these days. But hey, it works! &lt;/p&gt;

&lt;h2&gt;
  
  
  2. &lt;a href="https://github.com/pestphp/pest" rel="noopener noreferrer"&gt;pestphp/pest&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Testing is a must, but sometimes is a painful process. Do you hate writing test classes? Say no more! Pest is a beautiful PHPUnit wrapper that brings joy to any developer that uses it. I know that this sounds like a cheap teleshopping commercial, but it's that good and simple. Give it a try.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. &lt;a href="https://github.com/laravel/horizon" rel="noopener noreferrer"&gt;laravel/horizon&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;You have probably heard of this because it's a Laravel product. So if you're running an app that uses Redis a lot, you might need this. It helps you monitor your queues and scale up your workers.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. &lt;a href="https://github.com/mcamara/laravel-localization" rel="noopener noreferrer"&gt;mcamara/laravel-localization&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This is probably the most popular localization package out there. Helps you run multilanguage sites in no time and has support for a lot of Laravel versions, so even if you still run v4 or v5 (which you shouldn't) you can plug this in right away.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. &lt;a href="https://github.com/tighten/ziggy" rel="noopener noreferrer"&gt;tighten/ziggy&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;I've talked more about Ziggy an its implementation in my &lt;a href="https://dev.to/geowrgetudor/setting-up-laravel-with-inertiajs-vuejs-tailwind-css-21pc"&gt;Setting up Laravel with Inertia.js + Vue.js + Tailwind CSS&lt;/a&gt; article. Basically you can use it to pass your web routes into the DOM's head. Now you can easily access them from your Vue/Svelte/React frontend. Heck, you can even retrieve your routes from an Ziggy Api endpoint if you don't want to print them in your DOM.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. &lt;a href="https://github.com/barryvdh/laravel-snappy" rel="noopener noreferrer"&gt;barryvdh/laravel-snappy&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This is just a Laravel service provider for Snappy. If you don't know, you can use Snappy to screenshot or save a web page to PDF. It uses &lt;u&gt;wkhtmltopdf&lt;/u&gt; under the hood.&lt;/p&gt;

&lt;p&gt;An alternative and a more popular solution to this is of course &lt;a href="https://github.com/spatie/browsershot" rel="noopener noreferrer"&gt;spatie/browsershot&lt;/a&gt; which does the same thing but using headless Chrome. I used to use Snappy years ago, but now I use Browsershot.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. &lt;a href="https://github.com/nunomaduro/larastan" rel="noopener noreferrer"&gt;nunomaduro/larastan&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Just a PHPStan wrapper for Laravel that helps you finding errors in your code. Depending on how your write your code, it might not catch everything, but it's really useful if you want to maintain an error free app and a specific code quality standard.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. &lt;a href="https://github.com/spatie/laravel-backup" rel="noopener noreferrer"&gt;spatie/laravel-backup&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;We're back to &lt;a href="https://github.com/spatie" rel="noopener noreferrer"&gt;Spatie&lt;/a&gt;... because Spatie builds awesome packages. Actually, I don't even know if there's a project I've been working on that doesn't have a Spatie package installed.&lt;/p&gt;

&lt;p&gt;The title says it all. You get backups for your whole project. You can save them on your disk or even S3 and you have a few artisan commands you can leverage to your needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. &lt;a href="https://github.com/worksome/envy" rel="noopener noreferrer"&gt;worksome/envy&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This is something that I've discovered a few days ago. It's basically a took that scans for your missing ENV vars. You should always keep your &lt;code&gt;.env.example&lt;/code&gt; up to date.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. &lt;a href="https://github.com/livewire/livewire" rel="noopener noreferrer"&gt;livewire/livewire&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Livewire is a great too to build a modern interfaces without the need of Vue or React or Svelte. So you get to use Blade with some custom components that are updating in real-time because &lt;strong&gt;Live&lt;/strong&gt;wire, get it? It's an awesome tool and just like Inertia, it brings simplicity to the Laravel ecosystem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;There are many other awesome packages that worth being mentioned, but I've picked just a few of them for now. What do you think about them? Which one have you used and what else do you recommend? Let me know in the comments.&lt;/p&gt;

&lt;p&gt;Cheers! ;)&lt;/p&gt;

&lt;h4&gt;
  
  
  Support &amp;amp; follow me
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;a href="https://www.buymeacoffee.com/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FBuy_Me_A_Coffee-FFDD00%3Fstyle%3Dfor-the-badge%26logo%3Dbuy-me-a-coffee%26logoColor%3Dblack" alt="Buy me a coffee"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://twitter.com/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FTwitter-1DA1F2%3Fstyle%3Dfor-the-badge%26logo%3Dtwitter%26logoColor%3Dwhite" alt="Twitter"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://github.com/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FGitHub-100000%3Fstyle%3Dfor-the-badge%26logo%3Dgithub%26logoColor%3Dwhite" alt="GitHub"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://linkedin.com/in/geowrgetudor" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FLinkedIn-0077B5%3Fstyle%3Dfor-the-badge%26logo%3Dlinkedin%26logoColor%3Dwhite" alt="Linkedin"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>laravel</category>
      <category>composer</category>
      <category>packages</category>
    </item>
  </channel>
</rss>
