I am trying to call my Dribble posts onto my Gatsby website.
I followed the tutorial by this article https://medium.com/#nithin_94885/dribbble-shots-in-your-website-v2-api-5945a355d106, where I generated my Access Token from Dribble (a unique code to allow my gatsby site to access my dribble posts).
I am having trouble figuring out where to add the script that calls the API in my gatsby site.
I have tried pasting it to my gatsby-node.js file (In the past I thought this was where the script should go)
I am quite the newbie.. if the script that calls the Dribble API looks like this:
// Set the Access Token
var accessToken = '9f061d26c5a8be96b17a81718959a67dd54ca9669ca41752777193f7cc5be7c3';
// Call Dribble v2 API
$.ajax({
url: 'https://api.dribbble.com/v2/user/shots?access_token='+accessToken,
dataType: 'json',
type: 'GET',
success: function(data) {
if (data.length > 0) {
$.each(data.reverse(), function(i, val) {
$('#shots').prepend(
'<a class="shot" target="_blank" href="'+ val.html_url +'" title="' + val.title + '"><div class="title">' + val.title + '</div><img src="'+ val.images.hidpi +'"/></a>'
)
})
}
else {
$('#shots').append('<p>No shots yet!</p>');
}
}
});
and my gatsby-node.js file looks like this:
const path = require('path');
const { createFilePath } = require('gatsby-source-filesystem');
// Look at every node when it is created
exports.onCreateNode = ({node, getNode, actions}) => {
// Check for markdown nodes
const { createNodeField } = actions;
if(node.internal.type === 'MarkdownRemark') {
// Create a slug out of the markdown filepath name
const slug = createFilePath({
node,
getNode,
basePath: 'projects'
});
// Add the newly created slug to the node itself
createNodeField({
node,
name: 'slug',
value: `/project${slug}`
});
}
};
exports.createPages = ({ graphql, actions }) => {
const { createPage } = actions
return new Promise((resolve, reject) => {
graphql(`
{
allMarkdownRemark {
edges {
node {
fields {
slug
}
}
}
}
}
`).then(result => {
result.data.allMarkdownRemark.edges.forEach(({ node }) => {
createPage({
path: node.fields.slug,
component: path.resolve(`./src/templates/project.js`),
context: {
// Data passed to context is available in page queries as GraphQL variables.
slug: node.fields.slug,
},
})
})
resolve()
})
})
};
How can I add the script so that the API script will call my shots in Dribble to link back to it?
I expected this to be an easy solution but I have been struggling with this Dribble/Gatsby integration for days now. :(
Related
I have set up an ACF options page in WordPress called Projects
Inside the Projects options page there is an ACF repeater allowing the user to add multiple Projects.
In Gatsby, I’m using Graphql to query the data for my Projects in two files:
Inside a custom hook, allowing access to the data globally in my Gatsby site
Inside a gatsby-node.js file in order to generate a slug for my template page called project-details.js
Obviously there is no slug in Graphql for this repeater field in the ACF options page. Instead, I’m generating a slug based on a nested Title text field that’s found inside each Project repeater field.
I’m using both the replaceAll() and toLowerCase() methods to create the slug and then making it available as part of my data.
Here's my custom hook:
export const useProjectsQueryAlt = () => {
const data = useStaticQuery(graphql`
query ProjectsQueryAlt {
wp {
projects {
projects {
allprojects {
projectContent
projectTitle
featuredImage {
mediaItemUrl
id
}
projectGallery {
caption
id
mediaItemUrl
}
}
}
}
}
}
`)
const project = data.wp.projects.projects.allprojects.map(node => {
const { projectContent, projectTitle, featuredImage, projectGallery } = node;
const title = node.projectTitle;
const spacesToHyphen = title.replaceAll(' ', '-');
const slugFromTitle = spacesToHyphen.toLowerCase()
return {
projectContent,
projectTitle,
slug: slugFromTitle,
featuredImage,
projectGallery: projectGallery.map(node => {
const { caption, id, mediaItemUrl } = node;
return {
caption,
id,
mediaItemUrl
}
})
}
})
return { project }
}
Here's my gatsby-node file:
const path = require('path')
exports.createPages = async ({ graphql, actions }) => {
const { data } = await graphql(`
query Projects {
wp {
projects {
projects {
allprojects {
projectTitle
}
}
}
}
}
`)
data.wp.projects.projects.allprojects.forEach(node => {
const title = node.projectTitle;
const spacesToHyphen = title.replaceAll(' ', '-');
const slugFromTitle = spacesToHyphen.toLowerCase()
actions.createPage({
path: '/projects/' + slugFromTitle,
component: path.resolve('./src/templates/project-details.js'),
context: { slug: slugFromTitle },
})
})
}
Here's my template file project-details.js
import React from 'react'
function ProjectDetails() {
return (
<div>
...my page template content
</div>
)
}
export default ProjectDetails
I now need to find a way to check that the two appended slugs match in my ‘project-details.js’ template file in order to display the relevant project data to the corresponding URL.
Seeing as I’ve generated my slugs on the front end, following the Gatsby Docs for setting up dynamically generate pages doesn’t align with my use case. I was hoping somebody has had experience with this use case and can point me in the right direction.
The problem in your approach is that you are generating a "fake" slug based on the title of the project so you can't use that field to filter any GraphQL node because the field is not present in the project fields. Your best option is using the title itself or using any autogenerated identifier (id, if it's present as a field).
actions.createPage({
path: '/projects/' + slugFromTitle,
component: path.resolve('./src/templates/project-details.js'),
context: { title },
})
Note: you can omit { title: title }
You can still use the path of your generated slug, this is a valid approach.
I'm assuming that if the title is a unique field, the slug must be too, hence you will be a valid filter.
Now in the project-details.js:
import React from 'react'
function ProjectDetails({ data }) {
console.log("my data is", data);
return (
<div>
...my page template content
</div>
)
}
export const query = graphql`
query($title: String!) {
yourACFNode(title: { eq: $title} ) {
# your fields
}
}
`
export default ProjectDetails
Of course, tweak the query above to match your ACF node but get the approach.
I would like to obtain all (or a subset) of my records from an Algolia index and access them via GraphQL.
I know there is a Gatsby plugin that allows you to do the opposite i.e., add data from a GraphQL query to Algolia, but not the other way around.
I have been able to get the tutorial for adding GraphQL data to work, but I have not had any success when trying to go beyond hardcoded arrays (this is in the gatsby-node.js file):
const algoliasearch = require("algoliasearch/lite");
const searchClient = algoliasearch(
process.env.GATSBY_ALGOLIA_APP_ID,
process.env.GATSBY_ALGOLIA_SEARCH_KEY
)
const searchIndex = searchClient.initIndex(process.env.GATSBY_ALGOLIA_INDEX_NAME)
exports.sourceNodes = ({ actions, createNodeId, createContentDigest }) => {
searchIndex.search("", {
attributesToRetrieve: ["name", "url"]
}).then(({ hits }) => {
hits.forEach(hit => {
const node = {
name: hit.name,
url: hit.url,
id: createNodeId(`hit-${hit.name}`),
internal: {
type: "hit",
contentDigest: createContentDigest(hit),
},
}
actions.createNode(hit)
})
});
}
While the console successfully logs the array of nodes, and the verbose Gatsby deploy output includes the "hit" node as a node type, they do not appear in the GraphQL explorer.
Any help is greatly appreciated, thank you!
I'm developing an express vue app. I have a problem in displaying image in vue.
In a vue page, I run an axios.get in vue js beforeMount hook, and get images data in base64 from API.
Then save data in an array. I don't see images but texts haven't problem. In some page refreshes like editing code and ... I see images but then problem remain.
vue js code:
<template>
<div v-for="(designImg, i) in designImgs" :key="i">
<q-img
:src="designImg"
height="100px"
class="bg-grey-4"
/>
</div>
<template>
<script>
data () {
return {
designImgs: null
}
},
beforeMount () {
this.$axios.get('shop/product', {
params: {
designId: this.$route.params.designId,
}
}).then((res) => {
if (res.data.error) {
console.log(res.data.error)
} else {
const designImgUrls = res.data.imageUrls.split(',')
const mydesignImgs = []
for (let i = 0; i < designImgUrls.length; i++) {
this.$axios.get('/shop/image', {
params: {
url: designImgUrls[i]
}
}).then((res) => {
const url1 = 'data:image/jpeg;base64, ' + res.data
mydesignImgs[i] = url1
}).catch(err => {
console.log(err)
})
}
this.designImgs = mydesignImgs
}
}).catch((err) => {
console.log(err)
})
}
<script>
Note that in above code we recieve from server these data:
imageUrls: "uploads\imagee-1592862806606.jpg,uploads\imagee-1592862806654.jpg"
and then after getting images data res.data is equals to a base64 image data like this:
/9j/2wBDAAYEBQYFBAY...
I have solved this problem.
I have changed the way of collecting image data in mydesignImgs array.
i have used this code:
mydesignImgs.push(url1)
instead of using this equality:
mydesignImgs[i] = url1
but why?
I have set up a blog using Gatsby's starter template. Right now, when I open an article, the url it shows is- http://localhost:8000/JavaScript:%20Behind%20The%20Scenes/. I looked up this answer and changed the path property but then the page wouldn't load, it just showed an empty page with the same url. I don't know why it's appending %20 in the path.
Note: The path is actually the folder name. For example, in the directory /content/blog/JavaScript:Behind The Scenes/index.md, path that goes in the url is actually the folder name. I don't know why. Path should've been the title that I've written in index.md of that folder.
index.md
---
title: 'The Execution Context'
date: '2020-02-16'
category: "JavaScript"
---
Blog Content..............
gatsby-node.js
const path = require(`path`)
const { createFilePath } = require(`gatsby-source-filesystem`)
exports.createPages = ({ graphql, actions }) => {
const { createPage } = actions
const blogPostTemplate = path.resolve(`./src/templates/blog-post.js`)
return graphql(
`
{
allMarkdownRemark(
sort: { fields: [frontmatter___date], order: DESC }
limit: 1000
) {
edges {
node {
fields {
slug
}
frontmatter {
title
category
}
}
}
}
}
`
).then(result => {
if (result.errors) {
throw result.errors
}
// Create blog posts pages.
const posts = result.data.allMarkdownRemark.edges.filter(
({ node }) => !!node.frontmatter.category
)
posts.forEach((post, index) => {
const previous = index === posts.length - 1 ? null : posts[index + 1].node
const next = index === 0 ? null : posts[index - 1].node
createPage({
path: post.node.fields.slug,
component: blogPostTemplate,
context: {
slug: post.node.fields.slug,
previous,
next,
},
})
})
})
}
exports.onCreateNode = ({ node, actions, getNode }) => {
const { createNodeField } = actions
if (node.internal.type === `MarkdownRemark`) {
const value = createFilePath({ node, getNode })
createNodeField({
name: `slug`,
node,
value,
})
}
}
Also, I have some problem with the Github and Twitter links. When I click them, it shows page not found. It's showing weird url: https://github.com/https://github.com/myGithubName
https://twitter.com/https://twitter.com/myTwitterName
I checked in where is this located and found out:
gatsby-meta-config.js
module.exports = {
title: `My Blog`,
description: `Blog posted about ...`,
author: `myName`,
introduction: `I explain with words and code.`,
siteUrl: `https://gatsby-starter-bee.netlify.com`, // Your blog site url
social: {
twitter: `https://twitter.com/myTwitterName`, // Your Twitter account
github: `https://github.com/myGithubName`,
medium: ``,
facebook: ``
},
icon: `content/assets/profile.jpeg`, // Add your favicon
keywords: [`blog`],
comment: {
disqusShortName: '', // Your disqus-short-name. check disqus.com.
utterances: 'JaeYeopHan/gatsby-starter-bee', // Your repository for archive comment
},
configs: {
countOfInitialPost: 10, // Config your initial count of post
},
sponsor: {
buyMeACoffeeId: 'jbee',
},
share: {
facebookAppId: '', // Add facebookAppId for using facebook share feature v3.2
},
ga: '', // Add your google analytics tranking ID
}
The links seem correct in gatsby-meta-config.js.
I don't know why it's appending %20 in the path.
%20 is the HTML encoding for a space inside the url. You cannot have spaces in your url so it is by default escaped by the HTML encoding.
the url is actually the folder name. I don't know why. Path should've been the title that I've written in index.md of that folder.
You do not do any formatting to your slug in gatsby-node.js:
createNodeField({
name: `slug`,
node,
value,
})
Without formatting the slug, your url defaults to the path inside your project.
My advise: Don't format the slug. Remove spaces from your folder path and you have a nice url: /content/blog/javascript-behind-the-scenes/index.md. The use of the hypen character - is also recommened by Google. Having an URL like that ranks better in SEO.
Also, I have some problem with the Github and Twitter links. When I click them, it shows page not found. Weird url it shows is: https://github.com/https://github.com/myGithubName https://twitter.com/https://twitter.com/myTwitterName
Supply only your social network's username in your gatsby-config.js:
social: {
twitter: `myTwitterName`, // remove everything before your username
github: `myGithubName`, // remove everything before your username
medium: ``,
facebook: ``
},
I have the following graphql query that is executing at build time from my gatsby-node.js file that I'm using to bring in my article data. Is there a way to use Apollo/Axios to retrieve new articles without having to rebuild the site essentially rehydrating my site in between builds? Any help is greatly appreciated!!
I'm using Gatsby v2, Drupal as my CMS and GraphQL.
exports.createPages = ({ graphql, actions }) => {
const { createPage } = actions;
const blogTemplate = path.resolve('src/templates/blog-post.js');
return graphql(`
{
blog: allNodeArticle{
edges {
node {
id
path {
alias
}
}
}
}
`
).then(result => {
if (result.errors) {
Promise.reject(result.errors);
}
// Create blog pages
result.data.blog.edges.forEach(({ node }) => {
createPage({
path: node.path.alias,
component: blogTemplate,
context: {
alias: node.path.alias,
},
});
});
});
}
I would like to merge in the new data as it becomes available while keeping older data completely static (massive benefit of Gatsby)