<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Contentful</title>
    <description>The latest articles on Forem by Contentful (@contentful).</description>
    <link>https://forem.com/contentful</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F390%2F6233b08f-25c6-4d56-98bb-10a1ea51bad0.png</url>
      <title>Forem: Contentful</title>
      <link>https://forem.com/contentful</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/contentful"/>
    <language>en</language>
    <item>
      <title>Create a bot with RSS and webhooks for Mastodon, a Twitter alternative</title>
      <dc:creator>Bulent Osman Yusuf</dc:creator>
      <pubDate>Tue, 22 Nov 2022 14:07:09 +0000</pubDate>
      <link>https://forem.com/contentful/create-a-bot-with-rss-and-webhooks-for-mastodon-a-twitter-alternative-l4o</link>
      <guid>https://forem.com/contentful/create-a-bot-with-rss-and-webhooks-for-mastodon-a-twitter-alternative-l4o</guid>
      <description>&lt;p&gt;&lt;strong&gt;Looking for a Twitter alternative? Here's two ways to set up a bot to automatically publish content from your Contentful space to your Mastodon server.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;&lt;em&gt;NB: This post was &lt;a href="https://www.contentful.com/blog/create-bot-rss-webhooks-mastodon-twitter-alternative/" rel="noopener noreferrer"&gt;first published on the Contentful Blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In recent weeks there’s been a huge surge in interest for an alternative to Twitter. Whether folks want to stretch their wings by learning about new social media platforms, or they’re looking for a simple Twitter replacement, an open source service called Mastodon is trending as the clear favorite.&lt;/p&gt;

&lt;p&gt;But there are things to take into account when using Mastodon for the first time. It has its own rules, vocabulary, and ways of operation. Tweets are now “toots.” You no longer have a universal timeline like Twitter, for example, but a thing called a federated timeline. And there’s even an edit button!&lt;/p&gt;

&lt;p&gt;In this post, we’ll take a quick tour of Mastodon – and, by extension, a mysterious place called the fediverse (oooooooh). We’ll also show you two simple ways to set up a bot to automatically publish content from your Contentful space to your Mastodon server of choice. Ready? Let’s go!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Mastodon?
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://joinmastodon.org/" rel="noopener noreferrer"&gt;Mastodon&lt;/a&gt; project first went live in October 2016, and is the creation of software engineer &lt;a href="https://mastodon.online/@Gargron@mastodon.social" rel="noopener noreferrer"&gt;Eugen Rochko&lt;/a&gt;. The mascot of the service is an adorable wooly mammoth. The concept is a decentralized social network built from free and open source software, where individuals have the ability to quickly spin up and self-host their own social networking services – while still being able to interact and communicate with one another. &lt;/p&gt;

&lt;p&gt;Growth in the past few weeks has been absolutely stellar. &lt;a href="https://mastodon.social/@Gargron/109300967725833789" rel="noopener noreferrer"&gt;According to a toot by Eugen on 7 November&lt;/a&gt;, “Hey, so, we’ve hit 1,028,362 monthly active users across the network today. 1,124 new Mastodon servers since Oct. 27, and 489,003 new users. That’s pretty cool.”&lt;/p&gt;

&lt;p&gt;Cool is an understatement!&lt;/p&gt;

&lt;h2&gt;
  
  
  What about the Fediverse?
&lt;/h2&gt;

&lt;p&gt;Mastodon as a service embodies all the characteristics of a &lt;a href="https://en.wikipedia.org/wiki/Fediverse" rel="noopener noreferrer"&gt;fediverse&lt;/a&gt;, which is shorthand for federated universe; a set of distinct but interconnected web publishing servers (also known as a node or instance) sharing the same protocols for communication. You have the option to follow and interact with people within your own server (your local timeline) but also with the denizens of neighboring servers which might be dedicated to different interests and specialisms (a federated timeline).&lt;/p&gt;

&lt;p&gt;For example, Person A could start a social media node using the Mastodon protocol dedicated to lovers of apples, while Person B could start one dedicated to those who prefer oranges. Users of either social network can freely interact with each other, talk about the joys of fruit salad, and attract followers and comments from both places. But they can also choose to confine themselves to their own network about their preferred fruit. Either option is entirely valid.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is it free to use Mastodon?
&lt;/h2&gt;

&lt;p&gt;Yes. Mastodon is funded entirely by &lt;a href="https://joinmastodon.org/sponsors" rel="noopener noreferrer"&gt;sponsors&lt;/a&gt; who cover the cost of operating individual servers or the salaries of volunteers running them. It’s ad-free and there are definitely no algorithms – no mathematical alchemy behind the scenes serving up content it thinks you might like – just a stream of toots that you’ll see posted in real time. &lt;/p&gt;

&lt;p&gt;But there are enough similarities to Twitter to make it recognizable to users of that other service, for example, the use of hashtags, notifications, and followers. And you can access it from your desktop or use mobile apps available for iOS and Android devices, both of the official and unofficial variety.&lt;/p&gt;

&lt;p&gt;Free speech is pivotal to Mastodon, but there are guardrails against hate speech and misinformation. The &lt;a href="https://joinmastodon.org/covenant" rel="noopener noreferrer"&gt;Mastodon Server Covenant&lt;/a&gt; is a list of server owners who pledge to provide active moderation against racism, sexism, homophobia and transphobia, plus several other user-first commitments on privacy and terms of service. This offers newcomers reassurance up front that they’re venturing into a safe space, free from trolls and fake news.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let’s build a bot for Mastodon!
&lt;/h2&gt;

&lt;p&gt;Now that you know a little bit about what makes this Twitter alternative so intriguing in its own right, let’s roll up our sleeves and build something for it! &lt;/p&gt;

&lt;p&gt;We’re not ready to create a server of our own on Mastodon just yet, but let’s kick it off with functionality that’s smaller and simpler (but no less useful): a bot that automagically notifies the community when a new post is published to the Contentful blog. &lt;/p&gt;

&lt;p&gt;This is a relatively straightforward process because Mastodon provides access to its data over a &lt;a href="https://www.contentful.com/blog/what-is-a-rest-api/" rel="noopener noreferrer"&gt;REST API&lt;/a&gt;, just like Contentful does. You have either the option of webhooks or RSS fields (or both) to tie it all together. With some simple alterations, you can follow these same steps to sync your content between other social or microblogging services like Twitter, Instagram, Tumblr, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wait, what’s a bot?
&lt;/h3&gt;

&lt;p&gt;Did you know? More than half of all web traffic is generated by bots. Why? Because internet bots are able to perform tasks that are simple and repetitive much faster than a human ever could. &lt;a href="https://en.wikipedia.org/wiki/Internet_bot" rel="noopener noreferrer"&gt;Wikipedia&lt;/a&gt; has a good definition: a bot is a software application that runs automated tasks (scripts) over the internet, such as messaging or publishing content. &lt;/p&gt;

&lt;h3&gt;
  
  
  What’s a webhook?
&lt;/h3&gt;

&lt;p&gt;Webhooks are unidirectional mechanisms that applications can use to talk to each other when a particular event occurs. Think of a webhook as an automated, one-way communication from one application to another. The first application sends the information to the receiver without waiting for a response. Then, it relies on the receiver to process this information. &lt;a href="https://www.contentful.com/blog/ultimate-guide-contentful-webhooks/" rel="noopener noreferrer"&gt;Read all about it in our ultimate guide to webhooks.&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What’s an RSS feed?
&lt;/h3&gt;

&lt;p&gt;RSS (RDF Site Summary or Really Simple Syndication) allows people to subscribe to newly published content via an RSS reader so that they don’t need to manually check websites or channels. An RSS feed takes the form of a standard XML (Extensible Markup Language) file, built of content and tags that define the content, and it looks a bit like HTML. XML is both human and machine readable. &lt;a href="https://www.contentful.com/blog/feed.xml" rel="noopener noreferrer"&gt;Check out the Contentful blog RSS feed here.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Sign up for a Mastodon account and choose a server
&lt;/h2&gt;

&lt;p&gt;Let’s start by signing up for an account with Mastodon. The first thing you need to do is pick a server. There are multiple servers available, filterable by topic (&lt;a href="https://socel.net/about" rel="noopener noreferrer"&gt;Animation&lt;/a&gt;! &lt;a href="https://astrodon.social/about" rel="noopener noreferrer"&gt;Astronomy&lt;/a&gt;! &lt;a href="https://fosstodon.org/about" rel="noopener noreferrer"&gt;FOSS&lt;/a&gt;!) and region, and the ones on &lt;a href="https://joinmastodon.org/servers" rel="noopener noreferrer"&gt;this index&lt;/a&gt; belong to the Mastodon Server Covenant. &lt;/p&gt;

&lt;p&gt;You can always switch servers later if you change your mind. We’re going with &lt;a href="https://mastodon.online/getting-started" rel="noopener noreferrer"&gt;mastodon.online&lt;/a&gt;, a newer server administered by Mastodon directly. &lt;a href="https://mastodon.online/@contentful" rel="noopener noreferrer"&gt;This is the account we have created for the bot&lt;/a&gt; (which, being a bot, is limited only to republishing content from the blog and is not moderated by a human).&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Generate a token in Mastodon
&lt;/h2&gt;

&lt;p&gt;Now that you have a Mastodon account and have familiarized yourself with the service, go to settings &amp;gt; profile &amp;gt; development and select “New Application.” &lt;/p&gt;

&lt;p&gt;Fill out some fields describing your project, then, under “Scopes” only select &lt;code&gt;write:statuses&lt;/code&gt; among all the checkboxes that you see. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4k1yh4gewg8akaf39763.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4k1yh4gewg8akaf39763.png" alt="Fill out some fields describing your project, then, under “Scopes” only select  raw `write:statuses` endraw  among all the checkboxes that you see. &amp;lt;br&amp;gt;
"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click “submit,” then a unique token will be generated. Hang on to this information, you’ll need it in a bit.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 3  / Option A: Create a webhook in Contentful
&lt;/h2&gt;
&lt;h3&gt;
  
  
  a) Sign up for a Contentful account
&lt;/h3&gt;

&lt;p&gt;Our assumption for this tutorial is that you already have a Contentful account, together with a Space that’s already populated with a content model. &lt;/p&gt;

&lt;p&gt;If you don’t already have one, &lt;a href="https://www.contentful.com/sign-up/" rel="noopener noreferrer"&gt;then this is the place to go to sign up for an account.&lt;/a&gt; And if you want to quickly spin up a blog, &lt;a href="https://www.contentful.com/blog/developer-showcase-low-code-examples-blog/" rel="noopener noreferrer"&gt;we have a roundup of some useful templates here.&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Come back when you’re ready to syndicate your content!&lt;/p&gt;
&lt;h3&gt;
  
  
  b) Create a webhook in Contentful
&lt;/h3&gt;

&lt;p&gt;So, let’s summarize. Our goal is to notify our Mastodon account of changes within specific parameters, e.g. that we have added a new post to the Contentful blog.&lt;/p&gt;

&lt;p&gt;The most straightforward approach is to create a webhook in your Contentful Space that communicates directly with Mastodon through the magic of APIs.&lt;/p&gt;

&lt;p&gt;Go to your webhooks via your “Settings” menu.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy3fbs63ftny5bd5acvl6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy3fbs63ftny5bd5acvl6.png" alt="Go to your webhooks via your “Settings” menu."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You’ll see a list of your webhooks; create a new one using the “Add Webhook” button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3kvsljhhqaclwn09wh3x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3kvsljhhqaclwn09wh3x.png" alt="You’ll see a list of your webhooks; create a new one using the “Add Webhook” button."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, this is where you’ll configure your webhook.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fho1wlrnfuaww5lh5eni1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fho1wlrnfuaww5lh5eni1.png" alt="Now, this is where you’ll configure your webhook."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Name:&lt;/strong&gt; Whatever you want! We chose “Contentful blog post to Mastodon.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Webhook URL:&lt;/strong&gt; This is the URL to the Mastodon API. Use the following format, replacing &lt;code&gt;[YOUR_INSTANCE]&lt;/code&gt; and &lt;code&gt;[YOUR_MASTODON_TOKEN]&lt;/code&gt; with the values from Steps 1 and 2.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;[YOUR_INSTANCE]/api/v1/statuses?access_token=[YOUR_MASTODON_TOKEN]&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;Trigger:&lt;/strong&gt; By default, “Trigger for all events” is selected. DO NOT leave it as it is. Change it to “Select specific triggering events” and make it trigger only when an entry is published. You can see what it looks like below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxer9ovzbkwxtw5s4por4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxer9ovzbkwxtw5s4por4.png" alt="By default, “Trigger for all events” is selected. DO NOT leave it as it is. Change it to “Select specific triggering events” and make it trigger only when an entry is published."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Headers:&lt;/strong&gt; You don’t need to add additional headers, but you need to change the “Content type” to application/json.&lt;/p&gt;

&lt;p&gt;💡Heads up — you can do all the above steps to set up your webhook programmatically using the Contentful API. You can find the code to do this in &lt;a href="https://github.com/contentful/mastodon-webhook" rel="noopener noreferrer"&gt;this repo&lt;/a&gt;.💡&lt;/p&gt;

&lt;p&gt;Finally, and this is a crucial step, you need to figure out what you will “toot” every time the webhook triggers. &lt;/p&gt;

&lt;p&gt;Remember, we want to automatically send a toot every time an entry is published. You define the text of your toot by using a &lt;em&gt;custom payload&lt;/em&gt; on your webhook.&lt;/p&gt;

&lt;p&gt;This depends on your content model. In our example, this is what our content model looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsylgjcplsc2fjnlu2xia.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsylgjcplsc2fjnlu2xia.png" alt="This depends on your content model. In our example, this is what our content model looks like:&amp;lt;br&amp;gt;
"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Based on our content model, this would be our payload:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "status": "New post! {/payload/fields/title/en-US}. \n [YOUR_WEBSITE]/{/payload/fields/slug/en-US}"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The values between the brackets will be replaced by dynamic data from Contentful. Make sure to replace &lt;code&gt;YOUR_WEBSITE&lt;/code&gt; with the URL of your blog, e.g., contentful.com/blog.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3 / Option B: Use a third-party automation service
&lt;/h2&gt;

&lt;p&gt;In some scenarios, you may prefer to sync up the two services using a third-party automation tool. &lt;/p&gt;

&lt;p&gt;This might be because your &lt;a href="https://www.contentful.com/help/content-" rel="noopener noreferrer"&gt;content model&lt;/a&gt; is in the middle of being revised, for example, or environmental governance rules in your org won’t permit you to create webhooks willy-nilly. We get it, it happens.&lt;/p&gt;

&lt;p&gt;For the purposes of this tutorial, we’ll go ahead and create an account with &lt;a href="https://ifttt.com/" rel="noopener noreferrer"&gt;IFTTT&lt;/a&gt;, though &lt;a href="https://zapier.com/" rel="noopener noreferrer"&gt;Zapier&lt;/a&gt; would be equally effective.&lt;/p&gt;

&lt;p&gt;We’ll need to specify two things for our project to work properly; a trigger and the action. Then we’ll top it off with some details for the web request.&lt;/p&gt;

&lt;h3&gt;
  
  
  a) This is the trigger
&lt;/h3&gt;

&lt;p&gt;Within IFTTT, click on “Create” or visit &lt;a href="https://ifttt.com/create" rel="noopener noreferrer"&gt;https://ifttt.com/create&lt;/a&gt;, and follow the prompts to create a dedicated applet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk577mgwo2iz1jwnm4ddl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk577mgwo2iz1jwnm4ddl.png" alt="Within IFTTT, click on “Create” and follow the prompts to create a dedicated applet."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the list of services, search for “RSS.”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo6gppry0ceycs2xsrrt0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo6gppry0ceycs2xsrrt0.png" alt="In the list of services, search for “RSS.”"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choose “New feed item” as your trigger.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8y8m12aueocwh27il753.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8y8m12aueocwh27il753.png" alt="Choose “New feed item” as your trigger."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Paste the URL of your RSS feed (&lt;a href="https://www.contentful.com/blog/feed.xml" rel="noopener noreferrer"&gt;ours is here&lt;/a&gt;), and then create the trigger.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjolrdnjyrluqwrr8v10j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjolrdnjyrluqwrr8v10j.png" alt="Paste the URL of your RSS feed and then create the trigger."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  b) And this is the action
&lt;/h3&gt;

&lt;p&gt;Now onto choosing an action; this is what IFTTT will do whenever there’s a new item added to your RSS feed.&lt;/p&gt;

&lt;p&gt;We’ll choose “webhook” to send the contents of our RSS entry to the Mastodon API.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fia7deq7d5dqj1apcmkac.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fia7deq7d5dqj1apcmkac.png" alt="We’ll choose “webhook” to send the contents of our RSS entry to the Mastodon API."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, choose the “webhook action” to “Make a web request” (it’s the only option), because as we said earlier, we’ll be sending a request to the Mastodon API.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp52c8zvswf1w1ttl5or4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp52c8zvswf1w1ttl5or4.png" alt="Choose the “webhook action” to “Make a web request”, because we’ll be sending a request to the Mastodon API."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  c) Make a web request
&lt;/h3&gt;

&lt;p&gt;Just a few more things you need to add and then we’re done.&lt;/p&gt;

&lt;p&gt;First, the URL that will receive the web request, it will be something like:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://[YOUR_INSTANCE]/api/v1/statuses?access_token=[YOUR_MASTODON_TOKEN]&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
Then, change the “Method” to “POST” by selecting in the drop down.&lt;/p&gt;

&lt;p&gt;Then, for the “Content Type,” select &lt;code&gt;application/json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then, in the “Body” section, put a JSON object with the “status” property, that will define a template for what your toots will look like.&lt;/p&gt;

&lt;p&gt;In our example, &lt;code&gt;{ "status": "{{EntryTitle}} -&amp;gt; {{EntryUrl}}" }&lt;/code&gt;, our toots will have a simple format of blog post title and then the URL.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe1c5a08is1lbyftu3udj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe1c5a08is1lbyftu3udj.png" alt="Our toots will have a simple format of blog post title and then the URL."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Testing, testing
&lt;/h2&gt;

&lt;p&gt;To test your new bot, you should go ahead and publish a sample blog post. &lt;/p&gt;

&lt;p&gt;Alternatively, you can live by the seat of your pants and wait until the next time you publish something for real...&lt;/p&gt;

&lt;p&gt;Either way, if everything has been set up correctly, you should now have a working bot that fires off a toot every time a new post appears on your site. &lt;/p&gt;

&lt;p&gt;Here’s a screenshot of our &lt;a href="https://mastodon.online/@contentful" rel="noopener noreferrer"&gt;Contentful bot&lt;/a&gt; working its magic on Mastodon – and hey, it’s already got some followers!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhih777s4fvimadi4xhf3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhih777s4fvimadi4xhf3.png" alt="Here’s a screenshot of our Contentful bot working its magic on Mastodon – and hey, it’s already got some followers!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up: Is Mastodon the best Twitter alternative?
&lt;/h2&gt;

&lt;p&gt;So there you have it. Now you know what Mastodon is, what the fediverse is, and how to tie it all together with your Contentful space. &lt;/p&gt;

&lt;p&gt;Is Mastodon really the best Twitter alternative available? We’ll leave that to you to judge, but with this simple little project you can really get your teeth into this intriguing platform and evaluate it for yourself.&lt;/p&gt;

&lt;p&gt;Get started! Start building with a free Contentful account, no credit card required. &lt;a href="https://www.contentful.com/sign-up/" rel="noopener noreferrer"&gt;Sign up.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>mastodon</category>
      <category>contentful</category>
      <category>bots</category>
      <category>webhooks</category>
    </item>
    <item>
      <title>Airtable automation: How I streamlined submissions to the Developer Showcase</title>
      <dc:creator>Harshil Agrawal</dc:creator>
      <pubDate>Thu, 13 Oct 2022 14:28:58 +0000</pubDate>
      <link>https://forem.com/contentful/airtable-automation-how-i-streamlined-submissions-to-the-developer-showcase-d40</link>
      <guid>https://forem.com/contentful/airtable-automation-how-i-streamlined-submissions-to-the-developer-showcase-d40</guid>
      <description>&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; This post was &lt;a href="https://www.contentful.com/blog/2022/10/13/airtable-automation-developer-showcase-submissions/" rel="noopener noreferrer"&gt;first published&lt;/a&gt; on the Contentful Blog.&lt;/p&gt;

&lt;p&gt;In April 2022, we launched the &lt;a href="https://www.contentful.com/developers/showcase" rel="noopener noreferrer"&gt;Developer Showcase&lt;/a&gt; to highlight the work of the community. Developers share their projects, apps, videos, or blog posts they’ve created around Contentful. The developer showcase has become the go-to place to see what others are building and get inspired!&lt;/p&gt;

&lt;p&gt;If you’ve worked on a project that you believe can help the community, you can go to the Developer Showcase page, and submit the &lt;a href="https://www.contentful.com/developers/showcase/submit/" rel="noopener noreferrer"&gt;form&lt;/a&gt;. If your project meets the criteria, you get an email from us for the next step. In this step, you share more information about the project and yourself. This information is then used on the Developer Showcase page.&lt;/p&gt;

&lt;p&gt;The process seems straightforward, but there are a lot of repetitive tasks that are being performed behind the scenes. In this tutorial, I’ll share how automated processes using Airtable and a few other integrations  got myself some time back!&lt;/p&gt;

&lt;h2&gt;
  
  
  The manual process and challenges
&lt;/h2&gt;

&lt;p&gt;As mentioned above, if a developer is interested in adding their project to the showcase, they submit a form on the website with initial details. Once the form is submitted, the developer relations (DevRel) team gets a notification over email with the submission details. We then manually enter the details into a Google Sheet.&lt;/p&gt;

&lt;p&gt;Imagine, getting submissions every day, and you have to fill out entries in the Google Sheet manually! Yes, data entry is monotonous and time-consuming. I knew it could be automated and save us time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ntlwddqrkb8yxo0wa5b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ntlwddqrkb8yxo0wa5b.png" alt="Stickman Submit Entry"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the details were entered in the Google Sheet, team members would review the submissions weekly. We’d check and decide if the submissions met the criteria. If the submission was a good fit, the developer would receive an email from us asking them to fill out another form with more details. The information shared via this form would get added to a Contentful space, which was being used to manage the content on the Developer Showcase page (yes, we use Contentful at Contentful!).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhh03hbv8wzqx233mrxn4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhh03hbv8wzqx233mrxn4.png" alt="Stickman Contentful"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above process was also manual. We had to manually add the relevant information shared via the form to the Contentful space. This again cost us time. I recognized this as another task that could be automated.&lt;/p&gt;

&lt;p&gt;Both the tasks were manual, which meant that the chances of human error were high. There were situations where I would enter the information in the wrong columns when I was in a hurry. This was also becoming monotonous.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automating the boring parts
&lt;/h2&gt;

&lt;p&gt;I take pride in being lazy! My laziness helps me find solutions that make my tasks joyful. Now that I recognized two tasks that could be automated, I started looking for solutions.&lt;/p&gt;

&lt;p&gt;My first step was to migrate to a spreadsheet-like tool that provided better features than Google Sheets. I was looking for a tool that would allow me to easily create automation workflows, configure different views, and also have an easy-to-use API.  &lt;/p&gt;

&lt;p&gt;Luckily for me, we already use &lt;a href="https://airtable.com/" rel="noopener noreferrer"&gt;Airtable&lt;/a&gt; at Contentful for various projects. I created a base in Airtable for the Developer Showcase which would contain all the details — from the initial form submission details to the final details.&lt;/p&gt;

&lt;p&gt;Everyone in the DevRel team is involved in the showcase. All of us decide if a submission should be added to the Developer Showcase. We handle this by voting. For every member of the team, I created a view that would list all the submissions that they haven’t viewed. Having an individual view made it easy for my team to go in, view the project, leave their thoughts, and vote. It hardly takes them 15 minutes now!&lt;/p&gt;

&lt;p&gt;The migration to Airtable also involved creating automation to handle the form submissions. After setting up the table and the individual views, I created an automation workflow in &lt;a href="https://zapier.com/" rel="noopener noreferrer"&gt;Zapier&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;This workflow would get triggered whenever there was a submission made to the Developer Showcase form. The workflow would then add the new record to the Airtable base, and also send a Slack message to notify us. All I had to do now was to check if the submission was valid and if it was, update the Valid column in Airtable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw78rjuubvnzevq99fa6n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw78rjuubvnzevq99fa6n.png" alt="Zapier"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above workflow replaced the manual labor of entering the data into Google Sheets. The first task was now automated!&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting Airtable to Contentful
&lt;/h2&gt;

&lt;p&gt;The other time-consuming task was entering the final details of the submissions to Contentful, and I wanted to automate it next. Now that we were using Airtable to manage the data, I re-created the template for the final submission form in Airtable. This enabled us to capture the data in Airtable itself. Whenever a developer submitted this form with the details, it now got saved in Airtable. There was no need to create an automation workflow to handle it!&lt;/p&gt;

&lt;p&gt;The data from the final form submission was in Airtable, and not Contentful, yet. To get this data added automatically to Contentful, I created a workflow in Airtable. If you’re using Airtable, you might know that Airtable doesn’t have webhooks (at the time of writing this article). This means that whenever data is created or updated, you can’t trigger external events. &lt;/p&gt;

&lt;p&gt;To overcome this, you can either create automation workflows that run at a certain interval of time, or check for new data and then process that data. A better and faster solution is to use automation within Airtable. It allows you to trigger actions when data is entered or updated.&lt;/p&gt;

&lt;p&gt;I created a workflow in Airtable to handle the above scenario. Every time a developer submitted the final form, this workflow would get triggered. It is out of the scope of this article to walk you through all the steps of creating the automation workflow. But, below I’m sharing the code snippet that populates Contentful with the data.&lt;/p&gt;

&lt;p&gt;Once the form is submitted, the workflow gets triggered. The next step is to create an action that will add the content to Contentful. Airtable doesn’t have an in-built action for Contentful, so there isn’t a no-code or even a low-code solution available just yet. However, it has an action that allows you to run custom JavaScript code. &lt;/p&gt;

&lt;p&gt;While working with this action, I learned that you can’t import npm packages. Hence, using the Contentful Management JavaScript SDK was not possible. Fortunately, Contentful has a REST API to interact with the &lt;a href="https://www.contentful.com/developers/docs/references/content-management-api/" rel="noopener noreferrer"&gt;Management API&lt;/a&gt;! I wrote the following code in the “Run a Script” action. This script populated the Contentful space with the data from Airtable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// @ts-ignore&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SPACE_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;SPACE_ID&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://api.contentful.com/spaces/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;SPACE_ID&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inputConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AUTHORLINK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;authorLink&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AUTHOR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;author&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ENTRY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;entry&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;linkId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;authorId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;makeCall&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;contentType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;Authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bearer MANAGEMENT_TOKEN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/vnd.contentful.management.v1+json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;X-Contentful-Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;contentType&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;body&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;checkLinkType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;github&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Github&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;linkedin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;LinkedIn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;twitter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Twitter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;youtube&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YouTube&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Website&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addAuthorLink&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;links&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;inputConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authorLink&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;links&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;linkType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;checkLinkType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;makeCall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/environments/master/entries&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;AUTHORLINK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fields&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;internalTitle&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en-US&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;inputConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authorName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;'s &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;linkType&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en-US&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;linkType&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;link&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en-US&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}))&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nx"&gt;linkId&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;linkId&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addAuthor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;links&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;linkId&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sys&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Link&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;linkType&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Entry&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;makeCall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/environments/master/entries&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;AUTHOR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fields&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en-US&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;inputConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authorName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bio&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en-US&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;inputConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authorBio&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;links&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en-US&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;links&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}))&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;authorId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addEntry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;makeCall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/environments/master/entries&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ENTRY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fields&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en-US&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;inputConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;projectTitle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en-US&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;inputConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;projectDesc&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;link&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en-US&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;inputConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;projectLink&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;author&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en-US&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sys&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Link&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;linkType&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Entry&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;authorId&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en-US&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sys&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Link&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;linkType&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Entry&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;FIELD_ID&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
              &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}))&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;addAuthorLink&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;addAuthor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;addEntry&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;})()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Walking through the code
&lt;/h2&gt;

&lt;p&gt;Let’s break down the code to understand what is happening. The first few lines are defining some variables that we need later in the code. This includes the space ID, URL of the Management API, content type IDs, as well as the input object from Airtable.&lt;/p&gt;

&lt;p&gt;We then define a reusable function &lt;code&gt;makeCall&lt;/code&gt; that takes the API endpoint, HTTP method, content type, and the body as the parameters. We use this function to call the Management API.&lt;/p&gt;

&lt;p&gt;An author of a Developer Showcase submission can share social links. These links are displayed on the respective author page, e.g., &lt;a href="https://www.contentful.com/developers/showcase/author/teemu-tammela/" rel="noopener noreferrer"&gt;one of our top contributors Teemu Tammela&lt;/a&gt;. To identify the type of this link, we are using the &lt;code&gt;checkLinkType&lt;/code&gt; function. It returns the type that we have configured in Contentful.&lt;/p&gt;

&lt;p&gt;Next, we define the &lt;code&gt;addAuthorLink&lt;/code&gt; function. This function creates an array of links shared by the author, gets the link type, and adds them to Contentful. It also returns an array of link IDs that get used in the &lt;code&gt;addAuthor&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;addAuthor&lt;/code&gt; function adds all the information about the author, as well as adds references to the links. The final result, a new entry of the author, is now available with references to the author’s social media accounts.&lt;/p&gt;

&lt;p&gt;Lastly, the &lt;code&gt;addEntry&lt;/code&gt; function adds the project details and references the author. Since the type of project has not been asked in the form, it is hard-coded. The type is manually updated before the entries are published.&lt;/p&gt;

&lt;p&gt;The last action in this automation workflow is sending a message on Slack. Since Airtable has an built-in app for Slack, it was straightforward to set it up!&lt;/p&gt;

&lt;p&gt;To summarize the above workflow, every time the Airtable form was submitted, the automation would be triggered. It will execute the “Run a script” action, that runs the above code and adds the content to Contentful. Once the content is successfully added, a message is sent on Slack.&lt;/p&gt;

&lt;p&gt;All we have to do now is log in to the Contentful space, review the newly created entries, add the missing assets, and publish the changes!&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s next?
&lt;/h2&gt;

&lt;p&gt;These workflows have saved us a huge amount of time! We don’t have to manually add data, and we can focus more on highlighting the amazing work the community is doing!&lt;/p&gt;

&lt;p&gt;The code currently doesn’t handle images, however. We manually have to add them to Contentful. I couldn’t find a good solution to handle images in Airtable, and I am still on the lookout. If you have worked with images in Airtable and have a solution, please let me know!&lt;/p&gt;

&lt;p&gt;There are a lot of other tasks that can be automated in the whole process. But my experience with automation has taught me one thing — start small and automate the things you do often. It has helped me not over-engineer a simple solution.&lt;/p&gt;

&lt;p&gt;Now that I have more free time, why don’t you share what you’ve created with Contentful? I would love to see it and share it with the community. Also, let me know which Developer Showcase entries you find the most interesting!&lt;/p&gt;

</description>
      <category>automation</category>
      <category>contentful</category>
      <category>airtable</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Developer Showcase Spotlight: Low-code examples of building blogs</title>
      <dc:creator>Bulent Osman Yusuf</dc:creator>
      <pubDate>Thu, 06 Oct 2022 11:21:26 +0000</pubDate>
      <link>https://forem.com/contentful/developer-showcase-spotlight-low-code-examples-of-building-blogs-pg6</link>
      <guid>https://forem.com/contentful/developer-showcase-spotlight-low-code-examples-of-building-blogs-pg6</guid>
      <description>&lt;p&gt;&lt;strong&gt;Wanna create a blog? Tools are readily available that make it super easy and fun. Contentful, Gatsby and Netlify are your building blocks for building blogs, and in this post I show a few examples.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This post was &lt;a href="https://www.contentful.com/blog/2022/09/27/developer-showcase-low-code-examples-blog/" rel="noopener noreferrer"&gt;first published&lt;/a&gt; on the Contentful Blog.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;My role at Contentful is to manage the company blog, and I love it. We have a dedicated team of developers, designers, writers, and editors all working together to deliver great content –– and I get to pester all of them on a daily basis.&lt;/p&gt;

&lt;p&gt;But when the &lt;a href="https://www.contentful.com/developers/showcase/" rel="noopener noreferrer"&gt;Developer Showcase&lt;/a&gt; was launched early this summer, it got me thinking about building a &lt;a href="https://jamstack.org/" rel="noopener noreferrer"&gt;Jamstack&lt;/a&gt; site of my own; a sandbox to play in, learn something new, and occasionally break stuff.&lt;/p&gt;

&lt;p&gt;The idea was simple: to create a basic blog from modular components, and to do it using existing resources without getting too deep into the code. I wanted to bring together standalone elements like a content management system, a static site generator and hosting provider through the &lt;a href="https://www.contentful.com/blog/2021/08/12/what-is-an-api/" rel="noopener noreferrer"&gt;magic of APIs&lt;/a&gt;. The grand result would be a site that was performant and secure.&lt;/p&gt;

&lt;p&gt;In the end, I got a bit carried away and wound up creating several blogs plus a portfolio to bring them all together. The result is called &lt;a href="https://www.contentful.com/developers/showcase/author/bulent-yusuf/" rel="noopener noreferrer"&gt;Get Some Jam&lt;/a&gt;. And that’s what’s been so utterly delightful about this project.&lt;/p&gt;

&lt;p&gt;Approaching it as a content editor searching for low-code solutions, I found many options for achieving my goal and couldn’t settle on just one. I’m going to tell you all about it in this post, so pull up a seat and make yourself comfortable.&lt;/p&gt;

&lt;h2&gt;
  
  
  First things first, set up a GitHub account
&lt;/h2&gt;

&lt;p&gt;If you leave here with only one takeaway (other than the fact that Contentful is amazing and you should totally be using it for your next project), it’s that a &lt;a href="https://github.com/" rel="noopener noreferrer"&gt;GitHub account&lt;/a&gt; is your passport to many exotic locations on the magical electronic interwebs.&lt;/p&gt;

&lt;p&gt;I used to think that GitHub was just a place where developers would store code and collaborate, but it’s a lot more than that. What’s also wonderful about GitHub is that an account functions as a universal identifier on the web, so you don’t need to create accounts with multiple services and then try to remember passwords for each of them. One GitHub account will grant you secure access to everything.&lt;/p&gt;

&lt;p&gt;From my personal GitHub account, for example, I created and synced up free accounts with &lt;a href="https://www.contentful.com/sign-up/" rel="noopener noreferrer"&gt;Contentful&lt;/a&gt; (content platform), &lt;a href="https://www.gatsbyjs.com/" rel="noopener noreferrer"&gt;Gatsby&lt;/a&gt; (static site generation and deployment), &lt;a href="https://www.netlify.com/" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt; (deployment), and &lt;a href="https://vercel.com/" rel="noopener noreferrer"&gt;Vercel&lt;/a&gt; (deployment), and between those four entities I was able to build four different websites in about a week. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffz7dz3bnw800ljc6kq32.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffz7dz3bnw800ljc6kq32.png" alt="A GitHub account is your passport to many exotic locations on the magical electronic interwebs."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The only outlier to this process was Google, which has its own authentication protocol for their services. That came into play for this project when it came to &lt;a href="https://domains.google/v2/" rel="noopener noreferrer"&gt;buying and managing domains&lt;/a&gt;. But Google makes doing this so easy that I really can’t object.&lt;/p&gt;

&lt;p&gt;Oh yes, and the OTHER useful thing about GitHub is that it’s your de-facto place for storing and delivering files that go into the upkeep of a website. Which leads us to my first example.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Building a low-code blog with Gatsby and Gatsby Cloud
&lt;/h2&gt;

&lt;p&gt;The tech stack for this &lt;a href="https://bulentyusuf.com/" rel="noopener noreferrer"&gt;first blog&lt;/a&gt; is very simple and consists of two components: Gatsby and Contentful.&lt;/p&gt;

&lt;p&gt;This is because Gatsby offers more than a &lt;a href="https://www.contentful.com/blog/2022/08/16/what-is-a-framework/" rel="noopener noreferrer"&gt;framework&lt;/a&gt; for static site generation, there’s also the option of a fully featured deployment and hosting service called Gatsby Cloud.&lt;/p&gt;

&lt;p&gt;So, my first port of call was the &lt;a href="https://github.com/contentful/starter-gatsby-blog" rel="noopener noreferrer"&gt;official GitHub repository where Contentful maintains a starter blog template built using Gatsby&lt;/a&gt;, which has push button deployment for Gatsby Cloud. This template is basic but properly formatted with all the necessary features of a functional blog. Things like an index page, formatting for individual posts and key visuals, plus timestamps, authors, and tagging.&lt;/p&gt;

&lt;p&gt;It also comes with a preconfigured content model to populate your Contentful space, and sample posts you can delete later. Much of the heavy lifting is done already for those who are still learning the concept of structured content. My thanks to &lt;a href="https://www.contentful.com/blog/author/david-fateh/" rel="noopener noreferrer"&gt;David Fateh&lt;/a&gt; for maintaining this great resource. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd8zr50bmio1kcxye25zu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd8zr50bmio1kcxye25zu.png" alt="The tech stack for this first blog is very simple and consists of two components: Gatsby and Contentful.&amp;lt;br&amp;gt;
"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Bonus: How to add inline images
&lt;/h3&gt;

&lt;p&gt;While adding some sample entries of my own to this blog, I found a setting that wasn’t to my liking. You’re not able to show inline images in the body of a post. This is because images are a Rich Text Asset that’s not defined (and therefore not queryable) in the content model when setting up the blog for the first time.&lt;/p&gt;

&lt;p&gt;After a bit of Googling, I found some helpful blog posts articulating how to resolve the issue. One by &lt;a href="https://www.contentful.com/blog/author/paul-scanlon/" rel="noopener noreferrer"&gt;Paul Scanlon&lt;/a&gt; over on the &lt;a href="https://www.gatsbyjs.com/blog/how-to-use-the-contentful-rich-text-field-with-gatsby/" rel="noopener noreferrer"&gt;Gatsby blog&lt;/a&gt; and another by &lt;a href="https://javascript.plainenglish.io/rendering-contentful-rich-text-components-in-gatsby-4744d4940cea" rel="noopener noreferrer"&gt;Andreea Macoveiciuc&lt;/a&gt; on Medium. After a bit of trial and error, I wedged an approximation of their code into my &lt;code&gt;blog-post.js&lt;/code&gt; file in &lt;code&gt;starter-gatsby-blog/src/templates/blog-post.js&lt;/code&gt; and now images are visible.&lt;/p&gt;

&lt;p&gt;Here it is if you’d like to use it yourself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;body {
   raw
   references {
      ... on ContentfulAsset {
         contentful_id
         title
         description
         gatsbyImage(width: 1000)
          __typename
      }
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I did attempt to have this merged into the main Starter Gatsby Blog repo on GitHub, but it causes issues at startup because it’s an unexpected element in the schema. As long as you use this code after the blog has been generated you’ll be golden.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Would you like to build something more elaborate with Contentful and Gatsby? &lt;a href="https://www.contentful.com/gatsby-starter-guide/" rel="noopener noreferrer"&gt;Check out this guide for a fully featured homepage starter.&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  2. Building a low-code blog with NextJS and Vercel
&lt;/h2&gt;

&lt;p&gt;Moving on to something slightly more complicated — but not by much — the tech stack for this &lt;a href="https://www.nextblog.net/" rel="noopener noreferrer"&gt;second blog&lt;/a&gt; is three components: Contentful, NextJS and Vercel. In this instance, we’re switching to a new framework and a new deployment service.&lt;/p&gt;

&lt;p&gt;Again, this is a basic but functional blog, with a pre-populated content model which looks like:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;title&lt;/code&gt; – Text field (type short text)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;content&lt;/code&gt; – Rich Text field&lt;/p&gt;

&lt;p&gt;&lt;code&gt;excerpt&lt;/code&gt; – Text field (type Long text, full-text search)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;coverImage&lt;/code&gt; – Media field (type one file)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;date&lt;/code&gt; – Date and time field&lt;/p&gt;

&lt;p&gt;&lt;code&gt;slug&lt;/code&gt; – Text field. You can optionally go to the settings of this field, and under Appearance, select Slug to display it as a slug of the title field.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;author&lt;/code&gt; – Reference field (type one reference)&lt;/p&gt;

&lt;p&gt;If you really want to dig into the process yourself, you can &lt;a href="https://github.com/vercel/next.js/tree/canary/examples/cms-contentful" rel="noopener noreferrer"&gt;follow the instructions on the GitHub repo&lt;/a&gt; and create the content model manually from within your Contentful space. OR you could just hit that big blue “deploy” button and have it taken care of for you. Can you guess which option I chose? =D&lt;/p&gt;

&lt;p&gt;Not much else to add here, except that this template might be really useful if you’re intent on showcasing high-definition images for each post. You can see our very own &lt;a href="https://www.contentful.com/blog/author/brittany-walker/" rel="noopener noreferrer"&gt;Brittany Walker&lt;/a&gt; spinning up this same template in a &lt;a href="https://www.contentful.com/nextjs-starter-guide/" rel="noopener noreferrer"&gt;video tutorial&lt;/a&gt; here.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffbipr7kilsdrtrck3onz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffbipr7kilsdrtrck3onz.png" alt="The tech stack for this second blog is three components: Contentful, NextJS and Vercel."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Building a low-code blog with RemixJS and Vercel
&lt;/h2&gt;

&lt;p&gt;At first glance, this &lt;a href="https://www.remixblog.net/" rel="noopener noreferrer"&gt;third blog&lt;/a&gt; looks exactly the same as the Gatsby Starter Blog. It’s actually a fork and &lt;a href="https://github.com/marcolink/contentful-remix-starter-blog" rel="noopener noreferrer"&gt;rebuilt from the ground up using the RemixJS framework&lt;/a&gt;. For this site, I opted to host it again on Vercel.&lt;/p&gt;

&lt;p&gt;This starter blog template is the work of Contentful Software Engineer &lt;a href="https://www.contentful.com/developers/showcase/author/marco-link/" rel="noopener noreferrer"&gt;Marco Link&lt;/a&gt;, and has pride of place on the Developer Showcase alongside some other projects of his making. &lt;/p&gt;

&lt;p&gt;One tweak that I made to the blog after creating it was to change the date formatting from DE to EN. You can do that by visiting the file &lt;code&gt;to-readable-date.ts&lt;/code&gt; in &lt;code&gt;contentful-remix-starter-blog/app/utils&lt;/code&gt; and changing the value “de-DE” to “en-GB”.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Would you like to build something more elaborate with Contentful and RemixJS? &lt;a href="https://www.contentful.com/remix-tutorial/" rel="noopener noreferrer"&gt;Check out this guide for a fully featured portfolio starter.&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  4. Building a low-code portfolio with Gatsby and Netlify
&lt;/h2&gt;

&lt;p&gt;Phew, that’s a lot of blogs! The last piece of the project is to bring them all together in one place, with all the relevant links and a bit of discourse about how they were made and the technologies used. This &lt;a href="https://getsomejam.net/" rel="noopener noreferrer"&gt;portfolio site&lt;/a&gt; is called “Get Some Jam,” and the pun is very much intended.&lt;/p&gt;

&lt;p&gt;I’d been searching the web for a suitable template, and eventually I found the &lt;a href="https://github.com/EmaSuriano/gatsby-starter-mate" rel="noopener noreferrer"&gt;Mate portfolio starter&lt;/a&gt; by software engineer &lt;a href="https://emasuriano.com/" rel="noopener noreferrer"&gt;Ema Suriano&lt;/a&gt;. This is a beautiful single page site with a customizable and responsive design regardless of whether you access it on a desktop, smartphone, or magic mirror. If you end up using this template yourself, &lt;a href="https://www.buymeacoffee.com/emasuriano" rel="noopener noreferrer"&gt;be sure to buy them a coffee&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It also has a handy feature to import posts from a Medium account, so that I could offer meta-commentary on the process of creating these posts and lessons learned alongside the links to the sites themselves. I expect that no one will find these posts interesting except perhaps my mother (and even that’s a stretch), but it felt good to document the personal eureka moments as I went along.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Facwmxpc61cc54ojeof74.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Facwmxpc61cc54ojeof74.png" alt="The last piece of the project is to bring them all together in one place, with all the relevant links and a bit of discourse about how they were made and the technologies used."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Next steps after the sites are built
&lt;/h2&gt;

&lt;p&gt;That’s the story behind my submission of &lt;a href="https://getsomejam.net/" rel="noopener noreferrer"&gt;Get Some Jam&lt;/a&gt; to the Developer Showcase. Thank you for your attention. And since you’ve made it this far, I’ve two more nuggets of wisdom to share from these low-code examples.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add webhooks for automating previews and updates
&lt;/h3&gt;

&lt;p&gt;We recently published a detailed guide to using webhooks in Contentful. &lt;a href="https://www.contentful.com/blog/2022/08/25/ultimate-guide-contentful-webhooks/" rel="noopener noreferrer"&gt;The ultimate guide, in fact&lt;/a&gt;. Just to add my two cents; this is one of the first things to investigate after you’ve set up your site with Contentful and your framework/deployment service of choice. It automates many of the key steps you would normally take when managing a site, such as web page previews or pushing them live when you hit the publish button in Contentful.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep an eye on Lighthouse scores
&lt;/h3&gt;

&lt;p&gt;Another fantastic feature that’s available on Gatsby Cloud and Netlify is Lighthouse scores. Essentially, Lighthouse is a tool from Google that analyzes web apps and web pages, collecting modern performance metrics and insights to guide developer best practices. Each time you deploy an update, your new build is given a score between 1–100 for each of the following criteria: Performance, Accessibility, Best Practices, Search Engine Optimization and Progressive Web Apps. &lt;a href="https://www.netlify.com/blog/view-google-lighthouse-scores-visualizations/" rel="noopener noreferrer"&gt;This post on the Netlify blog is a great introduction&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Sitting on the other side of my little project, I have a renewed appreciation for the Contentful content platform. Yes, it’s scalable and versatile and fast and reliable — all of these things are true. But it’s also accessible enough that a non-technical person can roll up their sleeves and build something for themselves. &lt;/p&gt;

&lt;p&gt;And this is made possible thanks to a terrific group of developers and creatives who have shared their efforts for the betterment of the community. I proffer a tip of the hat to them all.&lt;/p&gt;

&lt;p&gt;Get started! Start building with a free Contentful account, no credit card required.&lt;a href="https://www.contentful.com/sign-up/" rel="noopener noreferrer"&gt; Sign up.&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to get started using Angular with Contentful</title>
      <dc:creator>Luke Stahl</dc:creator>
      <pubDate>Tue, 20 Sep 2022 12:47:31 +0000</pubDate>
      <link>https://forem.com/contentful/how-to-get-started-using-angular-with-contentful-57lh</link>
      <guid>https://forem.com/contentful/how-to-get-started-using-angular-with-contentful-57lh</guid>
      <description>&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: This article originally appeared on the &lt;a href="https://www.contentful.com/blog/" rel="noopener noreferrer"&gt;Contentful Blog&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Angular and Contentful are popular tools for creating client-side applications or delivering content creation and management services.&lt;/p&gt;

&lt;p&gt;Because of its scalable design and productivity-enhancing capabilities, Angular powers the frontend of Google apps used by millions of users worldwide.&lt;/p&gt;

&lt;p&gt;Contentful is a cloud-based content management platform that organizes and manages content that can be accessed via various platforms — including websites and mobile apps. It’s a headless system that provides a project-specific framework for managing website content. It’s independent of the frontend, enabling you to use the backend and content infrastructure with any client-side framework — including Angular, React, and Vue, just to name a few.&lt;/p&gt;

&lt;p&gt;Contentful also enables you to add and update information that appears on the frontend of your website or mobile application. Additionally, it saves you the time and effort of developing your own backend — which would otherwise require knowledge of a backend language or platforms like Python or Node.js and database administration — and provides various tools to help developers interface the frontend with the backend.&lt;/p&gt;

&lt;p&gt;This beginner’s tutorial will demonstrate how to build a full-stack application using Contentful and Angular. In this demonstration, you’ll create a job listings website for developers. &lt;a href="https://github.com/contentful-developer-relations/angularcontentfuldemo2" rel="noopener noreferrer"&gt;All the sample code is stored on GitHub for reference&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Creating content
&lt;/h2&gt;

&lt;p&gt;Let’s get started with Contentful.&lt;/p&gt;

&lt;p&gt;First, sign up for a &lt;a href="https://www.contentful.com/sign-up/" rel="noopener noreferrer"&gt;free Contentful account&lt;/a&gt;. Next, create an empty space with a content model called JobListing in the Contentful UI. We won’t be showing a step-by-step guide on how to do this here, but you can refer to &lt;a href="https://www.contentful.com/help/contentful-101/" rel="noopener noreferrer"&gt;this page&lt;/a&gt; for a detailed walkthrough of creating a space and a content model. &lt;/p&gt;

&lt;p&gt;In this demonstration, the Job model has the following fields and types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Role&lt;/strong&gt;: Short text&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Description&lt;/strong&gt;: Long text&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HowToApply&lt;/strong&gt;: Rich text&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Organization&lt;/strong&gt;: Short text&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Date&lt;/strong&gt;: Date &amp;amp; time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skills&lt;/strong&gt;: Short Text &amp;amp; list&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Populate the fields with 3-4 sample job listings by clicking the &lt;strong&gt;Content tab&lt;/strong&gt;, then &lt;strong&gt;Add Blog&lt;/strong&gt; post. After filling out the fields, click &lt;strong&gt;Draft&lt;/strong&gt; and then &lt;strong&gt;Publish&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fte3ws806xrv4oxgrg24c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fte3ws806xrv4oxgrg24c.png" alt=" " width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that you’ve created and published your job listings, you’ll fetch them from the API and display them with Angular.&lt;/p&gt;

&lt;p&gt;One thing to note is that before you can communicate with Contentful, you’ll need an &lt;a href="https://www.contentful.com/developers/docs/references/authentication/" rel="noopener noreferrer"&gt;API key consisting of the Space ID, the Access Token, and the Entry ID&lt;/a&gt;. You can get these from your Contentful space.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create an Angular project
&lt;/h2&gt;

&lt;p&gt;Your Angular project will fetch and display the job listings from Contentful. To do this, you’ll:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create an Angular project and modify the page to display the retrieved content appropriately.&lt;/li&gt;
&lt;li&gt;Create an Angular service that can fetch the data.&lt;/li&gt;
&lt;li&gt;Include the routes required to navigate the app.&lt;/li&gt;
&lt;li&gt;Connect the service to the page and display the fetched content.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before you start, you’ll need to set up your development environment properly.&lt;/p&gt;

&lt;p&gt;Since Angular requires using Angular CLI to scaffold the initial project files and any necessary artifacts during the project’s development, you’ll need to have recent versions of Node.js and npm installed on your development machine. &lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Node and Angular CLI
&lt;/h2&gt;

&lt;p&gt;There are various ways you can install Node.js on your machine. You can pick one of the following options here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Obtain an installer compatible with your operating system from the &lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;official website&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Make use of the official package manager of your system.&lt;/li&gt;
&lt;li&gt;Use a Node version manager such as &lt;a href="https://github.com/nvm-sh/nvm" rel="noopener noreferrer"&gt;NVM&lt;/a&gt;, which allows you to manage multiple versions of Node on your development machine. We recommend using NVM.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While this article is accessible to anyone, it helps to have an understanding of TypeScript and Angular. &lt;/p&gt;

&lt;p&gt;If you already installed Node on your system, head to a terminal and install Angular CLI. This tutorial uses Angular CLI &lt;strong&gt;v13.3.7&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;If you want to use the same version as this tutorial, you simply need to specify the version when installing the CLI. Open a command line and type:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install -g @angular/cli@13.3.7.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After the installation, you’ll be able to use the ng tool from your terminal. &lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started with Angular
&lt;/h2&gt;

&lt;p&gt;Now it’s time to create our Angular project. In the command-line interface, run the following command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ng new angularcontentfuldemo --routing --style=css&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After confirming, Angular CLI will generate your initial project files, install the packages, and log the process on the command-line interface. The following should be printed after the project’s creation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;✔ Packages installed successfully.
    Successfully initialized git.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open the &lt;code&gt;app.component.ts&lt;/code&gt; file from the &lt;code&gt;src/app&lt;/code&gt; folder, and add the following line to the top of the file: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;import { ContentService } from './content.service';&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then, in the AppComponent class at the bottom of the file, add this line below &lt;code&gt;title = "angularcontentfuldemo"&lt;/code&gt; as follows:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;constructor(contentService: ContentService){}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Next, in your terminal, go to the directory of your project:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd angularcontentfuldemo&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You can then serve your Angular application by running the ng serve command as follows:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ng serve&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Your app will be served from &lt;a href="http://localhost:4200/" rel="noopener noreferrer"&gt;http://localhost:4200/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Leave your current command-line interface open for running the development server, and open a new command-line interface for running the commands that follow.&lt;/p&gt;

&lt;p&gt;Before proceeding, you’ll need to add your Contentful &lt;a href="https://www.contentful.com/developers/docs/references/authentication/" rel="noopener noreferrer"&gt;Space ID and Content Delivery API Access Token&lt;/a&gt; to the environment variables of our application. You can create an access token using the &lt;a href="https://be.contentful.com/login" rel="noopener noreferrer"&gt;Contentful web app&lt;/a&gt; or the &lt;a href="https://www.contentful.com/developers/docs/references/content-management-api/#/reference/api-keys/create-an-api-key" rel="noopener noreferrer"&gt;Content Management API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Open the &lt;code&gt;src/environments.ts&lt;/code&gt;file and update it as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;environment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;production&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;contentful&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;spaceId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_SPACE_ID&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_ACCESS_TOKEN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure to replace &lt;code&gt;YOUR_SPACE_ID&lt;/code&gt; and &lt;code&gt;YOUR_ACCESS_TOKEN&lt;/code&gt; with your actual credentials.&lt;/p&gt;

&lt;p&gt;Next, you need to install some necessary dependencies, such as &lt;code&gt;contentful&lt;/code&gt;, &lt;code&gt;bootstrap&lt;/code&gt;, &lt;a href="https://www.npmjs.com/package/@contentful/rich-text-types" rel="noopener noreferrer"&gt;rich-text-types&lt;/a&gt;, and &lt;a href="https://www.npmjs.com/package/@contentful/rich-text-html-renderer" rel="noopener noreferrer"&gt;rich-text-html-renderer&lt;/a&gt;. Navigate to your project’s folder and enter the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;contentful bootstrap 
npm &lt;span class="nb"&gt;install&lt;/span&gt; @contentful/rich-text-types @contentful/rich-text-html-renderer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll use Contentful to connect with Contentful APIs and Bootstrap for styling the Angular UI.&lt;/p&gt;

&lt;p&gt;Next, add Bootstrap to your project. There are various ways to add Bootstrap to Angular. In this demonstration, Bootstrap files are included via the &lt;code&gt;angular.json&lt;/code&gt; file. Open the configuration file that exists at the root of the project and add the following line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;styles&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./node_modules/bootstrap/dist/css/bootstrap.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src/styles.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
 &lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nx"&gt;Open&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;replace&lt;/span&gt; &lt;span class="nx"&gt;it&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;following&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;nav&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;navbar navbar-expand-lg navbar-light bg-light&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Developers&lt;/span&gt; &lt;span class="nx"&gt;Jobs&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;navbar-toggler&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;toggle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;collapse&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#navbarSupportedContent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;aria&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;controls&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;navbarSupportedContent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;aria&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;expanded&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;false&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;aria&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Toggle navigation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;navbar-toggler-icon&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/span&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/nav&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;outlet&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/router-outlet&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the code snippet above, you’ve removed the boilerplate markup, except for the &lt;a href="https://angular.io/api/router/RouterOutlet" rel="noopener noreferrer"&gt;router outlet&lt;/a&gt;, and added a Bootstrapheader bar. Please note that in order for the styling to take effect, you may need to restart your service.  &lt;/p&gt;

&lt;h2&gt;
  
  
  1. Create the service for communicating with Contentful
&lt;/h2&gt;

&lt;p&gt;Now, you’ll create the service that will encapsulate the code for communicating with Contentful. Go back to your command-line interface and run the following command to generate the service:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ng g s content&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;content-types.ts&lt;/code&gt; file in the &lt;code&gt;src/app/&lt;/code&gt; folder and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;CFRichTextTypes&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@contentful/rich-text-types&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Contentful&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;contentful&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;TypeJobListingFields&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Contentful&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EntryFields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Contentful&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EntryFields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;howToApply&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;CFRichTextTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Block&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;CFRichTextTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Inline&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;organization&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Contentful&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EntryFields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Contentful&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EntryFields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;skills&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Contentful&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EntryFields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;TypeJobListing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Contentful&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Entry&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TypeJobListingFields&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will be used to type the entries corresponding to your content model. You can either write the types manually like above, or use these automated tools for a more scalable approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/contentful-userland/cf-content-types-generator" rel="noopener noreferrer"&gt;cf-content-types-generator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/intercom/contentful-typescript-codegen" rel="noopener noreferrer"&gt;contentful-typescript-codegen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/arimkevi/contentful-ts-type-generator" rel="noopener noreferrer"&gt;contentful-ts-type-generator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/watermarkchurch/contentful-ts-generator" rel="noopener noreferrer"&gt;contentful-ts-generator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/marcolink/cf-content-types-generator-app" rel="noopener noreferrer"&gt;TS Content Types Generator App&lt;/a&gt;
Open the &lt;code&gt;src/app/content.service.ts&lt;/code&gt; file and start by adding the following imports:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Injectable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;contentful&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rxjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;environment&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../environments/environment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;TypeJobListingFields&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./content-types&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, add the client property and call the &lt;code&gt;createClientfunction&lt;/code&gt; to create a client as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;providedIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ContentService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;space&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentful&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;spaceId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentful&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;accessToken&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, add the following method after the constructor in the &lt;code&gt;content.service.ts&lt;/code&gt; file to fetch content from Contentful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;getJobListings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getEntries&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TypeJobListingFields&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
   &lt;span class="na"&gt;content_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jobListing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You call the &lt;a href="https://contentful.github.io/contentful.js/contentful/latest/ContentfulClientAPI.html#.getEntries" rel="noopener noreferrer"&gt;getEntries&lt;/a&gt; method of Contentful to retrieve the entries corresponding to the model content that you pass as the method’s first argument. You use &lt;code&gt;Object.assign&lt;/code&gt; to create an object containing the content type and any other queries that you pass to Contentful.&lt;/p&gt;

&lt;p&gt;This method also accepts a &lt;a href="https://www.typescriptlang.org/docs/handbook/2/generics.html" rel="noopener noreferrer"&gt;generic type&lt;/a&gt; that defines the type of content that will be returned, which in this case is &lt;code&gt;TypeJobListingFields&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Use the from operator to convert the promise returned from the method to an &lt;code&gt;observable&lt;/code&gt;, as this is more convenient to use with Angular.&lt;/p&gt;

&lt;p&gt;If you didn’t save your content type ID before, you could get it by clicking &lt;strong&gt;contentful&lt;/strong&gt; &amp;gt; &lt;strong&gt;content model&lt;/strong&gt;, then click on your content model name. Your content type ID should be on the right sidebar. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fph5spsa27jup46n0ei1v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fph5spsa27jup46n0ei1v.png" alt=" " width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To fetch a job listing by ID, add the following method below the &lt;code&gt;getJobListings()function&lt;/code&gt; in &lt;code&gt;content.service.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;getJobListingById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jobListingId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getEntry&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TypeJobListingFields&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jobListingId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Add routing
&lt;/h2&gt;

&lt;p&gt;After implementing the service, you need to create a component to display the job listings fetched from the backend and add routing.&lt;/p&gt;

&lt;p&gt;Go back to your command-line interface and run the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ng g c jobListings 
ng g c jobListing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will generate the components’ files and add them to the root application module.&lt;/p&gt;

&lt;p&gt;Next, open the &lt;code&gt;src/app/app-routing.module.ts&lt;/code&gt; file and start by importing the components as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;JobListingsComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./job-listings/job-listings.component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;JobListingComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./job-listing/job-listing.component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, add the following routes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;pathMatch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;full&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;redirectTo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;listings&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;listings&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JobListingsComponent&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;listing/:id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JobListingComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, you define three routes. The first route simply redirects the user to the second route, which routes to the &lt;code&gt;JobListingsComponent&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Open the &lt;code&gt;src/app/job-listings/job-listings.component.ts&lt;/code&gt; file and import the service and the other symbols as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ContentService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../content.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;TypeJobListingFields&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../content-types&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Entry&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;contentful&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, inside the component’s class, define the following array to hold the fetched job listings:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;jobListings: Entry&amp;lt;TypeJobListingFields&amp;gt;[] | undefined;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Next, inject the service via the component’s class as follows:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;constructor(public contentService: ContentService) { }&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://angular.io/guide/dependency-injection#injecting-services" rel="noopener noreferrer"&gt;Injecting the service&lt;/a&gt; makes it available to the component.&lt;/p&gt;

&lt;p&gt;Then, define the following method for fetching the content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;getJobListings&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getJobListings&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
     &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entryCollection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jobListings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;entryCollection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jobListings&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, call the previous method inside the &lt;code&gt;ngOnInit()&lt;/code&gt; life-cycle method of the component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getJobListings&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Life-cycle methods are methods that hook into key events of the component. You can find more information about them in this &lt;a href="https://angular.io/guide/lifecycle-hooks" rel="noopener noreferrer"&gt;article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the same way, open the &lt;code&gt;src/app/job-listing/job-listing.component.ts&lt;/code&gt; file and add the following imports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ActivatedRoute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ParamMap&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;switchMap&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rxjs/operators&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ContentService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../content.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;TypeJobListingFields&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../content-types&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, define the following property:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;jobListing: TypeJobListingFields | null = null;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Next, inject the following services:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;contentService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ContentService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ActivatedRoute&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;a href="https://angular.io/api/router/ActivatedRoute" rel="noopener noreferrer"&gt;ActivatedRoute&lt;/a&gt; class provides information about the active route in the outlet.&lt;/p&gt;

&lt;p&gt;Next, update the &lt;code&gt;ngOnInit&lt;/code&gt; hook of the component as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paramMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;switchMap&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ParamMap&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getJobListingById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
     &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jobListing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the component is initialized, you get the job’s listing ID from the route using &lt;code&gt;ParamMap&lt;/code&gt; with &lt;code&gt;switchMap&lt;/code&gt;. Since your service method returns an &lt;code&gt;observable&lt;/code&gt;, flatten the observable with the &lt;code&gt;switchMap&lt;/code&gt; operator and subscribe to the resulting &lt;code&gt;observable&lt;/code&gt; to get the fetched entry and assign it to the &lt;code&gt;jobListing&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;switchMap&lt;/code&gt; operator also cancels any previous ongoing requests. If the user navigates to the route with a different ID while the &lt;code&gt;ContentService&lt;/code&gt; is still fetching the content, &lt;code&gt;switchMap&lt;/code&gt; removes the previous request and returns the job listing for the current ID.&lt;/p&gt;

&lt;p&gt;This code will generate the base list of all jobs, each with a link to a more descriptive page containing the full content.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Rendering the content
&lt;/h2&gt;

&lt;p&gt;After that, the next step is to render the content in the component’s template. As our app will contain a list of components that contain a link to the full component description, we now have to construct the full components.&lt;/p&gt;

&lt;p&gt;Open the &lt;code&gt;src/app/job-listing/job-listing.component.html&lt;/code&gt; file and update it as follows. Be sure to remove the p tag!&lt;/p&gt;

&lt;p&gt;Notice that under the How to apply section, you’re displaying the content of the &lt;code&gt;howToApply&lt;/code&gt; field, yet you’re getting &lt;code&gt;[object Object]&lt;/code&gt; displayed. That’s because this is a Rich Text field, a JSON format for handling complex content structures in a strongly typed manner in Contentful. &lt;/p&gt;

&lt;p&gt;This is how the fields appear:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl5hhpsxg2jjxv6fjxpe4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl5hhpsxg2jjxv6fjxpe4.png" alt=" " width="800" height="625"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Contentful provides many tools to help you work with the &lt;a href="https://www.contentful.com/developers/docs/concepts/rich-text/" rel="noopener noreferrer"&gt;Rich Text&lt;/a&gt; feature. Because you’re already installed the &lt;code&gt;@contentful/rich-text-html-renderer&lt;/code&gt;package, it’s easy to display rich text fields via a &lt;code&gt;documentToHtmlStringfunction&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Since you’re using Angular, you need to use the function with a &lt;a href="https://angular.io/guide/pipes" rel="noopener noreferrer"&gt;custom pipe&lt;/a&gt; that you can apply to the field in the component’s template to display it correctly.&lt;/p&gt;

&lt;p&gt;Go back to your command-line interface and run the following command to generate a pipe:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ng g pipe toHtml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Open the &lt;code&gt;src/app/to-html.pipe.ts&lt;/code&gt; file and update it as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Pipe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PipeTransform&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;documentToHtmlString&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@contentful/rich-text-html-renderer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Document&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@contentful/rich-text-types&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Pipe&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;toHtml&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ToHtmlPipe&lt;/span&gt; &lt;span class="kr"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;PipeTransform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nf"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;documentToHtmlString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can then go back to the &lt;code&gt;joblisting.component.html&lt;/code&gt;file and display the rich text field using the following code:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;div [innerHtml]="jobListing.fields.howToApply | toHtml"&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Since the result of applying our custom &lt;code&gt;toHtml&lt;/code&gt; pipe to the &lt;code&gt;howToApply&lt;/code&gt; field is HTML content, you need to bind to the &lt;code&gt;innerHtml&lt;/code&gt; attribute to render it inside the &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After applying the pipe, the field should look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl26dd30hza2ac08ei0cf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl26dd30hza2ac08ei0cf.png" alt=" " width="800" height="622"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the final result with some example job listings: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq4ttkrrfmzdy8ffcpva2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq4ttkrrfmzdy8ffcpva2.png" alt=" " width="800" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Further functionality
&lt;/h2&gt;

&lt;p&gt;While this is basic functionality, there are many more things that make Angular a great choice with Contentful. One of the primary benefits of &lt;a href="https://angular.io/" rel="noopener noreferrer"&gt;Angular&lt;/a&gt; is the potential to develop apps that can be used on the web, native mobile, and desktop.&lt;/p&gt;

&lt;p&gt;It offers a number of benefits in terms of both performance and productivity, using APIs including &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers" rel="noopener noreferrer"&gt;Web Workers&lt;/a&gt; and &lt;a href="https://angular.io/guide/universal" rel="noopener noreferrer"&gt;Angular Universal&lt;/a&gt; for server-side rendering.&lt;/p&gt;

&lt;p&gt;Additionally, Angular also includes high-quality developer tools that simplify the process of developing full projects with multiple apps and libraries. It also comes with its own &lt;a href="https://angular.io/guide/template-syntax" rel="noopener noreferrer"&gt;templatesyntax &lt;/a&gt;that extends HTML and may be enhanced with custom components.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This tutorial used Contentful as our Angular application’s backend for managing content on a job listing website. By working through this demonstration, you’ve seen how easy it is to build a full-stack application using Contentful and Angular.&lt;/p&gt;

&lt;p&gt;Contentful enables you to accomplish more and separate your front end or view layer from &lt;a href="https://www.contentful.com/blog/2020/03/26/contentful-wordpress-alternative/" rel="noopener noreferrer"&gt;managing content&lt;/a&gt;, making it simpler to interface the front end with the back. Additionally, you save time with Contentful because you only need to write and update content once for all the platforms that are integrated with your CMS.&lt;/p&gt;

&lt;p&gt;Do you want to quickly and efficiently manage the contents of your Angular application, but don’t want to build a custom back end from scratch? Contentful is the solution you’re looking for.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Ruby on Rails tutorial: Getting started with Contentful</title>
      <dc:creator>Luke Stahl</dc:creator>
      <pubDate>Fri, 16 Sep 2022 14:14:13 +0000</pubDate>
      <link>https://forem.com/contentful/ruby-on-rails-tutorial-getting-started-with-contentful-1lge</link>
      <guid>https://forem.com/contentful/ruby-on-rails-tutorial-getting-started-with-contentful-1lge</guid>
      <description>&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: This article originally appeared on the &lt;a href="https://www.contentful.com/blog/" rel="noopener noreferrer"&gt;Contentful Blog&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ruby on Rails, often shortened to Rails, is a Ruby-based Model-View-Controller (MVC) framework for building production-ready web applications and services. Rails provides several out-of-the-box features, such as database migrations and ActiveRecord (ORM), to assist developers as they build applications in minimal time. &lt;/p&gt;

&lt;p&gt;Rails shares several similarities with Django, a Python web development framework. However, unlike Django, Rails allows developers to build the controller-specific logic of their application. They also share the convention-over-configuration philosophy and provide standard practices for developers to follow.&lt;/p&gt;

&lt;p&gt;Developers building applications with Rails will benefit from leveraging the existing functionalities of gems created by members of the Rails community. For an improved developer experience, Contentful provides several gems that make interacting with its API easier.&lt;/p&gt;

&lt;p&gt;To demonstrate how Contentful integrates with Rails, this article will guide you through the process of building a demo job listing application that relies on Contentful for its data. All the sample code is stored on &lt;a href="https://github.com/contentful-developer-relations/contentful-ruby-tutorial" rel="noopener noreferrer"&gt;GitHub for reference&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To follow this tutorial, it’s recommended that you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Contentful account and access to Contentful UI. If you do not have one, create a &lt;a href="https://www.contentful.com/sign-up/" rel="noopener noreferrer"&gt;free account&lt;/a&gt; with a free 60-day trial subscription.&lt;/li&gt;
&lt;li&gt;The Ruby compiler and Ruby on Rails framework installed on your computer.&lt;/li&gt;
&lt;li&gt;A basic familiarity with the Ruby programming language.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Preparing Contentful resources
&lt;/h2&gt;

&lt;p&gt;The purpose of our job listing application is to display open job roles to job seekers. Each job listing contains several details, including the job title, description, location, and salary. To structure the data, we need to define these details on Contentful within a content model.&lt;/p&gt;

&lt;p&gt;Using the Contentful UI, create a content model that models the fields within a job post. Each job post will be created as a data entry using this content model. For this tutorial, you will use the default Space created for every Contentful account.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a Contentful content model
&lt;/h3&gt;

&lt;p&gt;Once you’re logged into Contentful, click the &lt;strong&gt;Content Model&lt;/strong&gt; item within the top navigation bar to navigate to the Content Editor page.  &lt;/p&gt;

&lt;p&gt;In the &lt;strong&gt;Create new&lt;/strong&gt; content type model box, use “jobs” as the content model name, then provide your preferred description.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy9ynel5cxv2czje6b0u1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy9ynel5cxv2czje6b0u1.png" alt=" " width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After saving the content model, use the &lt;strong&gt;+ Add fields&lt;/strong&gt; button to add the following fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A short text field type named &lt;code&gt;title&lt;/code&gt; to store the job role within the job ad,&lt;/li&gt;
&lt;li&gt;A rich text field type named &lt;code&gt;description&lt;/code&gt; to describe the job being posted,&lt;/li&gt;
&lt;li&gt;A short text field type named &lt;code&gt;salary&lt;/code&gt; to store a salary range for the job role,&lt;/li&gt;
&lt;li&gt;A short text field type named &lt;code&gt;location&lt;/code&gt; to store the office address,&lt;/li&gt;
&lt;li&gt;A boolean field type named &lt;code&gt;remote&lt;/code&gt; to indicate whether the job is remote, and&lt;/li&gt;
&lt;li&gt;A media field type named &lt;code&gt;image&lt;/code&gt; to store a thumbnail of the job role.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Click the &lt;strong&gt;Save&lt;/strong&gt; button to save the fields you have added to the content model.&lt;/p&gt;

&lt;p&gt;With the content model saved, the next step is to add your first entry.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcr71lm5out9wxrygtqtc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcr71lm5out9wxrygtqtc.png" alt=" " width="800" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding data into the content model
&lt;/h3&gt;

&lt;p&gt;Data entries for your defined content models are managed through the Content page on Contentful. For the jobs content model, we want to add some data entries to populate the Rails application.  &lt;/p&gt;

&lt;p&gt;Navigate to the Content page and create two entries in the jobs content model. Feel free to copy job details from the Contentful career page or use your preferred details.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fislc4amx3nf8rbi4zscj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fislc4amx3nf8rbi4zscj.png" alt=" " width="800" height="257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Retrieving Contentful API credentials
&lt;/h3&gt;

&lt;p&gt;Contentful provides the &lt;a href="https://www.contentful.com/developers/docs/references/content-delivery-api/" rel="noopener noreferrer"&gt;Content Delivery API&lt;/a&gt; (CDA) for developers to retrieve data stored within a Contentful space. To access the API, provide the access token associated with your Contentful space for authentication. Tokens for a Contentful space are managed on the Settings page within the Contentful UI.&lt;/p&gt;

&lt;p&gt;Click the &lt;strong&gt;Settings&lt;/strong&gt; item within the navigation bar to reveal a dropdown, then click A*&lt;em&gt;PI Keys&lt;/em&gt;* to view all API keys for your Contentful space.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcbe1bn6wr3vinlhr6ayf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcbe1bn6wr3vinlhr6ayf.png" alt=" " width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the next page, click the &lt;strong&gt;Add API Key&lt;/strong&gt; button on the right-hand side to create the first access token for the space. &lt;/p&gt;

&lt;p&gt;Leave all fields within the API Key at their default values and record the &lt;strong&gt;Space ID&lt;/strong&gt; and &lt;strong&gt;Content Delivery API&lt;/strong&gt; - access token values in a secure text editor. In the following section, you’ll use these values while building the frontend of the Ruby project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbkj3zgl2ur7lk8n5i9hy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbkj3zgl2ur7lk8n5i9hy.png" alt=" " width="800" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this point, you have created a content model and obtained your Space ID alongside the associated access token. Let’s now build the Rails application to retrieve and display the two entries within the jobs content model.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building the Ruby on Rails application
&lt;/h3&gt;

&lt;p&gt;Within this tutorial, you will use Contentful as a &lt;a href="https://www.contentful.com/developers/docs/ruby/tutorials/create-your-own-rails-app/#:~:text=Contentful%20as%20a%20View%20Helper" rel="noopener noreferrer"&gt;View Helper&lt;/a&gt; to retrieve entries from your Contentful Space.  &lt;/p&gt;

&lt;p&gt;To begin, execute the two commands below to ensure you have Ruby and Rails installed on your computer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ruby &lt;span class="nt"&gt;--version&lt;/span&gt;
rails &lt;span class="nt"&gt;--version&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you do not have Rails installed, you could either install it following the gem command below or walk through the &lt;a href="https://gorails.com/setup/osx/12-monterey" rel="noopener noreferrer"&gt;GoRails installation guide&lt;/a&gt; to install Rails for your OS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gem &lt;span class="nb"&gt;install &lt;/span&gt;rails
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbde1eytvklejq7xdaqf3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbde1eytvklejq7xdaqf3.png" alt=" " width="800" height="145"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, generate a new application using the Rails CLI with the command below. The --css flag will instruct the Rails installer to use &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;TailwindCSS&lt;/a&gt; for styling the application layouts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails new contentful-job-ads &lt;span class="nt"&gt;--css&lt;/span&gt; tailwind
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will create several files and folders that make up the Rails application. You will do the most work within this app directory. The &lt;a href="https://guides.rubyonrails.org/getting_started.html#creating-the-blog-application:~:text=File/Folder,Purpose" rel="noopener noreferrer"&gt;File/folder section&lt;/a&gt; of the Rails documentation explains the purpose of each file and directory. &lt;/p&gt;

&lt;p&gt;Move into the generated Rails project directory and use &lt;a href="https://bundler.io/guides/rails.html" rel="noopener noreferrer"&gt;bundle&lt;/a&gt; to install the two gems below. You’ll use these while building the application.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;a href="https://rubygems.org/gems/contentful" rel="noopener noreferrer"&gt;Contentful gem &lt;/a&gt;for wrapping the Content Delivery and Preview APIs from Contentful. You’ll use the gem to access your content entries within Contentful from the Rails app. &lt;/li&gt;
&lt;li&gt;The &lt;a href="https://rubygems.org/search?query=rich_text_renderer" rel="noopener noreferrer"&gt;Rich_text_renderer gem&lt;/a&gt; for displaying the description Rich Text within the jobs content model.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;contentful-job-ads

bundle add contentful rich_text_renderer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using your preferred code editor, open the &lt;code&gt;contentful-job-ads&lt;/code&gt; project to create and modify existing files in the next section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defining the application route
&lt;/h3&gt;

&lt;p&gt;The Rails application is intended to display a list of all available jobs on the default page immediately after the opening application. To achieve this design,  change the default route within the application from the Rails welcome page to a custom page. &lt;/p&gt;

&lt;p&gt;Open the &lt;code&gt;routes.rb&lt;/code&gt; file within the &lt;code&gt;config&lt;/code&gt; directory and add the path below, which matches the jobs function within the root controller.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;draw&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
 &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;root#jobs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="nx"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, use the Rails CLI to generate a controller named root for the path you defined above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails generate controller root 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating a service object
&lt;/h3&gt;

&lt;p&gt;Service objects are Plain Old Ruby Objects (PORO) created for specific functions. These are where developers keep specific business logic to avoid clogging up a controller with unrelated code.&lt;/p&gt;

&lt;p&gt;By default, services aren’t included when you generate a Rails application. Create your first service manually with the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a &lt;code&gt;services&lt;/code&gt; directory within the &lt;code&gt;contentful-job-ads/app&lt;/code&gt; folder. &lt;/li&gt;
&lt;li&gt;Create a &lt;code&gt;job_service.rb&lt;/code&gt; file and add the code below to build the &lt;code&gt;JobService&lt;/code&gt; class.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;code&gt;JobService&lt;/code&gt; class below contains a constructor method that instantiates the Contentful client and stores the instance in a variable. You’ll use the &lt;code&gt;contentful_jobs&lt;/code&gt; method to retrieve all entries within the jobs content model, then use the &lt;code&gt;rich_renderer&lt;/code&gt; method to render the rich text for the job description. &lt;/p&gt;

&lt;p&gt;Replace the &lt;code&gt;CONTENT_SPACE_ACCESS_TOKEN&lt;/code&gt; and &lt;code&gt;CONTENTFUL_SPACE_ID&lt;/code&gt; placeholders with the access token and space ID credentials you previously obtained from the Contentful UI. Optionally, you can access these credentials using environment variables to ensure they’re not leaked when the application code enters a public code repository like GitHub.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JobService&lt;/span&gt;
  &lt;span class="nx"&gt;def&lt;/span&gt; &lt;span class="nx"&gt;initialize&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;client&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="nx"&gt;Contentful&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nx"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;access_token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CONTENTFUL_SPACE_ACCESS_TOKEN&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;space&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CONTENTFUL_SPACE_ID&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;dynamic_entries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;raise_errors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;end&lt;/span&gt;

&lt;span class="nx"&gt;def&lt;/span&gt; &lt;span class="nx"&gt;rich_renderer&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;renderer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;RichTextRenderer&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nx"&gt;Renderer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;
&lt;span class="nx"&gt;end&lt;/span&gt;

&lt;span class="nx"&gt;def&lt;/span&gt; &lt;span class="nx"&gt;contentful_jobs&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jobs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;include&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;end&lt;/span&gt;
  &lt;span class="nx"&gt;end&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, open the &lt;code&gt;contentful-job-ads/config/application.rb&lt;/code&gt; file and add the code below into the &lt;code&gt;Application&lt;/code&gt; class to load the custom services directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;config.eager_load_paths &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="sh"&gt;.root.join("app/services")
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating application view
&lt;/h3&gt;

&lt;p&gt;Create a jobs method within the root controller to instantiate the additional &lt;code&gt;JobsService&lt;/code&gt; class. The root controller resides in the &lt;code&gt;app/controllers/root_controller.rb file&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;def&lt;/span&gt; &lt;span class="nx"&gt;jobs&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;job_instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JobService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;
&lt;span class="nx"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, create a &lt;code&gt;jobs.html.erb&lt;/code&gt; file within the &lt;code&gt;app/views/root&lt;/code&gt; folder for the Rails application to render as its default page. &lt;/p&gt;

&lt;p&gt;Add the code below to the &lt;code&gt;jobs.html.erb&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;All Jobs&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width,initial-scale=1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;csrf_meta_tags&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;csp_meta_tag&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;stylesheet_link_tag&lt;/span&gt; &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;tailwind&lt;/span&gt;&lt;span class="err"&gt;",&lt;/span&gt; &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;inter-font&lt;/span&gt;&lt;span class="err"&gt;",&lt;/span&gt; &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;data-turbo-track&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;:&lt;/span&gt; &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;reload&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;stylesheet_link_tag&lt;/span&gt; &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;application&lt;/span&gt;&lt;span class="err"&gt;",&lt;/span&gt; &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;data-turbo-track&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;:&lt;/span&gt; &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="na"&gt;reload&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;javascript_importmap_tags&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;jobs = &lt;/span&gt;&lt;span class="s"&gt;@job_instance.contentful_jobs&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"width: 80rem;"&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;nav&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex flex-col items-center align-center"&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-center text-4xl font-semibold"&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; Work With Us At Contentful! &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;br&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-center text-lg"&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Together, let's &lt;span class="nt"&gt;&amp;lt;strong&amp;gt;&lt;/span&gt; deliver &lt;span class="nt"&gt;&amp;lt;/strong&amp;gt;&lt;/span&gt; the best CMS experience &lt;span class="nt"&gt;&amp;lt;br&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt; that  &lt;span class="nt"&gt;&amp;lt;strong&amp;gt;&lt;/span&gt; developers&lt;span class="nt"&gt;&amp;lt;/strong&amp;gt;&lt;/span&gt; and digital  &lt;span class="nt"&gt;&amp;lt;strong&amp;gt;&lt;/span&gt; products&lt;span class="nt"&gt;&amp;lt;/strong&amp;gt;&lt;/span&gt; can get!
    &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;br&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;br&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;section&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex flex-row justify-between"&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"pb-2 text-xl font-semibold"&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; All Open Roles &lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;hr&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;br&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;section&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;jobs.each&lt;/span&gt; &lt;span class="na"&gt;do&lt;/span&gt; &lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="na"&gt;product&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mb-12 pb-2 shadow-xl rounded-lg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"m-4 flex flex-row justify-between"&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex"&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex items-center  border-2 border-gray-600 mr-3 h-20 w-24 rounded-xl"&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;%= product.title %&amp;gt;"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https:&amp;lt;%= product.image.url%&amp;gt;"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mt-2"&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"font-semibold text-lg mb-2"&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;product.title&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"pt-1 pb-2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"inline-block bg-gray-200 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2 mb-2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Engineering&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"inline-block bg-gray-200 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2 mb-2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;product.salary&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex items-center"&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-right"&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;product.location&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; Posted On: &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;product.created_at.strftime&lt;/span&gt;&lt;span class="err"&gt;("%&lt;/span&gt;&lt;span class="na"&gt;B&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="na"&gt;d&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="na"&gt;Y&lt;/span&gt;&lt;span class="err"&gt;")&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;hr&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"m-4"&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;job_instance.rich_renderer.render&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="na"&gt;product.description&lt;/span&gt;&lt;span class="err"&gt;).&lt;/span&gt;&lt;span class="na"&gt;html_safe&lt;/span&gt;  &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To confirm that the application is working, you will start the Rails server to view the application you have built so far. &lt;/p&gt;

&lt;p&gt;Launch a separate terminal window and execute the watch command below to generate the TailwindCSS classes used in the &lt;code&gt;jobs.html.erb&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails tailwindcss:watch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, in your existing terminal window, run the command below to start the rails server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails server 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Alternatively, you can install &lt;a href="https://github.com/ddollar/foreman" rel="noopener noreferrer"&gt;Foreman&lt;/a&gt; on your computer and execute the &lt;code&gt;./bin/dev&lt;/code&gt; command to simultaneously generate the TailwindCSS classes and also run the Rails server in a single terminal. &lt;/p&gt;

&lt;p&gt;Using your web browser, navigate to the index page of the running Rails application at &lt;a href="https://localhost:3000/" rel="noopener noreferrer"&gt;local:host3000&lt;/a&gt;. You will see the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyy1907wve2ye8isli9ar.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyy1907wve2ye8isli9ar.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Further functionality
&lt;/h2&gt;

&lt;p&gt;Rails provides other features to extend the basic functionality of the job listing application that we’ve built. &lt;/p&gt;

&lt;p&gt;One notable Rails feature is &lt;a href="https://guides.rubyonrails.org/active_record_basics.html" rel="noopener noreferrer"&gt;Active Record&lt;/a&gt;, which allows developers to design the model layer of an application. Contentful’s &lt;a href="https://rubygems.org/gems/contentful_model" rel="noopener noreferrer"&gt;contentful_model gem&lt;/a&gt; allows you to associate your Rails models with content models.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Congratulations on building a job listing application that retrieves and displays job entries from a Contentful Space! To build the application, you successfully followed the Contentful as a View Helper approach by creating the Contentful client within a Service Object.&lt;/p&gt;

&lt;p&gt;Are you interested in building a related project using Contentful? &lt;a href="https://www.contentful.com/sign-up/" rel="noopener noreferrer"&gt;Create a free Contentful account&lt;/a&gt; and begin designing your content model!&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>cms</category>
      <category>tutorial</category>
      <category>rails</category>
    </item>
    <item>
      <title>What is TypeScript and why should you use it?</title>
      <dc:creator>Harshil Agrawal</dc:creator>
      <pubDate>Thu, 01 Sep 2022 10:04:30 +0000</pubDate>
      <link>https://forem.com/contentful/what-is-typescript-and-why-should-you-use-it-3bj1</link>
      <guid>https://forem.com/contentful/what-is-typescript-and-why-should-you-use-it-3bj1</guid>
      <description>&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; This article originally appeared on the &lt;a href="https://www.contentful.com/blog/2022/08/18/what-is-typescript-and-why-should-you-use-it/"&gt;Contentful Blog&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’ve been learning and using TypeScript for the past year for various projects, and I have been enjoying it. TypeScript provides a great developer experience, and I believe that it has increased my productivity. I don’t have to manually check for errors every time a change gets made, and the inline documentation helps me ship faster. In this article, I will give you an overview of TypeScript, share some of its features, and help you get started.&lt;/p&gt;

&lt;p&gt;Before learning about TypeScript, let’s take a step back and revisit JavaScript. Since the earliest days of the World Wide Web, JavaScript has been used to make websites interactive – handle mouse and keyboard events, validate forms, and so on. With time, the language evolved. You can now use JavaScript to build websites and apps for any platform. It can be used to code both the frontend and backend of your website/app. You can build cross-platform apps using React Native and desktop apps with Electron, and you can even use JavaScript for your next IoT project!&lt;/p&gt;

&lt;p&gt;With these extensive use cases, the complexity in the codebase increased. For smaller projects, using JavaScript is still fine. However, for larger projects, it became difficult to debug the code and catch errors.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is the difference between TypeScript and JavaScript?
&lt;/h1&gt;

&lt;p&gt;TypeScript is a superset of JavaScript. It means that TypeScript provides all the features and functionalities of JavaScript with some added features. TypeScript compiles to JavaScript, which the browser understands. TypeScript provides “type safety” (hence the name!) to JavaScript. It was created by Microsoft and is open source. If you’re interested in contributing or just going through the source code, you can find the repository on &lt;a href="https://github.com/Microsoft/TypeScript"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To understand type safety, consider an example where you define a variable name. In JavaScript, you would use a similar code as below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Harshil&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since this is a variable name and we haven’t defined its type, this variable can have any value. It doesn’t matter if it’s a string, number, boolean, or object. Hence, the below code will execute without errors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;

&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="na"&gt;first&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Harshi&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="na"&gt;last&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Agrawal:
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using TypeScript, you can define the type string for the variable name, as below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Harshil&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you change its value to any other type, the compiler returns an error. Type safety saves a lot of debugging time and helps in keeping the code consistent.&lt;/p&gt;

&lt;h1&gt;
  
  
  Features of TypeScript
&lt;/h1&gt;

&lt;p&gt;TypeScript extends JavaScript and improves the developer experience. It enables developers to add type safety to their projects. Moreover, TypeScript provides various other features, like interfaces, type aliases, abstract classes, function overloading, tuple, generics, etc. Explaining all the features is out of the scope of this article. However, I will present two that I find useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interface
&lt;/h2&gt;

&lt;p&gt;You receive an object when you call any Contentful API. This object response contains the necessary data that you need. Similar to the Contentful API, other APIs also send an object as a response.&lt;/p&gt;

&lt;p&gt;Interfaces get used to ensure that the object contains the required data with the correct data type. This object can be a response or request body or parameters for a function.&lt;/p&gt;

&lt;p&gt;An interface has the following syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;interfaceName&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;variableOne&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;variableTwo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the above syntax, we can create an interface Profile with the properties name and social.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Profile&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;social&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above interface can be used as follow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;hello&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Profile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Find &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; here &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;social&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above is a simple example of interfaces. There are various other functionalities that interfaces provide. You can set optional properties, extend interfaces to add new properties, and more. To learn more about interfaces, refer to the &lt;a href="https://www.typescriptlang.org/docs/handbook/interfaces.html"&gt;TypeScript documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Literal Types
&lt;/h2&gt;

&lt;p&gt;Another feature that I find useful is Literal Types. Though, by themselves, they’re not so useful. But one can combine them into unions, which makes the Literal Types useful.&lt;/p&gt;

&lt;p&gt;The following example demonstrates the syntax of Literal Types.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;social&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;twitter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;harshil1712&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the variable social has the type “twitter.” However, this isn’t useful on its own.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bob&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hey&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bob&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hey&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Max&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Argument of type '"Max"' is not assignable to parameter of type '"Alice" | "Bob"'.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above function, the second parameter can only take values that have the type of either “Alice” or “Bob.” This helps us in writing functions that only accept a certain set of known values. They can do much more with Literal Types. Read the &lt;a href="https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types"&gt;official documentation&lt;/a&gt; to learn more.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to use TypeScript?
&lt;/h1&gt;

&lt;p&gt;Now that you have a basic understanding of what TypeScript is, in this section, you will learn how to use TypeScript.&lt;/p&gt;

&lt;p&gt;Browsers don’t understand TypeScript. They understand JavaScript code. Hence, the TypeScript code needs to get compiled into JavaScript, and for that, you need the TypeScript compiler.&lt;/p&gt;

&lt;p&gt;You can install TypeScript globally using the following npm command. The global installation allows you to run the tsc command anywhere from your terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; typescript
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you have installed TypeScript, create an index.ts file and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello, World!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;greeting&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code declares a variable message and creates a function that logs the message to the console. To run this code, you have to compile it to JavaScript. Run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tsc index.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll observe that the compiler creates an index.js file with the compiled code.&lt;/p&gt;

&lt;p&gt;The TypeScript compiler is flexible and allows you to configure options like the target JavaScript version. At the time of writing this article, the default target is es3.&lt;/p&gt;

&lt;p&gt;To configure the compiler options, you can either pass them with the CLI command or create a tsconfig.json. You can learn more about the various configuration options on the &lt;a href="https://www.typescriptlang.org/tsconfig/"&gt;TSConfig Reference documentation&lt;/a&gt; page.&lt;/p&gt;

&lt;p&gt;If you want to use TypeScript in your next Contentful project, we released &lt;a href="https://www.npmjs.com/package/contentful"&gt;contentful.js&lt;/a&gt; v10 in Beta with enhanced TypeScript support. Check out the &lt;a href="https://www.contentful.com/developers/changelog/#beta-release-contentfuljs-v10-with-enhanced-typescript-support"&gt;changelog&lt;/a&gt; and let us know what you think!&lt;/p&gt;

&lt;h1&gt;
  
  
  Advantages of using TypeScript
&lt;/h1&gt;

&lt;p&gt;TypeScript extends JavaScript, providing a better developer experience. The benefits of using TypeScript over JavaScript include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Static typing – TypeScript comes with optional static typing and a type inference system, which means that a variable, declared with no type may be inferred by TypeScript based on its value.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Object oriented programming – TypeScript supports object-oriented programming concepts like classes, inheritance, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Compile time checks – JavaScript is an interpreted programming language. There is no compilation involved. Hence, the errors get caught during the runtime. Since TypeScript compiles into JavaScript, errors get reported during the compile time rather than the runtime.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Code editor support – IDEs or code editors like VS Code support autocomplete for a TypeScript codebase. They also provide inline documentation and highlight the errors.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use existing packages – You might want to use an npm package that is written in JavaScript. Since TypeScript is a superset of JavaScript, you can import and use that package. Moreover, the TypeScript community creates and maintains type definitions for popular packages that can be utilized in your project. You can learn more about it here.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  What is the best way to learn TypeScript?
&lt;/h1&gt;

&lt;p&gt;TypeScript comes with tons of features, and learning and implementing them all together might get overwhelming. I started learning TypeScript by refactoring my JavaScript codebase to TypeScript one line at a time. This helped me to migrate my codebase to TypeScript with minimal effort and helped me dive deeper into the concepts.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.typescriptlang.org/docs/handbook/intro.html"&gt;TypeScript Handbook&lt;/a&gt; is a great place to learn about TypeScript. It explains the concepts well and contains relevant examples. The handbook is also regularly updated with new features.&lt;/p&gt;

&lt;p&gt;There are also tutorials available that will help you with &lt;a href="https://www.typescriptlang.org/docs/handbook/migrating-from-javascript.html"&gt;migrating your JavaScript project&lt;/a&gt; to TypeScript or help you learn about &lt;a href="https://www.typescriptlang.org/docs/handbook/dom-manipulation.html"&gt;DOM manipulation&lt;/a&gt; in TypeScript.&lt;/p&gt;

&lt;p&gt;The Contentful community members have also created apps and tools that can help &lt;a href="https://github.com/marcolink/cf-content-types-generator-app"&gt;generate type declarations for your content types&lt;/a&gt; and &lt;a href="https://www.modelberry.com/"&gt;sync TypeScript with your content model&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you’re looking for your next TypeScript project, why don’t you create an app for your Contentful space with &lt;a href="https://www.contentful.com/developers/docs/extensibility/app-framework/"&gt;App Framework&lt;/a&gt;? The boilerplate is available in TypeScript, where you can learn or brush up your TypeScript knowledge. Happy type checking!&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>The ultimate guide to Contentful webhooks</title>
      <dc:creator>Luke Stahl</dc:creator>
      <pubDate>Tue, 30 Aug 2022 18:36:16 +0000</pubDate>
      <link>https://forem.com/contentful/the-ultimate-guide-to-contentful-webhooks-2d30</link>
      <guid>https://forem.com/contentful/the-ultimate-guide-to-contentful-webhooks-2d30</guid>
      <description>&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: This article originally appeared on the &lt;a href="https://www.contentful.com/blog/2022/08/25/ultimate-guide-contentful-webhooks/" rel="noopener noreferrer"&gt;Contentful Blog&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As web applications remain an integral and potent driving force of the digital age, developers, stakeholders, and end users can choose from a plethora of the newest technologies to support their applications. One of these tools is the webhook, which virtually any web app can integrate to create dynamic and responsive content. &lt;/p&gt;

&lt;h2&gt;
  
  
  What are webhooks?
&lt;/h2&gt;

&lt;p&gt;Webhooks are a unidirectional mechanism that applications can use to talk to each other when a particular event occurs. Think of a webhook as an automated, one-way communication from one application to another. The first application sends the information to the receiver without waiting for a response. Then, it relies on the receiver to process this information. &lt;/p&gt;

&lt;p&gt;For example, you might use a content management system (CMS) platform to serve as a data source for your application. Ideally, when you update fields of the CMS and publish them, you want your application to know to look for these updates automatically. So, your CMS triggers a webhook that rebuilds the application to mirror the CMS.   &lt;/p&gt;

&lt;p&gt;The one-way nature of webhooks differentiates them from many other communication systems, such as APIs. Though webhooks serve much of the same purpose as APIs, they’re less resource intensive and more efficient when you need to feed information somewhere asynchronously. &lt;/p&gt;

&lt;p&gt;APIs require both a request and a response, adding latency and possibly resulting in the need to poll for data with constant checks. In contrast, using webhooks eliminates the need to constantly check for new data. Instead, whenever a specific event occurs, the webhook automatically notifies you. Also, the one-way nature of webhooks enables multiple locations to receive the transmitted information simultaneously.&lt;/p&gt;

&lt;p&gt;The use cases for webhooks primarily depend on what you want to achieve with your application. There are several ways you can use webhooks creatively to meet your goals. For example, with webhooks, you can listen for database changes for a user’s profile completion and then send an email to the user with welcome information, next steps, and so on. Additionally, you can integrate applications — such as Jira, Bitbucket, or a calendar application — with your messaging platform to enable receiving real-time updates. &lt;/p&gt;

&lt;p&gt;Now that you’re more familiar with the general idea behind webhooks, let’s explore how you can gain even more function and flexibility with Contentful webhooks.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Contentful webhooks work
&lt;/h2&gt;

&lt;p&gt;The one-way communication webhooks provide is ideal for a system like Contentful. Contentful webhooks enable updates to flow in real time, as any change occurring within the system can trigger a webhook. The webhook then sends information about these changes or updates to any number of systems.&lt;/p&gt;

&lt;p&gt;This low-latency architecture provides much faster communication than a similar API-driven system, ensuring that any change to content within the system is immediately reflected in all connected systems.&lt;/p&gt;

&lt;p&gt;Most Contentful webhooks are triggered when either a data, content model, or content state undergoes a change. As a result, any sites or apps listening for that webhook then immediately know they need to update. These functionalities provide the possibility of triggering a chat event, an update event for users, or the rebuilding of your &lt;a href="https://www.contentful.com/blog/2022/04/27/best-api-first-nextjs-cms/" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt; or &lt;a href="https://www.contentful.com/blog/2022/05/31/the-best-cms-for-your-gatsby-project/" rel="noopener noreferrer"&gt;Gatsby&lt;/a&gt; static website. &lt;/p&gt;

&lt;p&gt;Contentful webhooks can be divided into five type categories: ContentType, Entry, Asset, Task, and Release. Moreover, each type supports a variety of actions. For example, for an Entry webhook, Contentful supports all potential actions: create, save, auto_save, archive, unarchive, publish, unpublish, and delete.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.contentful.com/developers/docs/concepts/webhooks/" rel="noopener noreferrer"&gt;table below&lt;/a&gt; displays the capabilities of each webhook type:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1sjn5yjgl1zprl0vldfz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1sjn5yjgl1zprl0vldfz.png" alt=" " width="800" height="389"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In addition to the types mentioned in the table, Contentful also offers some proprietary webhooks for release actions, bulk actions, and scheduled actions. Let’s explore each one of these and how you can use them. &lt;/p&gt;

&lt;h3&gt;
  
  
  Release and release actions
&lt;/h3&gt;

&lt;p&gt;To understand release actions, you first need to understand a release. A release is a field or tool that you can assign to your content. A primary application for a release might be to mass publish or unpublish the contents from your CMS. For example, if your ecommerce business is having a sales event and you want to publish all the spotlighted sale items, you can create and add the release to these items, then use it to publish and unpublish them. &lt;/p&gt;

&lt;p&gt;Release action webhooks can then listen for the release event — in this case, the publish and unpublish activities. Contentful supports two types of release actions: create and execute. The release action webhook is primarily designed to act on another action. For example, once you have published the release, you might want to listen for the release action webhooks. After successful execution, you might want to initiate a new website build to fetch data more efficiently. &lt;/p&gt;

&lt;h3&gt;
  
  
  Bulk actions
&lt;/h3&gt;

&lt;p&gt;Bulk actions can be especially useful when the data your application displays to the end user is constantly changing, and your headless application needs to consistently remain updated to provide the best user experience. Similar to release action webhooks, Contentful supports create and execute actions with this bulk action webhook. &lt;/p&gt;

&lt;p&gt;Returning to the example of the hypothetical ecommerce site, assume you intend to provide discounts on certain products according to the day. For this situation, you can create bulk actions that publish new products at the end of each day and unpublish the previous day’s discounted items. &lt;/p&gt;

&lt;p&gt;By listening to bulk action webhooks, you are able to know precisely when the bulk action executes, and can then trigger a build accordingly. Therefore, this type of webhook is extremely beneficial for any site that displays frequently updated dynamic content. &lt;/p&gt;

&lt;h3&gt;
  
  
  Scheduled actions
&lt;/h3&gt;

&lt;p&gt;Unlike bulk action and release action webhooks, scheduled actions expose webhooks for the create, save, execute, and delete event types. These webhooks can be beneficial for performing such steps as creating a build or running a search after setting up a scheduled action for your content. &lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing webhooks
&lt;/h2&gt;

&lt;p&gt;In this section, we’ll explain how to implement Contentful webhooks using both the Contentful dashboard and the Contentful API. &lt;/p&gt;

&lt;h3&gt;
  
  
  Using the Contentful dashboard
&lt;/h3&gt;

&lt;p&gt;Contentful’s dashboard interface makes it easy to create webhooks, regardless of your level of expertise.  &lt;/p&gt;

&lt;p&gt;Begin by logging into your account. Then, once you’re in the Space, click on the &lt;strong&gt;Settings&lt;/strong&gt; dropdown on the upper navigation bar, as shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhis39gvw5l9sumu0tqmh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhis39gvw5l9sumu0tqmh.png" alt=" " width="800" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After expanding the &lt;strong&gt;Settings&lt;/strong&gt; dropdown, select &lt;strong&gt;Webhooks&lt;/strong&gt; to navigate to the &lt;strong&gt;Webhooks&lt;/strong&gt; dashboard.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fng62571d7chajmv4jfrv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fng62571d7chajmv4jfrv.png" alt=" " width="800" height="547"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;strong&gt;Webhooks&lt;/strong&gt; dashboard, you’ll see a list of already created Webhooks (if you have any), a button labeled + &lt;strong&gt;Add Webhook&lt;/strong&gt; toward the upper-right corner of the page, and a right-hand panel that displays another helpful Contentful feature: a selection of several Webhook template options. These templates provide a user-friendly way to create webhooks for your continuous integration/continuous deployment (CI/CD) integrations. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk1zujjmdljbb24co2ui5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk1zujjmdljbb24co2ui5.png" alt=" " width="800" height="348"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For now, click the + &lt;strong&gt;Add Webhook&lt;/strong&gt; button to open the form, as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2z41qvkztvwogqqqf69w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2z41qvkztvwogqqqf69w.png" alt=" " width="800" height="659"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The form requires a name and URL for the webhook. Additionally, unless selected specifically, the created webhooks trigger all the events. &lt;/p&gt;

&lt;p&gt;Click the radio button next to &lt;strong&gt;Select specific triggering events&lt;/strong&gt; to see the checkbox selections for the events and types that you want this webhook to listen to. The disabled checkboxes represent the events that Contentful does not support for the given action type. &lt;/p&gt;

&lt;p&gt;Then, after moving past the Triggers section, there’s an option to add filters to the webhook. It offers a variety of selections to compare, such as &lt;strong&gt;Environment ID, Content Type ID, Entity ID, User ID(created by), User ID (updated by)&lt;/strong&gt;, and logical comparisons using equal, not equal, in, not in, regexp, and not regexp. Additionally, note that you can have more than one filter per webhook, which helps you to have sophisticated conditions. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4gxpr90iqmqnhl61ylrh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4gxpr90iqmqnhl61ylrh.png" alt=" " width="800" height="167"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the &lt;strong&gt;Filters&lt;/strong&gt;, you have the ability to set the &lt;strong&gt;Headers, Content type, Content length, and Payload&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo6uk0d11s13jm216j1wh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo6uk0d11s13jm216j1wh.png" alt=" " width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Payload&lt;/strong&gt; functionality provides the ability to alter the webhooks format to match your application’s structure. This can save considerable time. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm7jm8pyrgu5cd83zquim.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm7jm8pyrgu5cd83zquim.png" alt=" " width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After filling in the necessary details, click &lt;strong&gt;Save&lt;/strong&gt;. You’ve now created a webhook that you can view in the &lt;strong&gt;Webhooks&lt;/strong&gt; dashboard. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0q0sm4uorg7zz2rgn5cr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0q0sm4uorg7zz2rgn5cr.png" alt=" " width="800" height="565"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You now know how to create a webhook and add a filter using the Contentful graphical user interface (GUI). In the next section, you’ll use Contentful’s API to do the same.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Using the Contentful API to create the webhooks
&lt;/h2&gt;

&lt;p&gt;Contentful also offers the API routes to create and configure the webhooks. But, before you continue using the APIs to retrieve the webhooks, ensure that you have the API key you need to authorize. &lt;/p&gt;

&lt;p&gt;You’ll start by fetching the list of existing webhooks. You can get the webhook you created using the GUI by executing a curl request. The only things that you’ll need are the &lt;code&gt;SPACE_ID&lt;/code&gt; and &lt;code&gt;API_KEY&lt;/code&gt;.  The curl request should appear as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; GET &lt;span class="s2"&gt;"https://api.contentful.com/spaces/&amp;lt;SPACE_ID&amp;gt;/webhook_definitions"&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &amp;lt;API_KEY&amp;gt;"&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/vnd.contentful.management.v1+json"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Importing that request into Postman and pressing the Send button yields the previously created webhook with all the information, including the name, URL, space, filters, and headers. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpyhccdtkml0ykjfltask.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpyhccdtkml0ykjfltask.png" alt=" " width="800" height="741"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Similarly, you can use the API to create the webhook. To create a webhook via the API, you’ll need the &lt;code&gt;SPACE_ID&lt;/code&gt; and &lt;code&gt;API_KEY&lt;/code&gt;. Here’s how a basic curl request looks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://api.contentful.com/spaces/&amp;lt;SPACE_ID&amp;gt;/webhook_definitions"&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"url": "&amp;lt;URL&amp;gt;", "name": "WEBHOOK_NAME", "topics": ["*.*"], , "filters": []}'&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Authorization: Bearer &amp;lt;API_KEY&amp;gt;'&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/vnd.contentful.management.v1+json'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It accepts the four items as a part of the body of the API call, which includes URL, name, topics as an array of topics, and filters as an array of filters. &lt;/p&gt;

&lt;p&gt;Topics relate to what kind of changes you want to subscribe to (see the table at the beginning of the article). If you want to subscribe to all the actions across multiple types, you can use &lt;em&gt;.&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Similar to types and events, filters can also be passed in as a JSON object to the body of the API call to create the webhook. Check out what kind of filter constraints the API provides by reviewing the &lt;a href="https://www.contentful.com/developers/docs/concepts/webhooks/" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;So, if you want a filter similar to the one you created using the GUI, you’ll need to pass the following &lt;code&gt;filters&lt;/code&gt; object in the JSON body, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"filters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"in"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"doc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sys.environment.sys.id"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="s2"&gt;"master"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s also possible to add multiple logical conditions to behave like a logical “AND”:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"filters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"in"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"doc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sys.environment.sys.id"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="s2"&gt;"master"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"equals"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"doc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sys.id"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"146353"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the following information in mind, you can use the API with Postman. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3y4ogy9ithrq19ggiu49.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3y4ogy9ithrq19ggiu49.png" alt=" " width="800" height="332"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The following JSON object was passed to create a similar webhook as what you made using the GUI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://www.example-app.com/api/update"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Trigger Build API"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"topics"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"*.*"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"filters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"in"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"doc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sys.environment.sys.id"&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="s2"&gt;"master"&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the successful request, you should get a similar response from the API: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxs3fjg8oxtz5snwy8ev6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxs3fjg8oxtz5snwy8ev6.png" alt=" " width="800" height="671"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Contentful’s wide variety of webhooks can be largely beneficial for doing various tasks, such as building a static website after a set of actions, running a script to generate index files for the search, and sending a notification to the stakeholders after completion of scheduled or bulk actions.  &lt;/p&gt;

&lt;p&gt;Contentful also offers two ways to create webhooks using the API and GUI, providing a balance of flexibility and function. &lt;a href="https://www.contentful.com/sign-up/" rel="noopener noreferrer"&gt;Sign up for a free Contentful account&lt;/a&gt; and see how our market-leading content platform can support your project or business.&lt;/p&gt;

</description>
      <category>webhooks</category>
      <category>cms</category>
    </item>
    <item>
      <title>A hands-on tutorial for using Contentful with Vue</title>
      <dc:creator>Luke Stahl</dc:creator>
      <pubDate>Thu, 18 Aug 2022 15:43:00 +0000</pubDate>
      <link>https://forem.com/contentful/a-hands-on-tutorial-for-using-contentful-with-vue-1en7</link>
      <guid>https://forem.com/contentful/a-hands-on-tutorial-for-using-contentful-with-vue-1en7</guid>
      <description>&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: This article originally appeared on the &lt;a href="https://www.contentful.com/blog/2022/08/18/vue-tutorial/" rel="noopener noreferrer"&gt;Contentful Blog&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An advantage of using a &lt;a href="https://www.contentful.com/r/knowledgebase/what-is-headless-cms/" rel="noopener noreferrer"&gt;headless CMS&lt;/a&gt; is that it allows you to have a single data source. You can use Contentful’s REST APIs to serve content to multiple devices, such as web, mobile, and IoT devices, or different tech stacks on the client side. &lt;/p&gt;

&lt;p&gt;Contentful is an integrated, API-first content platform that enables you to create and deliver engaging digital experiences quickly and efficiently.&lt;/p&gt;

&lt;p&gt;This article demonstrates how to set up a project on Contentful, create a space, add data, and publish this data. Then, it goes through how to pull the data and display it on your web app using Vue.&lt;/p&gt;

&lt;p&gt;Vue is a frontend framework that allows you to implement web applications while improving scalability quickly. It abstracts low-level functionalities, letting you manage and display data properly. It also allows you to reuse code using components, meaning you can reuse a user interface without repeating code.&lt;/p&gt;

&lt;p&gt;In this demo, you’ll use the &lt;a href="https://www.contentful.com/developers/docs/references/content-delivery-api/" rel="noopener noreferrer"&gt;Content Delivery API&lt;/a&gt; to get ecommerce data and display it within a reusable Vue component. Specifically, you’ll build an ecommerce store that allows you to select and display bags and add them to a cart. You can view the complete project code on GitHub.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa0b0ngpuiqjme2gxnlxt.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa0b0ngpuiqjme2gxnlxt.gif" alt="Purse shopping cart gif" width="600" height="307"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;To get started, &lt;a href="https://www.contentful.com/sign-up/" rel="noopener noreferrer"&gt;create your free Contentful account&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;When you sign up, you’ll automatically get your first space. You can think of a space as a project within Contentful. For this tutorial, you can either rename the space that was created automatically or create a new one.&lt;/p&gt;

&lt;p&gt;Next, create a content model and content type. Consult the &lt;a href="https://www.contentful.com/help/contentful-101/#step-3-create-the-content-model" rel="noopener noreferrer"&gt;beginner’s guide to Contentful&lt;/a&gt; for step-by-step instructions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5fdwgl8wkg05g4s95st7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5fdwgl8wkg05g4s95st7.png" alt=" " width="800" height="689"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your content type needs a name that describes your collective data entries. Since this demo is an ecommerce store for bags, name the content type “Bags.”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvae21jlwnm108l40vllo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvae21jlwnm108l40vllo.png" alt=" " width="800" height="718"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, create fields in your content model. For your bag store, you need three fields: Title, ImageUrl, and Description. Be sure that the imageUrl points to a valid image or else the display will not work properly. &lt;/p&gt;

&lt;p&gt;Click + &lt;strong&gt;AddField&lt;/strong&gt; and add a new field. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpgtxkvmiiqanbquhwwul.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpgtxkvmiiqanbquhwwul.png" alt=" " width="800" height="476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, click the &lt;strong&gt;Content&lt;/strong&gt; tab and add some example entries using these fields. Make sure to publish each entry once you add it.&lt;/p&gt;

&lt;p&gt;For example, below is a listing for a brown messenger handbag, including a title, description, and URL.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbi9mvrfbacoq4us80k11.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbi9mvrfbacoq4us80k11.png" alt=" " width="800" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After a few entries have been added and published, you’ll be ready to pull your data from a &lt;a href="https://www.contentful.com/blog/2021/10/04/what-is-a-rest-api/" rel="noopener noreferrer"&gt;RESTful API&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0vzplhf439ndhptmv6hy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0vzplhf439ndhptmv6hy.png" alt=" " width="800" height="694"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Contentful’s Content Delivery API
&lt;/h2&gt;

&lt;p&gt;Contentful makes it possible to access your data using the &lt;a href="https://www.contentful.com/developers/docs/references/content-delivery-api/" rel="noopener noreferrer"&gt;Content Delivery API&lt;/a&gt;. This REST API allows you to access the data in your space through a single request. Contentful provides a GraphQL endpoint, but this demo will focus on the REST API.&lt;/p&gt;

&lt;p&gt;Now that you’ve added all your data to the dashboard, you can pull the data into your Vue application using the Content Delivery API. To proceed, make sure you have the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Space ID&lt;/strong&gt; — This is a unique ID associated with each space.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Content Delivery API access token&lt;/strong&gt; — This is a token used when interacting with the Content Delivery API.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find both by clicking &lt;strong&gt;Settings&lt;/strong&gt; in the top-right of the dashboard and selecting &lt;strong&gt;API Keys&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frgbf4cmiepzqnv5b0i0l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frgbf4cmiepzqnv5b0i0l.png" alt=" " width="800" height="673"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Add the following endpoint on &lt;a href="https://www.postman.com/" rel="noopener noreferrer"&gt;Postman&lt;/a&gt;, and it will return all our field entries:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://cdn.contentful.com/spaces/{SPACE_ID}/environments/master/entries?access_token={ACCESS_TOKEN}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faqozbqi85nc7e26armmz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faqozbqi85nc7e26armmz.png" alt=" " width="800" height="769"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your data is now returned from Contentful’s endpoint. Your next task is setting up your Vue code and pulling the data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Vue CLI
&lt;/h2&gt;

&lt;p&gt;To initiate your Vue app, you need to install &lt;a href="https://cli.vuejs.org/" rel="noopener noreferrer"&gt;Vue CLI&lt;/a&gt; globally on your machine. If you already have it installed, you can skip this step.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install -g @vue/cli&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Once it’s installed, you’ll use Vue CLI to initiate your project. Initiate a new project using this command in your terminal:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;vue create vue-ecommerce-site&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Within your terminal, you’ll have to manually select your preferred options for your project until the appropriate Vue boilerplate code is ready. Please select Vue 2, as that is what this tutorial is based upon. We suggest you deselect both Babel and Linter, as they can cause complications. Proceed with the installation. Once the installation is completed, you can navigate to your project’s folder:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd vue-ecommerce-site&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now, let’s install vue-router. Please install the following version:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm i vue-router@3.5.4&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Also, install &lt;a href="https://www.npmjs.com/package/axios" rel="noopener noreferrer"&gt;axios&lt;/a&gt;. You’ll use this popular HTTP client to make your API request to Contentful:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm i axios&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then, start the server:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm run serve&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It should fire up your project, and you should see this in the browser:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fevpqbm689tvctr9g2es8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fevpqbm689tvctr9g2es8.png" alt=" " width="800" height="545"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go into the components folder and create two new components called &lt;em&gt;ContentfulComponent.vue&lt;/em&gt; and &lt;em&gt;CartComponent.vue&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;ContentfulComponent.vue&lt;/em&gt; displays the list of bags, while &lt;em&gt;CartComponent.vue&lt;/em&gt; will display our cart.&lt;/p&gt;

&lt;p&gt;Now, let’s make use of our &lt;em&gt;vue-router&lt;/em&gt;. Create a &lt;em&gt;router&lt;/em&gt; folder inside our &lt;em&gt;src&lt;/em&gt; and within the router, we can now add &lt;em&gt;index.js&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;VueRouter&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue-router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ContentfulComponent&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../components/ContentfulComponent.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;CartComponent&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../components/CartComponent.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Vue&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;VueRouter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ContentfulComponent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ContentfulComponent&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/cart&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CartComponent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CartComponent&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;VueRouter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;history&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, go into your main.js and import the router.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Vue&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./App.vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./router/index&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="nx"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productionTip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;h&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;$mount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#app&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, go into your &lt;em&gt;App.vue&lt;/em&gt; file, which is automatically created in the boilerplate, and import the component for use. Do not remove the styling.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;app&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Bags&lt;/span&gt; &lt;span class="nx"&gt;Store&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h3&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;
      &lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;E-commerce logo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://photo-cdn2.icons8.com/cfD33FbEpD4Srs0gXnuRWXFlet6KXB0dnU-YHbZTVzU/rs:fit:715:1072/czM6Ly9pY29uczgu/bW9vc2UtcHJvZC5h/c3NldHMvYXNzZXRz/L3NhdGEvb3JpZ2lu/YWwvMS9lY2JjNzFj/YS00NjU2LTRjNWIt/OTM1MC0wMTBlMTI4/N2I4ODYuanBn.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;25%&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/router-view&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/template&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;App&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, go into the &lt;em&gt;ContentfulComponent.vue&lt;/em&gt; file and implement your data. First, declare the &lt;em&gt;theBags&lt;/em&gt; array under data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;theBags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, add a new function called &lt;em&gt;getBags&lt;/em&gt; under &lt;em&gt;methods&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;getBags&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;axios&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://cdn.contentful.com/spaces/{SPACE_ID}/environments/master/entries?access_token={ACCESS_TOKEN}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;theBags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This pulls your data and assigns it to the &lt;em&gt;theBags&lt;/em&gt; array you’ve declared earlier. You need to import &lt;em&gt;axios&lt;/em&gt; using the following command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;import axios from "axios";&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Finally, to fully implement your business logic, you’ll add a mounted lifecycle that executes on load. Add &lt;em&gt;this.getBags();&lt;/em&gt; so it can trigger the function once the page loads.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;mounted&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBags&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Within the &lt;em&gt;&lt;/em&gt;, you’ll loop over the theBags array and display its elements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;theBags&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bag.fields.title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bag in theBags&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;indi__item&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;indi__img&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bag.fields.imageUrl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt; 
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;bag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h3&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;bag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h3&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/template&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Find the full code for the component below. Be sure to add your own space ID and Content Delivery API access token.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/cart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Open&lt;/span&gt; &lt;span class="nx"&gt;Cart&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h3&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;theBags&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bag.fields.title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bag in theBags&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;indi__item&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;indi__img&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bag.fields.imageUrl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt; 
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;bag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h3&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;bag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h3&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/template&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ContentfulComponent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
      &lt;span class="na"&gt;theBags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; 
    &lt;span class="p"&gt;};&lt;/span&gt; 
  &lt;span class="p"&gt;},&lt;/span&gt; 
  &lt;span class="na"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nf"&gt;getBags&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
      &lt;span class="nx"&gt;axios&lt;/span&gt; 
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; 
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://cdn.contentful.com/spaces/{SPACE_ID}/environments/master/entries?access_token={ACCESS_TOKEN}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; 
        &lt;span class="p"&gt;)&lt;/span&gt; 
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
          &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;theBags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
        &lt;span class="p"&gt;});&lt;/span&gt; 
    &lt;span class="p"&gt;},&lt;/span&gt; 
  &lt;span class="p"&gt;},&lt;/span&gt; 
  &lt;span class="nf"&gt;mounted&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBags&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; 
  &lt;span class="p"&gt;},&lt;/span&gt; 
&lt;span class="p"&gt;};&lt;/span&gt; 
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also add the following styling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indi__item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt; &lt;span class="nx"&gt;solid&lt;/span&gt; &lt;span class="nx"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;justify&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indi__img&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/style&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here’s what this code looks like in action:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1pf6132n1t7fgf4s25hc.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1pf6132n1t7fgf4s25hc.gif" alt=" " width="600" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Letting shoppers add items to their cart
&lt;/h2&gt;

&lt;p&gt;Next, you’ll create a cart feature for your online bag store. This lets your shoppers select the bags they need and add them to their cart. &lt;/p&gt;

&lt;p&gt;Return to your &lt;em&gt;ContentfulComponent.vue&lt;/em&gt; file and add a new method under methods called &lt;em&gt;addToCart&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Add the code below to this method. With this code, you create a cart item in local storage, allowing your application to store the specific item you want to save to the cart. Then, to enhance user experience, you add an alert to notify users when they have successfully added an item to the cart.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;addToCart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;([]));&lt;/span&gt; 
      &lt;span class="p"&gt;}&lt;/span&gt; 
      &lt;span class="c1"&gt;//console.log(item); &lt;/span&gt;
      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;cartItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt; 
      &lt;span class="nx"&gt;cartItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt; 

      &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
      &lt;span class="nx"&gt;cartItems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cartItems&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 

      &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cartItems&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; 
      &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;added to cart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="p"&gt;},&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You also need to add a button to trigger this &lt;em&gt;addToCart&lt;/em&gt; function. You’ll add this to the &lt;em&gt;"indi&lt;/em&gt;&lt;em&gt;item"&lt;/em&gt; class under &lt;em&gt;&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;indi__item&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;indi__img&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bag.fields.imageUrl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt; 
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;bag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h3&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;bag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h3&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;addToCart(bag.fields)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Add&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here’s what your demo now looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frd5h0irgf8s2zp4dcjvp.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frd5h0irgf8s2zp4dcjvp.gif" alt=" " width="600" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the cart component
&lt;/h2&gt;

&lt;p&gt;Now that you’ve added the option to add an item to the cart, you need to give shoppers access to view their carts. So, it’s time to create a cart component that displays all the items in a shopper’s cart. &lt;/p&gt;

&lt;p&gt;This component will loop through the cart’s local storage and display the cart list. Plus, users can remove individual items they don’t want from their cart.&lt;/p&gt;

&lt;p&gt;To build the cart component, add a script tag, where you’ll add an empty cart array into data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, add a &lt;em&gt;method&lt;/em&gt; that gets your cart from the local storage and assigns it to the cart array above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nf"&gt;getCart&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;([]));&lt;/span&gt; 
      &lt;span class="p"&gt;}&lt;/span&gt; 
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; 
    &lt;span class="p"&gt;},&lt;/span&gt; 
  &lt;span class="p"&gt;},&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, add a &lt;em&gt;beforeMount&lt;/em&gt; lifecycle to trigger the getCart method on load.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;beforeMount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getCart&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; 
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final method you need to add is the &lt;em&gt;removeFromCart&lt;/em&gt; method, which allows you to remove a particular item from the cart array in the local storage. It receives the imageUrl from the item and uses &lt;em&gt;findIndex()&lt;/em&gt; to return the index of that specific item in the array. Then, it uses that index to remove the item from the array using &lt;em&gt;splice()&lt;/em&gt; and saves the updated array in the local storage cart item.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
&lt;span class="nf"&gt;removeFromCart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;itemImage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cartItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; 
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cartItems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findIndex&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;imageUrl&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;imageUrl&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;itemImage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
    &lt;span class="nx"&gt;cartItems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
    &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cartItems&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; 
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; 
   &lt;span class="p"&gt;},&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your template now looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Cart&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;item of cart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;item.id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;indi__item&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;indi__img&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;item.imageUrl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt; 
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;removeFromCart(item.imageUrl)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;remove&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Back&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h3&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/template&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code loops through the cart array and displays individual items. For each item, there is a button that can be used to remove the item by firing &lt;em&gt;removeFromCart&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Here’s the full component code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Cart&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;item of cart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;item.id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;indi__item&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;indi__img&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;item.imageUrl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt; 
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;removeFromCart(item.imageUrl)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Remove&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Back&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h3&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/template&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CartComponent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
      &lt;span class="na"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; 
    &lt;span class="p"&gt;};&lt;/span&gt; 
  &lt;span class="p"&gt;},&lt;/span&gt; 
  &lt;span class="na"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nf"&gt;removeFromCart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;itemId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cartItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; 
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cartItems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findIndex&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;imageUrl&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;imageUrl&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;itemId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
      &lt;span class="nx"&gt;cartItems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
      &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cartItems&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; 
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; 
    &lt;span class="p"&gt;},&lt;/span&gt; 
    &lt;span class="nf"&gt;getCart&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;([]));&lt;/span&gt; 
      &lt;span class="p"&gt;}&lt;/span&gt; 
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; 
    &lt;span class="p"&gt;},&lt;/span&gt; 
  &lt;span class="p"&gt;},&lt;/span&gt; 
  &lt;span class="nf"&gt;beforeMount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getCart&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; 
  &lt;span class="p"&gt;},&lt;/span&gt; 
&lt;span class="p"&gt;};&lt;/span&gt; 
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And, here’s your cart:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmko9o0vlsm5tfhnngnav.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmko9o0vlsm5tfhnngnav.gif" alt=" " width="600" height="366"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Using a bag ecommerce store as an example, this tutorial explored how to add data to Contentful and display it in a Vue application. You can find all the relevant code in this &lt;a href="https://github.com/contentful-developer-relations/contentful-vue-tutorial" rel="noopener noreferrer"&gt;repo on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A key advantage of building an Vue app using Contentful is that you’ll be working alongside an active community of avid users. So, if you come across any challenges, you can join the &lt;a href="https://www.contentfulcommunity.com/" rel="noopener noreferrer"&gt;Contentful Community&lt;/a&gt; to seek help from fellow developers.&lt;/p&gt;

&lt;p&gt;To expand on everything you’ve learned in this tutorial, &lt;a href="https://www.contentful.com/sign-up/" rel="noopener noreferrer"&gt;start building with Contentful&lt;/a&gt; for free today — no credit card required.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>cms</category>
      <category>tutorial</category>
      <category>vue</category>
    </item>
    <item>
      <title>What's a framework? All about software frameworks</title>
      <dc:creator>Luke Stahl</dc:creator>
      <pubDate>Tue, 16 Aug 2022 14:55:00 +0000</pubDate>
      <link>https://forem.com/contentful/whats-a-framework-all-about-software-frameworks-33l6</link>
      <guid>https://forem.com/contentful/whats-a-framework-all-about-software-frameworks-33l6</guid>
      <description>&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; This article originally appeared on the &lt;a href="https://www.contentful.com/blog/2022/08/16/what-is-a-framework/" rel="noopener noreferrer"&gt;Contentful Blog&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a programmer, you know that web development and software development can be complex work. A framework can make your job easier, and save you the trouble of writing your code totally from scratch. The right framework can also reduce your development time by making it faster to design and troubleshoot.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a framework?
&lt;/h2&gt;

&lt;p&gt;A framework is a boilerplate that facilitates development by offering infrastructure that you can build your own code on top of. Or, you can think of it as a template that provides pre-coded and reusable functions to facilitate software development.&lt;/p&gt;

&lt;p&gt;That all sounds very abstract, so here’s a quick example to make things more concrete: Let’s say you’re a frontend developer taking on a full-stack development project. You might use one of the many popular backend frameworks that provide server-side functionality you need, then add your custom code for the frontend. &lt;/p&gt;

&lt;p&gt;Most programming languages have at least one associated framework, if not more. JavaScript frameworks include Vue and Angular, Ruby has Ruby on Rails, Python has Django, and so on. The contents of a framework can vary broadly depending on the framework, its language, and its purpose.&lt;/p&gt;

&lt;p&gt;In most cases, popular frameworks are open source and maintained by a community of developers. For example, Vercel makes Next.js because it speeds up app development, and makes it simpler for developers to use their service.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why do we use frameworks?
&lt;/h2&gt;

&lt;p&gt;In short, frameworks make development much simpler for you and your team. Since some of the code is already written and tested, a framework can speed up the development process, improve security, reduce the risk of errors, and a whole lot more. &lt;/p&gt;

&lt;p&gt;For more in-depth information about what frameworks can do for you, see “What are the benefits of frameworks?” below. &lt;/p&gt;

&lt;h2&gt;
  
  
  Types of frameworks
&lt;/h2&gt;

&lt;p&gt;As you might guess, frameworks can be used for a variety of development projects. You can find frameworks for software development, web development, working with APIs, and even doing data science work. &lt;/p&gt;

&lt;p&gt;But here are the types that you’ll come across most often and a few popular examples of each. Note that some frameworks can extend across categories. &lt;/p&gt;

&lt;h2&gt;
  
  
  Front-end frameworks
&lt;/h2&gt;

&lt;p&gt;These web-application frameworks are used for the development of the front end (visible portions) of a web application, such as layout and design.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://angular.io/" rel="noopener noreferrer"&gt;Angular&lt;/a&gt;: An open-sourceJavaScript framework for developing single-page applications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://vuejs.org/" rel="noopener noreferrer"&gt;Vue&lt;/a&gt;: An open-sourceJavaScript framework for building user interfaces and single-page applications.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Back-end frameworks
&lt;/h2&gt;

&lt;p&gt;These frameworks are used for the development of the backend of web apps, or the components that handle server-side functionality.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://rubyonrails.org/" rel="noopener noreferrer"&gt;Ruby on Rails&lt;/a&gt;: A Ruby-based, server-side framework for developing web applications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.djangoproject.com/" rel="noopener noreferrer"&gt;Django&lt;/a&gt;: A high-level Python framework for web development.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://expressjs.com/" rel="noopener noreferrer"&gt;Express&lt;/a&gt;: A node.js framework for developing web and mobile applications.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Mobile development frameworks
&lt;/h2&gt;

&lt;p&gt;Used to assist in the development of mobile applications for Android, iOS, and more — or even cross-platform applications that rely on the same codebase. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://reactnative.dev/" rel="noopener noreferrer"&gt;React Native&lt;/a&gt;: An open-source UI framework maintained by Meta (Facebook) for developing cross-platform mobile apps on Android, iOS, Android TV, MacOS, and more.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://flutter.dev/" rel="noopener noreferrer"&gt;Flutter&lt;/a&gt;: An open-source UI framework maintained by Google. Can be used to develop mobile apps for developing cross-platform mobile apps.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Software framework vs code library
&lt;/h2&gt;

&lt;p&gt;If you’re having trouble telling the difference between a framework and a code library, don’t worry, you’re not alone. This distinction confuses many seasoned programmers.&lt;/p&gt;

&lt;p&gt;Contentful’s Senior Software Engineer &lt;a href="https://www.contentful.com/blog/author/david-fateh/" rel="noopener noreferrer"&gt;David Fateh&lt;/a&gt; explained the two terms by comparing development to the process of building a house. A framework, he says, is like a construction blueprint: A template that defines a basic structure for your build. A code library is more like a carpenter’s tool belt: It has tools designed to perform specific tasks.&lt;/p&gt;

&lt;p&gt;Developer Advocate &lt;a href="https://www.contentful.com/blog/author/alvin-bryan/" rel="noopener noreferrer"&gt;Alvin Bryan&lt;/a&gt; offers a real-world example to drive the point home: Unity and Unreal are both frameworks for developing games. They both use different programming languages, one uses C++ and the other uses C#. But they might use the same library for the task of managing and controlling sound. That means they both call that library to perform a specific task.&lt;/p&gt;

&lt;p&gt;To get a bit more technical, the distinction between a framework and a coding library can be explained by a concept called inversion of control. When you use a library, your code calls the library to perform a specific task, for a specific outcome. When you use a framework, it calls your code. &lt;/p&gt;

&lt;h2&gt;
  
  
  What are the benefits of a framework?
&lt;/h2&gt;

&lt;p&gt;Frameworks offer a skeleton to build on so that programmers don’t have to start from scratch when building software or web applications. In short, it will reduce your software or web development costs and reduce your development time. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You can focus on one area of development:&lt;/strong&gt; If you’re a full-stack developer and you have a knack for backend development, you can use a framework to cover the frontend functionality. Now you can focus on what you’re best at.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved productivity:&lt;/strong&gt; You or your company can use a framework to cover reusable generic functions. This saves programmers from writing code for the parts of the software or web application that don’t change from project to project. On top of that, as you learn a framework for a language like Java, you can get even faster at development — and this will improve your productivity even further.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easier testing:&lt;/strong&gt; Frameworks can help you eliminate problems faster when you begin troubleshooting. If you’re using a reputable frontend framework, for instance, you can be sure that it’s working properly and focus your troubleshooting on the backend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Speed:&lt;/strong&gt; When you develop an application from scratch, your code for certain functionality might be less than perfectly optimized. (We all know deadlines can be tight.) When you use a framework for that same functionality, you are using code that has been developed and continuously reworked to provide the highest possible speed. In short: frameworks can make your apps much faster.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reliability:&lt;/strong&gt; A framework is maintained by developers who will test the code rigorously to ensure top-notch reliability. They’ll also ensure that it meets changing requirements so you don’t get caught with a web application that suddenly doesn’t work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation:&lt;/strong&gt; Good frameworks come with extensive documentation and community support. That is a big reason to use a framework, where you have regularly updated resources for reference, and other people to learn from and share experiences with.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better security:&lt;/strong&gt; Whether your framework is maintained by a company like Meta or Microsoft, or a community of programmers, you can trust that it has been tested and re-tested to address the security vulnerabilities of the programming language. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What are the challenges of a framework?
&lt;/h2&gt;

&lt;p&gt;Frameworks are great for many kinds of software and web development, but they’re not perfect. Here are some potential challenges to keep in mind as you explore the possibility of using a framework. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You need to learn the framework, and language:&lt;/strong&gt; A framework can help speed up development for a programmer, but they aren’t simply plug-and-play tools. You’ll need to learn the framework itself — and know the programming language the framework is based on. For example, if you like the idea of using Django, you’ll also need to know Python to make it work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structural limitations:&lt;/strong&gt; Even the most advanced frameworks aren’t designed to do everything. They’re designed for a specific purpose — such as offering a specific set of backend functionality. That makes them less useful for other tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;There are a lot of them:&lt;/strong&gt; Frameworks are popular these days, and it can be difficult to choose the right one. You’ll need to be careful to find one that works best for your application, and stick with it to get the most out of it. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How do you pick the right framework?
&lt;/h2&gt;

&lt;p&gt;If you are a programmer at a company, they will likely have a set of frameworks they like to use for various backend, frontend, and web development projects. Or, if you plan to work with a service like Contentful, they will likely have frameworks they can recommend for your software or web development.&lt;/p&gt;

&lt;p&gt;That makes it simple.&lt;/p&gt;

&lt;p&gt;If you’re looking for a framework on your own, there are questions you can ask to make the decision easier. For instance, what programming languages do you know? Is it important to use an open-source framework? What functionality do you need in a framework? Are you stronger as a frontend developer than a backend developer, or vice versa? What kind of project are you working on?&lt;/p&gt;

&lt;p&gt;Once you’ve answered these questions, look for the frameworks that are tailored toward your requirements. Then, do research to find out what other programmers think of a framework. Find the community of programmers that uses the framework and ask them whether they think it’s right for you. &lt;/p&gt;

&lt;p&gt;There are a lot of resources out there, whether you’re working on frontend development using JavaScript, or backend with Python. So don’t always pick the newest, shiniest framework. Do your homework and find the tool that’s right for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  What frameworks does Contentful recommend?
&lt;/h2&gt;

&lt;p&gt;If you’re planning to work with Contentful, we are agnostic about the framework you use for tooling on the backend. So find what works best for you, your company, and your particular software.&lt;/p&gt;

&lt;p&gt;On the frontend, Contentful endorses &lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;React&lt;/a&gt;. In fact, we use it ourselves as part of the tooling in our &lt;a href="https://www.contentful.com/app-framework/" rel="noopener noreferrer"&gt;App Framework&lt;/a&gt;. This is because it’s a widely adopted framework, it offers high usability, and it enables you to develop fast, scalable frontend applications. However, if you aren’t familiar with React or would prefer to use something else, Contentful’s rest APIs and GraphQL API make it straightforward and simple to integrate into your workflow, no matter which framework you choose. &lt;/p&gt;

&lt;p&gt;If you’re looking to integrate Contentful with other digital tools, you can use our own App Framework. Here’s &lt;a href="https://www.contentful.com/blog/2022/06/21/build-custom-apps-with-the-contentful-app-framework" rel="noopener noreferrer"&gt;how to build custom apps&lt;/a&gt; with this tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  The value of frameworks
&lt;/h2&gt;

&lt;p&gt;Frameworks can go a long way toward improving your software and web development projects. They offer fast, reliable patterns that you can use to avoid the trouble of starting from scratch. &lt;/p&gt;

&lt;p&gt;There are a variety of these tools out there, connected to programming languages from Java to Python, and intended for tasks as varied as backend development and data science. &lt;/p&gt;

&lt;p&gt;The options can be difficult to navigate, but with a little research you can find a framework that works for you. And the right framework will bring big benefits: It will reduce development time, save money, and ultimately help you make better applications and websites.&lt;/p&gt;

</description>
      <category>cms</category>
      <category>software</category>
      <category>architecture</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Content migration from Drupal 7 to Contentful: A step-by-step guide</title>
      <dc:creator>Bulent Osman Yusuf</dc:creator>
      <pubDate>Wed, 20 Jul 2022 14:36:51 +0000</pubDate>
      <link>https://forem.com/contentful/content-migration-from-drupal-7-to-contentful-a-step-by-step-guide-12ol</link>
      <guid>https://forem.com/contentful/content-migration-from-drupal-7-to-contentful-a-step-by-step-guide-12ol</guid>
      <description>&lt;p&gt;&lt;em&gt;NOTE: This article originally appeared on the &lt;a href="https://www.contentful.com/blog/2022/07/19/content-migration-from-drupal-7-to-contentful/"&gt;Contentful Blog&lt;/a&gt;. Sharing here on behalf of the author Patrick Geers.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Folks, we have an important question. Are you considering migrating your content from Drupal to Contentful? Then this post will show you how. &lt;em&gt;Carpe diem!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.drupal.org/psa-2022-02-23"&gt;Drupal 7 is officially reaching end of life on November 1, 2023&lt;/a&gt;. After that point, all support for this legacy content management system will come to a close. &lt;/p&gt;

&lt;p&gt;So how should you plan for the change? Sure, you could start using the latest version of Drupal. Or — and maybe this is a wild and crazy idea, but hear us out — you could move everything over to a new CMS. &lt;/p&gt;

&lt;p&gt;After all, if you’ve taken this long to move on from Drupal 7, there’s likely a good reason why you were taking your time.&lt;/p&gt;

&lt;p&gt;Let’s hazard a guess: Was it a feeling of dissatisfaction with using a monolithic CMS? Is it too complex to maintain? Do you desire a conscious uncoupling? To upgrade to something more versatile for your content needs?&lt;/p&gt;

&lt;p&gt;It’s time to use Contentful! We have a lot of resources on this site to outline the benefits of adopting a &lt;a href="https://www.contentful.com/r/knowledgebase/what-is-headless-cms/"&gt;headless CMS&lt;/a&gt;. But rather than dive into a discussion about content strategy and data migration, this post explains how to migrate content from Drupal 7 to Contentful. &lt;/p&gt;

&lt;p&gt;We’ll be outlining the workflow of a migration project step by step, together with examples, migration tools, and command line prompts. &lt;/p&gt;

&lt;p&gt;Before we dive in, there are two prerequisites in order for this guide to be useful. First, you have worked with Drupal 7. Second, you have some knowledge of the command line interface in Contentful. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.contentful.com/blog/2022/07/19/content-migration-from-drupal-7-to-contentful/"&gt;Ready? Let’s go!&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

</description>
      <category>drupal</category>
      <category>contentful</category>
      <category>php</category>
    </item>
    <item>
      <title>A galactic guide to building a blog with Next.js and Contentful</title>
      <dc:creator>Luke Stahl</dc:creator>
      <pubDate>Mon, 04 Apr 2022 14:25:58 +0000</pubDate>
      <link>https://forem.com/contentful/a-galactic-guide-to-building-a-blog-with-nextjs-and-contentful-12o1</link>
      <guid>https://forem.com/contentful/a-galactic-guide-to-building-a-blog-with-nextjs-and-contentful-12o1</guid>
      <description>&lt;p&gt;In a galaxy far, far away, there lived an individual who was known as the grill and breakfast guy. So he set out on an epic quest to become not just a Padawan Chef but a Master Chef, like those who came before him. &lt;/p&gt;

&lt;p&gt;This is a guide to building a blog with Contentful while using the popular JavaScript framework Next.js. If you haven’t caught on already, it’s a Star Wars-themed cookbook filled with recipes handed down from multiple family members and friends. I’m hopeful that you’ll enjoy this journey and the build out of this app. May the FOOD be with you. &lt;/p&gt;

&lt;h2&gt;
  
  
  Episode I: The Phantom Starter
&lt;/h2&gt;

&lt;p&gt;To get your project started you need to follow along with this amazing &lt;a href="https://www.contentful.com/nextjs-starter-guide/" rel="noopener noreferrer"&gt;Next.js and Contentful starter guide&lt;/a&gt; crafted by Developer Advocate &lt;a href="https://twitter.com/musicalwebdev" rel="noopener noreferrer"&gt;Brittany Walker&lt;/a&gt;. This walkthrough will help create your project, connect your Contentful account and deploy with Vercel. Following this starter you’ll be able to implement any of the additional features detailed below. &lt;/p&gt;

&lt;h2&gt;
  
  
  Episode II: Attack of the Webhooks
&lt;/h2&gt;

&lt;p&gt;Now that you have your project created, running it locally, and connected to Contentful, let’s add a webhook. By connecting it to your Vercel project, it will notify Vercel every time you make change to your content and trigger Contentful to rebuild. &lt;/p&gt;

&lt;p&gt;To add a webhook, go to settings in the Contentful web app and simply select “Add Webhook,” or you can use the Vercel template which we can do because this project is already deployed there. If you are taking the manual approach, here is the &lt;a href="https://www.contentful.com/developers/docs/concepts/webhooks/" rel="noopener noreferrer"&gt;Webhooks documentation&lt;/a&gt; to help you along. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7lzr7dky1pxpz6gch70q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7lzr7dky1pxpz6gch70q.png" alt="Webhook Templates" width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Episode III: Revenge of the Disqus
&lt;/h2&gt;

&lt;p&gt;With any good blog, having the ability for readers to interact is a must. On multiple occasions I’ve used Disqus when adding a comments section. However, being new to Next.js I wasn’t certain where to add it and Disqus doesn’t have integration with Next.js within its tool. So here are the steps to adding &lt;a href="https://disqus.com/" rel="noopener noreferrer"&gt;Disqus&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;First, sign up for an account at Disqus. They have a free plan which will get the job done. After signing up, you’ll need to click “I want to install Disqus on my site.” Follow the instructions by adding your website name and category. Again, you won’t see Next.js listed in the platforms section, so you will need to choose a manual universal code install. I will be providing an example of my code below. &lt;/p&gt;

&lt;p&gt;Now you are in luck because there is &lt;a href="https://www.npmjs.com/package/disqus-react" rel="noopener noreferrer"&gt;Disqus React&lt;/a&gt;, an npm package for Disqus. In your terminal run:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install disqus-react&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Next we are going to add a &lt;code&gt;comment.js&lt;/code&gt; file to the components folder and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// /components/comment.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;DiscussionEmbed&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;disqus-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;DisqusComments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;disqusShortname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stahlwalkercookbook&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;// use your shortName from Disqus project&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;disqusConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`https://cookblog.vercel.app/posts/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// use your URL&lt;/span&gt;
   &lt;span class="na"&gt;identifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Single post slug&lt;/span&gt;
   &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="c1"&gt;// Single post title&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DiscussionEmbed&lt;/span&gt;
       &lt;span class="nx"&gt;shortname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;disqusShortname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
       &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;disqusConfig&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
     &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;DisqusComments&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we need to import the Disqus component into the &lt;code&gt;[slug.js]&lt;/code&gt; file located in the posts folder in your pages directory. Then it’s just a matter of finding where you’d like the comments to populate, I placed it at the end of my blog posts. &lt;/p&gt;

&lt;h2&gt;
  
  
  Episode IV: A New Social Share
&lt;/h2&gt;

&lt;p&gt;I’m a fan of the ability to share your blog across whatever social networks you prefer. We’re going to use another &lt;a href="https://www.npmjs.com/package/next-share" rel="noopener noreferrer"&gt;npm package to add social sharing&lt;/a&gt;. In the terminal of your project run: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm i next-share&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;From there you can add the following code to your &lt;code&gt;[slug.js]&lt;/code&gt; file. I added this component after my article, before the comments. You’ll need to update the URL to your site’s URL to grab all the individual posts. From here, people will be able to share not just your site but the blog post you’ve written. Below is an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// /pages/posts/[slug.js]&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;social&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
           &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Looks&lt;/span&gt; &lt;span class="nx"&gt;tasty&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;share&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;friends&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;           &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FacebookShareButton&lt;/span&gt;
             &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`https://cookblog.vercel.app/posts/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
             &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FacebookIcon&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;round&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
           &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/FacebookShareButton&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;           &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TwitterShareButton&lt;/span&gt;
             &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`https://cookblog.vercel.app/posts/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
             &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TwitterIcon&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;round&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
           &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/TwitterShareButton&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feplp5a8a6smmx3oquooi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feplp5a8a6smmx3oquooi.png" alt="Social sharing icons" width="800" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Episode V: The Open Graphs Strike Back
&lt;/h2&gt;

&lt;p&gt;Now to make sure everything looks great when links from your blog are shared, we’re going to work on updating the open graph tags. Open graph tags hold metadata that is used by search engines and social media platforms. This section focuses on updating your open graph tags and including Twitter and Facebook. &lt;/p&gt;

&lt;p&gt;The file we are working with is located in the components directory and named &lt;code&gt;meta.js&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Make sure to customize yours to fit your project. For example, you’ll have to create a project in Facebook to obtain your &lt;code&gt;fb:app_id&lt;/code&gt;. With Twitter, I created a “summary_large_image” Twitter card, alternatively you can just put “summary” if you prefer the smaller content display. &lt;/p&gt;

&lt;p&gt;One problem I ran into was that images were not properly displaying. This was because the image meta properties require a full image URL, so keep that in mind while updating. &lt;/p&gt;

&lt;p&gt;Here is an example of what my meta tags look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// /components/meta.js&lt;/span&gt;

     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;twitter:card&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;summary_large_image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;twitter:site&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@LucasStahl11&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;twitter:creator&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@LucasStahl11&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;twitter:title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Stahlwalker Cookbook&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;twitter:description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A blog dedicated to cooking up recipes for all those far far and away.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt; &lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;twitter:image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://cookblog.vercel.app/images/starwarssocialfinal.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;

     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt; &lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;og:title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Stahlwalker Cookbook&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt; &lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;og:type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;website&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt; &lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;og:url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://cookblog.vercel.app/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt; &lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;og:image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://cookblog.vercel.app/images/starwarssocialfinal.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt; &lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fb:app_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;add Facebook id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt; &lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;og:description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A blog dedicated to cooking up recipes for all those far far and away.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To validate these are working correctly you can check &lt;a href="https://cards-dev.twitter.com/validator" rel="noopener noreferrer"&gt;Twitter’s validator&lt;/a&gt; and &lt;a href="https://developers.facebook.com/tools/debug/" rel="noopener noreferrer"&gt;Facebook’s debugger&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Regarding your Favicon images, those can be located in the public directory. Here is a link to a &lt;a href="https://realfavicongenerator.net/" rel="noopener noreferrer"&gt;Favicon generator&lt;/a&gt; to create the correct image sizes you need to replace the current Next.js image.&lt;/p&gt;

&lt;h2&gt;
  
  
  Episode VI: Return of the Categories
&lt;/h2&gt;

&lt;p&gt;Having your blog posts is one thing but wouldn’t it be cool if you could sort them by a category tag? To do this, we need to add another field to the content model, which we can do in the “Content Model” section in the Contentful web app. In the “Post” content type, I added a new text field and selected the “short” and “list” options. This new field means you can start tagging your blog posts that later can be searched. In my cookbook, I categorized the recipes by cuisine type. &lt;/p&gt;

&lt;p&gt;Once you have your content model updated, you need to update your GraphQL query in your code. In the &lt;code&gt;api.js&lt;/code&gt; file located in your “lib” directory, add the name of the new field to the query variable. I called my field foodCategory. If you are unsure how your query should look, this is where you can use the GraphQL playground app to make sure your queries are correct.&lt;/p&gt;

&lt;p&gt;To install the GraphQL playground app. You’ll find this by navigating to “Apps” and clicking on “Manage Apps” in the top menu of your Contentful app. Simply click install and then this feature will be available to querying data within your project. Note, you’ll need to configure this app, so have your Contentful Preview API token available.   &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2tj91g8udbo3iq2gbgl3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2tj91g8udbo3iq2gbgl3.png" alt="GraphQL playground" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I wanted the category to be listed under the header on the blog post pages. I added foodCategory as a prop for my PostHeader component so that I could access the category within the PostHeader component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="c1"&gt;// /pages/posts/[slug.js]      &lt;/span&gt;
               &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PostHeader&lt;/span&gt;
               &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
               &lt;span class="nx"&gt;coverImage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coverImage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
               &lt;span class="nx"&gt;foodCategory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;foodCategory&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
               &lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
               &lt;span class="nx"&gt;author&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;author&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
               &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you would like users to be allowed to search by category, you could add an API search tool such as &lt;a href="https://www.algolia.com/products/search-and-discovery/hosted-search-api/" rel="noopener noreferrer"&gt;Algolia &lt;/a&gt;or &lt;a href="https://www.elastic.co/elastic-stack/" rel="noopener noreferrer"&gt;Elasticsearch&lt;/a&gt;. You may also want to filter all blog posts by category and build that out. This is the first step in the process. &lt;/p&gt;

&lt;h2&gt;
  
  
  Episode VII: The CSS Awakens
&lt;/h2&gt;

&lt;p&gt;I have zero experience with Tailwind and it comes pre-installed with this project. If you are like me and want to get back to the basics you can style with regular CSS. The styles folder is located in the public directory, you’ll just have to apply a class (and remember since we are using Next.js you will need to use “className”) to the containers you are looking to style. &lt;/p&gt;

&lt;p&gt;Since this is a Star Wars-themed cookbook, I used &lt;a href="https://fonts.google.com/specimen/Audiowide?query=Audio" rel="noopener noreferrer"&gt;Google Fonts&lt;/a&gt; to get a font that had the look and feel similar to what has been used in the films. I also used &lt;a href="https://fontawesome.com/icons/twitter?s=brands" rel="noopener noreferrer"&gt;Font Awesome&lt;/a&gt; for social icons. I added both libraries to my &lt;code&gt;app.js&lt;/code&gt; Head tag. &lt;/p&gt;

&lt;h2&gt;
  
  
  Episode VIII: The Last Load More Button
&lt;/h2&gt;

&lt;p&gt;At this point, my homepage was displaying all of my blog posts. I wanted to have more control over how many posts were listed. You have the option to add pagination, and if that interests you, I suggest taking a look at the following blog on &lt;a href="https://www.contentful.com/blog/2021/04/23/paginating-contentful-blogposts-with-nextjs-graphql-api/" rel="noopener noreferrer"&gt;Next.js pagination with Contentful&lt;/a&gt;. If you want something simple and sweet you can add a load more button. In this instance I went with the latter.&lt;/p&gt;

&lt;p&gt;I modified the existing &lt;code&gt;more-stories&lt;/code&gt; component which allowed me to control how many posts to display and how many should appear when a user clicks to load more. I also used a prop to determine if the component should display a load more button since it is used in multiple places. Here is an example of what that looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// /components/more-stories.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;PostPreview&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../components/post-preview&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MoreStories&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;showMore&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nx"&gt;postNum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setPostNum&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Default number of posts displayed&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleClick&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nf"&gt;setPostNum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prevPostNum&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;prevPostNum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
 &lt;span class="p"&gt;}&lt;/span&gt;

 &lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;postNum&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;showMore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;showMore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

 &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;section&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mb-8 text-6xl md:text-7xl font-bold tracking-tighter leading-tight&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="nx"&gt;More&lt;/span&gt; &lt;span class="nx"&gt;Recipes&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;grid grid-cols-0 md:grid-cols-2 md:col-gap-16 lg:col-gap-32 row-gap-20 md:row-gap-32 mb-32&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;postNum&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PostPreview&lt;/span&gt;
           &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
           &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
           &lt;span class="nx"&gt;coverImage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coverImage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
           &lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
           &lt;span class="nx"&gt;author&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;author&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
           &lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
           &lt;span class="nx"&gt;excerpt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;excerpt&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
         &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;       &lt;span class="p"&gt;))}&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;showMore&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;load-more&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Load&lt;/span&gt; &lt;span class="nx"&gt;More&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;       &lt;span class="p"&gt;)}&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/section&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you have the code updated in your component, make sure to add the new prop, &lt;code&gt;showMore&lt;/code&gt;, to the component in the &lt;code&gt;index.js&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// /pages/index.js&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;morePosts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MoreStories&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;morePosts&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;showMore&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And there you have it, your load more should be in effect!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpqo5wn9430sp10cq1cvv.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpqo5wn9430sp10cq1cvv.gif" alt="Load more gif" width="200" height="125"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Episode IX: Rise of the Stahlwalker Cookbook
&lt;/h2&gt;

&lt;p&gt;And that is how I created my first Next.js project. We took a starter and built it out by adding apps, a commenting section, the ability to share, styled it with CSS rather than Tailwind and added a load more options for viewers to dive further into your blog posts. To see all of the final code, you can access it &lt;a href="https://github.com/Stahlwalker/cookblog" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.contentful.com/nextjs-starter-guide/" rel="noopener noreferrer"&gt;Next.js and Contentful starter guide&lt;/a&gt; really inspired me, so I’d love to see what you’ve built with it as well! I’m planning on continuing to add features to my new blog but if you’d like to check it out, here is the live version of the &lt;a href="https://cookblog.vercel.app/" rel="noopener noreferrer"&gt;Stahlwalker Cookbook&lt;/a&gt; project. &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>nextjs</category>
      <category>cms</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Forma 36 v4 released, GraphQL cheat sheet and Jamstack events</title>
      <dc:creator>Brittany Walker</dc:creator>
      <pubDate>Wed, 09 Feb 2022 19:47:04 +0000</pubDate>
      <link>https://forem.com/contentful/forma-36-v4-released-graphql-cheat-sheet-and-jamstack-events-1b8l</link>
      <guid>https://forem.com/contentful/forma-36-v4-released-graphql-cheat-sheet-and-jamstack-events-1b8l</guid>
      <description>&lt;p&gt;Happy February!&lt;/p&gt;

&lt;p&gt;I hope your start to 2022 was great. We're very excited to share what we've been working on! Our biggest news is that we released v4 of our design system, Forma 36. Additionally, the developer relations team participated in many fun events and we've published some new content to help you build faster and better with Contentful.&lt;/p&gt;

&lt;p&gt;Let's take a look!&lt;/p&gt;

&lt;h2&gt;
  
  
  Contentful corner
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.contentful.com/blog/2022/01/11/forma36-v4/" rel="noopener noreferrer"&gt;Forma 36 v4 has been released&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;We are very happy to announce the full release of Forma 36 v4, our open-source design system created to help developers easily customize Contentful's UI. &lt;/p&gt;

&lt;p&gt;This release includes highly anticipated updates that improve the user and developer experience. Our React components are now WCAG level AAA compliant, you can now pull in just the components that you need, which decreases bundle size, and all styling is encapsulated within components, meaning additional CSS imports are not required. These updates make it easier and faster for developers like you to use Forma 36 with your Contentful projects. &lt;/p&gt;

&lt;p&gt;Want a behind-the-scenes look at the development of this release? &lt;a href="https://www.contentful.com/blog/2022/01/18/developing-forma36-v4/" rel="noopener noreferrer"&gt;Head over to our blog&lt;/a&gt;. For instructions on how to use the latest version of Forma 36, &lt;a href="https://github.com/contentful/forma-36/blob/master/MIGRATION.md" rel="noopener noreferrer"&gt;explore our in-depth guide&lt;/a&gt; or &lt;a href="https://f36.contentful.com/v3-faq" rel="noopener noreferrer"&gt;migration FAQs&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.contentful.com/resources/graphql-api-cheat-sheet/" rel="noopener noreferrer"&gt;GraphQL API cheat sheet&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;As a developer, there's a lot to remember and Contentful has your back. I've put together a &lt;a href="https://www.contentful.com/resources/graphql-api-cheat-sheet/" rel="noopener noreferrer"&gt;cheat sheet &lt;/a&gt;of commonly used GraphQL features, queries and tips for you to reference as you're building.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.contentful.com/gatsby-starter-guide/" rel="noopener noreferrer"&gt;Get started with Contentful and Gatsby&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Did you know it takes less than 10 minutes to spin up a blog using Gatsby and Contentful? If you're curious about how to do it, &lt;a href="https://www.contentful.com/gatsby-starter-guide/" rel="noopener noreferrer"&gt;check out our Gatsby and Contentful starter walkthrough&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.contentful.com/careers/#openings" rel="noopener noreferrer"&gt;Work with us!&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Our Developer Relations team is growing! We're looking for a U.S.-based &lt;a href="https://www.contentful.com/careers/job/3539137/" rel="noopener noreferrer"&gt;director of developer experience&lt;/a&gt; and an EMEA-based &lt;a href="https://www.contentful.com/careers/job/3698465/" rel="noopener noreferrer"&gt;developer advocate&lt;/a&gt;. You could be just the fit for these roles if you have experience with front-end technologies and developer communities (bonus points if you enjoy building fun projects). Please don't hesitate to apply or make referrals --- we'd love to have you on our team.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.ctfassets.net%2Ffo9twyrwpveg%2F4oj3v7DlUGPycIq1ln4J6F%2Fcedc9745cf98122b7f19c8e83b3b97f2%2FContentful_community_.png%3Ffm%3Davif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.ctfassets.net%2Ffo9twyrwpveg%2F4oj3v7DlUGPycIq1ln4J6F%2Fcedc9745cf98122b7f19c8e83b3b97f2%2FContentful_community_.png%3Ffm%3Davif" alt="Contentful community"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Events with partners
&lt;/h2&gt;

&lt;p&gt;We've partnered with a few friends to bring you some fun events the past couple of months. &lt;/p&gt;

&lt;p&gt;In December Stefan partnered with Gatsby to &lt;a href="https://www.gatsbyjs.com/resources/webinars/gatsby-contentful-optimization/" rel="noopener noreferrer"&gt;show you how you can quickly create a Jamstack project&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Then, in January, he and Netlify's Jason Lengstorf donned their bunny and hippo house slippers to host a webinar on &lt;a href="https://www.contentful.com/resources/render-content-on-the-fly-with-jamstack/" rel="noopener noreferrer"&gt;how to serve and cache content&lt;/a&gt; on demand for faster build times and improved site performance.&lt;/p&gt;

&lt;p&gt;Get informed on future events --- visit our &lt;a href="https://www.contentful.com/developers/#news" rel="noopener noreferrer"&gt;developer events page&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links we like
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://messwithdns.net/" rel="noopener noreferrer"&gt;Mess with DNS&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Changing DNS settings can be a nerve-wracking experience. Lucky for us, &lt;a href="https://jvns.ca/" rel="noopener noreferrer"&gt;Julia Evans&lt;/a&gt; built a fun tool where you can experiment with DNS without the consequences.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://lynnandtonic.com/" rel="noopener noreferrer"&gt;Lynn Fisher's annual portfolio refresh&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Since 2007, designer &lt;a href="https://lynnandtonic.com/" rel="noopener noreferrer"&gt;Lynn Fisher&lt;/a&gt; has released an annual portfolio refresh. This year's version is a delight, pushing the limits of what can be done with SVGs and CSS web animation. &lt;a href="https://lynnandtonic.com/thoughts/entries/case-study-2021-refresh/" rel="noopener noreferrer"&gt;See what she achieved&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.learnwithjason.dev/better-screenreader-experiences-with-css" rel="noopener noreferrer"&gt;Better screen reader experiences with CSS&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;In one of my favorite livestreams, &lt;a href="https://benmyers.dev/" rel="noopener noreferrer"&gt;Ben Myers&lt;/a&gt; demonstrates how to navigate with screen readers and how your CSS can impact them in ways you might not realize or have even considered. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.ctfassets.net%2Ffo9twyrwpveg%2F4LD3W4NxLwjyUTqaNX1Svb%2Fd089ff2e45201c2cc3b48d6832a8a6b6%2FWriting_content_-_paper.png%3Ffm%3Davif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.ctfassets.net%2Ffo9twyrwpveg%2F4LD3W4NxLwjyUTqaNX1Svb%2Fd089ff2e45201c2cc3b48d6832a8a6b6%2FWriting_content_-_paper.png%3Ffm%3Davif" alt="changelog"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Changelog
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Easily disable and enable webhooks
&lt;/h3&gt;

&lt;p&gt;You can now disable and enable webhooks in one click, giving you more flexibility to manage integrations with Contentful.&lt;/p&gt;

&lt;h3&gt;
  
  
  Retrieve asset fields in multiple locales
&lt;/h3&gt;

&lt;p&gt;We modified the GraphQL API so users can request fields on an asset in multiple locales.&lt;/p&gt;

&lt;h3&gt;
  
  
  Environments governance
&lt;/h3&gt;

&lt;p&gt;With environment governance, admins can ensure that users only see the environments they need, letting them be much more confident in making changes, and avoid mistakes that could affect your end users.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.contentful.com/developers/changelog/#new-extensibility-locations-for-apps-in-compose-+-launch" rel="noopener noreferrer"&gt;Read the changelog here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Have a great month!
&lt;/h2&gt;

&lt;p&gt;That's it for February! Visit &lt;a href="https://www.contentful.com/developers/" rel="noopener noreferrer"&gt;our developer portal&lt;/a&gt; for even more news. The portal also houses developer blog posts, videos and tutorials. You can &lt;a href="https://www.contentful.com/resources/dev-newsletter/" rel="noopener noreferrer"&gt;subscribe to our newsletter here&lt;/a&gt;! As always, feel free to contact us on &lt;a href="https://www.contentful.com/slack/" rel="noopener noreferrer"&gt;Slack&lt;/a&gt; or &lt;a href="https://twitter.com/contentful/" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; to let us know how we can better support your awesome builds.&lt;/p&gt;

</description>
      <category>contentful</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
