<?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: Kushang Tailor</title>
    <description>The latest articles on Forem by Kushang Tailor (@kushang_tailor).</description>
    <link>https://forem.com/kushang_tailor</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%2F3900414%2F0d2c9537-2b52-4907-b8ab-96018be8376a.png</url>
      <title>Forem: Kushang Tailor</title>
      <link>https://forem.com/kushang_tailor</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/kushang_tailor"/>
    <language>en</language>
    <item>
      <title>How I Secured WordPress Media Files by Building My Own Upload Restriction Plugin</title>
      <dc:creator>Kushang Tailor</dc:creator>
      <pubDate>Wed, 29 Apr 2026 05:52:53 +0000</pubDate>
      <link>https://forem.com/kushang_tailor/how-i-secured-wordpress-media-files-by-building-my-own-upload-restriction-plugin-389l</link>
      <guid>https://forem.com/kushang_tailor/how-i-secured-wordpress-media-files-by-building-my-own-upload-restriction-plugin-389l</guid>
      <description>&lt;h1&gt;
  
  
  How I Secured WordPress Media Files by Building My Own
&lt;/h1&gt;

&lt;p&gt;Upload Restriction Plugin&lt;/p&gt;

&lt;p&gt;Security is one of those things you don't think about deeply &lt;br&gt;
until something breaks badly.&lt;/p&gt;

&lt;p&gt;For me, that moment came while managing multiple high-traffic &lt;br&gt;
WordPress websites. Sites that were running fine — until they &lt;br&gt;
weren't. Slowing down. Getting unstable. Eventually crashing.&lt;/p&gt;

&lt;p&gt;The culprit? Unrestricted file uploads.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem — What Was Actually Happening
&lt;/h2&gt;

&lt;p&gt;WordPress is flexible by nature. And that flexibility, if left &lt;br&gt;
unchecked, can become a serious vulnerability.&lt;/p&gt;

&lt;p&gt;On high-traffic sites, users interact with forms, media &lt;br&gt;
uploaders, and search inputs constantly. Even with proper input &lt;br&gt;
escaping and sanitization in place, there are edge cases — &lt;br&gt;
scenarios where those defenses don't fully catch what's coming &lt;br&gt;
through. And attackers know this.&lt;/p&gt;

&lt;p&gt;Here are the real attacks that happen when file upload &lt;br&gt;
restrictions are weak or missing:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Malicious Script Uploads (.php, .exe, .sh)
&lt;/h3&gt;

&lt;p&gt;An attacker uploads a file with a .php or .sh extension through &lt;br&gt;
a form or a vulnerable media endpoint. Once that file lands on &lt;br&gt;
your server, it can be executed remotely — giving the attacker &lt;br&gt;
full control over your WordPress installation. This is called &lt;br&gt;
Remote Code Execution (RCE) and it's one of the most dangerous &lt;br&gt;
attacks on any web server.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. SVG-Based XSS Attacks
&lt;/h3&gt;

&lt;p&gt;SVG files are XML-based and can contain embedded JavaScript. &lt;br&gt;
When a malicious SVG is uploaded to your media library and &lt;br&gt;
rendered in a browser, that JavaScript executes — allowing &lt;br&gt;
attackers to steal session cookies, hijack admin accounts, or &lt;br&gt;
redirect users to phishing sites.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Web Shell Uploads
&lt;/h3&gt;

&lt;p&gt;Attackers disguise a web shell — a backdoor script — as an &lt;br&gt;
innocent looking file. Once uploaded and accessed via browser, &lt;br&gt;
it gives them a persistent, hidden entry point into your server &lt;br&gt;
that survives even plugin updates and password changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. XML &amp;amp; HTML File Injections
&lt;/h3&gt;

&lt;p&gt;Uploading malformed XML or HTML files can trigger parser errors, &lt;br&gt;
expose server information, or be used to inject content into &lt;br&gt;
your site that search engines and users see — damaging your SEO &lt;br&gt;
and your reputation.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Large &amp;amp; Unnecessary File Type Uploads
&lt;/h3&gt;

&lt;p&gt;Even without malicious intent, allowing every file type creates &lt;br&gt;
problems. Uploading high-resolution TIFFs, PSDs, or uncompressed &lt;br&gt;
video formats bloats your server storage, slows down your media &lt;br&gt;
library, and eventually crashes shared or underpowered hosting &lt;br&gt;
environments.&lt;/p&gt;

&lt;p&gt;On one of my high-traffic projects, the site was slowing down &lt;br&gt;
week by week. No obvious code issue. No server misconfiguration. &lt;br&gt;
Just the gradual accumulation of unnecessary and problematic &lt;br&gt;
files finding their way into the media library — quietly &lt;br&gt;
consuming resources until the site buckled.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Existing Solutions — And Why They Weren't Enough
&lt;/h2&gt;

&lt;p&gt;Yes, WordPress has some built-in MIME type checking. And yes, &lt;br&gt;
there are security plugins that handle broad firewall rules.&lt;/p&gt;

&lt;p&gt;But I needed something specific, simple, and surgical. I didn't &lt;br&gt;
want a bloated security suite. I wanted one thing — the ability &lt;br&gt;
to precisely control which file extensions and MIME types are &lt;br&gt;
allowed to be uploaded to my WordPress sites. Nothing more, &lt;br&gt;
nothing less.&lt;/p&gt;

&lt;p&gt;I searched. I couldn't find exactly what I needed.&lt;/p&gt;

&lt;p&gt;So I built it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Solution — Restrict WP Upload Type
&lt;/h2&gt;

&lt;p&gt;I built and published the &lt;strong&gt;Restrict WP Upload Type&lt;/strong&gt; plugin on &lt;br&gt;
WordPress.org.&lt;/p&gt;

&lt;p&gt;The concept is straightforward: give site administrators full, &lt;br&gt;
granular control over which file extensions and MIME types are &lt;br&gt;
permitted in the WordPress Media Library — and block everything &lt;br&gt;
else.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://wordpress.org/plugins/restrict-wp-upload-type/" rel="noopener noreferrer"&gt;View the plugin on WordPress.org&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What the Plugin Does
&lt;/h3&gt;

&lt;p&gt;The plugin provides a clean settings panel inside your WordPress &lt;br&gt;
admin where you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Allow or disallow any file extension&lt;/strong&gt; — choose exactly 
which file types your site accepts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Control MIME types precisely&lt;/strong&gt; — not just extensions but 
the actual MIME type validation, making it harder to spoof&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access 96 file extensions and MIME types&lt;/strong&gt; — covering 
images, documents, audio, video, code files, archives, and more&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restrict SVG uploads&lt;/strong&gt; — one of the most commonly 
exploited file types in WordPress, now fully controllable&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Apply rules globally&lt;/strong&gt; — restrictions apply across the 
media library, upload forms, and any standard WordPress 
upload endpoint&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Real-World Use Cases
&lt;/h3&gt;

&lt;p&gt;Here's how different types of sites can use this plugin:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WooCommerce stores&lt;/strong&gt; — Allow only JPG, PNG, PDF and block &lt;br&gt;
everything else. Prevent customers or vendors from sneaking &lt;br&gt;
executable files through product upload forms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Portfolio or agency sites&lt;/strong&gt; — Block PSDs, TIFFs, and RAW &lt;br&gt;
files that designers sometimes accidentally upload, keeping &lt;br&gt;
your server storage clean.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Membership or community sites&lt;/strong&gt; — Restrict uploads to safe &lt;br&gt;
document formats only. Block PHP, SH, EXE, and all script &lt;br&gt;
file types entirely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Corporate websites&lt;/strong&gt; — Allow only PDF and DOCX for document &lt;br&gt;
uploads. Block all image formats if image uploads aren't &lt;br&gt;
needed at all.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Learned Building This
&lt;/h2&gt;

&lt;p&gt;The most interesting technical challenge was working with &lt;br&gt;
WordPress's &lt;code&gt;upload_mimes&lt;/code&gt; filter and &lt;code&gt;wp_check_filetype_and_ext&lt;/code&gt; &lt;br&gt;
function. WordPress does its own internal MIME validation, and &lt;br&gt;
overriding it cleanly — without breaking legitimate uploads or &lt;br&gt;
conflicting with other plugins — required careful handling.&lt;/p&gt;

&lt;p&gt;I also learned that MIME type spoofing is more common than &lt;br&gt;
most developers realize. An attacker can rename a .php file &lt;br&gt;
to .jpg and attempt to upload it. That's why checking only the &lt;br&gt;
file extension is never enough — you need to validate the actual &lt;br&gt;
MIME type of the file content, not just what the filename claims &lt;br&gt;
to be.&lt;/p&gt;

&lt;p&gt;The plugin handles both layers.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Result
&lt;/h2&gt;

&lt;p&gt;The plugin currently has &lt;strong&gt;300+ active installations&lt;/strong&gt; on &lt;br&gt;
WordPress.org, a perfect &lt;strong&gt;5-star rating&lt;/strong&gt;, and has been &lt;br&gt;
tested up to WordPress 6.7.5. It's been live since April 2022 &lt;br&gt;
and has remained stable across multiple WordPress versions.&lt;/p&gt;

&lt;p&gt;One reviewer described it as &lt;em&gt;"simple, fast and objective."&lt;/em&gt; &lt;br&gt;
Another said it &lt;em&gt;"works like a charm."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A particularly useful piece of feedback from a user highlighted &lt;br&gt;
the need to better communicate which plugin blocks an upload &lt;br&gt;
when the restriction triggers — something I've noted for a &lt;br&gt;
future update.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚠️ One Thing to Keep in Mind — Plugin Conflicts
&lt;/h2&gt;

&lt;p&gt;While the plugin works reliably across most WordPress setups, &lt;br&gt;
there is one scenario worth being aware of.&lt;/p&gt;

&lt;p&gt;If another active plugin on your site — such as Elementor, &lt;br&gt;
Divi, or any page builder / media-heavy plugin — also hooks &lt;br&gt;
into WordPress's MIME type functions internally, it may &lt;br&gt;
conflict with this plugin's restrictions.&lt;/p&gt;

&lt;p&gt;This happens because multiple plugins are trying to control &lt;br&gt;
the same WordPress filter (&lt;code&gt;upload_mimes&lt;/code&gt;) at the same time, &lt;br&gt;
and they can override each other depending on the order they &lt;br&gt;
load.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to check for this:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;After activating the plugin and saving your settings, 
try uploading a restricted file type&lt;/li&gt;
&lt;li&gt;If the restriction doesn't work as expected, temporarily 
deactivate other plugins one by one to identify the 
conflict&lt;/li&gt;
&lt;li&gt;Re-activate them and check which plugin is overriding 
the MIME type settings&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is not a bug — it's simply how WordPress plugin &lt;br&gt;
architecture works when multiple plugins touch the same hook. &lt;br&gt;
Being aware of it will save you debugging time and help you &lt;br&gt;
use this plugin more effectively on complex setups.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Takeaway
&lt;/h2&gt;

&lt;p&gt;If you're running any WordPress site with user-facing upload &lt;br&gt;
functionality — forms, media libraries, WooCommerce product &lt;br&gt;
uploads, membership portals — you should be controlling exactly &lt;br&gt;
what file types are allowed in.&lt;/p&gt;

&lt;p&gt;Sanitization and escaping are essential, but they are not &lt;br&gt;
enough on their own. File type restriction is a separate, &lt;br&gt;
dedicated layer of defense that too many WordPress sites skip.&lt;/p&gt;

&lt;p&gt;Don't wait for a crash to find out why.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://wordpress.org/plugins/restrict-wp-upload-type/" rel="noopener noreferrer"&gt;Restrict WP Upload Type on WordPress.org&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Have you ever dealt with a file upload attack on a WordPress &lt;br&gt;
site? I'd love to hear how you handled it — drop a comment &lt;br&gt;
below. 🔒&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>security</category>
      <category>php</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How I Became a Developer and Why? — My 9-Year Journey</title>
      <dc:creator>Kushang Tailor</dc:creator>
      <pubDate>Tue, 28 Apr 2026 05:06:11 +0000</pubDate>
      <link>https://forem.com/kushang_tailor/from-data-entry-at-a-ca-office-to-senior-wordpress-developer-my-9-year-journey-3f92</link>
      <guid>https://forem.com/kushang_tailor/from-data-entry-at-a-ca-office-to-senior-wordpress-developer-my-9-year-journey-3f92</guid>
      <description>&lt;h1&gt;
  
  
  From Data Entry at a CA Office to Senior WordPress Developer — My 9-Year Journey
&lt;/h1&gt;

&lt;p&gt;I didn't start my career in front of a MacBook with a cup of &lt;br&gt;
coffee, writing clean code in a cozy home office.&lt;/p&gt;

&lt;p&gt;I started in a textile market, standing 12 hours a day, earning &lt;br&gt;
₹3,000 a month.&lt;/p&gt;

&lt;p&gt;This is my honest story — the struggles, the fake promises, the &lt;br&gt;
wrong turns, and how WordPress changed everything for me.&lt;/p&gt;




&lt;h2&gt;
  
  
  Chapter 1: The Textile Market — Where It All Began
&lt;/h2&gt;

&lt;p&gt;After my SSC exams, there were a few months before results came &lt;br&gt;
out. I needed money. So I took up work in the textile market in near by area.&lt;/p&gt;

&lt;p&gt;For those who don't know — Gujarat is one of India's largest textile hubs. And the people who keep it running work incredibly hard. I'm talking 12 to 18 hour shifts, six or seven days a week, in hot, loud, and physically exhausting environments. The workers who load, unload, sort, and manage fabric rolls earn somewhere between ₹3,000 to ₹8,000 per month — with no paid leave, no sick leave, no fixed hours, and certainly no work-from-home option.&lt;/p&gt;

&lt;p&gt;I was earning ₹3,000 a month. For 12 hours of work every day.&lt;/p&gt;

&lt;p&gt;That's roughly ₹8 per hour.&lt;/p&gt;

&lt;p&gt;I wasn't complaining — it was honest work and it taught me &lt;br&gt;
discipline. But I knew this wasn't the life I wanted. I knew &lt;br&gt;
there had to be another way.&lt;/p&gt;




&lt;h2&gt;
  
  
  Chapter 2: The Dream of a Degree — And Why I Let It Go
&lt;/h2&gt;

&lt;p&gt;When my SSC results came, I passed. I was eligible to apply for a BE degree through the diploma-to-degree route. That was the &lt;br&gt;
"expected" path — get a degree, get a stable job.&lt;/p&gt;

&lt;p&gt;But my financial situation at home made that impossible. &lt;br&gt;
Engineering fees, books, travel — it wasn't happening.&lt;/p&gt;

&lt;p&gt;So I made a different choice. I enrolled in an Android &lt;br&gt;
Development course for ₹12,000. It wasn't a degree. But it was &lt;br&gt;
a skill. And I believed skills could open doors too.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What IT taught me later:&lt;/strong&gt; In the tech world, nobody asks &lt;br&gt;
where your degree is from. They ask what you've built. Your &lt;br&gt;
GitHub, your portfolio, your live projects — that's your real &lt;br&gt;
resume.&lt;/p&gt;




&lt;h2&gt;
  
  
  Chapter 3: Data Entry by Day, Android by Dawn
&lt;/h2&gt;

&lt;p&gt;To pay for the course, I joined a CA office as a full-time data &lt;br&gt;
entry operator. My stipend was ₹7,000 per month.&lt;/p&gt;

&lt;p&gt;My daily routine looked like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Early morning&lt;/strong&gt; — Android development classes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;All day until 7–8 PM&lt;/strong&gt; — Data entry at the CA office&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Night&lt;/strong&gt; — Study, practice, repeat&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Data entry work is underrated in how mentally demanding it is. &lt;br&gt;
You need to be precise, fast, and consistent — for hours on end. &lt;br&gt;
I also picked up accounting work using Tally, which added more &lt;br&gt;
responsibility to my plate.&lt;/p&gt;

&lt;p&gt;I was good at it. My speed improved. My accuracy was solid.&lt;/p&gt;

&lt;p&gt;But here's the hard truth about this career path — salary growth &lt;br&gt;
is painfully slow. Even in well-established banks and finance &lt;br&gt;
firms, the reality is difficult. A bank clerk or junior &lt;br&gt;
accountant in India earns roughly ₹15,000 to ₹25,000 per month. &lt;br&gt;
A bank manager might earn ₹50,000 to ₹80,000 — but only after &lt;br&gt;
10 to 15 years of service, late night shifts in some branches, &lt;br&gt;
and very rigid working hours. There is no remote work. There is &lt;br&gt;
no flexibility. And the ceiling is always visible from where you &lt;br&gt;
stand.&lt;/p&gt;

&lt;p&gt;I paid my entire ₹12,000 course fee in EMIs from my data entry &lt;br&gt;
salary. Every month, a piece of my stipend went toward buying &lt;br&gt;
myself a better future.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What IT taught me later:&lt;/strong&gt; In tech, salaries can grow 3x to &lt;br&gt;
5x within the first five years alone — based on your skills, not &lt;br&gt;
your seniority years. A senior developer today earns what a bank &lt;br&gt;
manager takes decades to reach.&lt;/p&gt;




&lt;h2&gt;
  
  
  Chapter 4: The Fake Course — The Hardest Lesson
&lt;/h2&gt;

&lt;p&gt;After completing the Android development course, the institute &lt;br&gt;
had promised job placement. That was part of the deal.&lt;/p&gt;

&lt;p&gt;They didn't deliver.&lt;/p&gt;

&lt;p&gt;I pushed myself. I traveled outside my city for interviews — as &lt;br&gt;
a fresher, with no experience, competing against candidates from &lt;br&gt;
engineering colleges. I gave multiple interviews. I learned from &lt;br&gt;
each one.&lt;/p&gt;

&lt;p&gt;But the institute had made commitments they were never capable &lt;br&gt;
of keeping. The "placement support" was practically non-existent. &lt;br&gt;
No real industry connections. No resume guidance. No interview &lt;br&gt;
preparation. Just hollow promises made to sell a course.&lt;/p&gt;

&lt;p&gt;This is a reality that thousands of students across India face &lt;br&gt;
every year. Coaching institutes and private training centers &lt;br&gt;
often market themselves with big claims — "100% job guarantee", &lt;br&gt;
"placement in top companies" — but deliver very little. They &lt;br&gt;
collect the fees, run a basic course, and when it comes to &lt;br&gt;
actually finding you a job, you're on your own.&lt;/p&gt;

&lt;p&gt;I had paid ₹12,000 — money I had earned through months of early &lt;br&gt;
mornings and long workdays — and I had nothing to show for it &lt;br&gt;
professionally.&lt;/p&gt;

&lt;p&gt;It was a frustrating and expensive lesson. But it also forced me &lt;br&gt;
to take control of my own career. Nobody was going to hand me a &lt;br&gt;
job. I had to find it myself.&lt;/p&gt;




&lt;h2&gt;
  
  
  Chapter 5: ₹4,000 a Month and a Bet on WordPress
&lt;/h2&gt;

&lt;p&gt;In 2017, I found a web development company willing to take me &lt;br&gt;
as a fresher.&lt;/p&gt;

&lt;p&gt;The stipend was ₹4,000 per month.&lt;/p&gt;

&lt;p&gt;Less than what I was earning in data entry. Less than what I &lt;br&gt;
made in the textile market.&lt;/p&gt;

&lt;p&gt;But I took it — because I saw the future clearly.&lt;/p&gt;

&lt;p&gt;Within 3 months, my dedication was noticed and my salary was &lt;br&gt;
increased to ₹8,000 per month. Progress — but still not enough &lt;br&gt;
to live comfortably.&lt;/p&gt;

&lt;p&gt;So I did what most people wouldn't expect from a developer — &lt;br&gt;
I signed up as a Swiggy delivery partner.&lt;/p&gt;

&lt;p&gt;Yes, after coding all day, I was delivering food orders in the &lt;br&gt;
evening. And honestly? The money was good. Better than my &lt;br&gt;
development stipend at the time. Swiggy delivery in a busy city &lt;br&gt;
like Surat can earn you ₹15,000 to ₹25,000 per month depending &lt;br&gt;
on your hours and orders — so it genuinely helped me stay &lt;br&gt;
financially stable during a critical phase of my learning.&lt;/p&gt;

&lt;p&gt;But after 2 to 3 months, I made a decision that changed &lt;br&gt;
everything. I quit the Swiggy job completely.&lt;/p&gt;

&lt;p&gt;Not because it was bad money. But because I realized I was &lt;br&gt;
splitting my energy at exactly the wrong time. The evening hours &lt;br&gt;
I was spending on deliveries were hours I could spend practising &lt;br&gt;
code, building projects, and growing faster as a developer. &lt;br&gt;
Short-term comfort was slowing down my long-term growth.&lt;/p&gt;

&lt;p&gt;I quit. I went all in on web development. And I never looked back.&lt;/p&gt;

&lt;p&gt;Here's why web development made sense to me and still does in &lt;br&gt;
2026:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Salary growth is real and fast.&lt;/strong&gt; A fresher web developer in &lt;br&gt;
India starts at ₹10,000 to ₹20,000 per month. Within 3 years, &lt;br&gt;
a skilled developer can earn ₹40,000 to ₹80,000. Senior &lt;br&gt;
developers and specialists working with global clients can earn &lt;br&gt;
₹1,00,000 to ₹3,00,000+ per month — or the equivalent in USD &lt;br&gt;
working remotely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Remote work is a reality.&lt;/strong&gt; The job I do today, I can do from &lt;br&gt;
my home, from a café, or from another country entirely. No &lt;br&gt;
commute. No rigid office hours. No standing for 12 hours in a &lt;br&gt;
warehouse.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The work culture is different.&lt;/strong&gt; 8-hour workdays are standard. &lt;br&gt;
Paid leaves, sick leaves, and casual leaves are normal. Many &lt;br&gt;
companies provide hardware support — laptops, monitors, &lt;br&gt;
peripherals — so you don't need to invest your own money to do &lt;br&gt;
your job. Some even provide internet allowances.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Skills compound over time.&lt;/strong&gt; Every project I do makes me &lt;br&gt;
better at the next one. In data entry, doing more data entry &lt;br&gt;
just made me faster at data entry. In WordPress development, &lt;br&gt;
learning PHP leads to WooCommerce. WooCommerce leads to plugin &lt;br&gt;
development. Plugin development leads to React and headless &lt;br&gt;
architecture. The learning never stops — and neither does the &lt;br&gt;
income growth.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where I Am Today
&lt;/h2&gt;

&lt;p&gt;It's 2026. That ₹4,000/month fresher is now a Senior WordPress &lt;br&gt;
Developer with 9 years of experience.&lt;/p&gt;

&lt;p&gt;I've built and published plugins on WordPress.org. I've handled &lt;br&gt;
data migrations, performance optimizations, WooCommerce &lt;br&gt;
customizations, and headless WordPress projects. I work with &lt;br&gt;
modern tools — React, Next.js, Tailwind CSS, Cursor AI — and &lt;br&gt;
collaborate with global teams using Slack, Basecamp, and more.&lt;/p&gt;

&lt;p&gt;The textile market taught me discipline.&lt;br&gt;
The CA office taught me precision.&lt;br&gt;
The fake course taught me self-reliance.&lt;br&gt;
The Swiggy bag taught me that shortcuts don't exist — &lt;br&gt;
only trade-offs.&lt;br&gt;
And WordPress gave me a career.&lt;/p&gt;




&lt;p&gt;If you're reading this from a similar background — a small town, &lt;br&gt;
a tight budget, a job that doesn't feel like it's going anywhere &lt;br&gt;
— I want you to know that the path isn't always straight. Mine &lt;br&gt;
certainly wasn't.&lt;/p&gt;

&lt;p&gt;But if you find the right skill and commit to it fully, the &lt;br&gt;
direction changes.&lt;/p&gt;

&lt;p&gt;Keep building. 🙌&lt;/p&gt;

</description>
      <category>career</category>
      <category>webdev</category>
      <category>wordpress</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How I Built a WooCommerce Plugin That Works With Every Page Builder</title>
      <dc:creator>Kushang Tailor</dc:creator>
      <pubDate>Mon, 27 Apr 2026 13:14:47 +0000</pubDate>
      <link>https://forem.com/kushang_tailor/how-i-built-a-woocommerce-plugin-that-works-with-every-page-builder-4c2a</link>
      <guid>https://forem.com/kushang_tailor/how-i-built-a-woocommerce-plugin-that-works-with-every-page-builder-4c2a</guid>
      <description>&lt;h2&gt;
  
  
  The Problem I Noticed
&lt;/h2&gt;

&lt;p&gt;When I was working on WooCommerce stores for my clients, I kept &lt;br&gt;
running into the same frustrating issue — there was no good way &lt;br&gt;
to create a fully customizable WooCommerce product category page &lt;br&gt;
that worked across all editors.&lt;/p&gt;

&lt;p&gt;Every solution I found was locked to a specific page builder. &lt;br&gt;
Elementor users had one option. Gutenberg users had another. &lt;br&gt;
SiteOrigin users were mostly out of luck. And if your client &lt;br&gt;
used no editor at all — just plain shortcodes — forget it.&lt;/p&gt;

&lt;p&gt;I thought: &lt;em&gt;why should the editor choice limit what you can &lt;br&gt;
build?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So I built the &lt;strong&gt;Product Category&lt;/strong&gt; plugin — and published it &lt;br&gt;
on WordPress.org.&lt;/p&gt;




&lt;h2&gt;
  
  
  What the Plugin Does
&lt;/h2&gt;

&lt;p&gt;In simple terms, it lets you create a fully customizable &lt;br&gt;
WooCommerce product category listing page — and it doesn't &lt;br&gt;
matter which editor you or your client prefers.&lt;/p&gt;

&lt;p&gt;It works with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Elementor&lt;/strong&gt; — via a dedicated Widget with live preview&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Gutenberg / Block Editor&lt;/strong&gt; — via its own custom React Block&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;SiteOrigin&lt;/strong&gt; — via a Widget&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;WP Bakery / JS Composer&lt;/strong&gt; — via Shortcode&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;No editor / Classic editor&lt;/strong&gt; — via Shortcode&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One plugin. Every editor. No compromises.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;p&gt;Here's what you can control right inside the plugin settings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set a custom title for your category listing&lt;/li&gt;
&lt;li&gt;Show or hide specific product categories via dropdown&lt;/li&gt;
&lt;li&gt;Choose from multiple category display styles&lt;/li&gt;
&lt;li&gt;Set rows and columns for the layout grid&lt;/li&gt;
&lt;li&gt;Sort categories by Name or Slug (ASC / DESC order)&lt;/li&gt;
&lt;li&gt;Show or hide category descriptions&lt;/li&gt;
&lt;li&gt;Show or hide pagination&lt;/li&gt;
&lt;li&gt;Show or hide category thumbnail images&lt;/li&gt;
&lt;li&gt;Add proper Alt tags to category images (for SEO &amp;amp; 
accessibility)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the best part — with Elementor and Gutenberg, all of this &lt;br&gt;
is &lt;strong&gt;live preview&lt;/strong&gt;. You see changes in real time as you design.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Challenge: Supporting Multiple Editors
&lt;/h2&gt;

&lt;p&gt;The hardest part wasn't building the features — it was &lt;br&gt;
architecting the plugin so that the same core logic could power &lt;br&gt;
four completely different integration points.&lt;/p&gt;

&lt;p&gt;Each editor has its own way of registering and rendering &lt;br&gt;
components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Elementor&lt;/strong&gt; uses a Widget class that extends 
&lt;code&gt;\Elementor\Widget_Base&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gutenberg&lt;/strong&gt; uses &lt;code&gt;register_block_type()&lt;/code&gt; with a 
&lt;code&gt;block.json&lt;/code&gt; definition&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SiteOrigin&lt;/strong&gt; uses &lt;code&gt;SiteOrigin_Widget&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shortcode&lt;/strong&gt; uses WordPress's &lt;code&gt;add_shortcode()&lt;/code&gt; function&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key decision I made was to keep the &lt;strong&gt;rendering logic &lt;br&gt;
centralized&lt;/strong&gt; in one function, and have each editor integration &lt;br&gt;
simply call that function with its own set of parameters. This &lt;br&gt;
way, a bug fix or a new feature only needs to be written once — &lt;br&gt;
and all four editor integrations benefit immediately.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;Building this plugin taught me a lot about how different &lt;br&gt;
WordPress ecosystems actually work under the hood. Each page &lt;br&gt;
builder has its own lifecycle, its own way of passing data, and &lt;br&gt;
its own rendering context.&lt;/p&gt;

&lt;p&gt;It also taught me the importance of &lt;strong&gt;backward compatibility&lt;/strong&gt;. &lt;br&gt;
The plugin has been live since 2019 and I've maintained it &lt;br&gt;
through multiple WordPress versions — all the way up to WP 6.9. &lt;br&gt;
Every update had to ensure existing users weren't broken.&lt;/p&gt;

&lt;p&gt;And perhaps most importantly — it taught me to &lt;strong&gt;listen to &lt;br&gt;
users&lt;/strong&gt;. Features like pagination, Alt tag support, and the &lt;br&gt;
Gutenberg block were all added based on real feedback from people &lt;br&gt;
using the plugin in production.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Result
&lt;/h2&gt;

&lt;p&gt;The plugin currently has &lt;strong&gt;200+ active installations&lt;/strong&gt; on &lt;br&gt;
WordPress.org, a &lt;strong&gt;5-star rating&lt;/strong&gt;, and has been stable through &lt;br&gt;
7 years of WordPress updates.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://wordpress.org/plugins/product-category/" rel="noopener noreferrer"&gt;Check it out on WordPress.org&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;If you're a WooCommerce developer who's ever struggled with &lt;br&gt;
editor compatibility, I hope this gives you some ideas. And if &lt;br&gt;
you use the plugin, I'd love to hear your feedback!&lt;/p&gt;

&lt;p&gt;Feel free to connect — I'm always happy to talk WordPress, &lt;br&gt;
WooCommerce, or plugin architecture. 🙌&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>woocommerce</category>
      <category>php</category>
      <category>wpdev</category>
    </item>
  </channel>
</rss>
