<?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>DEV Community: trueqap</title>
    <description>The latest articles on DEV Community by trueqap (@trueqap).</description>
    <link>https://dev.to/trueqap</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%2F788564%2F8c203f2b-8fe2-47b2-9918-18aa6a4301ef.jpeg</url>
      <title>DEV Community: trueqap</title>
      <link>https://dev.to/trueqap</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/trueqap"/>
    <language>en</language>
    <item>
      <title>How Bots Killed My WooCommerce Site Until I Automated WP Rocket Filter Caching</title>
      <dc:creator>trueqap</dc:creator>
      <pubDate>Wed, 27 Aug 2025 05:09:46 +0000</pubDate>
      <link>https://dev.to/trueqap/how-bots-killed-my-woocommerce-site-until-i-automated-wp-rocket-filter-caching-1ba0</link>
      <guid>https://dev.to/trueqap/how-bots-killed-my-woocommerce-site-until-i-automated-wp-rocket-filter-caching-1ba0</guid>
      <description>&lt;p&gt;Last month, my client's WooCommerce store went down. Not from a DDoS attack, not from bad code, but from Google and AI crawlers doing their job a little too enthusiastically.&lt;/p&gt;

&lt;p&gt;The culprit? Uncached WooCommerce filter pages being hammered by bots, each request hitting the database directly. The solution? A simple WordPress plugin that took me an afternoon to write and has since saved multiple sites from the same fate.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Day the Bots Came
&lt;/h2&gt;

&lt;p&gt;It started innocently enough. Server response times began creeping up. Then came the alerts: CPU usage at 90%, memory exhausted, MySQL connections maxed out. &lt;/p&gt;

&lt;p&gt;Looking at the access logs told the whole story:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Googlebot: GET /shop/?filter_color=red&amp;amp;min_price=50
BingBot: GET /shop/?filter_size=large&amp;amp;filter_material=cotton
GPTBot: GET /shop/?filter_brand=nike&amp;amp;max_price=200&amp;amp;rating_filter=4
ClaudeBot: GET /shop/?filter_color=blue&amp;amp;filter_size=medium&amp;amp;orderby=price
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hundreds of requests per minute, each with different filter combinations. Each one bypassing the cache. Each one running complex database queries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why WooCommerce Filters Break Under Load
&lt;/h2&gt;

&lt;p&gt;WooCommerce uses URL parameters for product filtering. When a user (or bot) visits &lt;code&gt;/shop/?filter_color=red&lt;/code&gt;, WooCommerce:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Parses the filter parameters&lt;/li&gt;
&lt;li&gt;Builds complex SQL queries with JOINs across multiple tables&lt;/li&gt;
&lt;li&gt;Calculates product counts for each filter option&lt;/li&gt;
&lt;li&gt;Generates the filtered product list&lt;/li&gt;
&lt;li&gt;Renders the entire page&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Without caching, this happens for EVERY request. Now multiply that by hundreds of bot requests per minute, each with different parameter combinations.&lt;/p&gt;

&lt;h2&gt;
  
  
  The WP Rocket Cache Gotcha
&lt;/h2&gt;

&lt;p&gt;WP Rocket is fantastic at caching, but it has a security feature: by default, it ignores URLs with query parameters. This prevents accidentally caching user-specific content like cart pages or search results.&lt;/p&gt;

&lt;p&gt;You can whitelist specific parameters in WP Rocket's &lt;code&gt;cache_query_strings&lt;/code&gt; setting, but here's what that looks like for a typical WooCommerce store:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;filter_color
query_type_color
filter_size
query_type_size
filter_material
query_type_material
filter_brand
query_type_brand
min_price
max_price
rating_filter
orderby
product_cat
product_tag
per_page
columns
sort
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's just the beginning. Every product attribute needs two entries (filter and query_type). Miss one? That parameter won't be cached.&lt;/p&gt;

&lt;h2&gt;
  
  
  Manual Configuration: A Losing Battle
&lt;/h2&gt;

&lt;p&gt;I started adding these manually. After 30 minutes of copying and pasting, I realized:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The client had 24 product attributes&lt;/li&gt;
&lt;li&gt;They regularly added new ones for seasonal products&lt;/li&gt;
&lt;li&gt;Other sites had the same problem&lt;/li&gt;
&lt;li&gt;I was solving the symptom, not the problem&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There had to be a better way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the Solution
&lt;/h2&gt;

&lt;p&gt;The solution was obvious: automate the entire process. The plugin needed to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Detect all WooCommerce attributes automatically&lt;/li&gt;
&lt;li&gt;Generate the correct filter parameters&lt;/li&gt;
&lt;li&gt;Update WP Rocket settings without breaking existing configurations&lt;/li&gt;
&lt;li&gt;Stay updated when attributes change&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here's the core logic that makes it work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;get_woocommerce_filters&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$filters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nv"&gt;$attribute_taxonomies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;wc_get_attribute_taxonomies&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Generate filter parameters for each attribute&lt;/span&gt;
    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$attribute_taxonomies&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$attribute&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$filters&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'filter_'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$attribute&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;attribute_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$filters&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'query_type_'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$attribute&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;attribute_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Add standard WooCommerce filters&lt;/span&gt;
    &lt;span class="nv"&gt;$filters&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'min_price'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$filters&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'max_price'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$filters&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'rating_filter'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$filters&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'orderby'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$filters&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'product_cat'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$filters&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'product_tag'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$filters&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'per_page'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$filters&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'columns'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$filters&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'sort'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;array_unique&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$filters&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Smart Update System
&lt;/h2&gt;

&lt;p&gt;The trickiest part was updating WP Rocket settings without destroying manual customizations. The solution: marker comments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$filter_start_marker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'# filter_start'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$filter_end_marker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'# filter_end'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;update_filters&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$option&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'wp_rocket_settings'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$existing_strings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$option&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'cache_query_strings'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nv"&gt;$new_filters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get_woocommerce_filters&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Find our markers&lt;/span&gt;
    &lt;span class="nv"&gt;$start_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;filter_start_marker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$existing_strings&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$end_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;filter_end_marker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$existing_strings&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$start_index&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$end_index&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Preserve everything outside our markers&lt;/span&gt;
        &lt;span class="nv"&gt;$before&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$existing_strings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$start_index&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$after&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$existing_strings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$end_index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Rebuild with updated filters&lt;/span&gt;
        &lt;span class="nv"&gt;$option&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'cache_query_strings'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nv"&gt;$before&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;filter_start_marker&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="nv"&gt;$new_filters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;filter_end_marker&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="nv"&gt;$after&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;update_option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'wp_rocket_settings'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$option&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;rocket_clean_domain&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Clear cache&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Manual entries outside the markers are preserved&lt;/li&gt;
&lt;li&gt;Automatic filters stay organized between markers&lt;/li&gt;
&lt;li&gt;Updates don't break existing configurations&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Real-World Results
&lt;/h2&gt;

&lt;p&gt;After deploying the plugin:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Server load average: 8.2 (on a 2-core server)&lt;/li&gt;
&lt;li&gt;Average response time: 3.8 seconds&lt;/li&gt;
&lt;li&gt;MySQL connections: 95% utilized&lt;/li&gt;
&lt;li&gt;Monthly hosting cost: Considering upgrade&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;After:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Server load average: 0.6&lt;/li&gt;
&lt;li&gt;Average response time: 0.4 seconds&lt;/li&gt;
&lt;li&gt;MySQL connections: 15% utilized&lt;/li&gt;
&lt;li&gt;Monthly hosting cost: Stayed on same plan&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The bot traffic didn't decrease – it just stopped killing the server. Filtered pages were now served from cache, turning database-heavy requests into simple file reads.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automatic Updates: Set and Forget
&lt;/h2&gt;

&lt;p&gt;The plugin hooks into WooCommerce attribute events:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;add_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'woocommerce_attribute_added'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'update_filters'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;add_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'woocommerce_attribute_updated'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'update_filters'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;add_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'woocommerce_attribute_deleted'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'update_filters'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add a new "Material" attribute? The filters update automatically. Delete an old seasonal attribute? Cleaned up automatically. No manual intervention needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance Impact: Basically Zero
&lt;/h2&gt;

&lt;p&gt;The plugin is intentionally minimal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No frontend processing&lt;/strong&gt;: Only runs in admin and on attribute changes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No database queries&lt;/strong&gt;: Reads existing WP options&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No admin menus&lt;/strong&gt;: Completely invisible once activated&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No scheduled tasks&lt;/strong&gt;: Event-driven updates only&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Total plugin size: ~150 lines of code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open Source Release
&lt;/h2&gt;

&lt;p&gt;I've released this as open source because every WooCommerce + WP Rocket user faces this problem. The plugin is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Free to use and modify&lt;/li&gt;
&lt;li&gt;GPL v2 licensed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;GitHub Repository&lt;/strong&gt;: &lt;a href="https://github.com/trueqap/wp-rocket-woo-filters-cache" rel="noopener noreferrer"&gt;https://github.com/trueqap/wp-rocket-woo-filters-cache&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation in 30 Seconds
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Download from GitHub&lt;/li&gt;
&lt;li&gt;Upload to &lt;code&gt;/wp-content/plugins/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Activate&lt;/li&gt;
&lt;li&gt;Done – seriously, that's it&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The plugin immediately scans your attributes and updates WP Rocket settings. No configuration needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bigger Picture
&lt;/h2&gt;

&lt;p&gt;This isn't just about WooCommerce or WP Rocket. It's about recognizing when manual processes become bottlenecks and having the confidence to automate them. &lt;/p&gt;

&lt;p&gt;The hours I spent building this plugin have been repaid many times over in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Support tickets avoided&lt;/li&gt;
&lt;li&gt;Server upgrades prevented&lt;/li&gt;
&lt;li&gt;Client sites staying online&lt;/li&gt;
&lt;li&gt;My own sanity preserved&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're managing WooCommerce sites with WP Rocket, you need this. If you're seeing high server loads from bot traffic, you need this. If you're manually managing cache settings, you definitely need this.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have you dealt with similar bot traffic issues? What's your approach to handling aggressive crawlers? Let me know in the comments!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If this helped you, give the &lt;a href="https://github.com/trueqap/wp-rocket-woo-filters-cache" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt; a star and share it with others who might benefit.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  WordPress #WooCommerce #WebPerformance #OpenSource
&lt;/h1&gt;

</description>
      <category>woocommerce</category>
      <category>wordpress</category>
      <category>wprocket</category>
      <category>aibots</category>
    </item>
    <item>
      <title>How to Run Cron on macOS in 2025: A Complete Guide</title>
      <dc:creator>trueqap</dc:creator>
      <pubDate>Sat, 12 Jul 2025 06:21:09 +0000</pubDate>
      <link>https://dev.to/trueqap/how-to-run-cron-on-macos-in-2025-a-complete-guide-2b8e</link>
      <guid>https://dev.to/trueqap/how-to-run-cron-on-macos-in-2025-a-complete-guide-2b8e</guid>
      <description>&lt;p&gt;Running cron jobs on macOS has become increasingly challenging due to Apple's enhanced security features. If you've been struggling to get your cron jobs working on modern macOS versions, this guide will walk you through the necessary steps to grant the required permissions and get everything running smoothly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Starting with macOS Mojave (10.14) and becoming more restrictive with each release, Apple introduced privacy protections that prevent background processes from accessing user data without explicit permission. This means your cron jobs might fail silently when trying to access files in protected locations like Desktop, Documents, Downloads, or external drives.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;macOS Monterey (12.0) or later&lt;/li&gt;
&lt;li&gt;Administrator access to your Mac&lt;/li&gt;
&lt;li&gt;Basic familiarity with Terminal and cron syntax&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Grant Full Disk Access to Cron
&lt;/h2&gt;

&lt;p&gt;The first crucial step is granting Full Disk Access to the cron binary. This allows cron to access files anywhere on your system.&lt;/p&gt;

&lt;h3&gt;
  
  
  Here's how to do it:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;strong&gt;System Settings&lt;/strong&gt; (or System Preferences on older versions)&lt;/li&gt;
&lt;li&gt;Navigate to &lt;strong&gt;Privacy &amp;amp; Security&lt;/strong&gt; → &lt;strong&gt;Full Disk Access&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click the lock icon and authenticate with your password&lt;/li&gt;
&lt;li&gt;Click the &lt;strong&gt;+&lt;/strong&gt; button to add a new exception&lt;/li&gt;
&lt;li&gt;Press &lt;strong&gt;⌘⇧G&lt;/strong&gt; (Command+Shift+G) to open the "Go to folder" dialog&lt;/li&gt;
&lt;li&gt;Enter &lt;code&gt;/usr/sbin&lt;/code&gt; and press Enter&lt;/li&gt;
&lt;li&gt;Find and double-click the &lt;code&gt;cron&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;Ensure the checkbox next to cron is enabled&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 2: Grant Full Disk Access to Terminal
&lt;/h2&gt;

&lt;p&gt;Since you'll be editing crontab through Terminal, it also needs Full Disk Access:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Still in &lt;strong&gt;Privacy &amp;amp; Security&lt;/strong&gt; → &lt;strong&gt;Full Disk Access&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click the &lt;strong&gt;+&lt;/strong&gt; button again&lt;/li&gt;
&lt;li&gt;Navigate to &lt;strong&gt;Applications&lt;/strong&gt; → &lt;strong&gt;Utilities&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Terminal.app&lt;/strong&gt; and click Open&lt;/li&gt;
&lt;li&gt;Make sure Terminal is checked in the list&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 3: Restart Crontab
&lt;/h2&gt;

&lt;p&gt;After granting the necessary permissions, you need to restart your crontab for the changes to take effect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# First, save your current crontab (if you have one)&lt;/span&gt;
crontab &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/my_crontab_backup.txt

&lt;span class="c"&gt;# Remove the current crontab&lt;/span&gt;
crontab &lt;span class="nt"&gt;-r&lt;/span&gt;

&lt;span class="c"&gt;# Re-add your crontab&lt;/span&gt;
crontab ~/my_crontab_backup.txt

&lt;span class="c"&gt;# Or create a new one&lt;/span&gt;
crontab &lt;span class="nt"&gt;-e&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Test Your Setup
&lt;/h2&gt;

&lt;p&gt;Let's create a simple test to verify everything is working:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Edit your crontab&lt;/span&gt;
crontab &lt;span class="nt"&gt;-e&lt;/span&gt;

&lt;span class="c"&gt;# Add this test job that runs every minute&lt;/span&gt;
&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Cron is working! &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/Desktop/cron_test.log

&lt;span class="c"&gt;# Save and exit (in vim: ESC, then :wq)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wait a minute or two, then check if the file appears on your Desktop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ~/Desktop/cron_test.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see timestamps appearing every minute, congratulations! Your cron is working correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Issues and Solutions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Issue 1: Cron jobs still not running
&lt;/h3&gt;

&lt;p&gt;Make sure you've granted Full Disk Access to the actual programs your cron jobs are calling. For example, if your cron job runs a Python script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; /usr/bin/python3 /Users/yourname/script.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might need to grant Full Disk Access to &lt;code&gt;/usr/bin/python3&lt;/code&gt; as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  Issue 2: Environment variables
&lt;/h3&gt;

&lt;p&gt;Cron runs with a minimal environment. Always use full paths and set necessary environment variables at the beginning of your crontab:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/local/bin:/usr/bin:/bin
&lt;span class="nv"&gt;HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/Users/yourname

&lt;span class="c"&gt;# Your cron jobs below&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Issue 3: Output and error handling
&lt;/h3&gt;

&lt;p&gt;Always redirect output to log files for debugging:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; /path/to/script.sh &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; /path/to/logfile.log 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Security Considerations
&lt;/h2&gt;

&lt;p&gt;Granting Full Disk Access is a significant security permission. Only grant it to trusted applications and scripts. Regularly review your Full Disk Access list and remove permissions for apps you no longer use.&lt;/p&gt;

&lt;p&gt;While macOS's security features can make running cron jobs more complex, it's still entirely possible with the right permissions. The key is understanding that both cron and Terminal need Full Disk Access, and you need to restart your crontab after making these changes.&lt;/p&gt;

&lt;p&gt;Remember to always test your cron jobs thoroughly and use proper logging to troubleshoot any issues. Happy scheduling!&lt;/p&gt;

</description>
      <category>cron</category>
      <category>macos</category>
    </item>
    <item>
      <title>Generate Avatars with Initials Using UI Avatars</title>
      <dc:creator>trueqap</dc:creator>
      <pubDate>Tue, 10 Sep 2024 12:50:20 +0000</pubDate>
      <link>https://dev.to/trueqap/generate-avatars-with-initials-using-ui-avatars-49j6</link>
      <guid>https://dev.to/trueqap/generate-avatars-with-initials-using-ui-avatars-49j6</guid>
      <description>&lt;p&gt;In today’s digital world, having a unique and personalized avatar can make a significant difference in user experience. Whether it's for a profile picture, comment section, or user dashboard, avatars help in identifying and connecting with users. One of the simplest and most effective tools for generating avatars with initials is &lt;a href="https://ui-avatars.com/" rel="noopener noreferrer"&gt;UI Avatars&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is UI Avatars?
&lt;/h2&gt;

&lt;p&gt;UI Avatars is a straightforward API that generates avatars based on user initials. It's designed to be easy to use, with no login required and no usage tracking. The final images are cached, but no other information is stored. You can create avatars by simply providing a name or surname, or both.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Statistics:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;+275,557,117&lt;/strong&gt; Daily requests&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2.8931ms&lt;/strong&gt; Avg. Processing Time&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to Use UI Avatars
&lt;/h2&gt;

&lt;p&gt;All requests to the UI Avatars API return an image stream that can be used directly in an &lt;code&gt;&amp;lt;img/&amp;gt;&lt;/code&gt; tag. Here’s how you can generate avatars with different settings:&lt;/p&gt;

&lt;h3&gt;
  
  
  Basic Usage
&lt;/h3&gt;

&lt;p&gt;To generate a default avatar for a user named "John Doe":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://ui-avatars.com/api/?name=John+Doe"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"John Doe Avatar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Customizing the Avatar
&lt;/h3&gt;

&lt;p&gt;You can customize the avatar by changing various parameters:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Background Color&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;   &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://ui-avatars.com/api/?background=0D8ABC&amp;amp;color=fff"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Blue Avatar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Random Background&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;   &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://ui-avatars.com/api/?background=random"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Random Background Avatar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Image Size&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;   &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://ui-avatars.com/api/?size=128"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"128px Avatar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Font Size&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;   &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://ui-avatars.com/api/?font-size=0.33"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Small Font Avatar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Initial Characters&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;   &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://ui-avatars.com/api/?length=1"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Single Initial Avatar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Rounded Image&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;   &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://ui-avatars.com/api/?rounded=true"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Rounded Avatar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Bold Text&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;   &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://ui-avatars.com/api/?bold=true"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Bold Text Avatar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Uppercase&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;   &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://ui-avatars.com/api/?uppercase=false&amp;amp;name=different+Case"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Lowercase Initials Avatar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Format (SVG or PNG)&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;   &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://ui-avatars.com/api/?format=svg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"SVG Avatar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Combining Settings
&lt;/h3&gt;

&lt;p&gt;You can combine multiple settings to create a more personalized avatar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://ui-avatars.com/api/?name=Elon+Musk&amp;amp;size=128&amp;amp;background=a0a0a0&amp;amp;color=ff0000&amp;amp;length=1&amp;amp;rounded=true&amp;amp;bold=true"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Custom Avatar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Using UI Avatars with Gravatar
&lt;/h3&gt;

&lt;p&gt;A practical use-case is to use UI Avatars as a fallback for Gravatar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://www.gravatar.com/avatar/EMAIL_MD5?d=https%3A%2F%2Fui-avatars.com%2Fapi%2F/Elon+Musk/128"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Gravatar Fallback Avatar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Due to Gravatar’s limitations, parameters must be passed as sub-directories instead of query parameters. Consider URL encoding the name if it contains special characters.&lt;/p&gt;

&lt;h3&gt;
  
  
  Retina Display Support
&lt;/h3&gt;

&lt;p&gt;For crisp avatars on high DPI screens, use 1.5x or 2x sizes but keep the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag at the original size:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://ui-avatars.com/api/?name=John+Doe&amp;amp;size=128"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"64"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"64"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Retina Avatar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Language/Script Support
&lt;/h3&gt;

&lt;p&gt;UI Avatars supports several Unicode scripts and languages, including Arabic, Armenian, Bengali, Georgian, Hebrew, Chinese, Japanese, Mongolian, Thai, and Tibetan.&lt;/p&gt;

&lt;h3&gt;
  
  
  WordPress Plugin
&lt;/h3&gt;

&lt;p&gt;If you have a WordPress site, you can use the free UI Avatars WordPress plugin for easy integration.&lt;/p&gt;

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

&lt;p&gt;UI Avatars provides a simple and efficient way to generate avatars with initials from names. With a variety of customization options and no need for login or usage tracking, it's a perfect solution for developers looking to enhance their user interfaces with personalized avatars.&lt;/p&gt;

&lt;p&gt;Try out UI Avatars today and see how it can improve your application's user experience!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>avatars</category>
      <category>api</category>
      <category>wordpress</category>
    </item>
    <item>
      <title>How to Install Docker and Docker Compose on Ubuntu - 2025</title>
      <dc:creator>trueqap</dc:creator>
      <pubDate>Mon, 22 Jul 2024 12:58:19 +0000</pubDate>
      <link>https://dev.to/trueqap/how-to-install-docker-and-docker-compose-on-ubuntu-5boh</link>
      <guid>https://dev.to/trueqap/how-to-install-docker-and-docker-compose-on-ubuntu-5boh</guid>
      <description>&lt;p&gt;Docker is an open-source platform for developing, shipping, and running applications inside containers. Docker Compose simplifies the process of managing multiple Docker containers. This guide will help you install Docker and Docker Compose on an Ubuntu system step-by-step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Update Package Repositories&lt;/li&gt;
&lt;li&gt;Install Docker Dependencies&lt;/li&gt;
&lt;li&gt;Add Docker GPG Key&lt;/li&gt;
&lt;li&gt;Set up the Docker Stable Repository&lt;/li&gt;
&lt;li&gt;Install Docker Engine&lt;/li&gt;
&lt;li&gt;Enable and Start Docker Service&lt;/li&gt;
&lt;li&gt;Verify Docker Installation&lt;/li&gt;
&lt;li&gt;Install Docker Compose&lt;/li&gt;
&lt;li&gt;Verify Docker Compose Installation&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ubuntu 18.04 or later&lt;/li&gt;
&lt;li&gt;A user with sudo privileges&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's get started!&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 1: Update Package Repositories&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;First, ensure your package repositories are up to date:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Step 2: Install Docker Dependencies&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Next, install the necessary dependencies for Docker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; apt-transport-https ca-certificates curl software-properties-common
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Step 3: Add Docker GPG Key&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Add the official Docker GPG key to your system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://download.docker.com/linux/ubuntu/gpg | &lt;span class="nb"&gt;sudo &lt;/span&gt;gpg &lt;span class="nt"&gt;--dearmor&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /usr/share/keyrings/docker-archive-keyring.gpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Step 4: Set up the Docker Stable Repository&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Set up the Docker stable repository on your system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;lsb_release &lt;span class="nt"&gt;-cs&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; stable"&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/apt/sources.list.d/docker.list &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Step 5: Install Docker Engine&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Now, install Docker Engine, CLI, and containerd package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; docker-ce docker-ce-cli containerd.io
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Step 6: Enable and Start Docker Service&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Enable and start the Docker service to ensure it runs on system startup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;docker
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Step 7: Verify Docker Installation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Run a simple test to ensure Docker is installed and functioning correctly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;docker run hello-world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything is set up correctly, you’ll see a message indicating a successful installation.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 8: Install Docker Compose&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Download the Docker Compose binary from the official GitHub repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;curl &lt;span class="nt"&gt;-L&lt;/span&gt; &lt;span class="s2"&gt;"https://github.com/docker/compose/releases/latest/download/docker-compose-&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /usr/local/bin/docker-compose
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apply executable permissions to the Docker Compose binary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo chmod&lt;/span&gt; +x /usr/local/bin/docker-compose
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a symbolic link to ensure that &lt;code&gt;docker-compose&lt;/code&gt; command can be run from any location:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /usr/local/bin/docker-compose /usr/bin/docker-compose
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Step 9: Verify Docker Compose Installation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Finally, verify that Docker Compose is installed correctly by checking its version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Congratulations! You have successfully installed Docker and Docker Compose on your Ubuntu system. You are now ready to start using Docker to containerize your applications and Docker Compose to manage multi-container applications. Happy coding!&lt;/p&gt;

</description>
      <category>docker</category>
    </item>
    <item>
      <title>Disabling All Emails in WordPress</title>
      <dc:creator>trueqap</dc:creator>
      <pubDate>Thu, 30 Nov 2023 16:52:50 +0000</pubDate>
      <link>https://dev.to/trueqap/disabling-all-emails-in-wordpress-2mhm</link>
      <guid>https://dev.to/trueqap/disabling-all-emails-in-wordpress-2mhm</guid>
      <description>&lt;p&gt;It's a common scenario: you're developing a site that's been cloned from a live site, filled with operational features, notifications, plugins, and automated email sending. For instance, in the case of an e-commerce site, it's not ideal if the development version is bombarding users with emails. In such cases, it's always necessary to disable the email sending function.&lt;/p&gt;

&lt;p&gt;Of course, there are plugins designed for this purpose, but I'm a fan of simplicity. I have a less elegant, but perfectly functional solution.&lt;/p&gt;

&lt;p&gt;I simply override the &lt;code&gt;wp_mail&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;If you find yourself in a similar situation and want to disable all emails, then paste the following line into your &lt;code&gt;wp-config.php&lt;/code&gt; file (at the very end):&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;With this solution, you eliminate the risk that comes with using a plugin to turn off email notifications. There's always a chance that, while you're in the process of setting up the plugin, a notification email might slip through and reach your users. By overriding the wp_mail function directly in the wp-config.php file, you ensure that no emails are sent out from the moment you implement this change.&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>wordpressemail</category>
    </item>
  </channel>
</rss>
