Category: Blog

  • How to Build a Custom WordPress Plugin with Perplexity AI

    No coding experience needed!

    Building a custom WordPress calendar plugin requires careful setup and structured code implementation. Here’s a step-by-step guide using best practices from plugin development tutorials and calendar implementations:

    Plan Your Calendar Features

    List what you want your plugin to do.
    We’ll use in this in the Perplexity prompt.

    • Create events within wp-admin
    • Embed calendar using shortcode
    • Show events in month/list views
    • Display event title, featured image, date, time, and location in both month and list views
    • Embed calendar views using shortcode with ability to filter by category
    • Assign events to categories
    • Let users click to see event details

    Perplexity Prompt

    “I want to build a custom WordPress calendar plugin. I want to add events with a featured image, description, start and end time, and location. Ability to assign event categories. I want month/day/list views. Display event title, featured image, date, time, and location in both month and list views. Ability to embed the calendar using shortcode. Toggle between month and list views. Walk me step by step through the process, from start to finish. I am not a coder. Give me all the necessary code and scripts. Break up the instructions into sections.”

    1. Plugin Setup & Core Structure

    Create directory wp-content/plugins/my-events-calendar/ with these files:

    my-events-calendar/
    ├── my-events-calendar.php
    ├── assets/
    │   ├── css/calendar.css
    │   └── js/calendar.js
    └── includes/
        ├── class-events-cpt.php
        └── calendar-views.php

    my-events-calendar.php (Main Plugin File):

    <?php
    /*
    Plugin Name: My Events Calendar
    Description: Custom calendar with multiple views and event management
    Version: 1.0
    Author: Your Name
    Text Domain: my-calendar
    */
    
    defined('ABSPATH') || exit;
    
    // Load core files
    require_once plugin_dir_path(__FILE__) . 'includes/class-events-cpt.php';
    require_once plugin_dir_path(__FILE__) . 'includes/calendar-views.php';
    
    // Initialize plugin
    add_action('init', 'my_calendar_init');
    function my_calendar_init() {
        My_Events_CPT::register_event_post_type();
        My_Events_CPT::register_event_taxonomy();
    }

    2. Event Post Type & Taxonomy

    includes/class-events-cpt.php:

    <?php
    class My_Events_CPT {
        public static function register_event_post_type() {
            register_post_type('mc_event',
                [
                    'labels' => [
                        'name' => __('Events'),
                        'singular_name' => __('Event')
                    ],
                    'public' => true,
                    'has_archive' => true,
                    'supports' => ['title', 'editor', 'thumbnail'],
                    'show_in_rest' => true,
                    'menu_icon' => 'dashicons-calendar'
                ]
            );
        }
    
        public static function register_event_taxonomy() {
            register_taxonomy('event_category', 'mc_event',
                [
                    'labels' => [
                        'name' => __('Event Categories'),
                        'singular_name' => __('Event Category')
                    ],
                    'hierarchical' => true,
                    'show_admin_column' => true
                ]
            );
        }
    }

    3. Event Metadata & Admin Interface

    Add to class-events-cpt.php:

    class My_Events_CPT {
        // ... existing code ...
    
        public static function add_event_meta_boxes() {
            add_meta_box(
                'mc_event_details',
                __('Event Details'),
                [self::class, 'render_event_meta_box'],
                'mc_event'
            );
        }
    
        public static function render_event_meta_box($post) {
            wp_nonce_field('mc_save_event_data', 'mc_event_nonce');
            
            $start = get_post_meta($post->ID, '_event_start', true);
            $end = get_post_meta($post->ID, '_event_end', true);
            $location = get_post_meta($post->ID, '_event_location', true);
            
            echo '<div class="mc-meta-fields">';
            echo '<label>'.__('Start Date/Time').'</label>';
            echo '<input type="datetime-local" name="_event_start" value="'.esc_attr($start).'">';
            echo '<label>'.__('End Date/Time').'</label>';
            echo '<input type="datetime-local" name="_event_end" value="'.esc_attr($end).'">';
            echo '<label>'.__('Location').'</label>';
            echo '<input type="text" name="_event_location" value="'.esc_attr($location).'">';
            echo '</div>';
        }
    
        public static function save_event_meta($post_id) {
            if (!isset($_POST['mc_event_nonce'])) return;
            if (!wp_verify_nonce($_POST['mc_event_nonce'], 'mc_save_event_data')) return;
            
            update_post_meta($post_id, '_event_start', sanitize_text_field($_POST['_event_start']));
            update_post_meta($post_id, '_event_end', sanitize_text_field($_POST['_event_end']));
            update_post_meta($post_id, '_event_location', sanitize_text_field($_POST['_event_location']));
        }
    }
    
    // Hook into admin
    add_action('add_meta_boxes', ['My_Events_CPT', 'add_event_meta_boxes']);
    add_action('save_post_mc_event', ['My_Events_CPT', 'save_event_meta']);

    4. Calendar Views & Shortcode

    includes/calendar-views.php:

    <?php
    class My_Calendar_Views {
        public static function shortcode($atts = []) {
            $atts = shortcode_atts([
                'view' => 'month',
                'category' => ''
            ], $atts);
    
            ob_start();
            echo '<div class="mc-calendar-wrapper" data-view="'.esc_attr($atts['view']).'">';
            
            // View switcher
            echo '<div class="mc-view-switcher">';
            echo '<button class="mc-view-month">'.__('Month').'</button>';
            echo '<button class="mc-view-list">'.__('List').'</button>';
            echo '</div>';
            
            // Content
            if ($atts['view'] === 'month') {
                self::render_month_view();
            } else {
                self::render_list_view();
            }
            
            echo '</div>';
            return ob_get_clean();
        }
    
        private static function render_month_view() {
            global $wpdb;
            $events = get_posts([
                'post_type' => 'mc_event',
                'posts_per_page' => -1,
                'meta_key' => '_event_start',
                'orderby' => 'meta_value',
                'order' => 'ASC'
            ]);
            
            // Month view grid implementation
            echo '<div class="mc-month-view">';
            foreach ($events as $event) {
                $start = get_post_meta($event->ID, '_event_start', true);
                $date = date('Y-m-d', strtotime($start));
                
                echo '<div class="mc-event" data-date="'.esc_attr($date).'">';
                echo get_the_post_thumbnail($event->ID, 'thumbnail');
                echo '<h3>'.get_the_title($event->ID).'</h3>';
                echo '<div class="mc-meta">';
                echo '<time>'.date('M j g:i a', strtotime($start)).'</time>';
                echo '<span class="mc-location">'.get_post_meta($event->ID, '_event_location', true).'</span>';
                echo '</div></div>';
            }
            echo '</div>';
        }
    
        private static function render_list_view() {
            $events = get_posts([
                'post_type' => 'mc_event',
                'posts_per_page' => -1,
                'meta_key' => '_event_start',
                'orderby' => 'meta_value',
                'order' => 'ASC'
            ]);
            
            echo '<div class="mc-list-view">';
            foreach ($events as $event) {
                echo '<div class="mc-event">';
                echo get_the_post_thumbnail($event->ID, 'medium');
                echo '<div class="mc-event-content">';
                echo '<h3>'.get_the_title($event->ID).'</h3>';
                echo '<div class="mc-meta">';
                echo '<time>'.get_post_meta($event->ID, '_event_start', true).' - '.get_post_meta($event->ID, '_event_end', true).'</time>';
                echo '<span class="mc-location">'.get_post_meta($event->ID, '_event_location', true).'</span>';
                echo '</div></div></div>';
            }
            echo '</div>';
        }
    }
    
    // Register shortcode
    add_shortcode('my_calendar', ['My_Calendar_Views', 'shortcode']);

    5. Frontend Styling

    assets/css/calendar.css:

    .mc-calendar-wrapper {
        max-width: 1200px;
        margin: 2rem auto;
    }
    
    .mc-view-switcher {
        margin-bottom: 1rem;
    }
    
    .mc-view-switcher button {
        padding: 0.5rem 1rem;
        margin-right: 0.5rem;
        background: #f0f0f0;
        border: 1px solid #ddd;
    }
    
    .mc-month-view {
        display: grid;
        grid-template-columns: repeat(7, 1fr);
        gap: 5px;
    }
    
    .mc-event {
        border: 1px solid #eee;
        padding: 10px;
        margin-bottom: 10px;
    }
    
    .mc-event img {
        max-width: 100%;
        height: auto;
    }
    
    .mc-list-view .mc-event {
        display: flex;
        gap: 20px;
        margin-bottom: 30px;
    }
    
    .mc-list-view .mc-event-content {
        flex: 1;
    }

    6. View Switching Functionality

    assets/js/calendar.js:

    document.addEventListener('DOMContentLoaded', function() {
        const wrappers = document.querySelectorAll('.mc-calendar-wrapper');
        
        wrappers.forEach(wrapper => {
            const switcher = wrapper.querySelector('.mc-view-switcher');
            const monthView = wrapper.querySelector('.mc-month-view');
            const listView = wrapper.querySelector('.mc-list-view');
            
            switcher.querySelector('.mc-view-month').addEventListener('click', () => {
                monthView.style.display = 'grid';
                listView.style.display = 'none';
            });
            
            switcher.querySelector('.mc-view-list').addEventListener('click', () => {
                monthView.style.display = 'none';
                listView.style.display = 'block';
            });
        });
    });

    7. Installation Steps

    1. Install the Plugin
      • Zip the my-events-calendar folder
      • Go to Plugins → Add New → Upload Plugin in WordPress admin
      • Activate the plugin
    2. Create Events
      • Navigate to Events → Add New
      • Add title, description, featured image
      • Fill in event dates/times and location
      • Assign categories
    3. Display Calendar
      • Use either of these methods:
        <?php echo do_shortcode('[my_calendar view="month"]'); ?>
      • Or in content editor:
        [my_calendar view="list"]
    4. Customize Appearance
      • Modify assets/css/calendar.css to match your theme

    Need Help? Ask Perplexity!

    • “Why isn’t my calendar loading events?”
    • “How do I fix a broken dropdown menu?”

    Tip: Copy-paste error messages into Perplexity for quick fixes!

    🎉 You’ve built a custom calendar plugin! 🎉

    Citations:

    1. https://wordpress.org/plugins/the-events-calendar/
    2. https://theeventscalendar.com/products/wordpress-events-calendar/
    3. https://wordpress.com/go/tutorials/how-to-create-an-events-calendar-in-wordpress/
    4. https://www.make.com/en/integrations/perplexity-ai/wordpress
    5. https://vocal.media/01/how-to-write-code-with-perplexity-ai-step-by-step-guide
    6. https://piecalendar.com
    7. https://gowp.com/best-wordpress-calendar-plugins/
    8. https://outstandingthemes.com/which-wordpress-calendar-plugin-is-right-for-me-a-comprehensive-guide/
    9. https://www.wpbeginner.com/plugins/which-is-the-best-wordpress-calendar-plugin/
    10. https://devowl.io/wordpress/calendar-plugins/
    11. https://kinsta.com/blog/wordpress-calendar-plugin/
    12. https://www.seedprod.com/how-to-make-a-calendar-in-wordpress/
    13. https://elfsight.com/blog/embed-calendar-to-wordpress/
    14. https://www.monsterinsights.com/how-to-create-a-wordpress-event-calendar-step-by-step/
    15. https://formidableforms.com/add-an-events-calendar-in-wordpress/
    16. https://happyaddons.com/how-to-create-event-calendar-in-wordpress/
    17. https://buildship.com/integrations/apps/perplexity-and-wordpress
    18. https://www.youtube.com/watch?v=w_YRnA8RdnU
    19. https://www.youtube.com/watch?v=JJ0UeibCpkU
    20. https://www.techtarget.com/searchenterpriseai/tutorial/How-to-use-Perplexity-AI-Tutorial-pros-and-cons

  • How to Use ChatGPT for Auto-Translation in Bubble

    Bubble is a no-code platform that allows users to build web applications without extensive programming knowledge. Integrating AI tools like ChatGPT into Bubble can enhance functionality, such as enabling auto-translation features for multilingual apps.

    This tutorial provides a detailed guide on how to set up ChatGPT in Bubble to automatically translate text.

    Overview

    Auto-translation is a valuable feature for apps targeting global audiences. By leveraging OpenAI’s ChatGPT API, you can create a seamless translation system within your Bubble app. This tutorial will cover:

    1. Setting up OpenAI’s API.
    2. Configuring Bubble workflows.
    3. Sending and receiving translation requests.
    4. Testing the auto-translation functionality.

    Step-by-Step Guide

    Step 1: Set Up OpenAI’s API

    Before integrating ChatGPT into Bubble, you need access to OpenAI’s API.

    1. Create an OpenAI Account

    • Visit OpenAI’s website and sign up for an account.
    • Navigate to the API section and generate an API key. This key will be used to authenticate requests from your Bubble app.

    2. Understand OpenAI’s API Structure

    • The API accepts input text and returns responses based on the specified prompt.
    • For translation, you’ll use prompts like: “Translate this text into [language]: [text].”

    3. Save Your API Key

    • Keep your API key secure; you’ll need it later when configuring Bubble.

    Step 2: Set Up Your Bubble App

    If you don’t already have a Bubble app, create one:

    1. Create a New App

    • Log in to your Bubble account.
    • Click “New App” and choose a name and template.

    2. Design the User Interface

    • Add input fields for users to enter text they want translated.
    • Include dropdowns or buttons for selecting the target language.
    • Add a text display element to show the translated result.

    Example UI elements:

    • Input Field: For original text (e.g., InputOriginalText).
    • Dropdown: For language selection (e.g., DropdownLanguage).
    • Button: To trigger translation (e.g., ButtonTranslate).
    • Text Element: To display translated output (e.g., TextTranslatedResult).

    Step 3: Install the API Connector Plugin

    Bubble uses plugins to connect external APIs, such as OpenAI’s.

    1. Install the Plugin

    • Go to the Plugins tab in Bubble.
    • Search for “API Connector” and install it.

    2. Configure the API Connector

    • Open the plugin settings and click “Add another API.”
    • Name your API (e.g., “OpenAI Translation”).
    • Set the authentication type to “Bearer Token.”
    • Enter your OpenAI API key in the token field.

    3. Define the API Call

    Add a new call for translation:

    • Method: POST
    • URL: https://api.openai.com/v1/chat/completions
    • Headers:
    json { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" }
    • Body:
    json{ "model": "gpt-3.5-turbo", "messages": [ { "role": "system", "content": "You are a translator." }, { "role": "user", "content": "Translate this text into [language]: [text]" } ] }
    • Replace [language] and [text] with dynamic values from your app (e.g., user input).

    Step 4: Create Workflows for Translation

    Workflows are essential for connecting user actions (e.g., clicking a button) with backend processes like API calls.

    1. Set Up Workflow Trigger

    • Go to the Workflow tab.
    • Create a new workflow triggered by ButtonTranslate click.

    2. Add an Action for API Call

    • Select “Plugins” > “API Connector” > “OpenAI Translation.”
    • Map dynamic data:
      • [text]: Use InputOriginalText's value.
      • [language]: Use DropdownLanguage's value.

    3. Display Translated Text

    • Add another action: “Element Actions” > “Set State.”
    • Set TextTranslatedResult’s value to the response from the API call.

    Step 5: Test Your Translation Feature

    Before deploying your app, test the auto-translation functionality:

    1. Preview Your App

    • Click “Preview” in Bubble’s editor.
    • Enter sample text in InputOriginalText.
    • Select a target language from DropdownLanguage.
    • Click ButtonTranslate.

    2. Verify Results

    • Check if TextTranslatedResult displays accurate translations.
    • Test multiple languages and edge cases (e.g., empty input).

    Step 6: Handle Errors Gracefully

    API calls may fail due to network issues or invalid inputs. Add error handling to improve user experience:

    1. Detect Errors

    • In the workflow, add conditions to check if the API call returns an error.

    2. Display Error Messages

    json {
      "error": {
        "message": "Unable to process request."
      }
    }
    • Use conditional logic to show error messages in a text element if an error occurs.

    Step 7: Optimize Performance

    Auto-translation involves external API calls, which can impact performance:

    1. Limit Calls

    • Prevent unnecessary calls by validating inputs before triggering workflows.

    2. Cache Results

    • Store translations locally using Bubble’s database or custom states for repeated use.

    Example Workflow Recap

    Here’s how your workflow might look:

    StepAction
    TriggerUser clicks ButtonTranslate.
    Validate InputEnsure InputOriginalText is not empty and DropdownLanguage is selected.
    Call OpenAI Translation APISend user input and language choice as parameters via the API Connector plugin.
    Display ResultUpdate TextTranslatedResult with the response from OpenAI’s API call.

    Advanced Features

    Once basic auto-translation is working, consider adding advanced features:

    Multiple Translations

    Allow users to translate text into multiple languages simultaneously by looping through selected languages in workflows.

    Save Translations

    Store translations in Bubble’s database so users can access them later.

    Language Detection

    Use ChatGPT to detect the language of input text automatically before translating it.

    Example prompt:
    “Identify this language and translate it into English: [text].”


    Conclusion

    Integrating ChatGPT for auto-translation in Bubble opens up opportunities for creating multilingual applications without extensive coding expertise. By following this step-by-step tutorial, you can set up workflows that leverage OpenAI’s powerful language model for seamless translations directly within your app.

    With proper testing, optimization, and creative enhancements, you can provide users with an intuitive experience that bridges language barriers effectively!