<?xml version="1.0" encoding="utf-8"?>
<!-- generator="Stay Regular" -->
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom">

  <channel>
    <title>Stay Regular Feed</title>
    <link>http://stayregular.net/both</link>
    <generator>Stay Regular</generator>
    <lastBuildDate>Mon, 30 Apr 2018 00:00:00 +0000</lastBuildDate>
    <atom:link href="http://stayregular.net" rel="self" type="application/rss+xml" />

        <description>The latest blog posts and projects from Stay Regular</description>
    
        <item>
      <title>Adding Images and Media to your GatsbyJS Blog</title>
      <link>http://stayregular.net/blog/adding-images-and-media-to-your-gatsbyjs-blog</link>
      <guid>blog/adding-images-and-media-to-your-gatsbyjs-blog</guid>
      <pubDate>Mon, 30 Apr 2018 00:00:00 +0000</pubDate>
      <description>
        <![CDATA[
                
        
        
        
        <p>In <a href="http://stayregular.net/blog/deploy-a-static-react-blog-using-gatsbyjs-and-github">our last tutorial</a> we built a <strong>static React-powered blog</strong> using the GatsbyJS framework and static site generator. One of the major features we didn't cover was the handling of images and media we want to include in our Markdown content. In this tutorial, we'll cover how to add a cover image to your blog articles.</p>
<h2>What's the big deal with images?</h2>
<p>The way GatsbyJS works is by compiling our blog's assets into static content. The assets include things like the React components, CSS, and any images we directly include in the components or CSS. So when you run your build, your page component <code>/about.js</code> will become an HTML file in the static folder.</p>
<p>But when it comes to images queried by the GraphQL, Gatsby doesn't automatically copy these assets into our static build. If you try and link to a local file, you'll find it doesn't exist on your development or production server. </p>
<p>There's a whole page of the GatsbyJS docs <a href="https://www.gatsbyjs.org/docs/adding-images-fonts-files/">that talks about the implementation of this feature</a> -- but they seem forgotten, exchanged in favor for <a href="https://www.gatsbyjs.org/packages/gatsby-image/">a few plugins</a> that accomplish the task of copying media assets. The plugins work fantastically, and implement the functionality we need with an approachable API.</p>
<p>Lets get building.</p>
<p><em>If you haven't already, make sure to complete the <a href="http://stayregular.net/blog/deploy-a-static-react-blog-using-gatsbyjs-and-github">first part of this tutorial</a> or <a href="https://github.com/whoisryosuke/gatsby-blog-tutorial">download a starter from Github here</a>.</em></p>
<h2>The plugins</h2>
<p>We'll need to install 4 plugins:</p>
<ul>
<li><a href="https://www.npmjs.com/package/gatsby-plugin-sharp"><strong>gatsby-plugin-sharp</strong></a> - This plugin allows us to use the <a href="https://github.com/lovell/sharp">Sharp image processing library</a> to resize and compress our images.</li>
<li><a href="https://www.gatsbyjs.org/packages/gatsby-transformer-sharp/"><strong>gatsby-transformer-sharp</strong></a> - This plugin allows us to query the images on GraphQL through special <code>ImageSharp</code> nodes.</li>
<li><a href="https://www.npmjs.com/package/gatsby-remark-copy-linked-files"><strong>gatsby-remark-copy-linked-files</strong></a> - This plugin does the magic of grabbing any files we link in our Markdown, like images or even PDFs, and copies them to the <code>./public</code> folder.</li>
<li><a href="https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-remark-images"><strong>gatsby-remark-images</strong></a> - This plugin makes all the images responsive, giving us access to a <code>&lt;Img /&gt;</code> component that automatically scales depending on the user's device size.</li>
</ul>
<p>Let's install them all:</p>
<pre><code class="language-bash">npm i --save gatsby-remark-images gatsby-plugin-sharp gatsby-remark-copy-linked-files gatsby-transformer-sharp</code></pre>
<p>Then add this to your <code>gatsby-config.js</code> file to let Gatsby know we have new plugins (and how to use some of them):</p>
<pre><code class="language-js">{
  plugins: [
    `gatsby-remark-copy-linked-files`,
    `gatsby-transformer-sharp`,
    `gatsby-plugin-sharp`,
    {
      resolve: `gatsby-remark-images`,
      options: {
        maxWidth: 1080,
      },
    },
  ],
}</code></pre>
<p>You can set the <code>maxWidth</code> of your images in the options to the size of your biggest image container.</p>
<h2>Add some images to Markdown</h2>
<p>We'll be adding a <code>cover_image</code> field to our Markdown files to show a big header image above posts, and to use as a thumbnail on archives. We'll add it to the <em>frontmatter</em> of the Markdown file to make it easy.</p>
<p>Open up one of the Markdown files in the <code>src/content/blog/</code> folder and add a <code>cover_image</code> field to the <em>frontmatter</em>:</p>
<pre><code class="language-markdown">---
title: "Using a Framework to Simplify Email Design"
date: "2017-08-10"
section: blog
cover_image: "./foundation-emails-guide@1x.jpg"
tags: design, development
---</code></pre>
<h2>Querying the images</h2>
<p>Let's open up the first page of the site and query up some images there. Head over to <code>src/pages/index.js</code> and scroll to the bottom where the GraphQL query is.</p>
<p>We're going to use the new <code>childImageSharp</code> node in GraphQL to grab responsive versions of the images. You can either scale by a certain size, or by resolution ratio. We'll be scaling by size.</p>
<p>Replace the entire <code>query</code> variable with this one:</p>
<pre><code class="language-js">
export const query = graphql`
  query IndexQuery {
    allMarkdownRemark(sort: {fields: [frontmatter___date], order: DESC}, limit: 3) {
      totalCount
      edges {
        node {
          id
          frontmatter {
            title
            date(formatString: "DD MMMM, YYYY")
            cover_image {
              publicURL
              childImageSharp {
                sizes(maxWidth: 1240 ) {
                  srcSet
                }
              }
            }
            section
          }
          fields {
            slug
          }
          excerpt
        }
      }
    }
  }
`;</code></pre>
<p>Let's break the query down a bit. We call <code>allMarkdownRemark</code>, which accesses all Markdown files on our server. We also <code>sort</code> by the date and order it DESC. Then inside, we ask for fields we want to show on the page. In our case, we want to see things like the title and date, nested inside the frontmatter field.</p>
<blockquote>
<p>If <a href="http://graphql.org/learn">the syntax of GraphQL</a> throws you for a loop, and you don't understand why you have <code>edges</code> and <code>nodes</code>, <strong>don't get stressed.</strong> I was a little confused at the start too since my background is in SQL. </p>
</blockquote>
<p>I'd recommend taking a look at the GraphQLi query builder, usually at <a href="http://localhost:8000/___graphql"><a href="http://localhost:8000/___graphql">http://localhost:8000/___graphql</a></a>, or just add <code>___graphql</code> to the end of your development server. This pulls up a live query builder during development that helps ensure you build a properly formatted query. If you click inside, start a new line, and press any letter on your keyboard -- you'll see a tooltip popup with all the possible options for fields. </p>
<p>This helps immensely when making new queries from scratch, or just trying to seeing what fields are available at certain depths.</p>
<h2>The Responsive <Img /> Component</h2>
<p>Now that we've queried the images, let's actually see them! </p>
<p>Here we'll be using the <code>&lt;Img /&gt;</code> component (not to be confused with <code>&lt;img src...&gt;</code>) from the <code>gatsby-image</code> package. You can read the plugin page for details, but it basically creates a responsive image nested inside a couple divs. If the user loads mobile, it loads a smaller image, and stretches it accordingly to fit the size. It also does stuff like the blurred placeholder loading image (ala Facebook or Medium).</p>
<p>To use the <code>&lt;Img /&gt;</code> component, import the <code>gatsby-image</code> package:</p>
<pre><code class="language-js">import Img from "gatsby-image";</code></pre>
<p>And then add the <code>&lt;Img /&gt;</code> tag anywhere in your code:</p>
<pre><code class="language-js">&lt;Img sizes={featured.frontmatter.cover_image.childImageSharp.sizes} /&gt;</code></pre>
<p>We reach into the frontmatter to grab the cover_image, which now has a <code>ImageSharp</code> node (because we added the plugin above). Though we use <code>childImageSharp</code>, probably because it's not a direct image node, but a image attached to a field. The <code>ImageSharp</code> node provides us with a <code>sizes</code> array containing various images at different viewport sizes. This all gets fed into the <code>&lt;Img /&gt;</code> component, which does the heavy lifting of swapping between the set of images depending on the user's device.</p>
<h2>That's it!</h2>
<p>Once you figure it out and find the right plugins, it's a fairly simple process. And being able to generate queries using the help of the GraphiQL browser, combined with dumping data into the console, makes deciphering the data structure fairly simple.</p>
<p>You can see this code more fleshed out with CSS and whatnot in my personal blog's repo: <a href="https://github.com/whoisryosuke/ryosuke-gatsby-blog/"><a href="https://github.com/whoisryosuke/ryosuke-gatsby-blog/">https://github.com/whoisryosuke/ryosuke-gatsby-blog/</a></a></p>
<h2>Next time: Paginated Archives</h2>
<p>In the next part of <a href="http://stayregular.net/blog/tag:gatsbyjs">this tutorial series</a> we'll be adding a paginated archive for our blog. Each blog post has it's own page, but we need an archive for users -- and SEO spiders, to browse and find our older posts. Keep an eye on the <a href="http://stayregular.net/blog/tag:gatsbyjs">#GatsbyJS</a> tag to see our next post!</p>
<p>If you have any questions or issues: feel free to comment down below, <a href="http://twitter.com/stayregular420">send us a tweet</a>, or <a href="http://stayregular.net/contact">contact us through our site's form</a>.</p>
<p>Stay regular,<br />
Oscar</p>
<hr />
<p><strong>Keep Reading:</strong></p>
<ul>
<li><a href="http://gatsbyjs.org">GatsbyJS</a></li>
<li><a href="http://gatsbyjs.org/docs/">GatsbyJS Docs</a></li>
<li><a href="http://graphql.org/learn/">GraphQL Docs</a></li>
<li><a href="https://www.npmjs.com/package/gatsby-plugin-sharp">gatsby-plugin-sharp</a></li>
<li><a href="https://www.gatsbyjs.org/packages/gatsby-transformer-sharp/">gatsby-transformer-sharp</a></li>
<li><a href="https://www.npmjs.com/package/gatsby-remark-copy-linked-files">gatsby-remark-copy-linked-files</a></li>
<li><a href="https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-remark-images">gatsby-remark-images</a></li>
<li><a href="https://github.com/lovell/sharp">Sharp image processing library</a></li>
</ul>        ]]>    
      </description>
    </item>
        <item>
      <title>How to Deploy a Laravel OAuth2 API on Heroku (for free!)</title>
      <link>http://stayregular.net/blog/deploy-laravel-on-heroku-to-create-oauth2-0-api</link>
      <guid>blog/deploy-laravel-on-heroku-to-create-oauth2-0-api</guid>
      <pubDate>Mon, 23 Apr 2018 00:00:00 +0000</pubDate>
      <description>
        <![CDATA[
                
        
        
        
        <p>Are you developing a quick frontend application and need a <strong>backend API for user authentication?</strong> You could put together a Node/Express API from scratch and deploy it on <a href="http://heroku.com">Heroku</a>, but unless you've got a great boilerplate, you'll be spending <em>valuable time</em> integrating dependencies like <a href="http://www.passportjs.org/">PassportJS</a> for <a href="https://jwt.io/introduction/">JWT authentication</a>. Or maybe you don't know too much server-side JS, and you're more comfortable with PHP. That's where <strong>Laravel</strong> comes in. </p>
<p><strong><a href="http://laravel.com">Laravel</a></strong> is a PHP framework that gives you essential features like JWT user authentication and routing right out of the box <em>(with an official plugin)</em>. And it's surprisingly easy to deploy on Heroku if you know a couple of tips and tricks for proper configuration.</p>
<h2>A (Free) API for User Authentication</h2>
<p>Today we'll be creating a basic Laravel application with user signup/login and JWT authentication API for apps. And it'll be deployed on the free tier of Heroku, a cloud-based hosting service. </p>
<p>You can then use this cloud-hosted API to integrate a user authentication system to a frontend application made in React, Vue, Angular, etc. Although you will need a secondary &quot;gateway&quot; API to connect to this Laravel API, or use a service that offers environment variables (like <a href="http://netlify.com">Netlify</a>), since frontend apps leave API credentials vulnerable.</p>
<p><em>This article presumes you have <a href="https://getcomposer.org/download/">Composer installed globally</a>. You don't have to know the <a href="http://laravel.com/">Laravel framework</a>, but it'll help you understand the structure of the application. And it'd probably help to run through <a href="https://devcenter.heroku.com/articles/getting-started-with-php#introduction">the Heroku guide</a> at least once to get your footing there.</em></p>
<h2>Setup Laravel</h2>
<p>The first step is getting Laravel setup. We'll install it using Composer, create a SQLite database, and then configure the <code>.env</code> file.</p>
<ol>
<li>Install Laravel using Composer:</li>
</ol>
<pre><code class="language-sh">composer create-project --prefer-dist laravel/laravel laravel-api-heroku</code></pre>
<ol start="2">
<li>
<p>Open up the project folder (laravel-api-heroku) and go to the <code>database</code> folder and create a new file called <code>database.sqlite</code>. It should be an empty file -- so just create it, save, and close.</p>
</li>
<li>
<p>Go back to the root of the project and copy the <code>.env.example</code> file and name the new file<code>.env</code>.</p>
</li>
<li>Open up the new <code>.env</code> file. Change the <code>DB_CONNECTION</code> variable to equal <code>sqlite</code>, and delete the other <code>DB_...</code> variables in the section. The section should look like this:</li>
</ol>
<pre><code class="language-env">LOG_CHANNEL=stack

DB_CONNECTION=sqlite

BROADCAST_DRIVER=log
CACHE_DRIVER=file
SESSION_DRIVER=file
SESSION_LIFETIME=120
QUEUE_DRIVER=sync</code></pre>
<p>Now we can start to bootstrap Laravel with some basic features like user registration/authentication.</p>
<h2>Setting up an Authentication API</h2>
<p>Laravel makes it incredibly simple to create a website where users can create an account or login, but it takes the simplicity a step further with the Passport package. Not only do we get user login, registration, password reset, etc all out of the box -- we also get an OAuth2.0 package with Passport that allows you to create a kind of &quot;social login&quot; for your own website (think the Twitter API when you access private user data). </p>
<p>We'll basically be following the same instructions in the Laravel docs, <a href="https://laravel.com/docs/5.6/passport">so check those out if you get lost.</a></p>
<p>Install the authentication package by running:</p>
<pre><code class="language-sh">php artisan make:auth</code></pre>
<p>Now we can get the Passport package installed. </p>
<pre><code class="language-sh">composer require laravel/passport</code></pre>
<p>Then we migrate the new database tables, like the users tables, or API keys.</p>
<pre><code class="language-sh">php artisan migrate</code></pre>
<p>Now we can install Passport using Artisan:</p>
<pre><code class="language-sh">php artisan passport:install</code></pre>
<p>We add a new trait to our User model (<code>app/User.php</code>):</p>
<pre><code class="language-php">&lt;?php

namespace App;

use Laravel\Passport\HasApiTokens;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use HasApiTokens, Notifiable;
}</code></pre>
<p>Then <code>Passport::routes</code> method within the <code>boot</code> method of your  <code>app/Providers/AuthServiceProvider.php</code>:</p>
<pre><code class="language-php">&lt;?php

namespace App\Providers;

use Laravel\Passport\Passport;
use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        'App\Model' =&gt; 'App\Policies\ModelPolicy',
    ];

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this-&gt;registerPolicies();

        Passport::routes();
    }
}</code></pre>
<p>Finally, in <code>config/auth.php</code>, you should set the driver option of the  api authentication guard to passport to authenticate incoming requests with <code>TokenGuard</code>:</p>
<pre><code class="language-php">'guards' =&gt; [
    'web' =&gt; [
        'driver' =&gt; 'session',
        'provider' =&gt; 'users',
    ],

    'api' =&gt; [
        'driver' =&gt; 'passport',
        'provider' =&gt; 'users',
    ],
],</code></pre>
<blockquote>
<p>Protip: If you have a previous Laravel installation and you're changing the configuration, make sure to wipe out the config cache by running <code>php artisan config:cache</code> in the console.</p>
</blockquote>
<p>Now we have a Laravel application pre-built with user authentication and OAuth2.0. You can test out the user auth by running <code>php artisan serve</code> and going to <a href="http://localhost:8000">the local development server</a>.There you should see the default Laravel landing page, and login and register buttons in the top right of the screen.</p>
<h2>Deploying to Heroku</h2>
<p>Heroku is a great host with an excellent free hosting package if you're looking quick and easy deployment for most styles of apps (NodeJS, PHP, Ruby, etc). We'll also be leveraging the free tier of their Postres database hosting, which gives you 10k database records to play with.</p>
<blockquote>
<p>Check out the guide <a href="https://devcenter.heroku.com/articles/getting-started-with-laravel">on Heroku's website for deploying Laravel</a>.</p>
</blockquote>
<p>First we have to let the Heroku server know our app is actually in the <code>public/</code> folder. Let's create a new file in the project root called <code>Procfile</code> and add the following:</p>
<pre><code>web: vendor/bin/heroku-php-apache2 public/</code></pre>
<p>Then create a new Heroku application <a href="https://devcenter.heroku.com/articles/heroku-cli">using the CLI</a>:</p>
<pre><code class="language-sh">heroku create</code></pre>
<p>Now add your application key for the production site:</p>
<pre><code class="language-sh">heroku config:set APP_KEY=$(php artisan --no-ansi key:generate --show)</code></pre>
<p>Commit any changes and push the master branch to the Heroku remote repo:</p>
<pre><code>git push heroku master</code></pre>
<p>Now we can add the database. Add a SQLite database to your Heroku app by going to the <a href="https://elements.heroku.com/addons/heroku-postgresql">Heroku PostgresSQL</a> page and clicking the install button. Then pick your app from the dropdown and click continue. You'll be prompted to pick a pricing plan, I went with the free Hobby plan.</p>
<p>Now you can <a href="https://devcenter.heroku.com/articles/heroku-postgresql#connecting-in-php">connect your application to Heroku's Postgres database</a> by updating your <code>config/database.php</code> file:</p>
<pre><code class="language-php">$DATABASE_URL = parse_url(getenv("DATABASE_URL"));
$DB_CONNECTION = parse_url(getenv("DB_CONNECTION"));

return [

    'default' =&gt; env('DB_CONNECTION', $DB_CONNECTION),
    // …

    'connections' =&gt; [

        // …

        'pgsql' =&gt; [
            'driver' =&gt; 'pgsql',
            'host' =&gt; $DATABASE_URL["host"],
            'port' =&gt; $DATABASE_URL["port"],
            'database' =&gt; ltrim($DATABASE_URL["path"], "/"),
            'username' =&gt; $DATABASE_URL["user"],
            'password' =&gt; $DATABASE_URL["pass"],
            'charset' =&gt; 'utf8',
            'prefix' =&gt; '',
            'schema' =&gt; 'public',
            'sslmode' =&gt; 'require',
        ],

        // …

    ],

    // …

];</code></pre>
<p>We also need to edit the environment variables to let Laravel know to use the <code>pgsql</code> database driver when we use Heroku in production. Head over to your project on Heroku, go to the Settings page, and click Show Config Vars. Make a new entry with they key <code>DB_CONNECTION</code> and <code>pgsql</code> as the value.</p>
<p>Now remove the OAuth keys that were generated locally from the <code>.gitignore</code> file by deleting this line:<code>/storage/*.key</code>. Ideally we'd generate these in production, but I had issues with Heroku generating them, so we just import the local ones instead!</p>
<p>Commit your changes to make the database connection real:</p>
<pre><code class="language-sh">git add .
git commit -m "Added Heroku database configuration"
git push heroku master</code></pre>
<p>Now that your database has been connected, make sure to run your database migrations in production to structure your fresh DB. You'll be running it through the Heroku CLI:</p>
<pre><code class="language-sh">heroku run php artisan migrate</code></pre>
<p>Your Laravel website should be live! You can register new users and login with the credentials you create. </p>
<h2>Connecting to your new API</h2>
<p>If you'd like to make an authenticated request to the API through a certain user, you'll either need to go through the OAuth2.0 verification process, or provide a personal access token (or JWT). Laravel Passport allows you to create a new client with a simple command line script:</p>
<pre><code class="language-sh">heroku run php artisan passport:client --personal</code></pre>
<p>When prompted for an app name, name it anything, and click Enter. You'll be provided a Client ID and Secret which you'll use to access the API remotely.</p>
<p>If you're not familiar with the OAuth2.0 protocol, here's a quick breakdown. OAuth2.0 protects your API by creating a 3-step verification system before offering a secure token to access the Laravel API endpoints secured with middleware authentication. </p>
<ol>
<li>
<p>You first redirect the user to the Laravel API's OAuth Authorize page (<code>http://yourlaravelapp.com/oauth/authorize</code>) and attach your Client ID and a callback URL to the request. </p>
</li>
<li>The user is either presented a login screen - or if they're already logged in - they see an authorization form to allow your frontend app to access their data (similar to Twitter's authorization when you use social login). Then the API then redirects the user back to the callback URL you provided, and it sends over a secret token. </li>
</ol>
<figure class="border"><img src="http://stayregular.net/content/2-blog/20180423-deploy-laravel-on-heroku-to-create-oauth2-0-api/laravel-passport-default-authorization-request.png" alt=""><figcaption>Laravel's default API permission authorization screen</figcaption></figure>
<ol start="3">
<li>You take that secret token and send it back to the API with your Client ID, secret, and callback URL. The API responds back with another secret token, this time a personal access token for the specific user that authorized by logging in. This personal access token is <a href="https://jwt.io/">a <strong>JWT</strong></a> or <strong>JSON Web Token</strong>, which is an industry standard method for authorizing between APIs.</li>
</ol>
<p>Any time we'd like to access any part of the API that requires authentication, like private user data, we send our request to the API with a Authorization Bearer token in the header. That token in the JWT we generated in step 3.</p>
<p>Here's a snippet of this kind of setup in Laravel using <code>session()</code> to store the access token. <em>Remember, this is a separate &quot;gateway&quot; application that obfuscates your API credentials for a frontend app</em>:</p>
<pre><code class="language-php">
Route::get('/', function () {
    $query = http_build_query([
        'client_id' =&gt; '420',
        'redirect_uri' =&gt; 'http://127.0.0.1:8001/callback',
        'response_type' =&gt; 'code',
        'scope' =&gt; 'access-patient-status'
    ]);

    return redirect('http://127.0.0.1/oauth/authorize?'.$query);
});

Route::get('/callback', function (Request $request) {
    $response = (new GuzzleHttp\Client)-&gt;post('http://127.0.0.1/oauth/token', [
        'form_params' =&gt; [
            'grant_type' =&gt; 'authorization_code',
            'client_id' =&gt; '420',
            'client_secret' =&gt; 'EXKWFSwGHrbGdC3M4F5kkzmtCZIXyE3fbA8agtw2',
            'redirect_uri' =&gt; 'http://127.0.0.1:8001/callback',
            'code' =&gt; $request-&gt;code,
        ]
    ]);

    session()-&gt;put('token', json_decode((string) $response-&gt;getBody(), true));

    return redirect('/user');
});

Route::get('/user', function () {
    if ( ! session()-&gt;has('token')) {
        return redirect('/');
    }

    $response = (new GuzzleHttp\Client)-&gt;get('http://127.0.0.1/api/user', [
        'headers' =&gt; [
            'Authorization' =&gt; 'Bearer '.Session::get('token.access_token')
        ]
    ]);

    return json_decode((string) $response-&gt;getBody(), true);
});</code></pre>
<p>You could also accomplish this in a React app using <code>react-router</code> to create the callback route, and a service like Netlify to securely <a href="https://www.netlify.com/docs/continuous-deployment/#build-environment-variables">access API key variables in your build environment.</a> (rather than exposing them directly in your production code).</p>
<h2>Let the hackathons begin</h2>
<p>I hope this inspires you to tackle your projects in a new way. We're living in the transition away from the monolith towards a microservices based architecture, and this type of setup will help you migrate your projects into this new infrastructure. The <a href="http://jamstack.org">JAMstack revolution</a> is upon is, and developers are engineering more frontend applications that utilize these modular, cloud-distributed API solutions. </p>
<p>You can take your app's source code and host it on a CDN for the most efficient distribution. And rather than pound the same server you're using to host the frontend to run requests to the backend to login or register users, we break that service out into a separate API that lives on it's own server. If the authentication API server crashes, it never takes down the website CDN (besides the functionality the API provides). <strong>It's the future!</strong></p>
<blockquote>
<p>Consider leveraging the power of Laravel's <a href="https://laravel.com/docs/5.6/socialite">Socialite package</a> to integrate social login into your API, and allow users to create accounts with social media profiles from Twitter, Facebook, etc.</p>
</blockquote>
<p>Looking for the source code? 💻 ⚙️  Find this completed project source code <a href="https://github.com/whoisryosuke/laravel-api-heroku">on Github here</a>.</p>
<p>Stay regular,<br />
Oscar</p>
<hr />
<p><strong>Keep Reading:</strong></p>
<ul>
<li><a href="https://devcenter.heroku.com/articles/getting-started-with-php#introduction">Heroku - Getting Started</a></li>
<li><a href="https://devcenter.heroku.com/articles/getting-started-with-laravel">Heroku - Deploying Laravel</a></li>
<li><a href="https://elements.heroku.com/addons/heroku-postgresql">Heroku - PostgresSQL DB Hosting</a></li>
<li><a href="https://laravel.com">Laravel framework</a></li>
<li><a href="https://laravel.com/docs/5.6/passport">Laravel - Passport package</a></li>
<li><a href="https://jwt.io/">JSON Web Tokens / JWT</a></li>
<li><a href="https://mikateach.com/setting-up-laravel-5-6-on-heroku/">Mikateach - Setting up Laravel 5.6 on Heroku</a></li>
<li><a href="https://blog.pusher.com/build-rest-api-laravel-api-resources/">Pusher - Build REST API using Laravel</a></li>
</ul>        ]]>    
      </description>
    </item>
        <item>
      <title>Deploy a Static React Blog using GatsbyJS and Github</title>
      <link>http://stayregular.net/blog/deploy-a-static-react-blog-using-gatsbyjs-and-github</link>
      <guid>blog/deploy-a-static-react-blog-using-gatsbyjs-and-github</guid>
      <pubDate>Mon, 16 Apr 2018 00:00:00 +0000</pubDate>
      <description>
        <![CDATA[
                
        
        
        
        <p>We'll be creating a blog using <a href="https://www.gatsbyjs.org">GatsbyJS</a>, a static site generator for <a href="https://reactjs.org/">React</a>. GatsbyJS takes your content, either static files or external data from an API, and generates pages that are hardcoded with the data. Rather than calling the API for your latest blog posts for each request, all your posts are pre-cached into separate HTML files. This allows you to serve your entire website over a CDN. And without any external API calls or even server-side rendering, the website loads lightning fast -- and is offline-friendly.</p>
<p>Today we'll be developing a static blog generated by GatsbyJS, written in Markdown, and we'll deploy on Github Pages to host the blog. </p>
<h2>But first, what is GatsbyJS?</h2>
<p><strong>GatsbyJS</strong> is a generator that allows you to code React apps that get compiled into static assets (HTML + JS). Each <strong>page</strong> is a technically React <strong>component</strong> that gets converted into an HTML and JS file when it's time to build the production site. If you've ever worked with a generator like <a href="https://jekyllrb.com/">Jekyll</a>, which converts code like <em>Liquid</em> and <em>Markdown</em> into HTML, you'll be familiar with this kind of concept.</p>
<p>What makes GatsbyJS special is it's implementation of <strong><a href="https://graphql.org/">GraphQL</a></strong>. All of your content is served through a GraphQL server on the development side. When it comes time to compile the static assets, GatsbyJS queries the GraphQL server for the data and inserts it into your HTML files. </p>
<h2>And what the heck is a JAMstack?</h2>
<p>Static websites are growing in popularity with the <a href="jamstack.org">JAMstack revolution</a>. JAM stands for Javascript, API, and Markup. What it basically means is your site is only comprised of:</p>
<ul>
<li><strong>Javascript</strong> (usually a framework like React)</li>
<li><strong>API</strong> (like an RSS feed, or JSON API endpoint) <em>optional</em> </li>
<li><strong>Markup</strong> (HTML, CSS, any media like images)</li>
</ul>
<p>The goal is to create a website is comprised of only client-side HTML + CSS + JS. No need to install <strong>Node</strong>, <strong>Ruby</strong>, <strong>PHP</strong>, or any other server-side language. This means we could even deploy this directly on a CDN like <strong>S3</strong> on <em>AWS</em> or <a href="http://netlify.com"><strong>Netlify</strong></a>.</p>
<blockquote>
<p>When a website is made this simple, you can deploy it nearly anywhere, since most servers support HTML, CSS, and JS. </p>
</blockquote>
<p>There are plenty of benefits to making your website static, from <strong>lighting fast load times</strong> to <strong>decreased server load</strong>, and Gatsby makes it <em>fairly</em> easy to pump out your own. You can find a great <a href="https://www.gatsbyjs.org/tutorial/"><em>'Getting Started'</em> guide</a> on the official GatsbyJS site, as well as many of the concepts we convey in this tutorial. If you get lost, I'd poke around there and see if it helps paint a clearer picture.</p>
<p>Let's build and deploy a static blog!</p>
<h2>Installing Gatsby</h2>
<h3>Using the CLI</h3>
<p>You can either install Gatsby using their CLI, which is recommended:</p>
<p><code>npm install --global gatsby-cli</code></p>
<p>Then run this command in the folder where you want the project:</p>
<p><code>gatsby new gatsby-blog</code></p>
<h3>Classic Git Way</h3>
<p>Or you can <a href="https://github.com/gatsbyjs/gatsby">clone the repo from Github</a> and run an NPM install:</p>
<p><code>git clone https://github.com/gatsbyjs/gatsby.git gatsby-blog &amp;&amp; cd gatsby-blog &amp;&amp; npm install</code></p>
<p><em>Note if you opt against installing the CLI, you'll have to run NPM scripts instead of <code>gatsby</code> commands when building for development or production.</em></p>
<h2>Spin up the server</h2>
<p>Run the following command to start up your GatsbyJS blog locally:</p>
<p><code>gatsby develop</code></p>
<p>This command runs the build process, compiling the code into static assets, and gives you access to your GatsbyJS site at <a href="http://localhost:8000/"><a href="http://localhost:8000/">http://localhost:8000/</a></a>. And to make development easier, when you update your code while this is running, it'll re-compile -- allowing you to refresh and see changes instantly.</p>
<h2>Creating the content</h2>
<p>Our blog will use Markdown files to contain and display our posts. We'll be using the standard Markdown format with a top header. Make a new file in <code>src/blog/first-blog-post.md</code>:</p>
<pre><code class="language-markdown">---
title: My first blog post
date: "2018-04-20"
---

Do you enjoy Gabe the Dog? He is the immortal lead singer of Bork, a European band that does covers of popular pop songs from the 80s, 90s, and today.

&lt;iframe width="560" height="315" src="https://www.youtube.com/embed/c--etqIJcow?ecver=1" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;
</code></pre>
<p>Now that we have some content, let's display it on the website.</p>
<h2>Grabbing our Markdown files</h2>
<p>GatsbyJS uses components to create pages, so we could literally just create new JS files for each blog post. But that's messy and inefficient. So what do we do instead? Gatsby offers the ability to create <em>source</em> plugins that pull data from certain endpoints, like RSS, Medium, or Github. We're going to make Markdown in the same folder as the Gatsby project, so we'll be using the Filesystem source plugin to grab files locally.</p>
<p>We'll also install a <em>transformer</em> plugin, which takes GraphQL data and processes it. In our particular case, we want to take our data and process the Markdown into HTML. Run the following command to install that plugin:</p>
<p><code>npm install --save gatsby-source-filesystem gatsby-transformer-remark</code></p>
<p>And add the following JSON to your config to enable both plugins. If you look close at the <code>path</code> property of the filesystem plugin, we load our blog articles from the blog folder:</p>
<pre><code class="language-json">plugins: [
    // react-helmet is included by default with gatsby
    `gatsby-plugin-react-helmet`,
    `gatsby-transformer-remark`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `src`,
        path: `${__dirname}/src/blog/`,
      },
    },
  ],</code></pre>
<p>Restart your development server to commit the changes (hit CTRL + C to terminate the server and then run <code>gatsby develop</code> again). Now run this GraphQL query on your local <a href="http://localhost:8000/___graphql">GraphiQL development panel</a>:</p>
<pre><code class="language-graphql">{
 allFile {
  edges {
    node {
      name
      extension
    }
  }
 }
}</code></pre>
<p>Enter the query and hit CMD + Enter. You should see a JSON object on the right side with the blog post we just made.</p>
<h2>Making pages dynamically</h2>
<p>We could easily start querying this data on our pages and displaying our posts. If you paste this into <code>src/pages/index.js</code> you'll see all your files printed out in your console:</p>
<pre><code class="language-javascript">
import React from "react"

export default ({ data }) =&gt; {
  // displays an object of the query data in console
  // simply access what you need using a map function
  // data.allFile.edges.map()
  console.log(data)
  return &lt;div&gt;Hello world&lt;/div&gt;
}

export const query = graphql`
  query MyFilesQuery {
    allFile {
      edges {
        node {
          relativePath
          prettySize
          extension
          birthTime(fromNow: true)
        }
      }
    }
  }
`
</code></pre>
<p>Which makes for a great frontpage with a list of all of our posts, but we end up at the same dilemma as before. If we want separate pages for each blog post, we have to make new components to query each page individually. That's where the GatsbyJS API comes into play.</p>
<p>GatsbyJS is capable of taking a GraphQL query and creating pages for every object based off a template. For every Markdown file we create, when we build our GatsbyJS website, it'll get run through a template to create a page. We end up with HTML files for each page with the Markdown parsed into readable text.</p>
<p>Paste this into your <code>gatsby-node.js</code> file.</p>
<pre><code class="language-javascript">const path = require(`path`);
const { createFilePath } = require(`gatsby-source-filesystem`);

exports.onCreateNode = ({ node, getNode, boundActionCreators }) =&gt; {
    const { createNodeField } = boundActionCreators
    if (node.internal.type === `MarkdownRemark`) {
        const slug = createFilePath({ node, getNode, basePath: `pages` })
        createNodeField({
            node,
            name: `slug`,
            value: slug,
        })
    }
};

exports.createPages = ({ graphql, boundActionCreators }) =&gt; {
    const { createPage } = boundActionCreators
    return new Promise((resolve, reject) =&gt; {
        graphql(`
      {
        allMarkdownRemark {
          edges {
            node {
              fields {
                slug
              }
            }
          }
        }
      }
    `).then(result =&gt; {
                result.data.allMarkdownRemark.edges.forEach(({ node }) =&gt; {
                    createPage({
                        path: node.fields.slug,
                        component: path.resolve(`./src/templates/blog-post.js`),
                        context: {
                            // Data passed to context is available in page queries as GraphQL variables.
                            slug: node.fields.slug,
                        },
                    })
                })
                resolve()
            })
    })
};
</code></pre>
<p>First, we'll create slugs based off our Markdown file names, and add them to the GraphQL query results. Then we'll use the <code>createPages</code> API to make new pages based off a GraphQL query for the Markdown posts. Then we'll use the <code>createPage</code> function to actually generate the page based off the new file path and component that'll act as the template.</p>
<p>When Gatsby runs the build process, it'll run this script as well, which will trigger the creation of pages.</p>
<p>There's not much to explain here since this is just very API specific code. It's simple enough to be self-explanatory, and anything that's unclear is probably opinionated decisions from the API.</p>
<h2>The Blog Template</h2>
<p>Now that our blog posts are ready to get converted into static pages, let's actually create the template we referenced above <code>./src/templates/blog-post.js</code>. Make a new file there and paste this into it:</p>
<pre><code class="language-javascript">import React from "react";

export default ({ data }) =&gt; {
    const post = data.markdownRemark;
    return (
        &lt;div&gt;
            &lt;h1&gt;{post.frontmatter.title}&lt;/h1&gt;
            &lt;div dangerouslySetInnerHTML={{ __html: post.html }} /&gt;
        &lt;/div&gt;
    );
};

export const query = graphql`
  query BlogPostQuery($slug: String!) {
    markdownRemark(fields: { slug: { eq: $slug } }) {
      html
      frontmatter {
        title
      }
    }
  }
`;
</code></pre>
<h2>Show me the posts!</h2>
<p>We've got our blog posts as Markdown ready to get converted, we have the React template, the only thing left is linking to the posts.</p>
<p>Head over to your <code>index.js</code> file and paste the following:</p>
<pre><code class="language-javascript">import React from "react";
import Link from "gatsby-link";

export default ({ data }) =&gt; {
  console.log(data);
  return (
    &lt;div&gt;
      &lt;h1 style={{ display: 'inline-block', borderBottom: '1px solid' }}&gt;
        Amazing Pandas Eating Things
      &lt;/h1&gt;
      &lt;h4&gt;{data.allMarkdownRemark.totalCount} Posts&lt;/h4&gt;
      {data.allMarkdownRemark.edges.map(({ node }) =&gt; (
        &lt;div key={node.id}&gt;
          &lt;Link
            to={node.fields.slug}
            css={{ textDecoration: `none`, color: `inherit` }}
          &gt;
            &lt;h3 style={{ marginBottom: '4px' }}&gt;
              {node.frontmatter.title}{" "}
              &lt;span style={{ color: "#BBB" }}&gt;— {node.frontmatter.date}&lt;/span&gt;
            &lt;/h3&gt;
          &lt;/Link&gt;
            &lt;p&gt;{node.excerpt}&lt;/p&gt;
        &lt;/div&gt;
          ))}
    &lt;/div&gt;
      );
      };

      export const query = graphql`
  query IndexQuery {
        allMarkdownRemark(sort: {fields: [frontmatter___date], order: DESC}) {
        totalCount
      edges {
        node {
      id
          frontmatter {
        title
            date(formatString: "DD MMMM, YYYY")
    }
          fields {
        slug
      }
      excerpt
    }
  }
}
}
`;
</code></pre>
<p>We query using the MarkdownRemark endpoint and grab the titles, slugs, and excerpts of our latest blog posts. Then we loop through the data to show the data, while using the <code>&lt;Link&gt;</code> component to link directly to the blog post (using the slug). </p>
<blockquote>
<p>Dont forget, you can always test out the query in the GraphiQL dev panel to make sure you have the right properties.</p>
</blockquote>
<p>If you restart your dev server at this point, you should see a list of the Markdown files you created. And if you click them, they'll take you to another page with the complete blog post. </p>
<p><strong>Congratulations!</strong> You've built your first static blog. You can stop here and just run <code>gatsby build</code> to make a production-ready version of your blog available in the <code>public</code> folder. Upload that directly to your FTP or web host and you're good to go. </p>
<figure><img src="http://stayregular.net/content/2-blog/20180416-deploy-a-static-react-blog-using-gatsbyjs-and-github/gatsby-first-blog-gabe-the-dog.png" alt=""></figure>
<p><strong>But why stop there?</strong> One of the principles of the JAMstack is using <strong>Git</strong> for version control. This allows you, or any dev on your team, to easily clone the website's repository and create an exact replica of the entire website. It also allows you to quickly push new changes to the server, rather than uploading files individually through an FTP. </p>
<h2>Let's git started</h2>
<p>If you haven't already installed Git on your computer, head over to the official website and download it. Then open up Terminal, <code>cd</code> to your project's root, and run the following command:</p>
<p><code>git init</code></p>
<p>This creates a new Git repository in your folder. Now let's commit all the changes we've made to the new repository:</p>
<p><code>git add -A &amp;&amp; git commit -m "Your Message"</code></p>
<p>This takes all the files in the folder and adds them to the Git repo. When you make changes, you'll be able to track the differences between previous versions before each commit (<code>git diff</code>). The message you leave usually hints at what kind of changes were made to the code. In this case, something like &quot;Initial commit&quot; or &quot;1.0&quot; is appropriate.</p>
<h2>Connect with Github</h2>
<p>Connecting with Github allows you to promote the highest accessibility for developers looking to access the website's source code, and to take advantage of Github's free hosting](<a href="https://pages.github.com/">https://pages.github.com/</a>). You'll sign up for a Github account if you don't already have one, create a public repo, and push (or upload) the project files to Github through Git commands.</p>
<h3>Sign up on Github</h3>
<ol>
<li>Create a new account on <a href="http://github.com">Github</a></li>
<li>Login to your account.</li>
<li>Click the plus sign in the top menu and click &quot;New repository&quot; from the dropdown.</li>
<li>Name your repo anything you'd like, then click the big green &quot;Create repository&quot; button.</li>
</ol>
<h3>Sync up your repo with Github</h3>
<p>To make syncing up to Github a single click we'll install <code>gh-pages</code>. This is a Github Pages package that pushes changes to Github and updates the page. Run the following command to install the package:</p>
<p><code>npm install gh-pages --save-dev</code></p>
<p>You'll also need to modify the <code>package.json</code> with a new script. This script runs the <code>gatsby build</code> process, then runs the <code>gh-pages</code> command to deploy to Github. Add the following line into the scripts section:</p>
<pre><code class="language-json">  {
        scripts: {
            // ...you'll see build, develop, format, etc above this....
            "deploy": "gatsby build --prefix-paths &amp;&amp; gh-pages -d public",
        }
    }
</code></pre>
<p>And since Github Pages hosts the blog in a subdirectory (e.g. <code>yourname.github.io/this-subdirectory/</code>), we have to add a path prefix to the configuration <code>gatsby-config.js</code> to let GatsbyJS know it's not in the root:</p>
<pre><code class="language-json">{
  siteMetadata: {
    title: `Your site Name`,
  },
  pathPrefix: "/your-repo-name",
}</code></pre>
<h3>Deploy!</h3>
<p>Go to your new repo on Github, click the Clone button, and copy the URL (ending in .git). Then run the following command to add a &quot;remote&quot; repo to your local git repo:</p>
<p><code>git remote add origin http://github.com/username/repo-name.git</code></p>
<p>Now we can build the site and push it to Github. Type in the following command, enter in your Github password when prompted, and profit!:</p>
<p><code>npm run deploy</code></p>
<p>The <code>public</code> folder of your blog will be uploaded to the <code>gh-pages</code> branch of your repo. If you click the dropdown labeled <strong>Branch: master</strong> you should see the gh-pages branch.</p>
<h3>Browse your blog</h3>
<p>Head back over to your repository on Github and see if you successfully pushed (or uploaded) your files. If it worked, head over to the project settings page. Here, you'll want to make sure Github Pages is enabled and that it's set to the <code>gh-pages</code> branch.</p>
<p>You should be able to access the blog by going to <a href="http://yourusername.github.io/repo-name/">http://yourusername.github.io/repo-name/</a>.</p>
<h2>Maybe not the Wordpress 5-minute install</h2>
<p>It might not be the most lightning fast blog creation out there, between the time it takes to install <code>npm</code> packages and the time you waste fussing with <code>git</code>. Though you have to admit that in a fairly short time span we were able to create a static blog ecosystem that deploys instantly. It's incredible to see the potential of GatsbyJS, and the different kind of experiences you can create compared to standard CMS platforms like Wordpress or Drupal.</p>
<p>If you've ever been thinking about taking the leap into a progressive web application (PWA), you want to try static, or you've just been interested in migrating off Wordpress -- I hope this guide helped you discover an alternative to the mainstream blogging experience.</p>
<h2>The potential is endless</h2>
<p>This is the first part in a series of articles we'll be writing featuring GatsbyJS. We've just dipped our toe in the water here, there's a wealth of plugins and potential we've yet to explore with this framework. We'll be looking into creating projects that explore or push the limitations of the JAMstack, from a portfolio site using the Behance API, to a static e-commerce store using Stripe, to building a true JAM app on a CDN with automatic and atomic builds.</p>
<p>Keep an eye on the <a href="http://stayregular.net/blog/tag:gatsbyjs">#GatsbyJS</a> tag to see our next post!</p>
<p>Find the <a href="https://whoisryosuke.github.io/gatsby-blog-tutorial/"><strong>example site here</strong></a>, and the <a href="https://github.com/whoisryosuke/gatsby-blog-tutorial"><strong>final example repo here</strong></a>.</p>
<p>Stay regular,<br />
Oscar</p>
<hr />
<p><strong>Keep Reading:</strong></p>
<ul>
<li><a href="http://kbroman.org/github_tutorial/pages/init.html">Git guide - Start a new git repository</a></li>
<li><a href="https://jamstack.org/best-practices/">JAMstack.org</a></li>
<li><a href="https://www.gatsbyjs.org">GatsbyJS</a></li>
<li><a href="https://www.gatsbyjs.org/tutorial/">GatsbyJS Tutorials</a></li>
<li><a href="https://www.gatsbyjs.org/packages/">GatsbyJS Plugins</a></li>
<li><a href="https://www.gatsbyjs.org/docs/how-gatsby-works-with-github-pages/">How GatsbyJS Works with Github Pages</a></li>
<li><a href="https://www.gatsbyjs.org/packages/gatsby-source-filesystem/?=filesy">gatsby-source-filesystem</a></li>
<li><a href="https://www.gatsbyjs.org/packages/gatsby-transformer-remark/?=remark">gatsby-transformer-remark</a></li>
</ul>        ]]>    
      </description>
    </item>
        <item>
      <title>How to make Shopify Template Snippets</title>
      <link>http://stayregular.net/blog/how-to-make-shopify-template-snippets</link>
      <guid>blog/how-to-make-shopify-template-snippets</guid>
      <pubDate>Mon, 09 Apr 2018 00:00:00 +0000</pubDate>
      <description>
        <![CDATA[
                
        
        
        
        <p>Customizable components are key to any modern platform. Users have an expectation to be able to adapt and change their websites using recyclable design components part of their theme's system. Users should be able to edit their sliders or page layouts on the fly, moving and editing things freely as they need, without development experience. </p>
<p>It's something that services like <strong><em>Squarespace</em></strong> and <strong><em>Wix</em></strong> embrace. Even <strong><em>Wordpress</em></strong> is trying to implement a version of it with their <em>Gutenberg</em> editor, and we've had it for years with the <em>WPBakery Page Builder</em> (formerly <em>Visual Composer</em>) plugin.</p>
<blockquote>
<p>Websites are a collection of components, there's no reason we can't abstract control away from the code and in the reach of a click.</p>
</blockquote>
<p><strong>Shopify</strong> offers a version of this with their '<strong>snippets</strong>'. A snippet is a reusable component that can be included in any template file. And on the frontpage of the website, you can use customizable snippets to compose a layout for the main landing page. </p>
<h2>How does it work?</h2>
<p>On the frontpage it's a very similar process to something like <em>Squarespace</em> or <em>Wix</em>. You have <strong><em>'content blocks'</em></strong>, each block is a <strong>snippet</strong>, and you arrange them in whatever order you'd like. If you click on a block, it reveals more options, like inserting text or images. </p>
<div class='images grid'><div class='image col-2'><img src=http://stayregular.net/content/2-blog/20180409-how-to-make-shopify-template-snippets/shopify-admin1.png /><p class='caption'>The widget</p></div><div class='image col-2'><img src=http://stayregular.net/content/2-blog/20180409-how-to-make-shopify-template-snippets/shopify-admin2.png /><p class='caption'>A block inside the widget</p></div></div>
<p>On any other page however, it still requires you to manually insert the include snippets into your Liquid page templates (<code>{% section 'your-snippet-here' %}</code>), and it doesn't offer the same level of customization. You can insert variables, but it's a different API than the block settings, so you'd have to account for that as well.</p>
<figure><img src="http://stayregular.net/content/2-blog/20180409-how-to-make-shopify-template-snippets/shopify-snippet.png" alt=""></figure>
<h2>Making the snippets</h2>
<p>Creating a snippet is a snap. Open up your Shopify theme folder, navigate to the snippets folder, and create a new Liquid file with any HTML you'd like. This is great for components that repeat across the website, like newsletter blocks or sidebar widgets. </p>
<p>Here's an example of a block that contains a text header and a flex grid of boxes with images as background:</p>
<pre><code class="language-html">&lt;div class="page-width"&gt;
  &lt;div class="section-block"&gt;
      &lt;div class="section-block__header section-block__header--padded text-center"&gt;
        &lt;h4 class="h1--mini section-block__title"&gt;Text columns with images&lt;/h4&gt;
      &lt;/div&gt;

    &lt;div class="flex column-flex"&gt;
        &lt;div class="flex__item column-overlay text-center"&gt;
            &lt;noscript&gt;
              &lt;div class="column-flex__image" style="background-image: url(http://images.google.com/imageurl.jpg); background-position: center center;"&gt;&lt;/div&gt;
            &lt;/noscript&gt;
            &lt;div class="column-flex__image lazyload"
              style="background-position: center center; background-image: url('http://images.google.com/imageurl.jpg);"&gt;
            &lt;/div&gt;
          &lt;div class="column-flex__content"&gt;
            &lt;p class="h5"&gt;Image Title&lt;/p&gt;
          &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
</code></pre>
<h2>West Code Customs</h2>
<p>Customizing a snippet is where things get interesting. To make a snippet customizable, you have to add a <strong>schema</strong> to the bottom of the snippet. Copy and paste the following into the bottom of your current snippet:</p>
<pre><code class="language-json">{% schema %}
  {
    "name": "Text columns with images",
    "class": "index-section",
    "max_blocks": 24,
    "settings": [
      {
        "type": "checkbox",
        "id": "title_enable",
        "label": "Show header",
        "default": true
      },
      {
        "type": "text",
        "id": "title",
        "label": "Heading",
        "default": "Text columns with images"
      }
    ],
    "blocks": [
      {
        "type": "text_block",
        "name": "Text",
        "settings": [
          {
            "type": "text",
            "id": "title",
            "label": "Heading",
            "default": "Add a title or tagline"
          },
          {
            "type": "image_picker",
            "id": "image",
            "label": "Image"
          },
          {
            "type": "radio",
            "id": "image_align",
            "label": "Image alignment",
            "options": [
              { "value": "top center", "label": "Top center" },
              { "value": "center center", "label": "Center" },
              { "value": "bottom center", "label": "Bottom center" }
            ],
            "default": "top center"
          }
        ]
      }
    ],
    "presets": [
      {
        "name": "Overlay Columns",
        "category": "Text",
        "blocks": [
          {
            "type": "text_block"
          },
          {
            "type": "text_block"
          },
          {
            "type": "text_block"
          }
        ]
      }
    ]
  }
{% endschema %}</code></pre>
<p>Once you add this to your snippet, if you go to your frontpage and click &quot;Add Section&quot;, you should see the snippet title you defined in the list.</p>
<h2>What does the Schema mean?</h2>
<p>The first chunk of JSON is pretty self explanatory. The <strong>name</strong> is the title you'll see in Shopify's backend. The <strong>max_blocks</strong> limits the number of sub-components you can create (e.g.: a recent article snippet limited to 9 posts).</p>
<p>The <strong>settings array</strong> is where you put your top level configurations for the snippet. In this example, we give the user the type in their own header, and enable or disable the visibility of it.</p>
<p>The <strong>blocks array</strong> defines the extra <em>&quot;sub-blocks&quot;</em> you can create within your content blocks, or snippet. In this example, we create a block where the user can define header text, upload an image, and pick the image alignment. Depending on the <code>max_blocks</code> defined earlier, you can make that many <em>&quot;sub-blocks&quot;</em>.</p>
<p>The <strong>presets array</strong> creates a &quot;default&quot; setup for your snippet. If the widget is 3 column and works best with 3 blocks, you can create 3 sample blocks. When the user creates a new snippet, the 3 sample blocks will be automatically created for them (filled with the defaultvalues you define).</p>
<h2>Adding the variables to your snippet</h2>
<p>You can access top-level snippet configurations using <code>{{ section.settings.title | escape }}</code>, swapping title for the <strong>ID name</strong> of the desired setting. To get to block settings, you loop through the blocks and then access the for loop, like so:</p>
<pre><code class="language-html">{% for block in section.blocks %}
      {{ block.settings.title | escape }}
{% endfor %}</code></pre>
<h2>If block contains variable, do something</h2>
<p>When you combine the parameters you get from customization with Shopify's liquid templating system, you can achieve some fairly dynamic components with a minor tinkering. What happens if the user doesn't define any blocks? Or forgets to upload an image? We can handle all these conditional cases with Liquid's <code>{% if %}</code>.</p>
<p><strong>How do we handle the on/off toggles, like the header?</strong></p>
<p>Make a simple if statement checking for the variable. If it's switched to &quot;on&quot;, the variable will be true, so any code inside will be executed:</p>
<pre><code class="language-html">{% if section.settings.title_enable %}
      {{ section.settings.title | escape }}
{% endif %}</code></pre>
<p><strong>What if an image isn't defined?</strong></p>
<p>You can check for the variable and see if is equal (or in this case, not equal) to <code>blank</code>, a Shopify value that checks if the value is empty.</p>
<pre><code class="language-html">{% if block.settings.image != blank %}
      {{ block.settings.image | img_url: '600x600' }}
{% else %}
      &lt;img src="Placeholder.svg" /&gt;
{% endif %}</code></pre>
<p><strong>What if the user doesn't create blocks?</strong></p>
<p>The blocks variable contains a size attribute that lets you see how many blocks there are. You can check if it's equal to 0 in this case:</p>
<pre><code class="language-html">{% if section.blocks.size == 0 %}
      {% include 'no-blocks' %}
      {% comment %}
            We include a placeholder snippet that contains something like a statement saying "Sorry, no posts found".
      {% endcomment %}
{% endif %}</code></pre>
<p>This also comes in handy if you need to check for grid consistency (e.g.: if blocks == 3, then do 3-column class attributes).</p>
<h2>The final code</h2>
<p>When we string together a couple of simple if statements, and swap the hard-coded data with our Shopify snippet configuration variables, we have a fully customizable block:</p>
<pre><code class="language-html">&lt;div class="page-width"&gt;
  &lt;div class="section-block"&gt;
    {% if section.settings.title_enable %}
      &lt;div class="section-block__header section-block__header--padded text-center"&gt;
        &lt;h4 class="h1--mini section-block__title"&gt;{{ section.settings.title | escape }}&lt;/h4&gt;
      &lt;/div&gt;
    {% endif %}

    &lt;div class="flex column-flex"&gt;
      {% for block in section.blocks %}
        {% if block.settings.image != blank %}
          {% assign img_url = block.settings.image | img_url: '600x600' %}
        {% endif %}
        &lt;div class="flex__item column-overlay text-center" {{ block.shopify_attributes }}&gt;
          {% if block.settings.image != blank %}
            &lt;noscript&gt;
              &lt;div class="column-flex__image" style="background-image: url({{ block.settings.image | img_url: '600x600' }}); background-position: {{ block.settings.image_align }};"&gt;&lt;/div&gt;
            &lt;/noscript&gt;
            &lt;div class="column-flex__image lazyload"
              style="background-position: {{ block.settings.image_align }}; background-image: url('{{ block.settings.image | img_url: '300x300' }});"
              data-bgset="{% include 'bgset', image: block.settings.image %}"
              data-sizes="auto"
              data-parent-fit="cover"&gt;
            &lt;/div&gt;
          {% else %}
            &lt;div class="column-flex__image"&gt;
              &lt;div class="placeholder-background"&gt;
                {{ 'placeholder.svg' | asset_url }}
              &lt;/div&gt;
            &lt;/div&gt;
          {% endif %}
          &lt;div class="column-flex__content"&gt;
            &lt;p class="h5"&gt;{{ block.settings.title | escape }}&lt;/p&gt;
          &lt;/div&gt;
        &lt;/div&gt;
      {% endfor %}
    &lt;/div&gt;

    {% if section.blocks.size == 0 %}
      {% include 'no-blocks' %}
    {% endif %}
  &lt;/div&gt;
&lt;/div&gt;

{% schema %}
  {
    "name": "Text columns with images",
    "class": "index-section",
    "max_blocks": 24,
    "settings": [
      {
        "type": "checkbox",
        "id": "title_enable",
        "label": "Show header",
        "default": true
      },
      {
        "type": "text",
        "id": "title",
        "label": "Heading",
        "default": "Text columns with images"
      }
    ],
    "blocks": [
      {
        "type": "text_block",
        "name": "Text",
        "settings": [
          {
            "type": "text",
            "id": "title",
            "label": "Heading",
            "default": "Add a title or tagline"
          },
          {
            "type": "image_picker",
            "id": "image",
            "label": "Image"
          },
          {
            "type": "radio",
            "id": "image_align",
            "label": "Image alignment",
            "options": [
              { "value": "top center", "label": "Top center" },
              { "value": "center center", "label": "Center" },
              { "value": "bottom center", "label": "Bottom center" }
            ],
            "default": "top center"
          }
        ]
      }
    ],
    "presets": [
      {
        "name": "Overlay Columns",
        "category": "Text",
        "blocks": [
          {
            "type": "text_block"
          },
          {
            "type": "text_block"
          },
          {
            "type": "text_block"
          }
        ]
      }
    ]
  }
{% endschema %}</code></pre>
<p>You should have something that looks like this:</p>
<figure><img src="http://stayregular.net/content/2-blog/20180409-how-to-make-shopify-template-snippets/speakers.png" alt=""></figure>
<h2>Easy as Schema</h2>
<p>I hope this helps you create some flexible components for your Shopify template. These customizable blocks empowers less tech-savvy editors with the ability to contribute on a new level effortlessly. </p>
<p>Is something not working correctly for you? Hit us up on <a href="http://twitter.com/stayregular420">Twitter</a> and ask for help. Or <a href="http://stayregular.net/contact">contact us today</a> if you need professional consultation and development for Shopify.</p>
<p>Stay regular,<br />
Oscar</p>
<hr />
<p>Keep Reading:</p>
<ul>
<li><a href="https://help.shopify.com/themes/liquid/tags/theme-tags#include">Shopify Docs on Snippets</a></li>
</ul>        ]]>    
      </description>
    </item>
        <item>
      <title>How to use the Bulma CSS Framework (with SASS)</title>
      <link>http://stayregular.net/blog/how-to-use-the-bulma-css-framework-with-sass</link>
      <guid>blog/how-to-use-the-bulma-css-framework-with-sass</guid>
      <pubDate>Fri, 16 Mar 2018 00:00:00 +0000</pubDate>
      <description>
        <![CDATA[
                
        
        
        
        <p>Bulma is described by it's site as a free and open source CSS framework based on Flexbox. Compared to packages like Bootstrap, it's <a href="https://codeburst.io/evaluating-css-frameworks-bulma-vs-foundation-vs-milligram-vs-pure-vs-semantic-vs-uikit-503883bd25a3#b3ae">more lightweight at 73kb</a> than other CSS systems like Bootstrap or Semantic. And it looks good, I like the aesthetic of the page and the <em>graphic</em> nature of it compared to a lot of other more reserved, almost <em>corporate</em> frameworks.</p>
<p>It's a simple as importing a single CSS if you're interested in using the default library. But if you want to easily change colors, typography, or any other settings across all the components -- it's much easier to use the SASS version. It was pretty easy, but it wasn't as well documented as I preferred, so I wrote this to help others through the process.</p>
<h2>Install Bulma-Start</h2>
<p>The kind folks at <strong>Bulma</strong> have put together a package to help developers compile <strong>SASS</strong> without any additional configuration to their existing project. Rather than installing <code>node-sass</code> yourself and setting up the <code>package.json</code>, you install the bulma-start package.</p>
<p>Run the following command in your project root:</p>
<p><code>npm install bulma-start</code></p>
<h2>How to use Bulma-Start</h2>
<p>The Github repo's readme wasn't very detailed on how to actually use the package. Luckily, <a href="https://github.com/jgthms/bulma-start/issues/1">someone had this issue already</a>, so the question's been roughly answered there.</p>
<p>In order to compile the SASS, you have to navigate terminal to the <code>node_modules/bulma-start</code> folder and run <code>npm</code> commands from there.</p>
<ol>
<li><code>cd node_modules/bulma-start/</code></li>
<li><code>npm run css-build</code></li>
</ol>
<h2>But what do I do with the files?</h2>
<p>You could include the CSS directly from the <code>node_modules</code> folder once it's compiled. But I personally put that folder under <code>.gitignore</code>, so it won't be committed to the repo.</p>
<p>I swapped this line in the <code>bulma-start/package.json</code>:</p>
<p><code>"css-build": "node-sass _sass/main.scss ../../assets/css/bulma.css",</code></p>
<p>This compiles the SASS file into a CSS file in your projects assets directory. And when you set NPM to watch, it'll keep updating the CSS file there as well. <em>Much easier.</em></p>
<h2>At the end of the day</h2>
<p>I wasn't a huge fan of Bulma. It's not organized well enough for my tastes. I had to convert it to a dark theme, which required me finding unique SASS variables for each components color (from background to link colors). It allows for greater customization between components, but makes mass-editing styles a nightmare. </p>
<p>They could really take a cue from Semantic UI and how they've designed their framework to be OOCSS. When I want a navbar to be blue, I don't have to dig through the Bulma SASS variables to find <code>$navbar-background-color</code>, I just include the CSS classes: <code>inverted blue</code>.</p>
<p>Stay regular,<br />
Oscar</p>
<hr />
<p><strong>Keep Reading:</strong></p>
<ul>
<li><a href="https://bulma.io/">Bulma</a></li>
<li><a href="https://bulma.io/bulma-start/">Bulma start (SASS Starter Kit)</a></li>
<li><a href="https://bulma.io/documentation/overview/start/">Bulma Docs</a></li>
</ul>        ]]>    
      </description>
    </item>
        <item>
      <title>420GoodyBox Official Photography</title>
      <link>http://stayregular.net/projects/420goodybox-official-photography</link>
      <guid>projects/420goodybox-official-photography</guid>
      <pubDate></pubDate>
      <description>
        <![CDATA[
                
        
        
        
        <p>Product photography documenting every 420GoodyBox subscription box for promotional uses on their website and print materials.</p>        ]]>    
      </description>
    </item>
        <item>
      <title>Hemp Wick</title>
      <link>http://stayregular.net/projects/hemp-wick</link>
      <guid>projects/hemp-wick</guid>
      <pubDate></pubDate>
      <description>
        <![CDATA[
                
        
        
        
        <p>Designed and manufactured by our staff from the ground up to be the highest quality, organic version of the product.</p>        ]]>    
      </description>
    </item>
        <item>
      <title>HempFest Redesign Concept</title>
      <link>http://stayregular.net/projects/hempfest-redesign-concept</link>
      <guid>projects/hempfest-redesign-concept</guid>
      <pubDate></pubDate>
      <description>
        <![CDATA[
                
        
        
        
        <p>Proposed redesign for Hempfest, a yearly hemp centric event in Washington.</p>        ]]>    
      </description>
    </item>
        <item>
      <title>We Have Munchies Medicated Rice Crispies</title>
      <link>http://stayregular.net/projects/we-have-munchies-medicated-rice-crispies</link>
      <guid>projects/we-have-munchies-medicated-rice-crispies</guid>
      <pubDate></pubDate>
      <description>
        <![CDATA[
                
        
        
        
        <p>Our goal was to create a top-down style cooking video featuring clever editing and plenty of typography for WeedPornDaily and We Have Munchies. The process was fairly straight-forward. A script was written following a basic recipe. The kitchen and studio area were prepped with lighting prior to shooting. The first third of the video is shot on the stove, all shots were first framed and then promptly executed in one take. The other portion of the video was recorded on a white box setup. The video was then edited and color corrected/graded. GIFs were created from the final product to further promote the video on social media.</p>
<iframe src=”https://www.youtube.com/embed/kSfMY78Lqls” frameborder=”0″ allowfullscreen></iframe>        ]]>    
      </description>
    </item>
        <item>
      <title>WeedPornDaily Headshop Promotional Ads</title>
      <link>http://stayregular.net/projects/weedporndaily-headshop-promotional-ads-summer-2016</link>
      <guid>projects/weedporndaily-headshop-promotional-ads-summer-2016</guid>
      <pubDate></pubDate>
      <description>
        <![CDATA[
                
        
        
        
        <p>Advertisements created to promote sales and coupons from the WeedPornDaily headshop. Oscar utilized personal videography of cannabis (or in one case, a scene from Independence Day) converted into a GIF format , and then superimposed typography and vector elements over the animation. The GIF was also optimized for Tumblr viewing, at 540 max pixels width and less than 1MB of data.</p>        ]]>    
      </description>
    </item>
    
  </channel>
</rss>