Should you go mobile first?

The full question sounds like this:

Should you build your website/web-app mobile first and scale to desktop?

Why do we need another article about this, it has been covered a lot of times already?

To make things clearer, I’m only interested in the site structure, building the CSS around it and how it changes from one device to another. Not the PWA or other things that will take the mobile first approach and make it more like a mobile app.

It might be an obvious answer for a lot of you, but to my shame, it wasn’t for me. I didn’t see a reason to go mobile first in my approach. I’ve created lots of sites with the approach of desktop first and scaling down on mobile as I went along. We even had a full workflow where we have the desktop site ready, test it and after that, we move to mobile.

This workflow might’ve been influenced by the designers I worked with or the clients that focused on the desktop version first.

It all changed after I read Responsive Design: Patterns & Principles by Ethan Marcotte. I recommend this book if you are a web developer, especially front-end.

I was amazed by how much more can be accomplished if you have a different perspective when creating the site. And it so happened that I read it during a complex project where we had a lot of parts and elements that were structured to be re-used throughout the site.

Understand the design/project

It starts by getting a better understanding of the design or the project as a whole. You need to get as many details from the client and designer. They might think the site as page by page, but this is not true anymore. The site has pages but those pages are created by elements, and those elements are the ones that need your attention.

What is relevant for the user on a small device?

  • On your newspaper site, you want to show the featured story on mobile and have it display as the first thing, not obstructed by anything else.
  • If you have an e-commerce site you want to show the featured product(s) that are available on sale.
  • Your book author might want to have a clear way to display the next event or book signing that she’ll attend.

This means understanding your project, getting to know exactly what matters, the core of the project. On mobile, you need to be able to deliver what’s important and not just fill the screen with everything. Providing the right content will keep the user engaged with your site, and it will also help you fix performance issues.

Working with elements

As you look over you will find elements that repeat themselves on different pages.

Once you identified the elements, you can start building the components. Get those components to live in their own space and create a structure just for them.

Then get them styled not in a relationship with the page or other elements, but as a standalone unit that will be placed on a page.

Why are elements important?

First of all, it’s like working with data: you want the actual data, not for it to be wrapped into something that needs to be adjusted when you want to display it.

You want the actual value from a field. Same with elements.

You want an element that does the Featured Story for the newspaper, Product on Sale for your e-commerce, Next Event for the author, that you can re-use wherever you like.

Having elements or components that will come together on a page will help you better manage the outcome.

Mobile Content

On a mobile first approach, the content on mobile devices is specially catered for mobile. You don’t just use what it’s on desktop but on a smaller screen.

There is an important difference here because you will need to take into account the fact that people might browse on 3G connections that are not that fast. This will make every extra resource that is loaded to take some extra seconds for the end-user.

We’re getting a better understanding of how the images are delivered and if you have to just hide content or eliminate it on mobile devices.

As you’re set on creating elements/components, you have to make sure that the media files you use are correctly optimized for screen size and enable/disable certain elements on mobile altogether. Don’t load them just to hide them on mobile.

Today this is even more powerful and easy to achieve with JS frameworks like Vue.

Isn’t mobile first the same as a responsive website?

Yes and no, mostly no. It’s kind of the same thing when you talk about the methods used (you’re still using a CSS framework for example), but it has very different outcomes.

I see the responsive way of creating sites as going from big to small and with this approach comes the idea of hiding elements on certain smaller screens or just move them around to fit. Nothing wrong with this, mobile has less space to display content.

But what do you hide on mobile?

You’re now faced with a problem that you didn’t have in mind at the beginning. You’re not aware of what is vital/relevant for your user on mobile.

The mobile first approach aims to solve this issue. You’re starting the site scaling from small to big, not downgrading the content. When you start with the small screen idea in mind, you realize what is important and what must be shown on the page. It’s not just about moving the content around so it will fit.

I’m aware that responsive is the easy way to do it. When you have a site that is already in use for some while and it has traffic on it, it’s the safe step to make it responsive, move things around to fit and just remove some elements on mobile.

I would love to cover more on this subject and break each idea into an article on its own, but for now I just wanted to offer a glimpse of what I took from that amazing book.

I really recommend reading the book. it’s around 100 pages with a lot of relevant examples and solutions from the real world. It might change the way you think about your current projects.

Things to check before going live with a WordPress site

You started the project, moved along through all the revision checkpoints, your client is happy and you’re ready to move it on a live environment with the proper domain, server, and so on.

Even if the project works well on your development environment, there are a few things you might want to look over before making it live and ready to be accessed by visitors and search engine bots.

Dynamically deliver assets

On long projects or because you want to do a quick test, there might be assets that are hardcoded in your project.

Some bits might need to be hardcoded, but be sure it’s dynamically made so when you change the domain it will still work.

An example from the top of my mind is when you add a background image in CSS with the URL from WP Media Library. You want to quickly test something, the image is in Media Library and you just add it in your CSS to test.

You forget about it and when you delete the dev version of the site you end up with broken content.

Search from your IDE in the project folder after the dev URL address to be sure nothing is left in there.

Server details

In most cases, this shouldn’t be an issue if you have a good hosting company.

  • Check the PHP version on the server and what you need for everything to work properly
  • Check if there is any kind of restriction on the number of requests and files that you can have

Basically do a full run of your functionalities on the new server just to be sure no surprises appear.

Clean any test data

You tested and tested the site for all the edge cases and now it’s ready to go live.

Make sure all the test data is removed when the site goes live. Sure, some data needs to stay in there (you might have standard pages or users that should be in there), but everything else should be removed and the database to be as clean as possible.

Content ready

If you cleaned the database and removed all the extra users, posts, pages, etc, now add in the content.

Be sure the right content is on the pages before making it live, or else you risk having search engine bots crawl on your site and index pages with “Lorem ipsum” text on them – this is not very professional.

Forms functionality

In most cases, contact forms are your way to get customers or feedback. This might not seem like such an important thing, but from your client’s point of view, forms not working means the site is not functional. If this part is broken and fails on sending the message, you and your client are losing business.

For example, in Contact Form 7 (or any other contact plugin) you might need to install an SMTP or else the emails will not go out.

Of course, not only contact forms, but any other ways of gathering the data should be tested on the live environment again.

Conversion rate is very important when you invest money in promoting the site or certain landing pages. Having the potential customer landing on the page but failing the conversion part, it’s just bad business.

Security

Always keep an eye on the security details. There is no need to explain how important this is regardless of how big or small your website is or if you have other users or just the administrator.

The most important and easy things to do:

  • Change the default administrator user to something else. Usually, you get the standard “admin”, don’t stick with that.
  • Change the password to something complex. I use the WordPress auto-generated password all the time, because it’s simple and helps me not having to create a password on the spot. Your client might want something that they can remember – suggest them to be a strong password (case sensitive, numbers, symbols, all that stuff).
  • Change the default login URL for WordPress. The standard login address from WordPress can easily be targeted by bots. You should change the wp-login.php to something personalized. Don’t do this by hand (you altering the code), just use a plugin like WPS Hide Login.
  • Install a security plugin. Wordfence should do the trick, it’s easy to use and it’s very popular.

A backup system in place

Periodical backups are a must: the files and database should be backed at least once a week. You can also go for twice per week, it really depends on the site and how much activity there is on it. If the content stays pretty much the same and there are no transactions happening, then you can set a longer period between backups.

A good option is UpdraftPlus – Backup/Restore. It’s one of the most used WordPress plugins and it does the job really well.

The hosting provider might also offer a backup system, use that too if you want to be sure nothing gets lost.

Make sure search engines can access the site

When you have the WP site (or any site) in development, the robots.txt is denying access for bots on your site. Or at least that’s the way it should be.

In WordPress, there is the option of Discourage Search Engines from crawling in Settings > Reading.

You should uncheck this after you cross all the points from above. Having the robots.txt still blocking search engines will make the site invisible for potential customers.

How to easily create Custom Post Types in WordPress?

We’re going to create a more easy to manage way of generating Custom Post Types.

First of all, we’re going to create a file that we’ll call it post-types.php and place it in a folder inside your theme called ‘config’.

In post-types.php we’ll create a class that generates Custom Post Types. I’ll call it DM_Project_Post_Types.

					

<?php
class DM_Project_Post_Types {


} // End class

new DM_Project_Post_Types;

In here we create 3 fuctions: a __construct, one to define the custom post types and one that will register them.

					

<?php
class DM_Project_Post_Types {

    public function __construct() {
        
    }

    public function all_post_types() {
     
    }

    private function dm_register_post_type() {

    }


} // End class

new DM_Project_Post_Types;

In the all_post_types function we define all the custom post types that we want to use and will pass that data into the dm_register_post_types.

					

    public function all_post_types() {
        $post_types = [
            [
                'post_type' => 'director',
                'singular'  => 'Director',
                'slug'      => 'director',
            ],
            [
                'post_type' => 'photographer',
                'singular'  => 'Photographer',
                'slug'      => 'photographer',
            ],


        ];

        foreach ($post_types as $key => $post_type) {
            $this -> dm_register_post_type( $post_type );
        }
    }

If you need to add custom data for ‘plural’ or other arguments, you can add them in the all_post_types function and pass them in dm_register_post_type to be used.

And the dm_register_post_type will look like this

					

    private function dm_register_post_type( $data ) {

        $singular  = $data['singular'];
        $plural    = ( isset( $data['plural'] ) ) ? $data['plural'] : $data['singular'] . 's';
        $post_type = $data['post_type'];
        $slug      = $data['slug'];

        $labels = array(
            'name'               => _x( $plural, 'post type general name', 'dm-artillerie-theme' ),
            'singular_name'      => _x( $singular, 'post type singular name', 'dm-artillerie-theme' ),
            'menu_name'          => _x( $plural, 'admin menu', 'dm-artillerie-theme' ),
            'name_admin_bar'     => _x( $singular, 'add new on admin bar', 'dm-artillerie-theme' ),
            'add_new'            => _x( 'Add New', $singular, 'dm-artillerie-theme' ),
            'add_new_item'       => __( 'Add New ' . $singular, 'dm-artillerie-theme' ),
            'new_item'           => __( 'New ' . $singular, 'dm-artillerie-theme' ),
            'edit_item'          => __( 'Edit ' . $singular, 'dm-artillerie-theme' ),
            'view_item'          => __( 'View ' . $singular, 'dm-artillerie-theme' ),
            'all_items'          => __( 'All ' . $plural, 'dm-artillerie-theme' ),
            'search_items'       => __( 'Search ' . $plural, 'dm-artillerie-theme' ),
            'parent_item_colon'  => __( 'Parent ' . $plural . ':', 'dm-artillerie-theme' ),
            'not_found'          => __( 'No ' . $plural . ' found.', 'dm-artillerie-theme' ),
            'not_found_in_trash' => __( 'No ' . $plural . ' found in Trash.', 'dm-artillerie-theme' )
        );

        $args = array(
            'labels'             => $labels,
            'description'        => __( $singular .'.', 'dm-artillerie-theme' ),
            'public'             => true,
            'publicly_queryable' => true,
            'show_ui'            => true,
            'show_in_menu'       => true,
            'query_var'          => true,
            'rewrite'            => array( 'slug' => $slug ),
            'capability_type'    => 'post',
            'has_archive'        => false,
            'hierarchical'       => false,
            'menu_position'      => null,
            'supports'           => array( 'title', 'author', 'thumbnail', 'excerpt', 'comments' )
        );

        register_post_type( $post_type, $args );

    }

By default I added a $plural variable that will just add an ‘s’ at the end of the custom post type single in case you don’t define a plural in all_post_types.

If you want to do a small adjustment you can also define a variable from ‘textdomain’. In my case that is ‘dm-artillerie-theme’ and it’s hardcoded in there.

Now in the __construct we make sure to init the all_post_types function

					

    public function __construct() {
        add_action( 'init', array( $this, 'all_post_types' ) );
    }

Your final code in the post-types.php file should look like this:

					

<?php
class DM_Project_Post_Types {

    public function __construct() {
        add_action( 'init', array( $this, 'all_post_types' ) );
    }

    public function all_post_types() {
        $post_types = [
            [
                'post_type' => 'director',
                'singular'  => 'Director',
                'slug'      => 'director',
            ],
            [
                'post_type' => 'photographer',
                'singular'  => 'Photographer',
                'slug'      => 'photographer',
            ],


        ];

        foreach ($post_types as $key => $post_type) {
            $this -> dm_register_post_type( $post_type );
        }
    }

    private function dm_register_post_type( $data ) {

        $singular  = $data['singular'];
        $plural    = ( isset( $data['plural'] ) ) ? $data['plural'] : $data['singular'] . 's';
        $post_type = $data['post_type'];
        $slug      = $data['slug'];

        $labels = array(
            'name'               => _x( $plural, 'post type general name', 'dm-artillerie-theme' ),
            'singular_name'      => _x( $singular, 'post type singular name', 'dm-artillerie-theme' ),
            'menu_name'          => _x( $plural, 'admin menu', 'dm-artillerie-theme' ),
            'name_admin_bar'     => _x( $singular, 'add new on admin bar', 'dm-artillerie-theme' ),
            'add_new'            => _x( 'Add New', $singular, 'dm-artillerie-theme' ),
            'add_new_item'       => __( 'Add New ' . $singular, 'dm-artillerie-theme' ),
            'new_item'           => __( 'New ' . $singular, 'dm-artillerie-theme' ),
            'edit_item'          => __( 'Edit ' . $singular, 'dm-artillerie-theme' ),
            'view_item'          => __( 'View ' . $singular, 'dm-artillerie-theme' ),
            'all_items'          => __( 'All ' . $plural, 'dm-artillerie-theme' ),
            'search_items'       => __( 'Search ' . $plural, 'dm-artillerie-theme' ),
            'parent_item_colon'  => __( 'Parent ' . $plural . ':', 'dm-artillerie-theme' ),
            'not_found'          => __( 'No ' . $plural . ' found.', 'dm-artillerie-theme' ),
            'not_found_in_trash' => __( 'No ' . $plural . ' found in Trash.', 'dm-artillerie-theme' )
        );

        $args = array(
            'labels'             => $labels,
            'description'        => __( $singular .'.', 'dm-artillerie-theme' ),
            'public'             => true,
            'publicly_queryable' => true,
            'show_ui'            => true,
            'show_in_menu'       => true,
            'query_var'          => true,
            'rewrite'            => array( 'slug' => $slug ),
            'capability_type'    => 'post',
            'has_archive'        => false,
            'hierarchical'       => false,
            'menu_position'      => null,
            'supports'           => array( 'title', 'author', 'thumbnail', 'excerpt', 'comments' )
        );

        register_post_type( $post_type, $args );

    }


} // End class

new DM_Project_Post_Types;

Now in functions.php add the PHP file that you just worked on:

					

require_once('config/post-types.php');

You will be able to generate as many custom post types you want and control the aspect of each of them without repeating the code. You also endup with a clean functions.php file and it will be easier to read in the future.

You can use this approach on other customizations that you’re doing on the site, creating a separate PHP file and call them from inside functions.php.