{
    "componentChunkName": "component---src-components-blog-post-jsx",
    "path": "/blog/adding-instagram-timeline-to-next-js-site/",
    "result": {"data":{"site":{"siteMetadata":{"author":"Monica Powell","siteUrl":"https://www.aboutmonica.com"}},"mdx":{"id":"2c6b55d3-14b5-5d55-9a4e-4a80cdd3a196","timeToRead":3,"body":"var _excluded = [\"components\"];\n\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"title\": \"How to Add Instagram Timeline To a NextJS Site\",\n  \"date\": \"2020-12-21T22:10:20.914Z\",\n  \"template\": \"post\",\n  \"draft\": true,\n  \"slug\": \"adding-instagram-timeline-to-next-js-site\",\n  \"tags\": [\"NextJS\"],\n  \"category\": [\"tutorial\"],\n  \"description\": \"This article walks through how to integrate Instagram on a NextJS site.\"\n};\n\nvar makeShortcode = function makeShortcode(name) {\n  return function MDXDefaultShortcode(props) {\n    console.warn(\"Component \" + name + \" was not imported, exported, or provided by MDXProvider as global scope\");\n    return mdx(\"div\", props);\n  };\n};\n\nvar Callout = makeShortcode(\"Callout\");\nvar TableOfContents = makeShortcode(\"TableOfContents\");\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, _excluded);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(Callout, {\n    variant: \"danger\",\n    mdxType: \"Callout\"\n  }, \"Due to changes in the Instagram API the method for displaying Instagram photos in this article currently \", mdx(\"b\", null, \"does not work\"), \" due to CORS issues. I recommend\", \" \", mdx(\"a\", {\n    href: \"https://developers.facebook.com/docs/development/\"\n  }, \"applying for access to Facebook/Instagram APIs\"), \" \", \"for stable access to content hosted on Instagram.\"), mdx(\"p\", null, \"I recently added an Instagram timeline to my site \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://www.indigitalcolor.com/\"\n  }, \"In Digital Color\"), \" and wanted to share how I added the Instagram integration to my NextJS site and document some of the hiccups I encountered along the way with authentication.\"), mdx(\"p\", null, mdx(\"img\", {\n    parentName: \"p\",\n    \"src\": \"/media/in-digital-color-ig-integration-screenshot.png\",\n    \"alt\": null\n  })), mdx(\"p\", null, mdx(\"em\", {\n    parentName: \"p\"\n  }, \"Screenshot of Instagram Timeline integration on indigitalcolor.com\")), mdx(TableOfContents, {\n    headings: props.tableOfContents,\n    mdxType: \"TableOfContents\"\n  }), mdx(\"h2\", {\n    \"id\": \"install-and-import-instagram-web-api\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", {\n    parentName: \"h2\",\n    \"href\": \"#install-and-import-instagram-web-api\",\n    \"aria-label\": \"install and import instagram web api permalink\",\n    \"className\": \"anchor before\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"Install and import \", mdx(\"inlineCode\", {\n    parentName: \"h2\"\n  }, \"instagram-web-api\")), mdx(\"p\", null, \"We'll use the \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/jlobos/instagram-web-api\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"a\"\n  }, \"instagram-web-api\")), \" npm package to do the heavy lifting for the integration. which should be installed within a NextJS site with \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"npm install instagram-web-api\"), \" or \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"yarn add instagram-web-api\"), \". Once the package is successfully installed it should be imported into \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"index.js\"), \" file (or whichever page you would like the Instagram feed to appear on) with:\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-js\"\n  }, \"import Instagram from \\\"instagram-web-api\\\"\\n\")), mdx(\"p\", null, \"At this point the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"index.js\"), \" file where I imported \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"instagram-web-api\"), \" looks like this:\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-js\"\n  }, \"import Instagram from \\\"instagram-web-api\\\"\\nimport Layout from \\\"../components/layout\\\"\\n\\nexport default function Index() {\\n  return <Layout>{/*Other Page Content*/}</Layout>\\n}\\n\")), mdx(\"h2\", {\n    \"id\": \"setup-getstaticprops-to-fetch-data-at-build-time\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", {\n    parentName: \"h2\",\n    \"href\": \"#setup-getstaticprops-to-fetch-data-at-build-time\",\n    \"aria-label\": \"setup getstaticprops to fetch data at build time permalink\",\n    \"className\": \"anchor before\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"Setup getStaticProps to Fetch Data at Build Time\"), mdx(\"p\", null, \"Next, we need to set up a way to get fetched data into our component. In this case, I chose to use the async \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"a\"\n  }, \"getStaticProps\")), \" function to pass data into our component.\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"getStaticProps\"), \" is a function available to pages within NextJS that allows data to be fetched at build time and passed into page-level components.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-js\"\n  }, \"import Layout from \\\"../components/layout\\\"\\nimport Instagram from \\\"instagram-web-api\\\"\\n\\n// empty array of instagram posts is being\\n// passed as a prop into the Index component\\nexport default function Index({ instagramPosts }) {\\n  return <Layout>{/*Other Page Content*/}</Layout>\\n}\\n\\nexport async function getStaticProps(context) {\\n  // set posts to an empty array as a placeholder\\n  let posts = []\\n  return {\\n    props: {\\n      // return the posts as the prop instagramPosts\\n      // for the Index function to use\\n      instagramPosts: posts,\\n    },\\n  }\\n}\\n\")), mdx(\"h2\", {\n    \"id\": \"setup-instagram-client-authentication\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", {\n    parentName: \"h2\",\n    \"href\": \"#setup-instagram-client-authentication\",\n    \"aria-label\": \"setup instagram client authentication permalink\",\n    \"className\": \"anchor before\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"Setup Instagram Client Authentication\"), mdx(\"p\", null, \"Before we can retrieve data from Instagram we should set up authentication \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"instagram-web-api\"), \" in \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"getStaticProps()\"), \" to be able to fetch data from Instagram. We can accomplish this by setting up a new Instagram client with \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"new Instagram({username: IG_USERNAME, password: IG_PASSWORD})\"), \" and attempting to log in with \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"await client.login()\")), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-js\"\n  }, \"export async function getStaticProps(context) {\\n  // create a new client to communicate with  Instagram\\n  // this service requires authentication\\n  //with username and password parameters\\n  const client = new Instagram({\\n    username: process.env.IG_USERNAME,\\n    password: process.env.IG_PASSWORD,\\n  })\\n\\n  let images = []\\n  try {\\n    // attempt to log in to Instagram\\n    await client.login()\\n  } catch (err) {\\n    // throw an error if login to Instagram fails\\n    console.log(\\\"Something went wrong while logging into Instagram\\\", err)\\n  }\\n\\n  return {\\n    props: {\\n      instagramPosts: images,\\n    },\\n  }\\n}\\n\")), mdx(\"p\", null, \"Credentials such as the password should be accessed via environment variables that are only available locally and at build time to avoid exposing this information. In NextJS, local environment variables can be accessed by creating a file entitled \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \".env.development.local\"), \". Although the username is not a secret you can add it to the environment file if you'd like. \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"env.development.local\"), \" should be added to your \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \".gitignore\"), \" file to avoid committing it to version control. Separately, I set up my hosting to have access to the appropriate secrets at build time which supersedes the values in the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \".env\"), \" file.\"), mdx(\"p\", null, \"My \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"env.development.local\"), \" file looks like this:\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\"\n  }, \"IG_USERNAME=\\\"super_cool_username\\\"\\nIG_PASSWORD=\\\"super_secret_secure_password\\\"\\n\")), mdx(\"p\", null, \"In addition to the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"env.development.local\"), \" at a minimum you should have a \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \".env\"), \" file that sets the defaults for env variables. My \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \".env\"), \" file looks like and is checked into version control:\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\"\n  }, \"IG_USERNAME=\\\"\\\"\\nIG_PASSWORD=\\\"\\\"\\n\")), mdx(\"h2\", {\n    \"id\": \"confirm-instagram-client-is-functional\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", {\n    parentName: \"h2\",\n    \"href\": \"#confirm-instagram-client-is-functional\",\n    \"aria-label\": \"confirm instagram client is functional permalink\",\n    \"className\": \"anchor before\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"Confirm Instagram Client is Functional\"), mdx(\"p\", null, \"If you're not already you should run the development server of your NextJS site with \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"npm run next\"), \" and check in the terminal that is running the server to see if there are any console errors. You might encounter the error log we added of \\\"Something went wrong while logging into Instagram\\\" during this stage of the process.\"), mdx(\"h2\", {\n    \"id\": \"resolving-4xx-authentication-errors\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", {\n    parentName: \"h2\",\n    \"href\": \"#resolving-4xx-authentication-errors\",\n    \"aria-label\": \"resolving 4xx authentication errors permalink\",\n    \"className\": \"anchor before\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"Resolving 4xx Authentication Errors\"), mdx(\"p\", null, \"While I was setting up the Instagram client with the correct credentials I encountered various 4xx authentication relates errors (if you're not familiar with HTTP status codes check out my site \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://www.httriri.com/\"\n  }, \"https://www.httriri.com/\"), \") being returned to Instagram saying \\\"Please wait a few minutes before trying again\\\". I was able to temporarily circumnavigate the 4xx errors and \\\"Please wait a few minutes before trying again\\\" message by switching my IP address with a VPN (Virtual private network) and attempting to authenticate again. A VPN allows you to access the internet with a remote VPN server's IP address as opposed to your local IP address. \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://www.comparitech.com/blog/vpn-privacy/change-ip-address/\"\n  }, \"This article\"), \" shares other ways you can change your IP address. I already had a VPN configured on my computer so I found that to be the most straightforward solution in my case. Using a VPN to access the internet resolved the issues I was encountering as they were IP address level issues. You can check if your issues are IP level by trying to log into Instagram manually on the same IP address and on another device that is connected to a separate cellular network (and has its own IP). I am wondering if there's a more official way to get Instagram to recognize API usage as not being unusual activity. If you are running into a 4xx error for a different reason this is a good time to manually confirm that the credentials you are providing are correct.\"), mdx(\"h2\", {\n    \"id\": \"request-timeline-data-from-instagram\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", {\n    parentName: \"h2\",\n    \"href\": \"#request-timeline-data-from-instagram\",\n    \"aria-label\": \"request timeline data from instagram permalink\",\n    \"className\": \"anchor before\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"Request Timeline Data from Instagram\"), mdx(\"p\", null, \"Once authentication is successful we can request specific data from Instagram calling \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"client.getPhotosByUsername({username: process.env.IG_USERNAME})\"), \" to fetch timeline data for the username that is passed in.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-js\"\n  }, \"export async function getStaticProps(context) {\\n  const client = new Instagram({\\n    username: process.env.IG_USERNAME,\\n    password: process.env.IG_PASSWORD,\\n  })\\n\\n  let posts = []\\n  try {\\n    await client.login()\\n    // request photos for a specific instagram user\\n    const instagram = await client.getPhotosByUsername({\\n      username: process.env.IG_USERNAME,\\n    })\\n\\n    if (instagram[\\\"user\\\"][\\\"edge_owner_to_timeline_media\\\"][\\\"count\\\"] > 0) {\\n      // if we receive timeline data back\\n      //  update the posts to be equal\\n      // to the edges that were returned from the instagram API response\\n      posts = instagram[\\\"user\\\"][\\\"edge_owner_to_timeline_media\\\"][\\\"edges\\\"]\\n    }\\n  } catch (err) {\\n    console.log(\\n      \\\"Something went wrong while fetching content from Instagram\\\",\\n      err\\n    )\\n  }\\n\\n  return {\\n    props: {\\n      instagramPosts: posts, // returns either [] or the edges returned from the Instagram API based on the response from the `getPhotosByUsername` API call\\n    },\\n  }\\n}\\n\")), mdx(\"h2\", {\n    \"id\": \"render-instagram-data-with-instagramfeed-component\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", {\n    parentName: \"h2\",\n    \"href\": \"#render-instagram-data-with-instagramfeed-component\",\n    \"aria-label\": \"render instagram data with instagramfeed component permalink\",\n    \"className\": \"anchor before\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"Render Instagram Data with InstagramFeed component\"), mdx(\"p\", null, \"Once we've successfully received timeline data back from the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"getPhotosByUsername()\"), \" call we can render this data. Below is the skeleton I used to transform the data returned from the Instagram API into a digestible and visually engaging component that displays recent photos and links to them on Instagram so that visitors can click through to the actual posts.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-js\"\n  }, \"import Link from \\\"next/link\\\"\\n\\nexport default function InstagramFeed({ instagramPosts }) {\\n  return (\\n    <>\\n      <h2>\\n        <a href=\\\"https://www.instagram.com/yourinstagramhandle/\\\">\\n          Follow Us on Instagram\\n        </a>\\n        .\\n      </h2>\\n\\n      <ul>\\n        {/* let's iterate through each of the\\n         instagram posts that were returned\\n         from the Instagram API*/}\\n        {instagramPosts.map(({ node }, i) => {\\n          return (\\n            // let's wrap each post in an anchor tag\\n            // and construct the url for the post using\\n            // the shortcode that was returned from the API\\n            <li>\\n              <a\\n                href={`https://www.instagram.com/p/${node.shortcode}`}\\n                key={i}\\n                aria-label=\\\"view image on Instagram\\\"\\n              >\\n                {/* set the image src equal to the image\\n                url from the Instagram API*/}\\n                <img\\n                  src={node.thumbnail_src}\\n                  alt={\\n                    // the caption with hashtags removed\\n                    node.edge_media_to_caption.edges[0].node.text\\n                      .replace(/(#\\\\w+)+/g, \\\"\\\")\\n                      .trim()\\n                  }\\n                />\\n              </a>\\n            </li>\\n          )\\n        })}\\n      </ul>\\n    </>\\n  )\\n}\\n\")), mdx(\"p\", null, \"In order to actually render this component and the associated post data from Instagram we need to import \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"InstagramFeed\"), \" into \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"index.js\"), \" and render it within the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Index\"), \" component with the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"instagramPosts\"), \" prop we received from \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"getStaticProps\"), \".\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-js\"\n  }, \"import Layout from \\\"../components/layout\\\"\\nimport Instagram from \\\"instagram-web-api\\\"\\nimport InstagramFeed from \\\"../components/instagramFeed\\\"\\n// empty array of instagram posts is being\\n// passed as a prop into the Index component\\nexport default function Index({ instagramPosts }) {\\n  return (\\n    <Layout>\\n      {/*Other Page Content*/}\\n      <InstagramFeed instagramPosts={instagramPosts} />\\n    </Layout>\\n  )\\n}\\n\")), mdx(\"p\", null, \"If everything worked properly you should now see all of your latest Instagram posts rendered on the page and be able to click any given posts to be taken to it on Instagram. If you are not seeing any posts rendering there may have been an issue with authentication (invalid credentials or rate limited by Instagram). If so, I recommend following my above troubleshooting steps of manually verifying credentials (in case of invalid credentials) or exploring using a VPN (if your IP address has been rate limited).\"));\n}\n;\nMDXContent.isMDXComponent = true;","tableOfContents":{"items":[{"url":"#install-and-import-instagram-web-api","title":"Install and import instagram-web-api"},{"url":"#setup-getstaticprops-to-fetch-data-at-build-time","title":"Setup getStaticProps to Fetch Data at Build Time"},{"url":"#setup-instagram-client-authentication","title":"Setup Instagram Client Authentication"},{"url":"#confirm-instagram-client-is-functional","title":"Confirm Instagram Client is Functional"},{"url":"#resolving-4xx-authentication-errors","title":"Resolving 4xx Authentication Errors"},{"url":"#request-timeline-data-from-instagram","title":"Request Timeline Data from Instagram"},{"url":"#render-instagram-data-with-instagramfeed-component","title":"Render Instagram Data with InstagramFeed component"}]},"frontmatter":{"title":"How to Add Instagram Timeline To a NextJS Site","date":"December 21, 2020","description":"This article walks through how to integrate Instagram on a NextJS site.","tags":["NextJS"]}},"allWebMentionEntry":{"edges":[{"node":{"wmTarget":"https://www.aboutmonica.com/blog/adding-instagram-timeline-to-next-js-site/","wmSource":"https://brid.gy/like/twitter/indigitalcolor/1359140132834725890/817045432966742016","wmProperty":"like-of","wmId":1032829,"type":"entry","url":"https://twitter.com/indigitalcolor/status/1359140132834725890#favorited-by-817045432966742016","likeOf":"https://www.aboutmonica.com/blog/adding-instagram-timeline-to-next-js-site/","author":{"url":"https://twitter.com/cc_utr","type":"card","photo":"https://webmention.io/avatar/pbs.twimg.com/c8c013e97f70e144e21d7612214e779f49f7c6c9285c5e9ca753f3ac8d3b3bdd.jpg","name":"Creative Coding Utrecht"},"published":null,"content":null}},{"node":{"wmTarget":"https://www.aboutmonica.com/blog/adding-instagram-timeline-to-next-js-site/","wmSource":"https://brid.gy/like/twitter/indigitalcolor/1359140132834725890/15111972","wmProperty":"like-of","wmId":1025192,"type":"entry","url":"https://twitter.com/indigitalcolor/status/1359140132834725890#favorited-by-15111972","likeOf":"https://www.aboutmonica.com/blog/adding-instagram-timeline-to-next-js-site/","author":{"url":"https://twitter.com/sergeyche","type":"card","photo":"https://webmention.io/avatar/pbs.twimg.com/54950d7bb52b8577f4095a51b2fb371bc2983d8bbeac43b2ccacccf48bf1070b.jpg","name":"Sergey Chernyshev"},"published":null,"content":null}},{"node":{"wmTarget":"https://www.aboutmonica.com/blog/adding-instagram-timeline-to-next-js-site/","wmSource":"https://brid.gy/like/twitter/indigitalcolor/1359140132834725890/18762994","wmProperty":"like-of","wmId":1024605,"type":"entry","url":"https://twitter.com/indigitalcolor/status/1359140132834725890#favorited-by-18762994","likeOf":"https://www.aboutmonica.com/blog/adding-instagram-timeline-to-next-js-site/","author":{"url":"https://twitter.com/laralfield","type":"card","photo":"https://webmention.io/avatar/pbs.twimg.com/2fb5301114074bf1dfa6b6dd18519ba04a665f3e368ff35b6b7d6d7693c66d2e.jpg","name":"Lara Littlefield"},"published":null,"content":null}},{"node":{"wmTarget":"https://www.aboutmonica.com/blog/adding-instagram-timeline-to-next-js-site/","wmSource":"https://brid.gy/like/twitter/indigitalcolor/1359140132834725890/1111007023041310725","wmProperty":"like-of","wmId":1024603,"type":"entry","url":"https://twitter.com/indigitalcolor/status/1359140132834725890#favorited-by-1111007023041310725","likeOf":"https://www.aboutmonica.com/blog/adding-instagram-timeline-to-next-js-site/","author":{"url":"https://twitter.com/SylwiaVargas","type":"card","photo":"https://webmention.io/avatar/pbs.twimg.com/845184ade9fa4f65528d67fefe48c4e61f03a5678ae8e965180bc19c47fe208b.jpg","name":"sylwia vargas"},"published":null,"content":null}},{"node":{"wmTarget":"https://www.aboutmonica.com/blog/adding-instagram-timeline-to-next-js-site/","wmSource":"https://brid.gy/like/twitter/indigitalcolor/1359140132834725890/3072201246","wmProperty":"like-of","wmId":1024604,"type":"entry","url":"https://twitter.com/indigitalcolor/status/1359140132834725890#favorited-by-3072201246","likeOf":"https://www.aboutmonica.com/blog/adding-instagram-timeline-to-next-js-site/","author":{"url":"https://twitter.com/almostengr","type":"card","photo":"https://webmention.io/avatar/pbs.twimg.com/93dcac46be31663fd02378fd915507caa9bf2275bcca9b581ea72a4528d367f1.jpg","name":"Kenny Robinson"},"published":null,"content":null}},{"node":{"wmTarget":"https://www.aboutmonica.com/blog/adding-instagram-timeline-to-next-js-site/","wmSource":"https://brid-gy.appspot.com/like/twitter/indigitalcolor/1351672593380765698/36206557","wmProperty":"like-of","wmId":995946,"type":"entry","url":"https://twitter.com/indigitalcolor/status/1351672593380765698#favorited-by-36206557","likeOf":"https://www.aboutmonica.com/blog/adding-instagram-timeline-to-next-js-site/","author":{"url":"https://twitter.com/RococoCode","type":"card","photo":"https://webmention.io/avatar/pbs.twimg.com/2c224c8ed102d0ff04b3208d1e354e2ad73c59a071d609a1c9c461343beb5028.jpg","name":"Alice Chang (she/her)"},"published":null,"content":null}},{"node":{"wmTarget":"https://www.aboutmonica.com/blog/adding-instagram-timeline-to-next-js-site/","wmSource":"https://brid-gy.appspot.com/like/twitter/indigitalcolor/1351672593380765698/249311093","wmProperty":"like-of","wmId":995945,"type":"entry","url":"https://twitter.com/indigitalcolor/status/1351672593380765698#favorited-by-249311093","likeOf":"https://www.aboutmonica.com/blog/adding-instagram-timeline-to-next-js-site/","author":{"url":"https://twitter.com/Epwnaz","type":"card","photo":"https://webmention.io/avatar/pbs.twimg.com/92371f3ff0244e398bbeb117b6bc22460a36ce6c71c111f4d878d440c1016a63.jpg","name":"Epwnaz 🏳️‍🌈"},"published":null,"content":null}},{"node":{"wmTarget":"https://www.aboutmonica.com/blog/adding-instagram-timeline-to-next-js-site/","wmSource":"https://brid-gy.appspot.com/post/twitter/waterproofheart/1341353382930509825","wmProperty":"mention-of","wmId":958705,"type":"entry","url":"https://twitter.com/indigitalcolor/status/1341353382930509825","likeOf":null,"author":{"url":"https://twitter.com/indigitalcolor","type":"card","photo":"https://webmention.io/avatar/pbs.twimg.com/b17a181a222b006c4de292e40f80a97674c9ce4d5ec3bf2ead3176653549519c.jpg","name":"Monica.dev"},"published":"December 22, 2020","content":{"text":"I wrote an article about my experience using the Instagram API with NextJS and debugging with a VPN aboutmonica.com/blog/adding-in…"}}}]}},"pageContext":{"permalink":"https://www.aboutmonica.com/blog/adding-instagram-timeline-to-next-js-site/","slug":"/blog/adding-instagram-timeline-to-next-js-site/","prev":{"id":"74af4e23-40a4-5870-9136-80bf16cedb48","frontmatter":{"title":"Creating New Supabase Users In NextJS","category":["tutorial"],"date":"2021-03-09T12:01:39.955Z","slug":"creating-new-supabase-users-in-next-js","tags":["NextJS","Supabase"],"redirects":null},"fields":{"slug":"/blog/creating-new-supabase-users-in-next-js/"}},"next":{"id":"1009dcc4-63ab-56e4-9a36-f01098c8dc9c","frontmatter":{"title":"Getting Started With Webmention and NextJS","category":["tutorial"],"date":"2020-10-03T16:51:30.675Z","slug":"getting-started-with-webmention-next-js","tags":["JavaScript","Webmention","Video","NextJS"],"redirects":null},"fields":{"slug":"/blog/getting-started-with-webmention-next-js/"}}}},
    "staticQueryHashes": ["1977783444","764694655"]}