Kalamuna's WordPress Starter that is being used internally to spin up new projects quickly.
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Contributors: Kalamuna
- Features
- Comes Packed With
- Rational
- Who is This For?
- Before You Start
- Getting Started
- 🥋 Conventions
- Config Folder
- Inc Folder Structure
-
🔥 Hybrid approach to theme building which leverages the best of both worlds:
modern classic PHP + Gutenberg blocks and templates
-
💤 Easily builds and compiles the assets using @wordpress/scripts
-
📂 Sane, modular folder structure for assets, templates, and classes
-
📦 Separate compilation of theme, editor, admin, and blocks CSS and JS, with the ability to toggle the enqueue of the built assets on/off
-
👍 Composer autoloading for classes and namespaces across the files
-
🔌 Dealing mostly with configuration files to turn stuff on or off
- Modern PHP
- Modern CSS (SASS)
- Modern JS (ES6+)
- Modern tooling for compiling assets
- Linting
- Testing
- Extensive documentation
- Set of pre-made blocks
- Set of pre-made templates
- Set of pre-made patterns
Work with WordPress, not against it.
KalaPress serves as a starter hybrid theme for Kalamuna’s clients. KalaPress is open source and built with the same tools that WordPress developers use every day: Gutenberg, CSS/SASS, JavaScript, and HTML. It is lightweight and as simple to maintain and use as possible, is easy to get started with, and compiles very quickly for everyday use.
Our thoughtful, integrated approach makes it easy to integrate unique branding into patterns, blocks, and elements that enhance the WordPress experience. This “Guided Design” approach to content development means the site can grow and evolve over time without losing what makes it unique. By leveraging the Gutenberg editor we can provide freedom and flexibility to front-line content entry people while ensuring the overall site remains consistent and on-brand.
❗Intermediate to advanced-level WordPress developers working either singly or as part of an agency.
Knowledge of SASS, NPM, and theme.json are helpful and to some extent necessary.
It is intended to be a starting point for easily building client-specific sites.
KalaPress is provided on an as-is basis 🤷 in the state Kalamuna uses in their day-to-day workflow. It is a work in progress as standards and practices change. We provide it publicly as a service to the open source community but provide no guarantees or warranties for its use.
We are constantly working and contributing to this repo to make it as straightforward and easy to use and possible. If you have any questions or suggestions, please feel free to open an issue or submit a pull request.
⛔ You occasionally may find some redundant and non-working code in the theme.
We are working on cleaning it up and creating an extensive documentation for it. Note that this theme has been converted from a fully classic theme into a hybrid one with a more modern way of handling things. there are parts that are in place from the previous development efforts, and will be removed soon.
- WordPress >= 6.2.0, tested up to 6.3.2
- PHP >= 7.4
- composer >= 2.0.0
- node >= 16.0.0
- Advanced Custom Fields >= 6.0
- NOTE: We use ACF Pro in our projects and love it. The theme currently uses ACF for some of its functionality. The public version of KalaPress is just born and we are converting from an older setup. This dependency will be removed in the future and made optional. For now, some parts will not work without ACF.
KalaPress requires PHP & Composer to be installed, or you need to have a local environment that provides them for you like Lando, DDEV, Local by Flywheel, MAMP, XAMPP, etc. You also need Node and NPM installed.
-
Either download the ZIP file from the repo or clone it into your local wp-content/themes directory.
-
In the KalaPress folder, run
composer install
.- If you don't do that an admin notice in the WordPress dashboard will remind you to do so.
-
Choose & activate the theme in the WordPress Dashboard.
-
Once the theme is installed, the following sections describe how to monitor and compile the theme for use.
All of the files in the inc
, Core
, and Config
directories as well as the functions.php
file are and MUST BE namespaced.
Returns the fully qualified name of the function and mostly used in add_action and add_filter like
add_action( 'init', space( 'my_hooked_function_into_wp' ) );
This is a MUST to do any time when you want to hook into WordPress' actions and filters. Otherwise, you will get a fatal error something like
Fatal error: Uncaught Error: call_user_func_array(): Argument #1 ($callback) must be a valid callback
Generally, it's recommended to have each .php file dedicated to a single function or action, and the name of the file should align with the function it contains, using hyphens instead of underscores in the file name.
So, as and example, if you have a function named register_block_pattern_categories() {...}
, it should be placed in a file called register-block-pattern-categories.php
, which is then stored in a suitable sub-directory within /inc.
When adding a new functionality or module (except blocks of course), in almost all other cases, they should reside inside the /inc
directory and be namespaced.
This includes custom post types, taxonomies, template-tags, shortcodes, etc. The inc folder is structured for easy organization and maintenance. none of the files that are placed in the inc folder, are loaded by default and all of them must be mentioned inside the respective config classes in the Config
directory.
The Config
folder, as the name suggests, contains all the configuration classes for the theme.
Config/
├── AssetsConfig.php
├── BlockCategoriesConfig.php
├── BlockPatternCategoriesConfig.php
├── BlocksConfig.php
├── BlockStylesConfig.php
├── IncludedFunctionsConfig.php
├── PostTypesConfig.php
└── TaxonomiesConfig.php
This class is responsible for loading the theme's assets like CSS and JS files. It also has the ability to load the assets in the admin area and the editor area separately.
This class is responsible for registering the block categories in the editor. It also has the ability to re-order the block categories in the editor so that your custom categories appear at the top.
💠 3. BlockPatternCategoriesConfig.php: This class is responsible for registering the block pattern categories in the editor.
This is under construction. for now use the inc/functions/register-block-pattern-categories.php
file to register block pattern categories.
This class is responsible for including the Custom blocks in the editor. A block is not recognized by WordPress unless the name is mentioned in the config array in this class.
This class is responsible for including the block styles in the editor. Read the comments inside the class for more information.
This class is responsible for loading the theme's included functions. It looks at the inc folder's sub-directories (except post-types and taxonomies) and loads the files inside them who are present in the array. Read the note below.
This class is responsible for including the custom post types. There is a very important documentation inside the class that explains how to add a new post type. Please read that carefully.
This class is responsible for including the custom taxonomies. There is a very important documentation inside the class that explains how to add a new taxonomy. Please read that carefully.
❕ NOTE:
When adding a new module or functionality in the inc
directory, you need to mention that new file inside the respective config class.
For example, if you are adding a new custom post type, you need to mention that file inside the PostTypesConfig
class inside the configuration array. This is how the theme knows about the new file and loads it.
❕ NOTE:
There is extensive documentation inside the Config
classes that explains with examples how to that specific config class works. Please read those comments carefully.
As a todo item, we are working to add those comments to the documentation here as well.
Here is where you put theme's essential PHP files, neatly categorized into different directories for efficient organization and easier maintenance. Each sub-directory serves a specific purpose:
Place your custom post type declarations here. Example files like faqs.php and team_member.php which define custom post types for FAQs and team members, respectively.
- You then go ahead and add the file name into the
PostTypesConfig
class inside theConfig
directory. - Please carefully read the comments inside the
PostTypesConfig
class for more information.
This is where you define custom taxonomies. For instance, faq_types.php might contain definitions for different FAQ categories or types.
- You then go ahead and add the file name into the
TaxonomiesConfig
class inside theConfig
directory. - Please carefully read the comments inside the
TaxonomiesConfig
class for more information.
This directory contains PHP files for various theme functionalities. For example: body-classes.php
for adding custom classes to the body tag.
- You then go ahead and add the file name into the
IncludedFunctionsConfig
class inside theConfig
directory.
A collection of PHP functions used in your theme templates to keep your code DRY. These might include functions to display breadcrumbs, custom menus, post metadata, etc.
- You then go ahead and add the file name into the
IncludedFunctionsConfig
class inside theConfig
directory.
Use this to store any modifications or customizations related to plugins. start the file name with the plugin name and then add the functionality name. For example, yoast-remove-page-source-comments.php
removes the source comments from the Yoast SEO plugin. Sticking to this naming convention will help you quickly find the file you need in the future.
- You then go ahead and add the file name into the
IncludedFunctionsConfig
class inside theConfig
directory.
Store any custom shortcode definitions in this directory (I mean if you are still using that). The .gitkeep file helps keep this directory in your repository even when no shortcodes are defined yet.
- You then go ahead and add the file name into the
IncludedFunctionsConfig
class inside theConfig
directory.
This directory is reserved for any WooCommerce-specific customizations or overrides. The .gitkeep file is there to keep the directory in your project until you add WooCommerce-related files.
- You then go ahead and add the file name into the
IncludedFunctionsConfig
class inside theConfig
directory.
You can create any other directories that make sense for your project. For instance, you might create a directory called inc/acf-fields/
to store your ACF field definitions.
- You then go ahead and add the file name into the
IncludedFunctionsConfig
class inside theConfig
directory.
/inc
├── post-types
│ ├── faqs.php
│ └── team_member.php
├── taxonomies
│ └── faq_types.php
│ ├── ...
│ └── ...
├── functions
│ ├── body-classes.php
│ ├── ...
│ └── ...
├── template-tags
│ ├── display-breadcrumbs.php
│ └── display-posted-on.php
├── plugins
│ ├── yoast-keep-metabox-collapsed.php
│ ├── yoast-remove-page-source-comments.php
│ ├── gravity-forms-add-signature-field.php
│ └── ...
├── shortcodes
│ └── .gitkeep
└── woocommerce
└── modify-checkout-fields.php
NPM is used to compile all SCSS, minify JS/CSS, and optimize images. Here are some helpful commands.
In the terminal, go to /wp-content/themes/kalapress
and run npm install
. This will install all the necessary node modules to do the various commands. You only need to do this once, when you first setup the theme in your local dev environment.
Note: This project is using node v16.
While you're working on SCSS, JS, and ACF Block files, you can run npm run start
to auto compile any changes you've made. Browsersync should be supported.
To compile for production, you can run npm run build
and it will place the compiled ACF Block files and Theme CSS and JS in the /wp-content/themes/kalapress/build
folder.
Building blocks using Advanced Custom Fields Pro (ACF) is a fast and relatively simple method of creating custom Gutenberg blocks. The main drawbacks to creating via this method are: a) it’s not open source and is dependent on a paid plugin, and b) the “Preview” in the editor doesn’t at all match the output, which can be confusing for users.
- Create a new folder in blocks/acf with the name of your desired block, for instance
card--featured
- Create a file with the same name as the folder for rendering the contents, in this case
card--featured.php
- Create a
block.json
file in that new folder, with the relevant info filled out
{
"$schema": "https://schemas.wp.org/trunk/block.json%22,
"apiVersion": 3,
"name": "acf/card--featured",
"title": "Kalamuna - Card Featured",
"description": "Display a clickable block of content with a featured image, headline, and text.",
"category": "theme",
"icon": "images-alt2",
"keywords": [
"card",
"featured"
],
"acf": {
"mode": "edit",
"renderTemplate": "card--featured.php"
},
"example": "true",
"supports": {
"align": [
"left",
"right",
"center"
],
"spacing": {
"margin": [
"top",
"bottom"
]
}
},
"style": "file:./card--featured.css",
"script": "file:./card--featured.js"
}
Note that renderTemplate
will refer to the php file in the same folder.
- Create an
.scss
file in the same folder with the same name, in this casecard--featured.scss
. Add a reference to this file inblock.json
so it gets imported via the “style” attribute as in the example. - Create a js file in the same folder with the same name, in this case
card--featured.js
. Add a reference to this file inblock.json
so it gets imported via the "script" attribute as in the example.- Other values here can control which scripts (and styles) get loaded in the editor or the view only, see Metadata in
block.json
| Block Editor Handbook | WordPress Developer Resources - The first line in the js file should import the scss file, like
import './card--featured.scss'
;
- Other values here can control which scripts (and styles) get loaded in the editor or the view only, see Metadata in
- In Terminal, run
npm run build:blocks:acf
so the block is compiled and available in the CMS. If this fails, the most likely explanation is a comma at a line inblock.json
that doesn't have another attribute after it. - Create a Field Group in ACF with the required fields for your block, and output them in the render php file.
- In Terminal, make sure you are in the project root.
- Type
npm add:block:static
and follow the prompts. The block will be added in theblocks/native
directory. - Add a line to
inc/blocks-config.php
for your new block, like'native/static' => true
(be sure to add a comma to the end of the preceding line if there wasn't one) - When you’re ready to actually build the block, go to Terminal in the project root and start the build; in this case you’d probably want to use
npm run start:build:blocks:native
so you are only compiling the relevant parts of the theme and not the whole thing.
Font Sizes for our WordPress themes can be adjusted through the theme.json file under settings.typography.fontSizes.
There are three key/value pairs to look for:
slug
: the unique identifier used in the custom CSS variable.size
: the CSS font-size value (preferably using the rem unit).name
: the name that appears in the WordPress editor.
{
"settings": {
"typography": {
"fontSizes": [
{
"slug": "x-small",
"size": "0.8rem",
"name": "x-small"
},
{
"slug": "small",
"size": "0.875rem",
"name": "small"
},
{
"slug": "base",
"size": "1rem",
"name": "base"
}
]
}
}
}
These font settings can then be referenced throughout the theme using their associated CSS variables:
var(--wp--preset--font-size--x-small)
var(--wp--preset--font-size--small)
var(--wp--preset--font-size--base)
The font-size options in our themes typically range from: x-small, small, base, medium-small, medium, medium-large, large, x-large, xx-large, xxx-large.
In most cases, you'll only need to update the “size” values. If you need to add additional font-size options, try to keep the naming convention the same and place them in a sensical order within the fontSize array.
Fluid typography responsively scales font sizes depending on the viewport width. This allows fonts to smoothly scale between minimum and maximum sizes.
By default, WordPress disables fluid typography, but we enable it in most of our themes. To see if fluid typography is enabled, look for these settings in theme.json
:
{
"settings": {
"typography": {
"fluid": true
}
}
}
Once fluid typography is enabled, there are some additional settings that need to be added to your font size option.
- Inside "fluid", enter your
min
andmax
font-size
values. min
: the minimum font size. This is shown on viewports below 768px.max
: The maximum font size. This is shown on viewports above 1600px.
{
"settings": {
"typography": {
"fontSizes": [
{
"slug": "xx-large",
"size": "3rem",
"name": "xx-large",
"fluid": {
"min": "2.25rem",
"max": "3rem"
}
}
]
}
}
}
WordPress uses the clamp() function to resize your font-sizes based on the min and max values you enter. To read more about clamp() visit: clamp() - CSS: Cascading Style Sheets | MDN.
In some cases, you may want to disable fluid typography for a specific font option. To disable it, set the value for fluid
to false like so:
{
"settings": {
"typography": {
"fontSizes": [
{
"slug": "xx-large",
"size": "3rem",
"name": "xx-large",
"fluid": false
}
}
]
}
}
}
To set the default font-size for your theme, enter a fontSize
value under styles.typography.fontSize
.
{
"styles": {
"typography": {
"fontSize": "var(--wp--preset--font-size--medium)",
}
}
}
These settings are outputted to the websites tag like so:
body {
font-size: var(--wp--preset--font-size--medium);
}
To add a font size to a specific block, enter a fontSize
value under styles.blocks.blockname.typography
. In the example below, we’re styling our buttons to use the large font-size
option that we added to our settings.
{
"styles": {
"blocks": {
"core/button": {
"typography": {
"fontSize": "var(--wp--preset--font-size--large)"
}
}
}
}
}
When entering a fontSize
value, any valid CSS value is accepted. However, it’s recommended to use one of the fontSize
option presets that we have already added in our theme settings so that we can keep things consistent.
We choose to disable many of the font options that WordPress enables by default. We do this to help keep the editor options within design restrictions.
An example of font options that we typically disable in theme.json
:
{
"settings": {
"typography": {
"customFontSize": false,
"dropCap": false,
"lineHeight": false,
"letterSpacing": false,
"textDecoration": false,
"fontStyle": false,
"fontWeight": false,
}
}
}
Container widths for our WordPress themes can be adjusted through the theme.json
file. There are two key/value pairs to look for:
contentSize
sets the default width of the page container, blocks in the editor, and blocks in the front-end.wideSize
activates the wide width feature and sets the width for wide blocks that extend past the page container.
Theme.json Settings:
{
"settings": {
"layout": {
"contentSize": "88.25rem",
"wideSize": "91.5rem"
}
}
}
Note: It's recommended to use the rem
unit when adding width values.
These settings can be referenced throughout the theme using their associated CSS variables:
var(--wp--style--global--content-size)
var(--wp--style--global--wide-size)
For KalaPress, we have leveraged these CSS variables for layout mixins and have assigned those styles to alignment utility classes.
Available Mixins:
@mixin container
@mixin container--full
@mixin container--wide
@mixin container--narrow
Available utility classes:
.alignfull
- Blocks can be set to Full width by selecting the option in the toolbar..alignwide
- Blocks can be set to Wide width by selecting the option in the toolbar..alignnarrow
- This is not a default WordPress utility class so it does not appear within the toolbar. We have added this class to accommodate narrow container sizes. Future scope: Add additional control to toolbar or register a block style.
Spacing settings in theme.json By default, WordPress uses its own spacing scale. For KalaPress, we have created our own custom spacing scale to accommodate the Gutenberg editor.
In the editor sidebar under the Dimensions settings, users can choose from the x-small, small, medium, or large options to add padding or margins around blocks. This is beneficial for adding spacing between sections, for example:
Example of a Medium bottom margin being applied to a block. Note: Some blocks only support top and bottom margins.
We have added four presets: X-Small, Small, Medium, and Large. Spacing sizes can be adjusted in theme.json
under settings.spacing.spacingSizes
.
Some of the sizes have been added using clamp()
so that they are responsive. More information about the clamp()
function: clamp() - CSS: Cascading Style Sheets | MDN. When entering new size values, it's recommended to use rem
for the units.
Theme.json Spacing Sizes Settings:
{
"settings": {
"spacing": {
"spacingSizes": [
{
"size": "1.5rem",
"slug": "x-small",
"name": "X-Small"
},
{
"size": "clamp(1.75rem, 6vw, 3rem)",
"slug": "small",
"name": "Small"
},
{
"size": "clamp(2rem, 6vw, 6rem)",
"slug": "medium",
"name": "Medium"
},
{
"size": "clamp(2rem, 8vw, 9rem)",
"slug": "large",
"name": "Large"
}
]
}
}
}
If you apply margin or padding settings directly into your block pattern, the Dimensions option panel will expand and display your settings. Because there are options to change the padding and margin on all four sides of an element, applying your own settings can help guide the user on which margins/paddings should be changed for a specific block pattern.
Example: this block pattern has margin settings applied to it. When it is inserted onto the page, the dimensions panel expands, and displays the margin settings.
Example: this block pattern does not have any margin or padding settings applied to it. Once added to the page, the Dimensions panel remains closed. In order to add spacing you must expand the panel and select margins/padding for each individual side.
These spacing settings are available for all core blocks that support spacing. See Core Blocks Reference | Block Editor Handbook | WordPress Developer Resources to view which core blocks support padding and margins.
In some cases, you may not want to enable this feature, so there is an option to disable it for specific blocks. To disable, set margin
or padding
to false
under settings.blocks.core/block-name.spacing
{
"settings": {
"blocks": {
"core/button": {
"spacing": {
"margin": false,
"padding": false
}
}
}
}
}
The KalaPress theme color palette and gradients can be modified through the theme.json
file under settings.color.palette
and settings.color.gradients
.
There are three key/value pairs to look for:
slug
: the unique identifier used in the custom CSS variable.name
: the name that appears in the WordPress editor.color
orgradient
: The CSS color value.
Instead of using color-specific slugs, we recommend using base, contrast, and sequential slugs like primary, secondary, tertiary, quaternary, etc.
base
: the background color.contrast
: the color for elements on the page, ie. text, headings, lists, etc.primary
,secondary
,tertiary
, etc: the accent colors.
This method promotes development with Global Styles in mind so that we can more efficiently adapt our themes to our client's brands.
The main colors for the website should be added through theme.json
, but there are additional color variables available to use in src/sass/settings/_color.scss
. These include: greyscale colors, lightened and darkened versions of the primary & secondary colors, etc.
Once you’ve added your color values to theme.json
, it’s important to update the Brand Theme Color values in src/sass/settings/_color.scss
as well.
{
"settings": {
"color": {
"palette": [
{
"slug": "base",
"color": "#f2f2f2",
"name": "Base (Light Grey)"
},
{
"slug": "contrast",
"color": "#191919",
"name": "Contrast (Black)"
}
{
"slug": "primary",
"color": "#CE3C90",
"name": "Primary (Pink)"
},
{
"slug": "secondary",
"color": "#323334",
"name": "Secondary (Charcoal)"
}
],
"gradients": [
{
"slug": "primary-to-transparent",
"gradient": "linear-gradient(180deg, var(--wp--preset--color--primary), rgba(255, 255, 255, 0))",
"name": "Primary to Transparent"
}
]
}
}
}
These color settings can then be referenced throughout the theme using their associated CSS variables. For example:
var(--wp--preset--color--primary)
var(--wp--preset--gradient--primary-to-transparent)
Additionally, new class names are created that reference these color variables. These class names are used within the block editor and front-end.
- background color class:
.has-primary-background-color
- text color class:
.has-primary-color
- gradient background color class:
.has-primary-to-transparent-gradient-background
An example of what this would look like in the editor for the new color palette. While the color variables from the previous steps are available to use across your entire theme, there is an option to add separate color palettes and gradients for individual blocks as well. This feature might be helpful if you want to limit a block to use certain colors and gradients.
- For color palettes, add your color values under:
settings.blocks.core/blockname.color.palette
. - For gradients, add your gradient values under:
settings.blocks.core/blockname.color.gradients
. - Color palette and gradients added to a Button block in theme.json:
{
"settings": {
"blocks": {
"core/button": {
"color": {
"palette": [
{
"slug": "primary",
"color": "#CE3C90",
"name": "Primary (Pink)"
},
{
"slug": "secondary",
"color": "#323334",
"name": "Secondary (Charcoal)"
},
{
"slug": "base",
"color": "#f2f2f2",
"name": "Base (Light Grey)"
}
],
"gradients": [
{
"slug": "secondary-to-transparent",
"gradient": "linear-gradient(0, var(--wp--preset--color--secondary) 0%, var(--wp--preset--color--primary-1) 100%)",
"name": "secondary to Transparent"
}
]
}
}
}
}
}
In some cases, you may want to disable the ability to change colors and gradients within a block. To do this, you would alter the properties like so:
{
"settings": {
"blocks": {
"core/paragraph": {
"color": {
"palette": [], // disables the color palette entirely.
"gradients": [], // disables the gradients entirely.
"background": false, // disables the ability to choose a bg color.
"text": false, // disables the ability to choose a text color.
}
}
}
}
}
We choose to disable many of the color and gradient options that WordPress enables by default. We do this to help keep the editor options within design restrictions.
An example of color options that we typically disable in theme.json
:
{
"settings": {
"color": {
"custom": false,
"customDuotone": false,
"customGradient": false,
"defaultDuotone": false,
"defaultGradients": false,
"defaultPalette": false
}
}
}