Matt Jones Tech
  • Blog
  • Video Projects
  • Web Projects
  • Make Any WordPress Block Sticky Without Plugins

    Make Any WordPress Block Sticky Without Plugins

    position: sticky vs position: fixed

    In CSS, you can use both position: sticky and position: fixed to make any WordPress block sticky, but there are some important differences that should be noted.

    position: sticky keeps that element within the document flow. Great for things like columns and sidebars that have content above them. When the user scrolls to a certain position, the element will become sticky or return to the normal document flow, based on user input.

    position: fixed removes the element from the normal document flow, FIXING it to a specific position (top, bottom, left right). It’s position remains fixed, regardless of user input.

    For more info on how position works, check out this MDN article on CSS Position.

    Target Your Element

    Making elements sticky has a variety of useful applications such as sidebars, and calls to action, but in my case I want to make the main header element of my page (a navigation menu) stick to the top of the page as the user scrolls.

    Since the main navigation menu will remain at the top of the page at all times, I’m going to use position: sticky because I want it to remain in the normal document flow. If I were to use position: fixed, yes, the menu would stick to the top of the page, but the rest of my webpage will float up underneath my menu, and you won’t be able to see it.

    If you’re targeting a specific block, you may want to give it a class or ID and target that way, but in my case, I’m fine just grabbing the entire <header> element:

    header {
    	position: sticky;
    	top: 0;
    	width: 100%;
    	margin: 0 auto;
    }

    Possible Reasons position: sticky Isn’t Working:

    1.) Check if a threshold has been specified

    position: sticky requires a threshold to be specified. Make sure that you’ve set something other than auto for any of the following properties:

    • top
    • right
    • bottom
    • left

    2.) Check your vendor prefixes

    If you’re on Safari, you may need to add a webkit prefix to your position: sticky call:

    .sticky {
        position: -webkit-sticky;
        position: sticky;
        top: 0;
    }

    3.) Check for overflow rules

    If you have the overflow property set on any parent or ancestor of the sticky element, the position: sticky rule won’t work.

    However, if you specify a height on the overflowing container, then sticky will work.

    matt

    September 8, 2022
    Web Development
  • How to Host Multiple Local Sites Using XAMPP and VirtualHosts

    How to Host Multiple Local Sites Using XAMPP and VirtualHosts

    As a web developer, it’s always a good idea to have a good working local environment for testing. Let’s dive into how to host multiple local sites using XAMPP and VirtualHosts.

    XAMPP Install

    You can download and instlal XAMPP over at https://www.apachefriends.org/download.html. XAMPP includes Apache and all the necessary setup to get your environment off the ground.

    Using Virtual Hosts to Set Up Multiple Installs

    If you’re only hosting one local site at a time, just doing a simple file protocol should be just fine to do your development. But once you have a need to work on more than one site at a time (locally), then you’ll need to set up a virtual host to separate your site installs.

    Why Virtualhosts?

    This is born out of the fact that your Apache install can only host a single directory (usually like /srv/www/, /var/www/, or with XAMPP, it’s typically something like /opt/lampp/htdocs/). Because of this, your site install is going to be localhost/wordpress/ in the browser.

    This starts to become a problem when you install a new site at /opt/lampp/htdocs/newsite/ and wordpress has to be at the root of its hosted folder. The minute you try to make subfolders, it messes with all your links and suddenly you start getting repeated parts of your links and they end up breaking the site.

    The solution? Virtualhosts. Basically special domains that are specifically defined to work on your local machine, to help you manage all your locally hosted sites.

    Associate Local IP Address with Apache-Hosted Subfolders

    Hop into a terminal and open the file /opt/lampp/etc/extra/httpd-vhosts.conf.

    Inside that file, around line 23, you’ll see some commented-out examples of how to set up Virtualhosts. Following that example, type out your own Virtualhosts configuration below the example:

    <VirtualHost 127.0.0.[0-99]:80> 
        DocumentRoot "/opt/lampp/htdocs/somesite"
        DirectoryIndex index.php
    
        <Directory "/opt/lampp/htdocs/somesite">
          Options All
          AllowOverride All
          Require all granted
        </Directory>
    </VirtualHost>

    Define Site Directory

    Next, around line 217 of /opt/lampp/etc/httpd.conf you’ll need to define your site directory

    <Directory /opt/lamp/htdocs/somesite>
        Options Indexes FollowSymLinks
        AllowOverride All
        Order allow,deny
        Allow from all
    </Directory>

    Define Local Domain Name

    This is the fun part! Make up whatever name you want (preferably something memorable that also makes sense) and assign it to the same IP address you defined earlier in httpd-vhosts.conf

    So inside your /etc/hosts file, define your local domain like so:

    127.0.0.1       localhost
    127.0.0.2       somesite.local

    Test It Out

    If all went well, you should be able to open your browser, and somesite.local will point to the IP address you defined in /etc/hosts, and that IP would be configured to use a Virtualhost by /opt/lampp/etc/extra/httpd-vhosts.conf and that Virtualhost would be pointing to a local directory defined by /opt/lampp/etc/httpd.conf that contains your website files!

    matt

    September 7, 2022
    Web Development
  • Customize the Default WordPress Login Page Without Plugins

    Customize the Default WordPress Login Page Without Plugins

    Let’s take a look at how to customize the default WordPress login page without using any plugins.

    Changing the Logo

    First, open your functions.php file in your child theme and drop in the following function:

    function my_loginlogo() {
      echo '<style type="text/css">
        h1 a {
          background-image: url(' . get_template_directory_uri() . '/path/to/your/logo.png) !important;
        }
      </style>';
    }
    add_action('login_head', 'my_loginlogo');

    Just keep in mind that get_template_directory_uri() returns the root directory of your parent theme. To return the root directory of your child theme, use get_stylesheet_directory_uri(). If your logo is someplace else, like in your uploads directory for example, you can use the wp_upload_dir() function instead.

    A Note about wp_upload_dir()

    wp_upload_dir() actually returns an array, so if you call it in a function like this, expecting it to return a url or a file path, you’ll end up getting an error, and could potentially lock you out of your site.

    In my case, I’ve saved my logo in my uploads directory, so I used the ['baseurl'] item in the returned array. Here’s another example of what your image URL path could look like from the above function call:

    function my_loginlogo() {
      echo '<style type="text/css">
      h1 a {
        background-image: url(' . wp_upload_dir()['baseurl'] . ' path/to/your/logo.png) !important;
        }
    </style>';
    }
    add_action('login_head', 'my_loginlogo');

    Also, don’t forget to use single quotes inside your array selector for wp_upload_dir(). If you try something like wp_upload_dir()[baseurl], it won’t work.

    Change the Logo URL

    Now that you’ve got the custom logo loaded, you can have it link to anywhere with another functions.php call

    function my_loginURL() {
        return 'https://www.myawesomelink.com';
    }
    add_filter('login_headerurl', 'my_loginURL');

    Change the Logo Tooltip

    If you’re getting an annoying tooltip on your logo that says “WordPress” by default, you can change it like so:

    function my_loginURLtext() {
        return 'A Better Tooltip or nothing at all';
    }
    add_filter('login_headertitle', 'my_loginURLtext');

    Add Custom CSS

    Enqueue the new stylesheet, specifically for the login page like so:

    function my_logincustomCSSfile() {
        wp_enqueue_style('login-styles', get_stylesheet_directory_uri() . '/path/to/your/styles.css');
    }
    add_action('login_enqueue_scripts', 'my_logincustomCSSfile');

    Add Custom Link(s) Below Form

    function my_loginfooter() { ?>
        <p style="text-align: center; margin-top: 1em;">
        <a style="text-decoration: none;" href="https://www.myawesomesite.com/">If you have any questions, visit my awesome site
            </a>
        </p>
    <?php }
    add_action('login_footer','my_loginfooter');

    Bonus: Redirecting Users After Logging In

    function my_loginredrect( $redirect_to, $request, $user ) {
      if ( isset( $user->roles ) && is_array( $user->roles ) ) {
        if( in_array('administrator', $user->roles)) {
          return admin_url();
        } else {
          return site_url();
        }
      } else {
          return site_url();
      }
    }
     
    add_filter('login_redirect', 'my_loginredrect', 10, 3);

    Hiding or Changing the Login Page URL

    It should be noted that this isn’t recommended from a “security through obscurity” standpoint as elaborated on by the CEO of Wordfence.

    But if you still want to proceed, it’s pretty straightforward, again, without using plugins, just duplicate your wp-login.php file and name it something else like new-login.php. Inside the new file, you’ll want to run a search and replace for wp-login within that file and replace it with whatever you named your new login file. So in my example, you’ll run a search within wp-login.php and replace every instance of wp-login with new-login

    Next, you’ll need to register your new login URL in functions.php:

    /*
     * Change WP Login file URL using "login_url" filter hook
     * https://developer.wordpress.org/reference/hooks/login_url/
     */
    add_filter( 'login_url', 'custom_login_url', PHP_INT_MAX );
    function custom_login_url( $login_url ) {
    	$login_url = site_url( 'new-login.php', 'login' );	
        return $login_url;
    }

    Once you’ve dropped that in your functions.php and uploaded your new-login.php file, you’ll want to test your new login URL to ensure it’s working properly. If everything checks out, you can trash your original wp-login.php file.

    matt

    August 31, 2022
    Web Design, Web Development
  • Add Custom Fonts to a WordPress Site Without Any Plugins

    Add Custom Fonts to a WordPress Site Without Any Plugins

    Let’s dive into how to add custom fonts to WordPress without using any plugins.

    Choose a Font

    Originally, I was using a font called “Arrow” from DaFont. This actually ended up giving me problems later on, something I’ll cover later.

    Convert to WOFF2 (if you need to)

    Any font in the entire world. Just make sure it’s in a format that’s good for the web, like woff2. If your font isn’t already in woff2 format, there’s a really nifty command line tool to convert (compress, actually) your font into the preferred format before we get going.

    sudo apt update
    
    sudo apt install woff2

    Usage:

    woff2_compress [path-to-font-file]

    This command will automatically compress the file to .woff2 and name it the same as your input filename and place it in the same directory.

    Upload Font to Child Theme

    I just put it in the root directory of my child theme, under /fonts

    ├── fonts
    │   └── Almo_Andrea_FontlabARROW.woff2
    ├── functions.php
    ├── screenshot.png
    ├── style.css
    └── theme.json
    

    Enqueue Font

    Enqueue your font inside functions.php like so:

    function my_plugin_add_stylesheet() {
        wp_register_style( 'arrowFont', get_stylesheet_directory_uri() . '/fonts/Almo_Andrea_FontlabARROW.woff2');
        wp_enqueue_style( 'arrowFont' );
    }
    add_action( 'wp_enqueue_scripts', 'my_plugin_add_stylesheet' );

    Typically, in the past, you’d have to call a @font-face rule in your CSS in order to assign that font to various elements. Additionally, if you’re using a child theme to handle your fonts, in the past, you’d have to make rules for how to implement your custom fonts in addition to your @font-face rule. However, as of WordPress 5.9, the @font-face rule is actually handled via theme.json.

    Add Font To Any/All Blocks via theme.json

    In my case, I’m riffing off of the TwentyTwentyTwo theme, so in my child theme, I just copied over the theme.json file to make my modifications. In my case, I’m looking for where the default font is registered. I found it around like 170, but it’s gonna look something like this:

    "typography": {
    			"dropCap": false,
    			"fontFamilies": [
    				{
    					"fontFamily": "-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,Oxygen-Sans,Ubuntu,Cantarell,\"Helvetica Neue\",sans-serif",
    					"name": "System Font",
    					"slug": "system-font"
    				},
    				{
    					"fontFamily": "\"Source Serif Pro\", serif",
    					"name": "Source Serif Pro",
    					"slug": "source-serif-pro",
    					"fontFace": [
    						{
    							"fontFamily": "Source Serif Pro",
    							"fontWeight": "200 900",
    							"fontStyle": "normal",
    							"fontStretch": "normal",
    							"src": [ "file:./assets/fonts/source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2" ]
    						},
    						{
    							"fontFamily": "Source Serif Pro",
    							"fontWeight": "200 900",
    							"fontStyle": "italic",
    							"fontStretch": "normal",
    							"src": [ "file:./assets/fonts/source-serif-pro/SourceSerif4Variable-Italic.ttf.woff2" ]
    						}
    					]
    				}
    			],

    In this section, you’ll want to update everything that needs to change to match what you’ve got going on in your child theme and whatever font you’ve chosen. In my case, I’ve updated “fontFamily”, “name”, “slug”, “src” and the “font-face” to match my font and child theme file paths.

    Once you’ve updated everything under “typeography”, now you can move on and update the “name” value for each of the blocks you want to use the new font on. By default the headers get their own font and it’s specified by the css variable var(--wp--preset--font-family--source-serif-pro). I changed the last bit with the slug that I set for my font, so my slug was arrow. My modifications looked like so:

    	"styles": {
    		"blocks": {
    			"core/button": {
    				"border": {
    					"radius": "0"
    				},
    				"color": {
    					"background": "var(--wp--preset--color--primary)",
    					"text": "var(--wp--preset--color--background)"
    				},
    				"typography": {
    					"fontSize": "var(--wp--preset--font-size--medium)"
    				}
    			},
    			"core/post-title": {
    				"typography": {
    					"fontFamily": "var(--wp--preset--font-family--arrow)",
    					"fontWeight": "300",
    					"lineHeight": "var(--wp--custom--typography--line-height--tiny)",
    					"fontSize": "var(--wp--custom--typography--font-size--gigantic)"
    				}
    			},

    Just keep updated the last part of that variable until you’ve changed all the blocks you’re trying to target with your new font. That’s it! Hope this helped someone.

    Potential Issues: Font Weight

    Something I’d like to note when you add custom fonts to WordPress… When you define your font inside of your theme.json, you’re required two things in order to register a font. From my understanding, these two requirements to register a font are actually coming from the CSS rule @font-face which requires a font family and a font weight attribute.

    If you were like me, and using a custom font that didn’t specify different weights within the font file itself, this can potentially be an issue. If @font-face can’t detect a font weight within the file inside of your src, then it won’t load the font and will use some default system fallback.

    To fix and/or avoid this issue, be sure to use a font that defines at least one font weight, and be sure to match that particular font weight within your @font-face call inside theme.json

    matt

    August 27, 2022
    Web Design, Web Development
  • Enqueue Stylesheets in a WordPress Block Theme

    Enqueue Stylesheets in a WordPress Block Theme

    Today we’re going to take a look at how to enqueue stylesheets in a WordPress block theme. My main stylesheet for a newly created custom WordPress block theme wasn’t loading after several tries and I couldn’t figure out what was going on.

    Every search result was just saying , “Oh, you gotta enqueue your stylesheet, just paste this code in…” but it never worked, even after replacing the parts where you had to specifiy the filename and filepath specific to the sheet you’re trying to load.

    The Root of My Problem

    After several tries, I finally figured it out. My problem wasn’t with wp_enqueue_style(), but rather get_template_directory_uri() and get_stylesheet_uri(), both of which are frequently used to enqueue stylesheets in a wordpress block theme.

    get_stylesheet_uri() returns the the actual file named style.css (required to have a theme)

    get_stylesheet_directory_uri() returns the filepath to the root of your theme directory (without the trailing slash), so example output would be yourdomain.com/wp-content/themes/your-theme-name

    And if that wasn’t enough, there’s one more bit of key information about get_stylesheet_directory_uri():

    In the event a child theme is being used, this function will return the child’s theme directory URI. Use get_template_directory_uri() to avoid being overridden by a child theme

    Anyway, all that said, if your stylesheet isn’t loading right off the bat, be sure to double check which functions you’re calling in addition to wp_enqueue_style() just to make certain you’re actually pointing to the stylesheet or JS file you’re trying to load.

    /*
    Theme Name: Twenty Twenty
    Theme URI: https://wordpress.org/themes/twentytwenty/
    Author: the WordPress team
    Author URI: https://wordpress.org/
    Description: Our default theme for 2020 is designed to take full advantage of the flexibility of the block editor. Organizations and businesses have the ability to create dynamic landing pages with endless layouts using the group and column blocks. The centered content column and fine-tuned typography also makes it perfect for traditional blogs. Complete editor styles give you a good idea of what your content will look like, even before you publish. You can give your site a personal touch by changing the background colors and the accent color in the Customizer. The colors of all elements on your site are automatically calculated based on the colors you pick, ensuring a high, accessible color contrast for your visitors.
    Tags: blog, one-column, custom-background, custom-colors, custom-logo, custom-menu, editor-style, featured-images, footer-widgets, full-width-template, rtl-language-support, sticky-post, theme-options, threaded-comments, translation-ready, block-styles, wide-blocks, accessibility-ready
    Version: 1.3
    Requires at least: 5.0
    Tested up to: 5.4
    Requires PHP: 7.0
    License: GNU General Public License v2 or later
    License URI: http://www.gnu.org/licenses/gpl-2.0.html
    Text Domain: twentytwenty
    This theme, like WordPress, is licensed under the GPL.
    Use it to make something cool, have fun, and share what you've learned with others.
    */
    

    Just a side note, apparently style.css that sits in the root of your theme directory exists for the sole purpose of registering the theme name, author, version, and all that. It’s never intended to hold the actual style code for the theme (I think).

    It might work for you, but the minute I tried to enqueue the style.css file that contained all the registration info, it immediately broke the entire site. Of course, I could have been enqueuing it incorrectly too. Anyway, just a thought.

    Enqueue Stylesheets Update (8/10/22):

    I recently discovered that putting all my child theme styles in an external stylesheet and enqueuing it from a subdirectory via functions.php has caused some strange issues for me when I try to use the Divi Builder.

    It appears that this method of loading child theme stylesheets prevents the CSS from loading in the visual builder.

    This issue has caused me to rethink my strategy when it comes to enqueuing stylesheets. I have since moved all my styling rules to the primary style.css (used to register the theme) and ditched the function call that enqueues the stylesheet from the child theme’s subdirectory. This move solved all the issues I was experiencing with the visual builder, but I’m still not sure what I was breaking and how I was breaking it.

    matt

    August 1, 2022
    Web Design, Web Development
    web development, wed design, wordpress
  • Mount SFTP Directory Using Rclone (An Alternative to Filezilla)

    Mount SFTP Directory Using Rclone (An Alternative to Filezilla)

    Learning How to Mount an SFTP Directory Using Rclone

    Since the beginning of my web dev journey, I’ve been using FileZilla as my primary SFTP client for two huge reasons. Number one, it’s available cross-platform and Linux is one of those platforms. Number two, it’s available at a really good price: free.

    Over the last few years, it’s been working great for me. A few years back, I made the transition to Manjaro and have been relying almost exclusively on the AUR for most of my software needs. That’s been going great until the latest FileZilla update. For whatever reason, it broke, and I haven’t had time to go on a side quest to get it working again.

    Against a wall

    Unfortunately, at the time of this writing, I was trying to use FileZilla compiled from the default package manager in Manjaro and it was having trouble launching. When I tried executing filezilla from the terminal, I got an error saying that it couldn’t find some gtk3_aui package and pacman didn’t know what I was talking about either, so I needed a quick open source alternative to FileZilla until it got fixed.

    Luckily, I remembered that I could use rclone to mount Backblaze B2 buckets on my file system just like a normal external hard drive. I figured sense rclone works with every file-serving platform and protocol out there, I’d give it a shot.

    Setup

    Setup was pretty straightforward, just run rclone config and choose your cloud service. For me, this time, it was SFTP. It took me through quite a bit of options since SFTP is a bit more open than a proprietary service like Backblaze’s B2 buckets. Once I went through all the options, set passwords, ports, hostname, username, it was all set up and good to go, I could call it like I’d call any other rclone connection.

    Mount

    Once you’re set up, the mounting is pretty easy for Linux and Mac users. Just run the mount command and tell rclone where to mount your destination. So for example, back when I was setting up my rclone cofig, my SFTP was named SHC. So to mount the root directory of my web server to someplace on my local machine and use it just like an external drive, just run rclone mount SHC:/ /path/to/local/dir/. For more info, feel free to check out the Rclone docs and see what else you can do with Rclone.

    matt

    June 13, 2022
    Web Development
  • Migrating a Site? Here are some tips to keep in mind

    At face value, moving a site from one host to another may seem pretty straightforward. Depending on what kind of site you’re talking about, this could be a bigger task than you’d expect. I just recently moved a site to a new host and ended up learning a few tricks that could hopefully help you down the road. To begin you’re going to need some basic access to the site in question. In my example, I’ll just be focusing on a WordPress site. A lot of these concepts and ideas can be carried over and applied to different sites of course, but there are some WordPress specific things to keep in mind when it comes to migration. WordPress can be a little, shall we say… “WordPressy”.

    Step 1: Buy Hosting

    This one may seem pretty obvious, but you’re going to want to secure some hosting in order to transfer your site to… well, somewhere. There are a few things to consider when going for hosting, and the type of site you’re migrating is going to have everything to do with the type of hosting you choose. If you’re migrating a WordPress site, then it would definitely make sense to go with a host that specializes in WordPress hosting. If you’re moving a site that is absolutely mission-critical and cannot afford any downtime whatsoever, then you’ll probably want to consider some dedicated hosting. Dedicated meaning you’re the only one on that server. If it’s more of a lightweight site that doesn’t demand a lot of resources, or if it’s more of a recreational site that’s just for fun, or if it’s just an experiment or something, then shared hosting makes more sense. Point being, get some hosting for your site, so you’ll be ready to start the migration.

    Step 2: Consider the Site’s Needs

    This kinda goes hand-in-hand with considering the type of hosting your site needs, but this step will focus more on what exactly the site in question is doing. What purpose does this site serve? Is it a blog? Is it a portfolio? Is it an e-commerce shop? Those questions will determine your next steps and how you should move forward.

    Once you’ve answered that first question, you’ll need to think about this: What is currently happening on the site that will need to continue happening? For example, if this is an e-commerce shop, are there active customers with a purchase history? Are there active subscriptions with a regular, automated renewal date? Think about all the stuff that will continue to happen on that site as time goes on.

    Step 3: Make a Full Copy of the Site

    There are quite a few variations and sub-steps associated with this step, but the main objective is to make a full copy of the entire folder structure of the site all the way to the root directory, as well as exporting a full copy of the database. Those steps look different for different websites, but those main concepts remain the same.

    For this example, we’ll focus on a WordPress shop. If you’re migrating to WPEngine, they make a great little plugin that does all the heavy lifting for you. Else, if you’re migrating to another host, doing a manual migration isn’t awful, but there are some critical things you’ll need to keep in mind to keep everything working and minimize downtime. However, just keep in mind, as a general rule, any migration of any kind will absolutely result in some downtime at the very least. The trick is to minimize that downtime and perform the migration at an off-hour when traffic is at the lowest.

    Step 3a: Export Your Database(s)

    If your current hosting provider gives you access to a cPanel, then you’re in business. From cPanel, navigate to PHPmyadmin, select your database(s), and export. If you’re working with MongoDB or another database, I’m not gonna lie, I’ve not exported databases from MongoDB before, but I’m sure it’s nothing StackOverflow can’t handle.

    Step 3b: Download Your Folder Structure

    Next, log into your backend via your favorite FTP client, and download your entire folder structure.

    Step 4: Create an Empty Database and Assign User

    If your new hosting provider gives you access to a cPanel, then awesome. From there, you should be able to easily create a new SQL database, create a new database user and password, and assign that user all privileges. If you have a password manager, you’ll want to use it to store these database credentials. You’ll need them for later.

    Step 5: Upload Your Folder Structure

    Once you’ve purchased a hosting plan with your preferred provider, you’ll have access to the server via some protocol (likely FTP or SFTP). Once you have a username and password for your FTP connection, go ahead and log in, and begin uploading the folder structure you just downloaded. Depending on the size of your site, this may or may not take quite a long time.

    Step 7: Edit Your wp-config File

    Now, dive into your wp-config file and modify the lines that define your database name, the database user, and the database password.

    define( 'DB_NAME', 'your-database-name-goes-here' );
    define( 'DB_USER', 'your-database-username-goes-here' );
    define( 'DB_PASSWORD', 'your-database-password-goes-here' );

    Step 6: Import Database

    At this point, you’ll need to log into your freshly created database and choose “import”. Feed it the .sql file you received when you completed Step 3a.

    Side note: if you have issues at this step, double check your PHP settings. Sometimes, if your database is massive and/or your max_post_size, upload_max_filesize, max_execution_time settings don’t allow enough memory or time to complete the import, the import will fail. These settings can be changed in several places, one being your wp-config file, (since you’re probably already in there)

    Step 8: Update Your DNS

    Now that you have two working copies of your site on two separate servers, the next step is updating your DNS. This will point your URL to the new server. Depending on your DNS provider, this could take anywhere from 10 minutes to 24 hours. Once the DNS updates and propogates across the internet, you’re ready for the next step.

    Step 9: Assess The Situation

    At this point, you should have two working copies of the same site on two separate servers. If you’re running WordPress, there are a number of plugins (like Jetpack and WooCommerce Subscriptions) that will recognize when they are on a duplicate site. A really cool feature of a lot of these plugins is that if they detect a duplicate site, they will disable themselves on duplicate sites. This will help mitigate the risk of duplicate sites running in parallel and doing everything twice (like automatically charging subscribers when their subscription is up for renewal)

    Depending on what your site is doing (especially automated tasks), it might be a good idea to shut it down ASAP before the old server has a chance to run automated tasks in parallel with the new server.

    Step 10: Make Sure You Have a Local Copy

    Depending on how you completed Step 3a and 3b, you may already have a local copy of your site. Some site migrations can happen directly between two remote servers (for example, if you use the WPEngine plugin, you won’t have a local copy). This goes for your database as well, don’t forget your database!

    Step 11: Cleanup

    Now that you have a local copy of your site, you can safely delete the site from the old server. This will prevent any potential issues with running duplicate sites on the internet, regardless of DNS.

    matt

    February 9, 2021
    Web Design, Web Development
  • Using WP_Query() to sort datetime meta_value

    Just like the title suggests, I’ve spent the last several hours struggling with meta_query to return CPTs based on some datetime picker meta_value. Let me explain my setup.

    I’m writing a plugin that stores data from a custom_post_type for gym classes with a handful of custom fields put into place using ACF. One of those custom fields is gym_class_date which contains the output from a jQuery datetime picker. Here’s a look at my broken code:

     $today = date(‘Ymd H:i:s’);
    
     
    
    
     $MJCalendar = new WP_Query(array(
    
     ‘post_type’ => ‘gym_class’,
    
     ‘posts_per_page’ => –1,
    
     ‘meta_key’ => ‘gym_class_date’,
    
     ‘orderby’ => ‘meta_value’,
    
     ‘order’ => ‘ASC’,
    
     //only return upcoming classes, not classes in the past
    
     ‘meta_query’ => array(
    
     array(
    
     ‘key’ => ‘gym_class_date’,
    
     ‘compare’ => ‘>=’,
    
     ‘value’ => $today,
    
     )
    
     )
    
     ));
    
     
    
    
     while($MJCalendar->have_posts()) {
    
     $MJCalendar->the_post();

    When I ran the code, the resulting output was… nothing. So what gives?

    I burned an entire Sunday scratching my head over this and I finally figured it out. Here was my problem:

    ACF always stores datetime values in an EXTREMELY specific way: 'YYYY-MM-DD HH:ii:ss'. And I mean specific. Even though earlier in my code, I defined $today = date('Ymd H:i:s');… it was just wrong enough to break literally everything. Turns out, 20210116 16:37:24 does NOT equal 2021-01-16 16:37:24.

    Adding some simple dashes to my $today = date('Y-m-d H:i:s'); declaration made everything magically start working again.

    That’s gonna do it for this post, I know it’s a bit of a short one, but it took me FOREVER to figure out this stupid detail. Note to self, and hopefully to you, when you’re comparing two  datetime values with a meta_query, for Pete’s sake, make absolutely sure that your format is perfectly the exact same as the format coming from the database. Otherwise, none of your comparison operators will work.

    matt

    January 8, 2021
    Web Design, Web Development
    code, php, wordpress, wp_query()
  • Divi Visual Builder Not Loading

    Divi Visual Builder Not Loading…

    Divi Visual Builder not loading? I recently installed Divi on a new server and realized that in doing so, I strangely couldn’t access the Divi Visual Builder anymore… The Divi Visual Builder just sat there and spun forever.

    Oh boy…

    So upon further inspection… I open up the console to see what was going on. To my surprise (or maybe unsurprisingly?) there were TONS of errors in the log. All of them were, in one way or another, pointing to the fact that:

    uncaught reference error: jQuery undefined

    jQuery undefined? What gives? The WordPress Core comes bundled with tons of JavaScript libraries… jQuery being one of them. So why can’t it be found?

    One solution suggested on the web was heading over to the Divi theme options and enabling the classic editor. Apparently there were a few issues with the transition to WordPress 5.0, the new Gutenberg editor, and compatibility with Divi… I haven’t experienced any issues since the transition to 5.0, but you can check out more info on that topic here.

    However, for my situation, enabling/disabling the classic editor didn’t work for me. I was still missing jQuery either way, and the Visual Builder was still just….

    Yeah.

    So here’s the solution that worked for me

    In my particular situation… I was running traffic to my WordPress server through Cloudflare. Not everyone does this, and it’s not always the source of many problems, but for this particular case, it was the issue for me.

    Inside my Cloudflare settings, I went to the Speed tab at the top:

    Then click ‘Optimization’ below that:

    And scroll about halfway down the page, and make sure that the Rocket Loader setting is disabled.

    After that, I was able to refresh my WordPress site, click ‘Enable Divi Builder’ and voila!

    Hope that helps! If you’re interested, check out more random solutions to random problems by visiting the rest of my blog

    matt

    September 27, 2020
    Web Design, Web Development
    cloudflare, divi, theme, wordpress
  • How to Set Up a Raspberry Pi Development Server

    How to Set Up a Raspberry Pi Development Server

    Starting with a fresh install of Raspian:

    sudo apt update

    sudo apt upgrade

    sudo apt install apache2

    sudo apt install php

    sudo apt install mysql-server php-mysql (mariadb-10.0)

    sudo apt-get install certbot python-certbot-apache
    sudo certbot --apache

    Next, you just set up your MariaDB database and install WordPress.

    cd /var/www/html

    sudo rm *

    sudo wget http://wordpress.org/latest.tar.gz

    sudo tar xzf latest.tar.gz

    sudo mv wordpress/* .

    sudo rm -rf wordpress latest.tar.gz

    Give Apache access to the WordPress folders and files:

    sudo chown -R www-data: .

    Set up MySQL/MariaDB:

    sudo mysql_secure_installation

    You will be asked to Enter current password for root (enter for none): Since we’re only setting this server up for testing and development purposes on a local network, I’ll go ahead and enter my root password. In a production environment, you’ll definitely want a strong DB password, different than the root password.

    Next, you’ll see something like, you've alredy set a root password, so there's no need to update it (but you can still update it here if you like) press enter.

    Remove anonymous users : y

    Disallow root login remotely : y

    Remove test database and access to it : y

    Reload privilege tables now : y

    You should see: All done! Thanks for using MariaDB!

    Create a WordPress Database

    sudo mysql -uroot -p then enter your root password (or DB password if you set it up differently in the mysql_secure_installation command.)

    Next you’ll see the Maria DB shell. Your prompt will look like MariaDB [(none)]>. Create a new database named wordpress

    create database wordpress;

    Mind the semicolon- it’s required.

    If this was successful, you’ll see Query OK, 1 row affected (0.00 sec)

    No you can grant DB privileges to root. Replace PASSWORDGOESHERE with your password.

    GRANT ALL PRIVILEGES ON wordpress.* TO 'root'@'localhost' IDENTIFIED BY 'PASSWORDGOESHERE';

    FLUSH PRIVILEGES;

    Exit with CTRL + D

    Come up with a name for your dev server

    I’ll be using deadpool3.com as my example.

    Note: At the time of this writing, I own deadpool3.com, but you can use literally any URL you want. You don’t have to own it. (I think google.com may be an exception. They’ve got some fancy code going on and I wasn’t able to get my /etc/hosts to cooperate in my testing.) More on that in a sec.

    Configure static IP address

    Next, set your static IP address. You can do this by editing one file. Open it by typing sudo nano /etc/dhcpcd.conf

    Inside the file (I made a comment above these lines, so I know what I typed if I open this file again later) add the following lines:

    #Matt's static IP configuration:
    interface wlan0
    static ip_address=192.168.1.111/24
    static ip6_address=fd51:42f8:caae:d92e::ff/64
    static routers=192.168.1.1
    static domain_name_servers=192.168.1.1 8.8.8.8 fd51:42f8:caae:d92e::1

    So in my case, I made my static IP address 192.168.1.111. Double check your router and network settings for an acceptable range of IP addresses to choose from.

    Configure /etc/hosts file on your laptop

    Note: You’ll have to edit the /etc/hosts file for every computer on your local network that you’ll be accessing your dev server from. In most home network dev server setups, this will just be a single computer.

    Drop the following line at the very bottom of the file ON YOUR LAPTOP or DESKTOP and be sure to replace the IP address with the static IP you just configured in the previous step:

    sudo nano /etc/hosts

    ## Raspberry Pi Server Address ##
    192.168.1.111 deadpool3.com

    WordPress Configuration

    You can either leave your keyboard/mouse/monitor plugged into your pi, and go to localhost in a browser, or grab a different computer on your local network and go to the domain name you set up in /etc/hosts. In my case, it’s deadpool3.com. You should see the WordPress setup screen like this:

    • Choose your language
    • Click Let’s go!

    Fill out your DB information:

    Database Name:      wordpress
    User Name:          root
    Password:           <YOUR PASSWORD>
    Database Host:      localhost
    Table Prefix:       wp_

    Click ‘Submit’ and ‘Run the install’.

    Once you’re finished, drop into Settings > Permalinks. Select ‘Post name’ and hit ‘Save Changes’

    Configure SSL Encryption

    sudo apt install openssl

    Create a root key that will be able to generate ssl certs. You can do this by running: mkdir ~/SSLcerts && cd SSLcerts and then openssl genrsa -des3 -out rootCA.key 2048

    Create a root certificate by running openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.pem

    Now you’ll need to trust your root CA on every machine you’ll be accessing the server with. To do this, you’ll need to copy the rootCA.pem file to your SSL trusted certs directory on every machine on your local network.

    sudo scp [email protected]:/home/pi/SSLcerts/rootCA.pem /etc/ssl/certs

    Next, create an OpenSSL configuration file for us to use with our server. sudo nano ~/SSLcerts/deadpool3.com.csr.cnf and paste the following into that file, and save.

    [req]
    default_bits = 2048
    prompt = no
    default_md = sha256
    distinguished_name = dn
    
    [dn]
    C=US
    ST=RandomState
    L=RandomCity
    O=RandomOrganization
    OU=RandomOrganizationUnit
    [email protected]
    CN = deadpool3.com

    Next, create a file called v3.ext and paste some more code into it. This will allow us to create a public certificate file.

    sudo nano ~/SSLcerts/v3.ext and pasted the following:

    authorityKeyIdentifier=keyid,issuer
    basicConstraints=CA:FALSE
    keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
    subjectAltName = @alt_names
    
    [alt_names]
    DNS.1 = deadpool3.com

    Next, we’ll use the configuration options we pasted into deadpool3.csr.cnf to create a key file for deadpool3.com. To do this, type: openssl req -new -sha256 -nodes -out deadpool3.com.csr -newkey rsa:2048 -keyout deadpool3.com.key -config <( cat deadpool3.csr.cnf )

    Next we need a domain certificate:

    openssl x509 -req -in deadpool3.com.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out deadpool3.com.crt -days 500 -sha256 -extfile v3.ext

    That’s all the files we need to make! Lastly, we need to move the .key and .crt files into a directory where apache2 can access them. In that case, I’m just ging to create a new file in my apache2 root directory like so: sudo mkdir /etc/apache2/ssl

    Next, just copy them over. sudo cp ~/SSLcerts/{deadpool3.com.key,deadpool3.crt} /etc/apache2/ssl

    And that’s SSL certs generated! Done!

    Next, you’ll need to tell Apache where those new SSL keys and certs are. To do this, you’ll need to modify the <VirtualHosts> file. By default, you should have one file named /etc/apache2/sites-enabled/000-default.conf. We’ll use this as a template. sudo cp /etc/apache2/sites-enabled/000-default.conf /etc/apache2/sites-enabled/deadpool3.com.conf

    We’ll want to change a few things and add some stuff. At the very top, inside the <VirtualHost> tag, you’ll want to change the port number to 443. Next we’ll add the following to line 2 (above the very first commented out line):

    sudo nano /etc/apache2/sites-enabled/deadpool3.com.conf

    No add these lines just below the opening <VirtualHost> tag

    #Custom SSL setup
    SSLEngine On
    SSLCertificateFile /etc/apache2/ssl/deadpool3.crt
    SSLCertificateKeyFile /etc/apache2/ssl/deadpool3.com.key

    Next, remove the comment (#) in front of ServerName and replace www.example.com with your server name (in my case, www.deadpool3.com). The remaining defaults should do fine for our purposes.

    So at the end, your <VirtualHost> file should look something like this:

    <VirtualHost *:443>
    	#Custom SSL setup
    	SSLEngine On
    	SSLCertificateFile /etc/apache2/ssl/deadpool3.crt
    	SSLCertificateKeyFile /etc/apache2/ssl/deadpool3.com.key
    	
    	
    	# The ServerName directive sets the request scheme, hostname, and port that
    	# the server uses to identify itself. This is used when creating
    	# redirection URLs. In the context of virtual hosts, the ServerName
    	# specifies what hostname must appear in the request's Host: header to
    	# match this virtual host. For the default virtual host (this file) this
    	# value is not decisive as it is used as  last resort to host regardless.
    	# However, you must set it for any further virtual host explicitly.
    	ServerName www.deadpool3.com
    
    	ServerAdmin webmaster@localhost
    	DocumentRoot /var/www/html
    
    	# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
    	# error, crit, alert, emerg.
    	# I t is also possible to configure the loglevel for particular
    	# modules, e.g.
    	#LogLevel info ssl:warn
    
    	ErrorLog ${APACHE_LOG_DIR}/error.log
    	CustomLog ${APACHE_LOG_DIR}/access.log combined
    
    	# For most configureation files from conf-available/, which are
    	# enabled or disabled at a global level, it is possible to
    	# include a line for only one particular virtual host. For example the
    	# following line enables the CGI configuration for this only
    	# after it has been globally disabled with "a2disconf".
    	#Include conf-available/serve-cgi-bin.conf
    </VirtualHost>
    

    Next, we’ll need to take a look at the master apache2.conf file. sudo nano /etc/apache2/apache2.conf. This is a super well-commented out file, so it should be largely self-explanatory. We’re going to scroll down until we find the <Directory> tag for /var/www/. Make sure that the AllowOverride parameter is set to All. Your <Directory> tag should look something like this:

    <Directory /var/www/>
    	Options Indexes FollowSymLinks
    	AllowOverride All
    	Require all granted
    </Directory>

    sudo a2enmod rewrite

    sudo a2enmod ssl

    sudo systemctl restart apache2

    Other helpful resources

    https://www.freecodecamp.org/news/how-to-get-https-working-on-your-local-development-environment-in-5-minutes-7af615770eec/

    https://github.com/dakshshah96/local-cert-generator/

    Oh wow https://www.selfsignedcertificate.com/

    SUPER Apache2 guide: https://www.dedoimedo.com/computers/www.dedoimedo.com-apache-web-server-lm.pdf

    matt

    July 10, 2020
    General Computing, Web Development
    servers, web design, web development
Previous Page
1 2 3
Next Page

Prove all things; hold fast that which is good. 1 Thess 5:21