Core Functionality Plugin

A WordPress theme should only contain that which relates to the look and feel of the site. Any core functionality belongs in a plugin.

A good rule-of-thumb is that anything a user would expect to keep after changing themes belongs in a plugin. This includes custom post types, taxonomies, custom metaboxes, shortcodes, and customizations to other plugins (like my Display Posts Shortcode snippets).

For specific functionality that’s reusable and/or the client might want to selectively disable, it’s best to build as its own plugin, like BE Events Calendar.

For everything else that’s project-specific but should be theme-independent, I put in a plugin called Core Functionality. Feel free use this as a starting point for your own core functionality plugin.

See my Core Functionality Plugin on GitHub

Click here

Bill Erickson

Bill Erickson is the co-founder and lead developer at CultivateWP, a WordPress agency focusing on high performance sites for web publishers.

About Me
Ready to upgrade your website?

I build custom WordPress websites that look great and are easy to manage.

Let's Talk

Reader Interactions

Comments are closed. Continue the conversation with me on Twitter: @billerickson


    • Bill Erickson says

      Yep, I do this as well. The only issue is mu-plugins doesn’t look within folders. So instead of dropping /core-functionality in there, You have to drop the contents of your core functionality plugin directly in the mu-plugins directory.

      • Remkus says

        You can of course include any additional folders / files from that one plugin file in the /mu-plugins/ folder

  1. Doak Heggeness says

    I enjoy your site. I have used your rotator and ‘Rotator Options’ metabox before, so I thought I would give your plugin a try. Sounds like a really good idea. I used your child theme and plugin. The rotator metabox loads and the ‘Instructions’ are saved but do not display with the ‘Featured Image’ on my localhost. I do not want to waste your time, and I do not have the time to look into it further, but I thought at least I should say something. I reinstalled it and got the same result.

    Keep On Trucking!

    • Bill Erickson says

      Make sure the field ID’s you’re saving are the same that the rotator is pulling.

      WP Rotator uses wp_rotator_url and wp_rotator_show_info for custom field names. The Custom Functionality plugin has be_rotator_url and be_rotator_show_info.

      This is just sample data and isn’t designed specifically to work with WP Rotator. But if you change be_ to wp_ it will.

  2. Govertz says

    About MU-plugins, it is possible to use a folder for each plugin.If you make an include file in your MU-plugins folder.

    Here is the snippet, I’m not sure about how to list code, so I have excluded the tags.

    include (‘plugin_folder_name/file_name.php’);

    • Bill Erickson says

      Yep, that’s definitely an option. But the way I look at it, the plugin.php file in /core-functionality does exactly that. It simply includes all the relevant files. So I drop plugin.php in /mu-plugins which just includes all my files, and everything else is in /mu-plugins/lib

  3. Cathy Tibbles says

    THANK YOU for sharing this!! I’m just learning to clean up my functions files and this is going to help A LOT!!

  4. Jason Day says

    Great points. I get frustrated with the direction themes seem to be taking, where a ton of functionality is written directly into the theme. And frequently, it’s hard to tease out the functionality due to pieces being in various places – page template, functions.php, header.php, etc. Woothemes makes great themes, but I don’t understand why they don’t create plugins a la faultpress, wikeasi, supportpress, etc. Additionally, they created a decent framework/theme, but haven’t based any of there own themes on that framework. I appreciate you sharing this, as I think this gives a good basis and maybe a step in the right direction for theme developers.

  5. Jon Breitenbucher says

    Really nice post Bill. If I might, how do you handle things like single-{post-type}.php, archive-{post-type}.php, taxonomy-{taxonomy}.php. I had thought about moving my custom post-types and taxonomies to a core functionality plugin, but was unsure how to handle these templates since they would be dependent on the core functionality plugin.

    Also, the mu-plugins idea doesn’t work so well for a network environment where not all sites require the extra functionality.

    • Bill Erickson says

      The registering of the custom post types and taxonomies belong in the functionality plugin, but their display (the template files) belong in the theme. Besides there not being an easy way to package theme files in a plugin, the idea is that if you change themes you’d need to change those theme files as well.

      I don’t work on multisite websites, so that’s not an issue for me 🙂

      • Jon Breitenbucher says

        That is kind of what I concluded from my investigations.

        I maintain four network installs. All for the same university. 🙁

  6. Dorian Speed says

    Hi, Bill – just wanted to thank you for this and your other post on Custom Post Types. What you’ve described about a core functionality plugin makes a lot of sense and I’d never thought about it before. I’m about to start experimenting with Custom Post Types for the first time and happened upon your site – great instructions and advice.

  7. Richard Buff says

    How come there are no shortcodes listed in I always use the url, wpurl, and child shortcodes that I learned from your site and include them in every project. I recently switched to using a Core Functionality plugin (which I also first heard of on your site) for non-theme related things and I just added a shortcodes.php file to the /lib/functions folder. Is that how you do it when you add shortcodes for a client site?

    • Bill Erickson says

      If shortcodes are required, I create a file in /lib/functions/shortcodes.php.

      A long time ago I used the url, wpurl, and child shortcodes in sidebar widgets because my find/replace of URLs when migrating didn’t work on serialized arrays (widget content is stored as a serialized array). Now that I use this approach, I use actual URLs instead of shortcodes everywhere. I no longer need those three shortcodes.

  8. Joe Alberts says

    Thanks for this idea!

    I was curious though; how do you flush the rewrite rules cache when you make CPTs this way? Must Use plugins don’t respond to activation hooks, which is what appears to be the normal method. Do you just go to Settings > Permalinks after you make your CPTs? Calling that page up seems to force a refresh (you stop getting 404s on newly created CPT posts after).

    • Bill Erickson says

      Yes, I go to Settings > Permalinks to flush the rewrite rules. Since this is a plugin developed for a specific client, and I’m the one who’s implementing it for them, I don’t have to worry about the rewrite rules being flushed (the client never activates/deactivates it).

      Thanks for the reminder. I updated the post above to indicate I no longer use must-use plugins for this and why.

      • Joe Alberts says

        Thanks for the reply and update. You make some fair points rationalizing not using this any longer. The first is the most compelling for me.

        I assume you just chunk this out into a regular old plugin then?