Apr 01. 2019 · by Helge Sverre

Team Workflow with Project Config in Craft CMS 3

Step 1 - Local development

Teammate #1 adds all the fields and configure the section (ex: a blog channel, it has a summary text field and a rich text field, title is always added by default by craft) required for the current page or feature being worked on, as new fields are added or changed, Craft will sync these changes to our project.yaml file in the background.

Come time to push our changes to Git, we add and commit the config/project.yaml file.

Step 2 - Pulling down content from our teammate

Say the site is not ready to be pushed to production yet, but we have the latest version in git, now it is time for teammate #2 to work on something else, but it requires the changes made by teammate #1, previously we had to do all kinds of crazy database SQL syncing, making sure we did stuff in the right order, or else with might risk losing someones changes.

But not with project config, being a version controlled file, we can simply pull down the latest changes from there, run the project sync command (listed below), and we have all the administrative and template changes done by teammate #1, teammate #2 can now do whatever changes need to be done (add another field, change the blog channel uri path from /news to /blog, etc) and push their changes.

Step 3 - Resolving merge conflicts

Now, let's imagine that in parallel to teammate #2, teammate #3 was doing some changes on the same feature that teammate #1 was doing (noticed a typo in a field description and changed it for instance), and has pushed it to git before teammate #2 has pushed their work (and forgot to pull down the new changes).

Aside: This might actually not cause a merge conflict, but for the sake of example, let's imagine it does.

Now teammate #2 is about to push their changes to git, but ooops!

~ Merge conflict

Fear not, as the project.yaml file is a human readable format, we can go in and with the help of a merge tool like Sublime Merge, PhpStorm's Resolve conflict window or using a text editor like VS Code and "merge together" the work from teammate #1 and #3, (keeping our channel changes, but "merging in" the change to the field description).

Be sure to update the "dateModified" timestamp to the latest version when dealing with mergeconflicts, if the dateModified field is lower than the one in production, the changes will be ignored.

The dateModified timestamp is a Unix Time stamp, you can use this tool to convert it to human readable format.

Step 4 - Deploying to production

Now it is time to push our work to production, what we want to accomplish here is for Craft CMS to notice our new administrative changes (create new fields, update existing fields, update changes to sections etc) run them automatically, which will run several sql commands to alter existing tables, all without us having to do some crazy SQL file restore on the live production site.

In Craft 3.1.7 a console command was introduced that does this for us, called php craft project-config/sync

We push our code to master, then via whatever code deploy tool you have, pull down the latest changes, and run the project-config/sync command, your site should now be updated with the latest administrative changes.

    Console command for syncing with Project Config.
    php craft project-config/sync

    To make sure we don't get merge conflicts, or inconsistant behaviour on the production system, it is a smart idea to disable administrative changes in production, this can be done with the configuration option below:

    return [
        '*' => [
            // Other config here ...
        'dev' => [
        	// Enable project config changes in development
            'useProjectConfigFile' => true,
        'production' => [
            // Disable project config changes on production
            'allowAdminChanges' => false,

    If you are not already using environment configuration for plugins and general site settings, you might run into a tricky situation where you cannot change options that are natural to change in production, like email configuration, maybe you're using the Mailgun adapter in production, and simply Mailtrap's SMTP setting in local development, another example is SEOMatic, where you have to remember to set the "environment" plugin setting to "Live" when in production or else seo meta tags wont be rendered.

    You can get around this issue by using environment configuration for general configuration and plugins that support it, SEOMatic in this case, does provide all configuration options as environment files, you can check the docs on that here.

    Admin changes (plugin settings) can't be set on the server when using project config, use environment variables in the plugin configuration file to workaround it, it is a better solution anyways.