SlideShare a Scribd company logo
Embracing the modern web using
Drupal as Headless CMS
with GatsbyJS
by Jesus Manuel Olivas / weKnow
$ whoami
Jesus Manuel Olivas
jmolivas@weknowinc.com
twitter.com/jmolivas
github.com/jmolivas
drupal.org/u/jmolivas
jmolivas.weknowinc.com
weAre
101 Web Development
Embracing the modern web using Drupal as a Headless CMS with Gatsby BADCamp
Traditional Monolithic CMS
The Traditional Headless
+
Visitor Server CMS Database
Challenges
Performance Reliability Security Hosting
Is there anything else we can use?
Static Site Generators
Back to the flat-files
Visitor CDN
The JAMStack Stack
Challenges
• Web Forms (CRM Integration , Serverless
Function, Form submission PaaS)
• E-Commerce (Shopify, Salsify, PXM,
Headless Commerce, Stripe, Paypal, Recurly)
• Comments (Disqus, Serverless functions)
A GUI providing a WYSIWYG to
enter content and create a content
model
Decoupling the
"Content Management System"
from the
“Production Environment".
●
Git Based / Headless CMS
●
CloudCannon
NetlifyCMS
Forestry
Blaze
Sanity
Drupal
Contentful
Gatsby is a free and open source
framework based on React that
helps developers build blazing
fast websites and apps
Embracing the modern web using Drupal as a Headless CMS with Gatsby BADCamp
The Content Mesh
● https://www.gatsbyjs.org/blog/2018-10-18-creating-compelling-content-experiences/
https://github.com/weknowinc/drupal-boina
https://github.com/weknowinc/gatsby-starter-drupal-boina
How to Start?
https://boina.weknowinc.com/
http://drupal-boina.weknowinc.com/
Must have Gatsby plugins
• gatsby-source-drupal
• gatsby-transformer-remark
• gatsby-remark-drupal (support drupal images)
• gatsby-remark-images
• gatsby-remark-external-links
• gatsby-plugin-sharp
• gatsby-plugin-react-helmet
JSON:API
TUI Editor (WYSIWYG for markdown)
Build Hooks (Trigger a external build hook)
Gatsby Live Preview
https://weknowinc.com/blog/drupal-and-gatsby-live-preview
What to keep using
• Data modeling.
• Content editor capabilities,
revisions, moderation and
scheduling.
• Pathauto
• Site Settings
• Twig
• Render array
• Theme layer
• Theme preprocessing
• Views (use GraphQL instead)
What is Gone
Embracing the modern web using Drupal as a Headless CMS with Gatsby BADCamp
●●
Feel free to turn off your Drupal site after build
●https://twitter.com/ckaotik/status/647020262001614848
Code or didn't happen
Embracing the modern web using Drupal as a Headless CMS with Gatsby BADCamp
Embracing the modern web using Drupal as a Headless CMS with Gatsby BADCamp
Source Data
Gatsby Source Drupal
    {
      resolve: 'gatsby-source-drupal',
      options: {
        baseUrl: `${process.env.DRUPAL_HOST}`,
        apiBase: `api`,
        preview: true,
      },
    },
Gatsby Source Airtable
{
  resolve: `gatsby-source-airtable`,
  options: {
    apiKey: process.env.AIRTABLE_API_KEY,
    tables: [
      {
        baseId: `appVUfH5DCWgBSBH1`,
        tableName: `Statistics`,
        mapping: { 
          icon: `fileNode`,
        }
      },
      {
        baseId: `appVUfH5DCWgBSBH1`,
        tableName: `Events`,
      },
      {
        baseId: `appVUfH5DCWgBSBH1`,
        tableName: `Presentations`,
        tableLinks: [`event`],
      },
    ]
  }
},
Custom Source API
exports.sourceNodes = async ({ actions }) => {
  const {createNode} = actions;
  const items = await axios.get(`https://YOUR-API-ENDPOINT-URI`);
  for (const item of items.data) {
      await createNode({
        children: [],
        ...item,
        parent: null,
        internal: {
          type: 'Items',
          contentDigest: crypto
            .createHash(`md5`)
            .update(JSON.stringify(item))
            .digest(`hex`),
        }
    })
  }
};
Create Pages
Create Pages 1/2
exports.createPages = ({ graphql, actions }) => {
  const { createPage } = actions
  return graphql(`
    {
      allNodeLanding(filter: {path: {alias: {ne: "/homepage"}}}) {
        edges {
          node {
            path {
              alias
            }
          }
        }
      }
    }
  `)
Create Pages 2/2
.then(result => {
    if (result.errors) {
      throw result.errors
    }
    const landings = result.data.allNodeLanding.edges
    landings.forEach(landing => {
      createPage({
        path: landing.node.path.alias,
        component: path.resolve(`./src/templates/landing.js`),
        context: {
          slug: landing.node.path.alias,
        },
      })
    })
  })
Create GraphQL Fragments
Paragraphs as GraphQL Fragments
import { graphql } from 'gatsby';
export const ParagraphCtaFragment = graphql`
  fragment ParagraphCtaFragment on paragraph__cta {    
    __typename
    field_cta_link {
      alias
    }
    field_download
    field_is_animated
    field_cta_size
    field_bg_color
    field_text {
      processed
    }
  }
`
Paragraphs as GraphQL Fragments
import { graphql } from 'gatsby';
export const ParagraphHeroFragment = graphql`
  fragment ParagraphHeroFragment on paragraph__hero {
    __typename
    field_title {
      processed
    }
    relationships {
      field_background_image {
        relationships {
          field_media_image {
            localFile {
              childImageSharp {
                fluid(maxWidth: 1440, maxHeight: 560, cropFocus: CENTER) {
                  ...GatsbyImageSharpFluid
                }
              }
            }
          }
        }
      }
    }
  }
`
Paragraphs as GraphQL Fragments
import { graphql } from 'gatsby';
export const ParagraphJSXComponentFragment = graphql`
  fragment ParagraphJSXComponentFragment on paragraph__jsx_component {    
    __typename
    field_component
    field_text {
      processed
    }
    field_title {
      processed
    }
  }
`
Use GraphQL Fragments
GraphQL queries using Fragments
query landingBySlug($slug: String!) {
    landing: nodeLanding(path: {alias: {eq: $slug}}) {
          title
      relationships {
        field_components {
          ...ParagraphHeroFragment
          ...ParagraphJSXComponentFragment
          ...ParagraphGridCardFragment
          ...ParagraphTextContentFragment
          ...ParagraphPartnersFragment
          ...ParagraphCtaFragment
        }
      }
}

}`
Render React Components
Render Components
import { componentResolver } from '../utils'
  const field_components = componentResolver(landing.relationships.field_components);
  return (
    <Layout>
      <SEO
        title={}
        keywords={[]}
      />
      {field_components && (
          field_components.map((item, i) => {
            return (
              <React.Fragment key={i}>
                {item}
              </React.Fragment>
            )
          })
      )}
    </Layout>
  );
Map Data to Components
Resolve Components 1/3
import TitleHero from ‘../components/title-hero';
import Cta from ‘../components/cta’;
import StatsBlocks from '../components/stats-blocks'
import StatsEventsBlocks from '../components/stats-events-blocks'
import TeamAdmin  from '../components/team-admin'
import AnimatedWordsHero  from '../components/animated-words-hero'
import Presentations from '../components/presentations';
const JSXComponents = {
  StatsBlocks: (props) => (<StatsBlocks {...props} />),
  TeamAdmin: (props) => (<TeamAdmin {...props} />),
  StatsEventsBlocks: (props) => (<StatsEventsBlocks {...props} />),
  AnimatedWordsHero: (props) => (<AnimatedWordsHero {...props} />),

Presentations: (props) => (<Presentations {...props} />),
}
Resolve Components 2/3
export const componentResolver = (data) => {
   const components = [];
   data.forEach(element => {
   if (element.__typename === `paragraph__hero`) {
     const title = element.field_title ? element.field_title.processed : ``;
     const field_image = element.relationships.field_image.relationships;
const image = field_image.field_media_image.localFile.childImageSharp.fluid;
      components.push(<TitleHero title={title} image={image} />);
    }
. . .
Resolve Components 3/3
. . .
   if (element.__typename === `paragraph__jsx_component`) {
      const Component = JSXComponents[element.field_component];
      const title = element.field_title ? element.field_title.processed : '';
      const text = element.field_text ? element.field_text.processed : '';
      
components.push(<Component title={title} text={text} />);
    }
  })
  return components;
}
Thank you
Feel free ask here and via twitter @jmolivas

More Related Content

PDF
Embracing the modern web using Drupal as Headless CMS with GatsbyJS NYC
PDF
Building Responsive Websites with the Bootstrap 3 Framework
PDF
How to keep Drupal relevant in the Git-based and API-driven CMS era DrupalCampNJ
PDF
How to keep Drupal relevant in the Git-based and API-driven CMS era Florida
PDF
Embracing the modern web using a Headless CMS with GatsbyJS CMS Philly
PDF
Embracing the modern web using a Headless CMS with GatsbyJS Stanford
PDF
How to keep Drupal relevant in the Git-based and API-driven CMS era - BADCamp
PDF
Drupal South 2018 -  How to keep Drupal relevant in the Git-based and API-dri...
Embracing the modern web using Drupal as Headless CMS with GatsbyJS NYC
Building Responsive Websites with the Bootstrap 3 Framework
How to keep Drupal relevant in the Git-based and API-driven CMS era DrupalCampNJ
How to keep Drupal relevant in the Git-based and API-driven CMS era Florida
Embracing the modern web using a Headless CMS with GatsbyJS CMS Philly
Embracing the modern web using a Headless CMS with GatsbyJS Stanford
How to keep Drupal relevant in the Git-based and API-driven CMS era - BADCamp
Drupal South 2018 -  How to keep Drupal relevant in the Git-based and API-dri...

More from Jesus Manuel Olivas (18)

PDF
Remix & GraphQL: A match made in heaven with type-safety DX
PDF
Drupal 10 Party GraphQL
PDF
How to use Drupal to create editorial experiences your content creators will...
PDF
Beyond Static: Building a Dynamic Application with Gatsby
PDF
Drupal, GraphQL, Views, View Modes and Gatsby for a US Gov site CMS Philly
PDF
Building a modern application using Symfony API Platform and GatsbyJS PHP QRO
PDF
Building a dynamic application with GatsbyJS-Tec-Mexicali
PDF
Building a modern web application in the cloud partnercon
PDF
Blazing fast sites using Blaze, Hybrid CMS NYC
PDF
Writing a slack chatbot seattle
PDF
Building a Modern Web Application in the Cloud TecNerd
PDF
Tools and Projects Dec 2018 Edition
PDF
Creating a modern web application using Symfony API Platform Atlanta
PDF
Battle of the CMS DrupalCampLA
PDF
Creating a modern web application using Symfony API Platform, ReactJS and Red...
PDF
Writing a slack chatbot DrupalCampLA
PDF
Improving your Drupal 8 development workflow DrupalCampLA
PDF
Writing a slack chatbot mxlos
Remix & GraphQL: A match made in heaven with type-safety DX
Drupal 10 Party GraphQL
How to use Drupal to create editorial experiences your content creators will...
Beyond Static: Building a Dynamic Application with Gatsby
Drupal, GraphQL, Views, View Modes and Gatsby for a US Gov site CMS Philly
Building a modern application using Symfony API Platform and GatsbyJS PHP QRO
Building a dynamic application with GatsbyJS-Tec-Mexicali
Building a modern web application in the cloud partnercon
Blazing fast sites using Blaze, Hybrid CMS NYC
Writing a slack chatbot seattle
Building a Modern Web Application in the Cloud TecNerd
Tools and Projects Dec 2018 Edition
Creating a modern web application using Symfony API Platform Atlanta
Battle of the CMS DrupalCampLA
Creating a modern web application using Symfony API Platform, ReactJS and Red...
Writing a slack chatbot DrupalCampLA
Improving your Drupal 8 development workflow DrupalCampLA
Writing a slack chatbot mxlos
Ad

Recently uploaded (20)

PPTX
FINAL REVIEW FOR COPD DIANOSIS FOR PULMONARY DISEASE.pptx
PDF
PRIZ Academy - 9 Windows Thinking Where to Invest Today to Win Tomorrow.pdf
PPTX
UNIT-1 - COAL BASED THERMAL POWER PLANTS
PPTX
bas. eng. economics group 4 presentation 1.pptx
PDF
Structs to JSON How Go Powers REST APIs.pdf
PDF
Operating System & Kernel Study Guide-1 - converted.pdf
PPTX
CH1 Production IntroductoryConcepts.pptx
PDF
Queuing formulas to evaluate throughputs and servers
PPTX
Fluid Mechanics, Module 3: Basics of Fluid Mechanics
PPTX
Practice Questions on recent development part 1.pptx
PPT
Drone Technology Electronics components_1
PPTX
Engineering Ethics, Safety and Environment [Autosaved] (1).pptx
PPTX
“Next-Gen AI: Trends Reshaping Our World”
PPTX
Unit 5 BSP.pptxytrrftyyydfyujfttyczcgvcd
PPTX
Internship_Presentation_Final engineering.pptx
PDF
Arduino robotics embedded978-1-4302-3184-4.pdf
PDF
algorithms-16-00088-v2hghjjnjnhhhnnjhj.pdf
PPTX
Simulation of electric circuit laws using tinkercad.pptx
FINAL REVIEW FOR COPD DIANOSIS FOR PULMONARY DISEASE.pptx
PRIZ Academy - 9 Windows Thinking Where to Invest Today to Win Tomorrow.pdf
UNIT-1 - COAL BASED THERMAL POWER PLANTS
bas. eng. economics group 4 presentation 1.pptx
Structs to JSON How Go Powers REST APIs.pdf
Operating System & Kernel Study Guide-1 - converted.pdf
CH1 Production IntroductoryConcepts.pptx
Queuing formulas to evaluate throughputs and servers
Fluid Mechanics, Module 3: Basics of Fluid Mechanics
Practice Questions on recent development part 1.pptx
Drone Technology Electronics components_1
Engineering Ethics, Safety and Environment [Autosaved] (1).pptx
“Next-Gen AI: Trends Reshaping Our World”
Unit 5 BSP.pptxytrrftyyydfyujfttyczcgvcd
Internship_Presentation_Final engineering.pptx
Arduino robotics embedded978-1-4302-3184-4.pdf
algorithms-16-00088-v2hghjjnjnhhhnnjhj.pdf
Simulation of electric circuit laws using tinkercad.pptx
Ad

Embracing the modern web using Drupal as a Headless CMS with Gatsby BADCamp