Please take a moment to read over some guidelines we use while developing on TownSites.
Code Formatting
Casing
The only universal standard to naming conventions in programming is that there is no standard. However, here are the ones we use, for reference:
- PHP variables, functions and properties:
snake_case
- JavaScript variables, functions and properties:
camelCase
- PHP and JavaScript classes:
PascalCase
- File and folder names:
kabab-case
- HTML/CSS classes, IDs and attributes:
kabab-case
Indentation
If you’re looking to keep formatting consistency across the platform, TownSites’ code formatting looks similar to this:
// An function demonstrating 1TBS indentation, in which brackets share the same line as the statement:
function myFunction() { // Comments can go on the same line as the bracket
if (myVariable) { // Indents use 4 spaces
doSomething();
} else {
while (myOtherVariable == true) doAnotherThing();
// ↑ An example of a one-line statement. Long comments can also be formatted like this
}
}
Please opt for descriptive variable names whenever possible.
WordPress Themes
We use the Divi theme on both TownSites Main and TownSites Primary, extended with a child theme (named divi-child
). This both allows our customers to use the Divi Builder to customize their TownSite and our developers to extend the TownSites’ functionality with the help of React. The React extensions to the Divi theme, should you need to create/edit them, are located in /wp-content/plugins/divi-custom-modules
. The Divi documentation for developers can be found here.
WordPress Plugins
Below is a list of notable plugins included in the TownSites Software:
Our Plugins
- Article Composer hosts the code which writes and schedules articles, social media posts, and video scripts automatically using OpenAI.
- Divi Custom Modules stores all of our extensions to the Divi Builder, most notably our Listings tool, which pulls data from other sites to place on the homepage of the TownSite.
- Rollout Tool: A very powerful plugin that eliminates hours of work by updating the entire multisite at once.
- TownSite Utilities: Functions that extend other third-party plugins are stored here.
Third-party Plugins
- MailPoet serves as the backbone of our Mailing List feature.
- Feed Them Social displays social media content on a Customer’s TownSite.
- NS Cloner is used to clone a new TownSite from the template.
- Relevanssi supplies the platform’s search functionality.
- WP-SCSS works to compile the theme’s SCSS code as soon as it is needed.
Stylesheets
We use SCSS to style our Software. The stylesheets are stored in divi-child/scss
and the WordPress plugin WP-SCSS will compile the SCSS automatically to the divi-child/css
directory as soon as it is saved. The structure for the SCSS files are as follows:
main.scss
: Variables, includes and site-wide rules for the Customer’s TownSite are stored here.dashboard-main.scss
: Variables, includes and site-wide rules for the Customer Dashboard are stored here._section.scss
: Style rules applied to Divi sections, and their children._row.scss
: Style rules applied to Divi rows, and their children._blog.scss
Style rules for the Blog, Search page, and individual Posts.dashboard/
: Includes for the customer Dashboard are stored here, called fromdashboard-main.scss
.modules/
: Style rules applied to Divi modules, and their children. Some style rules for modules can also be found inmain.scss
.themes/
: Customers have the ability to change their TownSite’s theme from their dashboard. Style rules for individual themes can be found in this directory.
Frameworks
Although we use “vanilla” code by default, we do utilize a few frameworks to make things easier:
jQuery
While coding JavaScript, you will likely see IIFEs that pass in jQuery. We employ jQuery in TownSites for two reasons:
- Legibility: jQuery’s slogan is “Write less, do more,” which is exactly what we use it for. In most cases in which legibility would be improved by using a shorthand
$()
function as opposed to native JavaScript, jQuery is used and encouraged. However, it shouldn’t be abused—here are some cases in which jQuery should not be used:- Don’t use jQuery in places where it isn’t readily available. If it’s a small use case in a spot where jQuery isn’t yet defined, it’s best just to not use it. (See: You Might Not Need jQuery)
- Definitely don’t use jQuery in code that requires high amounts of reactive programming. In cases like that, such as on the Customer Dashboard, we use Vue.js instead (see below).
- Monkey Patching: With TownSites being a WordPress environment, we every so often need to manipulate an included plugin that does not offer any hooks or other means of changing the code (other than editing the plugin directly, which should never be done). In this case we have to extend the plugin at runtime by manipulating the DOM after the plugin has loaded—jQuery makes this easy to achieve with little complication. The plugin MailPoet is a good example of where this happens a lot.
Vue.js
We use Vue for programming UI elements. The Customer Dashboard, for example, has many instances of dynamically changing text which depend on JavaScript properties, similar to a web application. In those areas, a small Vue app is written to handle the instance, avoiding the many issues caused by using native JavaScript for code which is primarily reactive in nature.
React
We use React to extend and create new modules for the Divi Builder. The readme.md
file included in the divi-custom-modules
plugin has more information on how this is done.
External APIs
Via PHP cURL, TownSites utilizes API handlers and scrapers in order to connect to other websites and pull data from them. These files are written in PHP and stored in /wp-content/themes/divi-child/handlers
. They typically consist of a class, followed by WordPress hooks. We use wp-ajax to call these handlers via AJAX on the client side. Please follow this format when creating a new or building on an existing API handler.
Annotation
All code should be immediately understandable. Please comment your functions and any other other code that may not be easily readable by another developer. When writing PHP, make use of PHPDoc blocks above your functions and classes. Legibility is crucial when writing your code, as the absence of it can cause disconnects and delays.
You can also use the // MARK:
or ////
tags to mark sections of code in a file.
Additionally, when creating a new plugin or directory, it is good practice to include a readme.md
file that includes a summary of the code written, descriptions of important and critical files, and any other tribal knowledge needed to change the code’s functionality.
Other Notes
WordPress Hooks: Almost all custom code is embedded within a WordPress hook that ensures it is fired at the correct time. Within plugins and classes Hooks and actions are generally stored in a functions.php
or {plugin-name}.php
file that branch off using include()
calls.
Function names generally start with a prefix mirrored by the other functions in a theme/plugin. A function in the divi-child
theme may be called dich_load_color_scheme()
, for example.
Classes: Classes are used as a means to handle scoping. API files, for instance, start with a class which contains all the functions pertaining to that API, followed by a list of hooks. The class is hoisted and can be called anywhere within the Software.
JavaScript Instantiation: As a general rule, JavaScript functions are stored as object methods in a file called via a hook such as wp_enqueue_scripts
or admin_enqueue_scripts
. JavaScript variables are passed in from the server via the WordPress function wp_localize_script
.
Links: When creating hyperlinks or calling/including scripts, please use absolute links. The PHP function get_host_info()
should return all the information you need to create an absolute link. All external links should open in a new tab.
Debugging: You can debug JavaScript using the Chrome Developer Tools or the VS Code IDE (via the JavaScript Debugger extension). You can also debug PHP using XDebug; the listening port number is 9003.
Notable files:
common.php
, located in thedivi-child
theme, stores functions viewable in any file in both TownSites Main and TownSites Primary. The functionget_host_info()
, for example, can be used to get information about the current environment to ensure that your code can adapt to any environment in which it is run without errors..gitignore
is used to fence off WordPress code from our code. Should you create a new plugin, ensure that it is not blocked from being staged by a.gitignore
file.