diff --git a/docs/blog/2019-10-14-adding-anchors-to-gatsby/index.md b/docs/blog/2019-10-14-adding-anchors-to-gatsby/index.md
new file mode 100644
index 0000000000000..32335346374f1
--- /dev/null
+++ b/docs/blog/2019-10-14-adding-anchors-to-gatsby/index.md
@@ -0,0 +1,229 @@
+---
+title: "Adding Anchors 🔗 to Gatsby, using Sanity.io"
+date: 2019-10-14
+author: "ajonp"
+excerpt: "Have you ever hunted around for days trying to find that simple package for adding anchor links to your Gatsby blog? It is easier than you might think!"
+tags: ["browser-apis", "sanity"]
+canonicalLink: https://ajonp.com/blog/anchor-links-from-sanity-in-gatsby
+publishedAt: ajonp.com
+---
+
+![Gatsby Link](https://res.cloudinary.com/ajonp/image/upload/v1571083718/ajonp-ajonp-com/blog/gatsby-anchor-links/Gatsby_Sanity_Anchor_Links.webp)
+
+# Anchor Links 🔗 from Sanity in Gatsby
+
+> TL;DR version is make sure you implement `onRouteUpdate` and `shouldUpdateScroll` in `gatsby-browser.js`.
+
+## So what is an anchor link?
+
+Anchor links are a way to navigate within the same page in HTML. The easiest way to think of them are like a table of contents, or bookmarks on a page.
+You will see anchors used often in markdown pages that have header tags in the form of `#`. Now in order for those normal header tags to have a link they must be wrapped on the front end with a link tag, similar to this: `Headline Link
`. If you inspect the code on this page, you will even see an example of just that, as the blog is written in markdown and converted to HTML.
+
+## Sanity.io
+
+### How does this work with Sanity.io
+
+[Sanity](https://www.sanity.io/) is a headless content based CMS. You write in a [rich text editor](https://www.sanity.io/docs/what-you-need-to-know-about-block-text), which creates [portable text](https://www.portabletext.org/). So unlike markdown you wont have to convert header `#` items but you will have to serialize the portable text into something that Gatsby can understand. I won't dive too deeply into how you create a site using sanity.io there are some [great guides](https://www.gatsbyjs.org/packages/gatsby-source-sanity/?=sanity#gatsby-source-sanity) for that using `gatsby-source-sanity`.
+
+### Extending the Sanity Gatsby blog
+
+Sanity.io's Gatsby [blog example](https://www.sanity.io/guides/the-blog-template), is a great starting point for how to get up and running quickly. You can use that and then extend the functionality however you would like. In the example there is a file for posts which looks similar to below, what we really care about is the line `
{props.children}+ ) : ( +
{props.children}
+ ) +} +``` + +## Adding Gatsby Anchor Links + +Now even though, Knut Melvær has a great guide called [Internal and external links](https://www.sanity.io/guides/portable-text-internal-and-external-links) that covers in great detail how to add links to your front end, I am a fairly lazy developer and I don't want to manually select and add all of my anchor links so that is why I used the above method. This same approach can be made using markdown files using [gatsby-remark-autolink-headers](https://www.gatsbyjs.org/packages/gatsby-remark-autolink-headers/?=remark). + +The one missing piece I found is scrolling to the correct location within the page in Gatsby. In order to do this Gatsby provides some awesome [browser-apis](https://www.gatsbyjs.org/docs/browser-apis/). In order for the scrolling to occur when the page is first loaded we need to use `onRouteUpdate` this will allow us to use the location and check for an existance for `hash` which is our anchor link. I also implemented `shouldUpdateScroll` as selecting an internal link did not trigger a route update, so this was needed without refresh. + +gatsby-browser.js + +```js +/** + * Implement Gatsby's Browser APIs in this file. + * + * See: https://www.gatsbyjs.org/docs/browser-apis/ + */ + +// You can delete this file if you're not using it + +exports.onRouteUpdate = ({ location }) => { + anchorScroll(location) + return true +} +exports.shouldUpdateScroll = ({ + routerProps: { location }, + getSavedScrollPosition, +}) => { + anchorScroll(location) + return true +} + +function anchorScroll(location) { + // Check for location so build does not fail + if (location && location.hash) { + setTimeout(() => { + // document.querySelector(`${location.hash}`).scrollIntoView({ behavior: 'smooth', block: 'start' }); + const item = document.querySelector(`${location.hash}`).offsetTop + const mainNavHeight = document.querySelector(`nav`).offsetHeight + window.scrollTo({ + top: item - mainNavHeight, + left: 0, + behavior: "smooth", + }) + }, 0) + } +} +``` + +## Final result + +A nice smooth scrolling screen on refresh and internal link click. + + diff --git a/docs/blog/author.yaml b/docs/blog/author.yaml index c6a12fd9017af..a3de125d882e3 100644 --- a/docs/blog/author.yaml +++ b/docs/blog/author.yaml @@ -357,3 +357,7 @@ bio: Creates tools that make designers & developers better at what they do. Polypane.rocks and Superposition.design | @kilianvalkhof | https://kilianvalkhof.com/ avatar: avatars/kilian-valkhof.jpg twitter: "@kilianvalkhof" +- id: ajonp + bio: A Community of developers, creating resources for all to use! | @ajonpcom | https://ajonp.com + avatar: avatars/ajonp.png + twitter: "@ajonpcom" diff --git a/docs/blog/avatars/ajonp.png b/docs/blog/avatars/ajonp.png new file mode 100644 index 0000000000000..eb8d57b371caa Binary files /dev/null and b/docs/blog/avatars/ajonp.png differ