Ray DelVecchio's Blog
April 8, 2025
How to Create a Workout Tracker Web App with AI
Imagine being able to create a fully functional web app without any prior coding experience.
With the help of AI tools, I’ve managed to develop a bunch of “mini” web applications using minimal hand-coded lines. AI offers smarter, faster, and more efficient solutions than traditional coding, especially as a solo developer who likes to tinker with new projects. It allows you to generate hundreds of lines of functional code.
You can then review the AI code output line by line to understand how it works and ask follow-up questions, significantly condensing your learning time.
This capability will undoubtedly empower non-developers to become tech entrepreneurs in the future.
In this article, I’ll walk you through the process of transforming a workout tracking spreadsheet into a functional web application using PHP, MySQL, jQuery, and JavaScript. We’ll cover the essential components of the app, the challenges encountered during development, and the solutions implemented along the way.
The Project BackgroundI started tracking my workouts back in November 2016, creating a comprehensive spreadsheet system with multiple components.
The setup included:
A master list of exercises with maximum rep counts by day and monthA detailed daily workout log (now containing over 4,444 workout entries)A monthly performance tracker with interactive exercise selectionStatistical summaries showing workout frequency by monthThis robust dataset made the perfect candidate for conversion to a database-driven web application, where I could maintain the functionality while gaining the benefits of web accessibility.
Leveraging AI for Rapid DevelopmentFor this project, I utilized Claude, a relatively new AI tool with advantages over alternatives like ChatGPT, particularly in coding capabilities and the ability to process screenshots.
In my initial prompt to Claude, I provided three screenshots of my spreadsheet architecture and requested skeleton code using specific technologies:
I have a spreadsheet to log my workouts. I’d like to turn this into a web app. I will provide three screenshots: one is a list of all the exercises with the max number of reps for the set day and month; one is a sheet where I log the daily workouts with the date, including a dropdown to select a specific exercise; and the last is a monthly performance chart where I can select the exercise and a live update to show my monthly reps for that specific exercise and update the chart. Can you create skeleton code to turn this into a web app using PHP, jQuery, JavaScript, and MySQL?
I specifically chose these languages due to my background in WordPress development, where most of my customizations have involved this technology stack. By specifying my preferred languages, I ensured that the AI generated code compatible with my experience and existing skill set.
Database StructureAt the heart of any data-driven application is a well-designed database. For our workout tracker, we need two primary tables:
CREATE TABLE exercises ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL, category VARCHAR(50) NOT NULL, max_set INT, max_day INT, max_month INT);CREATE TABLE workouts ( id INT AUTO_INCREMENT PRIMARY KEY, date DATE NOT NULL, exercise_id INT, total_reps INT, set1 INT, set2 INT, set3 INT, FOREIGN KEY (exercise_id) REFERENCES exercises(id));The exercises table stores information about each exercise, including its name, category, and maximum repetition records. The workouts table records individual workout sessions, linking to specific exercises and tracking the number of repetitions per set.
Adding User AuthenticationA key enhancement to our workout tracker is implementing a secure user authentication system. This allows multiple users to track their workouts independently.
Creating the Users TableFirst, we need to add a new table to our database schema:
CREATE TABLE users ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) UNIQUE NOT NULL, email VARCHAR(100) UNIQUE NOT NULL, password_hash VARCHAR(255) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, last_login TIMESTAMP);Modifying Existing TablesWe need to update our existing tables to associate data with specific users:
ALTER TABLE exercises ADD COLUMN user_id INT;ALTER TABLE workouts ADD COLUMN user_id INT;ALTER TABLE exercises ADD FOREIGN KEY (user_id) REFERENCES users(id);ALTER TABLE workouts ADD FOREIGN KEY (user_id) REFERENCES users(id);Authentication FunctionsAdd these functions to your functions.php file:
function registerUser($username, $email, $password) { global $conn; $password_hash = password_hash($password, PASSWORD_DEFAULT); $sql = "INSERT INTO users (username, email, password_hash) VALUES (?, ?, ?)"; $stmt = $conn->prepare($sql); $stmt->bind_param("sss", $username, $email, $password_hash); if ($stmt->execute()) { return $conn->insert_id; } else { return false; }}function loginUser($username, $password) { global $conn; $sql = "SELECT id, password_hash FROM users WHERE username = ?"; $stmt = $conn->prepare($sql); $stmt->bind_param("s", $username); $stmt->execute(); $result = $stmt->get_result(); if ($user = $result->fetch_assoc()) { if (password_verify($password, $user['password_hash'])) { $_SESSION['user_id'] = $user['id']; updateLastLogin($user['id']); return true; } } return false;}function updateLastLogin($user_id) { global $conn; $sql = "UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE id = ?"; $stmt = $conn->prepare($sql); $stmt->bind_param("i", $user_id); $stmt->execute();}function logoutUser() { session_unset(); session_destroy();}function isLoggedIn() { return isset($_SESSION['user_id']);}function getCurrentUserId() { return $_SESSION['user_id'] ?? null;}Registration and Login PagesCreate register.php:
Create login.php:
Create a simple logout.php:
Updating Existing Functions for User ContextModify your existing database functions to include the user_id parameter:
function getExercises() { global $conn; $user_id = getCurrentUserId(); $sql = "SELECT * FROM exercises WHERE user_id = ?"; $stmt = $conn->prepare($sql); $stmt->bind_param("i", $user_id); $stmt->execute(); return $stmt->get_result()->fetch_all(MYSQLI_ASSOC);}function logWorkout($date, $exercise_id, $total_reps, $set1, $set2, $set3) { global $conn; $user_id = getCurrentUserId(); $sql = "INSERT INTO workouts (date, exercise_id, total_reps, set1, set2, set3, user_id) VALUES (?, ?, ?, ?, ?, ?, ?)"; $stmt = $conn->prepare($sql); $stmt->bind_param("siiiiii", $date, $exercise_id, $total_reps, $set1, $set2, $set3, $user_id); return $stmt->execute();}Authentication MiddlewareUpdate your main pages to include authentication checks:
This ensures only authenticated users can access your application.
Core ArchitectureOur application now follows an enhanced web architecture:
Authentication Layer: Manages user registration, login, and session managementBackend (PHP): Handles data processing and database interactions within user contextFrontend (HTML/CSS/JavaScript): Provides the user interface and client-side functionalityDatabase (MySQL): Stores and retrieves workout data linked to specific usersBy adding user authentication, we’ve transformed our single-user app into a multi-user platform where each person’s workout data remains private and separate.
Key Features Implementation1. Navigation SystemThe app features a clean, tab-based navigation system that allows users to switch between different sections:
Exercises Log Workout Performance ChartThis is powered by jQuery to dynamically load content without full page refreshes:
$('#show-exercises').click(function(e) { e.preventDefault(); $.get('get_exercises.php', function(data) { $('#content').html(data); });});2. Exercise ManagementOne significant feature is the ability to view and add exercises. We implemented this with a table display and an add form:
// get_exercises.php Exercise Category Max (Set) Max (Day) Max (Month) + Add ExerciseWhen a user clicks the “Add Exercise” button, a form appears that, upon submission, sends data to add_exercise.php for processing.
3. Workout LoggingThe core functionality allows users to log their workouts. A key improvement we made was enabling multiple exercises to be logged for a single day:
$(document).on('click', '#add-exercise', function() { exerciseCount++; // Remove the "Remove Last Row" button from all existing exercise inputs $('.exercise-input .remove-exercise').remove(); const newExercise = $('.exercise-input').first().clone(); newExercise.find('input').val(''); newExercise.find('select').val(''); // Append the new exercise input $('#exercise-inputs').append(newExercise); // Add the "Remove Last Row" button only to the last exercise input $('#exercise-inputs .exercise-input:last') .append('Remove Last Row');});This dynamic form allows users to add as many exercises as needed for a single workout session.
Workout Streaks TrackingOne key motivational feature we’ve implemented is the ability to track workout streaks – both the current streak and the longest streak achieved:
function getWorkoutStreaks() { global $conn; $user_id = getCurrentUserId(); $sql = "SELECT DISTINCT date FROM workouts WHERE user_id = ? AND date < CURDATE() ORDER BY date DESC"; $stmt = $conn->prepare($sql); $stmt->bind_param("i", $user_id); $stmt->execute(); $result = $stmt->get_result(); $dates = $result->fetch_all(MYSQLI_ASSOC); $current_streak = 0; $longest_streak = 0; $streak = 0; $yesterday = date('Y-m-d', strtotime('-1 day')); $prev_date = null; foreach ($dates as $row) { $date = $row['date']; if ($prev_date === null) { $streak = 1; if ($date == $yesterday) { $current_streak = 1; } } else { $diff = (strtotime($prev_date) - strtotime($date)) / 86400; if ($diff == 1) { $streak++; } else { $longest_streak = max($longest_streak, $streak); $streak = 1; } if ($current_streak > 0 && $diff == 1) { $current_streak++; } } $prev_date = $date; } // Final check $longest_streak = max($longest_streak, $streak); return [ 'current_streak' => $current_streak, 'longest_streak' => $longest_streak ];}This function calculates two key metrics:
Current streak: Consecutive days with workouts up to yesterdayLongest streak: The longest sequence of consecutive workout days in historyThe function works by:
Fetching all workout dates for the user (ordered from newest to oldest)Iterating through these dates to identify consecutive daysTracking the current streak (must include yesterday)Finding the longest streak in the entire historyMonthly Progress CalculationWe also added a function to calculate monthly progress – what percentage of days in the current month have recorded workouts:
function getMonthlyProgress() { global $conn; $user_id = getCurrentUserId(); $current_month = date('Y-m'); $days_in_month = date('t'); $sql = "SELECT COUNT(DISTINCT date) as workout_days FROM workouts WHERE user_id = ? AND date LIKE ?"; $stmt = $conn->prepare($sql); $like_param = $current_month . '%'; $stmt->bind_param("is", $user_id, $like_param); $stmt->execute(); $result = $stmt->get_result(); $row = $result->fetch_assoc(); $workout_days = $row['workout_days']; $monthly_progress = ($workout_days / $days_in_month) * 100; return number_format($monthly_progress, 1);}This function:
Determines the current month and how many days it hasCounts how many days in the current month have recorded workoutsCalculates the percentage of days with workoutsReturns a formatted percentage string4. CSV Upload IntegrationFor users who prefer batch uploads or are migrating from spreadsheets, we added CSV upload functionality:
function getExerciseIdByName($name) { global $conn; $sql = "SELECT id FROM exercises WHERE name = ?"; $stmt = $conn->prepare($sql); $stmt->bind_param("s", $name); $stmt->execute(); $result = $stmt->get_result(); if ($row = $result->fetch_assoc()) { return $row['id']; } return null;}This function helps map exercise names from the CSV to their corresponding database IDs, enabling smooth data imports.
5. Performance Tracking and VisualizationTo help users track their progress, we implemented a performance chart using Chart.js:
function updateChart(exerciseId) { $.ajax({ url: 'get_performance_data.php', method: 'GET', data: { exercise_id: exerciseId }, dataType: 'json', success: function(data) { const labels = data.map(item => item.month); const reps = data.map(item => parseInt(item.total_reps)); chart.data.labels = labels; chart.data.datasets[0].data = reps; chart.update(); }, error: function(xhr, status, error) { console.error('Error fetching performance data:', error); } });}This function fetches performance data for a selected exercise and updates the chart, providing visual feedback on progress over time.
Recent Workouts ManagementTo help users track and manage their workout history, we’ve implemented a function to display and allow deletion of recent workouts:
function getRecentWorkouts($user_id, $days = 14) { global $conn; $sql = "SELECT w.id, w.date, e.name as exercise_name, w.total_reps, w.set1, w.set2, w.set3 FROM workouts w JOIN exercises e ON w.exercise_id = e.id WHERE w.user_id = ? AND w.date >= DATE_SUB(CURDATE(), INTERVAL ? DAY) ORDER BY w.date DESC, e.name ASC"; $stmt = $conn->prepare($sql); $stmt->bind_param("ii", $user_id, $days); $stmt->execute(); return $stmt->get_result()->fetch_all(MYSQLI_ASSOC);}For the corresponding HTML and JavaScript, we created a dynamic table with delete functionality:
Date Exercise Total Reps Set 1 Set 2 Set 3 Delete ❌The deletion functionality is handled via AJAX to provide a smooth user experience:
$(document).ready(function() { $('.delete-btn').on('click', function() { var row = $(this).closest('tr'); var workoutId = row.data('id'); if (confirm('Are you sure you want to delete this workout?')) { $.ajax({ url: 'recent_workouts.php', method: 'POST', data: { delete_id: workoutId }, dataType: 'json', success: function(response) { if (response.success) { row.remove(); } else { alert('Error deleting workout: ' + response.error); } }, error: function() { alert('An error occurred while trying to delete the workout.'); } }); } });});On the server side, we handle the delete request:
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_id'])) { $delete_id = $_POST['delete_id']; $delete_sql = "DELETE FROM workouts WHERE id = ? AND user_id = ?"; $delete_stmt = $conn->prepare($delete_sql); $delete_stmt->bind_param("ii", $delete_id, $user_id); if ($delete_stmt->execute()) { echo json_encode(['success' => true]); } else { echo json_encode(['success' => false, 'error' => $conn->error]); } exit();}Workout Days by Month ChartTo help visualize workout consistency over time, we added a function to calculate workout days per month:
function getWorkoutDays(){ global $conn; $user_id = getCurrentUserId(); $sql = "SELECT DATE_FORMAT(date, '%Y-%m') AS month, COUNT(DISTINCT date) AS workout_days FROM workouts WHERE user_id = ? GROUP BY month ORDER BY month"; $stmt = $conn->prepare($sql); $stmt->bind_param("i", $user_id); $stmt->execute(); $result = $stmt->get_result(); return $result->fetch_all(MYSQLI_ASSOC);}This data powers a Chart.js bar chart showing workout frequency by month:
var workoutDaysCtx = document.getElementById('workoutDaysChart').getContext('2d');var workoutDaysChart = new Chart(workoutDaysCtx, { type: 'bar', data: { labels: , datasets: [{ label: 'Workout Days per Month', data: , backgroundColor: 'rgba(75, 192, 192, 0.6)', borderColor: 'rgba(75, 192, 192, 1)', borderWidth: 1 }] }, options: { scales: { y: { beginAtZero: true, title: { display: true, text: 'Number of Workout Days' } }, x: { title: { display: true, text: 'Month' } } }, plugins: { title: { display: true, text: 'Workout Days per Month' } } }});This chart visualization provides users with a clear view of their workout consistency over time. The PHP code to prepare the data looks like this:
// Query to get workouts grouped by month$workout_days_data = getWorkoutDays();$months = [];$workout_days = [];foreach ($workout_days_data as $row) { $months[] = $row['month']; $workout_days[] = $row['workout_days'];}// Convert PHP arrays to JSON for use in JavaScript$months_json = json_encode($months);$workout_days_json = json_encode($workout_days);Dashboard MetricsTo provide users with an at-a-glance view of their progress, we designed a metrics dashboard that displays key performance indicators.
HTML/CSS StructureHere’s a clean, modern metric dashboard design:
Workout Metrics Dashboard body { font-family: 'Roboto', sans-serif; background-color: #f4f4f8; margin: 0; padding: 20px; color: #333; } .dashboard { display: flex; flex-wrap: wrap; gap: 20px; max-width: 1200px; margin: 0 auto; } .metric { background-color: #ffffff; border-radius: 10px; padding: 20px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); flex: 1 1 calc(33.333% - 20px); min-width: 200px; display: flex; flex-direction: column; align-items: center; transition: transform 0.3s ease; } .metric:hover { transform: translateY(-5px); } .metric-icon { font-size: 2.5em; margin-bottom: 10px; } .metric-value { font-size: 1.8em; font-weight: bold; margin-bottom: 5px; } .metric-label { font-size: 1em; color: #666; text-align: center; } @media (max-width: 768px) { .metric { flex: 1 1 calc(50% - 20px); } } @media (max-width: 480px) { .metric { flex: 1 1 100%; } } 🔥 Current Streak 🏆 Longest Streak 📈 % Monthly Progress 💪 Last Month's Top Exercise 📊 % Improvement Score Enhanced Progress VisualizationFor the monthly progress metric, we replaced the simple percentage text with an SVG pie chart:
Monthly ProgressFor dynamic PHP integration, you’d replace the static value with a calculation:
Where $progress is your percentage value (e.g., 13), and we multiply it by 0.628 (which is approximately 2π/100) to convert the percentage to the correct fraction of the circle’s circumference.
Handling ChallengesAt this stage, I reached the limit on prompts for this conversation, as Claude limits usage to five or six prompts at a time. I often had to wait a few hours before continuing. To work around this, I alternated between Claude and other free AI tools like ChatGPT or Google Gemini to maximize response quality and efficiently address minor issues.
The pro version of Claude includes a project feature that enables collaboration on a set of documents or code.
Debugging Workout Logging IssuesWhen testing the workout logging functionality, we encountered an issue where the operation would fail silently. We implemented better error reporting to diagnose the problem:
function logWorkout($date, $exercise_id, $total_reps, $set1, $set2, $set3) { global $conn; $sql = "INSERT INTO workouts (date, exercise_id, total_reps, set1, set2, set3) VALUES (?, ?, ?, ?, ?, ?)"; $stmt = $conn->prepare($sql); if ($stmt === false) { return "Prepare failed: " . $conn->error; } $stmt->bind_param("siiiiii", $date, $exercise_id, $total_reps, $set1, $set2, $set3); if ($stmt->execute() === false) { return "Execute failed: " . $stmt->error; } return true;}The issue was a mismatch in the parameter types specified in the bind_param method. By adding detailed error reporting, we could quickly identify and fix the problem.
Calculating Exercise MaximumsTo keep track of personal records, we created a function that calculates the maximum repetitions for each exercise:
function updateExerciseMaxes() { global $conn; // Get all exercises $exercises_query = "SELECT id FROM exercises"; $exercises_result = $conn->query($exercises_query); while ($exercise = $exercises_result->fetch_assoc()) { $exercise_id = $exercise['id']; // Max reps per set $max_set_query = "SELECT MAX(GREATEST(set1, set2, set3)) as max_set FROM workouts WHERE exercise_id = $exercise_id"; $max_set_result = $conn->query($max_set_query); $max_set = $max_set_result->fetch_assoc()['max_set']; // Additional queries for max_day and max_month // Update the exercise record $update_query = "UPDATE exercises SET max_set = $max_set, max_day = $max_day, max_month = $max_month WHERE id = $exercise_id"; $conn->query($update_query); } return true;}This function runs complex SQL queries to calculate the maximum values and update them in the database.
Troubleshooting Authentication IssuesDuring implementation of the user authentication system, we encountered some challenges with the user ID not being properly passed to other functions. Here’s how we resolved it:
Session ManagementThe most common issue was related to session management. Here’s a fixed version of getCurrentUserId() with improved error handling:
function getCurrentUserId() { if (!isset($_SESSION)) { error_log("Session not started when calling getCurrentUserId()"); return null; } if (!isset($_SESSION['user_id'])) { error_log("user_id not set in session when calling getCurrentUserId()"); return null; } return $_SESSION['user_id'];}To ensure sessions are properly started, we added session_start() at the beginning of all PHP files that use sessions:
Function DebuggingWe also implemented debugging code in key functions to track down issues:
function logWorkout($date, $exercise_id, $total_reps, $set1, $set2, $set3) { global $conn; $user_id = getCurrentUserId(); if ($user_id === null) { error_log("User ID is null in logWorkout function"); // You might want to throw an exception here or handle this case return false; } // ... rest of the function}This extra error checking helped identify where the authentication chain was breaking down.
Streak Calculation ChallengesThe streak calculation logic was particularly tricky to get right. We went through several iterations before landing on a reliable solution:
First Attempt: Used a recursive common table expression (CTE) in MySQL, which was elegant but proved too resource-intensive and caused timeouts.Second Attempt: Tried a complex MySQL query with window functions, which also had performance issues.Final Solution: Simplified the approach by fetching the raw data and performing calculations in PHP, which proved much more efficient and maintainable.The key insight was recognizing that some computations are better handled in application code rather than in database queries, especially when dealing with sequential data analysis like streaks.
Debugging the Streak LogicWe experienced issues where the current streak calculation wasn’t working correctly. The problem was in how we were comparing dates and checking for continuity:
// Problematic code$diff = abs((strtotime($date) - strtotime($prev_date)) / 86400);The solution was to ensure we were calculating the difference between consecutive dates correctly:
// Fixed code$diff = (strtotime($prev_date) - strtotime($date)) / 86400;This subtle change fixed the issue because we needed to account for the fact that the dates were being processed in descending order.
Another challenge was properly identifying the start of the current streak. We needed to specifically look for yesterday’s date:
$yesterday = date('Y-m-d', strtotime('-1 day'));if ($date == $yesterday) { $current_streak = 1;}These detailed adjustments to the logic ensured that the streak calculations worked correctly in all scenarios.
ConclusionTransforming a spreadsheet into a web application involves careful planning, thoughtful architecture, and attention to detail. By leveraging PHP, MySQL, jQuery, and JavaScript, we created a robust workout tracking system that offers more functionality and a better user experience than the original spreadsheet.
The final product allows users to track their exercises, log workouts with multiple exercises per day, upload data via CSV, and visualize their performance over time with interactive charts and engaging visual elements like pie charts. The modern, responsive design with intuitive navigation elements like the pill selector ensures a pleasant experience across devices.
By incorporating visual progress indicators such as the SVG pie chart, we’ve made the data more meaningful and engaging for users, helping them stay motivated and track their fitness journey more effectively.
This project demonstrates the power of web technologies in creating practical, everyday tools that enhance productivity and help users achieve their fitness goals. The combination of solid backend functionality with thoughtful frontend design creates an application that’s both powerful and a pleasure to use.
I’m also launching this workout tracker app since I’ve been tracking my workouts for nearly a decade, and I believe others may find this useful as well. If you’re interested in using this tool, go check it out here – Habit IQ.
The post How to Create a Workout Tracker Web App with AI appeared first on Website Profit Course.
March 8, 2025
I Built an AI Article Generator From Scratch (& Why It Beats ChatGPT)
In today’s fast-paced digital landscape, content creation remains one of the most time-consuming aspects of maintaining an online presence.
I can’t speak for anyone else but a 1,000 word blog post takes me something like 6-8 hours to create from scratch.
That involves:
Digging deep to learn a new topic.Sketch an outline before writing.Write content worth reading.Make Google love your content.Formatting before publishing.What if you could leverage AI to generate high-quality articles in minutes instead of hours?
That’s exactly what I set out to build when I was recently tasked with writing blog posts and new website pages for my local business clients.
I made a simple but powerful AI article generator that streamlines the content creation process above, so you start with a well-structured first draft that is much easier to add on top of vs. starting with a blank sheet.
✏️ Try the Free Article Generator Demo
Want to run this on your own server with no limitations? Purchase the full source code here.
The Development JourneyCreating this tool was a fascinating process that showcased how AI can dramatically accelerate software development. Let’s look at the key steps and challenges I faced while building this solution, along with the prompting techniques I used to engage effectively with the AI models.
Establishing the FoundationFirst, I needed a clear vision for the article generator. The goal was simplicity: users enter a brief topic description (3-5 words), click a button, and receive a complete article.
To kick off the process, I shared my detailed requirements with an AI assistant and provided an example form integrated with the LLM APIs. Here’s what I asked:
I want to create an article generator. Use this example form template for a workout planner (PHP file attached), and mimic the exact template code and styles to create the article generator. I will be using the exact same openai.php and anthropic.php wrappers to use AI functions to generate the article. It will be generated by a series of prompting steps shown below.This article generator form will be dead simple where I input an article idea in a text box, which will be the seed idea with a big “generate” button (same styles from planner.css).
The output will also be the same with a notification area, and the output.txt file which contains the article content.
I then outlined the multi-step prompting process I envisioned for the first version of the article generator (which I’ve since updated a few times):
Generate two separate outlines using different AI models.Combine these outlines into one coherent structure.Think up SEO keywords relevant to the topic.Produce a well-written, comprehensive article.The exact prompt sequence I asked for was this:
SEED IDEA - 3-5 word description input via form.PROMPT #1 - Outline an article for the topic SEED_IDEA. I want a very concise 3-5 bullet points outline, each with a short 1-sentence description of what's included in that bullet section.PROMPT #2 - Combine these two outlines for an article entitled "Affair Recovery Timeline", and make it ultra-concise without losing any of the core ideas: [Include OUTLINE_1 and OUTLINE_2]PROMPT #3 - Extract and generate keywords that people likely search that are related to the article outline: [Include OUTLINE_COMBINED]PROMPT #4 - Write an article on the topic of SEED_IDEA using the outline below. Make it as long as it needs to be to adequately cover all the topics in the outline. Consider using the SEO keywords below to enhance the article, but do not force them. [Include KEYWORD_LIST and OUTLINE_COMBINED]The AI assistant provided a complete implementation plan, including:
PHP code for the backend processing.HTML structure for the user interface.JavaScript code for handling form submission and displaying results.Detailed explanation of the workflow.The response included a complete solution with proper error handling, AJAX calls, and a user-friendly interface—all while maintaining the same styling as my existing workout planner application.
Here is the pseudo-code of the LLM response (which is ironically summarized by an AI chat to condense the full code!):
HIGH-LEVEL PSEUDOCODE: AI ARTICLE GENERATORFILES:- generate_article.php: Handles backend processing of article generation requests.- article.php: Provides the HTML structure and user interface for the article generator.- article.js: Manages the client-side logic and AJAX requests for article generation.- lib/openai.php: Abstracts interactions with the OpenAI API.- lib/anthropic.php: Abstracts interactions with the Anthropic API.- planner.css: Contains the styling rules for the article generator's user interface.- api.log: Stores a record of API calls and responses for debugging and monitoring.FILE: generate_article.php (Backend Processor)1. Receives a seed idea from the user via a POST request.2. Validates and sanitizes the input.3. Uses the OpenAI and Anthropic APIs to generate two article outlines.4. Combines the generated outlines into a single, refined outline.5. Generates SEO keywords related to the combined outline.6. Uses an AI model to write the full article based on the outline and keywords.7. Returns the generated article as a JSON response.8. Handles errors and logs API interactions.FILE: article.php (Frontend HTML)1. Presents a form for the user to input an article seed idea.2. Provides a "Generate Article" button to trigger the article generation process.3. Includes a loading indicator to show when the process is running.4. Displays the generated article and a download option in a designated area.FILE: article.js (Frontend JavaScript)1. Captures the form submission event.2. Sends an AJAX request to generate_article.php with the user's seed idea.3. Displays a loading indicator while waiting for the response.4. Handles the JSON response from the backend.5. Displays the generated article and a download button to the user.6. Handles and displays any errors that occur during the process.FILE: lib/openai.php (OpenAI API Wrapper)1. Encapsulates the logic for interacting with the OpenAI API.2. Takes a prompt as input and returns the API's response.FILE: lib/anthropic.php (Anthropic API Wrapper)1. Encapsulates the logic for interacting with the Anthropic API.2. Takes a prompt as input and returns the API's response.FILE: planner.css (CSS Styling)1. Defines the visual presentation and layout of the article generator's user interface.FILE: api.log (API Logging)1. Stores a record of API requests and responses for debugging and monitoring purposes.This foundation gave me everything needed to build out the powerful article generation tool that leverages multiple AI models in sequence to create high-quality content from a simple topic idea.
It’s not always smooth sailing and error free, though.
You will likely get some issues that you must debug… or let AI debug for you!
Just continue to test, ask questions, grab any errors you receive and feed them back into the chat to find solutions.
Building the User InterfaceI prioritized a clean, intuitive interface with a single input text box and a big “Generate” button:
Article Topic/Idea Generate Article Generating your article...Bootstrap and Font Awesome make form design effortless in this code snippet.
The form uses Bootstrap’s margin classes (i.e. mb-4) to create proper spacing between elements without writing custom CSS.
Font Awesome icons (fas fa-sync-alt and fas fa-spinner) add visual polish to the submit button and loading indicator.
These libraries work together to create a professional-looking article generator interface with minimal coding effort – perfect for developers who want clean, responsive designs without extensive CSS knowledge.
From there if we need to add custom CSS, we can.
The Power of Chain PromptingThe most fascinating aspect of this project was implementing “chain prompting” – a technique where multiple AI operations are strung together sequentially, with each step building upon the previous one. This approach dramatically improves output quality compared to generating an entire article in a single prompt.
Chain prompting proves effective by decomposing complex tasks into specialized sub-tasks that allow each step to concentrate exclusively on its specific area of expertise. This creates a powerful refinement pipeline where outputs from one prompt are fed as the input to the next prompt, effectively creating a progressive enhancement process at each stage.
The approach leverages the unique strengths of different AI models, combining their capabilities to deliver superior results than any single model or prompt could achieve alone.
Here’s how the chain prompting logic works in the article generator:
try { // Step 1: Generate outlines from both AIs $prompt1 = [ ['role' => 'system', 'content' => 'You are an expert article outliner.'], ['role' => 'user', 'content' => "PROMPT_1"] ]; $outline1 = anthropicAi($prompt1); // Use Claude Sonnet model $outline2 = openAi($prompt1); // Use ChatGPT model // Step 2: Combine outlines $prompt2 = [ ['role' => 'system', 'content' => 'You are an expert at synthesizing article outlines.'], ['role' => 'user', 'content' => "PROMPT_2"] ]; $outlineCombined = openAi($prompt2); // Use ChatGPT model // Step 3: Generate SEO keywords $prompt3 = [ ['role' => 'system', 'content' => 'You are an SEO expert.'], ['role' => 'user', 'content' => "PROMPT_3"] ]; $keywords = anthropicAi($prompt3); // Use Claude Sonnet model // Step 4: Write article $prompt4 = [ ['role' => 'system', 'content' => 'You are a professional article writer.'], ['role' => 'user', 'content' => "PROMPT_4"] ]; $article = anthropicAi($prompt4); // Use Claude Sonnet model // Return final article echo json_encode(['article' => $article]); exit;} catch (Exception $e) { http_response_code(500); echo json_encode(['error' => 'Error generating article: ' . $e->getMessage()]); exit;}Notice how each output from previous steps ($outlineCombined and $keywords) becomes input for this final prompt. The AI isn’t starting from scratch – it’s building upon layers of previous work.
System prompts are foundational to unlocking the full potential of large language models, acting as invisible instruction sets that guide the AI behavior throughout conversations. They establish the AI’s role, expertise, and operational parameters. In a small app like this article generator, extensive system prompts will create guardrails that ensure consistency and quality across every output stage—from outlining and keyword research to final composition.
While the simplified example code shows basic system prompts like “You are an expert article outliner,” to get the most out of your AI models, you want to employ elaborate prompts with detailed guidelines for tone, formatting, and expert knowledge. This behind-the-scenes engineering explains why the same question to different AI implementations produces vastly different results, as the system prompt essentially programs the AI’s personality and capabilities for specific professional tasks.
Combining well written system prompts with chain prompting produces dramatically better results than asking for an entire article in one step. It’s like the difference between having four specialists collaborate on a project versus asking one generalist to handle everything.
The error handling wraps the entire process, ensuring any failures in the chain are gracefully reported back to the user – an essential consideration when working with multiple API calls that could each potentially fail.
Troubleshooting IssuesWhen working with AI-generated code, you’ll typically receive functional code that works 90% of the time. However, being a first version, it often lacks logistical elements like proper logging and error checking that make future debugging easier.
For example, my code included a function logApi() which existed in my example code from a previously created workout planner form (generate_plan.php), but the AI didn’t place this function anywhere to be used. I had to ask a follow-up question about where to place this function call within the generated code, and I also requested that each AI response be saved in a text file so I could easily reference specific steps like the outline or brainstorming later.
tell me where to add logApi within generate_article.php. I want to log each prompt and response exactly like I did in generate_plan.php. Only tell me where to add the logApi function calls, do not give me full code.You’ll begin to notice patterns in how AI occasionally omits certain parts of code. For instance, I encountered a recurring issue with my wrapper files for OpenAI and Anthropic. I was using PHP echo statements to save details of each step to an API log file, but this caused errors when running the code from the browser because it was interpreting these log statements as part of the AI response. The solution was to implement the ob_get_clean() function, which effectively clears these extra log statements and returns only the pure AI response.
can you then implement the same error checking and validation before echo'ing the response back via JSON. I specifically need generate_article.php to implement the ob_get_clean() section of the code to clear the buffer since the wrapper files echo other things. include the JSON_THROW_ON_ERROR, too. Do not give me any of the function code, just provide this additional code that you omitted.Remember that AI is only creating a first pass on the user interface, so you’ll likely need to provide more detailed instructions to achieve your desired appearance. For instance, I had to follow up specifically to get the correct spinner icon which visually indicates that the backend processing is working.
I also encountered authentication issues where the system was retrying hundreds of times rather than gracefully quitting. When testing the original code, I discovered that I needed to build in more validation around these errors as they occurred. This prompted me to request error checking that would terminate the script if authentication failed on any of the API function calls.
I'm realizing that it's working but there is no refresh icon indicating that it's running. Include an icon in the button text to the left of the wording with a font awesome spinning refresh icon. I'm also receiving an authentication error. For instance here's what I see in api.log:Array( [error_type] => authentication_error [error_message] => x-api-key header is required)It looks like it retried hundreds of times, so please build in some type of error checking to just quit the script if authentication fails on any of the API function calls.This prompt led the AI to create a function handleApiError() which was supposed to quit the app if it encounters this authentication error.
// Add this function near the top with other function definitionsfunction handleApiError($response) { if (is_array($response) && isset($response['error_type'])) { if ($response['error_type'] === 'authentication_error') { http_response_code(401); echo json_encode([ 'error' => 'API Authentication failed. Please check API credentials.', 'details' => $response['error_message'] ?? 'Unknown authentication error' ]); exit; } } return $response;}However that didn’t work!
I had to go back and forth for about 10 minutes trying to spot where the issue was actually occurring, and it turned out to be within my wrapper file, anthropic.php.
Here were some of my prompts:
This is giving me authorization errors. I tried to fix this by exiting the script upon ONE single authentication error but it's still trying far too many times. This is what's appearing on the console log after the script runs for several minutes (it should quit immediately after the first anthropicAi() if the authentication doesn't work). I also don't understand why the authentication isn't working. I'm setting environment variables in my .htaccess file and using the getenv() in PHP. this works perfectly using the exact same openai.php and anthropic.php files on another project, hosted on the same server just with a different domain. The only difference is one project is on the root domain and the other is in a subfolder. Please fix these problems or give me ideas for what's going on if you are unsure of a solution. Only provide the changed code, no unchanged working code.why are you convinced it's the JS? I think it's PHP.this is the error in my api.log. use your smartness and figure it out:API Error (HTTP 401): authentication_error - x-api-key header is requiredFull response: Array( [type] => error [error] => Array ( [type] => authentication_error [message] => x-api-key header is required ))this makes sense, but what i still don't understand is why maxRetries is set to 3 yet I'm getting 500+ errors in my api.log. am i misunderstanding that use?when are errors passed along via httpcode 200 and when it that httpcode different. im so confused.Handling such issues is the typical life of a software developer, and it doesn’t come without frustration.
But now you have the ultimate assistant to help you.
Over time, you build your own infrastructure of code and functions to address the various scenarios you encounter. You also want to use these issues as an opportunity to elaborate on your system prompts to avoid it responding similarly with less than ideal answers in the future.
With AI assistance, you can now simply copy and paste error messages and your codebase into a chat, and it will solve the problem 80% of the time. For the remaining 20%, you’ll need to engage in follow-up conversations to diagnose and resolve the issue.
You don’t need to be a coding expert, but when you obtain working code examples based on ideas you clearly articulate, you’ll learn what’s going on within the code much faster.
Once you grasp the fundamentals, you can start asking more technical questions about function names, variables, and the general jargon that surrounds programming to receive even higher quality responses as you guide the AI toward exactly what you want to achieve.
The Age of AI-Accelerated DevelopmentWhat’s most remarkable about this project is how quickly it came together. Traditional development would have required:
Days of planning the article generation logic.Extensive testing of different prompt strategies.Complex error handling for multiple API endpoints.Custom UI design and implementation.By leveraging AI throughout the development process, I was able to compress this timeline dramatically.
The AI not only powers the article generator tool itself but also assisted in developing the code, troubleshooting issues, and refining the implementation.
Key TakeawaysAPI Integration Complexity: Working with multiple AI APIs requires careful error handling and retry logic.Prompt Engineering Matters: The quality of results depends heavily on how prompts are structured.Multi-Step Processes Work Better: Breaking complex tasks into sequential steps produces better results.Error Handling Is Critical: Especially when dealing with rate-limited external services.User Experience Simplicity: A focused, single-purpose tool is often more valuable than a complex multi-feature application.Try the Free Article GeneratorThe AI Article Generator showcases how modern development can leverage artificial intelligence not just as a feature but as the core functionality of an application.
Try the free version to generate your own articles, or purchase the source code to run it on your own server without limitations.
The post I Built an AI Article Generator From Scratch (& Why It Beats ChatGPT) appeared first on Website Profit Course.
February 16, 2025
Stop Coding HTML & CSS — Let AI Generate the PERFECT Website!
Learn how to revolutionize your web design process using AI-generated HTML and CSS code.
This step-by-step guide will show you how to create professional websites efficiently while saving countless hours of development time.
Start with the HTML Structure(PROMPT) Create a skeleton HTML file for a business website homepage that includes a header, a "hero" section, a three-blurb section, and a footer.Using AI tools like ChatGPT or Claude can dramatically speed up your development time.
Here’s how to make the most of these tools:
The foundation of any great website starts with clean, organized HTML, so we’ll use the prompt above to create a basic skeleton structure that includes:
Header sectionHero areaMain content sections (three blurbs)FooterThis structure provides the perfect canvas for our AI-generated CSS enhancements.

Before diving into CSS generation, let’s create the basic infrastructure for this mini project:
Text editor (I ❤️ Notepad++)Google Chrome InspectorCreate two files — index.html and styles.cssHere’s a look at the bare HTML file viewed in the browser without any styles applied.

After getting my HTML skeleton code from the AI, at the end of its response it said, “Let me know if you’d like CSS or Javascript enhancements.”
This is why the prompt above is so simple.
I replied with a straightforward “Yes for CSS,” and the AI immediately generated a complete CSS stylesheet that perfectly matched my HTML structure.
The generated CSS included everything from global styles, to individualized section styles, along with responsive design rules.

It automatically styled the header and footer and created a gradient hero section, but unfortunately, incorrectly formatted the three-column content area as stacked blurbs.
So we have to follow up… don’t expect perfection on the first try!
Pro Tip — Use a desktop tool like Chatbox to use multiple AI models in one unified interface and create custom roles, for example, my “CSS Formatter” role, which takes existing CSS and makes it match precisely how I want the code to look (see image below).

When working with AI-generated CSS, these are my best practices:
I style one block of code at a time and ask for 3-5 optionsCopy & paste each variation using Chrome’s inspector tool to testEnsure proper responsive behaviorCheck for color consistency across sectionsAsk to merge options that you like, describing what to keep from each
You can ask for a snippet of code to style an HTML section or a few fixes with the complete CSS file to ensure you have all the necessary styles and avoid conflicts.
However, this is one area where AI gets confused — ignoring related parts of your code when focusing on a minor problem or inferring things you want to change when you don’t.
If you’re looking to maintain overall consistency, provide full files or even the entire codebase as context before asking to complete a task.
If you have a hyper-specific fix, only provide the minimal necessary code to complete it.
Just be prepared for small issues and use them to write better prompts that avoid the problem in the first place!
Troubleshooting Common AI Chat Issues(PROMPT) All my blurbs are showing in the first column instead of a proper three-column layout that's optimized for mobile. The gray background of the section should be full width to the browser. Rewrite and provide the new full style.css file.# index.htmlPASTE_HTML_CODE_HERE# style.cssPASTE_CSS_CODE_HEREWe had the issue of the three-blurb section being shown stacked in a single column. I tried a few follow-ups with ChatGPT’s free tier, and it didn’t solve the issue. So I decided to switch over to Claude, my preferred AI model for code tasks.
This solved the problem on the first try (which is why I use it more than ChatGPT for most technical tasks)!

When you encounter problems with AI-generated code, here are a few things I like to try:
Start fresh with a new chat session and up-to-date code contextTry different AI models (Claude often excels with code)Be specific about layout requirementsUpload screenshots to show what you’re describing visuallySketch out the basic layout on paper and ask to generate codeAsk AI how you can improve your prompt to get your desired resultThe quality of your results is 100% dependent on the quality of your prompt. If you’re not getting what you want, there is an extremely high likelihood you can adjust your prompt and get it working.
AI truly gets you in the mode of a manager handling outsourced employees, and the prompt strategies are like delegating tasks with detailed guidelines.
Time-Saving Tip — Create a library of assets through each AI project you take on. That could mean website templates with standardized, modular HTML & CSS. Or it could be carefully crafted prompts you re-use repeatedly for your most frequent daily tasks.
If you’re interested in learning more about AI and its practical applications, I’ve created a comprehensive collection of AI learning guides that cover everything from basic concepts to cost-saving strategies.
These guides will help you better understand the technology we’re using here while building a stronger foundation in AI overall.
How Does AI Affect Web Design?We are still very early on the AI innovation curve, and it’s sometimes hard to remember that this is as bad as it’ll ever be.
If you honestly look forward into the future, you can see how creating a website, or even a web app with AI will be as straightforward as describing what you want. The best analogy I heard for this is how high-level coding languages abstracted away the need to understand the hardcore technical assembly language syntax.
The same thing is happening now at the level of human language with LLMs (Large Language Models, like ChatGPT).
Knowledge of HTML, CSS, Javascript, and any other coding language will not be necessary to build amazing websites and apps.
The key is understanding how to effectively communicate with AI models and refining their output to match your specific needs.
The only way to figure that out is to experiment with different AI tools and approaches to find what works best for your workflow!
The post Stop Coding HTML & CSS — Let AI Generate the PERFECT Website! appeared first on Website Profit Course.
December 28, 2024
How to Create a Custom WordPress Shortcode
Today’s tutorial is going to be one of my favorites because we’re diving into a blend of PHP, HTML, and CSS in a short amount of time. We’ll create a custom WordPress shortcode that displays a block of text, styled to look like an iPhone text message. Here’s a sneak peek of what it will look like when we’re done!
This approach is my favorite way to learn. I never attended a boot camp or took classes for any of these programming languages or WordPress development. My curiosity drove me to figure it out over time through small projects. I believe working on projects fueled by your own ideas is far more rewarding than simply taking a boot camp to add a skill to your resume.
Getting Started with ShortcodesWe’ll accomplish this through the functions.php file within your theme directory. If you’re a developer, you’re likely familiar with this, but if you’re a beginner, you might wonder, “What is that?” Regardless of your experience level, let’s get started on this project.
I’m currently on a WordPress post page, and this is where we’ll begin. The first step in creating a shortcode is to start with plain HTML. Once the HTML and CSS are harmonized, I can convert them into PHP code and include a few options.
Creating the HTML StructureI want to add a custom HTML block here to paste in the HTML code. It’s simple: a with a class of "imsg" for iMessage. There will also be a second class, "first", to designate the sender of the first message, and a third class called "reply" to determine whether the message appears in blue or gray.
Once I save this, I’ll add custom CSS in the appearance section. I usually do this from the child theme’s style.css file, but there are typically two or three places where you can add custom CSS. For today, I’ll paste this in the additional CSS section. While I won’t dive into it in detail now, I’ll step through some of these CSS styles at the end of our project.
Building the ShortcodeNow, let’s move on to building the shortcode. When I work on custom code like this, I often search for others who have used similar functions or tackled the same goal. I found this helpful website to generate your shortcode template. You fill in your details, and it builds your PHP code to add to the functions.php file.
I’ll start on the shortcode tab. The first step is to fill out the shortcode name we’ll use; I’ll call it "imsg". For the function name, I’ll append "_shortcode" to it, replacing "custom" with "imsg". This site provides examples of both self-closing and enclosing shortcodes, but we want the enclosing type since the content will be the text message.
Next, I’ll select “enclosing” and build in one attribute: whether it’s a reply. If it’s a reply, it’ll be gray; if not, it’ll be blue. Moving on, I’ll define our attributes, naming this one "reply" (all lowercase) and setting its default value to false. Essentially, if the shortcode has the option reply=true, it will use the reply style.
Let’s update this code and grab our skeleton code to work with, pasting it into the functions.php file. You can access the functions.php file from the appearance editor; it’s usually right under the style.css. Scroll down to the bottom, and we’ll add our custom code there.
If you want to read more about how this works, WordPress has a page in their Codex section. If you Google “WordPress shortcode API,” you’ll find it. This resource describes some of the options we’ll cover. I won’t go into a full-length explanation, but it’s a great starting point if you need something specific and aren’t sure where to look.
Understanding the CodeTo summarize quickly: we’re providing a function to add a shortcode. This is our custom function, and we use the WordPress function add_shortcode to attach it to the WordPress system, allowing us to use it within posts and pages. There are two arguments: the first is the attributes (the options we define within the shortcode), and the second is the content (what the shortcode wraps around, essentially our text message).
Next, we define our default values. If the reply value isn’t set within the shortcode, it defaults to false. If we want to manually change that to true, we have to do it within the shortcode. I may not be the best at explaining this, so if any experienced developers come across this, feel free to leave a comment with your insights.
Now, we need to add a bit of logic. We have to check the reply option and determine what to do based on that. Checking the reply option will only take a single line of code. I like to comment on each section, so I’ll start with two forward slashes to begin a comment line and write something descriptive as a reminder for later.
I’ll create a variable called $msg_type, which will hold the string of the class we’ll add to the . I’ll use a one-line if-else statement for this. The framework is to put a conditional statement in parentheses, followed by a question mark. If the conditional statement passes (is true), we assign the first value; if it’s false, we assign the second value.
Let’s start with the conditional statement. I’ll use a function that removes links from a string of text: esc_attr. We’ll put our attributes array inside this function. To get the value for the reply option, we’ll use square brackets and single quotes: ['reply']. This gives us the value, either false (the default) or whatever we define it as within the shortcode.
I want to check if this is true. We’ll use two equal signs and look for the string "true" surrounded by quotes. While I could discuss comparisons and logic in PHP in detail, I’ll keep this brief to maintain our pace.
So, if this is true, we add the class "reply". If it’s not, we add the class "first". This line should be complete, and now we need to return our value. If you’re familiar with coding, you know the return function will return a string of code, and we’ll place our variables within that.
I’ll copy the pure HTML code we had earlier and replace the class with our variable. To break this string, I need to add two single quotes. In PHP, opening strings start with a single quote, and within our HTML, we’ll use double quotes for anything inside that. This can be confusing and lead to errors in PHP code, so I’ll add the two quotes to break this up. To concatenate strings in PHP, we use the period operator.
I’ll concatenate the first part of the string with our variable $msg_type, and then concatenate the second part of the string. We also need to replace the hard-coded message with our content in the same way, using two single quotes to break it up.
Let’s save this and head to the post where we currently have the plain HTML code. I’ll replace that with the shortcode. I’ll copy and paste it, removing the block and adding a shortcode block instead. I’ll substitute the HTML with the shortcode and do the same for the closing tag. Since we haven’t set any options yet, the message should appear in blue.
Let’s update this post and see how it looks. If all goes well, we’ll end up with our iPhone-style messages. If something seems off, let’s troubleshoot. Nothing ever goes perfectly! At first glance, I see there’s no space between the classes. I forgot to add that space, so let’s correct that.
Now I’ll add another reply to see both styles in action. I’ll copy this, insert another shortcode element, and paste it in. I’ll place a longer message after filling out the option. I just need to add reply=true with double quotes around that string. Let’s save the page and check it out.
And there you have it! As promised, let me quickly dive into the CSS and explain the different styles I applied without getting too deep into the syntax. There are three main parts to this:
Styling the Containers — We apply CSS properties to either element. We set the position: relative to enable absolute positioning for sub-elements. We adjust the font size, set the font family to a sans-serif font, and tweak the line height, border radius, and padding.Creating the Arrows — The arrows, positioned using CSS, are generated with the ::before and ::after pseudo-elements. These are absolutely positioned with a height and width of 0, and their color is created through borders.Setting Backgrounds and Colors — The code for the first message sets the background to blue and the font color to white. We apply a custom margin to offset it to the right, and the blue arrow is created using borders, while similar styles are used for the reply element with different values.I’ll include a link below to download all the code. You can copy and paste it into your project!
I hope you found this tutorial valuable! It was a game-changer when I first learned about custom shortcodes, especially since I was really into coding.
If you have skills in building websites and working with WordPress and want to start freelancing to monetize those skills, check out the rest of my blog.
Overall, I’ve found the most success working with local clients. Many small businesses struggle with a weak web presence and need your help. They don’t hire web developers easily; it takes time to build trust. That’s why I recommend focusing on the local aspect—you can converse with them over the phone or even meet in person.
The post How to Create a Custom WordPress Shortcode appeared first on Website Profit Course.
December 27, 2024
How to Transfer Data from Old PC to New Computer Without the Hassle
I invested in a new PC after nearly eight years with my previous computer system.
To ensure a seamless transition between the old PC and the new PC, I developed a comprehensive checklist of steps and procedures.
Now that I’ve completed this migration, I want to share these detailed insights to help you confidently navigate your next computer upgrade!
Use Cloud StorageThe cornerstone of my migration strategy revolves around cloud storage implementation.
Store your important files in cloud services like Google Drive and Dropbox to let them do the backups for you.
This strategy ensures your files are accessible anywhere and simplifies the transfer process. That’s precisely what I do between the two services above.
My documents, spreadsheets, and slides are made with Google Drive.
I made this transition from Microsoft’s ecosystem to Google Drive many years ago, which has proven invaluable during migrations since there is no migration — you just log in to your Google account! 😄
All other files (i.e., PDF, JPG, PNG, HTML, CSS, MP4, etc.) go into a well-defined folder hierarchy within Dropbox.
Dropbox automatically synchronizes files across all my installed devices and remains accessible through any web browser or on the Dropbox app on my phone.
When you set up a new PC, your entire Dropbox will be downloaded to this new device, which can take some time to sync up on that first install.
After that, it’s smooth sailing.
File Organization & InventoryA crucial step involves examining files outside your cloud storage structure.
Carefully review common folders like:
✅ C:/Users/You (or Mac equivalent)
✅ Desktop
✅ Downloads
✅ Photos
✅ Videos
If you’re utilizing OneDrive or alternative services, apply the same scrutiny.
I recommend right-clicking important folders like the ones above to document their sizes and see which occupy the most of your hard drive storage space.
When I went through my previous PC upgrade, I set up Dropbox for the first time and moved all the files that I wanted to keep out of the aforementioned folders and into an organized Dropbox folder structure. I think Dropbox now allows you to select folders outside of your main “C:\Dropbox” folder to sync if you prefer that method.
Software Installation PlanConduct a thorough inventory of your applications, specifically the Applications or Program Files folder, along with “Installed apps” page in your Windows Settings.
I like doing fresh installations to remove any overhead accumulated through the years.
Some applications store custom settings that won’t automatically transfer with a fresh installation, necessitating manual export or documentation of your personalization.
Focus primarily on your top 2-3 most frequently used programs during this phase since you might not catch everything. You’ll likely have to patch up a few settings here and there that you completely forget about until you encounter that scenario on your new PC!
💰 Review Paid ApplicationsAnother weird situation that I found was downloading installers isn’t always straightforward if you’re using paid software.
For instance, my legacy version of QuickBooks required preserving both the executable file and license key since they were nowhere to be found online — so I now store these files in my Dropbox if I go through this process again instead of requiring a new purchase.
I’ve avoided the monthly Quickbooks Online charge for many years since the already paid-for legacy version works just fine for my needs as a solo web design freelancer!
🖥️ Take Screenshots of Old DesktopI like to take screenshots of your desktop arrangement. It’s incredibly useful for recreating your application icon layout and taskbar configurations.
Screenshots are automatically saved to a folder in your Dropbox!
🎵 File AssociationsDon’t forget to document your file associations with preferred default programs to maintain your preferred programs for opening specific file types.
For example, I like bypassing the pre-installed Windows programs and using VLC Player for nearly every media file type like MP3, MP4, and about 20 others.
Some programs let you choose these upon installation, but it can’t hurt to figure out your most used file types and take note of what programs open them by default to make these associations on your new PC easily.
Document Your Transfer DetailsThroughout this process, I maintained detailed documentation in a spreadsheet.
It not only is useful today, but I can come back to it in the future to repeat this process and make it more seamless.
Before acquiring the new computer, I recorded my previous system specifications (CPU, RAM, Disk Space, etc.) with a comprehensive program inventory.
I then used highlighting to identify priority installations and noted others that were less critical where I might ignore them until a future need actually arises. I did this to promote a clean and efficient initial installation of the new PC.
As an example, my total Dropbox usage is ~550 GB, utilizing roughly a quarter of my 2 TB Professional plan allocation. My installed programs occupied approximately 65 GB.
👨💻 Web Development ConsiderationsAs a web designer, I have specific technical requirements that I like to set up that the average computer user might not. However, I bet you have your quirks, too!
For instance, I sometimes use the system HOSTS file, which manages domain name to IP address mapping and requires special attention during migration if you want to copy the contents.
Additionally, software like Adobe Creative Cloud only permits installation on two computers. I was already using a PC and a Macbook, so I needed to deactivate my old PC under my Adobe account device settings before proceeding with the new installation.
New PC SetupAfter completing the Windows installation, I prioritize installing Google Chrome and signing into my Google profile, immediately restoring access to my Google Drive files.
Following this, I install Dropbox to initiate file synchronization. With 500+ GB of data, this process typically requires 3-4 hours, so I walk away and let it go until it’s done downloading.
🖱️ Install Your ApplicationsOnce these foundational elements are in place, I return to my spreadsheet list to install remaining applications.
I customize the desktop and taskbar layout according to my documented preferences and screenshots of the old PC.
After completing application installations, I configure the file associations and connect peripheral devices like printers.
⚙️ Custom ConfigurationHere’s a few things I did which might give you ideas…
For Chrome, most everything syncs upon logging into your Google account, but one setting that might not is choosing the Desktop as the default download location instead of the Downloads folder — this is a personal preference.
I adjust the Windows taskbar to display on only one monitor in my triple-monitor setup, instead of duplicating itself across all three monitors. For FileZilla, my preferred FTP client, which is installed on both Windows and Mac systems, I create necessary symlinks to synchronize settings across both platforms.
I also maintain a curated collection of background images in my Dropbox for Windows desktop personalization. So I’ll set that up to automatically rotate photos within this folder to re-create my old PC vibe. Or I’ll seek out new photos to freshen things up.
The final phase for advanced users may involve registry modifications, such as custom icon spacing, changing the default drag-and-drop behavior to Move instead of Copy, or adjusting the right-click context menu to include or exclude commands.
Future-ProofingDocumenting your process like this will serve as a template for future upgrades, with slight modifications based on changing software requirements and personal preferences.
For those considering a new PC purchase… 👉 Explore & buy a new computer on Amazon!
My previous system was a powerful refurbished Dell that I got on Amazon for a great price. It served me well for eight years until performance degradation became noticeable with resource-intensive applications, specifically Adobe Photoshop and Premiere Pro.
I hope to get another solid 4-5 years out of my current system, and everything beyond that is gravy. I’m not the type to chase every yearly upgrade (though that might change in the new world of A.I.).
If things work and I’m not frustrated, I’ll run this thing into the ground. 😆
Let me know if this process works for you or what you’d add, update or change!
The post How to Transfer Data from Old PC to New Computer Without the Hassle appeared first on Website Profit Course.
May 1, 2024
How to Set the Homepage in WordPress
Today, we’ll go through the ultimate guide to setting your WordPress homepage.
This simple task might seem straightforward. In fact, I just walked through a tutorial with the Twenty Twenty-Four theme by WordPress, where they’ve made it simple to craft a homepage layout design visually.

However, that’s not the case with the thousands of other themes that people have installed on their existing WordPress websites — especially classic ones without visual block editing.
It can be quite perplexing to figure out where to set the homepage design and how to do it because this process is entirely dependent on the theme you have installed… plus there are multiple ways to do it.
You need a basic understanding of the WordPress template hierarchy.
So, if this is something that has confused you in the past, let’s address the technical elements of assigning your homepage in WordPress!
Homepage Precedence Flow Chart
I tried to cover every possible scenario and created a flowchart to illustrate the complexity of the template hierarchy.
You can grab a copy of this flow chart below.
👉 WordPress Homepage Flow ChartWant this helpful free giveaway or training?
Let’s explore these cases so you can gain a comprehensive understanding of how WordPress actually serves the homepage.
The initial question to consider is — Does the active theme support full-site editing?
If the answer is yes, it’s as straightforward as creating a front page template, which may or may not be included in your block theme. This full-site editing feature was introduced with the core WordPress software in 2022.
Let’s head back to our WordPress dashboard.
Old vs. New WordPress Block ThemeNavigate to the appearance section, where you’ll find several themes I’ve installed.
The easiest way to determine if full-site editing is enabled is to look at your admin menu on the left. If all you see under the “Appearance” menu is “Themes” and “Editor,” it means your active theme has visual editing capabilities built-in.

All the options that used to reside under this “Appearance” menu are now accessible through the newer visual editor.
Now, let’s say we activate an older theme like GeneratePress, which doesn’t have full-site editing built-in by default. You’ll notice the additional options “Customize,” “Widgets,” and “Menus.”
Older themes may also include their own theme options page.
In the past, theme customization primarily occurred through a page like this where you’d select settings, rather than using a drag-and-drop style visual editor.
“Front Page” TemplateLet’s reactivate the Twenty Twenty-Four theme and head to our editor. From there, we’ll navigate to the “Templates” section. Here, you’ll find a list of our templates. If we want to view them all, we can click on “Manage All Templates” to see them displayed in a larger panel.

Right now, we don’t have a “Front Page” template. Instead, our homepage is being managed by the “Blog Home” template. You’ll soon see the distinction between them.
If you wish to create a completely new homepage, you can click “Add New Template” and select the “Front Page” template.

This is the easiest solution since it takes precedence over everything else!
Setting a Custom HomepageWhen we don’t have a front page template, the next question is — Is the custom homepage set?
This is a WordPress setting that I utilize quite often, especially when building small business websites.
By default, WordPress displays blog posts on the homepage, which isn’t always desirable. To adjust this setting, navigate to the “Settings > Reading” section. Here, you can assign an existing WordPress page to display as your homepage.

Then you’ll designate what page will be used to show your blog posts.
After saving these changes, take a look at your homepage to see what’s changed.
WordPress Template Hierarchy
Everything we’re discussing today ties back to the WordPress theme template hierarchy.
Previously, this was managed through PHP files, which we’ll see shortly after we activate an older theme. Nowadays, it’s handled through the visual editor with block themes, like Twenty Twenty-Four.
Here’s the WordPress developer page where the graphic above is embedded. Before block themes became prevalent, you’d have to edit or add raw PHP files within your child theme to customize. Each of them is responsible for generating specific pages on the front end.
Essentially, we follow this hierarchy from left (page type) to right (the PHP file that can generate that page).
What we just demonstrated was the “Site Front Page” type in the hierarchy. If we utilize the “Front Page” template in a block theme or edit the front-page.php file, that will take precedence.
If there is no front page template and we manually select a page to display on our homepage from the WordPress settings, it’s governed by the “Page” template.
This is exactly what you saw in the previous two sections!
Navigating further down the hierarchy, we encounter fallbacks such as home.php, which we’ll explore in a moment, and everything defaults to index.php.
Confused, yet? 😆
“Blog Home” TemplateNow, returning to the visual editor, you’ll notice that our original homepage layout was run by the “Blog Home” template. The description indicates that this template showcases the latest posts, serving as either the site homepage or the posts page (if you selected a different page under the reading settings).
In our case, we have a completely custom layout here without blog posts. Instead, it’s a custom-built full-width layout that comes pre-packaged with the Twenty Twenty-Four theme.
Looking at our flowchart, the basic hierarchy order goes like this…
Front Page template (front-page.php) > Page template (page.php) > Blog Home template (home.php)
If you don’t have a Front Page template, your homepage will use whatever page is set from the WordPress reading settings.
If you don’t have a Front Page template and the homepage isn’t set from the reading settings, it’ll use your Blog Home template.
Templates with Dynamic ContentAnother complicating factor to consider is the presence of dynamic content.
Even if your template is structured like the Front Page template, there’s a possibility that includes the “Post Content” block.

This situation can create a hybrid scenario where you visually edit the Front Page template to alter the design, but some of the content is coming from the page within WordPress you set as the homepage from the reading settings.
Child Theme Without Full Site EditorLet’s now explore a theme that doesn’t have full-site editing enabled.
Returning to the appearance theme section, let’s activate Twenty Twenty-One, the last theme developed by WordPress without visual editing built-in.
Upon activation, you’ll notice our Appearance menu options indicating that full-site editing is not enabled on this site.
Referring back to our flowchart, the first question to consider now is whether or not a child theme is installed.
This is crucial because you will be editing PHP files directly, which was the norm for template customization before visual editing.
If you don’t have a child theme installed, your customizations will be overwritten whenever a theme update is released.
This is why a child theme is so important. Essentially, a child theme utilizes all the template files from the parent theme, unless you specifically copy any into your child theme and edit them. In that case, your child theme’s customizations will be used instead of those in the parent theme.
Installing a child theme is quite simple to do, especially with older themes. You can find instructions on how to set up a child theme either manually or through a plugin.
A child theme only requires two files — functions.php and style.css.
Customizing Child Theme PHP Templates
Let’s proceed with what we accomplished above, except we’re using an older theme that requires PHP modifications.
If front-page.php doesn’t exist, we can create it ourselves. To do this, let’s open up FileZilla, my preferred FTP program, to access our web server directories.
Navigating through FileZilla, we’ll go to the “wp-content/themes” folder where all our themes reside. If you’ve created a child theme, you’ll find a separate directory for it, typically named after the parent theme with “-child” appended to the end of the folder name.
Go into your parent theme directory, and copy one of the existing template files to your local computer, then edit it with your favorite code editor.
Recalling the template hierarchy, if we have a custom homepage set, it will utilize page.php — the template that governs all our pages. And if the custom homepage isn’t set, we can create home.php.
To create front-page.php, I recommend copying either index.php or page.php from your parent theme.
Let’s open up the file in Notepad++.

The PHP template consists of WordPress functions to retrieve the header and footer. These tasks have now been streamlined in the visual builder through the use of template parts and blocks.
The page’s content is generated by a “while” loop, which requires some coding knowledge to customize.
Then you can manually add HTML code anywhere within these templates, and if styling is required, you’d update the child theme’s style.css file accordingly.

Once you make a few edits, try renaming front-page.php to home.php, and you’ll learn firsthand how the template hierarchy is operating.
Go Customize Your Website Homepage!I understand this process can seem intricate, and even more confusing while being explained in a text format like this blog post, so I advise you to watch the video tutorial, too.
But it’s manageable when you test it on your own website. Simply examine your homepage’s content and work backward to identify its source.
Then test things out by putting unique HTML/PHP code into your custom files. When you refresh to see what’s on the homepage, you’ll start to cement your understanding of how these little changes are affecting your front-end!
If you are new to WordPress, I highly recommend selecting a block theme from day one, such as Twenty Twenty-Four. This way, you can construct everything visually, and you don’t have to worry about hacking PHP files!
👉 WordPress Homepage Flow ChartWant this helpful free giveaway or training?
The post How to Set the Homepage in WordPress appeared first on Website Profit Course.
April 8, 2024
How to Deliver a Client Website
Today, we’ll talk about the client handoff process when delivering a WordPress website.
Sometimes, folks tend to overcomplicate this step, striving for the perfect process. However, in dealing with others, listening to your client’s unique situation and meeting them halfway often proves most effective.
So, let’s explore the major sticking points to launching a client website.
15 Tools to Start Your Web Design BusinessWant this helpful free giveaway or training?
Who Buys Domain & Hosting?
Firstly, there’s the question of the website infrastructure nuts and bolts, i.e., who purchases the domain and web hosting?
There’s no one-size-fits-all approach.
I’ve encountered almost all the scenarios, from clients having both and just needing to launch WordPress on a hosting package they’ve already bought, to clients who start from scratch.
Personally, I prefer doing everything under my accounts for ease of management. However, if clients already have their domain and hosting sorted, there’s no need to change that, especially if they are past the refund period!
Simply obtain their account login details and work with what they have.
The added benefit is that you’ll learn how various domain providers and web hosting companies operate and find the one you like the most.
Many web developers choose to start a website locally, creating directly on a PC. While this approach is convenient for you (done with software like XAMPP to run PHP and MySQL on your computer), it poses a challenge when clients want to preview the site.
Sending them a link to see your work isn’t feasible if the site is only locally hosted!
To address this, I solely for demo websites. You can ensure this domain isn’t indexed by Google by editing the robots.txt file.
Then, I install each unique WordPress site within a subfolder, so it looks like…
yourdemodomain.com/my-clientThis makes it easy for clients to review and provide feedback.
Nowadays, many hosting companies offer a more convenient solution through a “staging area,” which is usually installed as a temporary subdomain on your real domain name.
I’ve covered client pricing more extensively in another blog post. Most commonly, to launch a website, you charge 50% upfront payment and the remaining 50% upon launch, once the site is approved and ready to go.
When I receive the final payment, that’s when I transfer the site to their live domain.
This is where migration plugins come in handy. My personal favorite is Duplicator, which turns the complicated process into easy-to-follow on-screen instructions.
My overarching philosophy is to make things as easy as possible for clients, handling these technical tasks so they don’t need to worry about them.
For hosting, you simply need to choose an option that allows for unlimited websites, and the limiting factor is either your space, bandwidth or resources used across all sites.
Initially, I started with a reseller plan from HostGator, upgraded to a VPS for a few years, and now run most client websites on a SiteGround GrowBig plan.
For domains, I started with GoDaddy and still use them to this day, since I’ve had very few issues with them. Their hosting is another story, and I like having domains and hosting on separate platforms.
[image error]SiteGround Web HostingLaunch your website or blog today on SiteGround, the hosting company recommended by WordPress!
Buy NowI may earn a commission if you purchase using my links which helps support this website.
Who Owns the Website?
Ownership of the website itself is a more tricky matter.
Many web designers simply hand over complete ownership to the client. They are in the business of charging a high ticket price for the setup and letting the client handle everything post-launch on their own domain/hosting.
While this approach is valid, I’ve found that it can lead to challenges, especially if clients lack the expertise to manage the site effectively.
Even when you provide training or tutorials for them to DIY, clients struggle to grasp the intricacies of WordPress. It’s common for them to initially express enthusiasm for handling updates and edits themselves, only to find themselves overwhelmed once they actually dive in.
Simply put, most clients aren’t equipped to manage the website independently using WordPress. They are busy with their own problems, and adding another frustrating technical experience to their plate is their worst nightmare.
If a client is a website novice and wants to DIY, they are better off using a more constrained platform like Squarespace instead of hiring a web designer.
That’s why I’ve shifted away from one-time projects and offer ongoing management services for a monthly fee.
This way, clients can simply contact me via text or email (whatever is most convenient) with their requested website updates. Then, I take care of them on my schedule.
When it comes to domains, I’ve encountered issues with larger national website providers that unfairly lock customers into a bad deal.
For instance, they will register the domain, and if the client decides to cancel, they will withhold domain access instead of transferring ownership.
This is detrimental from an SEO standpoint, as maintaining ownership and building authority on your primary business domain over a long period is crucial for success with Google.
My approach here is simple — be reasonable and cooperative with clients!
If they choose to cancel or request ownership of the domain name or website when it’s under my control, I do my best to accommodate them.
In such cases, what I would do is create a complete website backup with Duplicator and hand it over. For the domain, they’d have to create an account with GoDaddy or another domain provider, and I would initiate a transfer.
They get everything, yet it’s not my responsibility to set it up on a new hosting account — that’s on them to figure out or whoever they hire next.
If the website is already set up on their domain and hosting, it’s on them to deal with those companies. If you’re using a premium theme like Divi, you can simply remove your API key from the settings before making a backup, so they won’t receive future updates.
Basically, all of the little problems that might occur in the future are now their issue, not yours.
[image error]Divi Visual BuilderThe #1 WordPress theme on the entire internet to design your website with drag-and-drop!
Buy NowI may earn a commission if you purchase using my links which helps support this website.
Should Clients Get Admin Access?
As I mentioned briefly, if a client requests admin access, I’m more than willing to provide it, as long as they understand the responsibility and ramifications of the power this brings!
You can create a separate WordPress account for them. If they just want to update content, limit the account role to author or editor vs. full administrator privileges.
If they want 1-on-1 training, incorporate that into your pricing structure. You cannot do this for free.
In my early days, I made this mistake, and funny enough, that’s why I started creating YouTube tutorials. Despite investing time in creating tutorials for my first handful of clients, only one regularly published themselves.
I thought to myself, there’s a broader audience of web designers who are interested in learning WordPress, so why not share these same tutorials on YouTube?
Many freelancers hesitate to offer full management services or charge a monthly fee.
However, I’ve found it to be beneficial for both myself and my clients. It allows for increased margin and revenue for you, reducing the constant need for new clients. And it enables you to provide more focused attention to each individual client.
It’s also a great way to test new ideas and do things that the bigger companies can’t with their cookie-cutter solutions.
Web Design Client QuestionnaireWant this helpful free giveaway or training?
Provide Post-Launch Value to Earn More
Maintaining ongoing value post-launch is crucial for website success. Continuously adding to and optimizing the site is key, as is monitoring traffic and performance.
To achieve this, you must track analytics reports, which show goal completions such as contact form inquiries or phone number clicks. This data will more clearly illustrate the value that a website is bringing your client, and is an easy way to justify what they pay you monthly!
You can send this info to your clients either through a concise one-page PDF or via screencasts, where you can record yourself navigating through important graphs within your analytics reports and providing them a brief explanation.
Consistently, clients have expressed appreciation for these reports (especially the screencasts), finding value in understanding their website’s traffic and conversion rates.
This approach has undoubtedly fostered long-term client relationships, with several clients remaining with me for over a decade. Building such rapport means you don’t need to work with dozens of clients to generate a sustainable side income or turn this into a full-time operation.
Beyond website management, I offer additional services such as social media, SEO, and online advertising.
The internet landscape evolves rapidly, and I can safely say that the average business owner doesn’t have the capacity to keep up with changes across all these platforms – WordPress, Google, Facebook, Instagram, etc.
Part of what they are paying for is you to stay abreast of these developments and come up with ways to utilize the right combination of marketing channels to get them the best results.
The flipside is that I’ve had clients who are happy with a professional website and do fine with referral work. They often go 6-12 months without reaching out to me. In this situation, when they actually do have a request, I’ll go out of my way to take care of it.
Other clients are much more proactive, and appreciate regular communication, whether it’s via phone calls or face-to-face meetings. This fosters trust and ensures a long-lasting partnership, but you also have to balance it because some of them will happily talk your ear off for 2 hours every week if they could. 😆
Check Existing Email Accounts
One last thing, but certainly not least, is handling email accounts tied to the client’s domain.
You can omit this completely if you’re building from scratch on a new domain. However, if your client has an existing domain name with custom email, you must do an audit to determine their current setup before transferring anything.
That’s because when you change domain DNS settings, it will also affect how email is handled.
In cases where clients don’t have existing domain-hosted email accounts, I prefer setting up email forwarders rather than creating new email accounts.
This approach allows clients to retain their custom domain email addresses, ensuring professionalism in communication. But the web server doesn’t store email, and you don’t have to worry about monitoring these inboxes, which will eat into your web hosting quota(s).
Forwarders are also easier since they require no setup. The email goes directly to your client’s existing address, and they handle it from their preferred inbox, whether it’s Gmail, Yahoo, iCloud, or another popular provider.
Most of my clients, particularly in the home service contractor niche, prefer this streamlined approach, as they primarily rely on email and phone calls to generate leads and close deals offline.
Remember, you’ll never fully grasp the intricacies of this client website handoff process until you engage with others and encounter the challenges unique to their business industry.
Don’t hesitate to seek out clients, even if you don’t have all the answers right away.
Learn by doing and develop your own business processes from this real-life freelancing experience!
15 Tools to Start Your Web Design BusinessWant this helpful free giveaway or training?
The post How to Deliver a Client Website appeared first on Website Profit Course.
April 6, 2024
13 ChatGPT Prompts for WordPress Freelancers
I’m sure by now you’ve heard of the artificial intelligence tool ChatGPT made by OpenAI.
Let’s walk through some ChatGPT prompts that are tailored specifically for WordPress users and freelancers.
This will be a game-changer for you, as it will accelerate your learning process and significantly boost your productivity.
Take these ChatGPT + WordPress examples and use your own creativity or situation to tailor the prompts to your needs!
👉 13 ChatGPT + WordPress Prompts PDFWant this helpful free giveaway or training?
Create a Website Outline(PROMPT) Outline the pages needed for a landscaping website.When it comes to simple business websites like these, the structure tends to be quite predictable.
You’ve got your essential pages—the homepage, about, services, portfolio, and gallery. Each serves a distinct purpose, providing visitors with valuable information about the landscaping company.
However this prompt will become useful as a web designer working with a client in a new niche. Having a predefined template of the website infrastructure like this makes your job much easier.
Then if you ask follow-up questions, you can go more detailed into any one specific page or content idea.
Choose WordPress theme(PROMPT) I'm deciding between two WordPress themes - Divi & Beaver Builder. Provide a comprehensive pros & cons list for each.Nearly every WordPress user faces this task at some point. In this case, you’re torn between two popular options — Divi by Elegant Themes and Beaver Builder — both known for their visual page-building capabilities.
With ChatGPT, you can create a nicely organized list of pros and cons to consider while making your final decision.
For example, here are some benefits of using Divi.
Pros:
✅ Boasts the most powerful page builder among its competitors.
✅ Offers a lifetime license, allowing for a one-time payment instead of annual renewals.
✅ Provides extensive customization options, including access to a wide range of CSS styles.
Cons:
❌ While Divi excels in customization, it may have a steeper learning curve compared to other themes.
Now, let’s take a look at Beaver Builder:
Pros:
✅ User-friendly interface, making it easy to create and customize pages.
✅ Offers annual license renewal, providing ongoing support and updates.
Cons:
❌ Limited modules and customization options compared to Divi.
❌ May not provide as much flexibility for advanced users accustomed to extensive customization.
Your feedback via a subscriber survey shows that Divi is your preferred choice.
That’s why I use Divi today to power all my websites (including this one).
As someone who appreciates extensive control and customization, Divi’s flexibility to edit more CSS styles suits my needs.
If you’re still undecided or seeking further insights, don’t hesitate to turn to ChatGPT for additional guidance on the specific WordPress themes you’re considering. Its ability to provide tailored recommendations and insights can help you further clarify which theme best suits your website requirements.
Create WordPress Shortcode(PROMPT) Create a WordPress shortcode that lets me insert a Google Map with latitude and longitude as the input values.Get a tailored snippet of WordPress code that allows you to seamlessly embed a map into a blog post or page on your website.
This PHP code below creates a WordPress shortcode that allows you to customize the latitude and longitude, as requested in the prompt. It also adds a few more parameters that it knows you can edit via Google’s embed code, such as zoom level, width, and height.
function custom_google_map_shortcode($atts) { // Extract attributes extract(shortcode_atts(array( 'latitude' => '', // Latitude coordinate 'longitude' => '', // Longitude coordinate 'zoom' => '15', // Default zoom level 'width' => '600', // Default width 'height' => '400' // Default height ), $atts)); // Construct Google Maps URL with provided coordinates and parameters $map_url = 'https://www.google.com/maps/embed/v1/...' . $latitude . ',' . $longitude . '&zoom=' . $zoom . '&size=' . $width . 'x' . $height; // Output the map return '';}// Register shortcode with WordPressadd_shortcode('google_map', 'custom_google_map_shortcode');Then you simply insert the shortcode `[google_map latitude=”your_latitude” longitude=”your_longitude”]` into any WordPress post or page, replacing “your_latitude” and “your_longitude” with the desired coordinates. You can include the other parameters as necessary or let them fall back to the default options.
Feel free to integrate this shortcode into your WordPress site either by adding it to your theme’s functions.php file or by creating a custom plugin.
And remember, it doesn’t always provide the best solution to your first question or request. If you encounter errors or realize the code is not working as intended, follow up with more requirements and constraints.
For example, the code above uses Google Developer API, whereas you probably can get away with using the more generic Google embed URL that you can manually share while browsing Google maps.
ChatGPT gives you an enormous headstart, but you still have to use your human brain to implement it correctly!
Marketing Plan for a Website Client(PROMPT) Act as an expert in service business marketing and lead generation. Provide targeted and actionable advice to a roofing business owner who is struggling with generating leads and marketing their services effectively. Your advice should include proven techniques for attracting customers, promoting services, and converting prospects into paying customers.Did you just land a roofing client and want to help boost their business?
ChatGPT can provide a concise yet targeted plan to generate more leads and ensure your client wants to stick with you!
Here’s what it gave me…
✅ **Optimize Your Website**: Ensure your website is user-friendly, mobile-responsive, and optimized for search engines. Highlight your services, showcase past projects, and include clear calls-to-action.
✅ **Local SEO Strategy**: Claim and optimize your Google My Business listing, target local keywords in your content, and encourage satisfied customers to leave reviews.
✅ **Content Marketing**: Create informative blog posts, videos, and infographics that address common roofing issues and provide valuable solutions. Share this content on your website and social media channels to establish authority and attract potential customers.
✅ **Pay-Per-Click Ads**: Invest in targeted Google Ads and Facebook Ads campaigns to reach local homeowners actively searching for roofing services. Use compelling ad copy and targeted keywords to maximize click-through rates.
✅ **Referral Program**: Encourage satisfied customers to refer their friends and family by offering incentives such as discounts on future services or referral bonuses.
✅ **Networking**: Attend local business events, chamber of commerce meetings, and industry conferences to network with potential customers and industry professionals. Build relationships and partnerships that can lead to referrals and new business opportunities.
✅ **Local Partnerships**: Collaborate with other local businesses such as real estate agents, home builders, and property managers to cross-promote services and expand your reach within the community.
By helping your clients implement these strategies, you will build a loyal freelancing customer base that will turn to you for all things related to online marketing.
Generate Social Media Posts(PROMPT) Write 20 social media posts for a local landscaping company. The details are below:Business Name: Ray's Lawn CareService Areas: Ocean City, NJYear Started: 1999Here are the best topics that are common to this business:- Regular yard maintenance- Weeding garden beds- Mowing lawn- Overseeding- Aerating- Fertilizing- Residential & commercialFormat: 1-2 sentences long, friendly and conversational. Include seasonal references.Today, I’ll share one more example that I’ve personally used with one of my home service clients (I just swapped out their info).
Recently, I had a client who wanted to maintain an active presence on Facebook. They were managing it themselves, but they’re not very tech-savvy and didn’t enjoy the process. They were posting generic content, and honestly, ChatGPT could probably do it better than they could, so why not outsource this task?
I provided a very specific request, including personalized details about their business — like the name, service area, and the year they started. Additional information like licenses, certifications, or associations they’re part of could also be included.
Then, I provided a list of topics common to their business industry.
With this approach, you can have dozens of social media posts ready to go. Because you asked for social media posts, ChatGPT automatically appends hashtags and emojis.
This essentially completes your social media marketing proposal to a website client!
By the way, I also offer a Divi landscaping website template for just $17. If you’re a Divi user and want a ready-made template to quickly set up a WordPress website for a local lawn company, this is a great option.
With this template and ChatGPT’s social media plan, you’ll have everything to set up a local company with professional digital marketing.
FYI, don’t forget to grab the cheat sheet that includes 13 ChatGPT prompts, including the handful we went through today! 👇
👉 13 ChatGPT + WordPress Prompts PDFWant this helpful free giveaway or training?
The post 13 ChatGPT Prompts for WordPress Freelancers appeared first on Website Profit Course.
December 2, 2023
WordPress Twenty Twenty-Four Theme Customization Tutorial
WordPress recently launched the Twenty Twenty-Four theme, improving on the previous few that are made 100% with Gutenberg blocks. Let’s take it for a spin today!
WordPress is continually upgrading the full site editing features, and in this new theme, they’ve enhanced the pre-made layouts, making it more user-friendly. So, instead of completely revamping this website, I’ll make minor customizations to build on what they’ve given us.
2024 Theme Tutorial PDF GuideWant this helpful free giveaway or training?
Install Twenty Twenty-Four ThemeLet’s dive into the dashboard of a fresh WordPress installation. We’re using WordPress version 6.4.1, and on the dashboard, you’ll see if the Twenty Twenty-Four theme is installed.

If not, navigate to “Appearance > Themes” to install it.
Full Site Editor OverviewOnce activated, we can go to “Appearance > Editor” to modify all our templates.

WordPress has added a menu on the left, giving access to:
NavigationStylesPagesTemplatesPatterns (including Template Parts)Included in this update is a feature that allows editing of page content within the template editor. This resolves a major frustration users had when designing their templates, thinking they could add content directly there vs. the Pages section from the admin area.
With every release, WordPress introduces new UI changes while empowering full site editing — which can be confusing if you log in and things suddenly look different after a core software update.
For example, reusable blocks are now called “synced patterns”. For template parts like the header and footer, you’ll now find those in your Patterns.
As you can tell, WordPress is undergoing plenty of changes to modernize the way you build websites. Expect these transformations (& powerful features) to continue for the next few years!
Pick a Style VariationNow, let’s explore the pre-made styles available.

There are eight options, and I’ll select the blue one called Maelstrom. This theme comes with a homepage layout example for an architecture company, which we’ll use.
After saving the selection, I’ll start by creating a couple of pages and uploading the media required to complete this design.
Publish Photos to Media LibraryNavigate back to the dashboard and go to the Media section.
📝 Grab the “Twenty Twenty-Four Theme Tutorial Guide” below, including all the photos & the step-by-step process we’re doing now!
2024 Theme Tutorial PDF GuideWant this helpful free giveaway or training?
I’ll drag and drop the files by clicking “Add New Media File.”

Now, we have all the photos we need to fill into our templates and pages.
Publish Pages with PatternsMoving over to the Pages section within the dashboard, click on “Add New Page.”

With Twenty Twenty-Four, you have the option to choose a pattern right as you create a page instead of starting from scratch.

I’ll quickly add a few pages and we can test out adding content from the template editor instead.
Our homepage uses the “Business home” pattern.
Let’s create an About page using the “About” pattern. Set the title and publish.
Next, create a portfolio page using the “Portfolio home image gallery” pattern.
Finally, create a pricing page. There is no complete page layout pattern within the popup list, but we can find a pricing table pattern another way. Let’s publish it as an empty page, and we’ll finish that in just a bit!
Navigating the New Template EditorNow, if we move back to “Appearance > Editor”, let’s dig into the specifics of how you’re going to customize your layouts.
You can easily access the editor by clicking the preview window.
Search for Templates, Parts & PagesAt the top center, this navigation lets you move between templates, template parts, or pages via search (or keyboard shortcut CTRL+K). Previously, this was a dropdown menu.

We’re currently editing the “Blog Home” template, which will be displayed on our homepage. If you want a fully custom homepage, you can create it in the Pages section and set it as the Homepage within the WordPress “Settings > Reading” section.
If you want to edit an individual page (like the ‘About’ page we just created) or the overriding template that applies to all pages, you can search for either.
Notice how the icons vary depending on whether you’re editing a template, a template part, or a specific page.
Enable List ViewIn the top left, click the three-line icon to find the hierarchy of blocks comprising the template being shown on the editor preview window.

At the top level, we have our Header & Footer template parts, marked in purple.
All the content in the middle is organized within Group blocks, creating various sections on this homepage.
If you want a single-line description of the selected block’s nested hierarchy, look to the bottom left.

On the right side, you’ll find your Settings and Styles options, which you can show or hide by selecting the respective icons.

Within the settings, you’ll find individual settings for the selected content block, and when you deselect, you may also see settings for the entire template or page.
The styles are the defaults that apply across your entire website.

In the top right corner, you can open a preview window or change the screen size, allowing you to switch between desktop, tablet, and mobile views.

Make adjustments if necessary to ensure your design is mobile-friendly.
Set Your Custom StylesIf you want to change the pre-made style that we chose (Maelstrom), you can access it from the “Browse Styles” button, just like we observed within the template editor landing page.
With WordPress, there are typically several places where you can edit the same thing!
This is even more evident now with Twenty Twenty-Four, as you can edit the page content directly within the template editor or navigate to the Pages section to edit there.
With the Styles menu open, click on the eye icon to see the “Style Book”.

It provides a preview of how various blocks appear, including quotes, lists, code, images, buttons, and much more.
You can further customize the pre-made template by adjusting typography, colors, and layout settings, which apply to your entire site.
I’ll only make a few small changes.
I’ll dive into the “Styles > Typography > Button” settings to modify how all buttons appear. Let’s increase the size to medium and make them bold.

I’d also like to convert it to uppercase, but it seems this option isn’t available in the typography section. To achieve that, let’s backtrack a bit and head into “Styles > Blocks > Button”.

Scroll down to the typography section to switch the “Letter Case” option to uppercase.
You can do as little or as much customization as you’d like.
For instance, you can set the default style of any block from “Styles > Blocks” and search for your desired block.
Although this one comes with a built-in color palette, you can adjust it or create your own from the “Styles > Colors” section, that way, it’s ready to go when you create content and want to edit something.
Edit “Blog Home” TemplateLet’s start from the top.
Customize “Header” Template Part
There’s a space already designated to upload our logo.
We’ll simply click that button and select the logo from our media library.
Next to the logo, we have our “Site Title” block, which is currently showing “My WordPress”. Just select it and edit the text — I’ll paste the name of the architecture company.
You can also manage this through the WordPress admin area via the “Settings > General” section to set the title & tagline outside of the editor.
Customize Homepage ContentGo through the template and replace the stock content with your own. I’ll show you a few simple examples.
Let’s link up the first button to our About page.

Select it and click the link icon, then search for “about,” which should pull up our page.
Now, let’s swap a photo with our own.

Select an Image block, and hit the replace button. We’ll access our media library and choose one.
Moving on to the Headline block, here’s a new feature — adding an asterisk to the headline.

If we open the settings, you’ll notice the option to either have a default heading or one with an asterisk.
Next, let’s look at a minor inconvenience.
The testimonial section includes an area to upload a headshot icon of the person. However, it’s tricky to click because of its size, causing these scroll bars. The “Media Library” link and upload button are barely visible.

Luckily, there’s just enough room for me to click!
Customize “Footer” Template PartNow, onto the footer section.

Analyzing the footer structure, we notice a group with three columns. Interestingly, the second column contains no content and acts as a spacer. The third column displays three more columns of links.
To streamline this, I’ll remove the first link list, meant for sub-pages of the About page, which we haven’t created yet. To trash the Stack block, select it from the list view, then click the three-dot icon and choose “Delete”.

Then, I’ll drag and drop the second Stack into the empty second column, ensuring it’s nested correctly.
In the last column, we’ll drag and drop the last Stack above the Row level, eliminating the need for the row, which you can delete.

To ensure equal width, I’ll adjust via the Column block settings. The first was set to 30%, the second to 20%, and the third to 50%, which obviously totals 100. I’ll adjust them to 34%, 33%, 33% for equal width.

Moving on to the social list, I’ll replace this set of links with the “Social Icons” block. Insert them after the headline, once again simplifying the structure by deleting the Stack block with the social links.

Designing these layouts can be straightforward or intricate for an enhanced design. It takes some trial and error to grasp the different layout blocks like the Group, Columns, Rows, and Stacks.
Once you select “Add After,” you can choose a block by typing the forward slash (/), and then searching for the type of content you want to add.
To add social networks, click the plus (+) button. We’ll include Facebook, Instagram, and X (formerly Twitter). At the moment, WordPress gives you options for both the old and new Twitter icons.

To ensure these icons show up on the front end, we need to link them. Once the links are added, you’ll notice the icons transition from slightly transparent to full color.
With any selected block, the box on the left navigates up one level. For instance, if we’re in the X social icon block and click this box, we’ll return up a level to the “Social Icons” block.

Here, we can select our size. Let’s set it to Large. I also prefer external links to open in a new tab, you can toggle this option in the settings, too.
Additionally, you can change the justification or orientation.

That sums up what I’m doing for the homepage. Let’s save these changes.
Upon saving, it displays the elements updated within your site.

We’ve updated the site Icon, Logo, Title, the “Blog Home” template, the Header and Footer template parts — which will reflect these changes wherever used — and the custom styles that affect your entire site.
Save it and take a look at the front end by refreshing the page.
Edit a Template Part OnlyLet me guide you through an alternate navigation method to access a template part like the Footer for a quick fix.
Going back to the “Appearance > Editor” landing page, and select Patterns.

Look under the pattern categories and click “Manage all template parts.”

I’ll head into our Footer template part and the editor window displays the footer only.
Save your template part, and go check out your changes on the live website.
It’s quite amazing how swiftly you can craft something beautiful with these premade layouts!
Edit “About” Page ContentReturning to our template editor, I’ll look up the About page from the top-center navigator.

Clicking on any locked item presents this notification — “Edit your template to edit this block.” The Pages template controls the common layout of all your WordPress pages, such as the page title and featured image.
For this task, we’ll focus solely on editing the content of the About page.
Currently, there’s a button named “About Us,” which seems irrelevant on this page! We’ll change this to “Portfolio” and link it to the portfolio page by searching & selecting it.

Now, let’s move down to the team images.
I’ll add them from the media library. We have Francesca, Rhye, Helga, and Ivan, and as I pick the faces for each name, I think they match pretty accurately. What do you think? 😆

Let’s save this now.

As we’ve mentioned, you have the option to edit your pages directly from the template editor. Since we did this with the last page, I’ll edit this one right from the Pages section from the WordPress admin menu.
Our portfolio layout is done from the pattern that we imported upon publishing at the beginning, so all we need to do is fill it with photos.

The only thing I’ll update on this page is to transform the Heading block to a paragraph, reset the size (to make it smaller) and center it.
On the right-hand side within our settings, you can set the image aspect ratio and the scale, which is currently set to cover so it’ll fill the entire area.

There’s also an awesome new feature in this version of WordPress – a built-in lightbox. Enabling this will expand the photo on click, eliminating the need for plugins or external JavaScript libraries like FancyBox.
Image “Expand on Click” with Custom CSSHovering over the photos, you’ll notice a little icon on the top right and the cursor becomes a magnifying glass. This signifies the expand-on-click feature. When clicked, it’ll open the image in a full-size popup window, overlaying the background with your WordPress Styles base color.

Now, let’s dive into how to use custom CSS to tweak this feature. To start, I typically use the Google Chrome inspector.
Right-clicking and selecting “Inspect” brings up that element in the inspector window and shows you the raw HTML code behind the site. This tool is invaluable as a web designer to help you locate and modify elements on your browser before making any edits to the live website.
Hovering over elements highlights them on the page, making it easier to identify where styles are set.
In this case, the background color (blue) is set within the element. It’s using our preset base color variable set within the WordPress styles. I want to overwrite this so it’s black and slightly transparent. You can target an HTML class in CSS by using the dot (.) selector before the class name. The element we’ll target via CSS is the “scrim” class within a parent element with the “wp-lightbox-overlay” class. When applying the CSS, we will set the background-color property using the rgba() function to input red, green, blue, and alpha (transparency) values. Then we will give our style precedence by using the “!important” property to overwrite the default inline style. Although this might sound complicated, it’s straightforward when you see how easy it is to copy and paste this one line of code below. To add custom CSS to your WordPress theme, you’ll need to navigate back to the template editor and show the Styles. Within the Styles menu, click the three-dot icon and select “Additional CSS.” Here, you’ll find the text box for writing or pasting CSS code. Go ahead and copy the code above into your Additional CSS, then save and test it out! Remember, when you can’t figure out how to do something with the visual editor, custom CSS can give you more fine-grain control. The last page we’ll tackle is the pricing page, so open it up in the template editor or Pages section. To access the pre-done pricing table, click the plus (+) button and choose “Browse all” to view previews of all available patterns. The pricing pattern layout gives you a solid structure for displaying three primary services or packages. The only modification I’ll make is adjusting the padding. It’s currently set to 5 for top, bottom, left, and right. Let’s change that to 2 to tighten up the spacing. Go browse through your entire website now — you should be impressed! The layout looks incredibly professional, achieved in a fraction of the time it would have taken just a few years back using the old WordPress theme system without full-site editing. Almost every time WordPress releases a core update, it seems like there’s a tweak in the backend, a change, or new features added to the visual template editor. The exciting thing is that all these features are free with the Twenty Twenty-Four theme. In the past, such functionalities were exclusive to those purchasing premium themes. Now, WordPress is increasingly integrating visual drag-and-drop design capabilities into the core software. As always, the best way to learn is to dive in and start building your own website. Setup WordPress in minutes! 👇 I may earn a commission if you purchase using my links which helps support this website. Your WordPress website is an incredible and cheap playground where you can experiment with these remarkable tools (plus the cost of domain & hosting) to create something that truly reflects your vision. Want this helpful free giveaway or training? The post WordPress Twenty Twenty-Four Theme Customization Tutorial appeared first on Website Profit Course.
/* Portfolio */.wp-lightbox-overlay .scrim { background-color: rgba(0, 0, 0, 0.9) !important; }Conclusion
[image error]Launch with HostGator
Start Now
October 29, 2023
How to Create a Custom WordPress Plugin (PHP, HTML, CSS, & JS Tutorial)
Ever wonder how WordPress plugins work? Today, I’ll show you how to create a custom WordPress plugin from scratch!
This plugin won’t be within the directory that requires approval from WordPress. Instead, you’ll build your own in a code editor and upload it to your website.
I drew inspiration and built upon the work of Bill Erickson, a developer who outlined the basic plugin creation process in his blog post. He provides his code example on GitHub.
You can grab my skeleton code below as a starting point for your custom plugin and follow along!
👉 Get Custom Plugin CodeWant this helpful free giveaway or training?
Plugin Code FrameworkOpen the files in your favorite code editor — my preferred option is Notepad++. It’s a lightweight code editor with a feature to save your “session” of open files. Clicking this session file (session.npp) will open all the associated plugin files in their own tabs.

In the top-level folder, we have only two main files:
readme.txt – This file provides information about the plugin.core-functionality.php – This file is what WordPress pulls from to show your plugin in the admin area.The latter PHP file includes all the other sub-folder files to perform our desired functions. We define the plugin directory and URL path here, which we’ll reference in the function files.

We include two main files within core-functionality.php:
insert-head.phpinsert-body.phpThis setup will allow you to custom code things into the website HTML head or footer. You can find these files in the “inc” sub-folder.
There are two more files, each in their extension sub-folder:
your-style.css – This file is responsible for the custom styles.your-script.js – This file handles Javascript interactivity.Of course, you can replace “your” with anything you want. I like using a unique acronym for the website.
This infrastructure provides a solid framework for building your plugin with PHP, HTML, CSS, Javascript, and jQuery.
Add Code to HTML HeadNow, let’s take a look at insert-head.php. Here, you’ll find WordPress developer functions typically added to your functions.php file, which is part of most themes.

This core functionality plugin is much like your functions.php file, just in a different location.
The primary reason to use a plugin instead is when you don’t have a child theme or if you want to keep customizations during a theme switch. A child theme is necessary when customizing your functions.php because, without it, you risk losing your customizations when the parent theme is updated.
Placing the code in a plugin like this makes your functions theme-independent.
In insert-head.php, we’re taking advantage of two built-in WordPress functions:
wp_enqueue_style() – To include our CSS file. wp_enqueue_script() – To include our JS file.📝 NOTE: WordPress has an extensive developer reference on their website to view & search for available functions and get the technical specifications on how they work.
Our custom enqueue_css_js() function adds our two files and appends version numbers based on the date of the last edit. This version is especially useful for bypassing cache issues, i.e., you make a change on the backend that doesn’t appear on the live website.
The next custom function is add_integration_code_head(), which — you guessed it — allows you to copy/paste HTML code from 3rd-party services to the of the HTML document using the wp_head WordPress hook.

The starting code above inserts FancyBox, a JS library that provides a modal popup for photo galleries. There’s also an empty comment as a placeholder to paste in Google Analytics or Tag Manager code.
Add Code to HTML BodyNow open insert-body.php, and the add_integration_code_body() function inserts this code to the end of the HTML document using the WordPress wp_footer hook.

Utilizing WordPress hooks like wp_head and wp_footer grants you the power to modify almost any part of your website.
The starting code includes a place for Google Tag Manager (GTM), which requires code in both the HTML head and body.
Website Integration Code ExampleMost of my websites are powered with Divi by Elegant Themes, and before understanding how to create a custom plugin like this, I was simply adding HTML code within Divi’s theme options on the integration tab.

The functions within the plugin mirror what you do in Divi’s theme options – they add code to your website’s HTML head or body.
[image error]Divi Visual BuilderThe #1 WordPress theme on the entire internet to design your website with drag-and-drop!
Buy NowWe earn a commission if you purchase using the link above which helps support this website.
This plugin project is a classic example of how WordPress offers multiple ways to accomplish the same task, and there’s rarely a single correct or best way to do it. Choose whatever method makes you most comfortable!
I’ll paste what I have from the Divi section. Let’s examine the code for a moment.

We’re using a mixed PHP/HTML format by adding the closing PHP tag (?>) followed by the copied HTML code from Divi’s settings, which includes GTM, FancyBox, and Typekit Fonts.
It’s worth mentioning that you should add comments like I do to articulate what’s happening in the code. You’ll forget if you don’t touch this for a few days!
We can use either PHP or HTML comments here. A PHP comment starts with two forward slashes (single line) or forward slash asterisk (multi-line, ended by those characters in reverse), while an HTML comment is enclosed by at the end.
// This is a one-line PHP comment/* This is a multi-line......PHP comment */Now, we’ll move on to what I have published in the Divi code section.
That includes GTM code, which I’ll copy into add_integration_code_body(), and the Javascript code to enable FancyBox on the HTML elements we want. We’ll adapt the latter to work with FancyBox v4 and add it to our Javascript plugin file, your-script.js.

In the code above, we’re using the Fancybox.bind() method to target anchor links with the class “fancybox” or within a parent element containing that class. Make sure to modify your code accordingly based on your specific use case.
For more information, refer to the WordPress developer reference.
Additionally, WordPress Stack Exchange and Stack Overflow are valuable forums for code questions and specific implementations.
Customize CSS StylesCSS (Cascading Style Sheet) provides the flexibility to customize your site’s appearance effortlessly and override any UI bugs inherited from your WordPress template or a plugin.
I usually start with CSS that applies to the theme or plugins I frequently use, like Divi or Contact Form 7, to override the default styles. Then, I’ll add a few sitewide features.

For example, we set CSS variables at the top level element to allow you to adjust your site’s colors easily. Each variable below represents a specific color, defined by its hexadecimal code or name.
body { --contrast: red; --dark: black; --light: #ffffff; --highlight: yellow;}With these color variables established, you can now use them throughout your stylesheet. The code below adds the –highlight variable as the background color for an HTML element.
.mark { background: var(--highlight); }Lastly, consider responsive styling to maintain a consistent design across different screen sizes. We can do that in CSS using the media queries shown below.
@media screen and (max-width: 800px) {/* Styles for screens up to 800px wide */
}@media screen and (max-width: 500px) {
/* Mobile-specific styles for screens up to 500px wide */
}
Get granular with CSS by targeting HTML elements, classes, IDs, and combinations of each, applying any properties you’d like to get the exact look you want.
Upload & activate custom plugin via FTPNow that you’ve set up your plugin files, it’s time to upload them to your web server with an FTP program such as FileZilla.
Using FileZilla, copy your plugin folder and its contents into your WordPress “wp-content/plugins” directory.

Return to your WordPress admin area and head to the “Plugins” page. You should see your new plugin listed. The name, description, version, and author you see come from the comments section within core-functionality.php.

Hopefully, no errors will occur after you activate it!
Now, you can test its functionality to ensure everything is working as expected or debug any errors in your code if things go awry.
To do that, check your web hosting error logs, where you’ll find helpful messages informing which PHP function caused the problem. Plus, you can test live Javascript and CSS updates.
Don’t forget to grab the WordPress plugin starter code to try out this theme-independent method to customize your website!
👉 Get Custom Plugin CodeWant this helpful free giveaway or training?
The post How to Create a Custom WordPress Plugin (PHP, HTML, CSS, & JS Tutorial) appeared first on Website Profit Course.