Can I create two different graphql query for two different folders separately in my Gatsby project - graphql

I'm a newbie programmer and Recently I want to add a blog page to my website. I already have a projects page using Graphql and .md files, now my problem is, every time I try to create a blog post with .md, it appears also in my projects page, could you please advice me with some of your kind experience on solving this issue and do I have to create a separate query? even I don't know how?
this is my current query.
export const query = graphql`
query ProjectsPage {
allMarkdownRemark(sort: { fields: frontmatter___date, order: DESC }) {
nodes {
frontmatter {
slug
stack
title
thumb {
childImageSharp {
gatsbyImageData(placeholder: BLURRED, layout: FULL_WIDTH)
}
}
}
id
}
}
}

One easy thing you can do is to add a key field on your markdown files to distinguish between posts and projects. This will allow you to filter GraphQL queries. In the same way, you can also place the markdowns in separate folders and filter them using the relative/absolute path.
export const query = graphql`
query ProjectsPage {
allMarkdownRemark(filter: { frontmatter: {key: { eq: "project" }}, sort: { fields: frontmatter___date, order: DESC }) {
nodes {
frontmatter {
slug
stack
title
thumb {
childImageSharp {
gatsbyImageData(placeholder: BLURRED, layout: FULL_WIDTH)
}
}
}
id
}
}
}
As I said, this approach assumes that you have created a key: project field in your markdown files. You can do the same using key: article.
Alternatively, placing the markdowns in different folders using fileAbsolutePath/relativePath if needed in the same way. This approach will rely on your filesystem structure to determine the available paths. Both approaches are based on a filtered query, choose whatever suits you better.
Use the GraphiQL playground to test all queries, paths and filters at localhost:8000/___graphql

Related

How to load image in Gatsby GraphQL query

I have small SQLite database with products, that have relative paths to images.
I'd like to include these images to my page. I'm trying to use this query:
query {
allContent {
nodes {
Category
Description
Price
ProductID
Title
ImageURI {
childImageSharp {
gatsbyImageData(width: 200)
}
}
}
}
}
But I have this error:
Field "ImageURI" must not have a selection since type "String" has no subfields.
This can happen if you e.g. accidentally added { } to the field "ImageURI". If you didn't expect "ImageURI" to be of type "String" make sure that your input source and/or plugin
is correct.
However, if you expect "value" to exist, the field might be accessible in another subfield. Please try your query in GraphiQL and use the GraphiQL explorer to see which fields
you can query and what shape they have.
It is recommended to explicitly type your GraphQL schema if you want to use optional fields. This way you don't have to add the mentioned
"dummy content". Visit our docs to learn how you can define the schema for "undefined":
https://www.gatsbyjs.com/docs/reference/graphql-data-layer/schema-customization#creating-type-definitions
As I understand, I should convert String to File in my query. Is it right? If yes, how to do that?
Full code & repo to reproduce: https://github.com/vladd11/gatsby-test/blob/master/src/pages/index.js
Just query allFiles outside of allContent nodes. Like:
allFile {
edges {
node {
relativePath
childImageSharp {
gatsbyImageData(width: 200)
}
}
}
}
Don't forget to add new source of data to Gatsby Config:
{
resolve: "gatsby-source-filesystem",
options: {
path: `${__dirname}/static`, // Directory with your images
name: "images",
},
}
Find image in this directory using relative path, then load image dynamically:
getImage(data.allFile.edges.find(value => value.node.relativePath === product.ImageURI).node)
Use GatsbyImage to show this image:
<GatsbyImage alt={product.Title} image={Image}/>

sort content by tag in Gatsby with Conteful API

In Contentful, I create a content with few media pictures. The pictures have two different tags boxon and attaqueGenetique. I want to sort the slideshow by using tags I've added for each media, but I don't find the way to do that. There is an example on the website Gatsby, but is not really clear and my try failed to make it mine.
The example from Gatsby
query FilterByTagsQuery {
allContentfulNumber(
sort: { fields: contentful_id }
filter: {
metadata: {
tags: { elemMatch: { contentful_id: { eq: "numberInteger" } } }
}
}
) {
nodes {
title
integer
}
}
}
I've supposed I must transpose thise code to mine where
allContentfulNumber become allContentfulDiaporama, and
metadata: {
tags: { elemMatch: { contentful_id: { eq: "numberInteger" } } }
}
become
metadata: {
tags: { elemMatch: { contentful_id: { eq: "boxon" } } }
}
but when I try to compile the console return
56:5 error Field "metadata" is not defined by type "ContentfulDiaporamaFilterInput" graphql/template-strings
I don't know where catch metadata from media when it's imported in content... but I'm very beginner with graphql and Contentful. If there is a solution, that's can make my day happy !!!
metadata in Gatsby's example is a GraphQL node valid in their data structure, if yours hasn't it simply don't use it or it will break the code since it's not a valid custom type.
The problem in your query, besides using an invalid field (metadata) is that you are using an elemMatch filter, comparingcontentful_id (number) to boxon (string), so it will never work in your scenario (it works in Gatsbys' because it's the same type). In your case, you may want to use in (for arrays) or eq (for single values). Check the available list at: https://www.gatsbyjs.com/docs/graphql-reference/#filter
As far as I understand your question, it seems that you want to split your diaporama data in two different nodes, the ones that contain boxon and the ones that contain attaqueGenetique. If so, you will need to create different nodes by aliasing them:
query FilterByTagsQuery {
boxon: allContentfulDiaporama(
sort: { fields: contentful_id }
filter: {
metadata: { tags: { in: ["boxon"] } }
}
) {
nodes {
#your data/fields here
}
}
attaqueGenetique: allContentfulDiaporama(
sort: { fields: contentful_id }
filter: {
metadata: { tags: { in: ["attaqueGenetique"] } }
}
) {
nodes {
#your data/fields here
}
}
}
Test the query in the GraphiQL playground, available at localhost:8000/___graphql where it will be much more intuitive for you to add or remove filters and see the available nodes.
The snippet above will generate two different data structures based on the tags aliased. With this: boxon: allContentfulDiaporama, you are aliasing the result of allContentfulDiaporama in boxon so in your page, you will be able to access directly props.data.boxon and props.data.attaqueGenetique respectively.
Keep in mind that the sort filtering method only works on dates or numeric values, in the case of strings, it will sort them alphabetically. So I'm assuming that your data has a contentful_id (I'm not sure how it will be helpful sorting by contentful_id).
According to this pull-request the enableTags feature was fixed in the cutting-edge release(5 days ago) so try to upgrade your plugin dependency.
It seems to be fixed in, according to this GitHub thread:
gatsby-source-contentful#7.5.0-next.0
Or in the next release.

Gatsby's mapping between markdown files

I'm creating a multi-author site (using gatsby-plugin-mdx) and have the following file structure:
/posts
- /post-1/index.mdx
- /post-2/index.mdx
- ...
/members
- /member-a/index.mdx
- /member-b/index.mdx
- ...
In the frontmatter of the post page I have an array of authors like
authors: [Member A, Member B]
and I have the name of the author in the frontmatter of the author's markdown file.
I'd like to set the schema up so that when I query the post, I also get the details of the authors as well (name, email, etc.).
From reading this page it seems like I need to create a custom resolver... but all the examples I see have all the authors in one json file (so you have two collections, MarkdownRemark and AuthorJson... while I think for my case all my posts and members are in MarkdownRemark collection.
Thanks so much!
I end up doing something like this. Surely there's a cleaner way, but it works for me. It goes through all the Mdx and add a field called authors, which is queried, to all Mdx types.
One problem with this is that there's also authors under members, which is not ideal. A better approach is to define new types and change Mdx in the last resolver to your new post data type. Not sure how to get that to work though. At the end, I could query something like:
query MyQuery {
posts {
frontmatter {
title
subtitle
}
authors {
frontmatter {
name
email
}
}
}
}
exports.createResolvers = ({ createResolvers }) => {
const resolvers = {
Mdx: {
authors: {
type: ["Mdx"],
resolve(source, args, context, info) {
return context.nodeModel.runQuery({
query: {
filter: {
fields: {
collection: { eq: "members" }
},
frontmatter: {
memberid: { in: source.frontmatter.authors },
},
},
},
type: "Mdx",
firstOnly: false,
})
}
}
},
}
createResolvers(resolvers)
}

Using frontmatter in a markdownfile to query for images in a page query

I'm using GraphQL from within a Gatsby project. I have a set of markdown files for a blog-like section of the site. In the frontmatter of each markdown file, there's an image property.
What I'd like to do is use Gatsby's fine image api to load the image in the frontmatter. When viewing an individual post (the ones created via createPage api), this works just fine because I can provide the frontmatter.image in the context. Here's what that query looks like.
export const pageQuery = graphql`
query($slug: String!, $image: String) {
markdownRemark(frontmatter: { slug: { eq: $slug } }) {
html
frontmatter {
date(formatString: "MMMM DD, YYYY")
slug
title
image
}
}
coverImage: file(relativePath: { eq: $image }) {
childImageSharp {
fluid(maxWidth: 1440) {
...GatsbyImageSharpFluid
}
}
}
}
`
On my index page where I'm displaying all these posts though, I want to display a smaller version of this image. I can get the image from the front matter easy enough, but I'm not sure how to integrate that into the query.
export const pageQuery = graphql`
query {
allMarkdownRemark(sort: { order: DESC, fields: [frontmatter___date] }) {
edges {
node {
id
excerpt(pruneLength: 250)
frontmatter {
date(formatString: "MMMM DD, YYYY")
slug
title
image # <--- want to use this in a file query
}
}
}
}
}
`
As far as I understand, I can't use string interpolation in a static query in the component where the image is actually used, so I need to get it here in the page query. Is what I'm trying to do possible? Is there a better way to handle this?
This "link" between your frontmatter's image string and an actual image file node (processed with Sharp) is called a foreign-key relationship.
Creating foreign-key relationships in Gatsby
There are two ways of doing this:
Using mappings in gatsby-config.js
Using a GraphQL #link directive through Gatsby's schema customization (from v2.2)
I recommend the second option, since it's a more GraphQL way of doing things, and happens in gatsby-node.js where most node operations are taking place. However, if you're starting out with Gatsby and GraphQL, the first option might be easier to set up.
Implementing the #link directive in gatsby-node.js
In your case, using the #link GraphQL directive, you would probably end up with something like this in your gatsby-node.js:
exports.createSchemaCustomization = ({ actions }) => {
const { createTypes } = actions
const typeDefs = [
`type MarkdownRemark implements Node { frontmatter: Frontmatter }`,
`type Frontmatter {
# you may need to adapt this line depending on the node type and key
# that you want to create the relationship for
image: File #link(by: "relativePath")
}`
]
createTypes(typeDefs)
}
If you want to see an example in the wild, check out gatsby-node.js in robinmetral/eaudepoisson.com.
Query processed images via your frontmatter
Finally, you'll be able to query like this:
{
allMarkdownRemark {
edges {
node {
frontmatter {
date
slug
title
# image now points to the image file node
image {
childImageSharp {
fluid(maxWidth: 1024) {
...GatsbyImageSharpFluid
}
}
}
}
}
}
}
}

How to transform Markdown query to Strapi query on GraphiQL?

I'm trying to get my hands on Gatsby + Strapi development (adding Material for styling), I'm new to both Gatsby and Strapi although I have some basic knowledge of React and it's making the way easier to follow.
I'm using this Gatsby Starter: https://www.gatsbyjs.org/starters/Vagr9K/gatsby-material-starter/ which includes the Material design I'm trying to achieve, but I'm having some trouble changing the Markdown queries to Strapi queries to avoid making a lot of code changes (posts are exactly the same but stored in Strapi). I have three Content Types in Strapi corresponding to the three different pages the original starter provides: Post, Category, and Tag.
This is the original MarkdownRemark graphQL query included in the post.jsx template:
query BlogPostBySlug($slug: String!) {
markdownRemark(fields: { slug: { eq: $slug } }) {
html
timeToRead
excerpt
frontmatter {
title
cover
date
category
tags
}
fields {
slug
date
}
}
}
How can I change it to retrieve the same info from Strapi?
I'm really new to this Strapi world so I'm having a lot of doubts with the GraphQL, as I can't follow the guide from the Markdown query because the Information displayed is not the same.
I'm also having trouble differentiating between allStrapiArticles and StrapiArticle, what's the main purpose of those?
EDIT: I've been testing the existing queries on GraphiQL to check what they are returning and this is what I'm seeing:
For the tag.jsx query:
query TagPage($tag: String) {
allMarkdownRemark(
limit: 1000
sort: { fields: [fields___date], order: DESC }
filter: { frontmatter: { tags: { in: [$tag] } } }
) {
totalCount
edges {
node {
fields {
slug
date
}
excerpt
timeToRead
frontmatter {
title
tags
cover
date
}
}
}
}
}
GraphiQL returns nothing:
{
"data": {
"allMarkdownRemark": {
"totalCount": 0,
"edges": []
}
}
}
For the category.jsx query:
query CategoryPage($category: String) {
allMarkdownRemark(
limit: 1000
sort: { fields: [fields___date], order: DESC }
filter: { frontmatter: { category: { eq: $category } } }
) {
totalCount
edges {
node {
fields {
slug
date
}
excerpt
timeToRead
frontmatter {
title
tags
cover
date
}
}
}
}
}
In this case, everything works fine and it retrieves article data.
And for the case of the query I've added as an example in this post (upper part of the question) I'm getting the following error:
"errors": [
{
"message": "Variable \"$slug\" of required type \"String!\" was not provided."
...
Make sure you are passing your variable in through Query Variables at the bottom of GraphiQL.
First, I would query AllMarkdownRemark to make sure you're getting the nodes from Gatsby. Something like:
query MyQuery {
allMarkdownRemark {
edges {
node {
fields {
slug
}
frontmatter {
title
}
}
}
}
}
If the slug is showing up, then this should work:
Sometimes a slug is not being generated. Which should show up checking allMarkdownRemark.

Resources