Giter VIP home page Giter VIP logo

Comments (12)

janosh avatar janosh commented on May 4, 2024 19

I think when filtering out draft content for the production build, it's best to do it as close to the source as possible. There might be multiple places where draft content shows up on your site and if you don't do the filtering until you've reached gatsby-node's page creation, you would have to implement the filtering in all of these places individually. For blog posts that might be your blog's index page and/or landing page that displays a list of most recent posts. This leads to verbosity and, if you forget a place, might leak your draft content.

If the content is part of the site's repo, a solution that avoids these problems is to use gatsby-source-filesystem's ignore option. You could add a prefix such as draft- to all files containing draft content and combine that with

{
  resolve: `gatsby-source-filesystem`,
  options: {
    path: `${__dirname}/content`,
    ignore: process.env.NODE_ENV === `production` && [`**/draft-*`]
  }
}

Then, once the content is ready to be published, simply remove the file's draft- prefix and build. An additional advantage to this approach is that it works with both files and folders. If you want to exclude multiple files, simply add the prefix to the parent directory. For example, you could have a permanent drafts folder and move posts or any other type of content in and out of this folder as needed.

from gatsby.

mtheoryx avatar mtheoryx commented on May 4, 2024 8

I'm doing something similar to what @abrad45 recommended. Except I don't exclude the "draft posts" from my query, I filter them after that promise resolves based on my NODE_ENV.

I want to see all posts in my dev environment, but don't want to generate them when I build the static site for production. Here's my example, if you're curious:

exports.createPages = ({ boundActionCreators, graphql }) => {
  const { createPage } = boundActionCreators;
  const blogPostTemplate = path.resolve(`src/templates/blog-post.js`);

  return graphql(`{
    allMarkdownRemark {
      edges {
        node {
          html
          id
          frontmatter {
            title
            date(formatString: "MMMM DD YYYY")
            path
            tags
            excerpt
            published
          }
        }
      }
    }
  }`)
  .then(result => {
    if (result.errors) {
      return Promise.reject(result.errors);
    }

    const allPosts = result.data.allMarkdownRemark.edges;

    const allowedPosts = allPosts.filter(post => 
      (process.env.NODE_ENV === 'development' 
      || post.node.frontmatter.published));

    allowedPosts.forEach(({node}) => {
      createPage({
        path: node.frontmatter.path,
        component: blogPostTemplate
      });
    });
  });
};

from gatsby.

gesposito avatar gesposito commented on May 4, 2024 3

Frontmatter has published:
Set to false if you don’t want a specific post to show up when the site is generated.

from gatsby.

pieh avatar pieh commented on May 4, 2024 2

gatsby currently doesn't have any predefined fields in frontmatter so you can add published field but it's up to you to honor that field in your gatsby-node.js.

For example in your createPages function you can modify query that gets markdown nodes from data layer to allMarkdownRemark(filter:{frontmatter:{published:{ne:false}}}) (create pages from markdown that doesn't have published field set to false - so if you don't specify that field, page gets created) or allMarkdownRemark(filter:{frontmatter:{published:{eq:true}}}) (so you would need to specify it to true to create page)

from gatsby.

phlogisticfugu avatar phlogisticfugu commented on May 4, 2024

isn't this already implemented by using an underscore as the first character in the filename?

from gatsby.

KyleAMathews avatar KyleAMathews commented on May 4, 2024

Kinda. That's for template files which are still included but not outputted as html files. This issue is about not including a file at all in the production build. E.g. a draft blog post. Probably this would be implemented by excluding the file when globbing.

from gatsby.

KyleAMathews avatar KyleAMathews commented on May 4, 2024

Closing this. There's too many ways of doing this to handle it easily within Gatsby. Simple way not to have file built β€” move it somewhere else!

from gatsby.

abrad45 avatar abrad45 commented on May 4, 2024

Sorry to dredge up something from nearly two years ago, but I feel that supporting published: false for draft posts is worthwhile. At worst, documentation is outdated:

From https://www.npmjs.com/package/gatsby-transformer-remark:

All frontmatter fields are converted into GraphQL fields.

That's not true, as adding in your own frontmatter fields does not work, nor does published as outlined on https://jekyllrb.com/docs/frontmatter/

from gatsby.

abrad45 avatar abrad45 commented on May 4, 2024

@pieh sorry for the delay. Took me a few days to sit down and play with this a bit more. I have this snippet in my gatsby-node.js and every post is returned, even ones with published: false in the frontmatter. I'm wondering if possible frontmatter values are whitelisted or something?

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

    const blogPostTemplate = path.resolve('src/templates/blog.jsx');

    return graphql(`
        {
            allMarkdownRemark(
                sort: { order: DESC, fields: [frontmatter___date] }
                limit: 1000
                filter: { frontmatter: { published: { ne: false } } }
            ) {
                edges {
                    node {
                        html
                        frontmatter {
                            path
                        }
                    }
                }
            }
        }
    `).then(result => {
        if (result.errors) {
            return Promise.reject(result.errors);
        }

        result.data.allMarkdownRemark.edges.forEach(({ node }) => {
            createPage({
                path: node.frontmatter.path,
                component: blogPostTemplate,
            });
        });
    });
};

from gatsby.

abrad45 avatar abrad45 commented on May 4, 2024

@pieh Aha!

I learned something important about Gatsby tonight :)

The above code worked as you said it would. It prevented pages with published: false in the frontmatter from being rendered. What it did not do is prevent them from appearing on / in the post list, because that data comes from src/pages/index.jsx. I kinda wish that Gatsby had one source of truth that different pages / contexts could draw from (a la redux stores) but I am new to GraphQL, so maybe I'll much prefer this as I get more used to it.

In short, yes this works, and no frontmatter does not have a white list. And, in the case of my blog, I actually want to do the opposite of what I was doing: I'll be making detail pages for draft posts, but not linking to them on the index so I can see how they'll look before I publish them.

Thanks for the help. I appreciate it.

from gatsby.

brootle avatar brootle commented on May 4, 2024

I really think it would make more sense if it would be possible to exclude posts based on frontmatter from GraphQL data layer, should be standard Gatsby feature! ;)

from gatsby.

Mantissa-23 avatar Mantissa-23 commented on May 4, 2024

@janosh seems to have the most straightforward answer to this question. I like how I can see at a glance what posts are drafts and how it's agnostic of filetype, instead of having to dig around with GraphQL queries or frontmatter processing.

from gatsby.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.