This is an opinionated Craft CMS starter project using DDev for local development, Tailwind CSS, Alpine Js, and Laravel Mix.
to install this package run composer create-project createsean/craft-starter .
to install this package run composer create-project createsean/craft-starter . --prefer-dist 4.2.31
To install with Craft 3 version run composer create-project createsean/craft-starter . --prefer-dist 1.14.0
- Local Development
- To Do
- Build Process
- Tailwind
- Accessibility
- Dark Mode
- Fragments
- Floated Labels
- Sticky header
- Picture Element
- Craft Plugins
- Typogrify
- Sprig
- contact Form
- Style Guide
- Content
- Composer nuke
Set up your local development, if you are using DDev for local development then everything should just work for you. If you are NOT using DDEV for local development skip this part and set up local development however you normally do (Valet, Mamp, etc), be sure to import the seed database db.sql.gz
- open .ddev/config.yaml and update line 15 to use the port you want. Must be unique to all ddev sites on your local computer
- open .ddev/config.yaml and update php version (line 4) and mysql_version (line 11) if needed
- update dotenv variables, especially SITE_NAME_EN, SITE_NAME_FR, PRIMARY_SITE_URL, SITE_PATH, ASSET_BASE_URL
- update email settings of dotenv for staging/production. Current settings work with mailhog in ddev. To open mailhog run
ddev launch -m
- Run
ddev start
and the site should start up. - run
ddev import-db --file=db.sql.gz
this will import the seeder database with settings, channels, etc. - run
php craft setup/security-key
- run
php craft setup/app-id
- run
ddev launch access
will open the Craft CP - To access the db from your host machine run
ddev describe
and you'll get the connection details needed
Login: cc_admin
Password: letmein
- after logging in be sure to update your password
- Ensure accessibility passes with default templates - aria labels, alt text etc.
- Set up site search.
- Contact Form.
- Move AlpineJs and plugins from CDN to compiled build process.
- Add content builder with common content types.
- Contact page
- About/Team page
- Add hero with different options i.e. slider, no slider, no image just title.
- Get news categories working using sprig.
- Add news _entry template.
- Add news listing with sprig pagination.
- Add notice bar option.
- Add 404 template.
- Add installation instructions.
- Replace matrix content builder with CKEditor longform
- update templates to use
.eagerly()
where possible
Tailwind is compiled using Tailwind-jit which is much faster than previously. it also ensures a small file size during watch
builds. However I still recommend running the production task before deployment.
Images and svg files should be copied to src/img and src/img/svg. When running npm run production
these will then be optimized and copied to /public/assets/images and /public/assets/images/svg respectively (if you don't want to run production, copy files to both locations)
You will need NodeJS version 14+. YOu can either update to 14+ or if you need multiple versions of node install the Node Version Manager Windows / Mac.
- run
npm install
ornpm i
Add any scripts or css you need by running npm install <package-name> --save-dev
You can then have the required javascript or css files combined and minimized by adding paths to the correct files in webpack.mix.js
on line 64-70(js) or line 74-78(css). when you run npx mix watch
everything will be combined and output to /public/assets/js
or public/assets/css
- update the banner text that gets prepended to css on lines 75-85 of
webpack.mix.js
with your project info - in
webpack.mix.js
update line 12const baseUrl = 'https://craft-starter.ddev.site'
with your local domain
.banner({
banner: (function () {
return [
'/**!',
' * @project Craft Starter Website',
' * @author Sean Smith, Caffeine Creations',
' * @Copyright Copyright (c) ' + moment().format("YYYY") + ', Caffeine Creations',
' *',
' */',
'',
].join('\n');
})(),
raw: true,
})
-
run
npx mix watch
to have laravel mix compile tailwind, set up browser sync. and combine scripts.- To get your SSL working with browsersync and DDEV follow these instructions
- SSL-enabled for DDev. You have to copy the SSL cert to somewhere outside of Docker first. Run this at your project root Stack Overflow:
docker cp ddev-router:/etc/nginx/certs ~/tmp/certs
- you may need to create the tmp/certs directory in your OS users directory
- You should only need to do this for 1 project and then everything should work on multiple projects.
-
Tailwind Config Viewer is set up and uses the following commands.
npm run tw-config-viewer
will load up the viewer at localhost:4000 andnpm run export-tw-config
will export the viewer topublic/tw-viewer
-
Tailwind Container Queries plugin is installed. See the (documentation)[https://github.com/tailwindlabs/tailwindcss-container-queries]
Add a @container
class to the a parent div and then use prefixes to target the container size like this @lg:bg-pink-400
. Matrix blocks by default have a @container
so it is easy to use containers out of the box.
<div class="@container">
<div class="@lg:bg-pink-400">
This div will have a pink background when the container is larger than 32rem.
</div>
</div>
when you are ready to deploy your code run npx mix -p
to optimize images in /src/img/
optimized images will be output in /public/assets/images
this will also run the critical css task which you can configure at line 143 by adding in an array of urls and templates
urls: [{
url: '',
template: 'home'
},
{
url: 'contact',
template: 'singles/contact'
},
],
There is an empty tailwind.config.js file at the root of the repository. Add config settings as necessary but I do have some conventions that I use on all projects
For colors use colornameBrand
where colorname is red
, blue
, or whatever the color is. and for font family use the name of the font. Below you can seen an example taken from another project in the extend key.
colors: {
redBrand: {
light: '#fce9e8',
default: '#de242b',
dark: '#990e3d',
},
grayBrand: {
light: '#f2f2f2',
default: '#637a84',
},
textBrand: {
light:'#334960',
default: '#3a4250',
},
blackBrand: '#041e26',
},
fontFamily: {
karla: ['Karla', 'sans-serif'],
montserrat: ['Montserrat', 'serif'],
},
I aim to ensure default templates pass accessibility tests - except for color contrast as that will need to be taken into account during the design phase.
Dark mode toggle buttons are built in and are added via an include on line 101 of _includes/dark-mode. If you are not using dark-mode comment out this file. Dark mode has 3 buttons dark, light, & system as per my article on this Dark Mode with Alpine.js and Tailwind
update styles to use the dark prefix like this.
<div class="bg-gray-100 dark:bg-gray-800">
<h2 class="text-black dark:text-white">My title goes here</h2>
<!-- more code -->
</div>
The main navigation has 2 options: one with dropdowns activated on click and the other activated on hover. On click dropdowns are the preferred methond for usability and accessibilty reasons. However sometimes clients insist on using hover so there is an option for that.
Template defaults to on click dropdowns to change to hover dropdowns comment line 67 and uncomment line 74 of _layout.twig
{#
// main nav click dropdown this is better user experience
// and better for accessibility
// works with tertiary level dropdowns
#}
{% include '_includes/main-nav' %}
{#
// main nav hover dropdown
// we use this when client insists on hover dropdowns
// does NOT work with tertiary dropdowns
#}
{# {% include '_includes/main-nav-hover' %} #}
Fragments are a section that is intended for creating reusable content. Often you will need a Call To Action that is duplicated around the site. In this section you create that Call to Action and then using the fragments block in the content builder pull it in to that entry.
Other uses may include a block with Related Entries, a Slideshow, or photo gallery that gets featured around the site.
There is one Fragment already added that is a call to action with a button to the Contact page.
Floated labels are already added to the css. To use floated labels set your html like this for Input fields
<div class="relative">
<input
type="text"
id="city"
class="w-full rounded-lg floating-input"
name="city"
value=""
autocomplete="city"
aria-label="City Name"
placeholder="City Name">
<label for="city" class="floating-label">{{ "City Name"|t }}</label>
</div>
And for selects use this:
<div class="relative">
<select
name="country"
id="country"
class="rounded-lg floating-select"
{# on click works with mouse but not keyboard... hmmm #}
onclick="this.setAttribute('value', this.value);"
value="">
<option value=""></option>
<option value="Canadas">Canada</option>
<option value="USA">United States</option>
</select>
{# <span class="highlight"></span> #}
<label class="floating-label">Country</label>
</div>
The layout template has a commented out header tag with that when enabled will make the navigation sticky. When scrolling down will disappear and re-appear when scrolling up.
This uses an include to generate a picture element with multiple sources with webp falling back to jpeg. use this example code to add an image to any page
if the image is empty uses a fallback image from placeholder.com - this can be update on line 21 of _includes/responsiveImage.twig
{{ include('_includes/responsiveImage', {
image: image,
transforms: [
{
mq:'(max-width: 767.9px)',
crop: {
width: 500,
height: 200,
mode: 'crop'
}
},
{
mq:'(min-width: 768px)',
crop: {
width: 500,
height: 200,
mode: 'crop'
}
},
{
mq:'(min-width: 1024px)',
crop: {
width: 300,
height: 100,
mode: 'crop'
}
},
{
mq:'(min-width: 1280px)',
crop: {
width: 700,
height: 250,
mode: 'crop'
}
},
],
attributes: {
alt: image.altText ?? image.title ?? null,
class: '',
loading: 'lazy',
dataAttributes: ''
},
}, with_context = false) }}
The following plugins are installed and ready to be used on the site. I prefer to keep plugin usage to a minimum so do not install a plugin unless absolutely necessary. If it can be done natively, it should be done natively.
- Environment Label - adds a color bar across the control panel indicating current environmen
- Minify - minifies html/css/js on production
- CKEditor - Rich Text Editor
- Retcon - extra twig filters
- SEOmatic - used for all SEO.
- Control Panel CSS - add custom styles to the CP
- Hyper - used for buttons and other linkks
- ~~User Manual - in CP user manual ~~ removed until a Craft 5 version is available
- Knock Knock - password protect staging site (pass: letmein)
- Typogrify
- Sprig - Reactive components
- AssetRev - link to css and js files with manifest.json file names
See the typogrify docs for advanced usage. For basic use add the typography filter to your redactor fields like this
{{ entry.copy|typogrify }}
Sprig adds reactive components. See the documentation and/or my article on Reactive Pagination With Sprig for examples.
Additionally NOTE that sprig will only reload components once when using the localhost:3000
url that comes with the build process. When building/testing sprig components reload manually using your localhost domain - i.e. https://site.ddev.com
The contact form is powered by the first party contact form plugin and Sprig. be sure to update the Email varaibles in dotenv so that email works correctly. Go to plugins > contact form
and update the Sender Text and Subject text of your emails.
The style guide will automatically create the color palatte from your tailwind config. Note: - it only works with custom colors not tailwind colors. Additionally custom colors need to be added before any tailwind colors and be in this format:
grayBrand: {
light: '#DADADA',
DEFAULT: '#373F41',
},
using tailwind dot notation does not work if you have a color that does not have other options be sure to use the above format with DEFAULT
as the key.
Each time you update the colors you will need to run the following command
npm run export-tailwind-config
Which will export a json list in templates/_tw-config
. Also see the comments in templates/styleguide
.
Uncomment block with .testing
class and then copy/paste the generated classes into the templates/_whitelist.twig
file.
A hero component is available with three options:
- Standard Hero - image, Hero Title, Copy, Button
- Basic Hero - no image, just a title and a dark background
- Slider Hero - same as standard but operates as a slider - maximum 5 slides
There is also a basic matrix field for a content builder. Once I have more time I will create a longform content CKEditor field to replace the matrix content builder.
If you ever need to remove the vender folder and basically reset all things composer run this command
composer nuke
This will delete the vendor folder, composer.lock, clear composers cache, and then run composer update. You can find the full command in the scripts section of composer.json