<?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: Jorge Araya</title>
    <description>The latest articles on DEV Community by Jorge Araya (@jorgearay).</description>
    <link>https://dev.to/jorgearay</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%2F2401764%2F099570e9-6f03-412f-8c29-ab45fde8cdf1.png</url>
      <title>DEV Community: Jorge Araya</title>
      <link>https://dev.to/jorgearay</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jorgearay"/>
    <language>en</language>
    <item>
      <title>The WordPress Stack I Keep Reaching For</title>
      <dc:creator>Jorge Araya</dc:creator>
      <pubDate>Wed, 15 Apr 2026 03:23:28 +0000</pubDate>
      <link>https://dev.to/jorgearay/the-wordpress-stack-i-keep-reaching-for-3ggf</link>
      <guid>https://dev.to/jorgearay/the-wordpress-stack-i-keep-reaching-for-3ggf</guid>
      <description>&lt;p&gt;Over the past few years I've worked with a good mix of WordPress setups. Traditional starter themes, page builders, and more recently some FSE experiments. Each approach solves a different problem, and I still think they all have their place depending on the type of project and the team behind it.&lt;/p&gt;

&lt;p&gt;That said, there’s one combination I keep coming back to more often than not:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://underscoretw.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;_tw&lt;/strong&gt;&lt;/a&gt; as the base theme&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ACF&lt;/strong&gt; with custom blocks&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tailwind CSS&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Alpine.js&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not because it's the "best" option in every case, but because it consistently hits a sweet spot between flexibility, performance, and development speed. It’s one of those setups that just feels reliable once you’ve used it a few times.&lt;/p&gt;

&lt;h2&gt;
  
  
  What most of my projects actually need
&lt;/h2&gt;

&lt;p&gt;The projects I typically work on don’t call for a heavy frontend framework or a fully visual editing experience. Most of them are marketing sites, content-driven builds, or custom client work where clarity and maintainability matter more than flashy tooling.&lt;/p&gt;

&lt;p&gt;What they really need is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clean, maintainable code that won't become a headache six months later&lt;/li&gt;
&lt;li&gt;Fast load times without needing constant optimization workarounds&lt;/li&gt;
&lt;li&gt;A structured editing experience that keeps content editors productive without giving them enough freedom to accidentally break things&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This stack fits that space really well. It gives me control as a developer while still delivering a solid experience for whoever is managing the content later on.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the pieces work together
&lt;/h2&gt;

&lt;p&gt;What I value most about this combination isn’t any single tool. It’s how they complement each other and reduce friction across the whole development process.&lt;/p&gt;

&lt;h3&gt;
  
  
  _tw as the foundation
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://underscoretw.com/" rel="noopener noreferrer"&gt;_tw&lt;/a&gt; gives me a clean starting point without imposing too many opinions. Instead of spending the first hour of a project removing things I don’t need, I can focus on shaping the theme around the project requirements from the start.&lt;/p&gt;

&lt;p&gt;It also comes with Tailwind already configured, which removes a lot of setup overhead and makes the initial development phase feel almost immediate.&lt;/p&gt;

&lt;h3&gt;
  
  
  ACF Blocks for content structure
&lt;/h3&gt;

&lt;p&gt;This is where most of the architecture lives. I define blocks that give clients clear, structured fields to work with. No guessing where things go. No accidentally breaking layouts by dragging elements around or mixing components in unintended ways.&lt;/p&gt;

&lt;p&gt;In practice, this means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;more predictable layouts
&lt;/li&gt;
&lt;li&gt;fewer support requests
&lt;/li&gt;
&lt;li&gt;and a smoother handoff once the project is live
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The editing experience ends up feeling intentional. Flexible enough to cover real use cases, but constrained enough to keep everything consistent across pages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tailwind for fast, predictable styling
&lt;/h3&gt;

&lt;p&gt;When every block is treated as its own component, Tailwind makes styling feel almost mechanical (in a good way). I’m not spending time naming classes or dealing with specificity issues. I’m just building.&lt;/p&gt;

&lt;p&gt;Over time, this also helps keep styles more consistent across the project. There’s less drift, less duplication, and fewer surprises when revisiting older code.&lt;/p&gt;

&lt;p&gt;Paired with the _tw setup, the workflow barely needs any CSS configuration out of the box.&lt;/p&gt;

&lt;h3&gt;
  
  
  Alpine.js for just enough interactivity
&lt;/h3&gt;

&lt;p&gt;Toggles, dropdowns, tabs, mobile menus, conditional visibility. Alpine handles all of it with a few attributes directly in the markup.&lt;/p&gt;

&lt;p&gt;No build step. No component hierarchy. No state management overhead.&lt;/p&gt;

&lt;p&gt;For the level of interactivity most marketing sites and corporate pages need, this approach keeps things simple and easy to maintain without sacrificing functionality.&lt;/p&gt;

&lt;h2&gt;
  
  
  When I reach for something else
&lt;/h2&gt;

&lt;p&gt;I don’t default to this stack on every project. There are clear cases where it’s not the right fit, and forcing it would only make things harder.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;App-like projects&lt;/strong&gt; that need complex state management or real-time interactions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Teams already committed to React, Vue, or similar ecosystems&lt;/strong&gt;, where consistency matters more than personal preference&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Projects where full visual editing is a hard requirement&lt;/strong&gt;, and the client expects to control layout more freely&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In those situations, I’ll switch to whatever makes the most sense. The goal is always to pick the right tool for the job, not to stick to a single stack out of habit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it keeps earning its spot
&lt;/h2&gt;

&lt;p&gt;Even with all the alternatives out there, like headless setups, block-based builders, and full JavaScript frameworks, I keep reaching for this stack because it consistently delivers where it matters.&lt;/p&gt;

&lt;p&gt;It lets me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ship faster&lt;/strong&gt; without cutting corners on structure
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hand off confidently&lt;/strong&gt;, knowing the codebase will still make sense later
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid unnecessary complexity&lt;/strong&gt; that doesn’t add real value to the project
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s predictable in the best way. I know how it behaves, how it scales, and what to expect when coming back to a project months later. That kind of reliability is hard to overstate in real-world work.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;This isn’t a fixed rule. It’s just a current favorite.&lt;/p&gt;

&lt;p&gt;I’m always experimenting with new approaches, especially as WordPress continues to evolve. If a better setup comes along for this type of project, I’m more than open to switching things up.&lt;/p&gt;

&lt;p&gt;But for now, &lt;a href="https://underscoretw.com/" rel="noopener noreferrer"&gt;_tw&lt;/a&gt; + ACF + Tailwind + Alpine keeps proving itself, project after project.&lt;/p&gt;




&lt;p&gt;I usually write about WordPress workflows and dev setups on my site.&lt;/p&gt;

&lt;p&gt;Original post:&lt;br&gt;
&lt;a href="https://jorgearaya.com/blog/wordpress-stack-i-keep-reaching-for" rel="noopener noreferrer"&gt;https://jorgearaya.com/blog/wordpress-stack-i-keep-reaching-for&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>wordpress</category>
      <category>acf</category>
      <category>ai</category>
    </item>
    <item>
      <title>Create Your Own Chromium Browser Extension from Scratch</title>
      <dc:creator>Jorge Araya</dc:creator>
      <pubDate>Fri, 28 Feb 2025 03:00:24 +0000</pubDate>
      <link>https://dev.to/jorgearay/create-your-own-chromium-browser-extension-from-scratch-42f</link>
      <guid>https://dev.to/jorgearay/create-your-own-chromium-browser-extension-from-scratch-42f</guid>
      <description>&lt;p&gt;Browser extensions are powerful tools that allow users to customize and enhance their browsing experience, or in my case, as a developer it allows me to create solutions for my everyday problems.&lt;/p&gt;

&lt;p&gt;If you’re a web developer interested in building your own extension for Chromium-based browsers like Google Chrome, Microsoft Edge, or Brave, this guide will walk you through the basics by creating an extension to copy the name of the images 🏞️.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Basics
&lt;/h2&gt;

&lt;p&gt;A Chromium extension is essentially a small web application made up of HTML, CSS, and JavaScript. It interacts with the browser through the Extensions API, allowing you to modify pages, add functionalities, and interact with the browser UI.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Components of a Chromium Extension
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Manifest File (manifest.json) - The configuration file that defines the extension’s metadata, permissions, and scripts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Background Script - Runs in the background and manages events.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Content Scripts - Injected into web pages to modify content.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Popup UI - The front-end interface shown when users interact with the extension.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Permissions - Defines what the extension can access, such as tabs, storage, or bookmarks.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setting Up the Extension
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Create the Project Directory
&lt;/h3&gt;

&lt;p&gt;Create a new folder and name it something like &lt;code&gt;image-name-copy&lt;/code&gt; or any other name you like.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Define the Manifest File
&lt;/h3&gt;

&lt;p&gt;Inside your project folder, create a &lt;code&gt;manifest.json&lt;/code&gt; file with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"manifest_version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Image Name Copy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Easily copy image filenames through a right-click context menu. Automatically saves names to clipboard with confirmation notification."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"permissions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"contextMenus"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"scripting"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"notifications"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"clipboardWrite"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"background"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"service_worker"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"background.js"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"host_permissions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;all_urls&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"icons"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"48"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"images/icon-48.png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"128"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"images/icon-128.png"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;



&lt;p&gt;Here are some important notes and definitions for the code above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;permissions: This is very important since it will define which browser permissions our extension will require.&lt;/li&gt;
&lt;li&gt;background: This is the main script where we'll handle events and execute our logic.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 3: Implement the Background Script
&lt;/h3&gt;

&lt;p&gt;Create a &lt;code&gt;background.js&lt;/code&gt; file inside your project folder.&lt;/p&gt;

&lt;p&gt;And first let create the context menu, this will add a menu item on the browser when you right-click, add this code on the &lt;code&gt;background.js&lt;/code&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Create context menu&lt;/span&gt;
&lt;span class="nx"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contextMenus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;copyImageName&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Copy Image Name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;contexts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;image&lt;/span&gt;&lt;span class="dl"&gt;"&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;Now, let's define what happens when the user clicks this menu item. We'll use a "click" listener to trigger the functionality we want when this menu item is clicked.&lt;/p&gt;

&lt;p&gt;A script is injected into the page using &lt;code&gt;chrome.scripting.executeScript()&lt;/code&gt; this method executes the code in the context of the web page where the user clicks the menu item. And this calls the function &lt;code&gt;copyToClipboard&lt;/code&gt; that contains the browser function &lt;code&gt;navigator.clipboard.writeText()&lt;/code&gt; to copy the filename.&lt;/p&gt;

&lt;p&gt;In this case, we are setting a notification as feedback. This way we can visually see when the name of the image is being copied. For the notifications I've created a separate function called &lt;code&gt;showNotification&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Add the following code right bellow the context menu code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Listen for click in context menu&lt;/span&gt;
&lt;span class="nx"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contextMenus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onClicked&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;menuItemId&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;copyImageName&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;srcUrl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;imageName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;extractImageName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;srcUrl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scripting&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;executeScript&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;tabId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;function&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;copyToClipboard&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;imageName&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(([&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;showNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Copied: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;imageName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;success&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Copy failed.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;showNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Error: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Copy to clipboard within the page&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;copyToClipboard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clipboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Failed to copy. Click on the page first.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Get the image name from the URL&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;extractImageName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;?&lt;/span&gt;&lt;span class="dl"&gt;"&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="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;untitled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Show notifications&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;showNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;success&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notifications&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;basic&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;iconUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;success&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;images/success.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;images/error.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;success&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Success&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&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;h3&gt;
  
  
  Step 4: Adding your images/icons
&lt;/h3&gt;

&lt;p&gt;Icons are required for browser extensions, you can create a folder named &lt;code&gt;images&lt;/code&gt; and add all the files in there. These images will be called in the &lt;code&gt;manifest.json&lt;/code&gt; file on the "icons" section.&lt;/p&gt;

&lt;p&gt;Step 5: Load the Extension in Chromium&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Open chrome://extensions/ in your browser.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable "Developer mode" (toggle in the top right corner).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click "Load unpacked" and select your project folder.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your extension should now appear in the list!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now if you right-click on an image on any page, it will copy the name of the file. Please note that this won't work on background images, since it requires a different process.&lt;/p&gt;




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

&lt;p&gt;Creating a Chromium extension is a great way to enhance browser functionality and customize the web experience. By following this guide, you now have the foundation to build and expand your own extensions. Happy coding!&lt;/p&gt;

&lt;p&gt;Here you can find a &lt;a href="https://github.com/jorgearaya474/image-name-copy" rel="noopener noreferrer"&gt;repository&lt;/a&gt; with the example used on this post.&lt;/p&gt;

&lt;p&gt;If you have any ideas, questions, or improvements, feel free to leave a comment bellow. Happy coding! 🚀&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>browser</category>
    </item>
    <item>
      <title>Building Your WordPress Website: Custom Code or Page Builder?</title>
      <dc:creator>Jorge Araya</dc:creator>
      <pubDate>Fri, 10 Jan 2025 03:47:35 +0000</pubDate>
      <link>https://dev.to/jorgearay/building-your-wordpress-website-custom-code-or-page-builder-3jip</link>
      <guid>https://dev.to/jorgearay/building-your-wordpress-website-custom-code-or-page-builder-3jip</guid>
      <description>&lt;p&gt;When you're building a WordPress website, you're faced with a crucial decision: should you opt for a custom-coded theme or rely on a page builder? Both approaches have their own strengths and weaknesses, and the best choice ultimately depends on your specific needs and priorities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Options
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Custom Code:
&lt;/h3&gt;

&lt;p&gt;Building a WordPress site with custom code involves manually writing HTML, CSS, JavaScript, and PHP to design and develop your website. This approach often provides complete control and flexibility over functionality, design, and performance.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unparalleled Flexibility:&lt;/strong&gt; Total control over every aspect of the website's look and feel. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Performance:&lt;/strong&gt; Can be optimized for speed and efficiency, leading to better search engine rankings.   &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved Security:&lt;/strong&gt; Reduced vulnerability to common WordPress exploits.   &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unique Branding:&lt;/strong&gt; Stand out from the crowd with a truly distinctive online presence.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Higher Cost:&lt;/strong&gt; Development and ongoing maintenance can be expensive.   &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Steeper Learning Curve:&lt;/strong&gt; Requires technical expertise for customization and updates, especially if you are just starting out in WordPress custom code development.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Longer Development Time:&lt;/strong&gt; Can take significantly longer to build compared to page builders.  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Page Builders:
&lt;/h3&gt;

&lt;p&gt;Page builders are drag-and-drop tools that allow you to design and build a website without needing to write code. Popular page builders for WordPress include Elementor, Beaver Builder, and Divi.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ease of Use:&lt;/strong&gt; Intuitive interfaces make website creation accessible to beginners.   &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Faster Development:&lt;/strong&gt; Quickly create complex designs without coding knowledge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost-Effective:&lt;/strong&gt; Many options are available as one-time purchases or affordable subscriptions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Large Community and Support:&lt;/strong&gt; Access to extensive resources, tutorials, and active communities.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Limited Customization:&lt;/strong&gt; May not be suitable for highly complex designs or unique branding needs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Potential Performance Issues:&lt;/strong&gt; Can sometimes impact website loading speed if not used carefully.   &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bloat:&lt;/strong&gt; Can lead to unnecessary code and increase website size, potentially affecting performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vendor Lock-in:&lt;/strong&gt; Can be challenging to migrate away from a page builder if you decide to change platforms.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Which is Right for You?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Choose a Custom-Coded Theme if:&lt;/strong&gt;&lt;br&gt;
You require a highly unique and complex website design, performance and SEO are top priorities, you have a dedicated budget for development and ongoing maintenance, and you need a high level of customization and control.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choose a Page Builder if:&lt;/strong&gt; &lt;br&gt;
You have limited technical expertise and prefer a user-friendly approach, you need to build a website quickly and efficiently, you're on a tight budget and looking for cost-effective solutions, and you value ease of use and a large community for support.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hybrid Approach
&lt;/h2&gt;

&lt;p&gt;Many developers successfully leverage a hybrid approach by combining the power of custom code with the user-friendliness of page builders. This synergistic method allows you to harness the strengths of both worlds, resulting in a website that is both visually appealing and highly functional.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key benefits include:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Increased flexibility:&lt;/strong&gt; Combine custom code for unique features with the ease of a page builder.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced performance:&lt;/strong&gt; Optimize with custom code while maintaining visual appeal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved security:&lt;/strong&gt; Build a secure foundation with custom code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; &lt;br&gt;
Use custom code for new content types or advanced features, then easily manage them with a page builder. You could build your custom theme foundation with code and then use a page builder for the internal content of pages or posts.&lt;/p&gt;

&lt;p&gt;This approach provides a balance of control, flexibility, and ease of use for your WordPress website.&lt;/p&gt;




&lt;p&gt;Both custom code and page builders have their place in WordPress development. Understanding your specific needs and limitations will help you make the right choice. Whether you opt for the creative freedom of custom coding or the efficiency of page builders, the key is to build a website that serves your goals, engages your audience, and scales with your growth.&lt;/p&gt;

&lt;p&gt;What would you choose? Share your thoughts in the comments below.&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>webdev</category>
    </item>
    <item>
      <title>First Look at Incremental Static Regeneration (ISR) in Next.js</title>
      <dc:creator>Jorge Araya</dc:creator>
      <pubDate>Tue, 07 Jan 2025 03:50:33 +0000</pubDate>
      <link>https://dev.to/jorgearay/first-look-at-incremental-static-regeneration-isr-in-nextjs-1pch</link>
      <guid>https://dev.to/jorgearay/first-look-at-incremental-static-regeneration-isr-in-nextjs-1pch</guid>
      <description>&lt;p&gt;Static site generation (SSG) is one of the core features that makes Next.js powerful. However, traditional static sites often face the challenge of keeping content up-to-date without redeploying the entire application.&lt;/p&gt;

&lt;p&gt;In this post, you'll learn:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What ISR is and why it's useful.&lt;/li&gt;
&lt;li&gt;How to implement ISR in a simple blog example.&lt;/li&gt;
&lt;li&gt;Common use cases and best practices.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What is Incremental Static Regeneration (ISR)?
&lt;/h2&gt;

&lt;p&gt;ISR is a feature that allows you to update static content at runtime, combining the speed of static pages with the flexibility of dynamic content.&lt;/p&gt;

&lt;p&gt;With ISR your application will have the ability to revalidate static pages after a specified time interval. In simpler words, this means you can serve pre-rendered content while keeping it updated without rebuilding your application. &lt;/p&gt;

&lt;p&gt;With ISR, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pre-render pages at build time.&lt;/li&gt;
&lt;li&gt;Set an interval (e.g., every 10 seconds) to regenerate the static page in the background.&lt;/li&gt;
&lt;li&gt;Serve updated content on subsequent requests.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;Incremental Static Regeneration (ISR) combines the benefits of static generation with the freshness of dynamic content.&lt;/p&gt;

&lt;p&gt;When a user makes the first request to a page, Next.js generates it statically and caches the result. This initial generation happens on-demand rather than at build time, meaning pages are created only when they're actually needed.&lt;br&gt;
Here's how it works step by step:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;First user visits the page → Next.js generates and caches it&lt;/li&gt;
&lt;li&gt;Other users visit → They see the cached version&lt;/li&gt;
&lt;li&gt;After revalidation time expires → Next visit triggers background update&lt;/li&gt;
&lt;li&gt;New version replaces the old one in cache&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After a specified time period, the next user request triggers a background regeneration, seamlessly updating the cached content.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to setup ISR?
&lt;/h2&gt;

&lt;p&gt;Let’s build a simple blog that updates dynamically using ISR. This example uses the App Router.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/articles/page.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;revalidate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="c1"&gt;// Set the revalidation interval to 10 seconds&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getPosts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://jsonplaceholder.typicode.com/posts?_limit=5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Articles&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getPosts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Latest Articles&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&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;In the above example the page will be regenerated every 10 seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to Use ISR?
&lt;/h2&gt;

&lt;p&gt;ISR is perfect for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Content that updates periodically but doesn’t need real-time updates.&lt;/li&gt;
&lt;li&gt;Product pages that need periodic updates (e.g., stock availability).&lt;/li&gt;
&lt;li&gt;Pages with dynamic content that changes occasionally.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;ISR in Next.js bridges the gap between static and dynamic content, offering a flexible and powerful way to build more sophisticated web applications. Whether you’re creating a blog, an online store, or a dashboard, ISR is a very cool feature that is worth exploring.&lt;/p&gt;

&lt;p&gt;What are your thoughts on ISR? Have you used it in your projects? Please share your experience in the comments!&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to set up a simple WordPress local environment with Docker</title>
      <dc:creator>Jorge Araya</dc:creator>
      <pubDate>Fri, 15 Nov 2024 03:35:19 +0000</pubDate>
      <link>https://dev.to/jorgearay/how-to-set-up-a-simple-wordpress-local-environment-with-docker-53dc</link>
      <guid>https://dev.to/jorgearay/how-to-set-up-a-simple-wordpress-local-environment-with-docker-53dc</guid>
      <description>&lt;p&gt;Docker is one of those amazing tools that everyone wants to get their hands on. In the last few years, it has become very popular, and if you are bored of the same local environment setups with xampp or wamp, this is a great option to learn about &lt;a href="https://www.docker.com/resources/what-container/" rel="noopener noreferrer"&gt;containers&lt;/a&gt; and improve your development environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  First, you need to install Docker
&lt;/h2&gt;

&lt;p&gt;To install docker desktop you can download it from the &lt;a href="https://www.docker.com/products/docker-desktop/" rel="noopener noreferrer"&gt;docker page&lt;/a&gt;. It's available for Windows, Linux, and Mac, check out the &lt;a href="https://www.docker.com/products/docker-desktop/" rel="noopener noreferrer"&gt;official page&lt;/a&gt;, select your system, and follow the installation steps, and then you'll be ready to go!&lt;/p&gt;

&lt;h2&gt;
  
  
  Create the project directory and files
&lt;/h2&gt;

&lt;p&gt;You need to create a directory where your WordPress installation is going to be, in this directory you will have the necessary folders to place your plugins and themes.&lt;/p&gt;

&lt;p&gt;Create a folder, I'm going to call it &lt;code&gt;wp-local-docker&lt;/code&gt;, inside this folder you need to create a docker compose file called &lt;code&gt;docker-compose.yml&lt;/code&gt;, this is the configuration file for our docker setup. In this file, we're going to add all the necessary services to have WordPress up and running.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;docker-compose.yml&lt;/code&gt; file you need to specify the version and the services, the first service will be the database; in this service, we define the database image that docker is going to use, the volume, the ports where the service will be running, and the MySql environment variables. &lt;/p&gt;

&lt;p&gt;The next service is going to be the WordPress service, where we need to define the image, the WordPress environment variables, and the volumes where the WordPress plugins and themes will be allocated, the entire file should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.9'&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql:latest&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db_data:/var/lib/mysql&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wordpress&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_DATABASE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wordpress&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wordpress&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wordpress&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3306:3306"&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;localwp&lt;/span&gt;

  &lt;span class="na"&gt;wordpress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wordpress:latest&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;WORDPRESS_DB_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;db:3306&lt;/span&gt;
      &lt;span class="na"&gt;WORDPRESS_DB_NAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wordpress&lt;/span&gt;
      &lt;span class="na"&gt;WORDPRESS_DB_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wordpress&lt;/span&gt;
      &lt;span class="na"&gt;WORDPRESS_DB_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wordpress&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;wpfiles:/var/www/html&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./wordpress/themes:/var/www/html/wp-content/themes&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./wordpress/plugins:/var/www/html/wp-content/plugins&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8000:80"&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;on-failure&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;localwp&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;db_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;wpfiles&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;*Make sure to use the correct identation to .yml files.&lt;/p&gt;

&lt;p&gt;As you may see, you will need a directory to allocate all your themes and plugins, for this create a folder called &lt;code&gt;wordpress&lt;/code&gt; and inside this folder create another two, one for &lt;code&gt;plugins&lt;/code&gt; and one for &lt;code&gt;themes&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;At this point, the only thing left to do is open docker, and once it's running on your system, open the terminal and go to your project folder, in my case &lt;code&gt;wp-local-docker/&lt;/code&gt; and run &lt;code&gt;docker-compose up&lt;/code&gt;, with this docker is going to create the containers and pull all the necessary thing to get the services (databse and wordpress) running. You can run &lt;code&gt;docker-compose down&lt;/code&gt; to stop the containers.&lt;/p&gt;

&lt;p&gt;And that's it! 🎉 You've now set up a Dockerized WordPress development environment. Enjoy the smooth and flexible experience of working with containers! Happy coding and have fun! 🚀&lt;/p&gt;

&lt;p&gt;Here is a &lt;a href="https://github.com/jorgearaya474/wp-local-docker" rel="noopener noreferrer"&gt;link&lt;/a&gt; to a github repository with a basic example. &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>wordpress</category>
    </item>
    <item>
      <title>Understanding Shortcodes in WordPress: A Beginner’s Guide</title>
      <dc:creator>Jorge Araya</dc:creator>
      <pubDate>Tue, 12 Nov 2024 04:13:07 +0000</pubDate>
      <link>https://dev.to/jorgearay/understanding-shortcodes-in-wordpress-a-beginners-guide-2ho9</link>
      <guid>https://dev.to/jorgearay/understanding-shortcodes-in-wordpress-a-beginners-guide-2ho9</guid>
      <description>&lt;p&gt;In the WordPress world, shortcodes are a very powerful feature. They allow you to insert complex functionality into your posts and pages with a simple code snippet. If you're just starting with WordPress development, this guide will help you understand what shortcodes are, how they work, and how to create your own!&lt;/p&gt;

&lt;h2&gt;
  
  
  What exactly are shortcodes?
&lt;/h2&gt;

&lt;p&gt;Shortcodes are small pieces of code that you add to a post, page, or widget to include dynamic content. They act as placeholders that WordPress processes and replaces with more complex functionality when the page loads.&lt;/p&gt;

&lt;p&gt;For example, &lt;code&gt;[year]&lt;/code&gt; could be a shortcode used to display the current year dynamically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why should you use shortcodes?
&lt;/h2&gt;

&lt;p&gt;They provide a simplified way to add advanced features to your content. Instead of writing the same code repeatedly, you can create a reusable shortcode to save time and maintain consistency. Shortcodes are perfect for adding custom features like contact forms, buttons, or galleries to multiple pages, with the ability to control them from a single place.&lt;/p&gt;

&lt;p&gt;Now, let’s get to the good part: how to create custom shortcodes.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to create a custom shortcode
&lt;/h2&gt;

&lt;p&gt;Creating your own basic shortcode in WordPress requires just a little PHP.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Open your &lt;code&gt;functions.php&lt;/code&gt; file.
&lt;/h3&gt;

&lt;h3&gt;
  
  
  2. Create a function for what you want the shortcode to do.
&lt;/h3&gt;

&lt;p&gt;For example:&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;function&lt;/span&gt; &lt;span class="n"&gt;cta_button_shortcode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;a href="#" class="cta-button"&amp;gt;Click Here!&amp;lt;/a&amp;gt;'&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;h3&gt;
  
  
  3. Register the shortcode.
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;add_shortcode&lt;/code&gt;function takes two parameters: the first is the name of the shortcode, for example, &lt;code&gt;[cta_button]&lt;/code&gt;. The second is the callback function that will handle all the logic and render the result—in this case, our &lt;code&gt;cta_button_shortcode&lt;/code&gt; function.&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_shortcode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'cta_button'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'cta_button_shortcode'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Use Your Shortcode!
&lt;/h3&gt;

&lt;p&gt;Now, you can use &lt;code&gt;[cta_button]&lt;/code&gt; in any post or page, and it will display a link element with the text "Click Here!".&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding parameters to the shortcode
&lt;/h2&gt;

&lt;p&gt;You can also add parameters to shortcodes, which act as attributes that pass information to the shortcode function. This lets you change the text or the link of our button without needing to edit the code or create additional shortcodes. With parameters, you can also define default values in case they’re not provided in the shortcode.&lt;/p&gt;

&lt;p&gt;I highly recommend checking out the &lt;a href="https://developer.wordpress.org/reference/functions/shortcode_atts/" rel="noopener noreferrer"&gt;official WordPress documentation&lt;/a&gt; about the shortcode atts.&lt;/p&gt;

&lt;p&gt;See the example bellow:&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;function&lt;/span&gt; &lt;span class="n"&gt;cta_button_shortcode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$atts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$atts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;shortcode_atts&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="s1"&gt;'text'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Click Here!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Default value&lt;/span&gt;
            &lt;span class="s1"&gt;'url'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Default value&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nv"&gt;$atts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'cta_button'&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;a href="'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nf"&gt;esc_url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$atts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'url'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'" class="cta-button"&amp;gt;'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nf"&gt;esc_html&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$atts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'text'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;/a&amp;gt;'&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;Now we can use it as &lt;code&gt;[cta_button text="Learn More" url="https://example.com"]&lt;/code&gt;, and if we need to change the text and link, we can do so without modifying our shortcode code.&lt;/p&gt;




&lt;p&gt;Now you know the basics of WordPress shortcodes! With just a few lines of code, you can create powerful and flexible content elements that make your site more dynamic and easier to manage. Whether you’re building buttons, forms, or unique design elements, shortcodes are here to make your life as a developer a bit easier and a lot more fun.&lt;/p&gt;

&lt;p&gt;So go ahead, experiment, and see what cool features you can create! 🎉 Shortcodes are like little magic tricks you can pull out anytime to make WordPress even more amazing. Happy coding! 🚀&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>php</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
