Andrew Welch · Insights · #craftcms #devops #craft-3

Published , updated · 5 min read ·

Please consider 🎗 sponsoring me 🎗 to keep writing articles like this.

Setting up a New Craft CMS 3 Project

With the release of Craft CMS 3, you might want to kick the tires. Here is how to set up a Craft CMS 3 project

Craft Cms 3 Rc 1

Now that Craft CMS 3 has been released, you’re like­ly eager to give it a go. This arti­cle is some­thing you might want to read first, to give you a roadmap for set­ting up your project.

This arti­cle will dis­cuss set­ting up a new Craft 3 project so you can exper­i­ment with it. It will not cov­er updat­ing an exist­ing Craft 2.x project to Craft 3; expect that to come in a future article.

Release Candidate Features Frozen

This makes it an excel­lent time to start get­ting famil­iar with it, whether you’re a fron­tend devel­op­er, a plu­g­in devel­op­er, or both. With the fea­ture set frozen, you’re work­ing against a known quantity.

I won’t rehash what is new in Craft 3; if you’re inter­est­ed in that, check out the Craft 3 Beta Exec­u­tive Sum­ma­ry article.

The canon­i­cal ref­er­ence will always be the Craft CMS doc­u­men­ta­tion for Serv­er Require­ments, Instal­la­tion, Con­fig­u­ra­tion, and Direc­to­ry Struc­ture. But there are a few tips, tricks, and hints I’d like to add to the sub­ject as well.

So, let’s dive in!

Link Should I Use Craft 3 in Production?

N.B. Since Craft CMS 3 was released on April 4th 2018, the answer is: def­i­nite­ly yes, you should be using Craft CMS 3.x in pro­duc­tion. The bal­ance of this sec­tion is left in for his­tor­i­cal reasons.

One of the most com­mon­ly asked ques­tions with the release of Craft CMS 3 RC1 is:

Should I Use Craft 3 in Production?

The answer is it depends. I per­son­al­ly am using Craft 3 RC1 in pro­duc­tion for a client site, as well as a for a new project of my own.

The biggest draw­back is that your favorite plu­g­in may not be port­ed yet, but Craft is flex­i­ble enough that you can gen­er­al­ly do with­out many plu­g­ins if you have to. There are also quite a few Craft 3 plu­g­ins avail­able already.

I think it makes sense to at the very least fire up a test site to kick Craft 3 RC1’s tires. For some client sites, I think it’s also very rea­son­able to start using it now as well. The speed and infra­struc­ture improve­ments are well worth it.

Link Changes from Craft 2.x

There are a few changes in terms of how things are set up in Craft 3 com­pared to Craft 2.x, and all for the bet­ter in my opinion.

Changes Craft 2 To Craft 3

Some of these changes will take some get­ting used to:

  • Craft 3 now uses Com­pos­er for instal­la­tion & updat­ing of Craft and any plu­g­ins you might have
  • The default direc­to­ry struc­ture has some changes; but these are just sug­ges­tions. You can use what­ev­er you like
  • Plu­g­ins writ­ten for Craft 2.x will not work with Craft 3, they will need to be updat­ed by developers
  • Craft 3 now uses a php­dotenv .env file by default for han­dling envi­ron­men­tal-spe­cif­ic things like pass­words, data­base names, etc.
  • There are some minor tem­plate changes for you to make; most are just dep­re­ca­tions, so they still work, but you’ll need to update them by the time Craft 4 rolls around

Link Composer

The first major change is that Craft 3 relies on Com­pos­er for things like instal­la­tion and updates of both Craft CMS itself, and any plu­g­ins you may be using.

  • Com­pos­er is a tool that allows for the instal­la­tion of PHP pack­ages, much like npm and yarn for JavaScript
  • Pack​ag​ist​.org is a web­site that’s a pub­lic list­ing of Com­pos­er pack­ages, sim­i­lar to npmjs​.com for JavaScript

If you don’t have Com­pos­er installed on your local dev set­up yet, here are instruc­tions on how to Install Com­pos­er.

Pix­el & Ton­ic has men­tioned that they plan to allow a non-Com­pos­er instal­la­tion path, but as devel­op­ers it actu­al­ly makes our lives much eas­i­er to embrace Composer.

So if you aren’t famil­iar with Com­pos­er, invest­ing some time to learn it now will pay div­i­dends down the road. Let’s dive in!

Craft 3 Cms Composer

To install a new Craft 3 project, all we need to do is the following:

composer create-project craftcms/craft PATH

Let’s break this down:

  • composer is just the glob­al­ly installed Com­pos­er command
  • create-project tells Com­pos­er that we want to cre­ate a new project from an exist­ing tem­plate (more on this later)
  • craftcms/craft is the pack​ag​ist​.org pack­age we want to use as a tem­plate when cre­at­ing our project
  • PATH is the rel­a­tive or absolute path to where we want our project cre­at­ed; nor­mal­ly it’d be some­thing like craft3 or ~/webdev/sites/mysitename or what have you

So out of my Home­stead VM that I use for local devel­op­ment, the com­mand I’d run is:

vagrant@homestead ~/sites $ composer create-project craftcms/craft crafttest

A whole bunch of text will fly by, but let’s talk about what’s actu­al­ly hap­pen­ing. Com­pos­er is going out to pack​ag​ist​.org to look for a pack­age named craftcms/craft and then it’s essen­tial­ly git cloneing that repos­i­to­ry, but with­out actu­al­ly pulling down the .git data.

We’re cre­at­ing a new project, after all, so we want to use the pack­age as a tem­plate to get the files in it as a start­ing point.

Have a look at the actu­al craftcms/​craft repos­i­to­ry on GitHub​.com, and you’ll see that there isn’t a whole lot to it, real­ly. It’s just some Craft con­fig­u­ra­tion files, composer.json, etc. So it’s just a bare bones project that gets made for us as a start­ing point.

Then it will run a composer install to install any of the Com­pos­er pack­ages that craftcms/craft claims as depen­den­cies, much like npm install or yarn does for npm packages. 

The crit­i­cal thing to under­stand here is that the craftcms/craft pack­age is just scaf­fold­ing that Pix­el & Ton­ic set up with what they think is a nice start­ing point for your new Craft 3 project. This actu­al­ly could be any pack​ag​ist​.org pack­age that is of "type": "project"!

For instance, I have set up a pack­age nystudio107/craft that allows me to set up Craft 3 with the direc­to­ry struc­ture and depen­den­cies that I want, and I can start a new Craft 3 project with my scaf­fold­ing by doing:

vagrant@homestead ~/sites $ composer create-project nystudio107/craft crafttest

The nystudio107/​craft project pack­age does every­thing the Pix­el & Ton­ic craftcms/​craft project pack­age does, and then installs a num­ber of tools and scaf­fold­ing that I use, and has been described in arti­cles in this blog. So it makes a great start­ing point.

Not only is this pret­ty use­ful should you want to set up your own scaf­fold­ing, it’s a key point to under­stand what’s going on. Let’s have a look at the composer.json file that comes with the craftcms/craft package:

  "name": "craftcms/craft",
  "description": "Craft CMS",
  "keywords": [
  "license": "MIT",
  "homepage": "",
  "type": "project",
  "support": {
    "email": "",
    "issues": "",
    "forum": "",
    "source": "",
    "docs": "",
    "rss": ""
  "require": {
    "craftcms/cms": "^3.0.0",
    "vlucas/phpdotenv": "^2.4.0"
  "autoload": {
    "psr-4": {
      "modules\\": "modules/"
  "config": {
    "optimize-autoloader": true,
    "platform": {
      "php": "7.0"
  "scripts": {
    "post-create-project-cmd": [
      "@php -r \"copy('.env.example', '.env');\"",
      "@php -r \"unlink('composer.json');\"",
      "@php -r \"unlink('');\"",
      "@php -r \"unlink('');\"",
      "@php -r \"rename('composer.json.default', 'composer.json');\"",
      "@composer dump-autoload -o",
      "@php craft setup/welcome"

So this is pret­ty inter­est­ing! The craftcms/craft project pack­age lists craftcms/cms as a depen­den­cy. It can get a lit­tle con­fus­ing, so remember:

  • craftcms/craft is the starter project scaf­fold­ing pack­age for your Craft 3 projects
  • craftcms/cms is the actu­al Craft 3 pack­age that con­tains all of the code that col­lec­tive­ly makes up Craft CMS

So Craft itself is just anoth­er Com­pos­er pack­age that gets pulled in. It works the same way for any plu­g­ins you might want to use, you can just add them to your composer.json and they’ll get installed as PHP packages.

Of course, Craft pro­vides a nice GUI for doing all of this as well, but it’s use­ful to under­stand how things work under the hood.

If you want to do a deep-dive on Com­pos­er, I’d sug­gest check­ing out the arti­cles Com­pos­er Sta­bil­i­ty Flags & Com­pos­er Autoload Fea­tures (there are sev­er­al parts to this arti­cle, make sure to read them all!).

Also extreme­ly use­ful for under­stand­ing Composer/​Packagist semver nam­ing is the Pack­ag­ist Semver Check­er.

Link Craft 3 Initial Setup

Okay, so after we’ve cre­at­ed a Craft 3 project, now we need to do a lit­tle bit of work set­ting it up.

Craft 3 Cms Setup Instructions

At the tail end of the instal­la­tion, you’ll see a mes­sage like this from Craft:

Generating a security key...
done (UDRBoBjQAzfgY5J9S-543Ie0PrxwCwZG)

Welcome to Craft CMS! Run the following command if you want to setup Craft from your terminal:

    ~/sites/crafttest/craft setup

The secu­ri­ty key that it gen­er­ates is just a ran­dom string of char­ac­ters (like a pass­word) that’s unique on a per-project basis. For mul­ti-envi­ron­ment setups, you’ll want to be using the same secu­ri­ty key in each environment.

Craft uses this for encrypt­ing data, so it’s just a unique seed that’s set in general.php.

If you run the com­mand ~/sites/crafttest/craft setup (or what­ev­er it out­puts for your project), it’ll set up your .env file for you:

vagrant@homestead ~/sites $ ~/sites/crafttest/craft setup
Which database driver are you using? [mysql,pgsql,?]: mysql
Database server name or IP address: [localhost]
Database port: [3306]
Database username: [root] homestead
Database password:
Database name: crafttest
Database table prefix:
Testing database credentials... success!
Saving database credentials to your .env file...

Your (emp­ty) data­base needs to have been cre­at­ed already, just like on Craft 2.x. It’ll then ask you if you want to install Craft now. If you say yes, it’s essen­tial­ly just a com­mand line equiv­a­lent of the famil­iar set­up wizard:

Install Craft now? (yes|no) [yes]:

Username: [admin]
Site name: crafttest
Site URL:
Site language: [en-US]

Of course, you don’t have to do it this way. You can say no, and install it by going to the URL just as you did for Craft 2.x if you like.

Either way, you’ll now have a php­dotenv .env file in your project root that has your cre­den­tials in it:

vagrant@homestead ~/sites $ cat crafttest/.env
# The environment Craft is currently running in ('dev', 'staging', 'production', etc.)

# The secure key Craft will use for hashing and encrypting data

# The database driver that will used ('mysql' or 'pgsql')

# The database server name or IP address (usually this is 'localhost' or '')

# The database username to connect with

# The database password to connect with

# The name of the database to select

# The database schema that will be used (PostgreSQL only)

# The prefix that should be added to generated table names (only necessary if multiple things are sharing the same database)

# The port to connect to the database with. Will default to 5432 for PostgreSQL and 3306 for MySQL.

Remem­ber, this file is nev­er checked into git, so we’ll need a man­u­al­ly cre­at­ed .env file for each envi­ron­ment we deploy Craft to, includ­ing our staging and live pro­duc­tion servers.

The con­stants in the .env file are parsed, and set as PHP Envi­ron­ment vari­ables that are read by the general.php, db.php, etc. Craft 3 config/ files:

 * Database Configuration
 * All of your system's database connection settings go in here. You can see a
 * list of the available settings in vendor/craftcms/cms/src/config/DbConfig.php.

return [
    'driver' => getenv('DB_DRIVER'),
    'server' => getenv('DB_SERVER'),
    'user' => getenv('DB_USER'),
    'password' => getenv('DB_PASSWORD'),
    'database' => getenv('DB_DATABASE'),
    'schema' => getenv('DB_SCHEMA'),
    'tablePrefix' => getenv('DB_TABLE_PREFIX'),
    'port' => getenv('DB_PORT')

While .env files are great for devel­op­ment, for live pro­duc­tion I’d rec­om­mend mov­ing the envi­ron­men­tal vari­ables to your web­serv­er con­fig, or using some­thing like Craft 3 Mul­ti-Envi­ron­ment as described in the Mul­ti-Envi­ron­ment Con­fig for Craft CMS article.

Link The Craft 3 Directory Structure

Alrighty, now that we have a fresh Craft 3 project installed & set up, let’s take a lit­tle sur­vey of what we actu­al­ly have installed.

Craft 3 Cms Directory Structure

Here’s what our fresh­ly installed project direc­to­ry looks like:

vagrant@homestead ~/sites/crafttest $ tree -L 2 -a .
├── composer.json
├── composer.lock
├── config
│   ├── app.php
│   ├── db.php
│   ├── general.php
│   ├── redactor
│   └── routes.php
├── craft
├── craft.bat
├── .DS_Store
├── .env
├── .env.example
├── .gitignore
├── modules
│   └── Module.php
├── storage
│   ├── .gitignore
│   ├── logs
│   └── runtime
├── templates
│   └── .gitkeep
├── vendor
│   ├── autoload.php
│   ├── bin
│   ├── cebe
│   ├── composer
│   ├── craftcms
│   ├── creocoder
│   ├── danielstjules
│   ├── .DS_Store
│   ├── enshrined
│   ├── ezyang
│   ├── guzzlehttp
│   ├── justinrainbow
│   ├── league
│   ├── mikehaertl
│   ├── paragonie
│   ├── pixelandtonic
│   ├── psr
│   ├── seld
│   ├── swiftmailer
│   ├── symfony
│   ├── twig
│   ├── vlucas
│   ├── yiisoft
│   └── zendframework
└── web
    ├── cpresources
    ├── .htaccess
    ├── index.php
    └── web.config

33 directories, 22 files

The first thing you’ll notice is that there is no craft/ direc­to­ry here at all any­more, which is some­thing we were used to see­ing in Craft 2.x. Every direc­to­ry that was inside of the craft/ direc­to­ry in Craft 2.x is now in our root project directory.

This makes sense if you think about it, since Craft itself is now just installed as anoth­er Com­pos­er depen­den­cy in the vendor/craftcms directory.

So let’s take a look at some notable files/​directories that we have in our projects now:

  • composer.json has all of the infor­ma­tion for our project, includ­ing the PHP pack­age depen­den­cies and their min­i­mum semver ver­sions
  • composer.lock has infor­ma­tion on what PHP pack­ages & their ver­sions are actu­al­ly installed (they may be new­er than our min­i­mum versions)
  • config/ is what used to be craft/config/, and has all of the famil­iar Craft CMS con­fig files
  • craft is a com­mand line tool that is exact­ly anal­o­gous to the web-fac­ing index.php. It’s what you use to run Craft 3 via the com­mand line (more on this below)
  • .env is our php­dotenv .env file that has our envi­ron­ment-spe­cif­ic things like data­base pass­words, etc. stored
  • .gitignore tells git what file pat­terns to ignore com­plete­ly, and nev­er check into git
  • storage/ is what used to be craft/storage/ and is where tem­po­rary run­time files, logs, etc. are kept, just like in Craft 2.x
  • templates/ is what used to be craft/templates/ and is where your Twig tem­plates are stored
  • vendor/ is where all of the PHP pack­age depen­den­cies that your project uses (includ­ing Craft itself) are stored
  • web/ is what used to be the public/, which con­tains our index.php, .htac­cess, etc. files, and is where the web serv­er root should be pointed

It’s impor­tant to note that Craft does­n’t real­ly care what you use as a direc­to­ry struc­ture, this is just what Pix­el & Ton­ic is pro­vid­ing you as a base set­up. If you don’t like the change from public/ to web/, that’s fine. Just rename it!

The craft com­mand line tool is actu­al­ly what we used ear­li­er to set up the .env file, and option­al­ly install Craft. Just think of it as a way to run Craft from the com­mand line. It inher­its a num­ber of tools from Yii2 Con­sole Com­mands, and Pix­el & Ton­ic has added a num­ber of Craft-spe­cif­ic things to it as well.

For instance, you can use ./craft install/plugin my-plugin-handle to install plu­g­ins from the com­mand line. Cool!

Link Deploying Craft CMS

The change in how Com­pos­er is used for Craft 3 dis­cussed ear­li­er leads direct­ly to how we should be updat­ing, test­ing, and deploy­ing Craft 3.

For Craft 2.x, we just checked all of craft/ (includ­ing the vendor/ sub-direc­to­ry) into git, updat­ed & test­ed it in local dev, and then deployed it to staging/live pro­duc­tion via our deploy­ment tool of choice, such as Lar­avel Forge,, Lar­avel Envoy­er, Deploy­Bot, etc.

Deploying Craft 3 Cms

There are a few impor­tant bits from Com­pos­er that we need to under­stand first, to see how this needs to change for Craft 3:

  • composer.json has all of the infor­ma­tion about our project, and what PHP pack­age depen­den­cies it requires as min­i­mum semver ver­sions
  • composer.lock has infor­ma­tion on what PHP pack­age depen­den­cies are actu­al­ly installed (we might have new­er ver­sions than what our min­i­mum ver­sions require)
  • vendor/ is a direc­to­ry that has all of the actu­al PHP pack­ages installed (includ­ing Craft CMS itself!)
  • .gitignore tells git what file pat­terns to ignore when track­ing changes in git

Here’s the default .gitignore file pro­vid­ed by the craftcms/​craft package:


The impli­ca­tions are that we’re nev­er check­ing our .env files into git (because putting sen­si­tive things like pass­words into ver­sion con­trol is a bad idea), but we’re also ignor­ing the entire /vendor directory.

So if we’re not check­ing any of our PHP pack­ages in the /vendor direc­to­ry into git (this includes Craft CMS itself, remem­ber!), how do we update and deploy things?

By embracing Composer, that’s how!

We’ll take advan­tage of how Com­pos­er works:

  • In local dev, we’ll update every­thing via composer update (or we can update just spe­cif­ic pack­ages via composer update packagevendor/package)
  • The above step can also be done via the AdminCP UI by click­ing on Update, either for Craft CMS itself, or any of its plu­g­ins. Under the hood, it ends up run­ning Com­pos­er just as described above
  • This caus­es Com­pos­er to down­load & install the updat­ed package(s), and then it writes out what’s installed to the composer.lock file
  • Then we test every­thing in local dev just as we used to, to make sure it’s ready for prime time
  • Since we ignore all of the /vendor direc­to­ry, the only thing that will be changed as far as git is con­cerned is the composer.lock file that lists what ver­sions of what pack­ages are actu­al­ly installed

Then on the serv­er-side deploy­ment of things, we’ll run the fol­low­ing from our project direc­to­ry on the server:

composer install --no-interaction --prefer-dist --optimize-autoloader

What composer install does is look at what­ev­er is in the composer.lock file, and if it’s new­er than what it sees installed local­ly, it updates & installs it! You can see the full options avail­able to com­pos­er install here.

The neat thing about doing it this way is we have less cruft checked into our git repos, and we can also dis­crete­ly update only spe­cif­ic things.

Maybe we only want to update a spe­cif­ic plu­g­in, we can do that by updat­ing only that plu­g­in via composer update pluginvendor/plugin from local dev. Since that’s the only change that gets writ­ten out to the composer.lock file, that’s the only thing that gets updat­ed when our serv­er runs composer install


The only down­side to this is that composer install can take a bit longer than a sim­ple git pull to exe­cute, so look­ing into atom­ic deploy­ments via, Lar­avel Envoy­er, Deploy­Bot, etc. might not be a bad idea.

For an in-depth look at doing atom­ic deploy­ments with, check out the Atom­ic Deploy­ments With­out Tears article.

Link Craft 3 Plugins

The bad news about plu­g­ins is that plu­g­in devel­op­ers will need to rewrite their plu­g­ins for Craft 3.

Craft 3 Cms Plugins

The good news is that Pix­el & Ton­ic has made a nice guide on Craft 3 Plu­g­in Devel­op­ment, and many plu­g­ins have already been port­ed. Check out the Craft 3 Plu­g­ins page to see what’s avail­able already.

Also, tools like plug​in​fac​to​ry​.io and arti­cles like So You Wan­na Make a Craft 3 Plu­g­in? are avail­able to help developers.

The best thing you can do is check with your plu­g­in ven­dor to see how far along they are on port­ing their plu­g­ins to Craft 3.

Pix­el & Ton­ic has stat­ed that a beta ver­sion of the Plu­g­in Store (which is inte­grat­ed into the Craft 3 AdminCP) will ship with Craft 3 CMS RC 1, but that only free plu­g­ins will be avail­able ini­tial­ly. Devel­op­ers can make plu­g­ins that will be paid plu­g­ins avail­able for free now as well, but they will require pur­chase once Craft CMS 3 is in GA release.

The full roll­out of the plu­g­in store with paid plu­g­ins, Com­merce 2, and the Gen­er­al Avail­abil­i­ty release of Craft 3 will hap­pen on April 4th, 2018. Check out the What We Announced at Dot All 2017 arti­cle for details.

Speak­ing of plu­g­ins, Craft 3 comes with no Rich Text field by default. You’ll need to install the Redac­tor plu­g­in first (don’t wor­ry, your exist­ing con­tent is still there). This is because P&T will be offer­ing a CKEd­i­tor Rich Text plu­g­in as well, in the near future.

Link Template Changes

The good news is that in terms of actu­al changes to your Twig tem­plates, there aren’t that many. Pix­el & Ton­ic has done a great job out­lin­ing the changes in Twig 2 as well as the changes in Craft Tem­plate Tags that you’ll need to be aware of.

The vast major­i­ty of the changes are mere­ly dep­re­ca­tion errors. That means that Pix­el & Ton­ic plans to phase them out when Craft 4 comes along, but they’ll still work for now.

You can check on any dep­re­ca­tion errors inside of Craft 3 by going to Util­i­tiesDep­re­ca­tion Errors.

Craft 3 Cms Deprecation Errors

Craft 3 CMS Dep­re­ca­tion Errors

If you’re using Craft CMS >= 3.1.18, you can enable hard mode” to have Craft throw an error in local dev, rather than log­ging a dep­re­ca­tion by adding this to your config/app.php:

 * config/app.php

use craft\helpers\App;

return [
    'components' => [
        'deprecator' => [
            'throwExceptions' => App::env('DEV_MODE'),

Hav­ing Craft CMS throw an error when it encoun­ters a dep­re­ca­tion in local dev makes it much eas­i­er to find and fix them all. In production, it will just log dep­re­ca­tion errors as normal.

The oth­er real­ly inter­est­ing thing is that in Craft 3, the entire appli­ca­tion instance is avail­able to your Twig templates. 

What that means in real terms is that you can do any­thing with the Craft 3 APIs via Twig that you can via PHP. So many small plu­g­ins that were need­ed to expose some need­ed func­tion­al­i­ty may no longer be nec­es­sary at all.

Phpstorm Craft Auto Completion

Twig inspec­tion hint

One absolute­ly amaz­ing thing you can do if you’re using Php­Storm is get full auto-com­ple­tion of the entire craft. APIs in your Twig tem­plates, too! To do make the mag­ic hap­pen, install the Sym­fony plu­g­in, then Go to Pref­er­encesLan­guages & Frame­worksPHPSym­fony and check Enable Plu­g­in for this Project.

Then all you need to do is put this inspec­tion hint at the top of your Twig templates:

{# @var craft \craft\web\twig\variables\CraftVariable #}

…and just like that, you get the same mag­ic auto-com­ple­tion of in your Twig tem­plates that you have in your PHP code. And since the entire Craft appli­ca­tion is avail­able in our Twig tem­plates now, this makes writ­ing Twig code that uses the Craft app APIs so much nicer.

Link Wrapping Up!

This is undoubtably the first of sev­er­al arti­cles I’ll be writ­ing on Craft 3. But hope­ful­ly it has giv­en you an idea of the lay of the land for Craft 3 development.

Go forth and make cool stuff!