<![CDATA[Jay George]]> – Blog / Software https://jaygeorge.co.uk/blog Thoughts and tutorials about web design. en https://jaygeorge.co.uk <![CDATA[The Web is Shipping in 2022]]> https://jaygeorge.co.uk/blog/the-web-is-shipping-in-2022 https://jaygeorge.co.uk/blog/the-web-is-shipping-in-2022 ]]> For as long as I can remember, the web has improved year on year at a stable but glacial pace. 2022 is different. It's the culmination of process changes and browsers working together more modularly.

2022 is the first year in memory that not only a single major technology ships, but a whole host of powerful technology. The result feels significant.

You see—the web typically moves slower than the 'app' world. But over the last few years, browser vendors—like Chrome, Safari, and Firefox—have been shipping behind experimental 'flags' that have enabled a more modular and faster approach to pushing out new tech.

What does this mean? These new technologies mean more expressive websites, from “scroll-linked” animation to eloquent magazine-like grids and sub-grid layouts.

This new tech is not only exciting for web developers but also for clients and, well… everyone who uses the web. For the rest of the article, I will be running through upcoming technology releases and translating what they mean into plain English.

Hat tips to Bramus Van Damme and Nicole Sullivan (both on the Google Chrome Developer Relations team).

A 26% More Colourful Web

]]>
Think of the modern, vibrant Picadilly Circus curved display vs the washed-out 80s mess of old. This is how good a P3 website feels.
]]> A specification set to release in 2022 called Colour Functions will allow developers to make websites literally 26% more colourful. Access to these colours mostly means we can make websites look much more rich and attractive.

If you're of a certain age and have ever dealt with a web developer, you might remember years ago web developers needed to design in “web-safe” colours.

At that time most consumer computer monitors could only display 256 colours, so if you designed in a broader range, most users wouldn't see the full spectrum of colours.

Colour Functions are kind of the same thing, except this time it's internet browsers holding things back, not monitors.

At the time of writing, most browsers can only access the "sRGB" (standard Red, Green, Blue) colour space, which is limited to a certain amount of colours.

There's a newer standard, known as the P3 (Protocol 3) colour space, where modern monitors and laptops can access a much richer range of colours.

]]>
The inner triangle here shows colours available to the sRGB colour space. The vibrant colours you see outside this are only available to P3 screens.
]]> P3 colours look stunningly rich compared to standard RGB colours. If you're wondering just how good, you can see P3 colours if you open up this demo in Safari (which at the time of writing is the only browser that supports P3).

If you can see all four spectrums (display-p3, lch, and lab), it means you have a P3-capable browser. If you can also notice a difference between the colours, it means you have a modern screen capable of displaying colours in this expanded spectrum.

Once all browsers support P3, web designs will gradually start looking a lot more vibrant and attractive as web developers start implementing P3 colours in designs.

I'm already looking forward to making my neon-infused black/white/blue website look 26% hotter.

Page Transitions

]]>
Page transitions make websites feel more like ‘apps’
]]> I'll be honest; this probably shouldn't be in here since I doubt it will “officially” ship in 2022. However, it is currently available, fully working, in an experimental version of Chrome. I wouldn't include this lightly, but it's just so relatively huge that I couldn't resist.

What are page transitions? Imagine you're on a hotel-booking app, and you click a thumbnail image of a hotel. In the next moment, information will probably slide across from the right, or maybe the hotel thumbnail will enlarge to fill the screen in one smooth motion.

You've just experienced a “page transition”—moving from one state (or page) to another in a smooth transition.

Page transitions are one of the few things that separate websites and 'apps'—apps providing a significantly smoother experience in this case.

We go from one page to the next on the web in “pop” movements without any kind of soft landing.

Transitions, on the other hand, are not only smoother and more visually appealing, but they also show us where we're going. Think of all the animations on your smartphone; when you flick up from the bottom of a screen on an iPhone, iOS shows you what happened in one smooth movement.

For web developers, native page transitions could bring us one step closer to confidently saying to clients, “you probably don't need an app”.

For what it's worth, an older colleague (sorry, Dean) pointed out that we were here decades ago with Internet Explorer 5.5. That obviously didn't last, but I hope this time is different now that we have better browser standards and collaboration between browser vendors.

Scroll-linked Animations

]]>
With scroll-linked animations you can smoothly animate anyting you want based on the user's scroll position
]]> Animating based on a user's scroll position is nothing new on the web.

Just about every client meeting I've had in the last few years can't end until a client smiles knowingly and asks for "parallax" effects.

However, implementing anything scroll-related has always been a bit hamfisted. You'll need to use some sort of script plugin to continually track where the user is on a page. The browser always struggles a little with this kind of stuff. Until now! (or the near-future, at least).

On the horizon is a “native” implementation of scroll-linked animation. “Native” means that the browser has it baked in so that you don't need to load a plugin.

Don't be fooled—this is not just developer convenience. Anything “Native” (baked into the browser) means performance will be significantly better and programming significantly simpler, leading to a much smoother and delightful implementation.

Systems and Components / not Pages

]]>
Historically we've designed websites like _pages_ rather than what they really are: a collection of interlocking and contextual patterns (like Lego). This is about to change with the introduction of Container Queries.
]]> I remember the vast mental shift that Responsive Web Design brought in the 2010s.

If you don't know what I'm talking about, Responsive Web Design was both a mental and technology shift to designing websites that worked on all sorts of different sized devices.

In the simpler days of web development, you'd just design a fixed-width page. With the advent of Responsive Web Design, we could suddenly query the device width. Developers started designing flexible layouts that could adjust to mobile phones, tablets, and various screen sizes.

Intrinsic Web Design

The web will always be an inherently flexible medium. Your website can be literally accessed by thousands of different device types with wildly different capabilities. Someone could access your site on anything from a computer at CERN, to a 2008 Blackberry, to a high-specced 2022 MacBook Pro. Layout and design need to be flexible and adjusted accordingly.

So what follows Responsive Web Design? 4 years ago, Jen Simmons gave a talk called Everything You Know About Web Design Just Changed. This was around the time web developers got access to modern layout models—namely CSS Grid and CSS Flexbox—two incredibly powerful layout technologies that enabled all sorts of wonderful Graphic Design-like layouts.

Fast-forward to 2022, and we're about to get something called Container Queries, which are the crowning jewel we've been waiting for in this era of new layout technology.

Container Queries allow web developers to query the surrounding space of the component. Querying contextual space was never previously possible. Instead, you had to query the area of the whole page. As container queries are released, we can design components that adjust based on context.

Jenn Simmons has suggested a new name to mark this paradigm shift: Intrinsic Design—which indicates that we're designing inherent systems rather than pages.

Web developers have been asking for this sort of expression for years to reflect the truly modular nature of designed components, allowing for more robust designs. Imagine brand guidelines for different components, where you can specify how things will look depending on the space available to them? The Responsive Logos project comes to mind.

Grids and Subgrids

]]>
I hope new layout systems encourage more creative, artistic, and unusual designs
]]> A few years ago, we had (CSS) Grid—a layout technology designed to give developers grid-like control over where designed objects were placed. Think of magazine-style layouts where designers place different arbitrary columns to create unusual artistic designs for feature articles. A few years later, we're on the cusp of “Subgrid”—a way for us to nest interesting design components inside a grid layout while still accessing the external grid references. It's a difficult concept to grasp, but the below image might give you a clearer idea.

]]>
This diagram from a [Smashing Magazine article](https://www.smashingmagazine.com/2018/07/css-grid-2/) by Rachel Andrews gives you an idea of how a subgrid can be nested inside its parent
]]> Previously where developers had needed to program complex layouts, they would do so with some sort of hack that may technically work brittlely, requiring extra code to handle edge cases.

Subgrid means developers can create a much more robust design ecosystem, allowing for more complex designs that stand up to the scrutiny of the ever-growing list of different screen sizes and devices.

Further Reading

I've tried to highlight the most visually understandable browser technology changes in this article, without making it too long. Still, the reality is there are far more technical things on the immediate horizon that only developers—including me!—are excited about.

I've listed more new technologies below to give readers an idea of how much is happening in the web browser space. 2022 is probably the best time there's ever been to be involved in web design and development.

For more technical reading including the below, I'd recommend Bramus Van Damme's blog post on CSS in 2022.

  1. Colour Functions

  2. Viewport Units

  3. :has()

  4. Overscroll Behaviour

  5. Accent Color (for form elements)

  6. Media Query Ranges

  7. Nesting

  8. Scoping

  9. Mixins

  10. Houdini

]]>
Thu, 12 May 2022 00:00:00 +0000
<![CDATA[Making a Podcast Website in Statamic]]> https://jaygeorge.co.uk/blog/making-a-podcast-website-in-statamic https://jaygeorge.co.uk/blog/making-a-podcast-website-in-statamic Making a podcast website is the same as a regular website when you break it down—the big difference is you need to output what's essentially an RSS feed. In this video, we'll build a podcast website in Statamic complete with an Apple podcast feed from scratch.

Most of the video will cover spinning up a site and setting up blueprints. For the written article, here are the things you need to output for the RSS feed, which you'll need to give your podcast host.

1. Output a Link to a Podcast RSS Feed in Your <Head>

Add this to your head.antlers.html:

{{# RSS
=================================================== #}}
<link rel="alternate" type="application/rss+xml" title="Name of your podcast feed" href="{{ current_url }}/rss">

2. Create an RSS Template

Create a new file at resources/views/rss.antlers.html. Here is my specific implementation:

{{ xml_header }}

<rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0">
    <channel>
        <title>{{ brand:name | cdata }}</title>
        <itunes:title>{{ brand:name | cdata }}</itunes:title>
        <link>{{ config:app:url }}</link>
        <language>en-us</language>
        <copyright>{{ brand:authors | cdata }}</copyright>
        <itunes:author>{{ brand:authors | cdata }}</itunes:author>
        <itunes:summary>{{ brand:podcast_description | cdata }}</itunes:summary>
        {{# This should hold a concise, one-sentence description of your podcast. #}}
        <itunes:subtitle>{{ brand:podcast_subtitle | cdata }}</itunes:subtitle>
        <itunes:explicit>yes</itunes:explicit>
        <description>{{ brand:podcast_description | cdata }}</description>
        <itunes:owner>
            <itunes:name>{{ brand:podcast_owner | cdata }}</itunes:name>
            <itunes:email>{{ brand:podcast_email | cdata }}</itunes:email>
        </itunes:owner>
        <itunes:image href="{{ config:app:url }}{{ glide:brand:podcast_artwork square='1400' }}" />
        <itunes:keywords>Games</itunes:keywords>
        {{# https://www.podcastinsights.com/itunes-podcast-categories/ #}}
        <itunes:category text="Leisure">
            <itunes:category text="Video Games" />
        </itunes:category>
        <itunes:category text="News">
            <itunes:category text="Tech News" />
        </itunes:category>
        <itunes:category text="Technology"/>

        {{# PODCAST
        =================================================== #}}
        {{ collection:episodes as='posts' sort='date:desc' }}
            {{ partial:rss-post }}
        {{ /collection:episodes }}
    </channel>
</rss>

In the above we're linking to an item partial, which looks like this:

{{ posts }}
    <item>
        <title>Ep.{{ episode_number | cdata }} {{ title | cdata }}</title>
        <link>{{ config:app:url }}/episodes/{{ episode_number }}-{{ slug }}</link>
        <itunes:author>{{ brand:authors | cdata }}</itunes:author>
        <itunes:explicit>yes</itunes:explicit>
        <itunes:subtitle>{{ content | smartypants | striptags | cdata }}</itunes:subtitle>
        <itunes:summary>{{ content | smartypants | striptags | cdata }}</itunes:summary>
        {{# the Description tag is requested by some hosts e.g. https://podcasters.radiopublic.com/dashboard #}}
        <description>{{ content | smartypants | striptags | cdata }}</description>
        <itunes:image href="{{ config:app:url }}{{ if artwork }}{{ glide:artwork square='1400' }}{{ else }}{{ glide:brand:podcast_artwork square='1400' }}{{ /if }}" />
        <enclosure url="{{ audio }}" length="{{ size }}" type="audio/mpeg" />
        <guid>{{ episode_number }}</guid>
        <pubDate>{{ date format='D, d M Y H:i:s O' }}</pubDate>
        <itunes:duration>{{ duration }}</itunes:duration>
    </item>
{{ /posts }}

3. Create a Route

We need to define a route which removes the layout template and processes. Open routes/web.php and add the following: Route::statamic('/rss', 'rss', ['layout' => '', 'content_type' => 'xml']);

What we're saying here is—When these routes are matched, use our 'rss' Antler's template, skip layout processing (you'll notice we have a blank layout argument), then render the content as 'xml'—which is needed for podcast feeds.

4. Validate Your Podcast Feed

Podcast aggregators are fussy about how they receive content so it's best to be thorough. My favourites are Cast Feed Validator and Podbase

]]>
Mon, 12 Apr 2021 00:00:00 +0000
<![CDATA[Serving Multiple RSS Feeds in Statamic]]> https://jaygeorge.co.uk/blog/serving-multiple-rss-feeds-in-statamic https://jaygeorge.co.uk/blog/serving-multiple-rss-feeds-in-statamic When it comes to RSS, it’s more tempting to subscribe to a feed when it's exactly what you want. For example, what if you want to subscribe to BBC News, but you don't really care for politics? Luckily bigger websites often provide multiple “sub” feeds so you can subscribe to specific topics rather than everything under the sun.

What if you want to offer multiple feeds on your own site? I was stuck with this question—since I write about a variety of things. I write music reviews, film reviews, posts about Statamic, and thought-pieces. I know not everyone cares for my music taste, so I decided to figure out how to offer different RSS feeds using Statamic since this is what my site is currently built on.

The result is my Subscribe page, where I've output all the possible RSS feeds on this site so fellow RSS-lovers can pick and choose. So how did I do this?

1. Conditionally Output an RSS Title in Your <head>

Adding a link to the head means that visitors can just dump the page URL in an RSS reader and it'll fetch the feed automatically. The minimum amount of code you’d need to link to an RSS feed would be like this:

<link rel="alternate" type="application/rss+xml" title="Jay's Blog feed" href="{{ current_url }}/rss">

This would work well for a blog, for example.

But since we want to offer different feed titles depending on the page, we'll need to use an if statement to understand which page we're on.

We can easily set variables in Statamic at the very top of the antlers file.

At the top of my resources/views/blog/index.antlers.html file I've added:

---
rss: blog
---

Subsequently at the top of my resources/views/listening/index.antlers.html file I have:

---
rss: listening
---

And at the top of my resources/views/watched/index.antlers.html file I have:

---
rss: watched
---

We now want an if statement in our head to detect the page and conditionally serve the relevant feed link. In my case I've broadly split RSS feeds into my Blog, Listening, and Watched. You could probably make this code a little leaner by simply outputting the title dynamically, but I wanted a little more control over the title so this is the way I did it.

{{ if view:rss == "blog" }}
    <link rel="alternate" type="application/rss+xml" title="Jay's Blog" href="{{ current_url }}/rss">
{{ elseif view:rss == "listening" }}
    <link rel="alternate" type="application/rss+xml" title="Jay George &ndash; Intrigue / Listening" href="{{ current_url }}/rss">
{{ elseif view:rss == "watched" }}
    <link rel="alternate" type="application/rss+xml" title="Jay George &ndash; Intrigue / Watched" href="{{ current_url }}/rss">
{{ /if }}

2. Create a Dynamic RSS Template

Create a new file called resources/views/rss.antlers.htmlThis is the file we'll use to generate a dynamic RSS feed depending on the URL. For reference, here is a simple static RSS feed:

<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">

<channel>
  <title>Your Page</title>
  <link>https://yoursite.com/blog</link>
  <description>Name of your blog</description>
  <item>
    <title>RSS Tutorial</title>
    <link>https://somesite.com/xml/xml_rss.asp</link>
    <description>New RSS tutorial on Some Site</description>
  </item>
  <item>
    <title>XML Tutorial</title>
    <link>https://somesite.com/xml</link>
    <description>New XML tutorial on Some Site</description>
  </item>
</channel>

</rss> 

What we need to do instead is dynamically construct a feed by testing the URL “segments”. This is best understood through looking at a code example. Here is my specific implementation. FYI I've used the standard HTML comments syntax here so they stand out a bit more in the example:

{{ xml_header }}

<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <!-- Construct RSS link by testing segments -->
        <atom:link href="{{ config:app:url }}/{{ segment_1 }}{{ if segment_2 }}/{{ segment_2 }}{{ /if }}{{ if segment_3 }}/{{ segment_3 }}/rss{{ /if }}" rel="self" type="application/rss+xml" />
        <title>{{ brand:name | cdata }} – {{ segment_1 | title }}{{ if segment_3 }} / {{ segment_3 | title }}{{ /if }}</title>
        <link>{{ config:app:url }}/{{ segment_1 }}</link>
        <description>{{ if segment_1 == 'blog' }}Thoughts and tutorials about web design.{{ /if }}</description>
        <language>en</language>
        <generator>{{ config:app:url }}</generator>

        {{# BLOG
        =================================================== #}}
        <!-- Test segments to determine which collections and taxonomies to pull into the feed -->
        {{ if segment_1 == 'blog' }}
            {{ if segment_3 }}
                {{ if segment_2 == 'categories' }}
                    { collection:blog as='posts' limit='10' taxonomy:categories="{segment_3}" }
                        {{ partial:rss-post }}
                    { /collection:blog }
                {{ elseif segment_2 == 'tags' }}
                    {{ collection:blog as='posts' limit='10' taxonomy:tags="{segment_3}" }}
                        {{ partial:rss-post }}
                    {{ /collection:blog }}
                {{ /if }}
            {{ else }}
                {{ collection:blog as='posts' limit='10' }}
                    {{ partial:rss-post }}
                {{ /collection:blog }}
            {{ /if }}
        {{ /if }}

        {{# LISTENING
        =================================================== #}}
        {{ if segment_1 == 'listening' }}
            {{ collection:listening as='posts' sort="date:desc" limit='10' }}
                {{ partial:rss-post-listening }}
            {{ /collection:listening }}
        {{ /if }}

        {{# WATCHED
        =================================================== #}}
        {{ if segment_1 == 'watched' }}
            {{ collection:watched as='posts' sort="date:desc" limit='10' }}
                {{ partial:rss-post-watched }}
            {{ /collection:watched }}
        {{ /if }}
    </channel>
</rss>

In the above we're linking to partials. As an example, here is the partial that's stored in /resources/views/_rss-post.antlers.html:

{{ posts }}
    <item>
        <title>{{ title | cdata }}</title>
        <link>{{ permalink }}</link>
        <guid >{{ permalink }}</guid>
        <description>
            {{ if hero_image }}
                <![CDATA[<img src="{{ config:app:url }}{{ glide:hero_image width="1920" height="1080" }}" width="1920" height="1080" alt="{{ hero_image:alt }}" />]]>
            {{ /if }}
            {{ main_content }}
                {{ if type == 'text' }}
                    {{ text | full_urls | cdata }}
                {{ elseif type == 'super_blockquote' }}
                    <blockquote>
                        {{ quote | full_urls | cdata }}{{ if attribution }}—{{ if attribution_link }}<a href="{{ attribution_link }}">{{ /if }}{{ attribution }}{{ attribution_link ?= '</a>' }}{{ /if }}
                    </blockquote>
                {{ elseif type == 'inline_image' }}
                    {{ caption ?= '<figure>' }}
                        <![CDATA[<img src="{{ glide:image }}" loading="lazy" width="{{ image }}{{ width }}{{ /image }}" height="{{ image }}{{ height }}{{ /image }}" alt="{{ image:alt }}" />{{ if caption }}<figcaption>{{ caption }}</figcaption>{{ /if }}{{ caption ?= '</figure>' }}]]>
                {{ elseif type == 'full-width_image' }}
                    {{ caption ?= '<figure>' }}
                        <![CDATA[<img src="{{ config:app:url }}{{ glide:image width="860" dpr="2" }}" loading="lazy" width="200" height="200" alt="{{ image:alt ?? caption }}" />{{ if caption }}<figcaption>{{ caption }}</figcaption>{{ /if }}{{ caption ?= '</figure>' }}]]>
                {{ /if }}
            {{ /main_content }}
        </description>
        {{ if categories || tags }}
            {{ if categories }}
                <category>
                    {{ categories }}
                        {{ title | cdata }}
                    {{ /categories }}
                </category>
            {{ /if }}
            {{ if tags }}
                <category>
                    {{ tags }}
                        {{ title | cdata }}
                    {{ /tags }}
                </category>
            {{ /if }}
        {{ /if }}
        <pubDate>{{ date format='D, d M Y H:i:s O' }}</pubDate>
    </item>
{{ /posts }}

3. Create a Route

We need to define a route that removes the layout template and processes since we simply want to output the feed as an 'atom' content type, which is the preferred content type for RSS.

You can create routes with Statamic through routes/web.php. This is the code I have in web.php:

// e.g. /blog/rss or /listening/rss
Route::statamic('{route_dir_1}/rss', 'rss', ['layout' => '', 'content_type' => 'atom']);
// e.g. /blog/categories/business or /blog/tags/dropbox
Route::statamic('{route_dir_1}/{route_dir_2}/{route_dir_3}/rss', 'rss', ['layout' => '', 'content_type' => 'atom']);

What we're saying here is—When these routes are matched, use our 'rss' Antler's template, skip layout processing (you'll notice we have a blank layout argument), then render the content as 'atom'—which is needed for RSS.

Some other things to note:

  • We have two routes in my particular example.

  • The order of the routes matters.

  • Put less specific routes first. If the URL matches the first route, the second route will effectively be ignored.

  • You can name the variables whatever you like, I just went with {route_directory_1}, etc. because it made it easy for me to understand

  • We don't need to do it here but you can reference these route variable names in your templates if you like—although in this case, I find it easier to use the built-in Statamic's built-in {segment} tags

Tidying Up

  1. Remember to clear the route cache, else the route won't work. Use the command php artisan route:clear to do this.

    1. Also, remember to run this command on your next deployment to your production server

  2. Validate your RSS Feed using the W3C validator to check everything is OK.

]]>
Sat, 10 Apr 2021 00:00:00 +0000
<![CDATA[Designing in the Browser as Fast as Humanly Possible]]> https://jaygeorge.co.uk/blog/designing-in-the-browser-as-fast-as-possible https://jaygeorge.co.uk/blog/designing-in-the-browser-as-fast-as-possible Following the previous video, we'll go through how to design in the browser using more shortcuts and workflow hacks, including some automation software – Keyboard Maestro.

General Tips for Designing

  1. Pop your DevTools “out”—this is a personal preference of mine. It isn't easy to get a clear view of your design when pushed to the side and surrounded by code. You can change how DevTools are displayed by going in the top right > click the vertical dots > and selecting a different docking icon.

  2. Use the Ruler tool—this can really help when trying to make sure elements line up.

    1. To enable the ruler tool, go to the Elements pane in DevTools, press shift + ? to access preferences > click the show rulers checkbox.

    2. A little trick I've learned is highlighting an element, so the rulers are displayed, then scroll vertically-only; without moving your mouse. DevTools will continue to draw rulers as you scroll to check elements beyond the viewport are lined up.

  3. Maintain your own base CSS file—I personally keep a core.css file, and a non-core.css file. I know I'll use everything in core and quite a lot of things in non-core. This can help kick-start a project, and design in the browser immediately without any set-up.

Keyboard Shortcuts

A good metaphor for thinking about automation and keyboard shortcuts is using a well-known tool like Photoshop of a Word document. If you use these all day, you'll start to get used to some shortcuts. For example, Photoshop has single-key shortcuts for things like Brush tool (b), pen tool (p), Stamp tool (s), Switch colours (x). Word has things like Bold (b), Underline (u).

If you use these tools all day long, it's difficult to do without shortcuts. I feel the same way when designing in the browser—I want as many shortcuts as I can remember to get my ideas out fast.

Here are some convenient keyboard shortcuts that are baked into DevTools:

  1. Incrementing—whenever you're keyboard is focused in a number field you can use the up/down arrows to increment by 1, and then combine with modifiers like shift to increment by 10, or alt to increment by 0.1. This works slightly differently in the Elements panel vs the Sources panel—the Elements panel being slightly superior since there is also the option to increment by 0.1.

    1. Incidentally, you can also use your scroll wheel to go up and down values, again using the modifier keys to change the way the numbers increment.

  2. Previous/Next edit points—Use alt & - and alt & + to get to where you were editing previously, or most recently. I find this one particularly useful when working with larger CSS files (like my core.css!) where I'm editing variables at the top of the file and need to get to where I was.

  3. Switching between inspecting and editing—you can use cmd + 1-9 to jump between different panels (you can also rearrange panels to whatever order you want by dragging them around).

    1. This is not turned on by default. To enable this, go to the Elements pane in DevTools, press shift + ? to access preferences > click the Enable cmd + 1-9 shortcut to switch panels checkbox.

    2. I use these shortcuts to switch between inspect mode (the Elements panel) and authoring CSS (the Sources panel).

Automating With Keyboard Maestro

There are a few different automation tools around. TextExpander is probably the most famous. I really like Keyboard Maestro (macOS only, unfortunately – apparently the closest thing on Windows is AutoHotkey). Keyboard Maestro is similar to TextExpander, but its feature set is much much larger, and it pretty much lets you automate whatever you can dream up.

Keyboard Maestro is incredibly handy when it comes to speeding up the authoring experience in DevTools, and you can get a free trial from their website if you're not sure. I have macros that deal with different aspects of authoring:

  1. Text expansions that speed up typing property/value pairs, for example, I might type ptt to have Keyboard Maestro type out padding-block-start: var(--spacing-somevalue), and place my cursor in the correct position so that DevTools presents me with a list of possible variables.

  2. Utilities such as deleting a line, moving lines up/down, commenting shortcuts, or maybe typing out a media query.

I've attached a sample of my macros below which may help you understand how to speed things up, before tailoring them to your needs.

If you'd like to understand a particular macro included in the attachment, hit me up on Twitter. Also, let me know if you have issues with any macros.

]]>
Tue, 09 Feb 2021 00:00:00 +0000
<![CDATA[Recommended Ploi Settings for Statamic]]> https://jaygeorge.co.uk/blog/recommended-ploi-settings-for-statamic https://jaygeorge.co.uk/blog/recommended-ploi-settings-for-statamic Below is a list of recommended settings for a Statamic + Ploi workflow. Since I use a couple of different CMS's with Ploi, I've split these into different sections.

General Ploi Settings

  • Click your avatar (top right) > Profile

    • Settings > Theme mode > Dark —I'm not usually a big dark-mode fan but I like it here

    • Backup configurations > configure these as needed

    • Security > Enable 2FA here

  • Server > Select your server > PHP

    • Manage Extensions (button)

      • Imagick (checkbox)

    • Enable OPcache (button). If we're using Statamic and have the default php7.4-fpm reload command in our deploy script, then we don't need to worry about the warning here

Editing File Backups

If you've spent some time setting up file backups (as above) you can edit or run them manually—but the settings are in a different place. Go to Sites > Your Site > Manage > File Backups

Notifications

  • Click your avatar (top right) > Profile

    • Integrations

      • Set this up first with whatever service you'd like. Personally I use Google Drive for backups and Telegram for notifications, so I'll include instructions for them below.

    • Notification Channels

      • For Telegram I chose a label of “Telegram” and clicked “Create”

Setting Up Notifications for Sites

Once you've set up this base configuration you'll need to set up notifications on a site basis.

  • Sites > Your Site > Notifications

    • Select your Telegram setup here from the dropdown

Setting Up Server Notifications

  • Servers > Your Server > Monitoring > add a notification for anything over 80%. There's no basis for this number, but it felt like a good point at which I'd like to take action.

    • While you're here, click the channel notification to also send an alert through Telegram if this happens

  • Server > Manage > Automatic update notifications > choose a service to be notified on e.g. Telegram. I tend to set up automatic server updates on a weekly basis here.

Password Protect a Site

I thought it was worth mentioning how to do this since it's a brilliant feature that's not easily discoverable. Password protection is desiable if you're working on a site that is under NDA or if maybe contains confidential information while under development.

To password protect a site go to Sites > Your Site > Manage > Authentication (button)

]]>
Tue, 26 Jan 2021 00:00:00 +0000
<![CDATA[Pulling Changes from a Statamic “Solo” Site]]> https://jaygeorge.co.uk/blog/pulling-changes-from-a-statamic-production-site-on-ploi https://jaygeorge.co.uk/blog/pulling-changes-from-a-statamic-production-site-on-ploi In this post, we'll go through how to pull down Git changes with a Statamic site. I'll specifically cover Ploi, but the steps will be similar on other platforms. This assumes that you have established an SSH connection to your server—if you haven't got this sorted, check out my earlier video, Setting Up SSH and SFTP Access With Ploi.

There are a few ways to use Statamic—workflow and licence-wise. This video may be useful if you're checking out Statamic with a solo licence and need to pull down some changes from your production environment, or you may just want to make sure your server can push to your repo via SSH if you're setting up Statamic Pro Git integration.

Make Sure You Have Your Repository Linked to Ploi Via SSH

One “Gotcha” with Ploi is if you link to a repository using the built-in “wizard” it will link to your repository using the OAuth protocol. Oath defaults to HTTPS, which means we won't be using SSH to push changes. This causes issues when trying to push back to the repository.

To solve this, when you link a site to a repository in Ploi, instead of selecting your provider, choose “Custom”. At this point, you need to ensure that you add your Ploi sever's SSH key to your account with your provider. Ploi will show you the SSH key to add when you select “Custom”. Copy the key, and (in Bitbucket, for example) go to your Personal Settings > SSH Keys > Add Key – paste in the copied SSH key and call it something like “Ploi - Name of your server”.

Go back into your repository in Bitbucket and click the “Clone” button in the top right. This will reveal the address of your Bitbucket repository. It will look something like this:

git@bitbucket.org:jaygeorge/jaygeorge.co.uk-statamic.git

Paste this into the Repository field in Ploi, select “Install composer dependencies” as usual and then click “Install Repository”. A huge thank you to Stephen Meehan for helping me out with this gotcha.

Check The Git Status On Your Server and Commit Changes to Git

  1. SSH into your machine, using a command like ssh ploi@yourserveripaddresshere

  2. Make sure you're in the correct directory—with Ploi that'll probably be a command like: cd yourdomainname.com

  3. git remote -v this should now show you two SSH-style addresses—one for fetch and one for pull.

  4. git status to see if there are any changes to the production site that you can push up to Git.

  5. Go ahead and add your changes to production e.g.

    1. git add .

    2. git commit -m "Content changes"

    3. git push

You should now be able to pull your changes down to your site locally using the git pull command.

]]>
Fri, 15 Jan 2021 00:00:00 +0000
<![CDATA[Downloading and Installing an Existing Statamic Site]]> https://jaygeorge.co.uk/blog/downloading-and-installing-an-existing-statamic-site https://jaygeorge.co.uk/blog/downloading-and-installing-an-existing-statamic-site In this post, I'll walk through downloading and running an existing Statamic repository. This is a handy reference if you've got a new machine, have a fresh install of macOS, or maybe you've inherited a Statamic repository.

Once you've cloned the site into your Sites folder, it's handy to ensure that your project folder has the same name as the domain so valet can run it easily, e.g. for my site—https://jaygeorge.wip—my project folder is called jaygeorge

If you're running valet park on your Sites you should be able to boot up http://yoursitename.wip (or maybe http://yoursitename.test if you haven't changed the default TLD). You can go a step further and run your domain on HTTPS by typing valet secure yoursitename

Installing the Site with Composer

Composer needs to do its thing and install the site. Run the following commands:

  1. composer update

  2. composer install

At this point, you need to ensure you have an environment file since these are not committed to git by default, since every machine will have a slightly different environment. I find the easiest way to add an environment file is like this:

  1. Make sure you have hidden files revealed on macOS. You can do this by using the keyboard shortcut cmd + shift + . in Finder to toggle hidden files.

  2. Duplicate .env.example using cmd + d

  3. Rename the newly duplicated file as just .env

Now you can run the following commands:

php artisan key:generate
php artisan optimize
php please cache:clear
php please stache:refresh
]]>
Wed, 13 Jan 2021 00:00:00 +0000
<![CDATA[Setting up Statamic v3 on MacOS – Improving Image Quality with ImageMagick]]> https://jaygeorge.co.uk/blog/setting-up-a-statamic-developer-environment-on-macos-improving-image-quality-with-imagemagick https://jaygeorge.co.uk/blog/setting-up-a-statamic-developer-environment-on-macos-improving-image-quality-with-imagemagick As part of my Statamic series, this post covers installing ImageMagick locally to process images, to get superior image quality on your sites.

You may be wondering “Why would I want to do this?” By default, like most CMS’s, Statamic generates images using software called “GD” (Graphics Draw). For most cases, this will probably be an OK default, but from my experience using ImageMagick as alternative image processing software generates superior images—especially with larger, more noticeable images.

Installing ImageMagick Locally

Even if you're comfortable getting ImageMagick installed on your production server, installing locally will likely be a different process.

  1. Open yoursite/config/statamic/assets.php

  2. Search for driver and change the value to imagick

  3. Make sure you have homebrew installed. To check if you have homebrew installed, you can run brew -v. If Terminal tells you the version number, then you're good to go. Otherwise, download homebrew from https://brew.sh/

  4. Run brew install imagemagick. Check for any errors. At this point in the video, I was prompted to run a command to remove some leftover files.

  5. Run brew install pkg-config

  6. When prompted with Please provide the prefix of Imagemagick installation [autodetect] : just hit enter.

  7. Once complete try running valet restart and refreshing your site. You'll know ImageMagick is successfully installed if 1) it generates Statamic Glide images correctly, and 2) if you go to yoursite/cp/utilities/phpinfo you should a new full section with the headline imagick, with the first row of the section detailing the imagick module version

Fixing Errors

In my experience development environment things seldom “just work”—there's either something you forgot to set or some error you need to deal with. While ImageMagick usually runs smoothly you'll see in the video I ran into an error. The good news is you can usually Google search-engine your way out of an error when it comes to popular software—and luckily ImageMagick is relatively popular.

Before you start searching for fixes it may be worth clearing the cache first with:

php please glide:clear

This didn't help the error I ran into—which in this case was:

warning: mkdir(): File exists in System.php on line 294

I eventually found an article by Patrique Ouimet, which detailed a fix—thank you, Patrique! https://patriqueouimet.ca/tip/installing-php-and-pecl-extensions-on-macos

In this case, you needed to run:

pecl config-get ext_dir | pbcopy

then type:

mkdir -p

followed by pressing cmd + v to paste the value you just copied to your clipboard.

Once this command has been run, and the directory has been created, try running pecl install imagick again and maybe run php please glide:clear to be on the safe side. Finally valet restart and go back to your Utilities > PHP Info in your control panel. If everything's worked out, you should now see an Imagick section here.

]]>
Tue, 12 Jan 2021 00:00:00 +0000
<![CDATA[Setting up Statamic v3 on MacOS Part 4 of 4 (Aside) Working with Git]]> https://jaygeorge.co.uk/blog/setting-up-a-statamic-developer-environment-on-macos-part-4-aside-working-with-git https://jaygeorge.co.uk/blog/setting-up-a-statamic-developer-environment-on-macos-part-4-aside-working-with-git In this post, I'll cover how to get your project into Git and get your machine to talk with a Git repository-hosting service such as Bitbucket. Using Git means we can save our project in different states, roll changes back if we make a mistake and also it allows us to push up/pull down changes to the website and its content.

Authorising Your Computer with SSH in Bitbucket

FYI if you've decided to store your files in a Github repository instead, this process will be very similar.

  1. Go ahead and set up a Bitbucket account if you don't already have one.

  2. When you log in to Bitbucket, you should be in the “Repositories” dashboard. From here look in the left-hand corner where you should see your avatar. Click this and then “Personal Settings” then “SSH Keys”.

  3. We now need to generate an SSH key on our machine. Open the Terminal application and paste in ssh-keygen -t ed25519 -C "your_email@example.com", substituting the email address for whatever your Bitbucket email address is.

  4. Once a key pair has been generated, you'll be prompted to enter a file to save the key. Press enter to accept the default location.

  5. You'll now be prompted to generate a passphrase. This is basically a password. Please make a note of whatever you type in because you'll need it later. Terminal should now inform you that a fingerprint has been generated.

  6. Back in Bitbucket press the add key button

  7. Give the key a label; for example, the name of the machine you've used to generate the key. In my case, I called it MacBook 2018

  8. At the time of writing Bitbucket prompts you to copy the key from your machine using a command that references an older encryption method (RSA). Since we've generated a key using a newer encryption standard, an RSA copy command won't work. To be sure you get the key, you can copy it directly from the file. Go to your home directory and make sure hidden files are showing in Finder—you can toggle these on/off using the keyboard shortcut cmd + shift + .

  9. You should see a .ssh directory. Inside the folder look for id_ed25519.pub. Open this in a text editor and copy the contents of this file. Paste this into the key field in Bitbucket, then press Add key.

Create a New Repository in BitBucket

In the repository dashboard in Bitbucket create a new repository. You can call the Repository whatever you like, but usually, you'll call it the name of your site. I find it useful to specify the site's technology, for example for my own site I've called it “jaygeorge-statamic”. This means if I ever switch to a different CMS in future (which I have done in the past!) I can store that as a separate repository, e.g. “jaygeorge-perch”.

I find it easier to select “no” when it asks me if I'd like to create other files—I prefer to create the repo locally and manually add these things. This is just personal preference though—you may find it easier to let Bitbucket do this for you.

Creating a Project in Git

It's now possible to clone down the repository using the Sourcetree app. This may be the simplest way to do things, but here I'll cover creating the repository locally from scratch and linking it to Bitbucket.

  1. If you don't already have a project in your Sites folder go ahead and make one, e.g. create a subfolder in Sites called test

  2. We now need to make sure we're in that project folder in Terminal. In Finder press cmd + c on the project folder to “copy” it. Back in Terminal type cd (with a space afterwards) and then press cmd + v to paste the directory path we've just copied. Hit enter

  3. The Terminal window's top bar should now show the name of the project folder we're in.

  4. Now we're going to create a Git project. To do this run git init and hit enter. Now run git add . – this command will add all your files to the repository. Now run git commit -m "Initial commit" – this command “commits” the files you've just added. The -m stands for “message”.

Adding Bitbucket as a Remote Repository

We've got our repository set up locally, and now we want to synchronise it with a host (in our case Bitbucket). Eventually, we will set up our production server to “pull” our code from Bitbucket—but that's for another day!

  1. Once you've created a repository back on the Bitbucket site, it should give you a few different sample commands. We can skip a few of these since we've already created a git repository, added files, and committed. We need to add the Bitbucket repository we've created as a “remote” now. You should see the command we need to run on the Bitbucket site, in my example it was git remote add origin git@bitbucket.org:jaygeorge/test.git.

  2. push up your commits to the master branch with git push -u origin master. If Terminal tells you the authenticity of the host can't be established say yes to continue. At this point, you'll be prompted to enter your passphrase that we made up earlier. Do so and hit enter (it'll be invisible so don't worry if you don't see anything while you're typing)

Once you've “pushed up” the code, at this point if you go back to Bitbucket and refresh the page you should see your commit along with its message. PS If you try to push to the repository again and get a permission denied public key message, try restarting your computer and trying again.

]]>
Mon, 11 Jan 2021 00:00:00 +0000
<![CDATA[Setting up Statamic v3 on MacOS Part 4 of 4 – Publishing a Statamic Site]]> https://jaygeorge.co.uk/blog/setting-up-statamic-v3-on-macos-part-4-of-4-publishing-a-statamic-site https://jaygeorge.co.uk/blog/setting-up-statamic-v3-on-macos-part-4-of-4-publishing-a-statamic-site In this post, part 4, we'll cover deploying a Statamic site. The one thing to bear in mind when you're thinking about which host to use is that Statamic runs on Laravel. There are definitely a few differences with hosting a Laravel site, most notably…

  1. You typically need to run a set of commands after each deploy. These commands may do things like clear the cache, and recompile assets like Tailwind / minified CSS and JS using Webpack.

  2. Laravel needs to be run on a folder named public rather than the wide-standard for hosts, public_html. This can be a change to resolve, especially on shared hosting where it's typically not even possible to rename the public_html folder.

Using a host that supports Laravel environments makes things a lot easier and I strongly recommend you go this route unless you love tinkering with servers and making your life more difficult.

Choosing a Host

N.B. If you decide to sign up to Ploi I would very much appreciate it if you used my referral code https://ploi.io/register?referrer=JjynFt5S8WmoZbiAZO3E

The two most popular “server management” solutions (note: not quite the same as a host—we’ll get to that later)—are:

  • Laravel Forge – built by Taylor Otwell. Taylor is the creator of the Laravel Framework and so this is a solid choice.

  • Ploi – Similar to Forge but more encompassing, with extra bells and whistles which make it easier to connect to repositories, and with a much nicer UI, in my opinion. Ploi also has PHPMyAdmin built-in, so if you have existing sites on other CMS's like WordPress or Perch (which I did), you can migrate them and keep everything in one place.

Whether you choose Forge or Laravel, both of these services have the same purpose – to administrate a host/server more easily. In terms of hosts, the most popular options for Statamic are Digital Ocean and Linode. Digital Ocean seems to be the favourite, and so my final recommendation would be a Statamic setup of using Ploi to manage a Digital Ocean server.

Publishing a Statamic Site using Ploi

Let's start from scratch with a free Ploi trial—we'll go from signing up to a trial to getting a Statamic site live. p.s. if you decide you like Ploi and want to help a man out, please use my referral code: https://ploi.io/register?referrer=JjynFt5S8WmoZbiAZO3E

  1. Sign up to a free trial on ploi.io

  2. Add a Git Provider – In the Dashboard click the “Link Git Provider” button, where you'll be prompted to link to your GitHub, BitBucket, or GitLab accounts. If you're a little unsure on Git, my Working With Git video may help you.

  3. Link to a Server Provider – Select your Server Provider. In my case, I'm using Digital Ocean.

    1. In Digital Ocean go to “API” in the bottom of the left column.

    2. Select “Generate a new Token”, call it something like “Ploi”.

    3. Copy the token using the little “copy” link.

    4. Go back to Ploi and paste the token in the “API Key” field. Label it something like “Digital Ocean” and click “Add Provider”.

  4. Create a Server – In the Dashboard click the “Create Server” button. Select your server provider and then in the “Details” section use the Credentials dropdown to select the account you just created. Fill the in the details here. If you're just starting out the lowest server plan should be fine. You'll want to make sure you select a Server Region that's closest to your main customer base. When you're done click the “Create Server” button. Ploi will now use Digital Ocean's API to create a server for you on their platform. This might take a bit of time – go and get a cuppa tea—you deserve it! it took 20 minutes for the progress bar to reach 100% for me.

At this point you'll be e-mailed server details. Save these somewhere safe (you'll need them!). I would personally then delete the e-mail for security reasons.

Recommended Ploi Settings

  • Click your avatar in the top right > Profile – set up TwoFactor Authentication here.

  • Settings > Theme mode – change this to Dark mode if you're a fan.

  • I'd recommend you use ImageMagick to process images rather than GD, which produces better quality image processing. For more information on that see my post about getting ImageMagick working locally. To enable ImageMagick in Ploi, go to Servers > PHP > Manage Extensions and check Imagick

Creating a Site

  1. In the Ploi dashboard > left hand menu > Servers > select your server – add a domain you'd like to link here e.g. yourdomain.com and click Add Site.

  2. Once the site has been created, click it, and select “Git Install Repository”, choose your provider and select your repository. Make sure you select “Install composer dependencies”, and then click Install Repository.

  3. At this point you'll be prompted to add some recommended script commands, ignore this – I'll give you some recommendations instead. Click “Ignore suggestions”

Once you can see the Deploy script, add these lines below where it says “echo "🚀 Application deployed!"”

npm install
npm run production

php artisan optimize
php please cache:clear
php please stache:refresh

php artisan route:cache
php artisan view:clear

The full deploy script should now look something like this (bear in mind your site directory will be different and your php version might be different).

cd /home/ploi/yourdomain.com
git pull origin master
composer install --no-interaction --prefer-dist --optimize-autoloader
echo "" | sudo -S service php7.4-fpm reload

echo "🚀 Application deployed!"

npm install
npm run production

php artisan optimize
php please cache:clear
php please stache:refresh

php artisan route:cache
php artisan view:clear

When you've finished editing the deploy script click “Save”

Click the “Edit Environment” button in the top right:

  • Change the APP_URL to https://yourdomain.com (rather than plain ol’ http).

  • Change the APP_ENV to production

Then in the top right click “Deploy Now”. Once you've successfully deployed your repository you can remove the npm install line.

Pointing your DNS to Ploi

In your domain registrar's DNS records, you should have the following three lines:

  1. An A record for * with a value of your server’s IP address (which you can find in the top left of Ploi once you're in a server or its sites)

  2. An A record for @ with a value of your server’s IP address

  3. A cname record for www with a value of yourdomain.com

Setting up an SSL Certificate for your Domain with Ploi

Once you've gone into your site in Ploi > left hand menu > SSL – accept the defaults here and click “Add certificate”. At this point Ploi will check with the DNS to connect. if you've correctly pointed your DNS to ploi this should work.

Automatically Deploying

When you push to your installed branch, Ploi will run the deploy script for you.

A final thing to consider is whether you'd like to automatically deploy your site when you push up to Git. You may want to be careful with this if you're handling a big client but otherwise, this is a big productivity boost. Once you've gone into your site in Ploi > left hand menu > Repository – scroll down to the Quick deploy heading and click “Enable Quick Deploy”. Another possible workflow is if you set up a staging site on Ploi and automatically deploy to that.

Quick Deploy Not Showing

I've run into a problem previously where "Quick Deploy" wasn't visible in the "Repository" section. I believe this happens when you initially add the repository using the "Custom" option rather than the built-in BitBucket/GitHub integration.

It's still possible to enable quick deploy though. To get around this, in Ploi > left hand menu > Repository – scroll down to the Repository section, and change "Custom" to "BitBucket" or "GitHub". Make sure the repository name is in the format "username/repo_name", for example "jaygeorge/london-local". The repository URL field should already automatically be in the correct format from when it was previously saved as "Custom", e.g. "git@bitbucket.org/jaygeorge/london-local.git"

Once you've turned Quick Deploy on, if you like you can switch back to "Custom" and Ploi should continue to quick-deploy.

]]>
Sun, 10 Jan 2021 00:00:00 +0000