# data[].attributes.title
Using Prefers Color Scheme and CSS Custom Properties 

# data[].attributes.metatag[].attributes.content
Using prefers-color-scheme and CSS Custom Properties to provide a theme for the users preferred appearance.

# data[].attributes.metatag[].attributes.content
Using prefers-color-scheme and CSS Custom Properties to provide a theme for the users preferred appearance.

# data[].attributes.body.value
What is prefers-color-scheme?

prefer-color-scheme is a CSS Media feature that detects the user's system's preferred appearance, whether it be light or dark, and then load the styles accordingly. There is no need for a theme colour mode toggle or switcher using prefers-color-scheme and it presumes that the user has their system set to how they prefer.

The full back is light and if you have privacy.resistFingerprinting = true in Firefox the prefers color scheme will full back to this.

Using prefers-color-scheme

/* This will only ever be rendered if prefers-color-scheme isn't support */
div {
  color: #aaf1c3;
  background-color: yellow;
}

@media (prefers-color-scheme: light) {
  div {
    color: #3e5a47;
    background-color: #fff6dc;
  }
}

@media (prefers-color-scheme: dark) {
  div {
    color: ##b9f3cc;
    background-color: #292900;
  }
}

So there is only really the need to have a default and then add a dark theme.

div {
    color: #3e5a47;
    background-color: #fff6dc;
  }


@media (prefers-color-scheme: dark) {
  div {
    color: #b9f3cc;
    background-color: #292900;
  }
}

The above code will render the below, left being dark and right being light or default.

Using the prefers-color-scheme you can also tell the user which mode they are in, the following box tells you what colour mode your system is set to and makes use of a display property set to none.

Dark Mode or Light Mode?

You are in Light Mode

You are in Dark Mode

Here's the code with the display property for the above.

div {
    color: #3e5a47;
    background-color: #fff6dc;
  }
P.darkmode {
    display: none;
  }

@media (prefers-color-scheme: dark) {
  div {
    color: #b9f3cc;
    background-color: #292900;
  }
  P.darkmode {
    display: inline-block;
  }
  P.lightmode {
    display: none;
  }
}

Using :root Selector and CSS Custom Properties

Now we have the basics of how this works let's look at using custom properties to set the colour scheme in the :root element like in the below code snippet.

:root {
  --body-color: #3e5a47;
  --background-color: #fff6dc;
  --heading-color: #4e534c;
  }

body {
  color: var(--body-color);
  background-color: var(--background-color);
}
h1,h2,h3,h4 {
  color: var(--heading-color);
}

@media (prefers-color-scheme: dark) {
  :root  {
    --body-color: #b9f3cc;
    --background-color: #292900;
    --heading-color: #c5eab7;
  }
}

In doing this now all we need to do is override the custom properties in our prefers-color-scheme @media query's :root selector for our dark theme. Below is a screen capture for this site at the time of publishing, see how easy it is set the whole scheme in the :root selector using CSS custom properties?

Final Thoughts

With 88% support at the time of writing and full-back set to light, this is one feature that can be included with all sites and there is no reason not too. One thing to note is that it does rely on the user setting their preferred colour mode in their system settings which brings up the question should we as designers and developers add a small message box that informs users that their system supports this or should we provide a colour switcher? I'll allow you to answer that.

Secondly, if you do implement this in your themes, remember to take special care in reviewing your colour palette and that the colours you choose adhere to at least the minimum colour contrast as per the WCAG (Web Content Accessibility Guidelines). I have written about colour contrast in another article What is Colour Contrast and Why it Matters in Web Design. If you are interested follow that link and have a read.

In following articles, I will be covering mostly front-end development and UX/UI topics in an attempt to design better interfaces. I will also be covering backend from time to time in the way of server management and CMS options. Sign up now to hear it first, link at below.

# data[].attributes.body.processed
What is prefers-color-scheme?

prefer-color-scheme is a CSS Media feature that detects the user's system's preferred appearance, whether it be light or dark, and then load the styles accordingly. There is no need for a theme colour mode toggle or switcher using prefers-color-scheme and it presumes that the user has their system set to how they prefer.

The full back is light and if you have privacy.resistFingerprinting = true in Firefox the prefers color scheme will full back to this.

Using prefers-color-scheme

/* This will only ever be rendered if prefers-color-scheme isn't support */
div {
  color: #aaf1c3;
  background-color: yellow;
}

@media (prefers-color-scheme: light) {
  div {
    color: #3e5a47;
    background-color: #fff6dc;
  }
}

@media (prefers-color-scheme: dark) {
  div {
    color: ##b9f3cc;
    background-color: #292900;
  }
}

So there is only really the need to have a default and then add a dark theme.

div {
    color: #3e5a47;
    background-color: #fff6dc;
  }


@media (prefers-color-scheme: dark) {
  div {
    color: #b9f3cc;
    background-color: #292900;
  }
}

The above code will render the below, left being dark and right being light or default.

Image

Using the prefers-color-scheme you can also tell the user which mode they are in, the following box tells you what colour mode your system is set to and makes use of a display property set to none.

Dark Mode or Light Mode?

You are in Light Mode

You are in Dark Mode

Here's the code with the display property for the above.

div {
    color: #3e5a47;
    background-color: #fff6dc;
  }
P.darkmode {
    display: none;
  }

@media (prefers-color-scheme: dark) {
  div {
    color: #b9f3cc;
    background-color: #292900;
  }
  P.darkmode {
    display: inline-block;
  }
  P.lightmode {
    display: none;
  }
}

Using :root Selector and CSS Custom Properties

Now we have the basics of how this works let's look at using custom properties to set the colour scheme in the :root element like in the below code snippet.

:root {
  --body-color: #3e5a47;
  --background-color: #fff6dc;
  --heading-color: #4e534c;
  }

body {
  color: var(--body-color);
  background-color: var(--background-color);
}
h1,h2,h3,h4 {
  color: var(--heading-color);
}

@media (prefers-color-scheme: dark) {
  :root  {
    --body-color: #b9f3cc;
    --background-color: #292900;
    --heading-color: #c5eab7;
  }
}

In doing this now all we need to do is override the custom properties in our prefers-color-scheme @media query's :root selector for our dark theme. Below is a screen capture for this site at the time of publishing, see how easy it is set the whole scheme in the :root selector using CSS custom properties?

Image

To see in action you need to switch your appearance mode in your system settings

Final Thoughts

With 88% support at the time of writing and full-back set to light, this is one feature that can be included with all sites and there is no reason not too. One thing to note is that it does rely on the user setting their preferred colour mode in their system settings which brings up the question should we as designers and developers add a small message box that informs users that their system supports this or should we provide a colour switcher? I'll allow you to answer that.

Secondly, if you do implement this in your themes, remember to take special care in reviewing your colour palette and that the colours you choose adhere to at least the minimum colour contrast as per the WCAG (Web Content Accessibility Guidelines). I have written about colour contrast in another article What is Colour Contrast and Why it Matters in Web Design. If you are interested follow that link and have a read.

In following articles, I will be covering mostly front-end development and UX/UI topics in an attempt to design better interfaces. I will also be covering backend from time to time in the way of server management and CMS options. Sign up now to hear it first, link at below.

# data[].attributes.body.summary
Using prefers-color-scheme and CSS Custom Properties to provide a theme for the users preferred appearance. 

# data[].attributes.metatag[].attributes.content
The Problem On mobile devices, if the font-size is set to less than 16px the user of the form will get a jumpy and unpleasant experience when clicking in an input element. This is because mobile browsers require input font-sizes to be at least 16px.

# data[].attributes.metatag[].attributes.content
The Problem On mobile devices, if the font-size is set to less than 16px the user of the form will get a jumpy and unpleasant experience when clicking in an input element. This is because mobile browsers require input font-sizes to be at least 16px.

# data[].attributes.body.value
The Problem

On mobile devices, if the font-size is set to less than 16px the user of the form will get a jumpy and unpleasant experience when clicking in an input element. This is because mobile browsers require input font-sizes to be at least 16px.

The Fix

Explicitly Set font-size

If you are using a library or have made you input font-sizes small on desktop be sure to set a mobile size or better still use default size for mobile and progressively enhance for desktop using a min-width media query.

Below is the code you need add, it selects all form elements that allow a user to add text.

select,
textarea,
input[type="text"],
input[type="submit"],
input[type="email"],
input[type="password"],
input:focus {
  font-size: 16px !important
}

Do Not Set Viewport user-scalable to no

I have included this solution mainly to point out that even though it does work it should not be use, as noted on MDN using user-scalable=no can cause accessibility issues with users, allowing users to zoom in and out on mobile devices is recommended.

Below is the viewport meta tag with user-scalable=no, no need to add this as default is yes.

<head>
    <title>viewport meta tag</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
</head>

# data[].attributes.body.processed
The Problem

On mobile devices, if the font-size is set to less than 16px the user of the form will get a jumpy and unpleasant experience when clicking in an input element. This is because mobile browsers require input font-sizes to be at least 16px.

Image

The Fix

Explicitly Set font-size

If you are using a library or have made you input font-sizes small on desktop be sure to set a mobile size or better still use default size for mobile and progressively enhance for desktop using a min-width media query.

Below is the code you need add, it selects all form elements that allow a user to add text.

select,
textarea,
input[type="text"],
input[type="submit"],
input[type="email"],
input[type="password"],
input:focus {
  font-size: 16px !important
}

Do Not Set Viewport user-scalable to no

I have included this solution mainly to point out that even though it does work it should not be use, as noted on MDN using user-scalable=no can cause accessibility issues with users, allowing users to zoom in and out on mobile devices is recommended.

Below is the viewport meta tag with user-scalable=no, no need to add this as default is yes.

<head>
    <title>viewport meta tag</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
</head>

# data[].attributes.title
Custom Icon Font Sets for Everyone and Why You Might Want to Use Them

# data[].attributes.metatag[].attributes.content
Including Custom Icon Fonts on Your Website, how to make them, using Fontello as an example.

# data[].attributes.metatag[].attributes.content
Including Custom Icon Fonts on Your Website, how to make them, using Fontello as an example.

# data[].attributes.body.value
In this piece, I will be explaining how you can create your own icon font set easily and how to include it on your site.

Why would I want to create a custom icon font set?

First I'll tackle the above question. I will write about this in a second part in more depth so will only cover it very briefly with the 3 points below.

The main reason is size, by packaging up a custom font you can make it only include the icons you need.

The second reason is you can mix and match icon sets and then combine them, this could be due to the style you like but then needing to add one or 2 icons from another set to provide the needed icon or icons.

Finally, you may want to add a custom icon as I did for a ski resort. This is possible by importing an SVG to include in your custom set. Read on and I will cover this in the creating a custom font glyph section below.

Creating Fonts Sets

Okay let's see how easy this is.

In this example I will use Fontello. Icomoon has a similar free service, so be sure to check them out at Icomoon. If you are just starting out, you can go to either of the sites, browse and select icons and upload custom SVG icons to get converted.

Starting a new Custom Font set

Visit Fontello and follow the steps below.

1.  Selecting Icons from the huge available free selection. This is as simple as browsing or searching for what you need. Once you have found what you need you can click on the icons to select them.

Creating a custom font glyph

2. This step is optional but in Fontello you can add a SVG by dropping it into the area at the top of the screen.

Things to think about and do when creating a custom icon. Make sure the SVG is optimized and that the detail isn't overly complicated. does it represent what it illustrates clearly? is it consistent with the other icons? Maybe, I should cover this in more detail, hmm.

3. Name your font and font glyphs.
This step is optional too. On Fontello you can name your font, customize the separate icon names, customize the codes, the prefixes, make the prefixes suffixes, all of this is 100% optional and unneeded, the default settings work fine so my recommendation is to leave as default.

4. Download Webfont
After you have selected your items and adding custom icons click on Download webfont button (#). If you want you can export the configuration file by using Get Config only option in the dropdown.

Add the Font to your Site

The fun bit. Seeing the fruits of your labour.

In the directory, you download there are a lot of files that include various methods to use the font. You can either add the fonts directly to your HTML or you can use the code in a ::before pseudo class/element.

Either method works and I don't want to get caught up in the pros and cons of either method here, choose one and go with it.

Before we add our elements to the HTML and the CSS to the stylesheet we have have to add the directories and link the stylesheet to our HTML page.

Basic directory set up and HTML link

/* Add a link in the <head> of the HTML */

<link rel="stylesheet" href="css/fontello.css">

Now it is time to add the icons to out HTML and the CSS.

Using pseudo before

Add the icon prefixed class to your element, any element can be used if you don't care about supporting IE7.

<i class="icon-emo-beer"></i>

<p class="icon-emo-beer">My nice parargraph...</p>

Specify the custom font in your stylesheet using the @font-face rule.

Add the CSS with the [class^=".. ] and [class*=".. ] attribute selector to the fontello.css stylesheet as shown below.

More on attribute selectors https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors

@font-face {
  font-family: 'fontello';
  src: url('../font/fontello.eot?37220454');
  /* for the complete file content check the downloaded fontello.css file or your-custom-font-name-css */
}

[class^="icon-"]:before, [class*=" icon-"]:before {
  font-family: "fontello";
  font-style: normal;
  /* for the complete file content check the downloaded fontello.css file or your-custom-font-name-css */
}

/* individaul icon before pseudo class content */
.icon-emo-beer:before { content: '\e80b'; } /* '' */

Using icon code

The icon font code is used in this example, it is preceded by &#, the codes are found in the downloaded files.

<i class="demo-icon icon-twitter">&#xe805;</i>

The CSS

Specify the custom font in your stylesheet using the @font-face rule.

Be sure to check the complete file but notice no pseudo-element.

@font-face {
  font-family: 'fontello';
  src: url('../font/fontello.eot?37220454');
  /* for the complete file content check the downloaded fontello.css file or your-custom-font-name-css */
}

.demo-icon {
  font-family: "fontello";
  font-style: normal;
  /* for the complete file content check the downloaded fontello.css file or your-custom-font-name-css */
}


.icon-twitter {
  color: blue;
}

Well, that's about it for including a font in your site. Following I will share a method I am using in my workflow to get custom icon fonts in my site faster and this is made possible my importing the JSON files back into Fontello.

Using an old custom icon Font set

By old I mean one I have used on other sites.

I already have a few icon sets that I have used in the past if I need to make a new set I can always use these to make a new set. I have found most sites will need social icons, phone, email, and various others. The icon sets come with a JSON config file which makes it easy to modify.

Did you say JSON? Yes, I did!

Editing JSON files

You can combine a few config files and delete unneeded icons, save it and then upload it to Fontello or Icomoon. The formats are different so be aware that the Fontello config files can't be used in Icomoon and visa versa. If you don't want to combine a few config files you can jump to step 7.

Follow these steps to combine & re-use your previously exported fonts

1. Find the config file which is in the font package

2. Open the config file in your favourite text editor

3. Remove the icon font glyphs you don't need from the file

4. Open the second file and do the same

5. Combine the files by copying the font nodes/objects from one file to the other
If you have an SVG icon definition, make sure you keep it in the same format/object structure.

6. Save it as a new file.

7. Upload to Fontello.

8. Add new icons if you want.

9. Continue with step 4 above.

Animations

Fontello provides the animation.css for if you are using the icon fonts for loaders which is a nice bonus. Just include the animation file or combine the @keyframe rule and animation property values with your other CSS.

Thoughts

I feel it is totally worth the extra effort when putting a site into production as every byte you can save will make your user happier. Also, you can change colours easily for dark and light mode without needing to create a new version for each display mode.

That bit of extra shows that as a company or designer that you care about your design or craft and people do notice it when things are easy to use.

A final note is I do feel if you are using Icons including a text alternative is important.

Thanks for reading.

# data[].attributes.body.processed
In this piece, I will be explaining how you can create your own icon font set easily and how to include it on your site.

Why would I want to create a custom icon font set?

First I'll tackle the above question. I will write about this in a second part in more depth so will only cover it very briefly with the 3 points below.

The main reason is size, by packaging up a custom font you can make it only include the icons you need.

The second reason is you can mix and match icon sets and then combine them, this could be due to the style you like but then needing to add one or 2 icons from another set to provide the needed icon or icons.

Finally, you may want to add a custom icon as I did for a ski resort. This is possible by importing an SVG to include in your custom set. Read on and I will cover this in the creating a custom font glyph section below.

Creating Fonts Sets

Okay let's see how easy this is.

In this example I will use Fontello. Icomoon has a similar free service, so be sure to check them out at Icomoon. If you are just starting out, you can go to either of the sites, browse and select icons and upload custom SVG icons to get converted.

Starting a new Custom Font set

Visit Fontello and follow the steps below.

Image

Easy to use and understand UI

1.  Selecting Icons from the huge available free selection. This is as simple as browsing or searching for what you need. Once you have found what you need you can click on the icons to select them.

Creating a custom font glyph

2. This step is optional but in Fontello you can add a SVG by dropping it into the area at the top of the screen.

Things to think about and do when creating a custom icon. Make sure the SVG is optimized and that the detail isn't overly complicated. does it represent what it illustrates clearly? is it consistent with the other icons? Maybe, I should cover this in more detail, hmm.

3. Name your font and font glyphs.
This step is optional too. On Fontello you can name your font, customize the separate icon names, customize the codes, the prefixes, make the prefixes suffixes, all of this is 100% optional and unneeded, the default settings work fine so my recommendation is to leave as default.

4. Download Webfont
After you have selected your items and adding custom icons click on Download webfont button (#). If you want you can export the configuration file by using Get Config only option in the dropdown.

Add the Font to your Site

The fun bit. Seeing the fruits of your labour.

In the directory, you download there are a lot of files that include various methods to use the font. You can either add the fonts directly to your HTML or you can use the code in a ::before pseudo class/element.

Either method works and I don't want to get caught up in the pros and cons of either method here, choose one and go with it.

Before we add our elements to the HTML and the CSS to the stylesheet we have have to add the directories and link the stylesheet to our HTML page.

Basic directory set up and HTML link

Image

/* Add a link in the <head> of the HTML */

<link rel="stylesheet" href="css/fontello.css">

Now it is time to add the icons to out HTML and the CSS.

Using pseudo before

Add the icon prefixed class to your element, any element can be used if you don't care about supporting IE7.

<i class="icon-emo-beer"></i>

<p class="icon-emo-beer">My nice parargraph...</p>

Specify the custom font in your stylesheet using the @font-face rule.

Add the CSS with the [class^=".. ] and [class*=".. ] attribute selector to the fontello.css stylesheet as shown below.

More on attribute selectors https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors

@font-face {
  font-family: 'fontello';
  src: url('../font/fontello.eot?37220454');
  /* for the complete file content check the downloaded fontello.css file or your-custom-font-name-css */
}

[class^="icon-"]:before, [class*=" icon-"]:before {
  font-family: "fontello";
  font-style: normal;
  /* for the complete file content check the downloaded fontello.css file or your-custom-font-name-css */
}

/* individaul icon before pseudo class content */
.icon-emo-beer:before { content: '\e80b'; } /* '' */

Using icon code

The icon font code is used in this example, it is preceded by &#, the codes are found in the downloaded files.

<i class="demo-icon icon-twitter">&#xe805;</i>

The CSS

Specify the custom font in your stylesheet using the @font-face rule.

Be sure to check the complete file but notice no pseudo-element.

@font-face {
  font-family: 'fontello';
  src: url('../font/fontello.eot?37220454');
  /* for the complete file content check the downloaded fontello.css file or your-custom-font-name-css */
}

.demo-icon {
  font-family: "fontello";
  font-style: normal;
  /* for the complete file content check the downloaded fontello.css file or your-custom-font-name-css */
}


.icon-twitter {
  color: blue;
}

Well, that's about it for including a font in your site. Following I will share a method I am using in my workflow to get custom icon fonts in my site faster and this is made possible my importing the JSON files back into Fontello.

Using an old custom icon Font set

By old I mean one I have used on other sites.

I already have a few icon sets that I have used in the past if I need to make a new set I can always use these to make a new set. I have found most sites will need social icons, phone, email, and various others. The icon sets come with a JSON config file which makes it easy to modify.

Did you say JSON? Yes, I did!

Editing JSON files

You can combine a few config files and delete unneeded icons, save it and then upload it to Fontello or Icomoon. The formats are different so be aware that the Fontello config files can't be used in Icomoon and visa versa. If you don't want to combine a few config files you can jump to step 7.

Follow these steps to combine & re-use your previously exported fonts

1. Find the config file which is in the font package

Image

2. Open the config file in your favourite text editor

3. Remove the icon font glyphs you don't need from the file

4. Open the second file and do the same

5. Combine the files by copying the font nodes/objects from one file to the other
If you have an SVG icon definition, make sure you keep it in the same format/object structure.

6. Save it as a new file.

7. Upload to Fontello.

8. Add new icons if you want.

9. Continue with step 4 above.

Animations

Fontello provides the animation.css for if you are using the icon fonts for loaders which is a nice bonus. Just include the animation file or combine the @keyframe rule and animation property values with your other CSS.

Thoughts

I feel it is totally worth the extra effort when putting a site into production as every byte you can save will make your user happier. Also, you can change colours easily for dark and light mode without needing to create a new version for each display mode.

That bit of extra shows that as a company or designer that you care about your design or craft and people do notice it when things are easy to use.

A final note is I do feel if you are using Icons including a text alternative is important.

Thanks for reading.

# data[].attributes.body.summary
Including Custom Icon Fonts on Your Website, how to make them, using Fontello as an example.

# data[].attributes.metatag[].attributes.content
2020 was trying for many and for me, that was no different. That said 2020 was a year of change, moving on from the old and in the end success. I have outlined my year of success below

# data[].attributes.metatag[].attributes.content
2020 was trying for many and for me, that was no different. That said 2020 was a year of change, moving on from the old and in the end success. I have outlined my year of success below

# data[].attributes.body.value
2020 was trying for many and for me, that was no different. That said 2020 was a year of change, moving on from the old and in the end success. I have outlined my year of success below

The first 6 months of 2020 was hard. I was wrapping up and moving on from a major project for a company I helped build from nothing to turning over 6 million dollars plus a year. I managed the complete online presence for this company, minus a few things in the end, and had become a partner as well. Even though I had put my life into this it was time to move on and let others take over. Unfortunately due to COVID-19, this project was also cut short and the phase I was working on was not completed, a lot of good work there gone to waste. One of the strange things that came about from this was if I had remained on I would have probably had budgets cut back to almost 0 and asked to help out, so the timing was somewhat perfect. I am not saying COVID-19 is a good thing, just that it is strange how things happen sometimes.

Overall this was a positive experience for me and made me stronger, taught me a lot about how the world works, and that I can help build a company & rank it at number 1. I'll leave it at that and concentrate on the future and my other achievements.

Studying Japanese

I wrote 5 sentences in Japanese every day. I started to do this back in May 2019. I have it marked as kids day here in Japan which is 5/5, but 2020 was the first year I did this every day and this is one habit I will continue. I do it first while drinking coffee and reading. My Japanese even though still very elementary is getting better by the day, word retention and basic conversation are the benefits from this. I wish I had started this simple habit sooner.

100 Days of Code

I finished #100DaysofCode round 1, racking up 145 days in total because I can't count. I started my first round of #100DaysofCode in 2019. I decided not to count work and since I had a few server issues and other things to get done I had to take a few breaks. I did code on those break days, however.

I started #100DaysofCode round 2, currently at day #70. I start this in November but failed after 10 days, so I got the mindset right and started again. My goal is to code 100 days in a row and by the end be producing something every day in that hour, something outside of my business but something that adds to my business.

New Technology

I started to learn Vue.js. I had played around with frameworks over the years, Angular 2 and React, but never really had the use for them. In the end, Vue.js seemed nice so have committed to it. I put a basic site live and I am using it to build small things for #100DaysofCode and writing about it. You can check my Vue.js articles here.

Start Again

I decided to relearn everything in web development or a least learn it deeper and also concentrate on Front-end development and UX/UI design.

This is something that I had been doing with #100DaysofCode, but I am now making it more the thing. As you work in web development and other related fields you are always producing, building, and successfully pushing stuff to production but you may not actually fully understand it. This is okay and in reality, being able to problem solve is the main job of a developer; solve the problem and move on.

Over the years you gain a deeper understanding, can understand jargon faster, pick up new concepts faster, and then things really start to click. I really now think that I am climbing up and my impostor syndrome is nothing more than something telling me I am breaking new ground.

Git and Git Flow

I started using Git Flow in my workflow. Even though I don't really mark the time I got into web development until around 2010, I had been building sites earlier than that part-time while teaching at language institutes, technical colleges, and eikaiwa (English conversation schools) in Sapporo City while doing my fair share riding the best powder snow in the world. If you ever come to Japan and encounter ground-staff at the airport, blame me if their English is bad.

That joke aside and the reason I mention it is because this was the time before Git and even though I was aware of other source control I didn't use it. I built basic HTML-v1-HTML-v1.1-HTML-v1.2 websites, you'll know the story. I started to take an interest in Git at some stage and used it to track and log separate installs for production websites and this worked. I used Git to work on my own project a bit more but a lot of the time didn't bother. Last few years I have finally started to use Git, not in all projects but I have now implemented Git Flow in some of my development workflow.

Social Media

I started using social media again¹. This was really a 2019 thing but I took a break again in 2020. Unsure if this is a win, but I know I need to use it to meet people so being able to safely use social media without feeling like I need to prove myself to people or that people are attacking me is a good start. I should mention I have used Instagram since 2010 as I liked it because I could share photos and like photos. I have just started on Instagram again after been a little slack due to the changes in usage, I am fully embracing it again, starting now.

Back-end

I documented my whole back-end process, creating a LAMP stack on Ubuntu, setting up virtual hosts with and without SSL, and installing Drupal with composer and updating. I collated years of notes to make the process faster, now I can get a LAMP stack up with Drupal 9 lightning fast. For me this is enough to know, I have managed servers as part of my job but now I will stick with what I know or APIs and JAMstack and put my energy into producing top-notch front-end user experiences.

Change

I changed the direction of my business. I had been a contract worker in a partnership. Last year I decided to take a step back and work out where I wanted to go. Having full-stack capabilities is great but I will not offer them as a service. I am wanting to get back to being creative but in the tech field somewhere, doing exactly what I am unsure. In the meantime, I can help small businesses build online presences as I have a wealth of experience and helped many people in doing this.

Side Project

I finished my side project mountain house. I bought this house 12 year ago. I had lived in it, then share-homed on Airbnb, then moved out and rented the whole house; rent money always being put back in. The house is now done, there are a few small things that need to be done so that guests can have a great stay and so the management in winter isn't such a problem. Winters are harsh here, having to deal with frozen pipes and massive build-up of snow on the roofs is a job in itself or if managed properly through good design it is not really an issue.

New direction New Site

I built this site, may not seem a lot now but it is a new direction for me and the thought processes and ideas that have come about while getting this far will come to fruition this year. Like any project, best to just get online and improve it slowly and continuously. Agile, Kanban, and continuous development and improvement is something I have a lot of experience in from building and manageing sites and online presences over the years.

Stack Overflow

I started to contribute to Stack Overflow. I started to see if I could help people on Stack Overflow. This year I hope to contribute more over there. Just a small start but it is easier for me to answer questions there.

Goodbye 2020

Well that's about it for 2020, goodbye. For me, it was a good year, while starting out working for others and ending up a freed person was a great feeling. Here is to 2021.

I will follow up shortly on my goals for this year but I don't think they will be too wild. I think I have always pressured myself too much and in doing so I have been unrealistic. I think a big achievement every week will be the goal, but planned far enough ahead so that these things are part of a bigger purpose. Thanks for reading and if you are interested in fronted-end development be sure to sign up to my newsletter.

¹I had been doing a small bit of Facebook advertising (and Google Ad(word)s) quite successfully for various companies. I don't really consider this social media though.

# data[].attributes.body.processed
2020 was trying for many and for me, that was no different. That said 2020 was a year of change, moving on from the old and in the end success. I have outlined my year of success below

The first 6 months of 2020 was hard. I was wrapping up and moving on from a major project for a company I helped build from nothing to turning over 6 million dollars plus a year. I managed the complete online presence for this company, minus a few things in the end, and had become a partner as well. Even though I had put my life into this it was time to move on and let others take over. Unfortunately due to COVID-19, this project was also cut short and the phase I was working on was not completed, a lot of good work there gone to waste. One of the strange things that came about from this was if I had remained on I would have probably had budgets cut back to almost 0 and asked to help out, so the timing was somewhat perfect. I am not saying COVID-19 is a good thing, just that it is strange how things happen sometimes.

Overall this was a positive experience for me and made me stronger, taught me a lot about how the world works, and that I can help build a company & rank it at number 1. I'll leave it at that and concentrate on the future and my other achievements.

Studying Japanese

I wrote 5 sentences in Japanese every day. I started to do this back in May 2019. I have it marked as kids day here in Japan which is 5/5, but 2020 was the first year I did this every day and this is one habit I will continue. I do it first while drinking coffee and reading. My Japanese even though still very elementary is getting better by the day, word retention and basic conversation are the benefits from this. I wish I had started this simple habit sooner.

100 Days of Code

I finished #100DaysofCode round 1, racking up 145 days in total because I can't count. I started my first round of #100DaysofCode in 2019. I decided not to count work and since I had a few server issues and other things to get done I had to take a few breaks. I did code on those break days, however.

I started #100DaysofCode round 2, currently at day #70. I start this in November but failed after 10 days, so I got the mindset right and started again. My goal is to code 100 days in a row and by the end be producing something every day in that hour, something outside of my business but something that adds to my business.

New Technology

I started to learn Vue.js. I had played around with frameworks over the years, Angular 2 and React, but never really had the use for them. In the end, Vue.js seemed nice so have committed to it. I put a basic site live and I am using it to build small things for #100DaysofCode and writing about it. You can check my Vue.js articles here.

Start Again

I decided to relearn everything in web development or a least learn it deeper and also concentrate on Front-end development and UX/UI design.

This is something that I had been doing with #100DaysofCode, but I am now making it more the thing. As you work in web development and other related fields you are always producing, building, and successfully pushing stuff to production but you may not actually fully understand it. This is okay and in reality, being able to problem solve is the main job of a developer; solve the problem and move on.

Over the years you gain a deeper understanding, can understand jargon faster, pick up new concepts faster, and then things really start to click. I really now think that I am climbing up and my impostor syndrome is nothing more than something telling me I am breaking new ground.

Git and Git Flow

I started using Git Flow in my workflow. Even though I don't really mark the time I got into web development until around 2010, I had been building sites earlier than that part-time while teaching at language institutes, technical colleges, and eikaiwa (English conversation schools) in Sapporo City while doing my fair share riding the best powder snow in the world. If you ever come to Japan and encounter ground-staff at the airport, blame me if their English is bad.

That joke aside and the reason I mention it is because this was the time before Git and even though I was aware of other source control I didn't use it. I built basic HTML-v1-HTML-v1.1-HTML-v1.2 websites, you'll know the story. I started to take an interest in Git at some stage and used it to track and log separate installs for production websites and this worked. I used Git to work on my own project a bit more but a lot of the time didn't bother. Last few years I have finally started to use Git, not in all projects but I have now implemented Git Flow in some of my development workflow.

Social Media

I started using social media again¹. This was really a 2019 thing but I took a break again in 2020. Unsure if this is a win, but I know I need to use it to meet people so being able to safely use social media without feeling like I need to prove myself to people or that people are attacking me is a good start. I should mention I have used Instagram since 2010 as I liked it because I could share photos and like photos. I have just started on Instagram again after been a little slack due to the changes in usage, I am fully embracing it again, starting now.

Back-end

I documented my whole back-end process, creating a LAMP stack on Ubuntu, setting up virtual hosts with and without SSL, and installing Drupal with composer and updating. I collated years of notes to make the process faster, now I can get a LAMP stack up with Drupal 9 lightning fast. For me this is enough to know, I have managed servers as part of my job but now I will stick with what I know or APIs and JAMstack and put my energy into producing top-notch front-end user experiences.

Change

I changed the direction of my business. I had been a contract worker in a partnership. Last year I decided to take a step back and work out where I wanted to go. Having full-stack capabilities is great but I will not offer them as a service. I am wanting to get back to being creative but in the tech field somewhere, doing exactly what I am unsure. In the meantime, I can help small businesses build online presences as I have a wealth of experience and helped many people in doing this.

Side Project

I finished my side project mountain house. I bought this house 12 year ago. I had lived in it, then share-homed on Airbnb, then moved out and rented the whole house; rent money always being put back in. The house is now done, there are a few small things that need to be done so that guests can have a great stay and so the management in winter isn't such a problem. Winters are harsh here, having to deal with frozen pipes and massive build-up of snow on the roofs is a job in itself or if managed properly through good design it is not really an issue.

New direction New Site

I built this site, may not seem a lot now but it is a new direction for me and the thought processes and ideas that have come about while getting this far will come to fruition this year. Like any project, best to just get online and improve it slowly and continuously. Agile, Kanban, and continuous development and improvement is something I have a lot of experience in from building and manageing sites and online presences over the years.

Stack Overflow

I started to contribute to Stack Overflow. I started to see if I could help people on Stack Overflow. This year I hope to contribute more over there. Just a small start but it is easier for me to answer questions there.

Goodbye 2020

Well that's about it for 2020, goodbye. For me, it was a good year, while starting out working for others and ending up a freed person was a great feeling. Here is to 2021.

I will follow up shortly on my goals for this year but I don't think they will be too wild. I think I have always pressured myself too much and in doing so I have been unrealistic. I think a big achievement every week will be the goal, but planned far enough ahead so that these things are part of a bigger purpose. Thanks for reading and if you are interested in fronted-end development be sure to sign up to my newsletter.

¹I had been doing a small bit of Facebook advertising (and Google Ad(word)s) quite successfully for various companies. I don't really consider this social media though.

# data[].attributes.metatag[].attributes.content
Condensing the Composer documentation into the 2 most important scripts needed to get Composer up and running on a LAMP server.

# data[].attributes.metatag[].attributes.content
Condensing the Composer documentation into the 2 most important scripts needed to get Composer up and running on a LAMP server.

# data[].attributes.metatag[].attributes.content
composer for dependencies management of Drupal

# data[].attributes.body.value
Composer is a PHP dependency manager, for those from JavaScript and Node.js it is the cousin of npm and uses a composer.json file in the same way npm uses a packages.json.

Composer is my preferred way to install and manage a Drupal website these days. I had been using Drush with Drupal 7 for quite some time but overtime have needed to use Composer to install some modules with libraries, one off the top of my mind being SMTP Authentication, and installing any way other than using composer has been a futile task.

In this article we will look at setting up Composer on your server. I have linked to the official documents and suggest you go there to get any the install scripts. This guide could be considered a quick start guide bringing together the few scripts needed to get Composer running on your server. If you have problems make sure you check the documents or search for the error or warning on a search engine, or drop me a message.

Prerequisite

You will need SSH Terminal access and a sudo user.

You need PHP installed to install and run composer. This should be already installed if you have a LAMP stack set up. My current LAMP stack is:

Ubuntu 20.04 LTS

Apache 2

MySQL

PHP7.4

Install Composer

When Composer is initially installed it is downloaded and installed in the current directory and can be run from that directory. We will move the composer.phar archive to be used globally in the second step.

With that said, log in to your server and move into the directory you want to use. I usually download it to a virtual host in the /var/www/domain-name/public_html, but if you do that make sure you don't leave it there as it would be a security risk.

Once in the directory run the script found on the download page, please grab the code from that page, I have only included it here for reference and removed the SHA checksum number.

https://getcomposer.org/download/

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === 'some-long-SHA-checksum-number-goes-here') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"

With the script you can copy all 4 lines and paste it in the terminal, each line will be run doing the following:

Download the installer.

Check the integrity of the installer.

Install composer.

Remove the installer.

After it has installed you can check that is installed by running the .phar archive using PHP with the following script.

php composer.phar this should give you this output.

Moving composer to a global location

As stated it is not very secure to leave the composer.phar in a public_html directory so moving it to a global location is recommended. Generally adding it to the system PATH is a good place.

mv composer.phar /usr/local/bin/composer
or
sudo mv composer.phar /usr/local/bin/composer

By moving it into a composer directory in your system's PATH you now use Composer by running composer.

Try running composer or composer -v

composer will give the same output as php composer.phar and composer -v with give you a v number only.

If you have any issues with moving Composer into the system PATH check the Composer site at the following location https://getcomposer.org/doc/00-intro.md#globally

Welcome to the world of Composer

Run these two scripts and you will have Composer up and running. Once you are comfortable with the process there are some other options, listed on the download page linked at the start, you can use on the php composer-setup.php line such as --install-dir=bin. Have a play around with these to make the install process even faster.

That's it, pretty easy, now you can run Composer from anywhere on your system. It is suggested not to have Composer set up on a production server though and that it should only be used on development and staging servers and then use a GIT workflow to move updates to production but that's a different story which can be covered in the future.

Happy Composing & thanks for reading.

# data[].attributes.body.processed
Composer is a PHP dependency manager, for those from JavaScript and Node.js it is the cousin of npm and uses a composer.json file in the same way npm uses a packages.json.

Composer is my preferred way to install and manage a Drupal website these days. I had been using Drush with Drupal 7 for quite some time but overtime have needed to use Composer to install some modules with libraries, one off the top of my mind being SMTP Authentication, and installing any way other than using composer has been a futile task.

In this article we will look at setting up Composer on your server. I have linked to the official documents and suggest you go there to get any the install scripts. This guide could be considered a quick start guide bringing together the few scripts needed to get Composer running on your server. If you have problems make sure you check the documents or search for the error or warning on a search engine, or drop me a message.

Prerequisite

You will need SSH Terminal access and a sudo user.

You need PHP installed to install and run composer. This should be already installed if you have a LAMP stack set up. My current LAMP stack is:

Ubuntu 20.04 LTS

Apache 2

MySQL

PHP7.4

Install Composer

When Composer is initially installed it is downloaded and installed in the current directory and can be run from that directory. We will move the composer.phar archive to be used globally in the second step.

With that said, log in to your server and move into the directory you want to use. I usually download it to a virtual host in the /var/www/domain-name/public_html, but if you do that make sure you don't leave it there as it would be a security risk.

Once in the directory run the script found on the download page, please grab the code from that page, I have only included it here for reference and removed the SHA checksum number.

https://getcomposer.org/download/

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === 'some-long-SHA-checksum-number-goes-here') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"

With the script you can copy all 4 lines and paste it in the terminal, each line will be run doing the following:

Download the installer.

Check the integrity of the installer.

Install composer.

Remove the installer.

After it has installed you can check that is installed by running the .phar archive using PHP with the following script.

php composer.phar this should give you this output.

Image

Moving composer to a global location

As stated it is not very secure to leave the composer.phar in a public_html directory so moving it to a global location is recommended. Generally adding it to the system PATH is a good place.

mv composer.phar /usr/local/bin/composer
or
sudo mv composer.phar /usr/local/bin/composer

By moving it into a composer directory in your system's PATH you now use Composer by running composer.

Try running composer or composer -v

composer will give the same output as php composer.phar and composer -v with give you a v number only.

If you have any issues with moving Composer into the system PATH check the Composer site at the following location https://getcomposer.org/doc/00-intro.md#globally

Welcome to the world of Composer

Run these two scripts and you will have Composer up and running. Once you are comfortable with the process there are some other options, listed on the download page linked at the start, you can use on the php composer-setup.php line such as --install-dir=bin. Have a play around with these to make the install process even faster.

That's it, pretty easy, now you can run Composer from anywhere on your system. It is suggested not to have Composer set up on a production server though and that it should only be used on development and staging servers and then use a GIT workflow to move updates to production but that's a different story which can be covered in the future.

Happy Composing & thanks for reading.

# data[].attributes.body.summary
Condensing the Composer documentation into the 2 most important scripts needed to get Composer up and running on a LAMP server. 

# data[].attributes.title
Enabling Drupal 9 as a Headless CMS to work with Vue.js

# data[].attributes.metatag[].attributes.content
Working with Drupal API and enabling CORS, to work with Vue.js and other front-end libraries.

# data[].attributes.metatag[].attributes.content
Working with Drupal API and enabling CORS, to work with Vue.js and other front-end libraries.

# data[].attributes.body.value
One of the reasons I am using Drupal as my CMS, apart from using it since Drupal 6, is because of the Drupal API first approach meaning that you can build decoupled front-ends for you Drupal instance and syndicate your content to them. Read on to find out how to do this with Vue.js and what needs to be done with your Drupal site to make it all happen.

Prepare Your Drupal API

The first thing I did was to install the JSON:API in Drupal. Since JSON:API has been included with core from Drupal 8.7 it is as easy as checking a check box and clicking install on the extend page of the administration backend of your Drupal site.

If you want to you can view the JSON API for this site at the public endpoint URL but if you try to consume the API resource from an dis-allowed origin you will get a big fat no. We will fix this later but lets set up Vue.js

The endpoint for the JSON API for all Drupal sites is at /jsonapi e.g. https://designkojo.com/jsonapi but due to Drupal's default access permissions most endpoints will return "Some resources have been omitted because of insufficient authorization" and "The current user is not allowed to GET the selected resource."

Create Your Vue.js App

I am going to assume you are familiar with creating a Vue.js app using the Vue CLI by running the vue create my-project command. If not I will cover this in another article soon, sign up to my newsletter and be first to know when it hits the internet or check the Vue CLI the documentation. In this example, I am using Vue.js 2 as I had an old Vue.js App I had created last year.

To get the Drupal API end-point data we will use Axios. Axios is a promise based HTTP client which make such tasks easy from the browser. From in your App directory, we can use npm install axios. This will add the package to the node_modules directory and also add it to the dependencies section in the package.json.

With Axios installed we now need to include it in our App, to make things easy we will use the HelloWord.vue component that comes with the default Vue CLI application. HelloWorld.vue can be found in the /src/components directory. In the HelloWorld.vue, in the script section add the import statement import axios from 'axios'. Now we can use axios to get our posts from Drupal.

In the export default block of the Helloworld.vue component, lets add a mounted hook. This hook runs once the App has mounted. In this hook we will use axios to perform a GET request. In the below example we will make a request to our articles https://designkojo.com/jsonapi/node/article endpoint, then we will add the response to our post data. We need to set up our data and add posts as a data value as well.

The mounted hook is one of many hooks we can use in the Vue.js lifecycle, you can read more about the lifescycle on vuejs.org/v2

import axios from 'axios'
export default {
  name: 'HelloWorld',
  mounted() {
    axios.get('https://designkojo.com/jsonapi/node/article')
      .then(response => this.posts = response.data.data)
      .catch(error => console.log(error))
  },
  data: function() {
    return {
      posts: null
    }
  }
}

So that is it we can now use {{posts}} in the template section of our component to see our response data in our App. Let's add pre { text-align: left; } in the CSS section to make it easier to read.

But, where is it? The API is set up, the endpoint is working, it seems to respond but still no data rendered on the page. Wait what this? The error Cross-Origin Request Blocked. Okay so there is one more thing to do and that is to enable CORS on Drupal.

Enable CORS for Drupal

So this is where Drupal shines, by default CORS is disabled so we need to set this up. To do this we need to make a copy of the default.services.yml and save it as service.yml. This is in the site/default/ directory.

Once we have made a copy we need set enabled to true, add allowedHeaders, allowedMethods, and allowedOrigins. Also, don't forget to flush the cache. Below is the modified CORS section of the services.yml which shows simonramsay.net as an allowed origin. simonramsay.net is hosted on netlify at present which was an extremely hassle-free process, more on that in the weeks to come.

parameters:
  session.storage.options:

   ####
   # The above and below are part of the services.yml file that ships with Drupal.
   # I have removed all parameters except CORS and left session.storage.options to show the format of YAML hierarchy and indentation.
   # To see full file please check default.services.yml in the /sites/default directory.
   # *Please note this block is added and highlight like so for this guide only.
   ####

   # Configure Cross-Site HTTP requests (CORS).
   # Read https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
   # for more information about the topic in general.
   # Note: By default the configuration is disabled.
  cors.config:
    enabled: true
    # Specify allowed headers, like 'x-allowed-header'.
    allowedHeaders: ['content-type']
    # Specify allowed request methods, specify ['*'] to allow all possible ones.
    allowedMethods: ['GET']
    # Configure requests allowed from specific origins.
    allowedOrigins: ['https://simonramsay.net']
    # Sets the Access-Control-Expose-Headers header.
    exposedHeaders: false
    # Sets the Access-Control-Max-Age header.
    maxAge: false
    # Sets the Access-Control-Allow-Credentials header.
    supportsCredentials: false

In this article we have looked at installing the JSON:API and enabling CORS on our Drupal site, as well as installing axios in our Vue.js App and rending the response to the App template. In a following post we will look at the JSON:API endpoint in more detail, how to navigate it to get the data we need, and how to render it on our new page. We will also look at switching to Vue.js 3 and NUXTJS to make a truly modern JAM stack app with server side rendering.

Until then mata ne.👋

# data[].attributes.body.processed
One of the reasons I am using Drupal as my CMS, apart from using it since Drupal 6, is because of the Drupal API first approach meaning that you can build decoupled front-ends for you Drupal instance and syndicate your content to them. Read on to find out how to do this with Vue.js and what needs to be done with your Drupal site to make it all happen.

Prepare Your Drupal API

The first thing I did was to install the JSON:API in Drupal. Since JSON:API has been included with core from Drupal 8.7 it is as easy as checking a check box and clicking install on the extend page of the administration backend of your Drupal site.

Image

If you want to you can view the JSON API for this site at the public endpoint URL but if you try to consume the API resource from an dis-allowed origin you will get a big fat no. We will fix this later but lets set up Vue.js

The endpoint for the JSON API for all Drupal sites is at /jsonapi e.g. https://designkojo.com/jsonapi but due to Drupal's default access permissions most endpoints will return "Some resources have been omitted because of insufficient authorization" and "The current user is not allowed to GET the selected resource."

Create Your Vue.js App

I am going to assume you are familiar with creating a Vue.js app using the Vue CLI by running the vue create my-project command. If not I will cover this in another article soon, sign up to my newsletter and be first to know when it hits the internet or check the Vue CLI the documentation. In this example, I am using Vue.js 2 as I had an old Vue.js App I had created last year.

To get the Drupal API end-point data we will use Axios. Axios is a promise based HTTP client which make such tasks easy from the browser. From in your App directory, we can use npm install axios. This will add the package to the node_modules directory and also add it to the dependencies section in the package.json.

With Axios installed we now need to include it in our App, to make things easy we will use the HelloWord.vue component that comes with the default Vue CLI application. HelloWorld.vue can be found in the /src/components directory. In the HelloWorld.vue, in the script section add the import statement import axios from 'axios'. Now we can use axios to get our posts from Drupal.

In the export default block of the Helloworld.vue component, lets add a mounted hook. This hook runs once the App has mounted. In this hook we will use axios to perform a GET request. In the below example we will make a request to our articles https://designkojo.com/jsonapi/node/article endpoint, then we will add the response to our post data. We need to set up our data and add posts as a data value as well.

The mounted hook is one of many hooks we can use in the Vue.js lifecycle, you can read more about the lifescycle on vuejs.org/v2

import axios from 'axios'
export default {
  name: 'HelloWorld',
  mounted() {
    axios.get('https://designkojo.com/jsonapi/node/article')
      .then(response => this.posts = response.data.data)
      .catch(error => console.log(error))
  },
  data: function() {
    return {
      posts: null
    }
  }
}

So that is it we can now use {{posts}} in the template section of our component to see our response data in our App. Let's add pre { text-align: left; } in the CSS section to make it easier to read.

But, where is it? The API is set up, the endpoint is working, it seems to respond but still no data rendered on the page. Wait what this? The error Cross-Origin Request Blocked. Okay so there is one more thing to do and that is to enable CORS on Drupal.

Image

Enable CORS for Drupal

So this is where Drupal shines, by default CORS is disabled so we need to set this up. To do this we need to make a copy of the default.services.yml and save it as service.yml. This is in the site/default/ directory.

Once we have made a copy we need set enabled to true, add allowedHeaders, allowedMethods, and allowedOrigins. Also, don't forget to flush the cache. Below is the modified CORS section of the services.yml which shows simonramsay.net as an allowed origin. simonramsay.net is hosted on netlify at present which was an extremely hassle-free process, more on that in the weeks to come.

parameters:
  session.storage.options:

   ####
   # The above and below are part of the services.yml file that ships with Drupal.
   # I have removed all parameters except CORS and left session.storage.options to show the format of YAML hierarchy and indentation.
   # To see full file please check default.services.yml in the /sites/default directory.
   # *Please note this block is added and highlight like so for this guide only.
   ####

   # Configure Cross-Site HTTP requests (CORS).
   # Read https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
   # for more information about the topic in general.
   # Note: By default the configuration is disabled.
  cors.config:
    enabled: true
    # Specify allowed headers, like 'x-allowed-header'.
    allowedHeaders: ['content-type']
    # Specify allowed request methods, specify ['*'] to allow all possible ones.
    allowedMethods: ['GET']
    # Configure requests allowed from specific origins.
    allowedOrigins: ['https://simonramsay.net']
    # Sets the Access-Control-Expose-Headers header.
    exposedHeaders: false
    # Sets the Access-Control-Max-Age header.
    maxAge: false
    # Sets the Access-Control-Allow-Credentials header.
    supportsCredentials: false

Image

JSON data example as would be rendered to the page using <pre>{{posts}}</pre> in our template.

In this article we have looked at installing the JSON:API and enabling CORS on our Drupal site, as well as installing axios in our Vue.js App and rending the response to the App template. In a following post we will look at the JSON:API endpoint in more detail, how to navigate it to get the data we need, and how to render it on our new page. We will also look at switching to Vue.js 3 and NUXTJS to make a truly modern JAM stack app with server side rendering.

Until then mata ne.👋

# data[].attributes.body.summary
Working with Drupal API and enabling CORS, to work with Vue.js and other front-end libraries.

# data[].attributes.title
Make Items Editable in Vue.js using V-if & V-Model Directives 

# data[].attributes.metatag[].attributes.content
In this article, I will be extending my To Doodle app with the v-model and v-if directives to allow editing of tasks and more.

# data[].attributes.metatag[].attributes.content
In this article, I will be extending my To Doodle app with the v-model and v-if directives to allow editing of tasks and more.

# data[].attributes.body.value
In this article, I will be extending my To Doodle app with the v-model and v-if directives to allow editing of tasks and more.

If you haven't read my other article on creating the basic To Doodle app functionality then you may want to read that but it is not necessary to understand this.

Using v-model to Update the Data in Real-time

https://vuejs.org/v2/guide/forms.html

If you add v-model to form elements you create a 2-way binding meaning you get real-time updating. Let's see how it works.

In our v-for li items add a form input with the v-model directive and add the property you want to bind. I this case our data property is task.todo.

<li v-for="(task, index) in tasks" v-bind:class="{completed:task.selected}">
  {{ task.todo }} ( {{ index }} {{ task.selected }})
  <input v-model="task.todo">
</li>

Check the following example, now when entering a new task not only does a task get added to the list, there is also a form input element where you can edit the task, in real-time, awesome.

See the Pen Vue.js Todo App with V-model input by Simon (@simonramsay) on CodePen.

As cool as this is, it is not really that user-friendly so we will hide it and then make it appear when we want to edit it. To do this we can use v-if.

The Vue.js v-if conditional

https://vuejs.org/v2/guide/conditional.html

Who doesn't like good conditional to display or hide content?

This directive is one of my favourites, it is so clean, useful, and easy to use. You can display and hide elements by checking the value of a data property.

Add v-if to hide and show the input

We have an item in a list and you can check it off, delete it, and also update it. All of this was effortless as illustrated in the example. You can check how this was done in the first article here.

The task from the tasks array is also easily be bound to the input now added below the task and you can edit the task and the task will update in real-time using v-model.

This was nice but not really what I had envisioned, I was thinking more similar to clicking on the task list item and being able to edit the task. So with that in mind, we will wrap our input in a div with a v-if directive to hide and show the input.

First, wrap the input in a div and add the v-if="task.edit", as we haven't created a task edit property it will be false and thus the element won't show.

<div v-if="task.edit">
   <input v-model="task.todo">
</div>

We could add the property when we create the task by modifying the addTask() but I don't think it would really matter. Any JS or Vue.js gurus please chime in if it would affect performance.

With that done the input is hidden, to make it appear we can use the li item and make it click-able and set the task.edit value to true using the below code. To get more detail on how the $set() method works check the $set method article in this mini-series for Vue.js.

 <li v-for="(task, index) in tasks" v-bind:class="{completed:task.selected}">
+   <span v-on:click="$set(task, 'edit', !task.edit)">
       {{ task.todo }} (index: {{ index }})
+   </span>
   <br>
  /* completed & remove bottons*/
</li>

Note how I added the $set() method to a span that is wrapping the {{}} values. This is done so that the click only happens on the task and not the li item, we also have completed and remove buttons, and an input in the li items so you will get some weird functionality if we don't do that.

If you now set the value back to false on input enter key up the v-if div will hide again. Nice.

<input
         v-model="task.todo"
+        v-on:keyup.enter="task.edit = false"
>

A few things to note and think about are:

1. You can you click on the li item to make editable and then enter to save and close.

2. Is having a save button instead of on enter key-up better?

3. A save button will allow better control and formatting of your messages as you could then use enter for a new line instead of saving/updating.

You could build a global toggle to give the user the option to use enter for save/send. I personally prefer using a save/send button and not saving on enter. A toggle in the settings is a more advanced feature which we could look at later.

So with that let's make a Save button.

Adding an Edit and Save button

Since we will have a save button let's also add an edit button. We will put the edit/save button next to our other buttons.

Add a button with the same $set() method we use on our task above and then add two spans one with v-if set to false for the Edit label and add the Save label with a v-if set to true.

<button v-on:click="$set(task, 'edit', !task.edit)">
  <span v-if ="!task.edit">Edit</span>
  <span v-if="task.edit">Save</span>
</button>

Now we can click on the li item or edit button to edit the item.

We will make one small tweak here to give a more natural user experience or UX.

Hide the task while editing

Intermission
Did you know that you are better to think about that and solve it before checking below, I think you will be able to do it easily with the knowledge gained by reading thus far. If you need a hint, go to the next line.

That's right, add a negated v-if directive on the task li item span like this.

-  <span v-on:click="$set(task, 'edit', !task.edit)">
+  <span v-if="!task.edit" v-on:click="$set(task, 'edit', !task.edit)">

Changing the Form Input to a Text area

Now that we have a save button we can remove the on key up and change the Input to a text area, this will allow multi-line tasks. We will leave the onclick task li item's span for edit as this is a nice feature.

Now when we add a task we can use the enter button to start a new line which is awesome. However, when you save the task the line breaks don't render. They are saved, click edit and you will see the multi-line note still exists. To fix this we can use the CSS white-space property with the pre-wrap or wrap values.

Enforce line-break using the White-space: pre-warp CSS property: value pair

Add this to the CSS for the li element and now the line-breaks will magically be rendered.

white-space: pre-wrap;
white-space: wrap;

Only Show top line with ellipse

If on saving you only want to show a few lines with an ellipse you can use ellipse like so.

.task {
  white-space: pre-wrap;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

For more on line-clamp property, you can check my Add an Ellipse to Truncated Text with CSS: Single-line and Multi-line Options tip.

Following is To Doodle App, check out the code and reach out if you don't understand anything!

See the Pen Vue.js Todo App Multi-line Text Areas by Simon (@simonramsay) on CodePen.

Well, that's about it for this issue of making web dev simplified. Hope you learnt something. I will continue with this basic To Doodle app, adding filtering and some nice mobile features. Then I will be using what we have learnt to build out a shopping app I prototyped a few years back while studying UX at Michigan University Online. Sign up to get first access to this, a mini CSS course, and more awesome content.

# data[].attributes.body.processed
In this article, I will be extending my To Doodle app with the v-model and v-if directives to allow editing of tasks and more.

If you haven't read my other article on creating the basic To Doodle app functionality then you may want to read that but it is not necessary to understand this.

Using v-model to Update the Data in Real-time

https://vuejs.org/v2/guide/forms.html

If you add v-model to form elements you create a 2-way binding meaning you get real-time updating. Let's see how it works.

In our v-for li items add a form input with the v-model directive and add the property you want to bind. I this case our data property is task.todo.

<li v-for="(task, index) in tasks" v-bind:class="{completed:task.selected}">
  {{ task.todo }} ( {{ index }} {{ task.selected }})
  <input v-model="task.todo">
</li>

Check the following example, now when entering a new task not only does a task get added to the list, there is also a form input element where you can edit the task, in real-time, awesome.

See the Pen Vue.js Todo App with V-model input by Simon (@simonramsay) on CodePen.

As cool as this is, it is not really that user-friendly so we will hide it and then make it appear when we want to edit it. To do this we can use v-if.

The Vue.js v-if conditional

https://vuejs.org/v2/guide/conditional.html

Who doesn't like good conditional to display or hide content?

This directive is one of my favourites, it is so clean, useful, and easy to use. You can display and hide elements by checking the value of a data property.

Add v-if to hide and show the input

We have an item in a list and you can check it off, delete it, and also update it. All of this was effortless as illustrated in the example. You can check how this was done in the first article here.

The task from the tasks array is also easily be bound to the input now added below the task and you can edit the task and the task will update in real-time using v-model.

This was nice but not really what I had envisioned, I was thinking more similar to clicking on the task list item and being able to edit the task. So with that in mind, we will wrap our input in a div with a v-if directive to hide and show the input.

First, wrap the input in a div and add the v-if="task.edit", as we haven't created a task edit property it will be false and thus the element won't show.

<div v-if="task.edit">
   <input v-model="task.todo">
</div>

We could add the property when we create the task by modifying the addTask() but I don't think it would really matter. Any JS or Vue.js gurus please chime in if it would affect performance.

With that done the input is hidden, to make it appear we can use the li item and make it click-able and set the task.edit value to true using the below code. To get more detail on how the $set() method works check the $set method article in this mini-series for Vue.js.

 <li v-for="(task, index) in tasks" v-bind:class="{completed:task.selected}">
+   <span v-on:click="$set(task, 'edit', !task.edit)">
       {{ task.todo }} (index: {{ index }})
+   </span>
   <br>
  /* completed & remove bottons*/
</li>

Note how I added the $set() method to a span that is wrapping the {{}} values. This is done so that the click only happens on the task and not the li item, we also have completed and remove buttons, and an input in the li items so you will get some weird functionality if we don't do that.

If you now set the value back to false on input enter key up the v-if div will hide again. Nice.

<input
         v-model="task.todo"
+        v-on:keyup.enter="task.edit = false"
>

A few things to note and think about are:

1. You can you click on the li item to make editable and then enter to save and close.

2. Is having a save button instead of on enter key-up better?

3. A save button will allow better control and formatting of your messages as you could then use enter for a new line instead of saving/updating.

You could build a global toggle to give the user the option to use enter for save/send. I personally prefer using a save/send button and not saving on enter. A toggle in the settings is a more advanced feature which we could look at later.

So with that let's make a Save button.

Adding an Edit and Save button

Since we will have a save button let's also add an edit button. We will put the edit/save button next to our other buttons.

Image

Add a button with the same $set() method we use on our task above and then add two spans one with v-if set to false for the Edit label and add the Save label with a v-if set to true.

<button v-on:click="$set(task, 'edit', !task.edit)">
  <span v-if ="!task.edit">Edit</span>
  <span v-if="task.edit">Save</span>
</button>

Now we can click on the li item or edit button to edit the item.

We will make one small tweak here to give a more natural user experience or UX.

Hide the task while editing

Intermission
Did you know that you are better to think about that and solve it before checking below, I think you will be able to do it easily with the knowledge gained by reading thus far. If you need a hint, go to the next line.

That's right, add a negated v-if directive on the task li item span like this.

-  <span v-on:click="$set(task, 'edit', !task.edit)">
+  <span v-if="!task.edit" v-on:click="$set(task, 'edit', !task.edit)">

Changing the Form Input to a Text area

Now that we have a save button we can remove the on key up and change the Input to a text area, this will allow multi-line tasks. We will leave the onclick task li item's span for edit as this is a nice feature.

Now when we add a task we can use the enter button to start a new line which is awesome. However, when you save the task the line breaks don't render. They are saved, click edit and you will see the multi-line note still exists. To fix this we can use the CSS white-space property with the pre-wrap or wrap values.

Enforce line-break using the White-space: pre-warp CSS property: value pair

Add this to the CSS for the li element and now the line-breaks will magically be rendered.

white-space: pre-wrap;
white-space: wrap;

Only Show top line with ellipse

If on saving you only want to show a few lines with an ellipse you can use ellipse like so.

.task {
  white-space: pre-wrap;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

For more on line-clamp property, you can check my Add an Ellipse to Truncated Text with CSS: Single-line and Multi-line Options tip.

Following is To Doodle App, check out the code and reach out if you don't understand anything!

See the Pen Vue.js Todo App Multi-line Text Areas by Simon (@simonramsay) on CodePen.

Well, that's about it for this issue of making web dev simplified. Hope you learnt something. I will continue with this basic To Doodle app, adding filtering and some nice mobile features. Then I will be using what we have learnt to build out a shopping app I prototyped a few years back while studying UX at Michigan University Online. Sign up to get first access to this, a mini CSS course, and more awesome content.

# data[].attributes.body.summary
In this article, I will be extending my To Doodle app with the v-model and v-if directives to allow editing of tasks and more.

# data[].attributes.metatag[].attributes.content
Even though not an essential tool I still like to use Drush when managing a site as it allows for quicker operations such as database updates, clearing or rebuilding the cache, and setting the state into maintenance in between running Composer commands on the command line without needing to switch to the Drupal GUI. In this post we will look at how we can install Drush, then install the Drush Launcher so we can use it by typing drush instead of vendor/bin/drush, and then wrap up with a bunch of commands that are the most useful in everyday development.

# data[].attributes.metatag[].attributes.content
Even though not an essential tool I still like to use Drush when managing a site as it allows for quicker operations such as database updates, clearing or rebuilding the cache, and setting the state into maintenance in between running Composer commands on the command line without needing to switch to the Drupal GUI. In this post we will look at how we can install Drush, then install the Drush Launcher so we can use it by typing drush instead of vendor/bin/drush, and then wrap up with a bunch of commands that are the most useful in everyday development.

# data[].attributes.body.value
Even though not an essential tool I still like to use Drush when managing a site as it allows for quicker operations such as database updates, clearing or rebuilding the cache, and setting the state into maintenance in between running Composer commands on the command line without needing to switch to the Drupal GUI.

In this post we will look at how we can install Drush, then install the Drush Launcher so we can use it by typing drush instead of vendor/bin/drush, and then wrap up with a bunch of commands that are the most useful in everyday development.

Installing Drush

On the Drush website it states that "It is required that Drupal sites be built using Composer" and thus to install Drush it is as easy as running composer require drush/drush.

If you don't have Composer installed you will need to do that first. You can check how to do that on the installing Composer page.

Non Composer Managed Site?

I have got Drush working on a tarball installed site by running composer require drush/drush. However, obviously Composer was installed on the server and when you do an update of vendor files, which is every minor release, the Drush package needs to be added back. Whether this really makes sense I still don't know, the jury is still out on this mainly due to the fact I mainly use Composer to maintain Drupal 9 sites.

Once installed you can then run Drush by using vendor/bin/drush -command-

If you run the below command you will see the status, you should see Drush 10. I have included all the most used Drush commands at the end of the page.

Having to type vendor/bin/drush each time is a bit of a hassle so we will fix that.

Run Drush with shortened command drush -command-

To use Drush only using drush from within the root directory of your Drupal site you need to install the Drush Launcher. Drush Launcher listens on the system $PATH and when Drush is run the launcher passes the control to the site-specific Drush located in the vendor directory. Drush Launcher is hosted on Github and has everything thing you need to get going however I will go over it here for Linux.

For OSX or Windows please visit the Github page as the commands and steps differ ever so little. For OSX it is suggested you use curl and for Windows there is a small snippet of code you need to add to work correctly.

To install follow these 3 steps

1. Grab the URL from the fore-mentioned page and run it in the terminal on the server you want to use it.

wget -O drush.phar https://github.com/drush-ops/drush-launcher/releases/latest/download/drush.phar

2. Change perms on drush.phar   chmod +x drush.phar

3. Move into $PATH and rename  sudo mv drush.phar /usr/local/bin/drush

What is a .phar?

A PHAR (PHP Archive) file is a package format to enable distribution of applications and libraries by bundling many PHP code files and other resources (e.g. images, stylesheets, etc.) into a single archive file. https://en.wikipedia.org/wiki/PHAR_(file_format)

So with that done, you can now run Drush from within you site root directory using drush -command-

Useful day to day Drush commands

Following are some useful commands that I find I use a lot. To see them in use with other tools such as CLI or Composer check out the Update Drupal Core article or the Update Drupal Modules article.

drush state:set system.maintenance_mode 1
drush state:set system.maintenance_mode 0

drush updatedb:status
drush updatedb
drush cache:rebuild

Well, that's is about it for Drush, a useful command line tools that can save you time by allowing you to run basic maintenance tasks. I haven't used it past the basic tasks listed above but still find it something I couldn't do without.

Thanks for reading and be sure to sign up for the newsletter if you are interested in front-end development, design, and of course using Drupal as a headless CMS.

# data[].attributes.body.processed
Even though not an essential tool I still like to use Drush when managing a site as it allows for quicker operations such as database updates, clearing or rebuilding the cache, and setting the state into maintenance in between running Composer commands on the command line without needing to switch to the Drupal GUI.

In this post we will look at how we can install Drush, then install the Drush Launcher so we can use it by typing drush instead of vendor/bin/drush, and then wrap up with a bunch of commands that are the most useful in everyday development.

Installing Drush

On the Drush website it states that "It is required that Drupal sites be built using Composer" and thus to install Drush it is as easy as running composer require drush/drush.

If you don't have Composer installed you will need to do that first. You can check how to do that on the installing Composer page.

Non Composer Managed Site?

I have got Drush working on a tarball installed site by running composer require drush/drush. However, obviously Composer was installed on the server and when you do an update of vendor files, which is every minor release, the Drush package needs to be added back. Whether this really makes sense I still don't know, the jury is still out on this mainly due to the fact I mainly use Composer to maintain Drupal 9 sites.

Once installed you can then run Drush by using vendor/bin/drush -command-

If you run the below command you will see the status, you should see Drush 10. I have included all the most used Drush commands at the end of the page.

Having to type vendor/bin/drush each time is a bit of a hassle so we will fix that.

Run Drush with shortened command drush -command-

To use Drush only using drush from within the root directory of your Drupal site you need to install the Drush Launcher. Drush Launcher listens on the system $PATH and when Drush is run the launcher passes the control to the site-specific Drush located in the vendor directory. Drush Launcher is hosted on Github and has everything thing you need to get going however I will go over it here for Linux.

For OSX or Windows please visit the Github page as the commands and steps differ ever so little. For OSX it is suggested you use curl and for Windows there is a small snippet of code you need to add to work correctly.

To install follow these 3 steps

1. Grab the URL from the fore-mentioned page and run it in the terminal on the server you want to use it.

wget -O drush.phar https://github.com/drush-ops/drush-launcher/releases/latest/download/drush.phar

2. Change perms on drush.phar   chmod +x drush.phar

3. Move into $PATH and rename  sudo mv drush.phar /usr/local/bin/drush

What is a .phar?

A PHAR (PHP Archive) file is a package format to enable distribution of applications and libraries by bundling many PHP code files and other resources (e.g. images, stylesheets, etc.) into a single archive file. https://en.wikipedia.org/wiki/PHAR_(file_format)

So with that done, you can now run Drush from within you site root directory using drush -command-

Useful day to day Drush commands

Following are some useful commands that I find I use a lot. To see them in use with other tools such as CLI or Composer check out the Update Drupal Core article or the Update Drupal Modules article.

drush state:set system.maintenance_mode 1
drush state:set system.maintenance_mode 0

drush updatedb:status
drush updatedb
drush cache:rebuild

Well, that's is about it for Drush, a useful command line tools that can save you time by allowing you to run basic maintenance tasks. I haven't used it past the basic tasks listed above but still find it something I couldn't do without.

Thanks for reading and be sure to sign up for the newsletter if you are interested in front-end development, design, and of course using Drupal as a headless CMS.

# data[].attributes.title
Drupal Contact Form & using SMTP to Send Email

# data[].attributes.metatag[].attributes.content
Learn about setting up Contact form in Drupal and how to send email from your site.

# data[].attributes.metatag[].attributes.content
Learn about setting up Contact form in Drupal and how to send email from your site.

# data[].attributes.metatag[].attributes.content
drupal contact and php mailer class to send mail by SMTP

# data[].attributes.body.value
To enable a contact form in Drupal 9 is easy. Drupal 9 has the contact module, you can start using this straight away but be aware that your server needs to be able to send mail or you need to use an SMTP server to send your mail. I will cover this in detail after setting up the contact form but be warned this is important.

Info

Actively maintained Yes, ships with core.
Requires Part of Core with No extra requirements.

Basics

Since Contact is installed with the standard install all you need to do is check some basic configurations of the form. To do this visit the Contact forms page.

Manage > Structure > Contact forms
/admin/structure/contact

Before looking at the configuration, however, let's look at what the Contact module consists of as there are 2 types of forms. I have outlined what these are.

Types of forms

Site user contact form

You can send email between users of the site. I won't cover this as on a simple install the chances are you will only have 1 or 2 users. However, it is good to know that you can have an internal message system out-of-the-box.

Site-wide Contact

By default, there is one feedback form already available and you can manage it at /contact/manage/feedback

This will be the one you will want to use. However, you can create as many different forms that you please.

The default URL is /contact/feedback. It can also be viewed and used at /contact

Edit contact form

/contact/manage/feedback

The basic settings that need to be configured are on this page, the ones with an * are required the others are optional.

Label*

Recipients*

Message - a message that is displayed in the highlighted regions, leave blank if you don't want to use it. The case where you might want it to blank is if you use the next options which is a custom path and page that a person submitting the form gets redirected to.

Redirect path - A path to a page, could be a custom thank you page with valuable information and another CTA or message.

Auto-reply - Send an automated message telling the person what to expect, I.e. we will be in contact shortly.

Weight - this is a Drupal thing, it is the order in which it is displayed on the contact form overview page.

Make this the default form - The default form is shown at /contact URL all other forms are at contact/name-of-form

Add Fields

/contact/manage/feedback/fields

You can add fields just like any other content/entity type to customize the data collected. Read more about Adding Fields to Drupal if you are unsure about what to do.

The field types that are available include select menus, checkboxes, input, text areas, and images. You do have to be careful about what you allow an anonymous user to upload, however, so keep this in mind.

The default fields are enough to get started. If you want to remove any of the default fields you can do that on the manage form display page.

Manage form display

/contact/manage/feedback/form-display

This re-arranges the order in which the form fields are displayed to the customer or user. You can also drag the field to the disabled area if you don't want one of the fields to show.

Remove the Preview Button

By default the preview button and the functionality to remove it doesn't work, you need to patch it to remove it, the patch has been committed and will be in 9.1.3. If you read this before 9.1.3 is released here is the issue. Make the Preview button on the Contact Forms to obey the "Manage form display" field settings.

Manage display

/contact/manage/feedback/display

Only has the message field on it but default.

Okay with that done we should test that it can send a message. In the next section, we will look at sending email from a Drupal site.

Sending Messages from Your Site

If you try to send the form you will probably get errors, if you don't then you are lucky. The main possible reason for this is that the server doesn't have the mail modules installed. Even though it is possible to install these, check the details at the end for that, you are best to use an SMTP server to send email from your Drupal site. To do that we need to use a PHP class, PHP mailer seems to be the most wildly used and to use that we can install SMTP Module.

SMTP Authentication Support

To use SMTP you don't need to install anything on the server as PHP Mailer, the library that SMTP module enables, connects to your mail's outgoing server. This is by far the best option for delivery and security of mail. I will outline the other options in the last section so you can see what I mean. To use SMTP please have a look at the SMTP module guide.

Another SMTP Drupal Option

PHPMailer SMTP

https://www.drupal.org/project/phpmailer_smtp

The PHPMailer SMTP module is for SMTP only, it does not help to format emails with HTML. The suggested SMTP module allows you to enable sending email in HTML format, but this module doesn't allow that. For a basic contact form this is probably not an issue, but for anything else use the recommended SMTP Module.

Storing Data with Contact Storage

So you have that setup and your emails are being sent and received.

As you get more and more messages it is nice to have them stored on the site as a backup in the case that mail delivery gets interrupted (I have had this happen in the past) and this is where contact storage comes in.

Info

https://www.drupal.org/project/contact_storage

Actively maintained Yes
Requires No extra requirements

Basics

If you don't know how to install a Drupal module visit the installing a module page and then return here.

Once installed the module enables 2 new tabs on the Contact form page and a multitude of new settings like being about to customize the submit button text.

Manage > Structure > Contact form
/admin/structure/contact

These tabs are Lists and Contact Settings

Lists

/admin/structure/contact/messages

A page that lists all the submitted messages with a filter to easily filter on contact forms if you have many and an operation to bulk deleted messages. Simple but effective way to keep original submissions safe.

Always keep off site and server database back ups, even if you install contact storage as a back up safe guard you should also make sure that your complete site is safe.

Contact Settings

This page has one setting that enables you send email HTML, this requires using another module to set up correctly so I won't go down that rabbit whole here but I will follow up with an article on configuring HTML email in the near future. For now I will leave it unchecked.

Other Things to Think About

Other things to think about when setting up an email form are needing to send auto-replies, sending a copy of the message to the person sending the form, and formatting the messages you send. Both these features are built into the modules so it has you covered. Remember SMTP is needed for the HTML formatting. I will cover this stuff in future content but in the meantime if you need help be sure to get in contact.

Since contact comes with Drupal it is a great option for basic contact forms and by adding SMTP to send your forms and contact storage if you want to save them to somewhere safe you have a great solution to get going.

Overtime if you want to create more complex forms, Webform is a great choice. Read on to find out about Webform and also other options to send mail.

Another Option for Webforms

Webform

Webform I have used extensively in the past and I can say that it is exhaustive in what it can do as a point and click form builder, it has storage out-of-the-box, multi-step forms, and a plethora of other features, too many to outline here but if you need help you can shoot me a message on the contact form.

I do intend to review Drupal 9 Webform in time but my experience is with Webform for Drupal 7 and Drupal 8 with a basic use case. Some things I achieved with Webform and in some cases with customization are:

Automatically populating values from other pages.

Forwarding data onto a CRM.

Send HTML autoresponders this is possible with Contact form (white paper)

For Drupal 9 Webform is really the only other solution which is a good thing as it means that everybody's energy is focused on making that better.

Other Options for sending email

Mail delivery from your domain to Gmail or GSuite, in particular, is problematic if you don't use SMTP. I have experienced this with domains not using SMTP to send email from the domain and using GSuite business as the email service provider. So as I have now said multiple times you are best to use SMTP to send email.

A quick review of other options so you can make the decision if SMTP is your best option. I assure you it is, but with the information below you can make the decision yourself.

Install Apache Modules

One of the following 2 modules need to be installed

sendmail
Does work but prolonged, you will probably run into delivery problems in the end.

postfix
I found this worked, you need to have a domain name to use on install.

VPS such as Hostgator or Shared Hosting

I have used these in the past and they seemed to work so the modules above must have been installed by default. However, the same problem I have encountered with mail delivery will ultimately happen so in the end, you are best to use an outgoing SMTP server.

A Mail Server

Setting up a mail server I will mention as an option but since I have never done it I can only tell you what I have read and that is unless you have time and budget to do so you are better to use a paid ESP (email service provider) and then use SMTP. A mailer will need all that a good ESP provides with good security amongst other things, not something to take lightly and possibly outside most small and medium-size businesses budgets.

I hope this shows you how easy Drupal makes it to have a contact form on your site and what other others there are if you need them. All you really need to do though is install SMTP and use the default pre-installed form and you are good to go. Thanks for reading and be sure to sign up for the Newsletter.

# data[].attributes.body.processed
To enable a contact form in Drupal 9 is easy. Drupal 9 has the contact module, you can start using this straight away but be aware that your server needs to be able to send mail or you need to use an SMTP server to send your mail. I will cover this in detail after setting up the contact form but be warned this is important.

Info

Actively maintained Yes, ships with core.
Requires Part of Core with No extra requirements.

Basics

Since Contact is installed with the standard install all you need to do is check some basic configurations of the form. To do this visit the Contact forms page.

Manage > Structure > Contact forms
/admin/structure/contact

Before looking at the configuration, however, let's look at what the Contact module consists of as there are 2 types of forms. I have outlined what these are.

Types of forms

Site user contact form

You can send email between users of the site. I won't cover this as on a simple install the chances are you will only have 1 or 2 users. However, it is good to know that you can have an internal message system out-of-the-box.

Site-wide Contact

By default, there is one feedback form already available and you can manage it at /contact/manage/feedback

This will be the one you will want to use. However, you can create as many different forms that you please.

The default URL is /contact/feedback. It can also be viewed and used at /contact

Edit contact form

/contact/manage/feedback

The basic settings that need to be configured are on this page, the ones with an * are required the others are optional.

Label*

Recipients*

Message - a message that is displayed in the highlighted regions, leave blank if you don't want to use it. The case where you might want it to blank is if you use the next options which is a custom path and page that a person submitting the form gets redirected to.

Redirect path - A path to a page, could be a custom thank you page with valuable information and another CTA or message.

Auto-reply - Send an automated message telling the person what to expect, I.e. we will be in contact shortly.

Weight - this is a Drupal thing, it is the order in which it is displayed on the contact form overview page.

Make this the default form - The default form is shown at /contact URL all other forms are at contact/name-of-form

Add Fields

/contact/manage/feedback/fields

You can add fields just like any other content/entity type to customize the data collected. Read more about Adding Fields to Drupal if you are unsure about what to do.

The field types that are available include select menus, checkboxes, input, text areas, and images. You do have to be careful about what you allow an anonymous user to upload, however, so keep this in mind.

The default fields are enough to get started. If you want to remove any of the default fields you can do that on the manage form display page.

Manage form display

/contact/manage/feedback/form-display

This re-arranges the order in which the form fields are displayed to the customer or user. You can also drag the field to the disabled area if you don't want one of the fields to show.

Remove the Preview Button

By default the preview button and the functionality to remove it doesn't work, you need to patch it to remove it, the patch has been committed and will be in 9.1.3. If you read this before 9.1.3 is released here is the issue. Make the Preview button on the Contact Forms to obey the "Manage form display" field settings.

Manage display

/contact/manage/feedback/display

Only has the message field on it but default.

Okay with that done we should test that it can send a message. In the next section, we will look at sending email from a Drupal site.

Sending Messages from Your Site

If you try to send the form you will probably get errors, if you don't then you are lucky. The main possible reason for this is that the server doesn't have the mail modules installed. Even though it is possible to install these, check the details at the end for that, you are best to use an SMTP server to send email from your Drupal site. To do that we need to use a PHP class, PHP mailer seems to be the most wildly used and to use that we can install SMTP Module.

SMTP Authentication Support

To use SMTP you don't need to install anything on the server as PHP Mailer, the library that SMTP module enables, connects to your mail's outgoing server. This is by far the best option for delivery and security of mail. I will outline the other options in the last section so you can see what I mean. To use SMTP please have a look at the SMTP module guide.

Another SMTP Drupal Option

PHPMailer SMTP

https://www.drupal.org/project/phpmailer_smtp

The PHPMailer SMTP module is for SMTP only, it does not help to format emails with HTML. The suggested SMTP module allows you to enable sending email in HTML format, but this module doesn't allow that. For a basic contact form this is probably not an issue, but for anything else use the recommended SMTP Module.

Storing Data with Contact Storage

So you have that setup and your emails are being sent and received.

As you get more and more messages it is nice to have them stored on the site as a backup in the case that mail delivery gets interrupted (I have had this happen in the past) and this is where contact storage comes in.

Info

https://www.drupal.org/project/contact_storage

Actively maintained Yes
Requires No extra requirements

Basics

If you don't know how to install a Drupal module visit the installing a module page and then return here.

Once installed the module enables 2 new tabs on the Contact form page and a multitude of new settings like being about to customize the submit button text.

Manage > Structure > Contact form
/admin/structure/contact

These tabs are Lists and Contact Settings

Lists

/admin/structure/contact/messages

A page that lists all the submitted messages with a filter to easily filter on contact forms if you have many and an operation to bulk deleted messages. Simple but effective way to keep original submissions safe.

Always keep off site and server database back ups, even if you install contact storage as a back up safe guard you should also make sure that your complete site is safe.

Contact Settings

This page has one setting that enables you send email HTML, this requires using another module to set up correctly so I won't go down that rabbit whole here but I will follow up with an article on configuring HTML email in the near future. For now I will leave it unchecked.

Other Things to Think About

Other things to think about when setting up an email form are needing to send auto-replies, sending a copy of the message to the person sending the form, and formatting the messages you send. Both these features are built into the modules so it has you covered. Remember SMTP is needed for the HTML formatting. I will cover this stuff in future content but in the meantime if you need help be sure to get in contact.

Since contact comes with Drupal it is a great option for basic contact forms and by adding SMTP to send your forms and contact storage if you want to save them to somewhere safe you have a great solution to get going.

Overtime if you want to create more complex forms, Webform is a great choice. Read on to find out about Webform and also other options to send mail.

Another Option for Webforms

Webform

Webform I have used extensively in the past and I can say that it is exhaustive in what it can do as a point and click form builder, it has storage out-of-the-box, multi-step forms, and a plethora of other features, too many to outline here but if you need help you can shoot me a message on the contact form.

I do intend to review Drupal 9 Webform in time but my experience is with Webform for Drupal 7 and Drupal 8 with a basic use case. Some things I achieved with Webform and in some cases with customization are:

Automatically populating values from other pages.

Forwarding data onto a CRM.

Send HTML autoresponders this is possible with Contact form (white paper)

For Drupal 9 Webform is really the only other solution which is a good thing as it means that everybody's energy is focused on making that better.

Other Options for sending email

Mail delivery from your domain to Gmail or GSuite, in particular, is problematic if you don't use SMTP. I have experienced this with domains not using SMTP to send email from the domain and using GSuite business as the email service provider. So as I have now said multiple times you are best to use SMTP to send email.

A quick review of other options so you can make the decision if SMTP is your best option. I assure you it is, but with the information below you can make the decision yourself.

Install Apache Modules

One of the following 2 modules need to be installed

sendmail
Does work but prolonged, you will probably run into delivery problems in the end.

postfix
I found this worked, you need to have a domain name to use on install.

VPS such as Hostgator or Shared Hosting

I have used these in the past and they seemed to work so the modules above must have been installed by default. However, the same problem I have encountered with mail delivery will ultimately happen so in the end, you are best to use an outgoing SMTP server.

A Mail Server

Setting up a mail server I will mention as an option but since I have never done it I can only tell you what I have read and that is unless you have time and budget to do so you are better to use a paid ESP (email service provider) and then use SMTP. A mailer will need all that a good ESP provides with good security amongst other things, not something to take lightly and possibly outside most small and medium-size businesses budgets.

I hope this shows you how easy Drupal makes it to have a contact form on your site and what other others there are if you need them. All you really need to do though is install SMTP and use the default pre-installed form and you are good to go. Thanks for reading and be sure to sign up for the Newsletter.

# data[].attributes.body.summary
Learn about setting up Contact form in Drupal and how to send email from your site.

# data[].attributes.metatag[].attributes.content
When working with servers without a GUI dashboard such as cPanel the SCP command is something you will need to get used to. Even if you do have a cPanel you will find being able to move files from one remote server to another remote server directly much faster than downloading to your local machine and then uploading to another remote machine. In this article, we will look at the 3 scenarios you may come across when working with files and directories on a system. In the end, we will also look at a few options that can be used with SCP. The 3 scenarios are

# data[].attributes.metatag[].attributes.content
When working with servers without a GUI dashboard such as cPanel the SCP command is something you will need to get used to. Even if you do have a cPanel you will find being able to move files from one remote server to another remote server directly much faster than downloading to your local machine and then uploading to another remote machine. In this article, we will look at the 3 scenarios you may come across when working with files and directories on a system. In the end, we will also look at a few options that can be used with SCP. The 3 scenarios are

# data[].attributes.body.value
When working with servers without a GUI dashboard such as cPanel the SCP command is something you will need to get used to. Even if you do have a cPanel you will find being able to move files from one remote server to another remote server directly much faster than downloading to your local machine and then uploading to another remote machine.

In this article, we will look at the 3 scenarios you may come across when working with files and directories on a system. In the end, we will also look at a few options that can be used with SCP.

The 3 scenarios are

1. From your local system to the remote system

2. From a remote system to the local system

3. From a remote to a remote

It is also assumed you have SSH key pairs set up but if you don't you could skip the key pair and use a password at the prompt. In the examples, I will show the SSH key example first and the password prompt example second. To do a remote server to a remote server using SCP you will need to set up SSH keys.

Using the SSH key you need to proceed the key with the -i option. This is the identity option that is passed directly to SSH.

You will also need to have the user and the IP for the server.

From your local system to the remote system

When uploading the files from the desktop they will go into the home directory of the user. You could place them directly in a known path by adding the path.

scp -i ~/.ssh/private_key ~/Desktop/file.zip  user@123.456.789.101:~/

scp  file.zip user@123.456.789.101:~/

From a remote system to the local system

You will need to know the location or the path of the file to access it. As with uploading, the path will be from the home of the user.

In this example, we are downloading the file from the /var/www/example.com/public_html/ directory to the desktop on a Mac.

scp -i ~/.ssh/_key user@123.456.789.101:/var/www/example.com/public_html/file.tar ~/Desktop

scp user@123.456.789.101:/var/www/example.com/public_html/file.tar ~/Desktop

From a remote to a remote

Apparently, there is a way to do this from the local machine, but it has stumped me as you need to pass the login details of both servers to do this. If you know how this is done then drop a message in the comments.

That said if you log into the remote server of the file you want to transfer and then locate the file you what to transfer to you can then run the same command from desktop to remote this work.

In this example, we are transferring from the current directory on a remote server to the home of another remote server. You need to have logged into remote server 1 and have the public key server_1_key.pub from server 1 on server 2.

You will need to use SSH for this.

scp -i ~/.ssh/server_1_key file.zip  user_server_2@123.456.789.101:~/

When Using SCP you can also pass options to the command like any other Linux command, some common option you may use are.

Useful Options to use with SCP

They have to be either capitalized or lowercase as shown.

-i  used with SSH key
-r  recursive.
-v  Verbose, shows the transfer
-C Compress only during transfer

Other options I don't use that much but are available.

-l 800 bandwidth limit
-p preserve the attributes of the file; perms, timestamp, ownership
-q quiet mode suppress the output

SCP is a powerful utility and when managing your own VPS is definitely something you will want to use from time to time.
For other server tips, check out the Tools section where I cover Git, Composer and other CLI tools.

Thanks for reading.

# data[].attributes.body.processed
When working with servers without a GUI dashboard such as cPanel the SCP command is something you will need to get used to. Even if you do have a cPanel you will find being able to move files from one remote server to another remote server directly much faster than downloading to your local machine and then uploading to another remote machine.

In this article, we will look at the 3 scenarios you may come across when working with files and directories on a system. In the end, we will also look at a few options that can be used with SCP.

The 3 scenarios are

1. From your local system to the remote system

2. From a remote system to the local system

3. From a remote to a remote

It is also assumed you have SSH key pairs set up but if you don't you could skip the key pair and use a password at the prompt. In the examples, I will show the SSH key example first and the password prompt example second. To do a remote server to a remote server using SCP you will need to set up SSH keys.

Using the SSH key you need to proceed the key with the -i option. This is the identity option that is passed directly to SSH.

You will also need to have the user and the IP for the server.

From your local system to the remote system

When uploading the files from the desktop they will go into the home directory of the user. You could place them directly in a known path by adding the path.

scp -i ~/.ssh/private_key ~/Desktop/file.zip  user@123.456.789.101:~/

scp  file.zip user@123.456.789.101:~/

From a remote system to the local system

You will need to know the location or the path of the file to access it. As with uploading, the path will be from the home of the user.

In this example, we are downloading the file from the /var/www/example.com/public_html/ directory to the desktop on a Mac.

scp -i ~/.ssh/_key user@123.456.789.101:/var/www/example.com/public_html/file.tar ~/Desktop

scp user@123.456.789.101:/var/www/example.com/public_html/file.tar ~/Desktop

From a remote to a remote

Apparently, there is a way to do this from the local machine, but it has stumped me as you need to pass the login details of both servers to do this. If you know how this is done then drop a message in the comments.

That said if you log into the remote server of the file you want to transfer and then locate the file you what to transfer to you can then run the same command from desktop to remote this work.

In this example, we are transferring from the current directory on a remote server to the home of another remote server. You need to have logged into remote server 1 and have the public key server_1_key.pub from server 1 on server 2.

You will need to use SSH for this.

scp -i ~/.ssh/server_1_key file.zip  user_server_2@123.456.789.101:~/

When Using SCP you can also pass options to the command like any other Linux command, some common option you may use are.

Useful Options to use with SCP

They have to be either capitalized or lowercase as shown.

-i  used with SSH key
-r  recursive.
-v  Verbose, shows the transfer
-C Compress only during transfer

Other options I don't use that much but are available.

-l 800 bandwidth limit
-p preserve the attributes of the file; perms, timestamp, ownership
-q quiet mode suppress the output

SCP is a powerful utility and when managing your own VPS is definitely something you will want to use from time to time.
For other server tips, check out the Tools section where I cover Git, Composer and other CLI tools.

Thanks for reading.

# data[].attributes.metatag[].attributes.content
Creating SSH keys and using them for accessing your virtual server machine.

# data[].attributes.metatag[].attributes.content
Creating SSH keys and using them for accessing your virtual server machine.

# data[].attributes.body.value
Logging into a server using a user name and password is not that secure and if possible you are best to use SSH or Secure Shell.

On this page, you will find all you need to create SSH keys, log in to your server using SSH, and how you can use it for remote to remote server transfers and access your Git repositories.

Basic Concept

SSH works with the idea of keys, these keys are long random strings and work together to unlock access or a connection between two locations on the internet. If the keypair you try to use doesn't authenticate SSH will deny you access to the connection.

As mentioned, SSH works with a keypair. This keypair is made of a private key and a public key. When you create a keypair on your system you will see the keypair will have the same name. The default keypair is id_rsa and if you are in the .ssh directory and have created a keypair you will see the private and public keys as shown below.

As you can see you can name your keys what you like.  So if you want to have different keys for different servers set up it is possible to create multiple keypairs. Let's set up a keypair.

Create a Key

To set up a keypair you need to run the following code in your terminal in the .ssh directory.

 ssh-keygen -t rsa

Now that we have created a keypair and we know the difference between public and private keys I guess it is a good time to mention that you should never share the private key. That's right, a private key is just that, it is private and should never be shared.

Okay, next we will set them up to use.

Installing the public key on a remote server

The idea is the same whether you create a keypair on your local system or on a remote system. Have a look at the following diagram.

As you can see, in both examples the keys are kept in the .ssh directory along with an authorized keys file and known_hosts file. So what are these files?

For a basic set up the only files, we need to touch are the public key and authorized key.
If you open up the public key you will see a long number similar to the following example.

ssh-rsa AA..LongRandomString....2/Qs5MC0= user@computer_local

cat (concatenate) can be used to show the content of any file and many other things.
cat file_name.ext

Copy this key how you find easiest, highlight and ctrl C or use a CLI command such as pbcopy.

pbcopy can be used to copy the contents of file to a clipboard.
cat designkojo-digitaloceean.pub | pbcopy

Once you have the public key on your clipboard, go to the server you want to make a connection to and log in to it using a user name and password.
Then open the .ssh/authorized_key file and paste the public key on a new line. I use nano for this simple task but use what you like.

Make sure you return to a new line and then save, in nano this can be done using Ctrl X and Y (yes) at the prompt then and Enter.  Or Ctrl O to Write Out and not close the file.

Make sure the perms of the authorized_keys is set to 600

-rw-rw-r-- 1 designkojo designkojo  1378 Mar 25 01:17 authorized_keys
chmod 600 authorized_keys
-rw------- 1 designkojo designkojo  1378 Mar 25 01:17 authorized_keys

So that's done now you can connect to the server from your local. Log out and try following the next steps.

Using SSH to log in

From the command line use the following code to log in using SSH.

ssh -i ~/.ssh/simon_rsa designkojo@45.45.4545.45

When SSH'ing in you may be asked whether to continue due to authenticity to the host can't be established. If so say yes.

So now you just logged in to your remote server using SSH and can safely work on the server, good job!

You can also use SSH with your code editor or IDE and I suggest you do so let's have a quick look at how that would be done with PHPStorm. The process should be the same with your editor of choice, look for server deployment configuration using SFTP, not to be confused with FSTP.

From SSH with an IDE or code editor

You can also use the same keypair when setting up your IDE or code editor to connect to your server for deployment. I use PHPStorm and you can use SFTP and then set your SSH configuration to use a keypair.

So that's it you will now be using SSH to deploy to your server.

With this knowledge, hopefully, you can now connect 2 servers. If you want to find about how to use SSH with SCP check out SCP Secured Copy.

Thanks for reading and be sure to check out more on tooling.

# data[].attributes.body.processed
Logging into a server using a user name and password is not that secure and if possible you are best to use SSH or Secure Shell.

On this page, you will find all you need to create SSH keys, log in to your server using SSH, and how you can use it for remote to remote server transfers and access your Git repositories.

Image

Basic Concept

SSH works with the idea of keys, these keys are long random strings and work together to unlock access or a connection between two locations on the internet. If the keypair you try to use doesn't authenticate SSH will deny you access to the connection.

As mentioned, SSH works with a keypair. This keypair is made of a private key and a public key. When you create a keypair on your system you will see the keypair will have the same name. The default keypair is id_rsa and if you are in the .ssh directory and have created a keypair you will see the private and public keys as shown below.

Image

As you can see you can name your keys what you like.  So if you want to have different keys for different servers set up it is possible to create multiple keypairs. Let's set up a keypair.

Create a Key

To set up a keypair you need to run the following code in your terminal in the .ssh directory.

 ssh-keygen -t rsa

Image

Now that we have created a keypair and we know the difference between public and private keys I guess it is a good time to mention that you should never share the private key. That's right, a private key is just that, it is private and should never be shared.

Okay, next we will set them up to use.

Installing the public key on a remote server

The idea is the same whether you create a keypair on your local system or on a remote system. Have a look at the following diagram.

Image

As you can see, in both examples the keys are kept in the .ssh directory along with an authorized keys file and known_hosts file. So what are these files?

For a basic set up the only files, we need to touch are the public key and authorized key.
If you open up the public key you will see a long number similar to the following example.

ssh-rsa AA..LongRandomString....2/Qs5MC0= user@computer_local

cat (concatenate) can be used to show the content of any file and many other things.
cat file_name.ext

Copy this key how you find easiest, highlight and ctrl C or use a CLI command such as pbcopy.

pbcopy can be used to copy the contents of file to a clipboard.
cat designkojo-digitaloceean.pub | pbcopy

Once you have the public key on your clipboard, go to the server you want to make a connection to and log in to it using a user name and password.
Then open the .ssh/authorized_key file and paste the public key on a new line. I use nano for this simple task but use what you like.

Make sure you return to a new line and then save, in nano this can be done using Ctrl X and Y (yes) at the prompt then and Enter.  Or Ctrl O to Write Out and not close the file.

Make sure the perms of the authorized_keys is set to 600

-rw-rw-r-- 1 designkojo designkojo  1378 Mar 25 01:17 authorized_keys
chmod 600 authorized_keys
-rw------- 1 designkojo designkojo  1378 Mar 25 01:17 authorized_keys

So that's done now you can connect to the server from your local. Log out and try following the next steps.

Using SSH to log in

From the command line use the following code to log in using SSH.

ssh -i ~/.ssh/simon_rsa designkojo@45.45.4545.45

When SSH'ing in you may be asked whether to continue due to authenticity to the host can't be established. If so say yes.

So now you just logged in to your remote server using SSH and can safely work on the server, good job!

You can also use SSH with your code editor or IDE and I suggest you do so let's have a quick look at how that would be done with PHPStorm. The process should be the same with your editor of choice, look for server deployment configuration using SFTP, not to be confused with FSTP.

From SSH with an IDE or code editor

You can also use the same keypair when setting up your IDE or code editor to connect to your server for deployment. I use PHPStorm and you can use SFTP and then set your SSH configuration to use a keypair.

Image

So that's it you will now be using SSH to deploy to your server.

With this knowledge, hopefully, you can now connect 2 servers. If you want to find about how to use SSH with SCP check out SCP Secured Copy.

Thanks for reading and be sure to check out more on tooling.

# data[].attributes.body.summary
Creating SSH keys and using them for accessing your virtual server machine.

# data[].attributes.metatag[].attributes.content
Too many people don't put things out there until they are 100% ready, myself included, you will never be 100% ready. What is a soft launch?

# data[].attributes.metatag[].attributes.content
Too many people don't put things out there until they are 100% ready, myself included, you will never be 100% ready. What is a soft launch?

# data[].attributes.metatag[].attributes.content
a rose petal in a glass with a soft blur filter on the backgound

# data[].attributes.body.value
Too many people don't put things out there until they are 100% ready, myself included, you will never be 100% ready.

What is a soft launch?

A soft launch is a launch that has no real launch date, you just put your site or application live without announcing it. This has many benefits from being able to hone the website or application without having a lot of users and traffic. At some later stage, you may decide to do a launch, especially if your product is commercial, and you intend to monetize. For more on a Soft Launch, jump over to Wikipedia.

Why I did a soft launch

There are many reasons why I did a soft launch. I will outline the main reasons why in this article in the hope that I can inspire you to put your site live so you can also hone your skill.

It can be daunting, I know, and we bash ourselves up over not being good enough. I have listed 6 reasons below, some of them are related to each other, but I have listed them separately as they are unique in some way. These are not the only reasons but seem like the main reasons. The order they are in has no meaning apart from it being the order they fell together, let's have a look.

Work out My Direction

Not only did I want to concentrate on how I wanted to present myself and my expertise, since I have a broad range of skills, but I also wanted to make sure that I was on the right track before I went all-in on something.

The initial collection of articles on this site has allowed me to find a direction and a topic or subject area. This site, as I wrote in What is this design kojo thing anyway?, is a place to put experimental work and I may syndicate some of it to more specialised domains in the future. The general topic area is front-end development, but I have also been building out a small Drupal 9 get started guide to share my experience in developing this site and also so I had some different types of content to design for. That leads to my second reason.

Wanting to re-focus on front--end UI/UX development, I needed content to design for.

Without Content, You Can't Design

Due to not actively sharing my work for the last 10 years, I had no content to design for and was unsure what type of content I was going to produce. In a way, I still don't know what content I will be producing in the future.

Since I now have content on this site that needs better presentation, I can design content types and also content elements. Also, by having a bunch of content on the site, I can now write about the UI/UX process while building the new front-end.

Advocate for content-first design

As a side note, in the past I have built sites for business' with no content, I built a brand and then the content was filled in, this is somewhat reverse of what should be done, and I guess I passed a lot of value to those clients in the past. Some of my most successful projects have either come with content or I have included to get it written and created. In a normal design process, the content should be supplied to you by the client and if they don't have it then they really need to get to work for you.

I will be writing about this in more detail in the coming months, and I will be sure to link to it here. However, let's have a quick look at what content types and elements I have identified.

Content types I have identified

The types of content I have are; thought and or theory pieces, technical guides or coding pieces, and design pieces. These pieces can be broken into other smaller parts or elements.

Elements I have identified

I have identified elements such as

code samples

code demonstrations

images

text

video

And HTML Semantic elements such a

article

figure

aside

li

ol

ul

These content types and elements also need to be thought about for mobile, desktop, dark, and light.

Since I have real content to work with, I can now design.

Not knowing what content I would produce

This is related to the previous point.

As I got started I realised the content I was writing doesn't really stand alone, every time I write I see that I either need to write one or 2 supporting pieces or add aside content.

This means I need to design the aside content, add notes to remind myself to link to the forthcoming content, and create a process and system. This will always be the case I have learnt but when starting out it was hard to see this aspect of creating content.

What is aside content?
It is supplementary content that isn't needed for the main article but adds the necessary explanation for some readers. This content should be designed in such a way that it stands out as separate from the main content and mark up should also indicate it.

So to summarise the first 2 reasons, I really didn't know what type of content I was going to write, how it would need to be presented, or what styles would be needed to present it. Therefore, I needed to write a variation of content with a variety of elements that I may create so that in the future I can produce high-quality articles at a faster pace. This generally is not a problem when someone else is supplying the content, as the content brings with it these elements and also a voice, a tone, and a lot of design hints that can be used.

Workout a publishing process and hone my writing skills

When I started out I hadn't written for a while, I had written reports for business partners and clients, I had written blog posts for travel websites but writing tech & design related stuff was new to me, well for 8 years I hadn't written openly and for that reason I wanted to make sure what I putting out is adding value to my readers. I am still proofing and reviewing some of the content written back in August 2020 as I work out the design for various types of content, but I also feel now my writing and process is allowing to produce better quality, this takes time.

Part of writing also means you should develop a voice, a tone, and vocabulary. A great case study on this that I recommend to any business trying to distinguish themselves is the Mailchimp tone and voice style guide, you should be able to find that with a search of your favourite search engine.

Writing Style and Voice I hadn't been writing for a bit, so even though I was publishing, the content wasn't up to a high level. This is somewhat related to point one in needing content to design for.

Create a Voice and a brand

The way your voice is created can then be used in all your marketing. This may come naturally for some, but for me, I felt like I need to develop a personal brand and then stick with it. Having a few small rules just makes it easier in the end.

In creating this voice and tone you need to write, it's a bit of a chicken and an egg thing, so part of this process is still underway, but I also studied some writing courses to help out.

For me this was important as I am an extra extrovert if there is such a thing so putting out quality content that speaks for itself is important, I don't feel I am there yet and possibly never will be but to start by doing a soft launch has allowed me to at least get to a standard I am proud to put out there.

I Wanted to Create My Own Platform

This is more due to being a designer, and an off-the-shelf solution isn't what I wanted or needed.

If I am going to talk about UI/UX and front-end design and aesthetics then what a better place than my own site to put into practice what I am talking about, as I talk about it. You may say you are using Drupal, though, and that would be right. However, I do believe there is no point in redesigning the wheel and Drupal gives me the flexibility to build an awesome front-end without worrying about the back-end, yep even a JAM Stack needs to have an API, that's the A in JAM.

Final Thoughts

That's about it. In this article, I looked at what a soft launch is and then some of the reasons why I chose to do one. Some of the reasons I made are illustrated in the fact that I don't have the content types ready even for this piece, some of the ideas discussed such as not having supporting content ready, and not being that great at writing are also well illustrated.

Over time as I find more focus I will possibly do a hard launch for a section of this site. Hope you learnt something and if you'd like to follow on with the redesign and other thoughts as they come, I'd be stoked for you to sign up to my newsletter and get first access to my content. Yes, that's right, you will get first access to most of the content plus I have a few other things I will be launching very shortly so to be first on the list and in the know you know what to do. 😉

Thanks for reading.

# data[].attributes.body.processed
Too many people don't put things out there until they are 100% ready, myself included, you will never be 100% ready.

What is a soft launch?

A soft launch is a launch that has no real launch date, you just put your site or application live without announcing it. This has many benefits from being able to hone the website or application without having a lot of users and traffic. At some later stage, you may decide to do a launch, especially if your product is commercial, and you intend to monetize. For more on a Soft Launch, jump over to Wikipedia.

Why I did a soft launch

There are many reasons why I did a soft launch. I will outline the main reasons why in this article in the hope that I can inspire you to put your site live so you can also hone your skill.

It can be daunting, I know, and we bash ourselves up over not being good enough. I have listed 6 reasons below, some of them are related to each other, but I have listed them separately as they are unique in some way. These are not the only reasons but seem like the main reasons. The order they are in has no meaning apart from it being the order they fell together, let's have a look.

Work out My Direction

Not only did I want to concentrate on how I wanted to present myself and my expertise, since I have a broad range of skills, but I also wanted to make sure that I was on the right track before I went all-in on something.

The initial collection of articles on this site has allowed me to find a direction and a topic or subject area. This site, as I wrote in What is this design kojo thing anyway?, is a place to put experimental work and I may syndicate some of it to more specialised domains in the future. The general topic area is front-end development, but I have also been building out a small Drupal 9 get started guide to share my experience in developing this site and also so I had some different types of content to design for. That leads to my second reason.

Wanting to re-focus on front--end UI/UX development, I needed content to design for.

Without Content, You Can't Design

Due to not actively sharing my work for the last 10 years, I had no content to design for and was unsure what type of content I was going to produce. In a way, I still don't know what content I will be producing in the future.

Since I now have content on this site that needs better presentation, I can design content types and also content elements. Also, by having a bunch of content on the site, I can now write about the UI/UX process while building the new front-end.

Advocate for content-first design

As a side note, in the past I have built sites for business' with no content, I built a brand and then the content was filled in, this is somewhat reverse of what should be done, and I guess I passed a lot of value to those clients in the past. Some of my most successful projects have either come with content or I have included to get it written and created. In a normal design process, the content should be supplied to you by the client and if they don't have it then they really need to get to work for you.

I will be writing about this in more detail in the coming months, and I will be sure to link to it here. However, let's have a quick look at what content types and elements I have identified.

Content types I have identified

The types of content I have are; thought and or theory pieces, technical guides or coding pieces, and design pieces. These pieces can be broken into other smaller parts or elements.

Elements I have identified

I have identified elements such as

code samples

code demonstrations

images

text

video

And HTML Semantic elements such a

article

figure

aside

li

ol

ul

These content types and elements also need to be thought about for mobile, desktop, dark, and light.

Since I have real content to work with, I can now design.

Not knowing what content I would produce

This is related to the previous point.

As I got started I realised the content I was writing doesn't really stand alone, every time I write I see that I either need to write one or 2 supporting pieces or add aside content.

This means I need to design the aside content, add notes to remind myself to link to the forthcoming content, and create a process and system. This will always be the case I have learnt but when starting out it was hard to see this aspect of creating content.

What is aside content?
It is supplementary content that isn't needed for the main article but adds the necessary explanation for some readers. This content should be designed in such a way that it stands out as separate from the main content and mark up should also indicate it.

So to summarise the first 2 reasons, I really didn't know what type of content I was going to write, how it would need to be presented, or what styles would be needed to present it. Therefore, I needed to write a variation of content with a variety of elements that I may create so that in the future I can produce high-quality articles at a faster pace. This generally is not a problem when someone else is supplying the content, as the content brings with it these elements and also a voice, a tone, and a lot of design hints that can be used.

Workout a publishing process and hone my writing skills

When I started out I hadn't written for a while, I had written reports for business partners and clients, I had written blog posts for travel websites but writing tech & design related stuff was new to me, well for 8 years I hadn't written openly and for that reason I wanted to make sure what I putting out is adding value to my readers. I am still proofing and reviewing some of the content written back in August 2020 as I work out the design for various types of content, but I also feel now my writing and process is allowing to produce better quality, this takes time.

Part of writing also means you should develop a voice, a tone, and vocabulary. A great case study on this that I recommend to any business trying to distinguish themselves is the Mailchimp tone and voice style guide, you should be able to find that with a search of your favourite search engine.

Writing Style and Voice I hadn't been writing for a bit, so even though I was publishing, the content wasn't up to a high level. This is somewhat related to point one in needing content to design for.

Create a Voice and a brand

The way your voice is created can then be used in all your marketing. This may come naturally for some, but for me, I felt like I need to develop a personal brand and then stick with it. Having a few small rules just makes it easier in the end.

In creating this voice and tone you need to write, it's a bit of a chicken and an egg thing, so part of this process is still underway, but I also studied some writing courses to help out.

For me this was important as I am an extra extrovert if there is such a thing so putting out quality content that speaks for itself is important, I don't feel I am there yet and possibly never will be but to start by doing a soft launch has allowed me to at least get to a standard I am proud to put out there.

I Wanted to Create My Own Platform

This is more due to being a designer, and an off-the-shelf solution isn't what I wanted or needed.

If I am going to talk about UI/UX and front-end design and aesthetics then what a better place than my own site to put into practice what I am talking about, as I talk about it. You may say you are using Drupal, though, and that would be right. However, I do believe there is no point in redesigning the wheel and Drupal gives me the flexibility to build an awesome front-end without worrying about the back-end, yep even a JAM Stack needs to have an API, that's the A in JAM.

Final Thoughts

That's about it. In this article, I looked at what a soft launch is and then some of the reasons why I chose to do one. Some of the reasons I made are illustrated in the fact that I don't have the content types ready even for this piece, some of the ideas discussed such as not having supporting content ready, and not being that great at writing are also well illustrated.

Over time as I find more focus I will possibly do a hard launch for a section of this site. Hope you learnt something and if you'd like to follow on with the redesign and other thoughts as they come, I'd be stoked for you to sign up to my newsletter and get first access to my content. Yes, that's right, you will get first access to most of the content plus I have a few other things I will be launching very shortly so to be first on the list and in the know you know what to do. 😉

Thanks for reading.

# data[].attributes.metatag[].attributes.content
Installing Drupal 9 XML Sitemap Module for SEO.

# data[].attributes.metatag[].attributes.content
Installing Drupal 9 XML Sitemap Module for SEO.

# data[].attributes.body.value
An XML sitemaps, even though not needed they are recommended. XML sitemaps inform search engines about the structure of your site and other things such as date of last modification, priority, and change frequency. XML sitemap project module adheres to the Sitemap protocol as set out at sitemaps.org. https://www.sitemaps.org/protocol.html

XML sitemap module is easy to set up and is very customizable, allowing you to easily include most URLs automatically. The project also comes with two sub-modules; XML Sitemap Custom & XML Sitemap Engines.

XML Sitemap Custom allows you to add custom URL links. These are usually ones that are generated from Views pages such as a directory of product pages, to find these you would need to do a site audit and then add them manually or if you manage your sitemap as you build your site, recommended, add them when created.

XML Sitemap Engines submits your site to search engines. Google and Bing are automatically included but there is also a way to add links to other search engines. Read on to find out how easy it is to configure.

Info

Actively maintained Yes
Requires No extra requirements

https://www.drupal.org/project/xmlsitemap

Basics

Enable from the Extend page or using Drush, (see the Install a module page)

Run cron /admin/config/system/cron

Visit yoursite/sitemap.xml

Drupal Specific Set up
sites/default/files/xmlsitemap needs to be created with correct perms

You will see a basic sitemap with your homepage, you need to configure the module to include other pages on your site.

To configure

Visit: /admin/config/search/xmlsitemap/settings

Include a stylesheet for humans not needed but is nice when you are building your sitemap.

Advanced Settings

Sitemap cache directory - this should automatically be created

Default base URL needs to be added https://yoursiteURL.com

Enable developer mode to expose additional settings. This is not needed for basic set up.

A sitemap overview of visibility/inclusion will show once you have added content in the next step.

Add Content Pages to include

Custom Entities Settings
Sitemap Entities Tab

Visit: /admin/config/search/xmlsitemap/entities/settings (in the top tabs)

Check Content

Select which content types to include

Sitemap settings column make sure Configure

Configure: Inclusion / Default Priority / Default change frequency
*if pages are excluded by default you can add them on the content node edit form.

Save Configuration

Run Cron and Visit yoursite/sitemap.xml

There other types of content you can add to your sitemap, check the custom entities page.

Quite some steps, but once your site becomes large it means you can customize to your heart's content.

Sub Modules

XML Sitemap Custom

Add page generate from views or other.

Visit: /admin/config/search/xmlsitemap/custom

XML Sitemap Engines

Bing or google or custom site map using [sitemap] token.

Visit: /admin/config/search/xmlsitemap/engines

You need check which search engines to submit to, and if only to do if the sitemap have been updated since last submission.

Other Settings

Rebuild

This should only be used in emergencies.

Visit: /admin/config/search/xmlsitemap/rebuild

Permissions

Like all modules you can grant access to a user based on their role, in the case of a basic site leaving this as default, admin, is good.

Thoughts

I have used XML Sitemap module since Drupal 6 and it does a great job. There is also Simple Sitemap module which seems to be well-used, with nearly 80,000 sites reporting that they use it, XML Sitemap reports 1/4 million sites. Simple sitemap looks interesting with inclusion of images and also bilingual sitemaps. XML sitemap now has bilingual support for grouped URLs. I haven't tested this yet so will follow up in the coming month with another post to cover Simple Sitemap and how it differs. https://www.drupal.org/project/simple_sitemap

Troubleshooting

If things aren't set up correctly to start you may get something stuck in cache to start, best to use Rebuild while setting up as it will force the clearing of the cache.

# data[].attributes.body.processed
An XML sitemaps, even though not needed they are recommended. XML sitemaps inform search engines about the structure of your site and other things such as date of last modification, priority, and change frequency. XML sitemap project module adheres to the Sitemap protocol as set out at sitemaps.org. https://www.sitemaps.org/protocol.html

XML sitemap module is easy to set up and is very customizable, allowing you to easily include most URLs automatically. The project also comes with two sub-modules; XML Sitemap Custom & XML Sitemap Engines.

XML Sitemap Custom allows you to add custom URL links. These are usually ones that are generated from Views pages such as a directory of product pages, to find these you would need to do a site audit and then add them manually or if you manage your sitemap as you build your site, recommended, add them when created.

XML Sitemap Engines submits your site to search engines. Google and Bing are automatically included but there is also a way to add links to other search engines. Read on to find out how easy it is to configure.

Info

Actively maintained Yes
Requires No extra requirements

https://www.drupal.org/project/xmlsitemap

Basics

Enable from the Extend page or using Drush, (see the Install a module page)

Run cron /admin/config/system/cron

Visit yoursite/sitemap.xml

Drupal Specific Set up
sites/default/files/xmlsitemap needs to be created with correct perms

You will see a basic sitemap with your homepage, you need to configure the module to include other pages on your site.

To configure

Visit: /admin/config/search/xmlsitemap/settings

Include a stylesheet for humans not needed but is nice when you are building your sitemap.

Advanced Settings

Sitemap cache directory - this should automatically be created

Default base URL needs to be added https://yoursiteURL.com

Enable developer mode to expose additional settings. This is not needed for basic set up.

A sitemap overview of visibility/inclusion will show once you have added content in the next step.

Add Content Pages to include

Custom Entities Settings
Sitemap Entities Tab

Visit: /admin/config/search/xmlsitemap/entities/settings (in the top tabs)

Check Content

Select which content types to include

Sitemap settings column make sure Configure

Configure: Inclusion / Default Priority / Default change frequency
*if pages are excluded by default you can add them on the content node edit form.

Save Configuration

Run Cron and Visit yoursite/sitemap.xml

There other types of content you can add to your sitemap, check the custom entities page.

Quite some steps, but once your site becomes large it means you can customize to your heart's content.

Sub Modules

XML Sitemap Custom

Add page generate from views or other.

Visit: /admin/config/search/xmlsitemap/custom

XML Sitemap Engines

Bing or google or custom site map using [sitemap] token.

Visit: /admin/config/search/xmlsitemap/engines

You need check which search engines to submit to, and if only to do if the sitemap have been updated since last submission.

Other Settings

Rebuild

This should only be used in emergencies.

Visit: /admin/config/search/xmlsitemap/rebuild

Permissions

Like all modules you can grant access to a user based on their role, in the case of a basic site leaving this as default, admin, is good.

Thoughts

I have used XML Sitemap module since Drupal 6 and it does a great job. There is also Simple Sitemap module which seems to be well-used, with nearly 80,000 sites reporting that they use it, XML Sitemap reports 1/4 million sites. Simple sitemap looks interesting with inclusion of images and also bilingual sitemaps. XML sitemap now has bilingual support for grouped URLs. I haven't tested this yet so will follow up in the coming month with another post to cover Simple Sitemap and how it differs. https://www.drupal.org/project/simple_sitemap

Troubleshooting

If things aren't set up correctly to start you may get something stuck in cache to start, best to use Rebuild while setting up as it will force the clearing of the cache.

# data[].attributes.body.summary
Installing Drupal 9 XML Sitemap Module for SEO. 

# data[].attributes.title
Write your first artilce in Drupal & Frontpage content

# data[].attributes.metatag[].attributes.content
This article assumes you have set up your site and are ready to add content.

# data[].attributes.metatag[].attributes.content
This article assumes you have set up your site and are ready to add content.

# data[].attributes.body.value
This article assumes you have set up your site and are ready to add content.

Even though setting up your site correctly is important to get right you can always write your first article and then go back and make changes to layout and theme later, in fact, this is a smart idea. One thing I would really recommend doing though is to install and set up media if you intend to use images. I have written about that on the Drupal Media page but the main reason behind this recommendation is to have any images you upload to be managed as media items (entities), not only upload them to the file system, as it makes them more reusable.

Okay with that out of the way let's add an article

Creating your first piece of content

On the homepage of a fresh install of Drupal, you will have a message that welcomes you and a link to create your first article. This link takes you to the Add content page, you can also get to that page by using the admin menu.

Manage > Content > Add content
/node/add

If you use the manage content menu you will be on the content management page. From here you need to click the + Add content button and it will take you to the Add content page.

Okay, now we know where the add content route is I would like to mention that you can also use the Shortcuts menu.

The Admin Toolbar
On any new site I set up, I will add the Admin toolbar which makes it easier to get around the admin of your Drupal site. I suggest you add that module along with my other must-haves. If you got me to install and set up your site this will already be installed for you.

Okay, we are now on the Add content page.

Add Content

From the add content page, you will have two options. The two options you have are an article and a basic page.

Article

An article is used for time-sensitive content, think news or blogs. This will also automatically populate the homepage when published.

Basic Page

Use this to create basic static pages such as an about us page. If you do add a basic page you will also need to add a link to the page as it won't show on the homepage.

The process of adding an article or a basic page is the same. I will add an article as this will feed straight onto the homepage if you haven't changed the default settings for the article content type. If you want to add a basic page to the front page then you need to check promote to front page setting.

Add an article from the Add content page

1. Click Article

Manage > (Content >) Add content > Create Article
node/add/article

After you click on the article link you will be redirected to the create article page. On this page, there are content fields and a bunch of configuration fields as shown below.

Content fields

Title

Body

Tags

Image - This is a basic image field by default. If you have set up Media and replaced the Image field with a Media field.

Configurations Fields

Revision Log Message

Menu settings

Comment settings

URL alias

Authoring information

Promotion options

Published check box

The published checkbox is positioned above the Save button.

2. Fill in the fields and settings.

3. Save

On save you will be taken to your newly created article and if you then navigate to the homepage you will see that your new article is there with a read more link.

Conclusion

Congratulations, you have published your first article and it is on the front page. As such this set up is great for a blog or to get going with setting up a new site. In time, however, you will probably want to modify your site to show something different on your homepage. I will be writing more about setting up a new Drupal site so be sure to subscribe to my newsletter where you will get a mix of front-end development tips and news as well as more on using Drupal and other headless CMSs.

Thanks for reading.

# data[].attributes.body.processed
This article assumes you have set up your site and are ready to add content.

Even though setting up your site correctly is important to get right you can always write your first article and then go back and make changes to layout and theme later, in fact, this is a smart idea. One thing I would really recommend doing though is to install and set up media if you intend to use images. I have written about that on the Drupal Media page but the main reason behind this recommendation is to have any images you upload to be managed as media items (entities), not only upload them to the file system, as it makes them more reusable.

Okay with that out of the way let's add an article

Creating your first piece of content

On the homepage of a fresh install of Drupal, you will have a message that welcomes you and a link to create your first article. This link takes you to the Add content page, you can also get to that page by using the admin menu.

Manage > Content > Add content
/node/add

If you use the manage content menu you will be on the content management page. From here you need to click the + Add content button and it will take you to the Add content page.

Okay, now we know where the add content route is I would like to mention that you can also use the Shortcuts menu.

The Admin Toolbar
On any new site I set up, I will add the Admin toolbar which makes it easier to get around the admin of your Drupal site. I suggest you add that module along with my other must-haves. If you got me to install and set up your site this will already be installed for you.

Okay, we are now on the Add content page.

Add Content

From the add content page, you will have two options. The two options you have are an article and a basic page.

Article

An article is used for time-sensitive content, think news or blogs. This will also automatically populate the homepage when published.

Basic Page

Use this to create basic static pages such as an about us page. If you do add a basic page you will also need to add a link to the page as it won't show on the homepage.

The process of adding an article or a basic page is the same. I will add an article as this will feed straight onto the homepage if you haven't changed the default settings for the article content type. If you want to add a basic page to the front page then you need to check promote to front page setting.

Add an article from the Add content page

1. Click Article

Manage > (Content >) Add content > Create Article
node/add/article

After you click on the article link you will be redirected to the create article page. On this page, there are content fields and a bunch of configuration fields as shown below.

Content fields

Title

Body

Tags

Image - This is a basic image field by default. If you have set up Media and replaced the Image field with a Media field.

Configurations Fields

Revision Log Message

Menu settings

Comment settings

URL alias

Authoring information

Promotion options

Published check box

The published checkbox is positioned above the Save button.

2. Fill in the fields and settings.

3. Save

On save you will be taken to your newly created article and if you then navigate to the homepage you will see that your new article is there with a read more link.

Conclusion

Congratulations, you have published your first article and it is on the front page. As such this set up is great for a blog or to get going with setting up a new site. In time, however, you will probably want to modify your site to show something different on your homepage. I will be writing more about setting up a new Drupal site so be sure to subscribe to my newsletter where you will get a mix of front-end development tips and news as well as more on using Drupal and other headless CMSs.

Thanks for reading.

# data[].attributes.title
Basic Site Settings & Creating a New Front Page

# data[].attributes.metatag[].attributes.content
Basic Site Setting & default front page and how to create a new front page or homepage in Drupal 9.

# data[].attributes.metatag[].attributes.content
Basic Site Setting & default front page and how to create a new front page or homepage in Drupal 9.

# data[].attributes.body.value
This basic site settings page is something that gets populated on install and you won't really need to visit it much. One of the main reasons you will probably want to visit it is to change the default front page.

Other settings you may change on this page are listed below. If you can't find the setting you need then you can also check the theme settings page which can be found by using the appearance link in the admin toolbar and then using the settings link associated with the theme.

The Basic site setting page can be found in the configuration section.
Manage > Configuration > Basic site settings
/admin/config/system/site-information

Below are the settings found on this page.

Site Details

Site name

Slogan

Email Address

Site name and slogan used in the theme usually but if you design a custom theme you may in fact leave them out. The email address is used for automated emails from the system and should be the same as the domain name.

Front page

Default front page
Optionally, specify a relative URL to display as the front page. Leave blank to display the default front page.

Error Pages

Default 403 (access denied) page

Default 404 (not found) page

These can be left blank and a generic page will be served.

All in all the settings are self-explanatory but let's go over changing the front page and then look at some quick ways you can modify the front page of your Drupal site.

Change the Frontpage

To change the front page you can add any URL from your site. You need to add a path that starts with a slash. Since this will be your homepage and the path will be stripped from the URL you can either use a node URL such as /node/3 or a pretty URL, such as /my-custom-front-page.

Pretty URLs and Drupal
To generate pretty URLs automatically you need to have all the path modules installed and set up. To find more about setting up paths and redirects please read Drupal SEO modules.

Okay, so now you know how to change the front page let's look at a few quick ways to create a new front page.

Building a new Frontpage

There are many ways to create a new front page but I will first look at the default front page.

The default front page

The default front page is in fact built using views and the front page view feeds any content that is promoted to the front page in the content's individual setting. You can find out more about node settings on creating your first article page if you haven't already read it.

Change the default front page

One of the quickest ways to change this is to add a header to the view and/or add a block to the content top region.

Add a header to the view

By adding a header to the view you can write an introduction to your site and this will be displayed above the list of articles or blogs that feed onto your homepage. To add a header to the view follow these steps.

1. Hover over the view section on the homepage and click on the small pencil icon.

2. Click on Edit view

3. Click on Add in the Header section

4. Check Text area Global.

5. Apply all displays. You could override the display using the For select menu at the top and select This page (override)

6. Check Display even if view has no result.

7. Add your text to the Content text area.
You can change the text format from Basic HTML to Full HTML if you like.
You can't load images here but you can use images that are hosted on your site.

8. Click Apply (all displays) or (this display)

9. Save the view.

Even though this is a nice quick solution it is limited in the fact you need to work with HTML, so in the end, you will probably want to find a more permanent solution.

To access the Frontpage view you can also use the views admin page at
Manage > Structure > Views
/admin/structure/views

Add a block to the content top region

I have written about blocks and regions but to do this you can visit the block layout page and click place block and then add custom block, add an image and you are done.
For more on blocks layouts and custom blocks the below resources.

What are Drupal blocks? Creating a simple block and placing a block.

Creating Customs Blocks and Custom Block Types in Drupal 9.

As nice as these quick solutions are in the end you will probably want to create a better homepage.

Create a New Frontpage

If you want to take things further then you will probably want to create an entirely new front page and one of the best ways to do that is to use a node and use some advanced built-in layout techniques such as adding fields and managing the display of the fields. You can even use layout builder to easily layout pages without any need to code. You will need to have the theme or CSS written to style it nicely but if you keep things simple and keep some basic design rules such as spacing and consistency you can get something quite complex put together without needing to have custom CSS written.

Even though I say complex please don't overdo it as having one message and one call to action will always be the best solution above the fold but adding supporting information lower on the page is a good idea.

I have written more about adding fields and configuring them on the create a field page and you can get more information about creating a new content type on this page.

Check back shortly for more ideas and no-code solutions using built-in modules and also well-supported contributed modules.

Once you have a new page ready to use as a front page you can add the URL to the Front page field on the basic site settings page.

Conclusion

In this article, we have looked at the basic site setting and then looked at a few ways to use views and blocks to modify the default homepage. We then discussed how we can use a node and more advanced layout and display tools that Drupal provides. Hope you enjoyed it and if you want more tips on front-end development and design including using technologies such a Drupal and Vue.js be sure to sign up for my newsletter.

# data[].attributes.body.processed
This basic site settings page is something that gets populated on install and you won't really need to visit it much. One of the main reasons you will probably want to visit it is to change the default front page.

Image

Other settings you may change on this page are listed below. If you can't find the setting you need then you can also check the theme settings page which can be found by using the appearance link in the admin toolbar and then using the settings link associated with the theme.

The Basic site setting page can be found in the configuration section.
Manage > Configuration > Basic site settings
/admin/config/system/site-information

Below are the settings found on this page.

Site Details

Site name

Slogan

Email Address

Site name and slogan used in the theme usually but if you design a custom theme you may in fact leave them out. The email address is used for automated emails from the system and should be the same as the domain name.

Front page

Default front page
Optionally, specify a relative URL to display as the front page. Leave blank to display the default front page.

Error Pages

Default 403 (access denied) page

Default 404 (not found) page

These can be left blank and a generic page will be served.

All in all the settings are self-explanatory but let's go over changing the front page and then look at some quick ways you can modify the front page of your Drupal site.

Change the Frontpage

To change the front page you can add any URL from your site. You need to add a path that starts with a slash. Since this will be your homepage and the path will be stripped from the URL you can either use a node URL such as /node/3 or a pretty URL, such as /my-custom-front-page.

Pretty URLs and Drupal
To generate pretty URLs automatically you need to have all the path modules installed and set up. To find more about setting up paths and redirects please read Drupal SEO modules.

Okay, so now you know how to change the front page let's look at a few quick ways to create a new front page.

Building a new Frontpage

There are many ways to create a new front page but I will first look at the default front page.

The default front page

The default front page is in fact built using views and the front page view feeds any content that is promoted to the front page in the content's individual setting. You can find out more about node settings on creating your first article page if you haven't already read it.

Change the default front page

One of the quickest ways to change this is to add a header to the view and/or add a block to the content top region.

Add a header to the view

By adding a header to the view you can write an introduction to your site and this will be displayed above the list of articles or blogs that feed onto your homepage. To add a header to the view follow these steps.

1. Hover over the view section on the homepage and click on the small pencil icon.

2. Click on Edit view

3. Click on Add in the Header section

4. Check Text area Global.

5. Apply all displays. You could override the display using the For select menu at the top and select This page (override)

6. Check Display even if view has no result.

7. Add your text to the Content text area.
You can change the text format from Basic HTML to Full HTML if you like.
You can't load images here but you can use images that are hosted on your site.

8. Click Apply (all displays) or (this display)

9. Save the view.

Even though this is a nice quick solution it is limited in the fact you need to work with HTML, so in the end, you will probably want to find a more permanent solution.

To access the Frontpage view you can also use the views admin page at
Manage > Structure > Views
/admin/structure/views

Add a block to the content top region

I have written about blocks and regions but to do this you can visit the block layout page and click place block and then add custom block, add an image and you are done.
For more on blocks layouts and custom blocks the below resources.

What are Drupal blocks? Creating a simple block and placing a block.

Creating Customs Blocks and Custom Block Types in Drupal 9.

As nice as these quick solutions are in the end you will probably want to create a better homepage.

Create a New Frontpage

If you want to take things further then you will probably want to create an entirely new front page and one of the best ways to do that is to use a node and use some advanced built-in layout techniques such as adding fields and managing the display of the fields. You can even use layout builder to easily layout pages without any need to code. You will need to have the theme or CSS written to style it nicely but if you keep things simple and keep some basic design rules such as spacing and consistency you can get something quite complex put together without needing to have custom CSS written.

Even though I say complex please don't overdo it as having one message and one call to action will always be the best solution above the fold but adding supporting information lower on the page is a good idea.

I have written more about adding fields and configuring them on the create a field page and you can get more information about creating a new content type on this page.

Check back shortly for more ideas and no-code solutions using built-in modules and also well-supported contributed modules.

Once you have a new page ready to use as a front page you can add the URL to the Front page field on the basic site settings page.

Conclusion

In this article, we have looked at the basic site setting and then looked at a few ways to use views and blocks to modify the default homepage. We then discussed how we can use a node and more advanced layout and display tools that Drupal provides. Hope you enjoyed it and if you want more tips on front-end development and design including using technologies such a Drupal and Vue.js be sure to sign up for my newsletter.

# data[].attributes.body.summary
Basic Site Setting & default front page and how to create a new front page or homepage in Drupal 9.

# data[].attributes.title
Modify the Output of a Drupal Views View using the UI

# data[].attributes.metatag[].attributes.content
Modifying the output of a View in Drupal via the UI is easy for any site-builder or user that has Views administration permissions to do so. What is Views ?

# data[].attributes.metatag[].attributes.content
Modifying the output of a View in Drupal via the UI is easy for any site-builder or user that has Views administration permissions to do so. What is Views ?

# data[].attributes.body.value
Modifying the output of a View in Drupal via the UI is easy for any site-builder or user that has Views administration permissions to do so.

What is Views ?

Views is a way to build customized lists and queries from your database: think product lists, lists of all you articles, a gallery from your post's images, or even placing locations on a map. You can add any field from your content type to your View, or reference any field in another content type and customize the SQL query in an advanced UI. You can even see the SQL that Views built for you. For more information check Views documentation on Drupal.org https://www.drupal.org/docs/8/core/modules/views/overview

In this example we will modify the sticky field found in all content types by default; it is used to stick content to the top of your list by checking a checkbox. We will modify the output so we can style it with a nice pin icon. To add the CSS for the pin icon you will need to have access to the theme code-base but other than that everything else can be done in the UI.

To be able to modify the output you first need to add the field to the view. I will cover this in more depth in another article as it goes beyond the scope of this piece, but to add a field to the View output you have to set the View display format to show fields and then add a field.

Modify a Field Using Rewrite Results

So we have the field as shown above with the label Content: Sticky at top of lists.

Click on this to modify or do it at the time of adding the field.

Clicking on the field opens up the configure field modal dialog box. The options will be slightly different depending on the field type.

Since sticky is a checkbox we only have the formatter of boolean. Then we have the option to change the output, since I am using this to display code if the checkbox is checked I have chosen 1/0 , but multiple option values are included, including custom.

There are other configuration option as shown but to customize the code output we only need to Rewrite results.

1. Click Rewrite results

2. Check Override the output of this field with custom text.

Next, we need to get the value of the field.

3. Click the replacement patterns
you will see we have 2 options.
I'm going to use {{ sticky__value }} == Raw value.

We can rewrite fields using values from other fields too. To do this you need to rearrange the fields in the UI and then you will have access to all fields above. In this case we don't need access to another field value so leaving it at the top is fine. [IMAGE 6]

4. In the Text area we can write our new output.

Using Twig to Rewrite the Output

Since Drupal 8, Twig has been used as the template engine. Twig is a PHP template engine and uses {{ }} and {% %} to render PHP in your templates. Twig is part of Symfony.

We are going to write a conditional, below is our pseudo code.

If the value of our boolean is 1 (checked).

Then add a unordered list (ul) with 1 li item.

The list item content will be the pin icon's custom character code  from our ui_blog custom font.

We also want to add a class to the li item and the i element.

This is our final snippet of code, it says if sticky value equals checked then include the code.

{% if  sticky__value == 1 %}
  <ul>
    <li class="pinned-sticky">
      <div class="" title="Code: 0xe805"><i class="ui_blog">&#xe800;</i></div>
    </li>
  </ul>
{% endif %}

After adding the code to the text area

5. Click Apply (this display)

6. Click Save

You will notice at the top For This block (override), if we had more than one display that we want this modification to be applied to we could apply it to All displays. However, in this case I only want to show the pin on the homepage display.

Add CSS rules to the theme

I had already added the code to my theme and included the custom ui_blog font so it shows. I will be writing about how to add nice custom icons, not just to Drupal themes, to any site in an upcoming article, make sure you subscribe to find out how.

Here is the code I added. Note that you would need to add position relative to the parent of the li for the absolute position to work.

.ui_blog {
  font-family: "ui_blog";
  font-size: 1.8em;
  color: #186fae;
}

.views-row li.pinned-sticky {
  position: absolute;
  top: -.5em;
  list-style: none;
  left: .5em;
}

So that's how you can modify the output of a View in the UI, the options are endless, and with Drupal's caching system this remains super fast. We can also create templates in our theme but for things like this that would be a bit of an over-kill. Thanks for reading and be sure to check some other articles.

You may also like...

Enabling Drupal 9 as a Headless CMS to work with Vue.js

# data[].attributes.body.processed
Modifying the output of a View in Drupal via the UI is easy for any site-builder or user that has Views administration permissions to do so.

What is Views ?

Views is a way to build customized lists and queries from your database: think product lists, lists of all you articles, a gallery from your post's images, or even placing locations on a map. You can add any field from your content type to your View, or reference any field in another content type and customize the SQL query in an advanced UI. You can even see the SQL that Views built for you. For more information check Views documentation on Drupal.org https://www.drupal.org/docs/8/core/modules/views/overview

In this example we will modify the sticky field found in all content types by default; it is used to stick content to the top of your list by checking a checkbox. We will modify the output so we can style it with a nice pin icon. To add the CSS for the pin icon you will need to have access to the theme code-base but other than that everything else can be done in the UI.

Image

To be able to modify the output you first need to add the field to the view. I will cover this in more depth in another article as it goes beyond the scope of this piece, but to add a field to the View output you have to set the View display format to show fields and then add a field.

Image

Drupal Views edit UI showing format setting set to Show: Fields and also the Add field button.

Modify a Field Using Rewrite Results

So we have the field as shown above with the label Content: Sticky at top of lists.

Click on this to modify or do it at the time of adding the field.

Clicking on the field opens up the configure field modal dialog box. The options will be slightly different depending on the field type.

Image

Since sticky is a checkbox we only have the formatter of boolean. Then we have the option to change the output, since I am using this to display code if the checkbox is checked I have chosen 1/0 , but multiple option values are included, including custom.

Image

There are other configuration option as shown but to customize the code output we only need to Rewrite results.

Image

1. Click Rewrite results

2. Check Override the output of this field with custom text.

Next, we need to get the value of the field.

3. Click the replacement patterns
you will see we have 2 options.
I'm going to use {{ sticky__value }} == Raw value.

We can rewrite fields using values from other fields too. To do this you need to rearrange the fields in the UI and then you will have access to all fields above. In this case we don't need access to another field value so leaving it at the top is fine. [IMAGE 6]

4. In the Text area we can write our new output.

Using Twig to Rewrite the Output

Since Drupal 8, Twig has been used as the template engine. Twig is a PHP template engine and uses {{ }} and {% %} to render PHP in your templates. Twig is part of Symfony.

We are going to write a conditional, below is our pseudo code.

If the value of our boolean is 1 (checked).

Then add a unordered list (ul) with 1 li item.

The list item content will be the pin icon's custom character code  from our ui_blog custom font.

We also want to add a class to the li item and the i element.

This is our final snippet of code, it says if sticky value equals checked then include the code.

{% if  sticky__value == 1 %}
  <ul>
    <li class="pinned-sticky">
      <div class="" title="Code: 0xe805"><i class="ui_blog">&#xe800;</i></div>
    </li>
  </ul>
{% endif %}

After adding the code to the text area

5. Click Apply (this display)

6. Click Save

You will notice at the top For This block (override), if we had more than one display that we want this modification to be applied to we could apply it to All displays. However, in this case I only want to show the pin on the homepage display.

Add CSS rules to the theme

I had already added the code to my theme and included the custom ui_blog font so it shows. I will be writing about how to add nice custom icons, not just to Drupal themes, to any site in an upcoming article, make sure you subscribe to find out how.

Here is the code I added. Note that you would need to add position relative to the parent of the li for the absolute position to work.

.ui_blog {
  font-family: "ui_blog";
  font-size: 1.8em;
  color: #186fae;
}

.views-row li.pinned-sticky {
  position: absolute;
  top: -.5em;
  list-style: none;
  left: .5em;
}

So that's how you can modify the output of a View in the UI, the options are endless, and with Drupal's caching system this remains super fast. We can also create templates in our theme but for things like this that would be a bit of an over-kill. Thanks for reading and be sure to check some other articles.

You may also like...

Enabling Drupal 9 as a Headless CMS to work with Vue.js

# data[].attributes.title
SMTP Authentication Support Module for Drupal

# data[].attributes.metatag[].attributes.content
Send email using an SMTP server to guarantee delivery of you important messages.

# data[].attributes.metatag[].attributes.content
Send email using an SMTP server to guarantee delivery of you important messages.

# data[].attributes.body.value
If you want to send email from your Drupal site then this is the module to use. It uses the PHPMailer Class via the PHPMailer package.

From the Github repository

PHPMailer is a full-featured email creation and transfer class for PHP

PHP mail() class can be used but you will end up with delivery issues.

Up until now, you may have been using the UI or FTP method to install and update your modules but from my experience trying to set up SMTP module and downloading the PHP Mailer Class and adding it to your libraries directory is a futile job. Now is the time if any to learn Composer.

If you are unfamiliar with Composer, it is the PHP package manager, similar to NPM or Yarn for JavaScript. I have written a short guide to Composer at Getting Going Composer.

Info

https://www.drupal.org/project/smtp

Actively maintained Yes, report installs 148,153
Requires No extra requirements
Libraries requires 6.x PHPMailer which is the latest version. "phpmailer/phpmailer": "^6.2"

Once installed correctly you can check Status Report /admin/reports/status If it isn't installed correctly you will get a message.

Basics

Install with Composer

composer require drupal/smtp

Running the above command with download everything needed, it's that simple.

Then either visit the Extend page and Install or run the Drush command if you are using Drush.

drush smtp en

For Manual UI install you need to download the library and put it the libraries directory yourself, as I said I have tried to do this on some non-Composer managed sites and it has been futile. In the end, I used Composer to install SMTP even on non-Composer managed sites and this worked.

Another option is the PHPMailer SMTP module. I haven't used this so I can not recommend it but from what I have read it can be installed without the need for Composer.

Once you have installed SMTP visit the configuration page.

SMTP Authentication Support Configuration

Manage > Configuration > System > SMTP Authentication Support
/admin/config/system/smtp

You will need your SMTP server name and you will also need the port number, for the mail service I use it is 465 but sometimes it maybe 587.

Search outgoing email server for your Email service provider and you should find the relevant information.

You will also need your email address and password for SMTP Authentication.

Once you have filled in the server and authentication details there are few other optional settings as outlined below.

E-mail options

Email options allow you to specify the name and email address that emails come from if different from the site default.

You can allow messages to be sent formatted in HTML by checking Allow to send e-mails formatted as HTML.

Testing and debug check built-in

After you have set up everything you can send a test e-mail and also turn on debugging if you have problems.

That's about it. Now your emails will use your SMTP server and not the PHP mail class.

Thanks for reading and be sure to reach out if you have a question or need help.

# data[].attributes.body.processed
If you want to send email from your Drupal site then this is the module to use. It uses the PHPMailer Class via the PHPMailer package.

From the Github repository

PHPMailer is a full-featured email creation and transfer class for PHP

PHP mail() class can be used but you will end up with delivery issues.

Up until now, you may have been using the UI or FTP method to install and update your modules but from my experience trying to set up SMTP module and downloading the PHP Mailer Class and adding it to your libraries directory is a futile job. Now is the time if any to learn Composer.

If you are unfamiliar with Composer, it is the PHP package manager, similar to NPM or Yarn for JavaScript. I have written a short guide to Composer at Getting Going Composer.

Info

https://www.drupal.org/project/smtp

Actively maintained Yes, report installs 148,153
Requires No extra requirements
Libraries requires 6.x PHPMailer which is the latest version. "phpmailer/phpmailer": "^6.2"

Once installed correctly you can check Status Report /admin/reports/status If it isn't installed correctly you will get a message.

Image

Basics

Install with Composer

composer require drupal/smtp

Running the above command with download everything needed, it's that simple.

Then either visit the Extend page and Install or run the Drush command if you are using Drush.

drush smtp en

For Manual UI install you need to download the library and put it the libraries directory yourself, as I said I have tried to do this on some non-Composer managed sites and it has been futile. In the end, I used Composer to install SMTP even on non-Composer managed sites and this worked.

Another option is the PHPMailer SMTP module. I haven't used this so I can not recommend it but from what I have read it can be installed without the need for Composer.

Once you have installed SMTP visit the configuration page.

SMTP Authentication Support Configuration

Manage > Configuration > System > SMTP Authentication Support
/admin/config/system/smtp

You will need your SMTP server name and you will also need the port number, for the mail service I use it is 465 but sometimes it maybe 587.

Search outgoing email server for your Email service provider and you should find the relevant information.

You will also need your email address and password for SMTP Authentication.

Once you have filled in the server and authentication details there are few other optional settings as outlined below.

E-mail options

Email options allow you to specify the name and email address that emails come from if different from the site default.

You can allow messages to be sent formatted in HTML by checking Allow to send e-mails formatted as HTML.

Testing and debug check built-in

After you have set up everything you can send a test e-mail and also turn on debugging if you have problems.

That's about it. Now your emails will use your SMTP server and not the PHP mail class.

Thanks for reading and be sure to reach out if you have a question or need help.

# data[].attributes.body.summary
Send email using an SMTP server to guarantee delivery of you important messages.

# data[].attributes.metatag[].attributes.content
So you might be wondering, probably not, what this Design Kojo thing is. This page is a quick post to explain exactly that.

# data[].attributes.metatag[].attributes.content
So you might be wondering, probably not, what this Design Kojo thing is. This page is a quick post to explain exactly that.

# data[].attributes.body.value
So you might be wondering, probably not, what this Design Kojo thing is. This page is a quick post to explain exactly that.

Design Kojo is a name I came up with over 10 years ago when setting up a business to focus mainly on digital and web design. Over the years I have done much more from 3D work to marketing to full-stack web development to management and online strategy of start-ups, and marketing of real-estate. I guess you could say jack of all trades and a master of none. Joke aside, with that coming to an end the old Design Kojo is now somewhat finished.

This is a new vision under the old name and maybe more fitting to the Design Kojo name and meaning, kōjō or factory from Japanese. Here I will be adding all my working thoughts and will syndicate to a portfolio site or elsewhere if I feel the work needs a different home. So that's it, design kōjō, a factory of thoughts on by design.

In some following rambling posts, I will cover other interesting information on why this site runs on Drupal, what I plan to do, and when I will release a portfolio or business site. This site though will be focused on exploring tech and in particular front-end development and design. Be sure to sign up to the newsletter to get a mix of design and development news, practical tips and tutorials, my past design and development work from the archives, and spots lights on other awesome designers and developers.

Here's to a bright and exciting future, cheers 🍻

# data[].attributes.body.processed
So you might be wondering, probably not, what this Design Kojo thing is. This page is a quick post to explain exactly that.

Design Kojo is a name I came up with over 10 years ago when setting up a business to focus mainly on digital and web design. Over the years I have done much more from 3D work to marketing to full-stack web development to management and online strategy of start-ups, and marketing of real-estate. I guess you could say jack of all trades and a master of none. Joke aside, with that coming to an end the old Design Kojo is now somewhat finished.

This is a new vision under the old name and maybe more fitting to the Design Kojo name and meaning, kōjō or factory from Japanese. Here I will be adding all my working thoughts and will syndicate to a portfolio site or elsewhere if I feel the work needs a different home. So that's it, design kōjō, a factory of thoughts on by design.

In some following rambling posts, I will cover other interesting information on why this site runs on Drupal, what I plan to do, and when I will release a portfolio or business site. This site though will be focused on exploring tech and in particular front-end development and design. Be sure to sign up to the newsletter to get a mix of design and development news, practical tips and tutorials, my past design and development work from the archives, and spots lights on other awesome designers and developers.

Here's to a bright and exciting future, cheers 🍻

# data[].attributes.metatag[].attributes.content
In this article, I will look at making a 3D cube in detail by looking at the 3D space and CSS 3D properties and values needed to make a cube.

# data[].attributes.metatag[].attributes.content
In this article, I will look at making a 3D cube in detail by looking at the 3D space and CSS 3D properties and values needed to make a cube.

# data[].attributes.metatag[].attributes.content
translate cube faces to make a cube in CSS

# data[].attributes.body.value
In this article, I will be explaining how to make a 3D cube in CSS.

Before I start I want to note I have used Flexbox to demonstrate this but Flexbox (display: flex;) is not needed¹. Items should be placed absolute in a wrapper div or element with the outer element set to relative.

¹If you want a 3D item to sit in the middle of a larger wrapper element then flexbox can still be handy but as you will see in the second part making the wrapper a set size and then making all the elements/faces of the item relative makes the object more re-usable.

So to make it clear Flexbox is only being used to demonstrate how the transform values work on the separate faces to keep them spaces nicely. I will point out the unneeded property values as we go and provide the complete items code in the second part.

Let's get stuck in.

Setting up the workspace

Normal

rotateY 45

rotateY 135

rotateY 225

rotateY 315

rotateX 90

rotateX -90

The below code will create the above demonstration minus the yellow square and the black normal line.

<div class="wrapper-transform-cube">
  <div class="transform--inner ">rotateY 45</div>
  <div class="transform--inner ">rotateY 135</div>
  <div class="transform--inner ">rotateY 225</div>
  <div class="transform--inner ">rotateY 315</div>
  <div class="transform--inner ">rotateX 90</div>
  <div class="transform--inner ">rotateX -90</div>
</div>

/* 3d Transform/Perspectives
 */
.wrapper-transform-cube {
  display: flex;
  flex-direction: row;
  justify-content: space-around;
  width: 90vw;
  height: 12vw;
  margin: 4em auto;
  border: 1px solid black;
  background-color: rgba(173, 255, 47, 0.48);
  /* Setting up the 3D space */
  perspective: 100cm;
  transform-style: preserve-3d;
}
.wrapper-transform-cube .transform--inner {
  width: 12vw;
  height: 12vw;
  border: 0 solid black;
  background-color: #1cc9fe;
}

So we have the setup done with 7 squares in the wrapper. The wrapper has a 3D perspective set on it and transform-style. For now, I won't go into detail on these properties but for 3D we need them on the wrapper.

perspective: 100cm;
transform-style: preserve-3d;

I have coloured the wrapper and added a centre line so we have some perspective to compare to as we go through steps. These are not included in the code sample above, neither is the 7 square on the left.

I have also added some text to explain the faces, namely the rotation we are going to do. The 7th square on the left is there as a reference so you can see what the transform operations do on the element looking straight on.

Rotate the faces of the cube

There are many ways we can manage the rotation of our squares which will become the faces of the cube. We could rotate the 4 sides on the Y-axis at 0˚, 90˚, 180˚, and 270˚ or any combination of values 90˚ apart. For this demonstration, I am going to use the angles 45˚, 135˚, 225˚, & 315˚. I will mention this again later as to why I used these values but for now, just remember they are at 90˚.

Normal

rotateY 45

rotateY 135

rotateY 225

rotateY 315

rotateX 90

rotateX -90

Below is the CSS needed to rotate the faces and the corresponding background-color. You will see that I have added these transforms to each individual face using a new class. For these to work you need to add the class to each face class attribute value like the following example.

-  <div class="transform--inner">rotateY 45</div>
+  <div class="transform--inner transform__inner--rotateY45 ">rotateY 45</div>

/* Rotate Cube Faces */
.wrapper-transform-cube .transform__inner--rotateY45 {
  background-color: #fe3136;
  transform: rotateY(45deg);
}
.wrapper-transform-cube .transform__inner--rotateY135 {
  background-color: #6bfe79;
  transform: rotateY(135deg);
}
.wrapper-transform-cube .transform__inner--rotateY225 {
  background-color: #1cc9fe;
  transform: rotateY(225deg);
}
.wrapper-transform-cube .transform__inner--rotateY315 {
  background-color: #fcfe79;
  transform: rotateY(315deg);
}
.wrapper-transform-cube .transform__inner--rotateX90 {
  background-color: #f6a822;
  transform: rotateX(90deg) rotateZ(45deg);
}
.wrapper-transform-cube .transform__inner--rotateX180 {
  background-color: #f6a822;
  transform: rotateX(-90deg) rotateZ(45deg);
}

With that, we can now see our cube faces rotate. I also rotated the faces on the right 90˚ and -90˚ on the x-axis for the top and bottom respectively. You can't see the top and bottom now. You can also see how rotating the faces for the sides cuts through the yellow wrapper, this is the transform-style: preserve-3d in effect.

Rotate the outer wrapper

To see the top and bottom we can tilt the wrapper on the x-axis

Using a negative deg value we can see it from above and positive from below. There you go, top and bottom insight.

Normal

rotateY 45

rotateY 135

rotateY 225

rotateY 315

rotateX 90

rotateX -90

/* 3d Transform/Perspectives */
.wrapper-transform-cube {
  display: flex;
  flex-direction: row;
  justify-content: space-around;
  width: 90vw;
  height: 12vw;
  margin: 4em auto;
  border: 1px solid black;
  background-color: rgba(173, 255, 47, 0.48);
  /* Setting up the 3D space */
  perspective: 100cm;
  transform-style: preserve-3d;
+ transform: rotateX(-30deg);
}

Make the Inner Elements Absolute

The next step is to remove the spacing on the element, as I said this spacing was added just to illustrate what is happening in the 3D space. To do this all we need to do is add absolute to the faces. Since we have Flexbox space around they all go to the centre, boom!

Normal

rotateY 45

rotateY 135

rotateY 225

rotateY 315

rotateX 90

rotateX -90

.wrapper-transform-cube .transform--inner {
  width: 12vw;
  height: 12vw;
  border: 0 solid black;
  background-color: #1cc9fe;
+ position: absolute;
}

Look at the top view to explore the thinness of the elements

A quick detour to look at it from the top as it seems we only have 2 faces now.

Note I have only tilted the wrapper to 89˚, this is because at 90˚ we won't see anything due to CSS elements not having any depth, but at the same time, they are 2 sided. This is one of the limitations of CSS in the 3D space, something I won't talk about here but will do in the future. It is something to keep in mind.

.wrapper-transform-cube {
- transform: rotateX(-30deg);
+ transform: rotateX(-89deg);
}

Normal

rotateY 45

rotateY 135

rotateY 225

rotateY 315

rotateX 90

rotateX -90

As stated it seems we only have 2 faces now but that is because the 45 and 225 faces are on top of each other and the 135 and 315 faces are on top of each other. Let's fix it by switching back to our above view and translate the faces.

Translate on the Z-Axis

To translate an item is to move the face along its axis or its plane, let's have a look at the following image to see what that means.

As the image illustrates you can move an element along its axis or plane relative to itself, this is actually crucial to understand. See how the elements at 45 degrees translate on the z-axis actually move out on the same angle?

These are like our faces of the cube, one of these is rotated 135˚ and the other 315˚, the ones rotated at 45˚ and 225˚ are hidden as explained earlier. When you translate these faces on the same z-axis by the same value they move away from each other. The elements remember which side is front and therefore the translate will be in the exact opposite direction for planes at 90˚ to each other, cool aye?

Add translate to the 6 sides of half the width of each face and see what happens?

Normal

rotateY 45

rotateY 135

rotateY 225

rotateY 315

rotateX

rotateX

.wrapper-transform-cube .transform__inner--rotateY45 {
  background-color: #fe3136;
- transform: rotateY(45deg);
+ transform: rotateY(45deg) translateZ(6vw);
}

Top and Bottom

The top and bottom had been left until now but usually, they would be transformed the same as the other faces so to finish up I'll make them absolute and make all the faces have slight transparency added.

rotateY 45

rotateY 135

rotateY 225

rotateY 315

rotateX

rotateX

To wrap up let look at the same cube made with the initial faces rotate at 0˚, 90˚, 180˚, and 270˚.

Rotate Cube faces at 0˚, 90˚, 180˚, and 270˚

rotateY 0

rotateY 90

rotateY 180

rotateY 270

rotateX

rotateX

See why I rotated them at 45˚, 135˚, 225˚, & 315˚ for this demonstration, the way to fix this is to rotate the wrapper by 45˚ and then we get the same. I didn't do it this way so we could use the wrapper looking straight on and not at the angle.

Rotate Cube faces at 0˚, 90˚, 180˚, and 270˚ and wrapper at 45˚

rotateY 0

rotateY 90

rotateY 180

rotateY 270

rotateX

rotateX

I will be taking a deeper look in the next article so be sure to sign up to get first access and be in the know about other awesome stuff coming to the interwebs soon.

Thanks for reading!

# data[].attributes.body.processed
In this article, I will be explaining how to make a 3D cube in CSS.

Before I start I want to note I have used Flexbox to demonstrate this but Flexbox (display: flex;) is not needed¹. Items should be placed absolute in a wrapper div or element with the outer element set to relative.

¹If you want a 3D item to sit in the middle of a larger wrapper element then flexbox can still be handy but as you will see in the second part making the wrapper a set size and then making all the elements/faces of the item relative makes the object more re-usable.

So to make it clear Flexbox is only being used to demonstrate how the transform values work on the separate faces to keep them spaces nicely. I will point out the unneeded property values as we go and provide the complete items code in the second part.

Let's get stuck in.

Setting up the workspace

Normal

rotateY 45

rotateY 135

rotateY 225

rotateY 315

rotateX 90

rotateX -90

The below code will create the above demonstration minus the yellow square and the black normal line.

<div class="wrapper-transform-cube">
  <div class="transform--inner ">rotateY 45</div>
  <div class="transform--inner ">rotateY 135</div>
  <div class="transform--inner ">rotateY 225</div>
  <div class="transform--inner ">rotateY 315</div>
  <div class="transform--inner ">rotateX 90</div>
  <div class="transform--inner ">rotateX -90</div>
</div>

/* 3d Transform/Perspectives
 */
.wrapper-transform-cube {
  display: flex;
  flex-direction: row;
  justify-content: space-around;
  width: 90vw;
  height: 12vw;
  margin: 4em auto;
  border: 1px solid black;
  background-color: rgba(173, 255, 47, 0.48);
  /* Setting up the 3D space */
  perspective: 100cm;
  transform-style: preserve-3d;
}
.wrapper-transform-cube .transform--inner {
  width: 12vw;
  height: 12vw;
  border: 0 solid black;
  background-color: #1cc9fe;
}

So we have the setup done with 7 squares in the wrapper. The wrapper has a 3D perspective set on it and transform-style. For now, I won't go into detail on these properties but for 3D we need them on the wrapper.

perspective: 100cm;
transform-style: preserve-3d;

I have coloured the wrapper and added a centre line so we have some perspective to compare to as we go through steps. These are not included in the code sample above, neither is the 7 square on the left.

I have also added some text to explain the faces, namely the rotation we are going to do. The 7th square on the left is there as a reference so you can see what the transform operations do on the element looking straight on.

Rotate the faces of the cube

There are many ways we can manage the rotation of our squares which will become the faces of the cube. We could rotate the 4 sides on the Y-axis at 0˚, 90˚, 180˚, and 270˚ or any combination of values 90˚ apart. For this demonstration, I am going to use the angles 45˚, 135˚, 225˚, & 315˚. I will mention this again later as to why I used these values but for now, just remember they are at 90˚.

Image

Normal

rotateY 45

rotateY 135

rotateY 225

rotateY 315

rotateX 90

rotateX -90

Below is the CSS needed to rotate the faces and the corresponding background-color. You will see that I have added these transforms to each individual face using a new class. For these to work you need to add the class to each face class attribute value like the following example.

-  <div class="transform--inner">rotateY 45</div>
+  <div class="transform--inner transform__inner--rotateY45 ">rotateY 45</div>

/* Rotate Cube Faces */
.wrapper-transform-cube .transform__inner--rotateY45 {
  background-color: #fe3136;
  transform: rotateY(45deg);
}
.wrapper-transform-cube .transform__inner--rotateY135 {
  background-color: #6bfe79;
  transform: rotateY(135deg);
}
.wrapper-transform-cube .transform__inner--rotateY225 {
  background-color: #1cc9fe;
  transform: rotateY(225deg);
}
.wrapper-transform-cube .transform__inner--rotateY315 {
  background-color: #fcfe79;
  transform: rotateY(315deg);
}
.wrapper-transform-cube .transform__inner--rotateX90 {
  background-color: #f6a822;
  transform: rotateX(90deg) rotateZ(45deg);
}
.wrapper-transform-cube .transform__inner--rotateX180 {
  background-color: #f6a822;
  transform: rotateX(-90deg) rotateZ(45deg);
}

With that, we can now see our cube faces rotate. I also rotated the faces on the right 90˚ and -90˚ on the x-axis for the top and bottom respectively. You can't see the top and bottom now. You can also see how rotating the faces for the sides cuts through the yellow wrapper, this is the transform-style: preserve-3d in effect.

Rotate the outer wrapper

To see the top and bottom we can tilt the wrapper on the x-axis

Image

Using a negative deg value we can see it from above and positive from below. There you go, top and bottom insight.

Normal

rotateY 45

rotateY 135

rotateY 225

rotateY 315

rotateX 90

rotateX -90

/* 3d Transform/Perspectives */
.wrapper-transform-cube {
  display: flex;
  flex-direction: row;
  justify-content: space-around;
  width: 90vw;
  height: 12vw;
  margin: 4em auto;
  border: 1px solid black;
  background-color: rgba(173, 255, 47, 0.48);
  /* Setting up the 3D space */
  perspective: 100cm;
  transform-style: preserve-3d;
+ transform: rotateX(-30deg);
}

Make the Inner Elements Absolute

The next step is to remove the spacing on the element, as I said this spacing was added just to illustrate what is happening in the 3D space. To do this all we need to do is add absolute to the faces. Since we have Flexbox space around they all go to the centre, boom!

Normal

rotateY 45

rotateY 135

rotateY 225

rotateY 315

rotateX 90

rotateX -90

.wrapper-transform-cube .transform--inner {
  width: 12vw;
  height: 12vw;
  border: 0 solid black;
  background-color: #1cc9fe;
+ position: absolute;
}

Look at the top view to explore the thinness of the elements

A quick detour to look at it from the top as it seems we only have 2 faces now.

Note I have only tilted the wrapper to 89˚, this is because at 90˚ we won't see anything due to CSS elements not having any depth, but at the same time, they are 2 sided. This is one of the limitations of CSS in the 3D space, something I won't talk about here but will do in the future. It is something to keep in mind.

.wrapper-transform-cube {
- transform: rotateX(-30deg);
+ transform: rotateX(-89deg);
}

Normal

rotateY 45

rotateY 135

rotateY 225

rotateY 315

rotateX 90

rotateX -90

As stated it seems we only have 2 faces now but that is because the 45 and 225 faces are on top of each other and the 135 and 315 faces are on top of each other. Let's fix it by switching back to our above view and translate the faces.

Translate on the Z-Axis

To translate an item is to move the face along its axis or its plane, let's have a look at the following image to see what that means.

Image

As the image illustrates you can move an element along its axis or plane relative to itself, this is actually crucial to understand. See how the elements at 45 degrees translate on the z-axis actually move out on the same angle?

These are like our faces of the cube, one of these is rotated 135˚ and the other 315˚, the ones rotated at 45˚ and 225˚ are hidden as explained earlier. When you translate these faces on the same z-axis by the same value they move away from each other. The elements remember which side is front and therefore the translate will be in the exact opposite direction for planes at 90˚ to each other, cool aye?

Add translate to the 6 sides of half the width of each face and see what happens?

Normal

rotateY 45

rotateY 135

rotateY 225

rotateY 315

rotateX

rotateX

.wrapper-transform-cube .transform__inner--rotateY45 {
  background-color: #fe3136;
- transform: rotateY(45deg);
+ transform: rotateY(45deg) translateZ(6vw);
}

Top and Bottom

The top and bottom had been left until now but usually, they would be transformed the same as the other faces so to finish up I'll make them absolute and make all the faces have slight transparency added.

rotateY 45

rotateY 135

rotateY 225

rotateY 315

rotateX

rotateX

To wrap up let look at the same cube made with the initial faces rotate at 0˚, 90˚, 180˚, and 270˚.

Rotate Cube faces at 0˚, 90˚, 180˚, and 270˚

rotateY 0

rotateY 90

rotateY 180

rotateY 270

rotateX

rotateX

See why I rotated them at 45˚, 135˚, 225˚, & 315˚ for this demonstration, the way to fix this is to rotate the wrapper by 45˚ and then we get the same. I didn't do it this way so we could use the wrapper looking straight on and not at the angle.

Rotate Cube faces at 0˚, 90˚, 180˚, and 270˚ and wrapper at 45˚

rotateY 0

rotateY 90

rotateY 180

rotateY 270

rotateX

rotateX

I will be taking a deeper look in the next article so be sure to sign up to get first access and be in the know about other awesome stuff coming to the interwebs soon.

Thanks for reading!

# data[].attributes.body.summary
In this article, I will look at making a 3D cube in detail by looking at the 3D space and CSS 3D properties and values needed to make a cube.

# data[].attributes.metatag[].attributes.content
API key authentication in Drupal as easy as installing the Key authentication module. Useful for making calls to exposed APIs from decoupled frontends.

# data[].attributes.metatag[].attributes.content
API key authentication in Drupal as easy as installing the Key authentication module. Useful for making calls to exposed APIs from decoupled frontends.

# data[].attributes.body.value
This module is necessary if you intend to expose an API to post to from a decoupled front-end. The module creates an API key for each user whose role has permission to use. The API key can be used in a request to your Drupal site instead of using the username and password basic authentication.

Info

https://www.drupal.org/project/key_auth

Actively maintained Yes, a small user base of ~1000 at the time of writing.
Requires No extra requirements.
Libraries No library.

Install either using the UI or composer.

Basics

There are some basic configuration settings that can be found where you would expect to find them; in the web services section of the configuration section.

Manage > Configuration > Web services > Key authentication
/admin/config/services/key-auth

Once installed you can configure the module to generate the authentication keys on user creation automatically. However, if you install the module you will need to visit your profile page to generate a key.

Other required settings set by default, you can change them if you like, are:

Key-length: set to 32 by default.

Parameter name: api-key by default.

Detection method: you can use either header or query.

The module page has a good rundown of all the features but I will point out a few things below.

Perms

If you want other user roles other than the administrator role to have key authentication you can give each role Use key authentication permissions.

User

Each user can generate a key, delete a key, and regenerate a key on their profile page if they have permission.

Thought Piece
I am unsure of all the use cases that would require all users to have or need keys but it is good to know the functionality is built in. However a few idea that come to mind are:

1. You build a decoupled secure back-end for writers to post from a mobile app. This would be a likely use case. However, it would unlikely you would need to give reset access and the app would need to have a secure login process so the ability to post was restricted.

2. Maybe a social network where users can post from an app to their profile and can reset the key is necessary to stop abuse. Again allowing users to post to the site using a key that is exposed would open abuse so other measures of checking and authentication would need to be in place.

Overall it is a basic module with a specific use case; it makes it super easy to mask username and passwords with a key to access the site for API calls.

I have written about using the key authentication module in a mini-series about using Vue.js and Drupal. The article series looks at making POST requests from a Vue.js front-end. The series as well as covering what you need to do in Drupal covers Vue.js and JSON:API in a practical use case.

If you are interested in using Drupal be sure to sign up for the newsletter as there will be weekly Drupal tips and tricks dropping in that with other mainly front-end development insights and technology reviews.

Thanks for reading.

# data[].attributes.body.processed
This module is necessary if you intend to expose an API to post to from a decoupled front-end. The module creates an API key for each user whose role has permission to use. The API key can be used in a request to your Drupal site instead of using the username and password basic authentication.

Info

https://www.drupal.org/project/key_auth

Actively maintained Yes, a small user base of ~1000 at the time of writing.
Requires No extra requirements.
Libraries No library.

Install either using the UI or composer.

Basics

There are some basic configuration settings that can be found where you would expect to find them; in the web services section of the configuration section.

Manage > Configuration > Web services > Key authentication
/admin/config/services/key-auth

Once installed you can configure the module to generate the authentication keys on user creation automatically. However, if you install the module you will need to visit your profile page to generate a key.

Other required settings set by default, you can change them if you like, are:

Key-length: set to 32 by default.

Parameter name: api-key by default.

Detection method: you can use either header or query.

The module page has a good rundown of all the features but I will point out a few things below.

Perms

If you want other user roles other than the administrator role to have key authentication you can give each role Use key authentication permissions.

Image

User

Each user can generate a key, delete a key, and regenerate a key on their profile page if they have permission.

Thought Piece
I am unsure of all the use cases that would require all users to have or need keys but it is good to know the functionality is built in. However a few idea that come to mind are:

1. You build a decoupled secure back-end for writers to post from a mobile app. This would be a likely use case. However, it would unlikely you would need to give reset access and the app would need to have a secure login process so the ability to post was restricted.

2. Maybe a social network where users can post from an app to their profile and can reset the key is necessary to stop abuse. Again allowing users to post to the site using a key that is exposed would open abuse so other measures of checking and authentication would need to be in place.

Overall it is a basic module with a specific use case; it makes it super easy to mask username and passwords with a key to access the site for API calls.

I have written about using the key authentication module in a mini-series about using Vue.js and Drupal. The article series looks at making POST requests from a Vue.js front-end. The series as well as covering what you need to do in Drupal covers Vue.js and JSON:API in a practical use case.

If you are interested in using Drupal be sure to sign up for the newsletter as there will be weekly Drupal tips and tricks dropping in that with other mainly front-end development insights and technology reviews.

Thanks for reading.

# data[].attributes.body.summary
API key authentication in Drupal as easy as installing the Key authentication module. Useful for making calls to exposed APIs from decoupled frontends. 

# meta.omitted.detail
Some resources have been omitted because of insufficient authorization.

# meta.omitted.links.item--wT16IOr.meta.detail
The current user is not allowed to GET the selected resource.

# meta.omitted.links.item--b5XUMRp.meta.detail
The current user is not allowed to GET the selected resource.

# meta.omitted.links.item--HmdemKa.meta.detail
The current user is not allowed to GET the selected resource.

# meta.omitted.links.item--Oifnods.meta.detail
The current user is not allowed to GET the selected resource.

# meta.omitted.links.item--mwFLufz.meta.detail
The current user is not allowed to GET the selected resource.

# meta.omitted.links.item--pDey5N0.meta.detail
The current user is not allowed to GET the selected resource.

# meta.omitted.links.item--Kl1aXpk.meta.detail
The current user is not allowed to GET the selected resource.

# meta.omitted.links.item--sEvUWBo.meta.detail
The current user is not allowed to GET the selected resource.

# meta.omitted.links.item--zltPltl.meta.detail
The current user is not allowed to GET the selected resource.

# meta.omitted.links.item--wDhzhIe.meta.detail
The current user is not allowed to GET the selected resource.

# meta.omitted.links.item--CjrqgRI.meta.detail
The current user is not allowed to GET the selected resource.

# meta.omitted.links.item--hsnNaum.meta.detail
The current user is not allowed to GET the selected resource.

# meta.omitted.links.item--XlkbryD.meta.detail
The current user is not allowed to GET the selected resource.

# meta.omitted.links.item--Fypb8cB.meta.detail
The current user is not allowed to GET the selected resource.

# meta.omitted.links.item--qb0ykye.meta.detail
The current user is not allowed to GET the selected resource.

# meta.omitted.links.item--yh0tlJf.meta.detail
The current user is not allowed to GET the selected resource.

# meta.omitted.links.item--6jSkXXC.meta.detail
The current user is not allowed to GET the selected resource.

# meta.omitted.links.item--5ehyNzj.meta.detail
The current user is not allowed to GET the selected resource.

# meta.omitted.links.item--ZVA6NO7.meta.detail
The current user is not allowed to GET the selected resource.

# meta.omitted.links.item--xT0e9s7.meta.detail
The current user is not allowed to GET the selected resource.

# meta.omitted.links.item--ri5lcBR.meta.detail
The current user is not allowed to GET the selected resource.

# meta.omitted.links.item--buZImcI.meta.detail
The current user is not allowed to GET the selected resource.

# meta.omitted.links.item--Uu0iQus.meta.detail
The current user is not allowed to GET the selected resource.

# meta.omitted.links.item--wCqVDZ0.meta.detail
The current user is not allowed to GET the selected resource.

# meta.omitted.links.item--5Vsep9F.meta.detail
The current user is not allowed to GET the selected resource.

# meta.omitted.links.item--cjZqIMD.meta.detail
The current user is not allowed to GET the selected resource.

# meta.omitted.links.item--lEgGKS2.meta.detail
The current user is not allowed to GET the selected resource.

# meta.omitted.links.item--RGbX980.meta.detail
The current user is not allowed to GET the selected resource.

# meta.omitted.links.item--7jCcAXI.meta.detail
The current user is not allowed to GET the selected resource.

# meta.omitted.links.item--OZkB5yZ.meta.detail
The current user is not allowed to GET the selected resource.