Category: Geekery

  • I hated cuilding Custom Gutenberg blocks… Until Claude changed everything

    For years I built client sites the “normal” way. Need a custom testimonial section? I would either: Use a page builder (and hate the bloat), Write a shortcode (and feel dirty), Or attempt a real native Gutenberg block… and spend 4–6 hours fighting block.json, React hooks, InnerBlocks, responsive attributes, and PHP render_callback just to get something that didn’t break on save.

    I wanted native blocks — fast, lightweight, fully accessible, with proper block.json registration, clean React edit components, and optional server-side rendering in PHP. But the boilerplate was brutal. Then, in late April 2026, everything changed.

    The Day I Discovered Cursor + Claude 4 Sonnet

    I saw a short X thread from a developer I respect saying: “I just built a 7-feature pricing table block with toggle, schema markup, and animated counters in 11 minutes using Cursor + Claude 4 Sonnet. I’m never going back.”

    I was skeptical. I’d tried Grok, ChatGPT, Copilot, and even the new WordPress Telex experiment. They were ok, not that impressive.

    But I downloaded Cursor (the AI-first code editor), pointed it at a fresh plugin folder, and switched the model to Claude 4 Sonnet.

    My first prompt was deliberately simple: Create a production-ready native Gutenberg block called Feature Grid. Use modern block.json. Support 3–6 columns, icon (Dashicon or SVG), heading, description, optional button. Add color controls for background, text, and accent. Make it fully responsive (1-col mobile, 2-col tablet, 3-col desktop).

    42 seconds later Cursor had created the block.json

    It even included proper wp.i18n, escaping, accessibility attributes, and a clean InnerBlocks wrapper. I was speechless.

    The Blocks I’ve Built Since Then (Any Layout I Can Imagine)

    Once I saw what was possible, I went crazy. Here are some of the blocks I’ve shipped to real client sites in the last 10 days:

    1. Testimonial Carousel with Star Ratings + Autoplay

    Drag-and-drop testimonials
    5-star rating system (stored as attribute)
    Autoplay + pause on hover + navigation arrows
    Schema.org markup generated in render.php
    Fully responsive + swipe on mobile
    Time taken: 14 minutes (including 3 iterations)

    2. Pricing Table with Monthly/Annual Toggle

    React state for toggle
    Animated price change
    Highlighted “Most Popular” column
    Custom color controls + hover effects
    Server-side rendered for SEO
    Time taken: 19 minutes

    3. Interactive FAQ Accordion with JSON-LD Schema

    Smooth CSS animations
    Open multiple / single mode toggle
    Auto-generates proper FAQ schema
    Searchable (client-side filter)
    Time taken: 12 minutes

    4. Masonry-Style Image Gallery with Lightbox

    Drag multiple images
    Masonry layout via CSS Grid + JS
    Click opens native lightbox (no extra library)
    Caption + alt text editing inside the block
    Time taken: 17 minutes

    5. Feature Comparison Table (like the ones on Notion / Linear)

    Add/remove rows & columns dynamically
    Check/cross icons with color
    Mobile-responsive (cards on mobile)
    Time taken: 23 minutes

    Every single one of these is 100% native Gutenberg, and it works perfectly in the Site Editor, Full Site Editing, and classic themes.

    How I Prompt Claude 4 in Cursor (The Secret Sauce)

    I now use a consistent workflow that gives me near-perfect results every time:

    Step 1 – Project Rules (I created a .cursor/rules file)

    Always use apiVersion: 3 and modern block.json schema
    - Prefer render.php for dynamic content when possible
    - Follow WordPress Coding Standards strictly
    - Include proper escaping, sanitization, and i18n
    - Make every block fully accessible (ARIA, keyboard nav, color contrast)
    - Output complete, ready-to-build folder structure

    Step 2 – The Master Prompt Template

    You are an expert WordPress Gutenberg block developer.
    Create a production-ready native block called [Block Name].

    Requirements:
    1. [list every feature, control, layout behavior]
    2. Use block.json with apiVersion 3
    3. Full responsive design (mobile-first)
    4. Color, typography, and spacing controls
    5. Accessibility best practices
    6. Clean, commented code

    I then iterate in Cursor’s chat sidebar:
    – Add InnerBlocks support so users can put buttons inside each card
    – Make the carousel use the new Interactivity API instead of vanilla JS
    – Add a ‘Show on mobile only’ toggle attribute

    Claude 4 Sonnet or Opus handles context across multiple files better than any model I’ve tried. It remembers what we already built and suggests smart improvements. Which is awesome. Now life gets easier, specially web developers who struggles to use Gutenberg. Hahaha!

    Now I spend that time on design and user experience instead of boilerplate. The best part? I’m actually learning faster. Claude explains why it chose certain patterns (I used useBlockProps with className merging because…). I’ve leveled up my own Gutenberg skills dramatically in just two weeks.

    Honest Limitations (Because I’m Not Selling You Anything)

    You still need to test in a real WordPress environment (Claude is amazing but not perfect with every edge case of the Site Editor). Complex blocks sometimes need 2–3 follow-up prompts. And sometimes, the JSON output is broken, because AIs are not perfect, they also make mistakes like their human creators. You should understand the basics of Gutenberg. This is not “no-code” development. It’s “super-code”, development. These limitations are tiny compared to the 80–90% time savings.

    My Honest Recommendation as of June 2026. If you are a WordPress developer who has ever thought:

    “I wish I could just describe the block I want and have it appear…”

    Then stop everything and install Cursor + switch to Claude 4 Sonnet today. It’s not just faster. It fundamentally changed what I believe is possible for a solo developer to ship. I went from avoiding custom blocks to actively suggesting them to clients because now they are fun instead of painful.

    Enjoy vibe coding!

  • Too many new features in WP 6.9

    I recently upgraded my blog to 6.9 and I love how WP progressed over the years. Back then I just use this for blogging, but now, it’s everything. You can even create apps, dashboards, booking systems, and everything you can think of using WP. Now, you can even leave comments like using Figma.

    The drag and drop editor Gutenberg that was so bad back then, really improved this 2026.

    I’m still using Classic Editor btw, but I’m gonna switch again and will just use the default Gutenberg editor moving forward. So far so gooooood!

    Also, I recently discovered vibe coding, and you can actually deploy professionally built websites and blog, that’s already headless in just a few seconds. Worst case scenario is minutes. lol! Now everyone is a web / app developer!

    Anyway, I know this guy who is bragging too much about he deployed this and that, and made this and that, with zero coding knowledge. Now this guy deployed a CRM where the company is actually using. One day, there’s an issue about it and he cannot fix it, nor the AI. I think it’s server related issue or some capacity as the code is not that optimized. It frequently goes down. He can’t fix it, AI can’t fix it, and it went down. He has zero clue how to fix it, so he resigned.

    Lesson here is, don’t overly rely on AI. Even a simple CSS issue, AI overcomplicates it, even if it’s just a simple one line fix.

    Gotta learn the basics, instead of just telling the artificial intelligence everything what you want.

    A solid foundation in basics is better than zero foundation at all.

    Stay humble. Stay foolish. Stay Hungry. Thank you Steve Jobs!

  • Clean Login custom user meta fields WP snippet

    I just made extra fields in my user registration and made it appear in the clean login [edit-profile] shortcode. Here’s a wp snippet that you can modify to do the same. I registered two custom user meta fields via formidable forms, but I can only view it if I display the form in the frontend. Formidable Forms lack the confirm email functionality when you change the email address in the web form, so I used clean login to achieve a frontend edit profile with e-mail confirmation.

    Below is an example snippet to add more fields in your clean login edit profile page.

    <?php
    // Add custom user meta fields to the Clean Login edit form
    add_action( 'clean_login_edit_profile_fields', function( $user_id ) {
        $contact   = get_user_meta( $user_id, 'contact', true );
        $territory = get_user_meta( $user_id, 'territory', true );
        ?>
        <p>
            <label for="contact"><?php _e( 'Contact', 'clean-login' ); ?></label><br>
            <input type="text" name="contact" id="contact" value="<?php echo esc_attr( $contact ); ?>" />
        </p>
        <p>
            <label for="territory"><?php _e( 'Territory', 'clean-login' ); ?></label><br>
            <input type="text" name="territory" id="territory" value="<?php echo esc_attr( $territory ); ?>" />
        </p>
        <?php
    });
    
    // Save the custom fields when user updates profile
    add_action( 'clean_login_save_profile_fields', function( $user_id ) {
        if ( isset( $_POST['contact'] ) ) {
            update_user_meta( $user_id, 'contact', sanitize_text_field( $_POST['contact'] ) );
        }
        if ( isset( $_POST['territory'] ) ) {
            update_user_meta( $user_id, 'territory', sanitize_text_field( $_POST['territory'] ) );
        }
    });
    
  • Formidable: Adding Dynamic Link to Parent Values in a View with Child (Repeater) as the Source.

    There are instances that you need to add a dynamic link to a Formidable Form view when your data source is the child table, instead of the parent table. Here’s a javascript snippet that will do the magic.


    function load_jquery() {
    wp_enqueue_script("jquery");
    }
    add_action('wp_enqueue_scripts', 'load_jquery');

    function custom_href_shortcode_fix() { ?>

    To ensure the modification of links applies to all pages of a jQuery DataTable and not just the first, we must utilize DataTables' callback functions to reapply our changes after every table draw (which occurs on pagination, searching, or ordering). Because DataTables rebuilds the elements in the table when you paginate or change the data view, changes made to the DOM are lost after the initial page load. Here's how you can adapt your JavaScript to handle this situation:

    1. First, ensure DataTables is loaded and initialized on your table. I'm going to assume you've done that as part of your setup since you mentioned you're working with jQuery DataTables.

    2. Modify your `custom_href_shortcode_fix` function to use DataTables' `drawCallback` option to reapply custom link configurations after every draw.

    Here's an example update for your code:


    function custom_href_shortcode_fix() { ?>

    A few key points:

    - Ensure you have your DataTables initialized in the script where you're implementing the `drawCallback`. Replace `'#yourTableId'` with the actual ID of the table you are using.
    - The `drawCallback` option is used here to specify a function that is called whenever the table is drawn on the page, including when the page is changed, sorted, or filtered.
    - We've included the initial application of the link modification logic outside of the `drawCallback` as well to ensure it's applied when the page first loads, before any DataTable actions may trigger a redraw.

    Make sure you replace the specific selectors and IDs (`'#yourTableId'` and `'a.dynamic-href'`) with ones that match your HTML structure and requirements.

    What if you encounter the error Cannot reinitialise DataTable?

    The error message "Cannot reinitialise DataTable" typically indicates that DataTables has been initialized on an element more than once. This is a common issue when attempting to apply DataTables configurations dynamically or when the page's state changes without proper cleanup.

    Given the context of your setup, where you might not control the initial initialization of the DataTables (especially in WordPress environments where plugins or themes might automatically apply DataTables to certain elements), we need to approach this with a method that checks if a DataTable instance already exists on an element and only apply modifications without reinitializing.

    Let's adjust your code to handle this scenario. Since you're working with a class selector and you might not be able to directly control the DataTable initialization process, you can use the `$.fn.dataTable.isDataTable()` function to check if an element is already initialized as a DataTable. Here's how you could modify your script:


    function custom_href_shortcode_fix() { ?>

    Additional adjustments:

    1. I wrapped the DataTable initialization in a check using `$.fn.dataTable.isDataTable()` to prevent reinitializing an already initialized DataTable.

    2. I kept the original logic for applying the hyperlink modifications outside the initialization block, which means it will run on page load for all matching elements immediately.

    3. I added an event listener `draw.dt` to the table, which DataTables triggers after each draw. This is useful if your tables are being modified or interacted with dynamically after the initial page loads. This ensures that your `href` modifications are reapplied after actions like pagination, searching, or sorting.

    Please ensure you replace `.yourTableClass` and `'a.dynamic-href'` with the actual selectors used in your project.

  • WordPress 6.4 first impressions!

    WordPress 6.4 was released today and here are my first impressions. It’s cool and it’s fast and I love the modern Twenty Twenty four theme! Other features include the following.

    User Experience Improvements: WordPress tends to focus on refining the user experience with each update. My first impressions might include appreciation for a more streamlined interface, smoother navigation within the dashboard, and enhancements to the site-building experience provided by the block editor (Gutenberg).

    Block Editor Enhancements: With every release, the Gutenberg block editor usually receives new features or improvements. I might notice new blocks, block patterns, or improved handling of media elements within the editor that further simplify the content creation process.

    Performance Enhancements: WordPress developers continuously work to optimize the script loading and database queries for a faster experience. Thus, my first impressions could include faster page load times and more efficient backend performance.

    Full-Site Editing Features: Since the incorporation of full-site editing (FSE) functionality, users expect robust enhancements in this area. Any improvements to the site editor, template creation, and global styles would stand out as significant to me.

    Accessibility: Given WordPress’s commitment to making the web accessible to everyone, I might be impressed by newly introduced features or improvements that make the CMS more accessible for users with disabilities.

    Default Theme – Twenty Twenty-Four: Typically included with a new major WordPress release is a default theme that showcases the latest features. I would be eager to see the aesthetics and functionality of the Twenty Twenty-Four theme, expecting a design that is both modern and optimized for a wide range of use cases.

    Developer Tools and Hooks: As a developer, I might look for new APIs, hooks, or enhanced coding tools that allow for more extensive customizations and integrations, enabling developers to build more robust themes and plugins.

    Can’t wait to explore the rest of the new features in 6.4.

  • Top 3 useful AI tools for your daily needs

    1. Google assistant: Google assistant is a virtual assistant developed by Google that allows you to interact with your Android or iOS device using natural language voice commands and provides information and services based on the user’s request. It can be used for various tasks such as setting reminders, managing calendar events, making phone calls, playing music, and more.

    2. Siri: Siri is an AI-based virtual assistant developed by Apple Inc. It allows users to interact with their iOS devices using natural language voice commands. Siri can be used to set reminders, check the weather, and get directions.

    3. Alexa: Alexa is an AI-based virtual assistant developed by Amazon. It can be used to play music, control lights and other smart home devices, set alarms and reminders, and more. Alexa is also integrated with many third-party services, allowing users to have access to a wide range of services.

  • WooCommerce: Add a product to cart automatically based on another product’s variation ID

    If you want to add a product to your cart based on another product’s ID or variation or a configurable product, then this code snippet might help. Was searching how to do this until I found one in Stack Overflow. The function is based on the first code example on this website post:
    https://www.tychesoftwares.com/how-to-automatically-add-a-product-to-your-woocommerce-cart-in-3-different-scenarios/

    Basically, that code adds a specific product to cart based on the item’s category. So If added a product from category XYZ, then another item, a free one or not, will also be added to your woocommerce cart automatically.

    But what if you want to add a product based on the options selected on a configurable product / variable product. Then the code below will help do exactly what you need

    function bv_atc() {
    if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
    foreach( WC()->cart->get_cart() as $cart_item_key => $values ) {
    $a = array(10,20,30);
    $b = array(40,50,60);

    if( in_array( $values['variation_id'], $a ) ) {
    WC()->cart->add_to_cart(1);
    } else if ( in_array( $values['variation_id'], $b ) ) {
    WC()->cart->add_to_cart(2);
    } else {
    //if you want to do something else like adding a random item, do it here.
    }
    }
    }
    add_action( 'woocommerce_add_to_cart', 'bv_atc', 10, 2 );

    Just add the code snippet to your functions.php and replace the values in the array. In my array I have two sets of items. Each item will add a different product to cart.

    Just add more if conditions if you have other items that you want to be added to your cart based on the selected variations of a specific product.

    Credits to Shaikh at Stackoverflow:
    https://stackoverflow.com/questions/68077784/check-if-this-variation-id-exists-in-cart-then-add-another-item-to-cart

  • Divi Blog Grid breaks when Minify JavaScript Files is enabled

    If you’ve noticed that your Divi blog grid breaks after you enable JS minifaction using any plugin, then you just need to exclude the custom.js from /themes/Divi/js/custom.js to be minified. This will fix the issue.

    I haven’t checked what’s in this Javascript file yet that doesn’t want to be minified, but that fixes the problem anyway.

    I encountered this first when I enabled Minify JavaScript Files using SG Optimizer plugin. Not sure if it’s the same issue with other minification plugins, but I suppose it is.

    For other Divi issues or question you may have, please don’t hesitate to leave a comment below. I will gladly help you out.