diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000000..dfa967bce0359 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +node_modules +**/node_modules +**/public +npm-debug.log +.git \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index e6bb7c9006d04..9bef255173e42 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -6,6 +6,7 @@ Useful Links: - Documentation: https://www.gatsbyjs.org/docs/ - How to Contribute: https://www.gatsbyjs.org/docs/how-to-contribute/ + - How to File an Issue: https://www.gatsbyjs.org/docs/how-to-file-an-issue/ - Become a Sponsor: https://opencollective.com/gatsby#sponsor Before opening a new issue, please search existing issues (https://github.com/gatsbyjs/gatsby/issues) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 641ed5dc302fd..7c9ca34a40614 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,15 +2,6 @@ title: How to contribute --- -## Filing an issue - -If you want your issue to be resolved quickly, please include in your issue: - -* Gatsby version, node.js version, OS version -* The contents of your `gatsby-config.js` and `package.json` as well as your - `gatsby-node.js`, `gatsby-browser.js` `gatsby-ssr.js` files depending on - changes you've made there. - ## Contributing We want contributing to Gatsby to be fun, enjoyable, and educational for anyone and everyone. Contributions go far beyond pull requests and commits; we are thrilled to receive a variety of other contributions including the following: @@ -21,7 +12,8 @@ We want contributing to Gatsby to be fun, enjoyable, and educational for anyone * Submitting documentation updates, enhancements, designs, or bugfixes * Submitting spelling or grammar fixes * Adding unit or functional tests -* Triaging GitHub issues -- especially determining whether an issue still persists or is reproducible +* Triaging [GitHub issues](https://github.com/gatsbyjs/gatsby/issues) -- especially determining whether an issue still persists or is reproducible +* [Reporting bugs or issues](/docs/how-to-file-an-issue/) * Searching for Gatsby on Discord or Spectrum and helping someone else who needs help * Teaching others how to contribute to Gatsby's repo! @@ -29,16 +21,6 @@ If you are worried or don't know where to start, you can always reach out to Sha Looking to speak about Gatsby? We'd love to review your talk abstract/CFP! You can email it to shannon [at] gatsbyjs [dot] com and we can give pointers or tips!!! -### Special Note on Issues - -If an issue is affecting you, start at the top of this list and complete as many tasks on the list as you can: - -1. If there is an issue, +1 the issue to indicate that it's affecting you -2. If there's an issue and you can add more detail, write a comment describing how the bug is affecting OR if you can, write up a work-around for the bug -3. If there's not an issue, write the most complete description of what's happening, preferably with link to a Gatsby site that reproduces the problem -4. Offer to help fix the bug (and it's totally expected that you ask for help; open-source maintainers want to help contributors) -5. Deliver a well-crafted, tested PR - ### Creating your own plugins and loaders If you create a loader or plugin, we would <3 for you to open source it, and put it on npm. @@ -62,9 +44,7 @@ The usual contributing steps are: * setup up repo and Install dependencies: `yarn run bootstrap` * Make sure tests are passing for you: `yarn test` * Create a topic branch: `git checkout -b topics/new-feature-name` -* Run `npm run watch` from the root of the repo to first do an initial Babel - build of all packages and then watch for changes to packages' source code and - compile these changes on-the-fly as you work. +* Run `npm run watch` from the root of the repo to watch for changes to packages' source code and compile these changes on-the-fly as you work. Note that the watch command can be resource intensive. To limit it to the packages you're working on, add a scope flag, like `npm run watch -- --scope={gatsby,gatsby-cli}`. To watch just one package, run `npm run watch -- --scope=gatsby`. * Install [gatsby-dev-cli](/packages/gatsby-dev-cli/) globally: `yarn global add gatsby-dev-cli` * Run `yarn install` in each of the sites you're testing with. * For each of your Gatsby test sites, run the `gatsby-dev` command there to copy @@ -78,7 +58,7 @@ The usual contributing steps are: ### Contributing to the documentation. -Gatsby, unsurprisingly, uses Gatsby for it's documentation website. +Gatsby, unsurprisingly, uses Gatsby for its documentation website. If you want to add/modify any Gatsby documentation, go to the [docs folder on Github](https://github.com/gatsbyjs/gatsby/tree/master/docs) and diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000000..b5e28c88503e2 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,27 @@ +# Create a standalone instance of GraphiQL populated with gatsbyjs.org's data +# --- +# libvips needed for image manipulation +FROM marcbachmann/libvips:8.4.1 as build + +# Node.js version 8 and build tools for sharp +RUN apt-get update && apt-get install -y build-essential g++ curl +RUN curl -sL https://deb.nodesource.com/setup_8.x | bash - && apt-get install -y nodejs && rm -rf /var/lib/apt/lists/* + +RUN npm install -g yarn@1.3.2 + +WORKDIR /usr/src/app + +COPY . . +RUN yarn && cd www && yarn +RUN cd www && yarn run build + +# Start again and just copy across the built files (+ node_modules) +# TODO: Can we do this all on Alpine for a much smaller image? This node:8 image is ~600MB +FROM node:8 as dist + +COPY --from=build /usr/src/app /usr/src/app +WORKDIR /usr/src/app + +# To run this image, set the port as an env var with `-e PORT=xxxx` e.g. +# docker run -p 8080:8080 --rm -it -e PORT=8080 / +CMD [ "node","./scripts/www-data-explorer.js" ] \ No newline at end of file diff --git a/README.md b/README.md index 8ead088e9c462..1171790fc1954 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ Websites built with Gatsby: * [Sourcegraph](https://about.sourcegraph.com) * [Simply](https://simply.co.za) * [The freeCodeCamp Guide](https://guide.freecodecamp.org) + ([source](https://github.com/freeCodeCamp/guides)) * [FloydHub's Blog](https://blog.floydhub.com) * [mParticle's Documentation](https://docs.mparticle.com) * [Segment's Blog](https://segment.com/blog/) @@ -31,6 +32,8 @@ Websites built with Gatsby: ([source](https://github.com/reasonml/reasonml.github.io)) * [Bricolage.io](https://www.bricolage.io/) ([source](https://github.com/KyleAMathews/blog)) +* [Hack Club](https://hackclub.com/) + ([source](https://github.com/hackclub/site)) * [Jamie Henson's Blog](http://jamiehenson.com/) ([source](https://github.com/jamiehenson/jh47-gatsby)) * [Sean Coker's Blog](https://sean.is/) @@ -144,6 +147,18 @@ Websites built with Gatsby: * [several levels](https://severallevels.io/) ([source](https://github.com/Harrison1/several-levels)) * [Flooring Factories Outlets](https://www.flooringfactoriesoutlets.com/) * [Nortcast](https://nortcast.com/) +* [VisitGemer](https://visitgemer.sk/) +* [Nexit](https://nexit.sk/) +* [ERC dEX](https://ercdex.com) +* [iContract Blog](https://blog.icontract.co.uk) +* [Dona Rita](https://donarita.co.uk) ([source](https://github.com/peduarte/dona-rita-website)) +* [Andy Slezak](https://www.aslezak.com) ([source](https://github.com/amslezak)) +* [Odayaka](http://odayaka.net) ([source](https://github.com/odayakanaasa/odayaka)) +* [Ventura Digitalagentur Köln](https://www.ventura-digital.de) +* [Cardiogram](https://cardiogr.am/) +* [LaserTime Clinic](https://lasertime.ru) ([source](https://github.com/oleglegun/lasertime)) +* [Gatsby Manor - themes for GatsbyJS](https://gatsbymanor.com) +* [Darren Britton's Portfolio](https://darrenbritton.com) ([source](https://github.com/darrenbritton/darrenbritton.github.io)) ## Docs diff --git a/docs/blog/2017-09-18-gatsby-modern-static-generation/index.md b/docs/blog/2017-09-18-gatsby-modern-static-generation/index.md index 7320c8c980dfd..a297523dca252 100644 --- a/docs/blog/2017-09-18-gatsby-modern-static-generation/index.md +++ b/docs/blog/2017-09-18-gatsby-modern-static-generation/index.md @@ -20,7 +20,7 @@ production by creating a landing page very fast. Static site generators like Jekyll all work pretty similarly: -* Describe your content in some common templating language ([Pug](pugjs.org), +* Describe your content in some common templating language ([Pug](http://pugjs.org), [Handlebars](http://handlebarsjs.com), etc) * While in development, start a local web server and add file "watchers" that will listen for content changes and re-render the site diff --git a/docs/blog/2018-02-09-announcing-gatsby-manor-themes-for-gatsbyjs/gatsbymanor.jpg b/docs/blog/2018-02-09-announcing-gatsby-manor-themes-for-gatsbyjs/gatsbymanor.jpg new file mode 100644 index 0000000000000..83a1c25d5a27f Binary files /dev/null and b/docs/blog/2018-02-09-announcing-gatsby-manor-themes-for-gatsbyjs/gatsbymanor.jpg differ diff --git a/docs/blog/2018-02-09-announcing-gatsby-manor-themes-for-gatsbyjs/index.md b/docs/blog/2018-02-09-announcing-gatsby-manor-themes-for-gatsbyjs/index.md new file mode 100644 index 0000000000000..fe9399ae05039 --- /dev/null +++ b/docs/blog/2018-02-09-announcing-gatsby-manor-themes-for-gatsbyjs/index.md @@ -0,0 +1,88 @@ +--- +title: Announcing Gatsby Manor, themes for Gatsby 🎉🎊 +date: "2018-02-09" +image: "gatsbymanor.jpg" +author: "Steven Natera" +--- + +I am proud to announce [Gatsby Manor](https://www.gatsbymanor.com/), a gallery +of themes for [Gatsby](https://www.Gatsby.org/). After 5 months of +development, Gatsby Manor is now in public beta. Check out our +[themes](https://www.gatsbymanor.com/themes) then use our [getting started](https://www.gatsbymanor.com/docs/quick-start/getting-started) guide to +kickstart your Gatsby project. + +## Overview + +Gatsby Manor is built on top of Gatsby to provide a painless way of building +websites with reusable React components we call themes. We even have a +cleverly named npm module for theme management called +[Jay](https://github.com/gatsbymanor/gatsby-jay) 😄. + +With Jay you can download a theme from our collection, and mount it as a default +theme. Styles are applied instantly without server restarts or additional lines +of code. Because of React, interactivity is supported out of the box. + +Want to switch themes? No problem. Jay can archive themes for later use in a +themes folder in your local directory. Edit and swap themes as often as you want +and Jay will manage the process. Want to learn more? Read our +[docs](https://www.gatsbymanor.com/docs/cli/)! + +## How it all started + +The idea began when I decided to update my personal website. I wanted a way to +rebuild my website with ease however the approaches were less than exciting. + +Building a new site myself would require a lot of time. My imagination often +runs wild when it comes to web design and what is supposed take a day of work +turns into weeks of site iterations. The joys of web development often causes me +to over-engineer simple websites. Not to mention that building a development +environment alone is the biggest requirement when starting from scratch. +Therefore another option needed to be explored. + +[Wordpress](https://wordpress.org/) would be the fastest solution to build a +website but I wanted to be able to rapidly prototype on customs themes. +Unfortunately, understanding the architecture to develop themes on this stack +would require additional time. Not to mention I dislike PHP (#sorryNotSorry 😅) +therefore this option was a clear loser. I tried [Hugo](https://gohugo.io/) and +[Jekyll](https://jekyllrb.com/). They gave me the right mix of speed and +control. But their templating languages were unappealing as long term options. + +When I stumbled onto Gatsby, I found the golden goose. I already worked with +React before, therefore I could prototype rapidly. The development environment +gave me a tight feedback loop out of the box. And I had all the control in the +world for enhanced interactive features. + +## The development process + +Once settled on Gatsby, I started working on my personal website. Within 2 +hours I wanted to prototype with different design elements because I found +inspiration from [html5up](https://html5up.net/) templates. However I did not +want to discard my work so far. + +I decided to make a new directory to store my outdated work, like a true digital +hoarder. A few more hours passed and I found myself yarning for +my original design choice because the new design was too complex. I knew this +situation would occur again (sometimes I can be indecisive 😅) so I decided to build +a small cli tool to switch between themes easily. But first I needed a name, and +Jay seemed the most clever since I was working with Gatsby. + +As I was debugging code one day, I stumbled onto a feature request for a +[theme system](https://github.com/gatsbyjs/gatsby/issues/2662). At that moment, +I decided I was going to build a theme solution for the community. Five +months later, Gatsby Manor was born. + +## Final notes + +Gatsby Manor is in public beta until we reach v1. There are plenty of +[Github](https://github.com/gatsbymanor) contributions to go around. To get +started, try out a Gatsby Manor theme using our tutorial on [getting started](https://www.gatsbymanor.com/docs/quick-start/getting-started). Open an +issue if you see an area of improvement. Follow and send us positive vibes on +Twitter using [@TheGatsbyManor](https://twitter.com/TheGatsbyManor). + +TL;DR [Gatsby Manor](https://www.gatsbymanor.com/) is a place to get themes for +your Gatsby project. Use our [getting started](https://www.gatsbymanor.com/docs/quick-start/getting-started) tutorial to use +a [theme](https://www.gatsbymanor.com/themes) in your Gatsby project today. + +Cheers! 🎉🎊 + +[@StevenNatera](https://twitter.com/stevennatera). diff --git a/docs/blog/2018-1-25-building-a-site-with-react-and-contentful/React-logo.png b/docs/blog/2018-1-25-building-a-site-with-react-and-contentful/React-logo.png new file mode 100644 index 0000000000000..352ab65fe4e5b Binary files /dev/null and b/docs/blog/2018-1-25-building-a-site-with-react-and-contentful/React-logo.png differ diff --git a/docs/blog/2018-1-25-building-a-site-with-react-and-contentful/contentful-logo.png b/docs/blog/2018-1-25-building-a-site-with-react-and-contentful/contentful-logo.png new file mode 100644 index 0000000000000..d564cb9e2d241 Binary files /dev/null and b/docs/blog/2018-1-25-building-a-site-with-react-and-contentful/contentful-logo.png differ diff --git a/docs/blog/2018-1-25-building-a-site-with-react-and-contentful/index.md b/docs/blog/2018-1-25-building-a-site-with-react-and-contentful/index.md index 7a121910197c9..1db286400f9c3 100644 --- a/docs/blog/2018-1-25-building-a-site-with-react-and-contentful/index.md +++ b/docs/blog/2018-1-25-building-a-site-with-react-and-contentful/index.md @@ -4,21 +4,21 @@ date: "2018-01-25" author: "Shannon Soper" --- -A poster of _Starry Night_ by Vincent Van Gogh followed me to each new dorm room in college because I bought it the first year and kept it until it ripped beyond repair. +A poster of _Starry Night_ by Vincent Van Gogh followed me to each new dorm room in college until it ripped beyond repair. I loved that poster. -My sister (a professional artist) and I often debate the merits and demerits of reprinting great works of art, like Van Gogh’s masterpiece. +My poster of _Starry Night_ often led to debates with my sister (a professional artist) about the merits and demerits of reprinting great works of art. -As much as I revere the original, I also love the fact that printing technology makes it easy to put _Starry Night_ on tote bags, coffee mugs, posters, t-shirts, and more because it became more accessible to a wide range of people (without advanced printers and computers, the original painting could only be shared with more people through painstaking replication via the original medium: oil painting on a canvas). +As much as I revere the original, I also love that printing technology can put _Starry Night_ on tote bags, coffee mugs, posters, t-shirts, and more. Technology has made great art accessible to a wide range of people (without advanced printers and computers, original paintings can only be shared with people through painstaking replication via the original medium: oil painting on a canvas). ![Starry Night painting by Vincent Van Gogh](starry-night.jpeg) -For the same reason, I’m also loving building a website with React and Contentful; together they allow things like images and text to easily appear in various formats across multiple platforms. +For the same reason that I love seeing _Starry Night_ on a poster, I loved building a website with React and Contentful; together, they allow images and text to easily appear in various formats across multiple platforms. It’s much faster and easier to resize and reuse the content you already have when you don’t have to painstakingly re-create for mobile, for web, etc. You basically just print it, again, and again, and again, in small and large and medium formats, in websites, mobile apps, multiple languages. Just...push a button on a printer to make copies. Easy, right? Well, easy if you already know React, at least. I wanted to make little site about my dog, Watson, yet didn’t know how to code. -Sometimes a friend or family member babysits him, and it is time-consuming to either write instructions or update and print new guides for babysitters since he learns new commands every day. A website seemed like a better way to manage this. +Sometimes a friend or family member babysits him, and it's time-consuming to either write instructions or update and print new guides for babysitters since he learns new commands every day. A website seemed like a better way to manage this. Here’s the site I built for my dog's babysitters after learning the basics of Contentful and React: http://watson.surge.sh/. Following are instructions on how you can also build a site with Contentful and React with tips I learned while building my site. @@ -26,17 +26,21 @@ Here’s the site I built for my dog's babysitters after learning the basics of ## What is React? Why choose it? +![React logo](React-logo.png) + React is a JavaScript library for building user interfaces. React helps developers and designers create composable UI components that painlessly adapt to data changes. ## What is Contentful? Why choose it? +![Contentful logo](contentful-logo.png) + Contentful is a headless Content Management System (CMS) that lets you organize your content into what could be called “modules,” or little bits of data that can be rearranged to appear nicely on mobile devices, tablets, computers, virtual reality devices (this is my own joke, but...maybe someday?) and more. -Actually, the way Contentful handles bits of content means that you can push content out when new technology develops without having to redesign and rewrite and rethink all of it for a new format. +Actually, the way Contentful handles bits of content means that you can push content out when new technology develops without having to redesign, rewrite, or rethink all of it for a new format. ## Pulling data in and pushing data out -If I’d had a JSON file with content in it, I could pull it into Contentful using [contentful-import](https://github.com/contentful/contentful-import), which I found out by chatting with a nice person in the Contentful chat window. Since I was creating new content, I didn’t need this and just created content straight in Contentful. For the first minute or so, I couldn’t figure out what a “content model” could or should look like. Luckily, the free trial offers a sample project that I opened and after looking around it for a couple minutes, I was good to go. +If you have a JSON file with content in it, you could pull it into Contentful using [contentful-import](https://github.com/contentful/contentful-import), which I found out by chatting with a nice person in the Contentful chat window. Since I was creating new content, I didn’t need this and just created content straight in Contentful. For the first minute or so, I couldn’t figure out what a “content model” could or should look like. Luckily, the free trial offers a sample project that I opened and after looking around it for a couple minutes, I was good to go. ![Creating a content type](creating-content-type.png) @@ -99,15 +103,15 @@ Here’s an instance of a GraphiQL query that worked in there but not in the act } ``` +## Making data look nice on the site + Once I got my GraphQL queries working, I called a couple friends for help rendering the data to each page on my site. They called this “printing,” a word that I enjoyed because it reminded me of the Vincent Van Gogh poster I had. -Basically, I had to create an object that could be referenced later, get stuff to appear in console so I could troubleshoot problems, and then just use the GraphQL query structure to drill down into the actual content I wanted to render on each page. Then I wrapped this all in some _light_ HTML formatting. Here's what it looks like on my site: +Here is one of the first pages I rendered into a table format: ![What the finished daily schedule looks like on my site](daily-schedule-finished.png) -Here are more examples of pages I created. The code from the photo gallery page shows that I import React at the top, then I tell it to export data from Contentful by using the hierarchy in the GraphQL query. - -In the middle, the code shows how I’m using JS to also pull bits of data in to be rendered using the structure of the GraphQL query: +Here are more examples of pages I created. This is the photo gallery page: ```jsx import React from "react"; @@ -157,9 +161,11 @@ query PhotoQuery { }`; ``` -A more complex page included the list of Tricks & Commands, because not all entries on Contentful included the same content. +## More complex pages + +The list of Tricks & Commands presented a complex challenge because not all entries on Contentful included the same content. For example, we got errors if we tried to query for a photo since some entires had photos and some did not. -Some had photos, and some did not. Because of this, my friends helped me figure out a way to use JS to make sure we only requested a photo to be printed IF there really was a photo. For any entries without a photo, the computer could forgive it (just this once). +Because each entry was inconsistent, my friends helped me figure out a way to use JS to make sure we only requested a photo to be printed IF the photo existed. And if a particular entry didn't have a photo, the computer could forgive it (just this once). Here is the code from that page: ```jsx import React from "react"; diff --git a/docs/blog/2018-2-3-sites-with-headless-cms/index.md b/docs/blog/2018-2-3-sites-with-headless-cms/index.md new file mode 100644 index 0000000000000..dc8da24b0a047 --- /dev/null +++ b/docs/blog/2018-2-3-sites-with-headless-cms/index.md @@ -0,0 +1,91 @@ +--- +title: Building Sites with Headless CMSs +date: "2018-02-03" +author: "Shannon Soper" +--- + +## What is a traditional CMS? + +A traditional Content Management System (CMS)--like Wordpress, Drupal, or Joomla--manages three things for a website: content, admin screens, and presentation layer. These three things are tightly integrated, which has advantages. For example, there’s only one system to learn / one vendor relationship, and overall, there may be fewer choices to make. In addition, traditional CMSs have been around for so long that many teams are familiar with them and many websites are already be running on them. Both advantages. + +You can think of a traditional CMS like an old home built by one person and with custom fittings. Gorgeous, and expensive to maintain, like the home in _The Money Pit_ (1986) with Tom Hanks and Shelley Long. + +![Tom Hanks on a staircase that is falling apart](money-pit-2.jpeg) + +Despite the advantages of this scenario, there are also some disadvantages which are listed below. + +### Slower load times AND expensive + +Most traditional CMSs can't run on [edge servers](https://www.cloudflare.com/learning/cdn/glossary/edge-server/) (servers running CDNs). This results in slower load times the farther away you live from the servers. For example, people often observe that US websites run slowly in Australia. This is not imaginary; when someone in Australia accesses a US site built with a traditional CMS, it has to be sent from far-away servers. + +### Hard to adapt content to new formats + +When content exists in a tight relationship with the presentation layer, adapting that content for new formats like smart watches, kiosks, and virtual reality can be challenging and expensive. + +## What is a headless CMS? + +> "A headless CMS does nothing but manage content. It doesn’t deliver content to humans at all. Rather, it +> 'delivers' content to an application of some type. Its immediate consumer is code, and it’s assumed that +> code will reformat the content for final delivery to a human." - Deane Barker + +To add to Deane Barker's eloquent explanation in the quote above (see his article [here](https://gadgetopia.com/post/9743)), a headless CMS only handles two things--content and managing that content through admin screens. This means that a separate presentation layer (or “head”) like GatsbyJS must reformat the content for delivery to a CDN and then final delivery to humans. + +_Note on how CMSs usually work:_ Most headless CMSs require you to create various structures for your content, typically called "content models", and then enter content into that structure. Content can include words, images, URLs, lists, etc. Then, outside of the CMS, you push this content through a presentation layer (GraphQL queries are one way to do this pushing). + +Following are some advantages to using a headless CMS. + +### Faster load times AND cheaper? + +With much less time (and therefore less money), you can set up a headless CMS with a presentation layer like GatsbyJS and a CDN and get your site running on edge servers. + +Besides being faster and therefore less expensive to set up, this method also produces faster load times for most sites. Let’s say a person in Australia accesses a US site built with a headless CMS and GatsbyJS; the site can run off of a closer server, so it will load quickly. This is an enormous advantage for both the user and for whomever created the site. + +Faster load times can be taken to the next level with sites that run offline. I recently chatted with a friend in New Delhi who used GatsbyJS to build his blog to run offline, which is an incredible advantage for commuters who want to read while on public transportation with spotty internet access. + +### Higher quality AND cheaper? + +The separation between a headless CMS and the presentation layer allows both to become highly specialized and efficient, similar to the food production system in the Jetson’s house: + +![The Jetson’s microwave shoots food at them and makes it so easy to eat!](the-jetsons.jpeg) + +When businesses specialize in one thing instead of several, they tend to become more time-efficient and can produce things at a lower cost. In human terms, this means that headless CMSs tend to cost you less than traditional CMSs, because they cost less up front or they take you less time to maintain. + +This specialization also means that headless CMSs perform well in scenarios in which a traditional CMS would prove inadequate. I’d like to point to Deane Barker’s [excellent article on use cases for headless CMSs](https://gadgetopia.com/post/9743), from which we've extracted a partial list: + +* You need to gather content from disparate places and pull it together into one platform +* You need to push content to various formats, including desktop sites, mobile sites, smart watches, ads, etc. +* Your developers dislike traditional CMSs, yet the editors and marketing folks prefer to add, edit, and delete content in a familiar editing environment +* You keep a traditional CMS and yet want to add a simpler/cheaper/more structured method for particular projects, types of content, or a specific group of editors +* All of the above! :) + +In all of these cases, a headless CMS is an excellent solution for you. + +## Which headless CMS should I choose? + +Whether or not you’re convinced that a headless CMS is a good idea, the next step would be to try some out for yourself. I found this handy site with a [list of headless CMSs to keep an eye on](https://headlesscms.org/about/). + +And here’s what I learned from testing several popular CMSs for five minutes each. (Background: I’m a writer and content editor who knows just enough about developing to get myself into major trouble :) + +### GraphCMS + +Their sleek design impressed me: the left hand side bar and onboarding process was quick and easy-to-understand. For example, I pretty much understand what web hooks are now, after 30 seconds of going through their tutorial. Very cool. Also, very excited to see their handy API explorer (built-in GraphiQL)! Not totally sure I get the concept called “enumerations” and the names for different kinds of permissions. The one called “create” was confusing because “create” is also a verb, so I expected something to happen when I clicked that button, but nothing happened. I suspect it is the name of one of the roles. + +### ButterCMS + +I've read that ButterCMS is particularly good for blogs, and after seeing how easy it is to add metadata and SEO title / metadescription to blog posts, it makes sense why this might be the case. Sometimes there were more clicks than necessary when saving things. And sometimes the jargon in this environment threw me off. Like “object”? What is that? It’s basically a category of content. So, if I’m going to create a lot of event descriptions, the event titles will be one object, the event description, another object, etc. It's an unfamiliar and abstract word for someone new to headless CMSs. + +### Built.io (Contentstack) + +I filled out a form to get a free trial and heard back a while later with some questions about the purpose of my trial site, when I expect to go live, where I work, etc. It felt like a bit too much information to provide for a free trial, so I didn’t respond. + +### Contentful + +I already built this site http://watson.surge.sh/ with Contentful and talk about that experience [here](/blog/2018-1-25-building-a-site-with-react-and-contentful/). Another thing I like about Contentful, which I didn't mention in the other article, is how smooth it is to toggle between content models (categories of content types). Their recent product update says you can add images inline in chunks of text, which makes the editing experience feel more like using a WYSIWYG. This seems like it would make things easy on the editing side, although I haven't explored if this would affect image presentation. + +### CloudCMS + +This system gives you lots of options when it comes to creating content. Maybe too many options. For example, the free trial account comes preloaded with a sample project. When I clicked on a sample book description, there was a list of about 12 hyperlinks and because of the sheer number of choices, and the fact that I'm unfamiliar with their terminology, I felt overwhelmed. Otherwise, this system has pixelated graphics and a workflow that was hard to navigate as an editor of content; it felt more like a series of rabbit holes instead of a flow. On the upside, some of the capabilities seem really useful, like a button that said "make it multilingual." Could it be that easy? + +## Conclusion + +I’d definitely choose a headless CMS over a traditional CMS if I had talented front-end developers, because they could choose their favorite framework for the presentation layer. That setup would give us the flexibility to switch delivery methods, presentation methods, and content management methods with agility. diff --git a/docs/blog/2018-2-3-sites-with-headless-cms/money-pit-2.jpeg b/docs/blog/2018-2-3-sites-with-headless-cms/money-pit-2.jpeg new file mode 100644 index 0000000000000..413bee9ec2507 Binary files /dev/null and b/docs/blog/2018-2-3-sites-with-headless-cms/money-pit-2.jpeg differ diff --git a/docs/blog/2018-2-3-sites-with-headless-cms/money-pit.jpeg b/docs/blog/2018-2-3-sites-with-headless-cms/money-pit.jpeg new file mode 100644 index 0000000000000..7fd4e2dad3e65 Binary files /dev/null and b/docs/blog/2018-2-3-sites-with-headless-cms/money-pit.jpeg differ diff --git a/docs/blog/2018-2-3-sites-with-headless-cms/the-jetsons.jpeg b/docs/blog/2018-2-3-sites-with-headless-cms/the-jetsons.jpeg new file mode 100644 index 0000000000000..9698b2c9bece6 Binary files /dev/null and b/docs/blog/2018-2-3-sites-with-headless-cms/the-jetsons.jpeg differ diff --git a/docs/blog/2018-2-6-choosing-a-back-end/contentful-fields.png b/docs/blog/2018-2-6-choosing-a-back-end/contentful-fields.png new file mode 100644 index 0000000000000..81ebcc5016684 Binary files /dev/null and b/docs/blog/2018-2-6-choosing-a-back-end/contentful-fields.png differ diff --git a/docs/blog/2018-2-6-choosing-a-back-end/contentful-page.png b/docs/blog/2018-2-6-choosing-a-back-end/contentful-page.png new file mode 100644 index 0000000000000..cb76707e9989a Binary files /dev/null and b/docs/blog/2018-2-6-choosing-a-back-end/contentful-page.png differ diff --git a/docs/blog/2018-2-6-choosing-a-back-end/contentful-pricing.png b/docs/blog/2018-2-6-choosing-a-back-end/contentful-pricing.png new file mode 100644 index 0000000000000..379454c08324c Binary files /dev/null and b/docs/blog/2018-2-6-choosing-a-back-end/contentful-pricing.png differ diff --git a/docs/blog/2018-2-6-choosing-a-back-end/contentful-project.png b/docs/blog/2018-2-6-choosing-a-back-end/contentful-project.png new file mode 100644 index 0000000000000..36a95338291aa Binary files /dev/null and b/docs/blog/2018-2-6-choosing-a-back-end/contentful-project.png differ diff --git a/docs/blog/2018-2-6-choosing-a-back-end/contentful.png b/docs/blog/2018-2-6-choosing-a-back-end/contentful.png new file mode 100644 index 0000000000000..192e589159e81 Binary files /dev/null and b/docs/blog/2018-2-6-choosing-a-back-end/contentful.png differ diff --git a/docs/blog/2018-2-6-choosing-a-back-end/gatsby.jpeg b/docs/blog/2018-2-6-choosing-a-back-end/gatsby.jpeg new file mode 100644 index 0000000000000..487b936a9c935 Binary files /dev/null and b/docs/blog/2018-2-6-choosing-a-back-end/gatsby.jpeg differ diff --git a/docs/blog/2018-2-6-choosing-a-back-end/index.md b/docs/blog/2018-2-6-choosing-a-back-end/index.md new file mode 100644 index 0000000000000..2a76aa65fbf57 --- /dev/null +++ b/docs/blog/2018-2-6-choosing-a-back-end/index.md @@ -0,0 +1,142 @@ +--- +title: Picking a back-end for GatsbyJS +date: "2018-02-06" +author: "Ross Whitehouse" +--- + +A little while ago I had the six-monthly itch to redo my portfolio site, and I decided I was going to learn to use Gatsby. But that seems to be only half the battle. After you’ve built your front-end, how do you decide on the back-end? There’s so many out there! + +![GatsbyJS](gatsby.jpeg) + +## Background - Why Gatsby? + +The only thing as abundant than Headless CMS options is Static Site Generator options. From Hugo (built on Google’s Go language) to Jekyll (Ruby) and even Nuxt which is based on VueJS. I picked Gatsby out of the pack for a number of reasons, chief amongst which is that I’m professionally a React.js developer, so getting to use React in these quick projects is a great benefit. + +Gatsby pitches as a “Blazing-fast static site generator for React”. So if I can build sites, but also encompass some React knowledge, all the better right? And I’m always looking for side-projects and sites for others, so if I can get a JAMstack sorted quicker and easier than my previous WordPress stack, then all the better going forward! I thought it was best to start with my own site, to test the viability. + +> **What-stack?** JAM stands for Javascript, API, Markup. There are lots of benefits to this type of site, but the one I’m interested in is that your CMS is detached from your site - no hefty WordPress build for your tiny blog site. +> [You can read more on the JAMstack website](https://jamstack.org/). + +I found Gatsby a real pleasure. You can find tutorials on their site for setup and once you see the code it’s fairly simple. I can personally recommend [Scott Tolinski’s series - available on Youtube](https://www.youtube.com/watch?v=b2H7fWhQcdE&list=PLLnpHn493BHHfoINKLELxDch3uJlSapxg). Gatsby nicely wraps up React and React Router with a nice folder structure, webkit, ES6, SASS support and - importantly - GraphQL. + +> **What-QL?** GraphQL is a query language for APIs. Where in the WordPress Days I’d have to get the whole post just to display the title, with GraphQL I can tell the API to give me just the title. +> [Their site is pretty handy too](http://graphql.org/). + +I got the site setup pretty quickly after learning about it. There’s a tonne of tutorials and instructional material around. And you can use as much or as little React as you want. There’s also a [massive list of available plugins](/docs/plugins/), which is only going to grow. + +So if you have any experience with React, or if you’re just getting started, this is a great choice. Gatsby doesn’t tell you how your code has to look. In fact it’s setup so you can use Markdown files for pages, but I didn’t fancy that, so I don’t. Simple as that! Likewise, if I want to scale this to build websites for other people, I don’t want to spend ages teaching them how to use Markdown, clone a git repo and add it to the git repo. Queue a Headless CMS. + +You build your site. You’ve got your SASS, you’ve got your Markdown files (or not), but everything’s blank! So now what? How do we populate it with content? + +## The Next Step: A back-end + +Now we need a system to manage and deliver our content in a nice API (instructed by our GraphQL of course). And there’s a whole bunch of them about. To help us out, Gatsby has plugins that cater to some Headless CMS like the WordPress API, Contentful, Cockpit, Prismic and NetlifyCMS - which Gatsby actually has a guide for. I’ll be going through a few of these to see which one might be more useful for this small project, and going forward. + +> After posting this, I heard some really good thing about [GraphCMS](https://graphcms.com/) - It’s designed to work with GraphQL inherently and they have a [Gatsby Starter Project](https://github.com/GraphCMS/graphcms-examples/tree/master/gatsby-source-plugin-blog) example to check out. + +Firstly, though, why do we want a Headless CMS and a JAMstack for the project? There are a few reasons most people use them, and some that are down to personal preference: + +1. **Easy setup!** +2. **No back-end code.** I’m a front-end dev and honestly don’t want to spend hours setting up some PHP that I won’t enjoy. Gimme the good stuff. +3. **No server needed.** Cloud CMSs mean that I don’t need to pay the hosting people to setup an SQL database. +4. **Easy to edit.** If I need to edit a site on the fly or have a client who needs to do the same, they don’t need to touch any code or run to their home workstation to fix a spelling error. They can access it anywhere. + +--- + +![Contenful](contentful.png) + +### Contentful + +This is the one I’ve heard the most about in my research. Contentful is big and well-known - used by over 130 thousand developers if their website is to be believed. I also like their description “Fast. Flexible. Future-proof. It’s everything your CMS isn’t.” It might as well say “My CMS could beat up your CMS.” + +With all the acclaim, however, can come a hefty price tag. Contentful does have a free tier if you display their logo in the footer, you can keep up to 10,000 records and have 3 users - which isn’t bad at all. For my personal site I’m happy to plaster whatever attribution on the bottom. If you wanted to use this for a client and they were dead against someone else’s logo being on there, you can go up a half-tier with the same spec for $39 a month. + +![Contentful's Pricing Packages](contentful-pricing.png) + +From the paid Developer edition upwards, it seems a pretty steep fee, especially compared to some others. That said, if you’ve got a client willing to fork out a hot $949, why not? + +![A quick sample project](contentful-project.png) + +As soon as you sign up (for free) you get access to a dashboard with some dummy content and links to tutorial videos\*. You can see the dashboard with all of your content types. I setup a ‘Page’ type for the text on my pages. You could do posts or other custom types. + +> \* In the videos the guy pronounces Contentful like ‘content’ as in pleased or satisfied. I always thought it was Contentful with ‘content’ as in CMS. But what do I know? He works there. + +![Contentful's well-laid-out post-types](contentful-page.png) + +You then setup your fields, choosing from a big list. If you want a simple Title/Body you can set it up as above, or you can use times and dates, images, whole JSON Objects and more. You can also localise fields to only show in certain countries, make them required, and how they appear in the CMS. For example, I couldn’t see how to create a checkbox (as there isn’t a field-type for it), but if you create a Short text field you have the option to only allow certain values. Then, you can set the CMS-appearance to a drop-down or some radio buttons. I’d have liked that to be an option as soon as I add a field - something like WordPress’ custom fields - but once you know it’s there it makes sense. + +![There are loads of field types available!](contentful-fields.png) + +Contentful looks like a fantastic service. It isn’t perfect but it checks all my boxes — and what do you want for nothing? It’s definitely the one to beat. + +--- + +![WP's REST API](wp.jpeg) + +### WordPress’ REST API + +Ever since I started coding I’ve used WordPress as a traditional CMS. I’m familiar with how it works, the terminology and documentation. I know that WordPress is very very well-documented. The API includes ACF - a plugin known to most if not all WP devs and theme builders - which opens the posts out to accept all sorts of different fields. In fact, one of my issues about Contentful was based on my much-longer-term experience with ACF and WP. + +I’m sure I don’t need to spend too much time telling you the benefits of WordPress. The support is great, the interface is great, and it scales wonderfully. In fact WordPress boasts 29% of the entire internet uses their service. That’s absolutely huge. There are a million and one plugins for everything from SEO to E-commerce, Custom Post Types, Custom Fields and more. + +How does this hook up to our Gatsby build, then? Well if you have WordPress.com - WP’s free blogging platform - you can do it automatically for free. If you have WordPress.org - the big-brother that allows custom development - then you’ll need to host that somewhere (possibly free, but more likely paid-for if you get much traffic). My issue with the WP API is that I wanted something that would strip me of the usual server-database setup. But that’s what I’d need to run a WordPress.org CMS - even in a decoupled capacity. I really just one a one-stop-cloud-shop for my CMS like Contentful. + +The WordPress.com option is one to consider. They have a [developer blog](https://developer.wordpress.com/2016/11/11/wordpress-rest-api-on-wordpress-com/) about how to get started, which links to a really cool [API console](https://developer.wordpress.com/docs/api/console/) where you can experiment with the different types of requests you can make. In fact Gatsby makes this easier with the [`gatsby-source-wordpress` plugin](/packages/gatsby-source-wordpress). In your Gatsby configuration file you set the URL of your WP install. Then in your WordPress site, [configure a new App](http://developer.wordpress.com/apps/), and your data is ready to be pulled down using a GraphQL Query. + +A lot of this information came from a [fantastic tutorial by Jeremey Duvall](https://jeremey.blog/gatsby-photo/). He goes through Gatsby, WordPress.com setup and hooking it up with GraphQL. It’s the whole setup right there. + +The only problem with the WordPress.com setup is that it’s restricted to posts and pages that boil down to title/image/content. If you want ACF or other plugins you’re going to need a paid-for WP package, which harks back to the WordPress.org issue: I can’t use it without paying for it. + +--- + +### NetlifyCMS + +We’ll be hearing more about Netlify in another article - their original product is a CDN for your entire site, and I’ll be writing more about serving your Gatsby site - but right now we’ll focus on their CMS. Firstly, it’s build on React, so it’s a good bet it’ll play nice with Gatsby (not to mention the Gatsby plugin I mentioned earlier). + +One big difference from the others here is that the content in NetlifyCMS is kept in your Git repo, meaning that code and content are versioned together. You won’t ever lose content if you still have the repo, and you can see the history at the press of a button - same as you can with your code. + +[Gatsby has a handy tutorial for NetlifyCMS](/docs/netlify-cms/) but they do stress that in order to save to Github etc, you will need your own server: + +> To save your content in a Git repo, the repo will need to be hosted on a service like GitHub, and you’ll need a way to authenticate with that service so Netlify CMS can make changes through the service’s API. For most services, including GitHub, authentication will require a server. + +They also say, however, that if you use NetlifyCMS with Netlify, they conveniently handle the authenticating for you. Netlify will watch your Git repository for changes and update automatically. This is important to consider that they’re designed to be used together, so if you’re in for one it would benefit you to be in for the other. This isn’t law, but you can see why they’d make it more convenient if you lock into their ecosystem. + +Pedro Duarte has a [great article](https://medium.com/netlify/jamstack-with-gatsby-netlify-and-netlify-cms-a300735e2c5d) about using Gatsby with both Netlify and NetlifyCMS. + +--- + +### Best of the rest - Prismic.io & Cockpit + +Prismic is sort of a Contentful-like service that does basically the same thing with a few differences. I’m greeted to a post-type-creator similar to Contentful’s, I can create an editor with a number of fields similar such as Title, Body, Image, Location, Link, Color. + +![Prismic's CMS](prismic.png) + +Prismic has a similar pricing structure to Contentful - but has a few more options at the budget-end. In fact the only difference between the 3 smaller tiers is the number of users you can add to the CMS. Further than that there are some more premium versions with up to an infinite amount of users and some fancy features like user roles and collaboration. Certainly for bigger projects and bigger clients that would be useful. + +![They do have more pricing options than Contentful](prismic-pricing.png) + +Cockpit also seems to share a lot of the same features except for two big differences: + +* It’s open source - anyone can download it, anyone can contribute to the git repository and improve it, meaning it’s fully free and will be available - in one form or another - forever. I could see an issue with Contentful if the service ever stopped working. They have backups on AWS and create nightly backups on their premium plans, but the actual interface may become unavailable. Because Cockpit is open source they could go out of business or go offline for a night or just stop working altogether, and there’s a repo available with your CMS on. + +* It’s self-hosted - this ties into the last point and if it did all come crashing down, as long as your site is still active so will your CMS be. Great news for the tech-paranoid! + +--- + +## Conclusion - Which Back-End is right? + +If nothing else, writing this article has given me a checklist that I need a CMS to fulfil. Some other CMSs have great features, but a couple of them are much more important to my use-case than others. + +### Free Option + +This is the top of the list. If I’m just messing about with the system, I don’t want to be forking out. If I have a larger project with a client who has actual money, then I’d reconsider. Also to this point I’d like it to be scalable. If I make a friend’s small site with Gatsby, and then overnight his company becomes million-pound business, I want to be able to upgrade the CMS to handle an increase in users or posts. + +### Ease Of Use + +Cloud-hosted or Git-hosted seem to be the best for this. I don’t need a server to run them and I can control it all in one place. The UI needs to be easy enough for a non-developer and it’d be nice if the system was well-supported so I could get help with issues when needed. + +In terms of which CMS to go with, they all have great merits and I can see them all being useful for different projects. But for my needs - for smaller side projects and for personal sites - Contentful and Prismic seem like the ones to go for. They’re both cloud-based with minimal setup and work via an API so I can access them wherever I need to. Also their free tiers have great features, and scale easily so that if I have a ‘proper’ project, I can get a version that will suit any needs. + +Was this post useful? Do you use any of these CMSs, or a different one? Please let me know, I’d love to hear about how you get one with them. And look out for a future post about hosting. I mentioned that NetlifyCMS runs great with Netlify, but there are other options! I’ll be looking at Github Pages, Heroku and more! + +You can find me on [Twitter](https://twitter.com/RossWhitehouse) and [Instagram](https://www.instagram.com/ross.dw/), and [check out my other posts](https://medium.com/@RossWhitehouse)! diff --git a/docs/blog/2018-2-6-choosing-a-back-end/prismic-pricing.png b/docs/blog/2018-2-6-choosing-a-back-end/prismic-pricing.png new file mode 100644 index 0000000000000..1196193281919 Binary files /dev/null and b/docs/blog/2018-2-6-choosing-a-back-end/prismic-pricing.png differ diff --git a/docs/blog/2018-2-6-choosing-a-back-end/prismic.png b/docs/blog/2018-2-6-choosing-a-back-end/prismic.png new file mode 100644 index 0000000000000..8ad8f3460ed80 Binary files /dev/null and b/docs/blog/2018-2-6-choosing-a-back-end/prismic.png differ diff --git a/docs/blog/2018-2-6-choosing-a-back-end/wp.jpeg b/docs/blog/2018-2-6-choosing-a-back-end/wp.jpeg new file mode 100644 index 0000000000000..6061c73a1337e Binary files /dev/null and b/docs/blog/2018-2-6-choosing-a-back-end/wp.jpeg differ diff --git a/docs/blog/2018-2-7-jam-out-your-blog/after-post-title.png b/docs/blog/2018-2-7-jam-out-your-blog/after-post-title.png new file mode 100644 index 0000000000000..8b4de7eafb6d2 Binary files /dev/null and b/docs/blog/2018-2-7-jam-out-your-blog/after-post-title.png differ diff --git a/docs/blog/2018-2-7-jam-out-your-blog/before-post-title.png b/docs/blog/2018-2-7-jam-out-your-blog/before-post-title.png new file mode 100644 index 0000000000000..3c8f55e291280 Binary files /dev/null and b/docs/blog/2018-2-7-jam-out-your-blog/before-post-title.png differ diff --git a/docs/blog/2018-2-7-jam-out-your-blog/index.md b/docs/blog/2018-2-7-jam-out-your-blog/index.md new file mode 100644 index 0000000000000..45cde987c4398 --- /dev/null +++ b/docs/blog/2018-2-7-jam-out-your-blog/index.md @@ -0,0 +1,158 @@ +--- +title: JAM Out Your Blog - Gatsby + Prose + Netlify +date: "2018-02-07" +author: "Vlad Pasculescu" +--- + +If you’re reading this, chances are you’ve heard a thing or two about Gatsby. Let me take you through a _jamstacked_ workflow that is friendly to both developers, as well as content-creators. + +![JAM Out Your Blog Header Image](jam-header.jpg) + +## Intro + +As a freelance developer, the business person inside of me is constantly looking for ways to streamline the development process. At the same time, the inner developer is looking for the most modern development experience. If you add this working with non-technical content-creators, it becomes quite the balancing act. + +I’m willing to assume that many readers have been here before and are currently cringing in unison. Luckily, I found a solution. + +My goal here is to share a tool set helps bring order to my freelance chaos. I'll be walking through a workflow that's ideal for personal blogs and hand-off projects where some sort of a CMS is in scope. + +I'll also be referencing a wonderful article written by Josh Weaver, [Gatsby + Contentful + Netlify (and Algolia)](https://www.gatsbyjs.org/blog/2017-12-06-gatsby-plus-contentful-plus-netlify/). Josh’s article spoke to my goals and frustrations perfectly and inspired me to share this alternative approach. + +_**Let’s get into it.**_ + +

via GIPHY

+ +## My Requirements + +### Like Josh’s requirements, my list includes: + +* **Speed** - this includes development, website performance, and deployment +* **Development Experience** - I want to use React and Webpack +* **Maintainability** - ease with which anyone can create, update and delete posts +* **Scalability** - need to make sure that performance is not hindered by a growing needs +* **Lean** - simplify the tools and services use to a bare minimum +* **Revision History** - for accountability and allowing for versioning +* **Inexpensive Hosting** - again, to maximize value and keep personal costs down +* **NO WordPress** - similarly, I don’t want to deal with updates, themes, hacks...etc +* **Continuous Deployment** - the site needs to always be up and running and current + +For the sake of brevity, let's infer that speed, development experience, scalability and lack of WordPress will be handled by Gatsby and the JAMstack. If you’re unfamiliar, take a look at [http://jamstack.org/. ](http://jamstack.org/) + +## CMS-Induced Headaches + +From a non-technical content-creator perspective, more UI and less code is ideal. So if we want to avoid WordPress, how can we provide the experience of a simple login where a user can create, edit and publish posts? + +Josh’s article provides a solution by way of using Contentful to manage content on his company’s documentation website. + +### Here are some Pros (at the time of writing): + +* Clean UI +* Free Tier +* User Roles (admins, editors, content authors) +* Comprehensive tutorials +* Fully-customizable front end +* Article search and filters + +With such a robust set of features, it is easy to see why Contentful is a popular service. However, between a combination of having no prior experience with the platorm, and wanting to keep things simple, I ran into issues, and felt that it was _too_ robust for my project goals. + +While, a fully-customizable front end may seem really flexible, _**there is NOTHING set up when you create a new project.**_ You will have to create your own content models for blog posts and use GraphQL to query for each blog post type you set up. + +

via GIPHY

+ +If you’re like me and have no previous experience with Contentful, expect a few headaches. Your first time working with the service will involve a great deal of trial and error to get content/posts into your Gatsby website. Couple this with being a GraphQL newbie (like me), and you will get frustrated..._**very quickly**_. + +All I wanted to do was streamline my process and here I was adding another service into the mix and creating more work for myself. No bueno. + +To spare you the details, I spent a few hours comparing my GraphQL queries to those used in the [Gatsby + Contentful example](https://github.com/gatsbyjs/gatsby/tree/master/examples/using-contentful) to find errors in my code. I eventually gave up and I thought that there had to be an easier way to manage content online. Luckily there is. It's called Prose. + +## Managing Content Via Github: Enter Prose.io + +Prose was originally created for editing markdown files on GitHub by the people at [Development Seed](https://developmentseed.org/). + +### Here is a summary: + +* Simple Content Authoring Environment +* Designed for CMS-Free Websites +* Web-based Interface for Managing Content Directly on Github +* Advanced Support for Markdown Content - Including Syntax Highlighting & Formatting Toolbar + +Source: [Prose](http://prose.io/#about) + +So, a service that works on top of Github where I, or anyone with a Github account can quickly create and manage posts. Sick! + +#### Follow these steps: + +1. Set up a repository for the website. +2. Share access to the repo with anyone on your team. +3. Log in via [Prose.io](http://prose.io/). +4. Select your website's repo from the Prose interface. +5. Done. You can edit existing posts, preview posts, and commit any changes directly within the interface. + set up a repository for the website + +

via GIPHY

+ +_**Yes, there’s more.**_ + +Because Prose was built for Jekyll, it recognizes any headmatter you add to your .md files. This will give developers the ability to build queries and replicate familiar features from other CMS platforms. Say hello to publish states, publish date, article author and more. + +I should also mention that Prose is an open source project that is available for download if you wish to self-host. Check out the [documentation on Github.](https://github.com/prose/prose) + +## Get Lean and Get on Netlify + +Let’s summarize where we are and why [Netlify](https://www.netlify.com/) will take care of the rest. + +```[ ] Lean - simplify the tools and services use to a bare minimum +[ ] Inexpensive Hosting - again, to maximize value and keep personal costs down + +[ ] Continuous Deployment - the site needs to always be up and running and current + +[x] Speed - this includes development, website performance, and deployment + +[x] Development Experience - I want to use React and Webpack + +[x] Maintainability - ease with which anyone can create, update and delete posts + +[x] Scalability - need to make sure that performance is not hindered by a growing needs + +[x] Revision History - for accountability and allowing for versioning + +[x] NO WordPress - similarly, I don’t want to deal with updates, themes, hacks...etc +``` + +When it comes to continuous deployment and inexpensive hosting, using Netlify is, as Josh mentions “ a no brainer.”  Check out [Netlify’s features here](https://www.netlify.com/features/) for a more in-depth look. + +With streamlining in mind, a workflow doesn’t get any leaner than working within the confines of Github and Netlify. Think about the magic: + +1. Use Gatsby to create your website. +2. Set up a GitHub repository to track changes and version history. +3. Once ready, deploy your repository to Netlify. +4. Use Prose (which accesses your GitHub), to create, edit and commit posts. +5. Netlify sees the update to the repository and re-renders the website. + +With this process in place, content creators do not need to understand Markdown, React, Git or Netlify. They can simply log into Prose and start writing. All the developer has to do is share the repository. + +_**It just works.**_ 🤙🏼 + +

via GIPHY

+ +## Concluding Thoughts + +With all of that said, this process has a few caveats related to working within Prose that I must address: + +1. If you follow a folder structure enclosing an index.md file for your posts, you will need to add the new folder within the URL of the post +2. Inserting an image adds extra markup which you will need to remove for an image to show up within your post. Prose will upload the image within the same directory as your index.md file. + +#### Default + +![Default Prose image path](before-post-title.png) + +#### After (this will work) + +![After image path change](after-post-title.png) + +3. You must commit a file by hitting the save icon or else the file is not saved. Posts cannot be saved as drafts in Prose. So, you will have to build the functionality within your headmatter and query posts based upon a draft/published state (if you need it). +4. Whoever will be posting will need to manually add headmatter to each .md file. Be warned that there is no specific area to do so. But after it's added, a fourth icon appears in the right pane where you can then edit and add other post details. + +I hope you try playing around with this workflow yourself with a Gatsby starter and see if this works for you. Gatsby provides incredible tools that “just work” without sacrificing an exciting development environment. If you pair it with Netlify and Prose, you will cut overhead and manage content directly from a GitHub repository. Let this approach bring some order to the chaos. + +_**Thank you for reading...Now get to hacking.**_ ✌🏼 diff --git a/docs/blog/2018-2-7-jam-out-your-blog/jam-header.jpg b/docs/blog/2018-2-7-jam-out-your-blog/jam-header.jpg new file mode 100644 index 0000000000000..514b7aba28e6e Binary files /dev/null and b/docs/blog/2018-2-7-jam-out-your-blog/jam-header.jpg differ diff --git a/docs/blog/author.yaml b/docs/blog/author.yaml index 18027dc05e507..41585ec2b689e 100644 --- a/docs/blog/author.yaml +++ b/docs/blog/author.yaml @@ -77,3 +77,15 @@ - id: Robin Vasan bio: Robin Vasan is an experienced early-stage venture investor and former repeat entrepreneur. His expertise covers the full life-cycle of building and scaling companies and he primarily invests in applications, cloud computing, open source, virtualization and security. avatar: avatars/robin-vasan.jpg +- id: Ross Whitehouse + bio: React and Front-End Developer from Birmingham, UK + avatar: avatars/ross-whitehouse.jpg + twitter: "@RossWhitehouse" +- id: Vlad Pasculescu + bio: Designer turned maker living and creating in Southern California + avatar: avatars/vlad-pasculescu.jpg + twitter: "@vladpasculescu" +- id: Steven Natera + bio: Founder of Gatsby Manor. Site Reliability Engineer. Open source addict. Writer at Hackernoon. + avatar: avatars/steven-natera.jpg + twitter: "@stevennatera" diff --git a/docs/blog/avatars/ross-whitehouse.jpg b/docs/blog/avatars/ross-whitehouse.jpg new file mode 100644 index 0000000000000..de9829299548f Binary files /dev/null and b/docs/blog/avatars/ross-whitehouse.jpg differ diff --git a/docs/blog/avatars/steven-natera.jpg b/docs/blog/avatars/steven-natera.jpg new file mode 100644 index 0000000000000..630d3557a42b6 Binary files /dev/null and b/docs/blog/avatars/steven-natera.jpg differ diff --git a/docs/blog/avatars/vlad-pasculescu.jpg b/docs/blog/avatars/vlad-pasculescu.jpg new file mode 100644 index 0000000000000..f5b2ce24f6d1a Binary files /dev/null and b/docs/blog/avatars/vlad-pasculescu.jpg differ diff --git a/docs/community/index.md b/docs/community/index.md index 33a9fb8ab37cf..51ed45249c47a 100644 --- a/docs/community/index.md +++ b/docs/community/index.md @@ -17,9 +17,9 @@ and orientation. The Gatsby community welcomes contributions. Please refer to the guides below on how to make sure your contributions get accepted: -[How to Contribute](/docs/how-to-contribute/) - -[Gatsby Style Guide](/docs/gatsby-style-guide/) +* [How to Contribute](/docs/how-to-contribute/) +* [How to File an Issue](/docs/how-to-file-an-issue/) +* [Gatsby Style Guide](/docs/gatsby-style-guide/) ## Gatsby news diff --git a/docs/docs/add-custom-webpack-config.md b/docs/docs/add-custom-webpack-config.md index 6abd361633eb5..8280012f13b92 100644 --- a/docs/docs/add-custom-webpack-config.md +++ b/docs/docs/add-custom-webpack-config.md @@ -12,8 +12,9 @@ To add custom webpack configurations, create (if there's not one already) a `gatsby-node.js` file in your root directory. Inside this file, export a function called `modifyWebpackConfig`. -When Gatsby creates its webpack config, this function will be called allowing you to update the default -webpack config. +When Gatsby creates its webpack config, this function will be called allowing +you to modify the default webpack config using +[webpack-configurator](https://github.com/lewie9021/webpack-configurator). Gatsby does multiple webpack builds with somewhat different configuration. We call each build type a "stage". The following stages exist: @@ -38,43 +39,40 @@ e.g. [Sass](/packages/gatsby-plugin-sass/), ## Example -Here is an example adding an additional global variable via the `DefinePlugin` and -the `less-loader` +Here is an example that configures **flexboxgrid** when processing css files. Add this in `gatsby-node.js`: ```js -exports.modifyWebpackConfig = ({ - stage, - rules, - loaders, - plugins, - boundActionCreators, -}) => { - boundActionCreators.setWebpackConfig({ - module: { - rules: [ - { - test: /\.less$/, - // We don't need to add the matching ExtractText plugin - // because gatsby already includes it and makes sure its only - // run at the appropriate stages, e.g. not in development - use: plugins.extractText.extract({ - fallback: loaders.style, - use: [ - loaders.css({ importLoaders: 1 }), - // the postcss loader comes with some nice defaults - // including autoprefixer for our configured browsers - loaders.postcss(), - `less-loader`, - ], - }), - }, - ], - }, - plugins: [ - plugins.define({ - __DEVELOPMENT__: stage === `develop` || stage === `develop-html`, - }), - ], - }); +exports.modifyWebpackConfig = ({ config, stage }) => { + switch (stage) { + case "develop": + config.loader("css", { + include: /flexboxgrid/, + }); + + break; + + case "build-css": + config.loader("css", { + include: /flexboxgrid/, + }); + + break; + + case "build-html": + config.loader("css", { + include: /flexboxgrid/, + }); + + break; + + case "build-javascript": + config.loader("css", { + include: /flexboxgrid/, + }); + + break; + } + + return config; }; ``` diff --git a/docs/docs/adding-a-list-of-markdown-blog-posts.md b/docs/docs/adding-a-list-of-markdown-blog-posts.md index b26bef541146f..d343174c5ebf6 100644 --- a/docs/docs/adding-a-list-of-markdown-blog-posts.md +++ b/docs/docs/adding-a-list-of-markdown-blog-posts.md @@ -6,7 +6,7 @@ Once you have added Markdown pages to your site, you are just one step away from ### Creating posts -As described [here](/docs/docs/adding-markdown-pages.md), you will have to create your posts in Markdown files which will look like this: +As described [here](/docs/adding-markdown-pages), you will have to create your posts in Markdown files which will look like this: ```md --- @@ -22,7 +22,7 @@ Has anyone heard about GatsbyJS yet? The first step will be to create the page which will display your posts, in `src/pages/`. You can for example use `index.js`. -```js +```jsx import React from "react"; import PostLink from "../components/post-link"; @@ -39,9 +39,9 @@ export default IndexPage; ### Creating the GraphQL query -The only thing left to do is to provide the data to your component with a GraphQL query. +Second, you need to provide the data to your component with a GraphQL query. Let's add it, so that `index.js` looks like this: -```js +```jsx import React from "react"; import PostLink from "../components/post-link"; @@ -74,4 +74,23 @@ export const pageQuery = graphql` `; ``` -This should get you a page with your posts sorted by descending date. You can further customise the `frontmatter` and the page component to get desired effects! +### Creating the `PostLink` component + +The only thing left to do is to add the `PostLink` component. Create a new file `post-link.js` in `src/components/` and add the following: + +```jsx +import React from "react"; +import Link from "gatsby-link"; + +const PostLink = ({ post }) => ( +
+ + {post.frontmatter.title} ({post.frontmatter.date}) + +
+); + +export default PostLink; +``` + +This should get you a page with your posts sorted by descending date. You can further customise the `frontmatter` and the page and `PostLink` components to get your desired effects! diff --git a/docs/docs/adding-images-fonts-files.md b/docs/docs/adding-images-fonts-files.md index e88fb3783334e..bf72c4fbeb2ed 100644 --- a/docs/docs/adding-images-fonts-files.md +++ b/docs/docs/adding-images-fonts-files.md @@ -51,7 +51,58 @@ production so you don’t need to worry about long-term caching of assets. Please be advised that this is also a custom feature of Webpack. -An alternative way of handling static assets is described in the next section. +Two alternative ways of handling static assets is described in the next sections. + +## Query for `File` in GraphQL queries using gatsby-source-filesystem + +You can query the `publicURL` field of `File` nodes found in your data layer to trigger copying those files to the public directory and get URLs to them. + +Examples: + +* Copy all `.pdf` files you have in your data layer to your build directory and return URLs to them: + +```graphql +{ + allFile(filter: { extension: { eq: "pdf" } }) { + edges { + node { + publicURL + } + } + } +} +``` + +* Copy post attachments defined in your Markdown files: + + Link to your attachments in the markdown frontmatter: + +```markdown +--- +title: "Title of article" +attachments: + - "./assets.zip" + - "./presentation.pdf" +--- + +Hi, this is a great article. +``` + +In the article template component file, you can query for the attachments: + +```graphql +query TemplateBlogPost($slug: String!) { + markdownRemark(fields: { slug: { eq: $slug } }) { + html + frontmatter { + title + attachments { + publicURL + } + } + } +} +``` ## Using the `static` Folder diff --git a/docs/docs/adding-tags-and-categories-to-blog-posts.md b/docs/docs/adding-tags-and-categories-to-blog-posts.md index a593aa00b63ad..733f0853443ee 100644 --- a/docs/docs/adding-tags-and-categories-to-blog-posts.md +++ b/docs/docs/adding-tags-and-categories-to-blog-posts.md @@ -4,16 +4,24 @@ title: Creating tags pages for blog posts Creating tag pages for your blog post is a way to let visitors browse related content. -To add tags to your blog posts, you will first want to have your site set up to turn your markdown pages into blog posts. To get your blog pages set up, see the [tutorial on Gatsby's data layer](tutorial/part-four/) and [Adding Markdown Pages](docs/adding-markdown-pages/). +To add tags to your blog posts, you will first want to have your site set up to turn your markdown pages into blog posts. To get your blog pages set up, see the [tutorial on Gatsby's data layer](/tutorial/part-four/) and [Adding Markdown Pages](/docs/adding-markdown-pages/). -## Add a tags field to your blog posts +The process will essentially look like this: + +1. Add tags to your `markdown` files +2. Write a query to get all tags for your posts +3. Make a tags page template (for `/tags/{tag}`) +4. Modify `gatsby-node.js` to render pages using that template +5. Make a tags index page (`/tags`) that renders a list of all tags +6. _(optional)_ Render tags inline with your blog posts + +## Add tags to your `markdown` files You add tags by defining them in the `frontmatter` of your Markdown file. The `frontmatter` is the area at the top surrounded by dashes that includes post data like the title and date. -``` +```md --- title: "A Trip To the Zoo" - --- I went to the zoo today. It was terrible. @@ -21,7 +29,7 @@ I went to the zoo today. It was terrible. Fields can be strings, numbers, or arrays. Since a post can usually have many tags, it makes sense to define it as an array. Here we add our new tags field: -``` +```md --- title: "A Trip To the Zoo" tags: ["animals", "Chicago", "zoos"] @@ -32,20 +40,22 @@ I went to the zoo today. It was terrible. If `gatsby develop` is running, restart it so Gatsby can pick up the new fields. -## Query your fields +## Write a query to get all tags for your posts Now these fields are available in the data layer. To use field data, query it using `graphql`. All fields are available to query inside `frontmatter` -Try running in Graph_i_QL the following query +Try running in GraphiQL (`localhost:8000/___graphql`) the following query ```graphql -query IndexQuery { - allMarkdownRemark { - totalCount +{ + allMarkdownRemark( + sort: { order: DESC, fields: [frontmatter___date] } + limit: 1000 + ) { edges { node { frontmatter { - title + path tags } } @@ -54,230 +64,238 @@ query IndexQuery { } ``` -The query fetches the title and tags for every blog post. +The resulting data includes the `path` and `tags` frontmatter for each post, which is all the data we'll need to create pages for each tag which contain a list of posts under that tag. Let's make the tag page template now: -Using this query, we can create a component for a blog front page that lists all posts and their tags. +## Make a tags page template (for `/tags/{tag}`) -```jsx -const IndexPage = ({ data }) => ( -
-

My Travel Blog

- {data.allMarkdownRemark.edges.map(({ node }) => ( -
-

- {node.frontmatter.title} - — {node.frontmatter.tags.join(`, `)} -

-
- ))} -
-); - -export const query = graphql` - query IndexQuery { - allMarkdownRemark { - totalCount - edges { - node { - id - frontmatter { - title - tags - } - } - } - } - } -`; -``` +If you followed the tutorial for [Adding Markdown Pages](/docs/adding-tags-and-categories-to-blog-posts/), then this process should sound familiar: we'll make a tag page template, then use it in `createPages` in `gatsby-node.js` to generate individual pages for the tags in our posts. -## Create tag pages +First, we'll add a tags template at `src/templates/tags.js`: -Tag pages list all the tags or all items with a certain tag and are a great tool for organizing content and making your site easy to browse. +```jsx +import React from 'react'; +import PropTypes from 'prop-types'; -First you will need a tag page component. In this example, we add a tags component in `src/templates/tags.js` which we'll use to create an index tags page at `/tags` and individual tag pages. +// Components +import Link from 'gatsby-link'; + +const Tags = ({ pathContext, data }) => { + const { tag } = pathContext; + const { edges, totalCount } = data.allMarkdownRemark; + const tagHeader = `${totalCount} post${totalCount === 1 ? '' : 's'} tagged with "${tag}"`; -```jsx -import React from "react"; -import { Link } from "gatsby"; - -export default function Tags({ pathContext }) { - const { posts, post, tag } = pathContext; - if (tag) { - return ( -
-

- {post.length} post{post.length === 1 ? "" : "s"} tagged with {tag} -

-
    - {post.map(({ id, frontmatter, excerpt, fields }) => { - return ( -
  • -

    - {frontmatter.title} -

    -

    {excerpt}

    -
  • - ); - })} -
- All tags -
- ); - } return (
-

Tags

-
    - {Object.keys(posts).map(tagName => { - const tags = posts[tagName]; +

    {tagHeader}

    +
      + {edges.map(({ node }) => { + const { path, title } = node.frontmatter; return ( -
    • - {tagName} +
    • + {title}
    • ); })}
    + {/* + This links to a page that does not yet exist. + We'll come back to it! + */} + All tags
); -} -``` - -Now we'll instruct Gatsby to create the tag pages. In the site's `gatsby-node.js` file we'll call the the [`createPages`](/docs/node-apis/#createPages) API to make a page for every tag. - -First create a function called `createTagPages`: - -```javascript -const path = require("path"); - -const createTagPages = (createPage, edges) => { - // Tell it to use our tags template. - const tagTemplate = path.resolve(`src/templates/tags.js`); - // Create an empty object to store the posts. - const posts = {}; - console.log("creating posts"); +}; - // Loop through all nodes (our markdown posts) and add the tags to our post object. +Tags.propTypes = { + pathContext: PropTypes.shape({ + tag: PropTypes.string.isRequired, + }), + data: PropTypes.shape({ + allMarkdownRemark: PropTypes.shape({ + totalCount: PropTypes.number.isRequired, + edges: PropTypes.arrayOf( + PropTypes.shape({ + node: PropTypes.shape({ + frontmatter: PropTypes.shape({ + path: PropTypes.string.isRequired, + title: PropTypes.string.isRequired, + }), + }), + }).isRequired, + ), + }), + }), +}; - edges.forEach(({ node }) => { - if (node.frontmatter.tags) { - node.frontmatter.tags.forEach(tag => { - if (!posts[tag]) { - posts[tag] = []; +export default Tags; + +export const pageQuery = graphql` + query TagPage($tag: String) { + allMarkdownRemark( + limit: 2000 + sort: { fields: [frontmatter___date], order: DESC } + filter: { frontmatter: { tags: { in: [$tag] } } } + ) { + totalCount + edges { + node { + frontmatter { + title + path + } + } } - posts[tag].push(node); - }); + } } - }); +`; +``` - // Create the tags page with the list of tags from our posts object. - createPage({ - path: "/tags", - component: tagTemplate, - context: { - posts, - }, - }); +**Note**: `propTypes` are included in this example to help you ensure you're getting all the data you need in the component, and to help serve as a guide while destructuring / using those props. - // For each of the tags in the post object, create a tag page. - - Object.keys(posts).forEach(tagName => { - const post = posts[tagName]; - createPage({ - path: `/tags/${tagName}`, - component: tagTemplate, - context: { - posts, - post, - tag: tagName, - }, - }); - }); -}; -``` +## Modify `gatsby-node.js` to render pages using that template -Then in the `createPages` API function, query using `graphql` for your fields and use that to call the new `createTagPages` function. +Now we've got a template. Great! I'll assume you followed the tutorial for [Adding Markdown Pages](/docs/adding-tags-and-categories-to-blog-posts/) and provide a sample `createPages` that generates post pages as well as tag pages. In the site's `gatsby-node.js` file, include `lodash` (`const _ = require('lodash')`) and then make sure your [`createPages`](/docs/node-apis/#createPages) looks something like this: -```javascript -exports.createPages = ({ graphql, boundActionCreators }) => { +```js +exports.createPages = ({ boundActionCreators, graphql }) => { const { createPage } = boundActionCreators; - // add the tags to the query - return new Promise((resolve, reject) => { - graphql(` - { - allMarkdownRemark { - edges { - node { - fields { - slug - } - frontmatter { - tags - title - } + + const blogPostTemplate = path.resolve('src/templates/blog.js'); + const tagTemplate = path.resolve('src/templates/tags.js'); + + return graphql(` + { + allMarkdownRemark( + sort: { order: DESC, fields: [frontmatter___date] } + limit: 2000 + ) { + edges { + node { + frontmatter { + path + tags } } } } - `).then(result => { - console.log(result); - const posts = result.data.allMarkdownRemark.edges; - - // call createTagPages with the result of posts - createTagPages(createPage, posts); - - // this is the original code used to create the pages from markdown posts - result.data.allMarkdownRemark.edges.map(({ node }) => { - createPage({ - path: node.fields.slug, - component: path.resolve(`./src/templates/blog-post.js`), - context: { - slug: node.fields.slug, - }, - }); + } + `).then(result => { + if (result.errors) { + return Promise.reject(result.errors); + } + + const posts = result.data.allMarkdownRemark.edges; + + // Create post detail pages + posts.forEach(({ node }) => { + createPage({ + path: node.frontmatter.path, + component: blogPostTemplate, + }); + }); + + // Tag pages: + let tags = []; + // Iterate through each post, putting all found tags into `tags` + _.each(posts, edge => { + if (_.get(edge, 'node.frontmatter.tags')) { + tags = tags.concat(edge.node.frontmatter.tags); + } + }); + // Eliminate duplicate tags + tags = _.uniq(tags); + + // Make tag pages + tags.forEach(tag => { + createPage({ + path: `/tags/${_.kebabCase(tag)}/`, + component: tagTemplate, + context: { + tag, + }, }); - resolve(); }); }); }; ``` +Some notes: -## Adding Tags To Your Blog Front Page +* Our graphql query only looks for data we need to generate these pages. Anything else can be queried again later (and, if you notice, we do this above in the tags template for the post title). +* While making the tag pages, note that we pass `tag` through in the `context`. This is the value that gets used in the `TagPage` query to limit our search to only posts tagged with the tag in the URL. -The blog front page we created previously doesn't link to the tag pages. One way to add this is by creating a tag component at `src/components/tags.js` +## Make a tags index page (`/tags`) that renders a list of all tags -```jsx -import React from "react"; -import { Link } from "gatsby"; +Our `/tags` page will simply list out all tags, followed by the number of posts with that tag: -export default function Tags({ list = [] }) { - return ( - - ); -} -``` +```jsx +import React from 'react'; +import PropTypes from 'prop-types'; -We can now use this new component on the blog home page by passing in our tags from the data layer: +// Utilities +import kebabCase from 'lodash/kebabcase'; -```jsx -import React from "react"; -import Tags from "../components/tags"; +// Components +import Helmet from 'react-helmet'; +import Link from 'gatsby-link'; -const IndexPage = ({ data }) => ( +const TagsPage = ({ data: { allMarkdownRemark: { group }, site: { siteMetadata: { title }} } }) =>
-

My Travel Blog

- {data.allMarkdownRemark.edges.map(({ node }) => ( -
-

{node.frontmatter.title}

- -
- ))} + +
+

Tags

+
    + {group.map(tag => ( +
  • + + {tag.fieldValue} ({tag.totalCount}) + +
  • + ))} +
+
-); +; + +TagsPage.propTypes = { + data: PropTypes.shape({ + allMarkdownRemark: PropTypes.shape({ + group: PropTypes.arrayOf( + PropTypes.shape({ + fieldValue: PropTypes.string.isRequired, + totalCount: PropTypes.number.isRequired, + }).isRequired, + ), + }), + site: PropTypes.shape({ + siteMetadata: PropTypes.shape({ + title: PropTypes.string.isRequired, + }), + }), + }), +}; + +export default TagsPage; + +export const pageQuery = graphql` + query TagsQuery { + site { + siteMetadata { + title + } + } + allMarkdownRemark( + limit: 2000 + filter: { frontmatter: { published: { ne: false } } } + ) { + group(field: frontmatter___tags) { + fieldValue + totalCount + } + } + } +`; ``` + +## _(optional)_ Render tags inline with your blog posts + +The home stretch! Anywhere else you'd like to render your tags, simply add them to the `frontmatter` section of your `graphql` query and access them in your component like any other prop. diff --git a/docs/docs/awesome-gatsby.md b/docs/docs/awesome-gatsby.md index 9189d92fdec8b..de4a112d06811 100644 --- a/docs/docs/awesome-gatsby.md +++ b/docs/docs/awesome-gatsby.md @@ -20,7 +20,7 @@ See the [list of official and community plugins](/docs/plugins/) * [Static Site Generation with Gatsby.js v0 — Scott Nonnenberg](https://blog.scottnonnenberg.com/static-site-generation-with-gatsby-js/) * [React.js Conf 2016 - Lightning Talks - Kyle Mathews](https://www.youtube.com/watch?v=RFkNRKL6ZoE) -* [Developing with React and Gatsby.js — Kyle Mathews](http://www.staticwebtech.com/presentations/developing-with-react-gatsbyjs/) +* [Developing with React and Gatsby.js — Kyle Mathews](https://www.youtube.com/watch?v=G4LVKJOOj7o) * [GraphQL Summit Open Source Lightning Talk on Gatsby — Kyle Mathews](https://youtu.be/y588qNiCZZo) * [Talk on GatsbyJS @ ViennaJS — Gerald Bauer](https://www.youtube.com/watch?v=f0O1nCgqA3E&feature=youtu.be&a) @@ -38,3 +38,4 @@ See the [list of official and community plugins](/docs/plugins/) * [Michael Cereda's multi-part series of blog posts on building his site with Gatsby](https://medium.com/@michaelcereda/creating-an-isomorphic-universal-website-with-react-part-1-a905350acba8#.akoo25l6j) * [Gatsby – Static Site Generator For React](https://codingthesmartway.com/gatsby-static-site-generater-for-react-introduction/) * [Construye y Publica Tu Blog Personal con Gatsby y Netlify](https://medium.com/@n370/construye-y-publica-tu-blog-personal-con-gatsby-y-netlify-parte-1-89804ba63625) +* [Ultra-schnellen Blog mit React und Gatsby erstellen](https://www.lekoarts.de/blog/ultra-schnellen-blog-mit-react-und-gatsby-erstellen) diff --git a/docs/docs/building-apps-with-gatsby.md b/docs/docs/building-apps-with-gatsby.md index 5ed665c39aa17..828fc39a3c687 100644 --- a/docs/docs/building-apps-with-gatsby.md +++ b/docs/docs/building-apps-with-gatsby.md @@ -4,7 +4,7 @@ title: "Building apps with Gatsby" Gatsby is an excellent framework for building web apps. You can use Gatsby to create personalized, logged-in experiences with two different methods. -The first approach to to build "hybrid" app pages which are statically rendered with dynamic sections. The second is, if needed, add client-only multi-page sections of the site. +The first approach is to build "hybrid" app pages which are statically rendered with dynamic sections. The second is, if needed, add client-only multi-page sections of the site. ## Hybrid app pages diff --git a/docs/docs/custom-html.md b/docs/docs/custom-html.md index 768922b06bbc7..b49ffe4e73b91 100644 --- a/docs/docs/custom-html.md +++ b/docs/docs/custom-html.md @@ -40,3 +40,18 @@ If you see this error: `Uncaught Error: _registerComponent(...): Target containe dangerouslySetInnerHTML={{ __html: this.props.body }} /> ``` + +### Adding custom JavaScript + +You can add custom JavaScript to your HTML document by using React's [dangerouslySetInnerHTML](https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml) attribute. + +```jsx +