About the Author:

How Are You Dealing with the Shift to DevSecOps?

March 9th, 2020

DevSecOps gets a lot of industry attention, but inside most companies the reaction – and adoption – is a bit more muted. DevOps, by comparison, is widely accepted in application development. For instance, 85% of respondents in Deloitte’s 2019 future of cyber survey of C-suite executives with security responsibilities said they use DevOps practices.

DevSecOps, however, is hard on its heels. According to data from Research and Markets, the DevSecOps market is expected to grow from $1.5 billion in 2018 to $5.9 billion by 2023 due to “the growing need for highly secure continuous application delivery and the increased focus on security and compliance.”

The DevSecOps approach, a combination of development, security and operations, prioritizes and integrates security into the software application lifecycle as early as the development phase. This represents a significant paradigm shift for the DevOps community.

The Need for Speed Often Predates Change

Traditionally in application development, the development team with its programming expertise made a product while the server and operating systems savvy operations team deployed it. DevSecOps merged the two teams into one so that everyone has to understand both areas in order to survive in today’s rapid software development environment.

Given DevOps popularity, the momentum is there for DevSecOps adoption, but progress has been slow on an enterprise level in part because it requires a fairly significant philosophical shift. Change can be tough. Companies are used to having an engineering team deal with code – DevOps – and a separate security team handle compliance audits and perform security scans, etc. Merging isn’t always as seamless as the DevSecOps model requires because it calls on DevOps technical talent to understand another set of skills: how to run and analyze security scans.

As is often the case with progress, some professionals will find themselves obsolete without careful career planning and additional training. For instance, security professionals who only know how to run scans will find themselves replaced by talent who can act in a more consultative fashion for DevSecOps teams: identifying best practices and vulnerabilities and then providing expert advice on how to prevent or solve those problems.

But there’s another reason DevSecOps adoption has been slower than it otherwise might have been considering the need for it in the marketplace – there is a lack of skilled talent available to take on DevSecOps roles. Companies looking for – and not finding – this kind of talent will have to develop it themselves. They can’t do without, and they can’t afford to wait until market supply catches up with market demand. Companies need agile, rapid software development as well as strong cybersecurity defense capabilities now.

Train to Build the DevSecOps Talent You Need

The only realistic option to handle this talent/skills gap is to train DevOps people how to integrate vulnerability scanning and insights into the application development process. Initially, there may be some grumbles. Some will want to know why the security team can’t simply do what its always done and conduct the necessary compliance tests, audits and scans. Leaders will have to clarify for them that when a company only releases code every few months, the old set up works fine; there is no need to change. That’s no longer the case, however.

Now teams release new code every week or even every day to keep up with increasingly accelerated development cycles. Calling on the security team in these circumstances takes too long, and in many cases, there may not be enough security talent to handle the workload. Training is the most reasonable option to ensure an organization can efficiently handle fast code deployment.

For anyone who initially rebels against DevSecOps training it might also help to relay some of the other benefits that a move from a traditional DevOps approach to DevSecOps brings. In addition to increased operational efficiency and effectiveness, organizations will find:

·     It’s easier to identify system and application vulnerabilities.

·     Teams are stronger and collaborate better.

·     Security teams are more agile.

·     Tech talent will have more time to focus on more strategic, high-value projects.

·     The environment as a whole will enjoy more transparency.

Conclusion

Today’s increasingly agile software development environment requires change if organizations and the technical talent that support them are to succeed. The shift from DevOps to DevSecOps is one of those changes. It leads to greater ROI, more innovation and a dynamic DevSecOps environment that supports high speed, high level new software development – if organizations start now to prepare their talent for what lies ahead and, in many cases, is already in play.

About the Author:

15 Blogs Every Javascript Developer Should Follow in 2020

January 7th, 2020

I’ve been following the most interesting JavaScript blogs quite for a while now (this is a part of my job running https://weekendjs.com/). There are many of them. More than you might think. There are blogs started more than ten years ago, and there are relatively new ones. Some bloggers are JavaScript superstars, and others are regular engineers like you and me. Some blogs are focused on a particular ecosystem (say Angular or React, or Vue), while others are rather general.

The exciting thing is that the number of good blogs with really robust material keeps growing from one year to another. It is a promising trend, which hopefully will continue.

A few words about who makes it into the list: only the bloggers who write relatively often (at least once per month). Those are all personal blogs, not hubs, companies, etc. And of course, the main metric is the quality of the material.

OK, enough words. Please welcome, in no particular order, the top 15 blogs a JavaScript developer should follow in 2018.

2ality

The author of the “Exploring ES6” book, Dr. Axel Rauschmayer is long known for his deep and comprehensive articles. They are always well-structured and tend to cover the topics in every detail. Usually he writes about ES6/7/8 features and how to use it, but recently, for example, he did a series of articles on ReasonML, which is a hot new JS-transpilable language from Facebook.

David Walsh

David Walsh is an engineer who works at Mozilla from Madison, Wisconsin. David writes regularly (several times per month). His posts are about web development in general. Usually, these are small, understandable pieces for a broad audience on JavaScript’s new features, Node, and more.

Reginald Braithwaite

Reginald “raganwald” Braithwaite, is the author of brilliant “JavaScript Allongé,” one of my favorite JavaScript books. If you haven’t read it, go ahead and do it. Seriously, it’s a pure pleasure, I promise. As you might expect, he writes a lot on functional-related topics. His articles are probably not for beginners and instead aimed at a more experienced audience.

Michael Herman

Michael Herman is a developer and public speaker. He writes about a lot of stuff such as Python, Docker, etc. Technically, I could leave him out of this list. But his write-ups on JavaScript and related material are extremely practical and helpful, so I just can’t leave out his brilliant blog.

Addy Osmani

I’m not sure I need to introduce Addy Osmani. He is a Chrome core developer, a web performance evangelist, and a public speaker. You probably use libraries he has written on a daily basis; just check his GitHub. He also wrote the very popular “Learning JavaScript Design Patterns” book. In his blog though, he writes a lot on Progressive Apps and is one of the core contributors to the concept.

Ponyfoo

This one is easily recognizable by the iconic pixelated image of a unicorn. The author writes lots about new ECMAScript features, in particular modules, and is (as you might expect) in the middle of writing a book about modules.

Dave Ceddia

Dave’s first post dates back to 2015. And it was about Angular 2 (yeah, can you believe it? Time runs so fast). In 2017, though, it seems as if he changed his preferred framework and started writing more on React. He’s also an author of a lovely little book called “Pure React” which is aimed at starters.

Todd Motto

Speaking of Angular, it’s surprisingly difficult to find robust material on the topic. It’s understandable, perhaps, since React seems to be a lot more fun to write about. Well, at least we have this guy. Todd writes a lot on connected topics (TypeScript, NGRX), speaks at the conferences and also does courses. He’s easily the best individual Angular blogger out there.

Tyler McGinnis

Tyler McGinnis is the author of many thorough React courses. So, as you might expect, he also writes a lot about React both Web and Native. His blog also contains a lot of video materials, which are a joy to watch.

John Papa

John Papa is a developer advocate, public speaker, and of course, a blogger. He also authored several courses on for Pluralsight. He used to write a lot on Angular, especially Angular 1, but it seems he’s more into Vue now. If you’re interested in this React alternative you should follow this guy.

Valentino G.

This guy writes a lot of different topics, including Django and Node. Most often he writes about React and friends.

Ben Nadel

I didn’t know about this one until recently, but now it’s easily one of my favorite JavaScript blogs. My favorite part is that he writes a lot about UX and its intersections with JavaScript. Highly recommend it!

Bram Van Damme

It’s interesting that lots of bloggers are from Europe. Like Bram, who is an engineer from Belgium. He writes about JavaScript and also more in general about the web and web development.

Ivan Akulov

Ivan writes about React and Webpack, and also in general about different optimizations you’ll need to do as a web developer. His write-ups are highly practical, and may not suit the beginners.

Robin Wieruch

Robin works in Berlin. He writes a lot (and quite often) about React and friends. But also (and that’s what makes him interesting) he writes about stuff like AI and machine learning. There aren’t a lot of places where you can read articles like “A Web Developer’s Guide to Machine Learning in Javascript” or “Neural Networks in Javascript.” If you’re interested in those topics, you definitely need to follow Robin.

I hope you liked this list. Now go ahead and add them to your preferred RSS reader as I did and enjoy the perpetual flow of the best articles from the JavaScript world!

About the Author:

Here Are the Two Things That Developers Value More Than Compensation When Choosing a Job

December 13th, 2019

We have no shortage of sayings about the primacy of money. “Money talks”. “Show me the money”. “Put your money where your mouth is”. But we sometimes overestimate money’s importance relative to many other things. This can be especially true when it comes to working and choosing which job to take.

When it comes to why software developers choose one job over another, many people would assume that comp would be the deal-breaker. Show me the money, right?

So that’s why it might be surprising to discover that perhaps it is not. At least that’s what HackerRank’s 2019 survey of 70,000+ software developers found.

Both professional growth and learning and work-life balance rank as more important (to software developers) than competitive compensation. Why?

Developers tend to be extremely curious and independent. They are constantly learning, self-teaching, and re-tooling. They also want to be able to show up to work when they want and occasionally work remotely.

To attract and keep their software developer talent, companies need to properly recognize L&D as a competitive advantage. Investing in professional growth, learning, and training is more important than just trying to outbid your competitors for talent.

Curious to learn more?

Our 2020 Developer Learning Survey Report is chock full of insights like the one found in this blog. We surveyed 800+ developers and combined our results with developer survey results from organizations like StackOverflow and HackerRank.

You can download the full survey report here.

About the Author:

Which Technologies Do Developers Want to Learn in 2020?

December 11th, 2019

Every company wants to give its developers the right training. One of the easiest (and quite logical) ways to do this to make sure the training is on the right technologies. Nobody wants to miss out on their day-to-day project work to learn about outdated languages or libraries. Worse yet is having to take training on a technology you definitely won’t use or just don’t care about.

But teaching the ‘right’ technologies is no easy task. We all know the technology space continues to evolve at a breakneck pace. What was cool or interesting last year could be dead the next. Here are a few strategies and tools we use to stay up to date on the technology space.

Google Trends

Google Trends is an amazing tool for getting a 30,000-foot view on whether a search term is becoming more/less popular. Be careful! Google Trends can be a massive time-waster for curious people.

Digressing — Google Trends is a great way to see whether a technology area is being searched for more or less than before. That should inform you as to whether to investigate more.

StackOverflow (StackExchange) Open Data

StackOverflow is the absolute go-to source for programming questions. StackExchange (the parent company) makes all of their data openly available and queryable (with a public-facing SQL interface). Fear not if you don’t know SQL. You can use other people’s queries to explore the data.

So how does this relate to technology popularity? Several queries allow you to see whether a specific technology is becoming more or less popular on StackOverflow. This would allow you to answer questions like “Should I perhaps offer Vue.js training to our JavaScript developers?”. Or “Is SQL-server still worth giving training on?”. These StackOverflow queries allow you to gain insights with the freshest data available. This data literally measures what kind of questions people are asking and what tags they are using. For example, this query on tag statistics allows you to see how popular different languages are on StackOverflow.

Tag Statistics

The query below allows you to see how a tag (e.g. python) is trending over time. Are more questions and answers occurring? At what growth rate?

Tag Size and Growth Trends (Python example)

Here’s a list of their most popular queries: https://data.stackexchange.com/stackoverflow/queries?order_by=popular

Github

Github is where most prominent open source projects are hosted and where developers go to collaborate and get help with bugs. Each Github project has an insights tab that tells people how active that project is. At what rate are issues being opened/closed? Well-used and growing open source projects will tend to have very active Github projects (and vice versa for dead or dormant technologies). So, for instance, if you were considering giving Gatsby training to your developers, you could check out the insights tab on Gatsby’s Github project page.

You’d see that this project is under extremely active development. This tends to mean lots of people are using it and trying to adopt it.

Contrast this with Ruby’s Insights and you get more of a story of a steadily developing and mature technology.

How you interpret this data is up for debate. But we recommend considering it as a source.

The 2020 DevelopIntelligence 2020 Developer Learning Survey Report

Curious to learn more about not only which technologies developers want to learn next but also the how and why? We recently released a our 2020 Developer Learning Survey Report, which includes our original survey data combined with survey data from StackOverflow, HackerRank, the State of JS report, and several others. It is designed to help companies design training programs and deliver training courses that developers will love.

About the Author:

How Does the CTO Decide What Technical Training Is Needed?

December 11th, 2019

A CTO, or chief technology officer, evaluates short- and long-term organizational needs, and makes capital investments in technology to help that organization reach its business goals. It’s the highest executive position for technology in a company, and it’s a strategic role. That does not mean, however, that it’s a stagnant one. Learning is very much a part of the picture, especially when it comes to directing training efforts for technical teams.

The CTO will likely work with the CLO, or chief learning officer, or other organizational learning leader to decide what training would be most beneficial. But to choose the right courses or build a curriculum that will produce business impact, the CTO has to do several things.

Maintain a Pulse on the Organization and the Industry at Large

The CTO has to solve technology-related issues and make sure an organization’s software products solve key problems for its intended audience. That requires an evolving knowledge of emerging technology trends and industry changes, and intimate knowledge of what is going on in the business as well as what strengths and weaknesses exist in the organization’s technical team.

Where do they excel? Where is there room for improvement? What new skills will help to optimize current workflows and future proof the organization? Holistically, what will accelerate the team’s growth? After all, it’s the developers and engineers who will execute the organization’s vision, deliver on potential, and achieve the business results that will prove technology’s value – and secure additional funding for more training.

For instance, if it’s a retail organization, machine learning will be critical as ecommerce and online sales channels must be built and optimized to suit rapidly changing customer and product needs. Machine learning has applications for a lot of the things customers encounter in everyday life: online recommendations and offers, linguistic rule creation so that companies will know what customers are saying about them on social media, even fraud detection.Python is one of the best programming languages for machine learning. Does the team have the skills it needs to handle it?

What about big data? It’s important for many companies in a variety of industries, and it’s a critical technical training area given the increased scrutiny on data privacy and security. The CTO must determine where is the current team lacking when it comes to skills around proper data collection, storage and data mining? How are their skills in Apache Spark, R, Java, C and other relevant programming languages? That information will inform how training is built, delivered and received.

A savvy CTO will even ask technical team leaders and members for input. Why not? They’re in the trenches. They know better than anyone what they lack to succeed on the job. VMWare polls it’s engineer population annually to identify what training offerings they want. If those align with the company’s business goals and product offerings, the company will offer that training.

Lead with Data, and Keep an Eye on the Future

Taking a data-driven approach to training can be powerful, but it requires goal setting and establishing key metrics to determine whether or not business goals and objectives have been met, and training engagements are successful. Then, based on established goals, the CTO can iterate what training will produce the expected results.

This requires that a CTO actively monitor the technical team, and solicit feedback in order to identify what skills are lacking. A data-driven training strategy will allow the technical team to prioritize its resources and energy to reach quantifiable goals, and create space to discover innovative ways to get work done efficiently, achieve business success, and sustain a competitive edge.

The CTO knows how to break down the dynamics of a technical problem. He or she will also know from a strategic perspective how best to use technical talent to push the business forward, and ensure the technical team is learning, growing, and building valuable relationships. The right training is a key part of that.

Choose the Right Training Partner

This part of a training strategy is almost as important as the strategy itself. It goes without saying that the right training partner will have the very latest offerings taught by expert practitioners and skilled facilitators. But the right training vendor will also act as a business partner.

Technical training company DevelopIntelligence will not only handle logistical details around scheduling and planning time for training so that technical talent have the mental space to learn, the organization’s guidance can be invaluable when it comes to redistributing the technical team’s work, or simply choosing the optimal time to conduct training in the first place.

The right training partner can also help fill gaps in a CTOs training knowledge in the same way the CLO would to maximize the relationship, and respect everyone’s time and investment. The training partner will insist on a deep understanding of the organization’s training goals and business objectives. They will inquire what are the established measurements by which to determine success for the learning engagement? If need be, the right training partner will even help to create those goals and success measures.

For instance, what should a training cohort know how to do by the end of the class? How should they be applying their new skills on the job? What follow up should be arranged to refresh classroom knowledge, and keep those valuable peer learning conversations going once learners are back in the workplace?

The right training partner will ask a lot of questions, and invite the CTO to share their concerns about the business and about the training they hope to receive. Why? At the end of the day, the training vendor has to provide value.

The CTO will demand it because the best training is rarely done simply for its own sake. It’s done to fulfill a need, whether it’s a current business need, or one that will be needed to shape an organization’s profitable and productive future.

About the Author:

3 Things Open Source Software Can Teach Learning Leaders

November 20th, 2019

The open source learning movement began with software development – examples include Android and Mozilla Firefox – and the software is open to everyone to use, customize or modify as needed to meet their individual or organizational requirements. It’s also free.

The open source movement, which began in the 1980s, enabled programmers and users to learn about or be trained on software and explore new codes and innovations because the code for open source software is available for anyone to add to, change or just generally improve. It has not only changed the way we develop software today, it has contributed significantly to the rapid advance of technology.

Part of the reason open source has been so influential is because it allows participants to collaborate and fully leverage their experts. Open source has applications outside the technology realm as well. For instance, some of the core ideas associated with open-source technology have made their way into strategic knowledge sharing efforts in an organizational context as learning leaders adopt them for their own use.

You may have heard of open source learning? As transparency, decentralization, and collaboration become the new normal in many organizations, the idea that anyone can and should share their expertise has taken hold. Further, the idea that individuals and teams should be able to tap into and build on each other’s know-how neatly sums up the concept of open-source learning.

Here are three ways open source learning can benefit technical training:

1.     Open source learning promotes diversity of thought. One key facet of open source learning that is ideally suited for technical training is there is no one-size-fits-all strategy or solution. Open source learning is inherently diverse because it embraces the idea that different people learn in different ways. Further, there is the underlying idea that each of those people likely has something valuable to contribute to the software development or the learning experience.

As in the best technical training offerings, a high level of customization is not only necessary, it’s expected. Plus, open source themed training isn’t just customized for learners, it’s customized for each organization’s unique business challenges and technology concerns.

Because anyone could conceivably contribute to open source code, it’s by nature interdisciplinary, and open source learning is as well. Ideally, technical talent in various roles will share the same classroom. That way, each person can bring their perspective to the learning environment. In this way their peers can absorb different goals and concerns from various departments. The overarching goals, however, remain the same. Common business goals provides needed structured so that learners can use each other’s experiences to explore different alternatives to reach that common goal.

2.    Open source learning prioritizes collaboration. With open source learning as the structure, a lab intensive, hands on technical training classroom is the perfect environment for multiple perspectives to come together to share knowledge. Peer-to-peer collaboration encourages learners to think creatively as well as analytically with support from expert facilitators who have deep experience in the work world as well as in specific technologies. Engagement is often high in this type of technical training environment, and it promotes knowledge retention as well as learning application once learners are back in the workplace.

3.     Technical training the open source way promotes innovation. Innovation is the lifeblood of technology and the foundation of any significant competitive edge for an organization.

In an open source style technical training environment, as learners master different technical concepts and skills, they develop multi-faceted, even divergent ways to think. This is often just what’s needed to identify new products, services or process efficiencies with which to game the market. Open source learning gives learners the freedom to create and manage interactive learning material, generating and sharing value that extends beyond the immediate training curriculum.

Open source learning also creates interactive, rightly timed opportunities for performance evaluation, and alternative assessments to gauge learner absorption of material and help the trainer shape the lesson to best meet learner’s needs in the moment. Deeper, more engaged learners often achieve notable training achievements in this environment.

Learning leaders should seek out technical training options that promote open-source style learning. It’s quite practical, and its principles align neatly with the best run technical training classrooms. For instance, with the right classroom-based technical training learners don’t need to absorb complicated theories or ideas that aren’t immediately relevant to their work or current business needs. This saves time and energy and enables learners to retain more of their knowledge and apply it more effectively on the job.

Open source learning helps learners to create value by sharing information, collaborating to achieve training objectives and enjoying the benefits of peer-to-peer learning and idea exchange to spark new, innovative solutions to training exercises and business challenges alike. Open source learning and a thematically aligned technical training classroom are both high touch and team-centric. Reminiscent of the ideal business environment, in this learning lab multiple stakeholders from different functions can learn, share, dream, create and work together to achieve common business goals.

About the Author:

Adding Authentication in AWS with Amplify

October 4th, 2019

If you’re familiar with using AWS for user authentication, DynamoDB, AppSync and other services in your app or website, you’ll love Amplify.

Amplify is a command-line interface that takes a few shortcuts, avoids the clicking and navigation and also makes a few wise decisions for you. Granted, you can customize things as you wish. And you can always go straight to the console source and make changes. But most of the time, using Amplify will do what you want faster and easier.

The first thing you need to do is install Amplify. You’ll need an AWS account and then run a few commands. You can see the details here: https://aws-amplify.github.io/docs/

Initialize a Project

Once it’s installed, you’re ready to go. I’ll use an iOS app but you can use basically the same steps for Android or a web app.

Navigate in the terminal to your project. From there, you’ll create your app’s existence with AWS with this command:

amplify init

The first thing it asks is for you to pick an editor:

I usually use Vim because it launches in the same terminal window.

Then it asks you to verify the type of project you’re working on. It can usually detect correctly based on the files:

Then you need to pick a profile (or create one on AWS which it helps you with):

Then it does it’s magic… and prints out a lot of lines. You can watch as it creates everything it needs. It will create a bucket in S3 for the deployment files, IAM roles as needed for running and accessing various pieces and a CloudFormation to manage it all.

The best part is you really don’t have to care! 🙂 Of course it’s always good to know what’s going on. I highly recommend going to each of the places listed in the AWS console to see what’s created.

Once the project is all setup, you’re ready to add features from AWS.

Help

If you run just “amplify” you get some basic help:

The key things you’ll tend to do are these:

amplify add <category> – This is how you add various services. If you add api, you’re adding AppSync (and possibly more like DynamoDB). If you add auth, that’s authorization using Cognito. Storage is S3 and so on.

Amplify does a great job of walking you through each one that while knowledge of each is great, it might not be necessary. Again, however, I highly recommend you understand what’s going on in the background.

I’d suggest using Amplify as a powerful tool to do what you already know about. I do not recommend using Amplify as a way to avoid learning the functionality of AWS.

Add Authorization

So let’s add a feature via Amplify to our app. We’ll use the command:

amplify add auth

One funny thing about amplify is that you can add a category with “amplify add <category>” or “amplify <category> add.” It’s like you can tell amplify “add this category” or you can tell a category to be added. Try not to let it bug you.

The first question you’ll be added is if you want to use the default configuration:

I like the default configuration. If you want to know more, select “I want to learn more” which displays this:

Again, I recommend learning about Cognito to understand the details. For this tutorial, we’ll go with the default.

It will set up the configuration for authorization to use a username, email and password for new accounts.

Amplify does this locally (and explains so at the end of the execution). So the configuration and everything is setup in files under the directory of your project.

It also mentions how you can push the change to AWS with the push command. To get it to AWS, you run:

amplify push

It will have you verify the changes before continuing:

In some cases there are more questions to answer and typically the default answer (e.g., Y/n – the capital letter being the default) is a good answer and you can just hit Enter on the keyboard.

Pushing to AWS can take a few minutes. Many lines will print out that look similar to when you created the project. Hopefully it ends with “All resources are updated in the cloud” and a satisfying green checkmark. 🙂

Cognito

Once it’s pushed to the server you can view the details at: https://console.aws.amazon.com/cognito/users

Of course you won’t have any users yet:

And locally you’ll have a new file that’s very important. It’s named awsconfiguration.json and it’s in the same directory your project is in:

This configuration file holds the details of the setup you created on AWS. It’s the file that you’ll include in your project (in this case Xcode) for access to the services and features.

As the extension implies, it’s a JSON file:

It lists the authentication related details the CocoaPods (iOS) will use to access AWS. As other categories are added via amplify, more items will be added to the awsconfiguration.json file.

If you include the file in your project where it is, you won’t need to update the file in your project as you add more services.

App Code

To add authentication to your code, you can visit the AWS documents per platform:

https://aws-amplify.github.io/docs/ios/authentication#initialization

https://aws-amplify.github.io/docs/android/authentication#initialization

https://aws-amplify.github.io/docs/js/authentication#configure-your-app

On the left side you’ll see a listing of other categories you can add similarly to your project.

For iOS, once you install the CocoaPods, checking to see if the user is logged in is pretty easy along with some other useful properties:

And showing the login/create account UI is similar:

Conclusion

Hopefully this removes some of the mystery of Amplify. I recommend trying it out and seeing how well it works for you. I’ve gotten pretty comfortable with it to the point that I don’t load up much of AWS to verify what it’s doing anymore.

Another great command in amplify is one that cleans everything up (for the given project). That way you can play around with it and remove it all easily. 🙂

amplify delete

 

About the Author:

Gatsby Tutorial Post Part 2: NetlifyCMS and Styling

April 29th, 2019

This is the 2nd part of a tutorial series on building fast and elegant sites with Gatsby, Material-ui, and NetlifyCMS (part 1 here). The previous part of the tutorial showed how to setup Gatsby and create pages manually as well as dynamically using gatsby-node.js. This part of the series will show the following:

  • Creating the Courses Page and Individual Courses
  • Adding Images to the Courses/Posts
  • Install Material-UI plugins and style all pages with Material-UI
  • Installing NetlifyCMS to allow non-technical users to make content changes
  • Adding More Fields Types to the Courses (that work out of the box with NetlifyCMS)

Demo Site (Here’s where we’re going to get to)

Github Repo (If you’d like to jump right into the code)

Creating the Courses Page and Individual Courses

Our demo site features both blogs (which we did previously) and courses (which we’ll do now). Similar to the blogs, this involves creating a parent /courses page, a course template, a courseitem component (for the list on /courses, and the markdown files for the courses. So let’s first create the main /courses page (that will list all of the courses) and pages for each course.

Here’s how I created each of the pages:

/pages/courses.js

import React from "react"
import { Link, StaticQuery, graphql } from "gatsby"

import Layout from "../components/layout"
import SEO from "../components/seo"
import CourseItem from "../components/CourseItem"

class CoursePage extends React.Component {
 render() {
   const { data } = this.props

   const { edges: posts } = data.allMarkdownRemark

   return (
     <div>
       <Layout>
         <SEO title="Courses Page" />
         <h1>Courses Page</h1>

         <div
           style={{
             display: "flex",
             justifyContent: "space-evenly",
             flexWrap: "wrap",
           }}
         >
           {posts &&
             posts.map(({ node: post }) => (
               <CourseItem
                 key={post.id}
                 post={post.frontmatter}
                 style={{ marginRight: 10, width: "50%" }}
                 slug={post.fields.slug}
                 excerpt={post.excerpt}
               />
             ))}
         </div>
       </Layout>
     </div>
   )
 }
}

export default () => (
 <StaticQuery
   query={graphql`
     query CoursePageQuery {
       allMarkdownRemark(
         sort: { order: DESC, fields: [frontmatter___date] }
         filter: { frontmatter: { templateKey: { eq: "single-course" } } }
       ) {
         edges {
           node {
             excerpt(pruneLength: 100)
             id
             fields {
               slug
             }
             frontmatter {
               title
               templateKey
               date(formatString: "MMMM DD, YYYY")
             }
           }
         }
       }
     }
   `}
   render={data => <CoursePage data={data} />}
 />
)

/templates/single-course.js

import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"
import { Link } from "gatsby"

const CoursePage = ({ data }) => {
 const { markdownRemark: post } = data

 return (
   <Layout>
     <Link to="/courses">
       <p>← Back to Courses</p>
     </Link>

     <h1>{post.frontmatter.title}</h1>
     <h4>{post.frontmatter.date}</h4>
     <p dangerouslySetInnerHTML={{ __html: post.html }} />
   </Layout>
 )
}

export default CoursePage

export const CoursePageQuery = graphql`
 query CoursePage($id: String!) {
   markdownRemark(id: { eq: $id }) {
     html
     frontmatter {
       title
     }
   }
 }
`

/components/courseitem.js

import React from "react"
import { Link } from "gatsby"

function CourseItem(props) {
 const { post, slug, excerpt } = props

 return (
   <div>
     <Link to={slug}>
       <h1>{post.title}</h1>
     </Link>
     <h3>{excerpt}</h3>
   </div>
 )
}

export default CourseItem

/courses/intermediate-react.md

---

templateKey: single-course

title: intermediate React

date: 2019-04-15T16:43:29.834Z

description: An intermediate React course

difficulty: Intermediate

---

what a course, what a course…….

/courses/cool-course.md etc

---

templateKey: single-course

title: Great course on JS

date: 2019-04-15T16:43:29.834Z

description: A great course

difficulty: Beginner

---

what a course, what a course...what a course, what a coursewhat a course, what a course...what a course, what a course

what a course, what a course...what a course, what a course

what a course, what a course...what a course, what a course

what a course, what a course...what a course, what a course

What’s going on here? Let’s review:

Gatsby-node.js creates the course pages using the appropriate template with this section of the code:

...

component: path.resolve(

`src/templates/${String(edge.node.frontmatter.templateKey)}.js`

),

…

In this case, it would be using single-course.js.

Within single-course.js there is a page query at the bottom. This queries for the right markdown file (using the id found in context) so that those specific pages will have the right title and html (from markdown) to display.

Within the courses.js file, we’re using a Static Query to query/search for the courses that have the templateKey of single-course and making a list of the courses (using the simple CourseItem.js component for help). This gives us a very basic (but functional) /courses page like this:

And an individual course page like this:

So these are pretty bland pages, unless you’re a hardcore minimalist. I’ll show you some Gatsby image plugins now that will add some color/life to these posts/courses.

Adding Images to the Courses/Posts

One of the top selling points of Gatsby is speed. Poorly sized or slow loading images are one of the easiest ways to make a website feel sluggish so this is an obvious area to optimize first. Two Gatsby plugins (gatsby-image and gatsby-transformer-sharp) are amazing tools for working with and optimizing Gatsby images. The latter leverages the Sharp image library, which is a very popular node module for resizing images. I’ll show you now to how add images to the course and post pages.

First, we need to install the plugins:

npm install --save gatsby-image gatsby-transformer-sharp gatsby-plugin-sharp

We’re also going to add a plugin that will allow us to access relative image paths in the project:

npm install gatsby-remark-relative-images --save

This will make for working with NetlifyCMS images easier later.

Then add them to the gatsby-config.js, within the big array of plugins like so:

 'gatsby-plugin-sharp',
    'gatsby-transformer-sharp',
    {
      resolve: 'gatsby-transformer-remark',
      options: {
        plugins: [
          {
            resolve: 'gatsby-remark-relative-images',
          },
          {
            resolve: 'gatsby-remark-images',
            options: {
              // It's important to specify the maxWidth (in pixels) of
              // the content container as this plugin uses this as the
              // base for generating different widths of each image.
            
              maxWidth: 590,
            },
          },
          {
            resolve: 'gatsby-remark-copy-linked-files',
            options: {
              destinationDir: 'static',
            },
          },
        ],
      },
    },
{
      resolve: 'gatsby-source-filesystem',
      options: {
        path: `${__dirname}/static/img`,
        name: 'uploads',
      },
    },
    {
      resolve: 'gatsby-source-filesystem',
      options: {
        path: `${__dirname}/src/pages`,
        name: 'pages',
      },
    },
    {
      resolve: 'gatsby-source-filesystem',
      options: {
        path: `${__dirname}/src/images`,
        name: 'images',
      },
    },

Now we can add the images to our posts. Create a folder called /static and a folder within that call img. That’s where the images will live. I downloaded some demo images for this fake courses and put them in the folder.

Now within the individual course markdown files, we need to add the images within the frontmatter (—) headings like so:

---

[more items]

image: /img/[imagename].jpeg

---

Now, we’ll edit the single-course.js page to be able to query for this image and render it on the page. Change the GraphQL query at the bottom of the page to include the image query, like so:

export const CoursePageQuery = graphql`
  query CoursePage($id: String!) {
    markdownRemark(id: { eq: $id }) {
      html
      frontmatter {
        title
        image {
          childImageSharp {
            fluid(maxWidth: 500, quality: 100) {
              ...GatsbyImageSharpFluid
            }
          }
        }
      }
    }
  }
`

This is using the gatsby-plugin-sharp plugin to render a fluid image with a maxWidth of 500 pixels. Right here within the GraphQL query, we’re able to choose how we’d like to receive the image in our component/html. This plugin has extensive documentation that can be found here.

Now, within the the single-course.js, we’ll use Gatsby-image to render the image in the html. It’s a simple import:

import Img from "gatsby-image"

And then a simple enough component to render.

<Img fixed={post.frontmatter.image.childImageSharp.fluid} />

This is how you add the right plugins, the files, and the queries to be able to use plugins within Gatsby.

Installing NetlifyCMS

NetlifyCMS (like an CMS) allows for non-technical users to edit content on a site. This allows people in marketing or content roles the freedom to create and frees up developers from having to do these sorts of small tasks. As was mentioned before, NetlifyCMS is made by static hosting service Netlify, but they can each be used separately from each other. Gatsby can be easily configured to work with WordPress, Contently, and many other data sources. NetlifyCMS has great docs, a generous free tier, and easy-to-use authentication.

NetlifyCMS is easy to configure with Gatsby using, you probably guessed it, gatsby-plugin-netlify-cms. Install it using npm and add it to gatsby-config.js:

npm install gatsby-plugin-netlify-cms --save

// gatsby-node.js

},.......[other plugins]

`gatsby-plugin-netlify-cms`,

….[other plugins] {

NetlifyCMS needs a config.yml file, which tells it which fields can be changed within the CMS. Create a folder called ‘admin’ within the Static folder and put the following config.yml file in it:

backend:
  name: git-gateway
  branch: master

media_folder: static/img
public_folder: /images

collections:
  - name: "pages"
    label: "Pages"
    files:    
      - file: "src/pages/about.md"
        label: "About"
        name: "about"
        fields:
          - {
              label: "Template Key",
              name: "templateKey",
              widget: "hidden",
              default: "about-page",
            }
          - { label: "Title", name: "title", widget: "string" }
          - { label: "Body", name: "body", widget: "markdown" }
  - name: "blog"
    label: "Blog"
    folder: "src/pages/blogs"
    create: true
    slug: "{{year}}-{{month}}-{{day}}-{{slug}}"
    fields:
      - {
          label: "Template Key",
          name: "templateKey",
          widget: "hidden",
          default: "single-blog",
        }
      - { label: "Title", name: "title", widget: "string" }
      - { label: "Publish Date", name: "date", widget: "datetime" }
      - { label: "Description", name: "description", widget: "text" }
      - { label: "Body", name: "body", widget: "markdown" }

  - name: "courses"
    label: "Courses"
    folder: "src/pages/courses"
    create: true
    slug: "{{year}}-{{month}}-{{day}}-{{slug}}"
    fields:
      - {
          label: "Template Key",
          name: "templateKey",
          widget: "hidden",
          default: "single-course",
        }
      - { label: "Title", name: "title", widget: "string" }
      - { label: "Publish Date", name: "date", widget: "datetime" }
      - { label: "Description", name: "description", widget: "text" }
      - { label: "Body", name: "body", widget: "markdown" }
      - { label: Image, name: image, widget: image }

This creates 3 collections within the CMS: one for updating the about page, one for the courses, and one for the blogs. The ‘widgets’ are NetlifyCMS widgets and should be self-explanatory in a moment. With the above config.yml, this is what my admin interface looks like:

Within the Courses Collection, I see this:

Take a look, again, at the config.yml.

Notice how the fields with this file line up with what you’re seeing in the CMS image above? The template key is hidden so it doesn’t show. But right there are string widget (aka text field) for Title, Description, and Body. And there’s a datetime widget (a datepicker) for Publish Data. NetlifyCMS is really just an interface for making changes to our markdown files here. The config.yml serves as a way to tell Netlify which fields are available for editing. NetlifyCMS features a wide variety of default widgets and you can even make custom ones.

Source: https://www.netlifycms.org/docs/widgets/

Although this takes some setup work, this workflow is extremely powerful for using Github markdown files as a CMS.

The final thing needed here is making the images hosted in static/img available for NetlifyCMS to use.

Add this to the top of the file within Gatsby-node.js

const { fmImagesToRelative } = require('gatsby-remark-relative-images')

And add this method call within the onCreateNode block:

exports.onCreateNode = ({ node, actions, getNode }) => {

const { createNodeField } = actions

fmImagesToRelative(node)

This plugin was specifically built to make NetlifyCMS play nice with relative image paths. Failure to add this config right will send you to bug hell (e.g. “Field “image” must not have a selection since type “String” has no subfields.”)

.

Styling it all with Material-UI

We’ve built out our posts, blogs, and about page. Now we’ll see how to style out all of the pages using the most popular React UI framework, Material-ui. Material-ui has nearly 50,000 stars on Github and over 1,000 contributors. It is a React implementation of Google’s Material Design principles. Material-ui gives React developers a wide variety of components, styling, and utilities for making their sites aesthetically pleasing and easy to use. If you don’t want your site to look like a generic Googly app, Material-ui is supremely easy to customize to your liking.

There are many ways to add Material-ui to a Gatsby project. Material-ui has a Gatsby starter to use. Another developer made a dedicated Gatsby-starter with Material-ui. But I find the easiest way to add Material-ui to Gatsby is with gatsby-plugin-material-ui. The previous two work but they are much more complicated. Plugins are one of the awesome parts of Gatsby: Just install the plugin, add it to gatsby-config.js and you’re good to go. Here’s how to do just that:

npm install gatsby-plugin-material-ui @material-ui/styles

Edit gatsby-config.js

module.exports = {
  plugins: [
    {
      resolve: `gatsby-plugin-material-ui`,
      options: {
      },
    },
  ],
};

If you’ve worked with Material-ui before, you’ve probably played around with its theming capabilities. Material-ui themes allow you to establish a global theme that can be called from various child components. This makes it easier to create one coherent look and feel (vs. having pages/components with different styles, which can look sloppy). With the gatsby-plugin-material-ui plugin, this theme will go in that options object in the config above like so:

options: {        
        theme: {
          palette: {
              primary: {
                  main: '#BA3D3B', // new color here 
              } 
          },
      },

Now we can import material-ui components anywhere within the our Gatsby project. Here’s how I changed the single-course.js page:

imports...
import { withStyles } from '@material-ui/core/styles';
import Grid from '@material-ui/core/Grid';
...
import Avatar from '@material-ui/core/Avatar';

const styles = theme => ({
  root: {
    flexGrow: 1,
  },
  paper: {
    padding: theme.spacing.unit * 2,
    textAlign: 'center',
    color: theme.palette.text.secondary,
  },
  title:{
    marginBottom:'.2em'
  },
  backButton: {
    textDecoration:'none'
  },
  bigAvatar: {
    '& img':{
      margin: 10,
      width: 60,
      height: 60,
    },
    width:100,
    height:100,
    border:'1px solid grey'
  
  },
});

const CoursePage = ({ data, classes }) => {
  const { markdownRemark: post } = data

  return (
    <Layout>
       <Link to='/courses' className={classes.backButton}>
      <p>← Back to Courses</p>

      </Link>
      
      <Grid container spacing={24}>
       
        <Grid item xs={9}>
          <h1 className={classes.title}>{post.frontmatter.title}</h1>
          <h4>{post.frontmatter.date}</h4>
          <p dangerouslySetInnerHTML={{ __html: post.html }}/>  
        </Grid>    
        <Grid item xs={3}>
        <Avatar src={post.frontmatter.image.childImageSharp.fluid.src} className={classes.bigAvatar} />
       
        </Grid>   
      </Grid>
  
    </Layout>
  )
}
export default withStyles(styles)(CoursePage);

[page query removed for brevity]

Here’s how I changed the single-blog template:

...
import { withStyles } from '@material-ui/core/styles';
import Grid from '@material-ui/core/Grid';
...
import Layout from '../components/layout'
import Img from "gatsby-image"
import { Link } from "gatsby"

const styles = theme => ({
  root: {
    flexGrow: 1,
  },
  paper: {
    padding: theme.spacing.unit * 2,
    textAlign: 'center',
    color: theme.palette.text.secondary,
  },
  title:{
    marginBottom:'.2em'
  },
  backButton: {
    textDecoration:'none'
  }
});

const BlogPage = ({ data, classes }) => {
  const { markdownRemark: post } = data

  return (
    <Layout>
      <div className={classes.root}>
      <Link to='/blog' className={classes.backButton}>
      <p>← Back to Blog</p>

      </Link>
      
      <Grid container spacing={24}>
        <Grid item xs={3}>
          <Img fluid={post.frontmatter.image.childImageSharp.fluid} />
        </Grid>
        <Grid item xs={9}>
          <h1 className={classes.title}>{post.frontmatter.title}</h1>
          <h4>{post.frontmatter.date}</h4>
          <p dangerouslySetInnerHTML={{ __html: post.html }}/>  
        </Grid>       
      </Grid>
      </div>
    
    </Layout>
  )
}


export default withStyles(styles)(BlogPage);

[page query removed for brevity]
`

Here’s the about page:

...
import { withStyles } from '@material-ui/core/styles';

const styles = theme => ({
  heroText: {
    color:'white',
    textAlign: 'center',
    lineHeight:7,
    marginTop:-20
  },
  mainBlogCopy: {
    marginTop: theme.spacing.unit,
  },
  blogText:{
    color:theme.palette.primary.main
  }
});

const AboutPage = ({ data, classes }) => {
  const { markdownRemark: post } = data

  return (
    <Layout>
      <div style={{
        backgroundImage: `url(${post.frontmatter.image.childImageSharp.fluid.src})`,
        height:300
      }}>
      <h1 className={classes.heroText}>{post.frontmatter.title}</h1>
      </div>
      <div className={classes.mainBlogCopy}>
       <p className={classes.blogText} dangerouslySetInnerHTML={{ __html: post.html }}/> 
      </div>
      
    </Layout>
  )
}

AboutPage.propTypes = {
  data: PropTypes.object.isRequired,
}

export default withStyles(styles)(AboutPage);

[page query removed for brevity]

Here’s what I added to the home page to make it look a little more like appendTo:

….
import { Link, StaticQuery, graphql } from "gatsby"
import Grid from "@material-ui/core/Grid"
import BlogItem from "../components/BlogItem"
import { withStyles, withTheme } from "@material-ui/core/styles"
import Button from "@material-ui/core/Button"
import Typography from '@material-ui/core/Typography'
import AppBar from '@material-ui/core/AppBar';
import Tabs from '@material-ui/core/Tabs';
import Tab from '@material-ui/core/Tab';


const styles = theme => ({
  mainBlogArea: {
    paddingTop: '20px !important',

  },
  redBox:{
    padding:30,
    paddingTop:50,
    height:200,
    backgroundColor:'#AC4839',
    marginBottom:30
  },
  greyBox:{
    padding:30,
    paddingTop:50,
    height:200,
    backgroundColor:'#D9D8D8'
  },
  blackButton:{
    backgroundColor:'black',
    color:'white'

  },
  redButton:{
    backgroundColor:'#AC4839',
    color:'white'

  },
  TabsSection:{
    marginTop:30,
    backgroundColor:'white',
    border:'1px solid grey',
    height:300,
  },
  Tab:{
      width:10
  }

  
})

const IndexPage = props => {
  const { data, classes } = props
  // const { edges: posts } = data.allMarkdownRemark

  return (
    <Layout>
      <SEO title="appendTo Home" keywords={[`Courses`, `Training`, `react`]} />

      <Grid container spacing={24}  className={classes.mainBlogArea}>
        <Grid item xs={8}>
          <div >
            {data.map(item => (
              <BlogItem
                key={item.id}
                post={item.frontmatter}
                image={item.frontmatter.image.childImageSharp.fluid.src}
                slug={item.fields.slug}
                date={item.frontmatter.date}
              />
            ))}
          </div>
        </Grid>
        <Grid item xs={4}>
          <div className={classes.redBox}>
            <Typography variant="h5" style={{color:'white'}}>
              Custom Private Courses
            </Typography>
            <Button variant="contained" className={classes.blackButton}>
              Get Started
            </Button>
          </div>

          <div className={classes.greyBox}>
          <Typography variant="h5">
              Live Public Courses
            </Typography>
            <Button variant="contained" className={classes.redButton}>
              Sign Up Today
            </Button>
          </div>

          <div className={classes.TabsSection} >
          <AppBar position="static">
            <Tabs>
              <Tab label="Popular" className={classes.Tab} />
              <Tab label="Recent" className={classes.Tab} />
        
            </Tabs>
            </AppBar>


          </div>
        </Grid>
      </Grid>
    </Layout>
  )
}

const StyledUpIndexPage = withStyles(styles)(IndexPage)

export default () => (
  <StaticQuery
    query={graphql`
      query IndexPageQuery {
        allMarkdownRemark(
          sort: { order: DESC, fields: [frontmatter___date] }
          filter: { frontmatter: { templateKey: { eq: "single-blog" } } }
        ) {
          edges {
            node {
              excerpt(pruneLength: 40)
              id
              fields {
                slug
              }
              frontmatter {
                title
                templateKey
                date(formatString: "MMMM DD, YYYY")
                image {
                  childImageSharp {
                    fluid(maxWidth: 1400, quality: 100) {
                      ...GatsbyImageSharpFluid
                    }
                  }
                }
              }
            }
          }
        }
      }
    `}
    render={data => (
      <StyledUpIndexPage
        data={data.allMarkdownRemark.edges.map(item => item.node)}
      />
    )}
  />
)

And finally, here’s what I added to the NavBar to allow for navigating between the pages:

import { Link } from "gatsby"
import React from "react"
import { withStyles } from "@material-ui/core/styles"
import AppBar from "@material-ui/core/AppBar"
import Toolbar from "@material-ui/core/Toolbar"
import Button from "@material-ui/core/Button"

import { StaticQuery, graphql } from "gatsby"
import Img from "gatsby-image"


const styles = {
  root: {
    flexGrow: "1 !important",
  },
  appbar: {
    backgroundColor: "#AC493A",
  },
  grow:{
    flexGrow:1
  },
  link: {
    color: `white`,
    textDecoration: `none`,
  },
}

class Header extends React.Component {
  constructor(props) {
    super(props)
  }

  render() {
    const { classes } = this.props

    return (
      <div className={classes.root}>
        <AppBar position="static" className={classes.appbar}>
          <Toolbar>
            <div className={classes.grow}>
              <Link to='/' >
              <StaticQuery
                query={graphql`
                  query {
                    file(relativePath: { eq: "appendto_logo.png" }) {
                      childImageSharp {
                        # Specify the image processing specifications right in the query.
                        # Makes it trivial to update as your page's design changes.
                        fixed(width: 150) {
                          ...GatsbyImageSharpFixed_noBase64
                        }
                      }
                    }
                  }
                `}
                render={data => <Img  critical={true} fadeIn fixed={data.file.childImageSharp.fixed} />}
              />
              </Link>
            </div>
            <div>
              <Link to="/about" className={classes.link}>
                <Button color="inherit">About</Button>
              </Link>

              <Link to="/blog" className={classes.link}>
                <Button color="inherit">Blog</Button>
              </Link>

              <Link to="/courses" className={classes.link}>
                <Button color="inherit">Courses</Button>
              </Link>
            </div>
          </Toolbar>
        </AppBar>
      </div>
    )
  }
}

export default withStyles(styles)(Header)

And here’s what we end up with: https://appendtostaticstyled.netlify.com/

We have here a site that we can continue to build upon and style with Material-ui. All users can make tweaks or changes using NetlifyCMS. And finally, this site is blazing fast and consists of static files that can be served for cloud storage service or CDN.

This starter project is a great way to start any project and I hope these two long posts helped you understand how it came together.

Recommended Reading

This tutorial showed you the essentials of Gatsby. That said, even with nearly 5500 words, it had to skip over a number of topics. Here’s some posts I recommend reading to get a better understanding of Gatsby:

About the Author:

Build Fast and Elegant Sites with Gatsby, NetlifyCMS and Material-UI

April 27th, 2019

This tutorial will show you how to use Gatsby, NetlifyCMS, Netlify, and Material-UI to build out a multi-page site that can be updated with an intuitive CMS. Before diving into the code, I’ll first tell you about the the tools we’ll be working with. Part 2 is here (if you need to skip ahead).

Gatsby

Gatsby is React-based framework that has recently gained a lot traction and use in production. AirBnb, Flamingo, and Impossible Foods are all companies using Gatsby to build production sites and apps. Gatsby sites get built with React, GraphQL, Gatsby plugins, and some sort of CMS. Gatsby outputs production assets as HTML/CSS/JS files that can be served from a cloud host like AWS S3 or a Google Cloud Storage Bucket.

Material-UI

Material-UI is a React UI framework that implements Google’s Material Design principles in React. It can be added to Gatsby projects in a variety of ways and we’ll see how to use it simply with a plugin.

Netlify/NetlifyCMS

One of the smaller hosting services that works really well with Gatsby is Netlify. Netlify (the company) authored an excellent CMS called NetlifyCMS that makes it really simple to produce/edit/manage content stored in Github. All in all, the combo of GraphQL, Netlify, and NetlifyCMS makes it really simple for developers (who already know React) to build fast websites with an intuitive CMS. NetlifyCMS can be setup so that non-technical users can easily make changes to the content and have Netlify push the changes live. Gone are the days of managing clunky WordPress sites or plugin catastrophes! Also gone are the days of slow loading heavy client side sites (looking at you Soundcloud and Yelp 👀).

Ok, whoah whoah — I’m mostly kidding. The WordPress ecosystem is actually pretty amazing and I use Soundcloud every dang day. What I mean to say is that Gatsby and the entire JAMstack paradigm represent a very exciting evolution in websites that developers will enjoy working on and people will enjoy using.

This tutorial will show you how to setup Gatsby with NetlifyCMS and build out a small demo site (see below). The goal of this tutorial is help give you a better conceptual framework for how Gatsby sites come together. Gatsby already has a very nicely done 8-part tutorial so this tutorial will seek to build upon that and make it even easier to learn Gatsby.

Tutorial Outline:

  • Part 1
    • What We’ll Build
    • About Gatsby (and why try it)
    • Setting up Gatsby
    • A high-level overview of what’s what in Gatsby
    • Understanding Gatsby’s Magic
    • Creating Basic Static Pages with Gatsby
    • Dynamically Creating Pages with gatsby-node.js
    • Creating the About Page
    • Creating the Blog Page and Blog Posts
  • Part 2
    • Setup NetlifyCMS to make editing the content more accessible
    • Create the Courses Page and Individual Courses
    • Add Images and more fields to the Courses and Blogs
    • Style it all with Material-UI

What We’ll Build

This tutorial will be focused on building a very basic clone of the appendTo site (that you’re on right now). This demo site consists of pages for About, Courses, Home, and the Blog. There will also be individual pages for each Course and Blog Post.

The site can be found here: https://appendtostaticstyled.netlify.com/courses

The content in this site lives in a Github repo and can be updated using NetlifyCMS. This gives developers or non-technical users a nice interface for making changes to the content.

About Gatsby (and why try it)

Gatsby is run by VC-backed Berkeley-based Gatsby Inc., which has almost 30 employees (at this time of writing). Many of their founders and employees have ‘making the web fast’ as their Linkedin tagline so it’s fair to say that speed is one Gatsby’s primary selling points. Definitely take a second to try out of some of the sites listed on the Gatsby showcase page. The speed at which an attractive, image-heavy ecommerce site like ShopFlamingo.com loads should inspire you to pick up Gatsby. There’s a pure simple joy in clicking on something and having it load near instantaneously.

The fact that Gatsby is being run as a business and used by large companies should give developers confidence that Gatsby will be around for a while and support will be above average. I find it confidence-inspiring that there are more than 5,000 closed issues on Github.

Furthermore, I received extremely fast help for anything I struggled with while making this post (via Discord, Github, and StackOverflow).

It’s also worth taking a look at some of the blog posts that Gatsby employees have written about their baby. A very interesting one is Making website building fun by founder Kyle Mathews. The whole essay is worth reading and gives you a sense of their founding principles. Mathews describes using the component React-headroom vs. having to implement the same functionality, from scratch, in HTML/CSS/JS (with many more lines). One of the key lines in that essay is this:

What makes technology fun?

This is a complex philosophical question and I’m writing this on a Saturday afternoon so I’ll cheat a bit and just cut the gordian knot by saying “simplicity is fun” and conversely, “complexity is not fun”.

Every one loves new projects. Why? Because they’re simple! We can dive in and experiment and reliably get something done. The more complex the project, the more things seem to break, the more time gets wasted on various yak shaves, and critically, the gap between thinking up an idea and being able to try it grows larger and larger.

Why am I mentioning this bit or the founder at all? Because Gatsby was designed to make building websites more fun. This likely explains the development of their plugin ecosystem and some of the magic and opinions Gatsby has. There’s some upfront difficulty and complexity in learning to play with Gatsby. But once you get it, you’ll probably find it really fun to use.

If you’re still considering other static site options, compare Gatsby with React-static to see how a more manual and less opinionated React-based static site library can look.

And with this background out of the way, let’s start building!

Setting up Gatsby

Gatsby offers a nifty CLI for working with Gatsby projects. As you probably guessed, here’s the terminal command to get it:

npm install -g gatsby-cli

Like many CLIs, typing gatsby –help in the Terminal shows you some of the new commands you can use:

Let’s use gatsby new now to create a new Gatsby project:

gatsby new appendToGatsby

After that build completes, run gatsby develop in the terminal and open http://localhost:8000/ in your browser. Pull the project folder into your text editor of choice.

Take a look at the files and folders generated by the Gatsby CLI. I don’t know about you, but I often feel a bit overwhelmed when I see a whole bunch of new files and folders that a generator has made for me. I sometimes claw through the files frantically trying to figure out what’s what and how it all wires together. To make this easier for you, I’m going to diagram this out.

You should be seeing a folder for components, pages, images and several .js files that live in the src root. Here’s a quick rundown on what they do:

Here’s what you should be seeing:

The hardest thing about Gatsby (for me) was all the little nuances and small details that make up its functionality. For example, with this starter project, I found myself looking for the React-router files and a base app.js. Don’t do this! Gatsby projects work differently than normal Create-React-App projects. Let’s create a new page and learn more.

Take what’s in page-2.js and create a file called coolnewpage.js (in that same /pages folder)

Mine looks something like this:

import React from "react"
import { Link } from "gatsby"

import Layout from "../components/layout"
import SEO from "../components/seo"

const CoolNewPage = () => (
 <Layout>
   <SEO title="Cool New Page" />
   <h1>Cool New Page</h1>
   <p>Gatsby is Magical but worth learning</p>
   <Link to="/">Go back to the homepage (index.js file)</Link>
 </Layout>
)

export default CoolNewPage

Then re-run gatsby develop in your terminal. Now when I go to http://localhost:8001/coolnewpage, I see this:

Of course this is nothing too special. But consider that you didn’t have to setup the routing or link the components together. Gatsby just detected that a new file was in the pages folder and created the page for it. Try to let some of your React habits go when learning Gatsby (suspend disbelief, if you will). This will make sense with a bit of practice. Let’s now try building something a bit more dynamic.

Building a dynamic About page

Building static pages (by literally placing them in the /pages folder) works fine and would be a good option for really simple ‘brochureware’ sites or a portfolio. But since you’ll likely want to build sites with multiple pages and templates, it makes sense to learn how to use data and templates to build pages dynamically.

We’re next going to build out the About page for this appendTo clone site. Building pages dynamically is quite challenging at first but it’s fairly easy to pick up. Here are the steps:

  1. Create a markdown file (with frontmatter headings) that will hold the page content
  2. Use the Gatsby API methods createPages and onCreateNode to create the page(s) in gatsby-node.js
  3. Create the page template with the appropriate GraphQL query to populate the page with data
  4. Install the appropriate plugins and add them to gatsby-config

It’s hard to understand how these files and APIs connect at first. I’ll walk you through it as slowly and simply as possible.

Step 1: Create the markdown files

Create a markdown file called about.md (that will go in the /pages folder) with the text/info that will go on the about page. Frontmatter (the information between the two triple dashes —) is where you can store fields like the title and the templateKey (which I’ll explain in a bit). Mine looks something like this:

about.md

templateKey: about-page

title: About Page (created with gatsby-node.js)

(This text is obnoxiously red on purpose)

appendTo is your leading source of technical news, tips, and tutorials.

[the rest of the post]

…..

Step 2: Create the pages using the Gatsby API methods in gatsby-node

We need to now create the pages using Gatsby’s createPages and onCreateNode API methods.

const path = require(`path`)
const { createFilePath } = require('gatsby-source-filesystem')

exports.createPages = ({ actions, graphql }) => {
 const { createPage } = actions

 return graphql(`
   {
     allMarkdownRemark(limit: 1000) {
       edges {
         node {
           id
           fields {
             slug
           }
           frontmatter {
             templateKey
           }
         }
       }
     }
   }
 `).then(result => {
   if (result.errors) {
     result.errors.forEach(e => console.error(e.toString()))
     return Promise.reject(result.errors)
   }


   const posts = result.data.allMarkdownRemark.edges

   posts.forEach(edge => {
     const id = edge.node.id
     createPage({
       path: edge.node.fields.slug,
       tags: edge.node.frontmatter.tags,
       component: path.resolve(
         `src/templates/${String(edge.node.frontmatter.templateKey)}.js`
       ),
       // additional data can be passed via context
       context: {
         id
       },
     })
   })
 })
}

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

Gatsby’s docs say “We do our best to make Gatsby APIs simple to implement.” I think they do an ok job here but it’s still a lot to grok. It doesn’t make sense for me to completely rehash part 7 of their tutorial where they explain this all in great depth. For this tutorial’s sake, I’ll give you the quick version of what’s going on in the code above.

The onCreateNode part below this is for creating the slugs field so that the page urls work properly. Similar to how that coolnewpage.js created a page at /coolnewpage above, this is doing so manually.

In essence, gatsby-node.js is in charge of querying the markdown files and then creating pages (and slugs) using the markdown data and the page templates. Now we need to create the appropriate page template so that this about page can be created.

Step 3: Create the page templates and their GraphQL queries

Next you need to create a /templates folder and a template for this page. My /templates/about.js page looks like this:

import React from 'react'
import PropTypes from 'prop-types'
import { graphql } from 'gatsby'
import Layout from '../components/layout'

const AboutPage = ({ data }) => {
 const { markdownRemark: post } = data

 return (
   <Layout>
     <h1>{post.frontmatter.title}</h1>   
      <p dangerouslySetInnerHTML={{ __html: post.html }} />      
   </Layout>
 )
}

AboutPage.propTypes = {
 data: PropTypes.object.isRequired,
}

export default AboutPage;

export const aboutPageQuery = graphql`
 query AboutPage($id: String!) {
   markdownRemark(id: { eq: $id }) {
     html
     frontmatter {
       title
     }
   }
 }
`

This looks similar to a normal React component, except for the graphql query at the bottom. This query is using the id passed to the context (on gatsby-node.js) to find the appropriate page (where that id matches). It then retrieves the html and the title from that page (aka, the markdown file). Remember this little bit at the bottom of the previous file?

That same ‘id’ is being used in the query right here to get the right page data.

Step 4: Install Plugins

The final thing we need to do is add the right plugins for us to be able to work with the file system and query markdown files.

Terminal

npm install --save gatsby-source-filesystem

npm install --save gatsby-transformer-remark

Within gatsby-config.js, you need to add these plugins into that [plugins array]:

   {
     resolve: `gatsby-source-filesystem`,
     options: {
       name: `src`,
       path: `${__dirname}/src/`,
     },
   },
  ….
   },
...
...
  `gatsby-transformer-remark`,

Then restart the server with gatsby develop and check out the new about page:

The first time doing this can feel a little challenging. There’s a lot of different files being used and it’s pretty easy for things to break. To prevent myself from getting lost in the cognitive overload of Markdown, React, config settings, GraphQL, React context, promises, and nested you-name-its, I came up with mental shorthand for what these files do:

Markdown files: The data that will go into the pages. Easy.

Templates in the /templates folder: React components with GraphQL queries at the bottom used to build the Gatsby static pages.

Gatsby-node.js: Finds my markdown files and creates pages/slugs for them using the right page template.

Gatsby-config.js: Array of plugins and settings I have to touch when installing plugins.

I hope these shorthands help you as you build your mental model of how Gatsby works.

If you need help understanding how to work with GraphQL in Gatsby, Gatsby comes with a built in GraphQL explorer/helper tool called GraphiQL. Gatsby’s tutorial also has a good write up on how to use it.

Creating the Blog Page and Blog Posts

Now that you’ve made an About page, creating other pages is fairly simple. Since appendTo (and the clone we’re building) is primarily a blog page, we’ll now create some blog posts. This involves creating three new files:

  1. /pages/blog.js (the parent /blog page with a list of the blog posts)
  2. /pages/blogs/blog1.md (an example of the markdown files for the blogs)
  3. /components/BlogItem.js (a small component to show the blog excerpt and title on the /blog page)
  4. /templates/single-blog.js (template for just one blog post)

Here’s how I created the blogs:

Step 1: Create blog.js

import React from "react"
import { StaticQuery, graphql } from "gatsby"

import Layout from "../components/layout"
import SEO from "../components/seo"
import BlogItem from "../components/BlogItem"

class BlogPage extends React.Component {
 render() {
   const { data } = this.props
   const { edges: posts } = data.allMarkdownRemark

   return (
     <Layout>
       <SEO title="Blog" />
       <h1>Blog Page</h1>
       <div>
         {posts &&
           posts.map(({ node: post }) => (
             <BlogItem
               key={post.id}
               post={post.frontmatter}
               slug={post.fields.slug}
               excerpt={post.excerpt}
             />
           ))}
       </div>
     </Layout>
   )
 }
}

export default () => (
 <StaticQuery
   query={graphql`
     query BlogPageQuery {
       allMarkdownRemark(
         sort: { order: DESC, fields: [frontmatter___date] }
         filter: { frontmatter: { templateKey: { eq: "single-blog" } } }
       ) {
         edges {
           node {
             excerpt(pruneLength: 40)
             id
             fields {
               slug
             }
             frontmatter {
               title
               templateKey
               date(formatString: "MMMM DD, YYYY")
             }
           }
         }
       }
     }
   `}
   render={data => <BlogPage data={data} />}
 />
)

This page looks similar to our about page. It is a React component with a GraphQL query at the bottom. This Static Query is a Gatsby component that can be used anywhere to query for data. In this case, it is querying for markdown files that have a templateKey of ‘single-blog’ in the frontmatter header. Let’s make these markdown files now.

Step 2: Create markdown blog files

Here’s an example blog I created and filled with hipster ispum. Notice the templateKey line at the top there. That’s what the query above (in my /blog.js file is looking for).

---

templateKey: single-blog

title: blog3

date: 2019-04-10T16:43:29.834Z

description: so stoked on blog3

---

astropub, small batch godard kickstarter sustainable shoreditch raw denim affogato twee. Disrupt normcore lumbersexual, craft beer aesthetic iPhone chambray irony glossier vinyl skateboard tbh fanny pack. Banh mi sartorial hot chicken semiotics roof party PBR&B whatever brunch, kombucha XOXO tumblr helvetica skateboard. Church-key chillwav

Now we need to make the BlogItem.js component that /blog.js can render this data into.

Step 3: Create BlogItem.js

BlogItem.js

import React from "react"
import { Link } from "gatsby"

function BlogItem(props) {
 const { post, slug, excerpt } = props

 return (
   <div>
     <div>
       <Link to={slug}>
         <h1>{post.title}</h1>
       </Link>
       <h3>{post.date}</h3>
       <p>{excerpt}</p>
     </div>
   </div>
 )
}

export default BlogItem

This is a fairly standard React component that uses the Gatsby Link component for linking to other pages.

Restart the development server and you should see this in your browser:

Step 4: Create the single-blog.js template

import React from 'react'
import PropTypes from 'prop-types'
import { graphql } from 'gatsby'
import Layout from '../components/layout'

const BlogPage = ({ data }) => {
  const { markdownRemark: post } = data

  return (
    <Layout>
      <p>{post.frontmatter.title}</p>
       <p> {post.html}  </p>
      />
    </Layout>
  )
}

BlogPage.propTypes = {
  data: PropTypes.object.isRequired,
}

export default BlogPage

export const BlogPageQuery = graphql`
  query BlogPage($id: String!) {
    markdownRemark(id: { eq: $id }) {
      html
      frontmatter {
        title
      }
    }
  }

Clicking on one of the blogs will lead you to this:

To review what’s happening here, the main /blog page is querying for blog markdown files (e.g. blog1.md), then passing this data to itself and rendering a list of blogs using the BlogItem components.

This post covered most of the basics of setting up Gatsby and creating pages manually and automatically using gatsby-node.js. The following post will explore the following:

  • Creating the Courses Page and Individual Courses
  • Installing NetlifyCMS
  • Styling it all with Material-UI

About the Author:

What Machine Learning Is Today, And What It Could Be Soon

March 23rd, 2019

What Machine Learning Is Today, And What It Could Be Soon

If AI is a broad umbrella that includes the likes of sci-fi movies, the development of robots, and all sorts of technology that fuels legacy companies and startups, then machine learning is one of the metal tongs (perhaps the strongest) that holds the AI umbrella up and open.

So, what is machine learning offering us today? And what could it offer us soon? Let’s explore the potential for ML technologies.

Intro to machine learning

Machine learning is the process of machines sorting through large amounts of data, looking for patterns that can’t be seen by the human eye. A theory for decades, the application of machine learning requires two major components: machines that can handle the amount of processing necessary, plus a lot (a lot!) of gathered, cleaned data.

Thanks to cloud computing, we finally have both. With cloud computing, we can speed through data processing. With cloud storage, we can collect huge amounts of data to actually sort through. Before all this, machines had to be explicitly programmed to accomplish a specific task. Now, however, computers can learn to find patterns, and perhaps act on them, without such programming. The more data, the more precise machine learning can be.

Current examples of machine learning

Unless you are a complete luddite, machine learning has already entered folds of your life. Choosing a Netflix title based on prompted recommendations? Browsing similar titles for your Kindle based on the book you just finished? These recommendations are actually tailor-made for you. (In the recent past, they relied on an elementary version of “if you liked x, you may like y”, culled from a list that was put together manually.)

Today, companies have developed proprietary algorithms that machine learnings train, or look for patterns, on, using your data combined with the data of millions of other customers. This is why your Netflix may be chock full of action flicks and superhero movies and your partner’s queue leans heavily on crime drama and period pieces.

But machine learning is doing more than just serving up entertainment. Credit companies and banks are getting more sophisticated with credit scores. Traditionally, credit companies relied on a long-established pattern of credit history, debt and loan amounts, and timely payments. This meant if you weren’t able to pay off a loan from over a decade ago, even if you’re all paid up now, your credit score likely still reflects that story. This made it very difficult to change your credit score over time – in fact, time often felt like the only way to improve your credit score.

Now, however, machine learning is changing how credit bureaus like Equifax determine your score. Instead of looking at your past payments, data from the very near past – like, the last few months – can actually better predict what you may do in the future. Data analysis from machine learning means that history doesn’t decide; data can predict your credit-worthiness based on current trends.

What the future holds for machine learning

Machine learning is just getting started. When we think of the future for machine learning, an example we also hear about are those elusive self-driving cars, also known as autonomous vehicles.

In this case, machine learning is able to understand how to respond to particular traffic situations based on reviewing millions of examples: videos of car crashes compared to accident-free traffic, how human-driven cars respond to traffic signs or signals, and watching how, where, and when pedestrians cross streets.

Machine learning is beginning to affect how we see images and videos – computers are using neural networks to cull thousands of images from the internet to fill in blanks in your own pictures.

Take, for instance, the photo you snapped on your holiday in London. You have a perfect shot of Big Ben, except for a pesky pedestrian sneaking by along a wall. You are able to remove the person from your image, but you may wonder how to fill the space on the wall that walker left behind. Adobe Photoshop and other image editors rely on an almost-standard API to cull other images of walls (that specific wall, perhaps, as well as other walls that look similar) and randomize it so that it looks natural and organic.

 

This type of machine learning is advancing rapidly and it could soon be as easy as an app on our phones. Imagine how this can affect the veracity of a video – is the person actually doing what the video shows?

Problems with machine learning

We are at a pivotal point where we can see a lot of potential for machine learning, but we can also see a lot of potential problems. Solutions are harder to grasp as the technology forges forward.

The future of machine learning is inevitable; the question is more when? Predictions indicate that nearly every kind of AI will include machine learning, no matter the size or use. Plus, as cloud computing grows and the world amasses infinite data, machines will be able to learn continuously, on limitless data, instead of on specific data sets. Once connected to the internet, there is a constant stream of emerging information and content.

This future comes with challenges. First, hardware vendors will necessarily have to make their computers and servers stronger and speedier to cope with these increased demands.

As for experts in AI, it seems there will be a steep and sudden shortage in the professional manpower who can cope with what AI will be able to day. Behind the private and pricey walls of Amazon, Google, Apple, Uber, and Facebook, most small- and medium-sized businesses (SMBs) actually aren’t stepping more than a toe or two into the world of machine learning. While this is due in part to a lack of money or resources, the lack of expert knowledge is actually the biggest reason that SMBs aren’t deeper into ML. But, as ML technologies normalize, they’ll cost less and become a lot more accessible. If your company doesn’t have experts who knows how you could be using ML to help your business, you’re missing out.

On a global level, machine learning provides some cause for concern. There’s the idea that we’ll all be replaced in our jobs by specific machines or robots – which may or may not come to fruition.

More immediately and troubling, however, is the idea that imaging can be faked. This trick is certainly impressive for an amateur photographer, but it begs an important question: how much longer can we truly believe everything that we see? Perhaps seeing is believing has a limited window as a standard truthbearer in our society.