<?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>DEV Community: Ian MacIntosh</title>
    <description>The latest articles on DEV Community by Ian MacIntosh (@ianjmacintosh).</description>
    <link>https://dev.to/ianjmacintosh</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%2Fuser%2Fprofile_image%2F407917%2Ffd8fe7d1-4614-416b-b417-f385402ba6fe.jpeg</url>
      <title>DEV Community: Ian MacIntosh</title>
      <link>https://dev.to/ianjmacintosh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ianjmacintosh"/>
    <language>en</language>
    <item>
      <title>Free Ideas for Free Learning</title>
      <dc:creator>Ian MacIntosh</dc:creator>
      <pubDate>Sat, 05 Dec 2020 00:32:33 +0000</pubDate>
      <link>https://dev.to/ianjmacintosh/free-ideas-for-free-learning-51m4</link>
      <guid>https://dev.to/ianjmacintosh/free-ideas-for-free-learning-51m4</guid>
      <description>&lt;p&gt;There's lots of good reasons to get into professional development, but the main one is: to make yourself more valuable. This means more useful/promotable to the company you’re with, or more hireable if it's time for a change. Learning can also get you more excited about a job where you’re otherwise not growing the way you'd like, showing you new ways to work (maybe new processes or tools) to help you, your team, and ultimately the company.&lt;/p&gt;

&lt;p&gt;If you've got the resources to do professional development in your off-hours, that could be an option, but don't be afraid to coordinate with your manager to find out how they envision your growth &lt;em&gt;at work&lt;/em&gt;. I wrote this article imagining a program where engineers spend one hour learning with a group and one hour learning by themselves every week, but find out what works best for you and your team. Can you start this week?&lt;/p&gt;

&lt;p&gt;Sometimes the hardest part is coming up with ideas, so I figured I'd share a few I've seen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contribute to an Open Source Project
&lt;/h2&gt;

&lt;p&gt;Giving back to some of the projects the world's web developers take for granted is an excellent way to learn new ways of doing things. If you're looking for projects to contribute to, start by looking at what open source projects your team already uses.&lt;/p&gt;

&lt;p&gt;Large open source projects often have processes that can inspire you to change how you and your organization work together. You'll also get an opportunity to get experience working with whatever interests you, learning from an existing codebase. Look over some pull requests or previous commits to get a feel for how things work, then take a crack at fixing an issue. Lots of projects have a &lt;code&gt;CONTRIBUTING.md&lt;/code&gt; file to help you get started.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compete in Teams
&lt;/h2&gt;

&lt;p&gt;If you have coworkers who are interested in having a fun hour-long micro-challenge competition, come up with an idea for a really simple application like a currency converter or an online survey tool and work in separate teams building it. Compare and contrast what you made afterwards, make it a contest. If other people like, let them pick a winner and participate in next week's challenge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep a Weekly List of Questions
&lt;/h2&gt;

&lt;p&gt;As you go about your regular work, keep a record of topics you felt unsure about. At the end of the week, share these notes with a larger group to get their input. Alternate weeks, recording questions one week and finding answers the next week. Use your time with the larger group to share what you learned.&lt;/p&gt;

&lt;h2&gt;
  
  
  Work on a Group Project
&lt;/h2&gt;

&lt;p&gt;Instead of just working on a short challenge, come up with an idea for a more involved project that could span weeks or months and collaborate with your team to make it a real application. Make it a first-rate application with a project homepage, tests, documentation, etc. Let everyone contribute however they like, inside or outside their specialization, so long as it keeps moving the app forward.&lt;/p&gt;

&lt;h2&gt;
  
  
  Take a Course Together
&lt;/h2&gt;

&lt;p&gt;Find a course that you and others could benefit from. Spend time each week learning the material and doing the exercises, then talk about the experience as a group. If the course costs money, a deliberate process with check-ins and milestones can help persuade your company to sponsor it. Personally I've found it's a lot more fun spending the group time discussing the previous week's material than trying to watch videos together.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do a 30-minute Speed Challenge
&lt;/h2&gt;

&lt;p&gt;Sit down in a group with peers to individually take on a 30-minute challenge (maybe pair up if you've got a mix of seniors and juniors), then go around in a circle sharing what each person built. For fun, you can take a vote of whose is the best, or everyone can make suggestions for a new challenge next week. The important part is to make it fun and get everyone involved without much overhead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Show and Tell
&lt;/h2&gt;

&lt;p&gt;You might already be doing something like this at sprint reviews, but show something cool you made last week to your teammates. Unlike a regular sprint review, this is a better opportunity to do a deep dive on the technical details of how things work. Let everyone share something they made.&lt;/p&gt;

&lt;p&gt;The idea is to walk everyone through something cool and teach them how they could do it themselves (or if the person sharing wants, why &lt;em&gt;not&lt;/em&gt; to do it how they did it). Don't let it turn into a live code review (that's what regular code reviews are for) or something everyone dreads each week. Keep it light!&lt;/p&gt;

&lt;h2&gt;
  
  
  Command of the Week, Usage of the Day
&lt;/h2&gt;

&lt;p&gt;Each week, pick a different command and encourage everyone to use it daily and share their application of it in the group chat. Commands like &lt;code&gt;sed&lt;/code&gt;, &lt;code&gt;awk&lt;/code&gt;, and &lt;code&gt;grep&lt;/code&gt; are great for this since they're powerful but often avoided because they take some practice. This doesn't need to just be bash commands, you could pick a feature in your language of choice. For example, you could focus on how a problem you're solving could use ES6's generators and explain if it'd be appropriate.&lt;/p&gt;

</description>
      <category>career</category>
      <category>webdev</category>
      <category>opensource</category>
      <category>bash</category>
    </item>
    <item>
      <title>Static Site, Meet CMS: Using Contentful with 11ty</title>
      <dc:creator>Ian MacIntosh</dc:creator>
      <pubDate>Mon, 30 Nov 2020 16:46:47 +0000</pubDate>
      <link>https://dev.to/ianjmacintosh/getting-content-from-contentful-into-eleventy-4dn9</link>
      <guid>https://dev.to/ianjmacintosh/getting-content-from-contentful-into-eleventy-4dn9</guid>
      <description>&lt;p&gt;I wanted my personal site to pull content from a CMS instead of having to manage a bunch of content files in my project's filesystem. I found a really excellent article (&lt;em&gt;&lt;a href="https://www.contentful.com/blog/2020/07/28/integrating-contentful-with-eleventy-create-static-sites/"&gt;Integrating Contentful with Eleventy to create static sites&lt;/a&gt;&lt;/em&gt;) on Contentful's website explaining how to do this, but wanted to share my own experience and an abbreviated version of the steps.&lt;/p&gt;

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

&lt;p&gt;Since this article is about getting content from Contentful into Eleventy, I presume you have an Eleventy project running and a Contentful space with content in it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Steps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Add Contentful Plugin&lt;/li&gt;
&lt;li&gt;Store Keys Safely &lt;/li&gt;
&lt;li&gt;Get Data from Contentful&lt;/li&gt;
&lt;li&gt;Make an Index&lt;/li&gt;
&lt;li&gt;Make Pages&lt;/li&gt;
&lt;li&gt;Work with Dates (Optional)&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Step 1: Add Contentful plugin 🔌
&lt;/h3&gt;

&lt;p&gt;Install the &lt;a href="https://www.npmjs.com/package/contentful"&gt;Contentful JavaScript Delivery SDK&lt;/a&gt; package:&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;--save-dev&lt;/span&gt; contentful
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Step 2: Store keys safely 🔑
&lt;/h3&gt;

&lt;p&gt;Find your &lt;em&gt;Space ID&lt;/em&gt; and &lt;em&gt;API access tokens&lt;/em&gt; in the &lt;a href="https://app.contentful.com/"&gt;Contentful admin panel&lt;/a&gt;, under &lt;em&gt;Settings&lt;/em&gt; &amp;gt; &lt;em&gt;API keys&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;You need to store these secret values somewhere the Contentful JavaScript Delivery SDK can find them to authenticate itself with Contentful. I like to store them as environment variables in a local &lt;code&gt;.env&lt;/code&gt; file and use &lt;em&gt;&lt;a href="https://www.npmjs.com/package/dotenv"&gt;dotenv&lt;/a&gt;&lt;/em&gt; to manage them. You don't need to do it this way, it's just the simplest way I know.&lt;/p&gt;

&lt;p&gt;Install the &lt;a href="https://www.npmjs.com/package/dotenv"&gt;dotenv&lt;/a&gt; package:&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;--save-dev&lt;/span&gt; dotenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're using git for source control, update your &lt;code&gt;.gitignore&lt;/code&gt; file to ignore the &lt;code&gt;.env&lt;/code&gt; file you're about to create. This is important so you won't store sensitive info in your repo.&lt;/p&gt;

&lt;h5&gt;
  
  
  Example &lt;code&gt;.gitignore&lt;/code&gt;:
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node_modules/
_site/
.env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you're ready to make your &lt;code&gt;.env&lt;/code&gt; file. Here's a starter template, replace the placeholder values with your space ID and access token. Again, these can be found in the &lt;a href="https://app.contentful.com/"&gt;Contentful admin panel&lt;/a&gt;, under &lt;em&gt;Settings&lt;/em&gt; &amp;gt; &lt;em&gt;API keys&lt;/em&gt;.&lt;/p&gt;

&lt;h5&gt;
  
  
  Example &lt;code&gt;.env&lt;/code&gt;:
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; &lt;span class="c"&gt;# Content Delivery API host:&lt;/span&gt;
 &lt;span class="nv"&gt;CTFL_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"cdn.contentful.com"&lt;/span&gt;

 &lt;span class="c"&gt;# Contentful Space ID:&lt;/span&gt;
 &lt;span class="nv"&gt;CTFL_SPACE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"space_id_placeholder"&lt;/span&gt;

 &lt;span class="c"&gt;# Content Delivery API access token:&lt;/span&gt;
 &lt;span class="nv"&gt;CTFL_ACCESSTOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"content_delivery_api_access_token_placeholder"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This &lt;code&gt;.env&lt;/code&gt; setup is what I use on my local dev environment, but if you're hosting your site with a third party, you may prefer to use their control panel for managing environment variables.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 3: Get Data from Contentful 🚅
&lt;/h3&gt;

&lt;p&gt;Add a new data source by adding a new file to your &lt;code&gt;/_data&lt;/code&gt; directory. I named mine &lt;code&gt;contentful.js&lt;/code&gt; because that's what &lt;a href="https://www.contentful.com/blog/2020/07/28/integrating-contentful-with-eleventy-create-static-sites/"&gt;the tutorial&lt;/a&gt; did.&lt;/p&gt;

&lt;h5&gt;
  
  
  Example &lt;code&gt;/_data/contentful.js&lt;/code&gt;:
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;"&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;contentful&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&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&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;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;createClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CTFL_HOST&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;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CTFL_SPACE&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;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CTFL_ACCESSTOKEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&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;client&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getEntries&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="s2"&gt;article&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="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&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;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&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;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&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="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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&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;return&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="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="s2"&gt;`Got &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;length&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; items from Contentful`&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;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="k"&gt;catch&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;error&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;See the &lt;code&gt;getEntries()&lt;/code&gt; call? The &lt;code&gt;content_type&lt;/code&gt; property tells Contentful what data you want. Replace &lt;code&gt;article&lt;/code&gt; with &lt;code&gt;post&lt;/code&gt; or whatever your &lt;em&gt;content type ID&lt;/em&gt; is. If you're not sure, check in the &lt;a href="https://app.contentful.com/"&gt;Contentful admin panel&lt;/a&gt;, under &lt;em&gt;Content model&lt;/em&gt; and select your desired content type. When I wrote this, it was on the right side of the page.&lt;/p&gt;

&lt;p&gt;If you haven't already done so, start your Eleventy server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;eleventy &lt;span class="nt"&gt;--serve&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the data call works, your console window running your server should show some champagne bottles and "Got 4 items from Contentful" in your console (or however many &lt;strong&gt;published&lt;/strong&gt; items are available). If you have no published items, you'll get 0 champagne bottles and might want to switch to the Content Preview API for testing purposes. See below for more on that.&lt;/p&gt;

&lt;p&gt;Once you confirm things work, you can remove the &lt;code&gt;console.log&lt;/code&gt; statements and begin the next step, working with this data to build an index.&lt;/p&gt;

&lt;h4&gt;
  
  
  Planning on Working with Unpublished Content? 👀
&lt;/h4&gt;

&lt;p&gt;You can get unpublished content from Contentful by calling the &lt;a href="https://www.contentful.com/developers/docs/references/content-preview-api"&gt;Content Preview API&lt;/a&gt; instead of the &lt;a href="https://www.contentful.com/developers/docs/references/content-delivery-api/"&gt;Content Delivery API&lt;/a&gt; (which only exposes published content).&lt;/p&gt;

&lt;p&gt;If you'd like to use the Content Preview API, switch your &lt;code&gt;CTFL_HOST&lt;/code&gt; value to &lt;code&gt;preview.contentful.com&lt;/code&gt; and your &lt;code&gt;CTFL_ACCESSTOKEN&lt;/code&gt; to your Content Preview API access token. You can find this with the other values, in the &lt;a href="https://app.contentful.com/"&gt;Contentful admin panel&lt;/a&gt;, under &lt;em&gt;Settings&lt;/em&gt; &amp;gt; &lt;em&gt;API keys&lt;/em&gt;. I add duplicate lines for in my &lt;code&gt;.env&lt;/code&gt; file, and when I want to switch between Content Preview API and Content Delivery API, I comment/uncomment the relevant lines.&lt;/p&gt;

&lt;h5&gt;
  
  
  Example &lt;code&gt;.env&lt;/code&gt; for working with unpublished content:
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Contentful "master" Space ID:&lt;/span&gt;
&lt;span class="nv"&gt;CTFL_SPACE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"abc123def456"&lt;/span&gt;

&lt;span class="c"&gt;# Content Delivery API host:&lt;/span&gt;
&lt;span class="c"&gt;# CTFL_HOST="cdn.contentful.com"&lt;/span&gt;

&lt;span class="c"&gt;# Content Delivery API access token:&lt;/span&gt;
&lt;span class="c"&gt;# CTFL_ACCESSTOKEN="abcdefghijklmnopqrstuvwxyz1234567890"&lt;/span&gt;

&lt;span class="c"&gt;# Content Preview API host:&lt;/span&gt;
&lt;span class="nv"&gt;CTFL_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"preview.contentful.com"&lt;/span&gt;

&lt;span class="c"&gt;# Content Preview API access token:&lt;/span&gt;
&lt;span class="nv"&gt;CTFL_ACCESSTOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"0987654321abcdefghijklmnopqrstuvwxyz"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Step 4: Make an Index 📖
&lt;/h3&gt;

&lt;p&gt;You can build a list of pages from your data using Eleventy's &lt;a href="https://www.11ty.dev/docs/pagination/"&gt;&lt;em&gt;pagination&lt;/em&gt;&lt;/a&gt; feature. I use &lt;a href="https://mozilla.github.io/nunjucks/"&gt;Nunjucks&lt;/a&gt; for a templating language in this example to build logic into my templates.&lt;/p&gt;

&lt;p&gt;My example will only work with 2 or more items in the data; the &lt;code&gt;for&lt;/code&gt; statement in Nunjucks won't work with only one item. If you only have one item, you may want to jump to the next step.&lt;/p&gt;

&lt;h5&gt;
  
  
  Example &lt;code&gt;/all-pages.njk&lt;/code&gt;:
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight twig"&gt;&lt;code&gt;---
pagination:
  data: contentful
  size: 10
---
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&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;ul&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nv"&gt;article&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;pagination.items&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/&lt;/span&gt;&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;article.fields.title&lt;/span&gt; &lt;span class="o"&gt;| &lt;/span&gt;&lt;span class="nf"&gt;slug&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;&lt;span class="s"&gt;/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;article.fields.title&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;endfor&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;pagination.href.previous&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;pagination.href.previous&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Previous&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;endif&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;pagination.href.next&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;pagination.href.next&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Next&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;endif&lt;/span&gt; &lt;span class="cp"&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;h4&gt;
  
  
  Explanation
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;pagination&lt;/code&gt; object tells Eleventy how to work with the data set:

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;data&lt;/code&gt; property is a reference to my data source (in my case, &lt;code&gt;contentful&lt;/code&gt; for &lt;code&gt;/_data/contentful.js&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;size&lt;/code&gt; property is how many items I want on each page. Eleventy will make as many pages as necessary to show all the data. For example, if I set &lt;code&gt;size&lt;/code&gt; to &lt;code&gt;10&lt;/code&gt; and have 47 items, Eleventy will make five pages; 10 items on each of the first four pages, and 7 items on the last page. Their URLs will be generated automatically by Eleventy (&lt;code&gt;/all-pages/index.html&lt;/code&gt;, &lt;code&gt;/all-pages/1/index.html&lt;/code&gt;, &lt;code&gt;/all-pages/2/index.html&lt;/code&gt;, etc.)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Eleventy stores the results in &lt;code&gt;pagination.items&lt;/code&gt; and I can iterate over them with Nunjucks's &lt;code&gt;for&lt;/code&gt;. I store each iteration in a variable named &lt;code&gt;article&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;I link to each item using each article's "title" field and Eleventy's built-in &lt;a href="https://www.11ty.dev/docs/filters/slug/"&gt;&lt;code&gt;slug&lt;/code&gt; filter&lt;/a&gt;. This filter lets me link to &lt;code&gt;/getting-content-from-contentful-into-eleventy/&lt;/code&gt; instead of &lt;code&gt;/Getting Content from Contentful into Eleventy/&lt;/code&gt;)

&lt;ul&gt;
&lt;li&gt;✋🏻 &lt;strong&gt;These pages don't exist yet! If I click a link, I get a 404, and that's fine for now.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;pagination.href&lt;/code&gt; object will have a &lt;code&gt;previous&lt;/code&gt; or &lt;code&gt;next&lt;/code&gt; property if there's a previous or next page, and its value will be its URL.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you navigate to &lt;code&gt;/all-pages/&lt;/code&gt; (or whatever you named yours) and confirm your list of all pages shows broken links for your content, you're ready to make the pages themselves.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 5: Make Pages 📄
&lt;/h3&gt;

&lt;p&gt;I use pagination again to build the pages themselves, specifying a &lt;code&gt;size&lt;/code&gt; of &lt;code&gt;1&lt;/code&gt; to put one item on each page.&lt;/p&gt;

&lt;h5&gt;
  
  
  Example &lt;code&gt;/page.njk&lt;/code&gt;:
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight twig"&gt;&lt;code&gt;---
pagination:
  data: contentful
  size: 1
  alias: article

templateEngineOverride: njk,md
permalink: "/&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;article.fields.title&lt;/span&gt; &lt;span class="o"&gt;| &lt;/span&gt;&lt;span class="nf"&gt;slug&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;/"
eleventyComputed:
  title: "&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;article.fields.title&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;"
  content: "&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;article.fields.markdownBody&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;"
---
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&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;h1&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;title&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;content&lt;/span&gt; &lt;span class="cp"&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;h4&gt;
  
  
  Explanation
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;pagination&lt;/code&gt; object has made a return, but instead of iterating over 10 items like in the last step, I set &lt;code&gt;size&lt;/code&gt; to &lt;code&gt;1&lt;/code&gt; item and use that item by itself for this page.

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;alias&lt;/code&gt; property defines how I can refer to the items coming from Contentful. Without an alias, I could reference &lt;code&gt;pagination.items[0].fields.title&lt;/code&gt; in my template, but by using an alias, I can reference &lt;code&gt;article.fields.title&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;In my example, I call two fields I've defined in my content model: &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;markdownBody&lt;/code&gt;. Review your own content model to locate the keys for content you'd like to display.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;eleventyComputed&lt;/code&gt; object allows me to reference values even more easily in my template. Instead of calling &lt;code&gt;article.fields.title&lt;/code&gt;, I can call &lt;code&gt;title&lt;/code&gt; to get the same data.&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://www.11ty.dev/docs/languages/#overriding-the-template-language"&gt;&lt;code&gt;templateEngineOverride&lt;/code&gt; property&lt;/a&gt; lets me force specific templating engine parsing rules. I use Nunjucks ("njk") for templating with Markdown ("md") content in my data. Eleventy automatically parses &lt;code&gt;.njk&lt;/code&gt; files using Nunjucks, but since I &lt;em&gt;also&lt;/em&gt; want Markdown (to compile my Markdown into HTML), I manually specify both: &lt;code&gt;njk,md&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;permalink&lt;/code&gt; property tells Eleventy where to save each page corresponding with each item. You can use template strings to give each page a unique name. If you omit the &lt;code&gt;permalink&lt;/code&gt; property, Eleventy's default behavior is to add a numbered page for each item. (e.g., &lt;code&gt;/page/1/index.html&lt;/code&gt;)

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;When my permalink value didn't end with a trailing slash, I got weird errors trying to load each page. My browser tried to save the page instead of viewing it in the browser, and then I got &lt;code&gt;ENOTDIR: not a directory&lt;/code&gt; errors until I manually deleted &lt;code&gt;_site/&lt;/code&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;If you already have a layout template you'd like to use, you can call it in your front matter: &lt;code&gt;layout: _template.njk&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To test, go to your console and confirm a new page is generated for each item retrieved from Contentful. (e.g., &lt;code&gt;Writing _site/getting-content-from-contentful-into-eleventy/index.html from ./page.njk.&lt;/code&gt;) Navigate to that URL (&lt;code&gt;/getting-content-from-contentful-into-eleventy/index.html&lt;/code&gt;) in your web browser.&lt;/p&gt;

&lt;p&gt;That's it, you're done! 🏁&lt;/p&gt;

&lt;p&gt;Due to the static nature of Eleventy, you'll need to generate your site again to see changes after modifying your content in Contentful.&lt;/p&gt;




&lt;h3&gt;
  
  
  Optional: Use Moment to Work with Dates 🗓
&lt;/h3&gt;

&lt;p&gt;To show &lt;em&gt;Published on Dec 25, 2018&lt;/em&gt; on my pages, I use a &lt;a href="https://www.npmjs.com/package/nunjucks-date-filter"&gt;Moment plugin for Nunjucks&lt;/a&gt;. Since Contentful stores dates in "2020-09-03T03:53:54.665Z" format, I wanted to show that same information in a way that's a little easier on the eyes. I've had nothing but good experiences with Moment even though it's probably overkill for this use case.&lt;/p&gt;

&lt;p&gt;Install the &lt;a href="https://www.npmjs.com/package/nunjucks-date-filter"&gt;Nunjucks date filter&lt;/a&gt; package:&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;--save-dev&lt;/span&gt; nunjucks-date-filter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your &lt;code&gt;.eleventy.js&lt;/code&gt; configuration file, add this new filter:&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;dateFilter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nunjucks-date-filter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eleventyConfig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;eleventyConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addNunjucksFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;date&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dateFilter&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;Use it in your templates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight twig"&gt;&lt;code&gt;Published &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;published&lt;/span&gt; &lt;span class="o"&gt;| &lt;/span&gt;&lt;span class="nf"&gt;date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'MMM D, YYYY'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>cms</category>
      <category>blog</category>
      <category>contentful</category>
      <category>11ty</category>
    </item>
    <item>
      <title>DNS for Web Developers</title>
      <dc:creator>Ian MacIntosh</dc:creator>
      <pubDate>Sat, 28 Nov 2020 00:55:46 +0000</pubDate>
      <link>https://dev.to/ianjmacintosh/dns-for-web-developers-5fe</link>
      <guid>https://dev.to/ianjmacintosh/dns-for-web-developers-5fe</guid>
      <description>&lt;p&gt;Imagine you go to your office, open up your web browser, and navigate to 172.217.172.197 to check your email. Then you visit 140.82.112.4 to review some code changes your coworkers have proposed. Then you open your favorite chat client and connect to 84.17.44.180. If you haven’t figured it out yet: this sucks. This is a world without domain names.&lt;/p&gt;

&lt;p&gt;Weʼre more accustomed to typing in gmail.com, github.com, and chat.freenode.net, but just like you need your friendʼs phone number to call them, your web browser needs to know the IP address of the server to request pages from. Fortunately, we have a system for finding the IP address for a given domain name that works so seamlessly that we almost never have to think about it.&lt;/p&gt;

&lt;p&gt;That also means I used to have no clue how any of it actually works, so whenever someone would talk to me about changing DNS settings, Iʼd get a sense of dread; “itʼs like a phone book for the internet” doesnʼt help me understand how record caching affects recursive lookups.&lt;/p&gt;

&lt;p&gt;If youʼve ever had that feeling, I want to help you get rid of it. Maybe youʼre a web developer working for a company that provides a supporting team of network engineers to maintain everything below the application layer, or maybe you’re in a position where you’re expected to know literally everything from color theory to algorithms. Either way, you should have a basic understanding of how DNS lets your site’s visitors connect to your app.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⌨️ Locate the address record for &lt;code&gt;www.ianjmacintosh.com&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Letʼs say I want to visit &lt;em&gt;&lt;a href="http://www.ianjmacintosh.com"&gt;www.ianjmacintosh.com&lt;/a&gt;&lt;/em&gt;. For my browser to see it, my browser needs to know the IP address to request it from. First, my browser will check to see if it already has a cached record of &lt;code&gt;www.ianjmacintosh.com&lt;/code&gt;ʼs IP address. This record is called an address record, or an &lt;em&gt;A record&lt;/em&gt;. If I donʼt have an A record on hand, my browser requests one from my &lt;em&gt;DNS resolver&lt;/em&gt;. DNS resolvers provide clients with whatever records they request, and every major ISP provides one. Iʼm going to demonstrate how to use a command line tool (&lt;code&gt;dig&lt;/code&gt;, short for &lt;em&gt;Domain Information Groper&lt;/em&gt;) to manually request records from Googleʼs public DNS resolver and other name servers.&lt;/p&gt;

&lt;p&gt;dig performs DNS lookups and displays the answers that are returned. Most DNS administrators use dig to troubleshoot DNS problems because of its flexibility, ease of use and clarity of output. It comes pre-installed on most Mac OS X and Linux systems, but Windows users who want to use it need to install it manually. If youʼre reading this on another OS (like Android or iOS) you can try to follow along with a web-based dig client like &lt;a href="https://networking.ringofsaturn.com/Tools/dig.php"&gt;this random one I found&lt;/a&gt;, but youʼll probably get more out of this article by reading for now and running the commands later at a computer with a local install of dig.&lt;/p&gt;

&lt;p&gt;Try your first &lt;code&gt;dig&lt;/code&gt; query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig @8.8.8.8 www.ianjmacintosh.com A +short
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This invocation queries &lt;code&gt;8.8.8.8&lt;/code&gt; (the IP address for Googleʼs public DNS resolver) for &lt;code&gt;www.ianjmacintosh.com&lt;/code&gt;ʼs &lt;code&gt;A&lt;/code&gt; (address) record. The &lt;code&gt;+short&lt;/code&gt; query option asks dig to provide a terse answer.&lt;/p&gt;

&lt;p&gt;That terse answer looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;54.207.147.214
18.230.52.212
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those are the IP addresses that Googleʼs DNS resolver said I should reach out to if I want &lt;code&gt;www.ianjmacintosh.com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Even if you stop reading now, at least you saw how to quickly get the IP address associated with a domain name.&lt;/p&gt;

&lt;h2&gt;
  
  
  DNS Trees
&lt;/h2&gt;

&lt;p&gt;Imagine you have a path on your local filesystem: &lt;code&gt;/Users/alice/projects/next-great-american-novel&lt;/code&gt;. The &lt;code&gt;next-great-american-novel&lt;/code&gt; directory is in the &lt;code&gt;projects&lt;/code&gt; directory, which is in the &lt;code&gt;alice&lt;/code&gt; directory, which is in the &lt;code&gt;Users&lt;/code&gt; directory, which is in the root (&lt;code&gt;/&lt;/code&gt;) directory. Computer scientists call this abstract idea a tree.&lt;/p&gt;

&lt;p&gt;The relationship between &lt;code&gt;com&lt;/code&gt;, &lt;code&gt;ianjmacintosh&lt;/code&gt;, and &lt;code&gt;www&lt;/code&gt; is the same, even though itʼs written the right-to-left instead of left-to-right. Instead of traversing directories on our local filesystem, we query DNS servers on remote systems. These servers are called &lt;em&gt;name servers&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;To get the A record for &lt;code&gt;www.ianjmacintosh.com&lt;/code&gt;, the DNS resolver asks a name server it already trusts about &lt;code&gt;com&lt;/code&gt;, which points it to another name server that knows all about &lt;code&gt;ianjmacintosh.com&lt;/code&gt;, which points it to another name server that knows all about &lt;code&gt;www.ianjmacintosh.com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Actually, thatʼs not entirely accurate; DNS resolvers and name servers sometimes have records cached locally and donʼt even need to make a request. If a name server has a cached record for &lt;code&gt;ianjmacintosh.com&lt;/code&gt;, itʼll start from there instead of going up to the top to locate the record for &lt;code&gt;www.ianjmacintosh.com&lt;/code&gt; or &lt;code&gt;pozo.ianjmacintosh.com&lt;/code&gt; or another subdomain of &lt;code&gt;ianjmacintosh.com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Also, sometimes the name server makes the appropriate next query on the requesterʼs behalf, saving the requester the trouble. That next server in turn may do the same, saving the requesting name server from needing to make an additional request. This can keep on going on and on forever, and is called a recursive search.&lt;/p&gt;

&lt;p&gt;Normally this is useful because it helps distribute the work required to locate records, but in our case we donʼt want to distribute that work! We want to do it all ourselves. So weʼre going to use dig to tell the name servers we want the A record for &lt;code&gt;www.ianjmacintosh.com&lt;/code&gt;, but we do &lt;em&gt;not&lt;/em&gt; desire recursion.&lt;/p&gt;

&lt;h3&gt;
  
  
  ⌨️ Query &lt;code&gt;8.8.8.8&lt;/code&gt; for &lt;code&gt;www.ianjmacintosh.com&lt;/code&gt;ʼs address (&lt;code&gt;A&lt;/code&gt;) record with the &lt;code&gt;+norecurse&lt;/code&gt; query option
&lt;/h3&gt;

&lt;p&gt;Hereʼs the syntax weʼre going to use with &lt;code&gt;dig&lt;/code&gt; throughout this article:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig &lt;span class="o"&gt;[&lt;/span&gt;@server] &lt;span class="o"&gt;[&lt;/span&gt;name] &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;queryopt...]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Iʼll use a keyboard emoji (⌨️) to indicate the queries Iʼd like you to perform using &lt;code&gt;dig&lt;/code&gt;. Iʼll describe them in plain English, your exercise will be to invoke the actual commands. Try to write each command on your own before comparing with how I did it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💁🏻‍♂️ Trying to keep up with how all this works mentally without running commands is difficult and silly. If you can, please go to your command line to follow along and get the most out of this article&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Try to compose a command to query 8.8.8.8 for &lt;code&gt;www.ianjmacintosh.com&lt;/code&gt;ʼs address record with the +norecurse query option on your own. Below, you can see the invocation I used 👀&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig @8.8.8.8 www.ianjmacintosh.com A +norecurse
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These arguments and options are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;8.8.8.8&lt;/code&gt; is the &lt;em&gt;server&lt;/em&gt; to query: Googleʼs public DNS resolver. I put an &lt;code&gt;@&lt;/code&gt; on the front because thatʼs what digʼs documentation (&lt;a href="https://linux.die.net/man/1/dig"&gt;&lt;code&gt;man dig&lt;/code&gt;&lt;/a&gt;) prescribes. If you omit this &lt;code&gt;[@server]&lt;/code&gt; argument, dig will consult &lt;code&gt;/etc/resolv.conf&lt;/code&gt; and query the name servers listed there.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;www.ianjmacintosh.com&lt;/code&gt; is the &lt;em&gt;name&lt;/em&gt; of the resource record to look up.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;A&lt;/code&gt; is the &lt;em&gt;type&lt;/em&gt; of record weʼre querying for -- we are looking for an “A” record (an address record). If you omit this &lt;code&gt;[type]&lt;/code&gt; argument, dig will perform a lookup for an A record anyway, but I always prefer to be as verbose and explicit as possible when showing examples.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;+norecurse&lt;/code&gt; is the query option to toggle recursion (and iteration) off. In short: this tell servers NOT to do any extra work for us. If you omit this &lt;code&gt;[queryopt]&lt;/code&gt;, the server youʼre querying may eliminate the need to do additional exercises to find our resource. Since weʼre trying to get practice, thatʼs bad!&lt;/li&gt;
&lt;li&gt;&lt;em&gt;NOTE: You may have noticed I omitted the &lt;code&gt;+short&lt;/code&gt; option. For the rest of this article, Iʼll work with verbose reports.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Putting it all together: this command instructs dig to query &lt;code&gt;8.8.8.8&lt;/code&gt; for a record named &lt;code&gt;www.ianjmacintosh.com&lt;/code&gt; with the type of &lt;code&gt;A&lt;/code&gt;, and asks the server &lt;em&gt;not&lt;/em&gt; to search recursively.&lt;/p&gt;

&lt;h3&gt;
  
  
  Read the response and notice you got an error
&lt;/h3&gt;

&lt;p&gt;dig will return a report like this one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.10.6 &amp;lt;&amp;lt;&amp;gt;&amp;gt; @8.8.8.8 www.ianjmacintosh.com A +norecurse
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: SERVFAIL, id: 25344
;; flags: qr ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;www.ianjmacintosh.com.     IN  A

;; Query time: 40 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Tue Nov 24 15:42:43 -03 2020
;; MSG SIZE  rcvd: 50
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of trying to understand all that, jump to the header section (&lt;code&gt;-&amp;gt;&amp;gt; HEADER &amp;lt;&amp;lt;-&lt;/code&gt;), and see it reads &lt;code&gt;status: SERVFAIL&lt;/code&gt;. Thatʼs short for “server failure” and means the name server was unable to process this query due to a problem with the name server. You didnʼt give a bad query, but it couldnʼt give you a real answer. If it &lt;em&gt;did&lt;/em&gt; provide an answer, itʼd show a big section with a headline of &lt;code&gt;ANSWER SECTION&lt;/code&gt; thatʼd have our requested record in it. It also explicitly says &lt;code&gt;ANSWER: 0&lt;/code&gt; on the line below &lt;code&gt;SERVFAIL&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In short, this report shows us Googleʼs public DNS resolver doesnʼt have the address record for &lt;code&gt;www.ianjmacintosh.com&lt;/code&gt;. If you ran this command again and added the &lt;code&gt;+short&lt;/code&gt; option, youʼd get an empty response.&lt;/p&gt;

&lt;p&gt;The reason we got an answer when we ran &lt;code&gt;dig&lt;/code&gt; before was because we didnʼt turn off recursion, and Googleʼs public DNS resolver did some extra work for us. That extra work started with going to what are called “root name servers.”&lt;/p&gt;

&lt;p&gt;The top-level domain &lt;code&gt;com&lt;/code&gt; is part of &lt;code&gt;.&lt;/code&gt; (pronounced “root”), just like &lt;code&gt;www.ianjmacintosh.com&lt;/code&gt; is part of &lt;code&gt;ianjmacintosh.com&lt;/code&gt;, and like &lt;code&gt;ianjmacintosh.com&lt;/code&gt; is part of &lt;code&gt;com&lt;/code&gt;. To explicitly show the root of a domain name, DNS often uses a trailing dot when showing domain names, as in: &lt;code&gt;www.ianjmacintosh.com.&lt;/code&gt; This is called a “fully qualified domain name” (FQDN), and that trailing &lt;code&gt;.&lt;/code&gt; carries the same meaning as the the leading &lt;code&gt;/&lt;/code&gt; in an absolute path (such as &lt;code&gt;/Users/alice/projects/next-great-american-novel&lt;/code&gt;): root.&lt;/p&gt;

&lt;p&gt;Every search needs to start &lt;em&gt;somewhere&lt;/em&gt;, and so our search for the &lt;code&gt;www.ianjmacintosh.com&lt;/code&gt;ʼs address record needs to start at the root. Weʼre looking for name server records, not an address record -- weʼre not trying to open &lt;code&gt;.&lt;/code&gt; in our browser. For this reason, weʼll need to change our &lt;code&gt;[type]&lt;/code&gt; argument from &lt;code&gt;A&lt;/code&gt; (for “address”) to &lt;code&gt;NS&lt;/code&gt; (for “name server”)&lt;/p&gt;

&lt;h3&gt;
  
  
  ⌨️ Query &lt;code&gt;8.8.8.8&lt;/code&gt; for &lt;code&gt;.&lt;/code&gt;ʼs name server (&lt;code&gt;NS&lt;/code&gt;) record with &lt;code&gt;+norecurse&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig @8.8.8.8 &lt;span class="nb"&gt;.&lt;/span&gt; NS +norecurse
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These arguments and options are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;8.8.8.8&lt;/code&gt; is Googleʼs public DNS resolver&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.&lt;/code&gt; is the root of all domain names&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NS&lt;/code&gt; is short for “name server”&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;+norecurse&lt;/code&gt; is still preventing the server from doing our exercises for us&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Putting it all together: this command instructs dig to query &lt;code&gt;8.8.8.8&lt;/code&gt; for a record named &lt;code&gt;.&lt;/code&gt; with the type of &lt;code&gt;NS&lt;/code&gt;, and asks the server &lt;em&gt;not&lt;/em&gt; to search recursively.&lt;/p&gt;

&lt;h3&gt;
  
  
  Locate a root server from the response report
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.10.6 &amp;lt;&amp;lt;&amp;gt;&amp;gt; @8.8.8.8 . NS +norecurse
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 51781
;; flags: qr ra ad; QUERY: 1, ANSWER: 13, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;.              IN  NS

;; ANSWER SECTION:
.           86755   IN  NS  a.root-servers.net.
.           86755   IN  NS  b.root-servers.net.
.           86755   IN  NS  c.root-servers.net.
.           86755   IN  NS  d.root-servers.net.
.           86755   IN  NS  e.root-servers.net.
.           86755   IN  NS  f.root-servers.net.
.           86755   IN  NS  g.root-servers.net.
.           86755   IN  NS  h.root-servers.net.
.           86755   IN  NS  i.root-servers.net.
.           86755   IN  NS  j.root-servers.net.
.           86755   IN  NS  k.root-servers.net.
.           86755   IN  NS  l.root-servers.net.
.           86755   IN  NS  m.root-servers.net.

;; Query time: 34 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Wed Nov 25 17:39:56 -03 2020
;; MSG SIZE  rcvd: 239
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wow! Thatʼs more like it! 🎉&lt;/p&gt;

&lt;p&gt;First off, check out the header where it says &lt;code&gt;status: NOERROR&lt;/code&gt;. No error! And on the next line, where it said &lt;code&gt;ANSWER: 0&lt;/code&gt; before, now it says &lt;code&gt;ANSWER: 13&lt;/code&gt;. We got a proper &lt;code&gt;ANSWER SECTION&lt;/code&gt; with 13 different root name servers, any of which should be able to answer a query for the name server record for &lt;code&gt;com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Pick one at random and use it your next query.&lt;/p&gt;

&lt;p&gt;By the way, instead of using an IP address for the server to send your next query to, you can use a domain name. dig will quietly ask your DNS resolver for its IP address in the background before sending your query. Instead of &lt;code&gt;8.8.8.8&lt;/code&gt;, you can use &lt;code&gt;dns.google&lt;/code&gt;. Instead of &lt;code&gt;198.41.0.4&lt;/code&gt; you can use &lt;code&gt;a.root-servers.net&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  ⌨️ Query a DNS root server for &lt;code&gt;com&lt;/code&gt;ʼs &lt;code&gt;NS&lt;/code&gt; record (with &lt;code&gt;+norecurse&lt;/code&gt;)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig @a.root-servers.net com NS +norecurse
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These arguments and options are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;a.root-servers.net&lt;/code&gt; is the server weʼre asking for a name server record for the top-level domain &lt;code&gt;com&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;com&lt;/code&gt; is the name of the record weʼre asking for&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NS&lt;/code&gt; is short for “name server”&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;+norecurse&lt;/code&gt; keeps &lt;code&gt;a.root-servers.net&lt;/code&gt; from doing a recursive search&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Get a &lt;code&gt;com&lt;/code&gt; name server from the report
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.10.6 &amp;lt;&amp;lt;&amp;gt;&amp;gt; @a.root-servers.net com NS +norecurse
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 16916
;; flags: qr; QUERY: 1, ANSWER: 0, AUTHORITY: 13, ADDITIONAL: 27

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;com.               IN  NS

;; AUTHORITY SECTION:
com.            172800  IN  NS  e.gtld-servers.net.
com.            172800  IN  NS  b.gtld-servers.net.
com.            172800  IN  NS  j.gtld-servers.net.
com.            172800  IN  NS  m.gtld-servers.net.
com.            172800  IN  NS  i.gtld-servers.net.
com.            172800  IN  NS  f.gtld-servers.net.
com.            172800  IN  NS  a.gtld-servers.net.
com.            172800  IN  NS  g.gtld-servers.net.
com.            172800  IN  NS  h.gtld-servers.net.
com.            172800  IN  NS  l.gtld-servers.net.
com.            172800  IN  NS  k.gtld-servers.net.
com.            172800  IN  NS  c.gtld-servers.net.
com.            172800  IN  NS  d.gtld-servers.net.

;; ADDITIONAL SECTION:
e.gtld-servers.net. 172800  IN  A   192.12.94.30
e.gtld-servers.net. 172800  IN  AAAA    2001:502:1ca1::30
b.gtld-servers.net. 172800  IN  A   192.33.14.30
b.gtld-servers.net. 172800  IN  AAAA    2001:503:231d::2:30
j.gtld-servers.net. 172800  IN  A   192.48.79.30
j.gtld-servers.net. 172800  IN  AAAA    2001:502:7094::30
m.gtld-servers.net. 172800  IN  A   192.55.83.30
m.gtld-servers.net. 172800  IN  AAAA    2001:501:b1f9::30
i.gtld-servers.net. 172800  IN  A   192.43.172.30
i.gtld-servers.net. 172800  IN  AAAA    2001:503:39c1::30
f.gtld-servers.net. 172800  IN  A   192.35.51.30
f.gtld-servers.net. 172800  IN  AAAA    2001:503:d414::30
a.gtld-servers.net. 172800  IN  A   192.5.6.30
a.gtld-servers.net. 172800  IN  AAAA    2001:503:a83e::2:30
g.gtld-servers.net. 172800  IN  A   192.42.93.30
g.gtld-servers.net. 172800  IN  AAAA    2001:503:eea3::30
h.gtld-servers.net. 172800  IN  A   192.54.112.30
h.gtld-servers.net. 172800  IN  AAAA    2001:502:8cc::30
l.gtld-servers.net. 172800  IN  A   192.41.162.30
l.gtld-servers.net. 172800  IN  AAAA    2001:500:d937::30
k.gtld-servers.net. 172800  IN  A   192.52.178.30
k.gtld-servers.net. 172800  IN  AAAA    2001:503:d2d::30
c.gtld-servers.net. 172800  IN  A   192.26.92.30
c.gtld-servers.net. 172800  IN  AAAA    2001:503:83eb::30
d.gtld-servers.net. 172800  IN  A   192.31.80.30
d.gtld-servers.net. 172800  IN  AAAA    2001:500:856e::30

;; Query time: 401 msec
;; SERVER: 198.41.0.4#53(198.41.0.4)
;; WHEN: Wed Nov 25 18:12:00 -03 2020
;; MSG SIZE  rcvd: 828
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Jiminy Cricket! Thatʼs a lot of info! We received 13 authorities to choose from for &lt;code&gt;com&lt;/code&gt; records, &lt;em&gt;and&lt;/em&gt; an additional section containing all their IP addresses.&lt;/p&gt;

&lt;p&gt;All of these 13 name servers have records for &lt;em&gt;every&lt;/em&gt; registered domain under &lt;code&gt;com&lt;/code&gt;. Really!&lt;/p&gt;

&lt;h3&gt;
  
  
  ⌨️ Ask a &lt;code&gt;com&lt;/code&gt; name server for &lt;code&gt;ianjmacintosh.com&lt;/code&gt;ʼs name server record (&lt;code&gt;+norecurse&lt;/code&gt; like usual)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig @192.31.80.30 ianjmacintosh.com NS  +norecurse
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;192.31.80.30&lt;/code&gt; is the server weʼre asking for a name server record for the top-level domain &lt;code&gt;com&lt;/code&gt;.

&lt;ul&gt;
&lt;li&gt;I could have just as easily used &lt;code&gt;d.gtld-servers.net&lt;/code&gt; instead and let dig find its IP address in the background, but since I already had the IP address in front of me, I used that instead.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ianjmacintosh.com&lt;/code&gt; is the name of the record weʼre asking for&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NS&lt;/code&gt; is short for “name server”&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;+norecurse&lt;/code&gt; keeps &lt;code&gt;192.31.80.30&lt;/code&gt; from doing a recursive search&lt;/li&gt;
&lt;/ul&gt;



&lt;h3&gt;
  
  
  Get an &lt;code&gt;ianjmacintosh.com&lt;/code&gt; name server from the report
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.10.6 &amp;lt;&amp;lt;&amp;gt;&amp;gt; @192.31.80.30 ianjmacintosh.com NS +norecurse
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 30145
;; flags: qr; QUERY: 1, ANSWER: 0, AUTHORITY: 4, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;ianjmacintosh.com.     IN  NS

;; AUTHORITY SECTION:
ianjmacintosh.com.  172800  IN  NS  dns1.p03.nsone.net.
ianjmacintosh.com.  172800  IN  NS  dns2.p03.nsone.net.
ianjmacintosh.com.  172800  IN  NS  dns3.p03.nsone.net.
ianjmacintosh.com.  172800  IN  NS  dns4.p03.nsone.net.

;; Query time: 411 msec
;; SERVER: 192.31.80.30#53(192.31.80.30)
;; WHEN: Wed Nov 25 18:37:01 -03 2020
;; MSG SIZE  rcvd: 135
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any of these four name servers could give me additional record information for &lt;code&gt;www.ianjmacintosh.com&lt;/code&gt;. Choose one for your next query, weʼre almost there!&lt;/p&gt;

&lt;h3&gt;
  
  
  ⌨️ Query an &lt;code&gt;ianjmacintosh.com&lt;/code&gt; name server for &lt;code&gt;www.ianjmacintosh.com&lt;/code&gt;ʼs &lt;code&gt;A&lt;/code&gt; record (&lt;code&gt;+norecurse&lt;/code&gt;)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig @dns1.p03.nsone.net www.ianjmacintosh.com A  +norecurse
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;dns1.p03.nsone.net&lt;/code&gt; is the server weʼre asking for a name server record for the top-level domain &lt;code&gt;com&lt;/code&gt;.

&lt;ul&gt;
&lt;li&gt;You can see I got lazy again and am letting dig find the IP address for &lt;code&gt;dns1.p03.nsone.net&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&lt;a href="http://www.ianjmacintosh.com"&gt;www.ianjmacintosh.com&lt;/a&gt;&lt;/code&gt; is the name of the record weʼre asking for&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;A&lt;/code&gt; is short for “address”&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;+norecurse&lt;/code&gt; keeps &lt;code&gt;dns1.p03.nsone.net&lt;/code&gt; from doing a recursive search -- not that it would have to&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  💰 Locate the IP address for &lt;code&gt;www.ianjmacintosh.com&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.10.6 &amp;lt;&amp;lt;&amp;gt;&amp;gt; @dns1.p03.nsone.net www.ianjmacintosh.com A +norecurse
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 25003
;; flags: qr aa; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;www.ianjmacintosh.com.     IN  A

;; ANSWER SECTION:
www.ianjmacintosh.com.  20  IN  A   18.230.52.212
www.ianjmacintosh.com.  20  IN  A   54.207.147.214

;; Query time: 31 msec
;; SERVER: 198.51.44.3#53(198.51.44.3)
;; WHEN: Wed Nov 25 18:40:39 -03 2020
;; MSG SIZE  rcvd: 82
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You did it! You got the IP addresses for the servers hosting &lt;code&gt;www.ianjmacintosh.com&lt;/code&gt;. Right there in the answer section, youʼll see the same IP addresses we saw in the report from our first dig: &lt;code&gt;18.230.52.212&lt;/code&gt; &amp;amp; &lt;code&gt;54.207.147.214&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;For fun, you can run dig with the &lt;code&gt;+trace&lt;/code&gt; query option to watch dig iterate over all these steps automatically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig www.ianjmacintosh.com +trace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Wow, that was a lot. Your computer does all this automatically behind the scenes whenever you try to go to a website. Congratulations, you now know &lt;em&gt;dramatically&lt;/em&gt; more than most people about DNS.&lt;/p&gt;

&lt;p&gt;Thereʼs plenty more to learn, but this is an excellent starting point. I plan on writing follow-up articles to explore some more DNS mysteries, including what a CNAME is, how you can update your records, and how to handle some common misconfigurations.&lt;/p&gt;

&lt;p&gt;If you just skimmed this article, didnʼt run any commands, and want to feel more confident with DNS anyway, thatʼs fine! I hope youʼll come back to this article and walk through the steps when you can. Until then, hereʼs some quick hits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DNS is like “a phone book for the internet” only in the vaguest analogous sense; itʼs more like a tree, and answering queries involves going from root to branch to branch&lt;/li&gt;
&lt;li&gt;DNS stands for “domain name system”&lt;/li&gt;
&lt;li&gt;By default, DNS messages are passed over port 53&lt;/li&gt;
&lt;li&gt;dig is a useful DNS diagnosis tool, and is part of BIND&lt;/li&gt;
&lt;li&gt;BIND stands for “Berkeley Internet Name Domain” and is a collection of domain name tools originally developed at UC Berkeley&lt;/li&gt;
&lt;li&gt;BINDʼs most notable application is its extremely popular &lt;em&gt;name daemon&lt;/em&gt; server (confusingly called &lt;code&gt;named&lt;/code&gt; as in “name D”, short for “name dameon”) which can respond to DNS requests&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Additional Information
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Why are domain trees written right-to-left (&lt;code&gt;subdomain.domain.com&lt;/code&gt;), then paths written left-to-right (&lt;code&gt;/users/~imacintosh/articles/dns-for-web-developers&lt;/code&gt;)?
&lt;/h3&gt;

&lt;p&gt;Good question. I havenʼt found a satisfying answer. Common explanations on Q&amp;amp;A forums point to how email addresses (&lt;code&gt;user@host&lt;/code&gt;) work the same way of going more specific to less specific. Jon Postelʼs &lt;a href="https://tools.ietf.org/html/rfc805"&gt;notes&lt;/a&gt; from a 1982 meeting of the “Network Working Group” suggest the group sought to make decisions that would provide the fewest implementation challenges. This seems to be one such decision, but I donʼt see the reasons why.&lt;/p&gt;

&lt;p&gt;For what itʼs worth, Tim Berners-Lee mentioned in &lt;a href="https://www.bcs.org/content-hub/isnt-it-semantic/"&gt;an interview&lt;/a&gt; if he could go back and do things differently, he would have put domains in &lt;code&gt;com.domain.subdomain&lt;/code&gt; order. 🤷🏻‍♂️&lt;/p&gt;

&lt;h3&gt;
  
  
  So basically the entire internet is running on the backs of 13 different root DNS servers?
&lt;/h3&gt;

&lt;p&gt;Nope! Those are 13 different IP addresses, but the servers responding to requests for them are much more numerous; there were over 1300 when I wrote this, and theyʼre pretty well distributed around the world. The &lt;a href="https://root-servers.org/"&gt;root servers homepage&lt;/a&gt; has a neat map that shows where they all are. If you want to understand how multiple systems can share one IP address, you can look up “anycast.”&lt;/p&gt;

&lt;h3&gt;
  
  
  If &lt;code&gt;18.230.52.212&lt;/code&gt; is the IP address for the server hosting &lt;code&gt;www.ianjmacintosh.com&lt;/code&gt;, why do I get a weird error message instead of your website when I visit it?
&lt;/h3&gt;

&lt;p&gt;The server at 18.230.52.212 serves up lots of websites, not just mine. That server needs to know which website youʼre asking for. When you visit &lt;em&gt;&lt;a href="http://www.ianjmacintosh.com"&gt;www.ianjmacintosh.com&lt;/a&gt;&lt;/em&gt; in your browser, it tells the server at 18.230.52.212 to serve up &lt;em&gt;&lt;a href="http://www.ianjmacintosh.com"&gt;www.ianjmacintosh.com&lt;/a&gt;&lt;/em&gt;. When you visit &lt;em&gt;18.230.52.212&lt;/em&gt;, it may not know what you want.&lt;/p&gt;

</description>
      <category>networking</category>
      <category>dns</category>
      <category>webdev</category>
      <category>bash</category>
    </item>
  </channel>
</rss>
