<?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: Stacie Taylor</title>
    <description>The latest articles on DEV Community by Stacie Taylor (@the_real_stacie).</description>
    <link>https://dev.to/the_real_stacie</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%2F222063%2Faa4b4d0b-4333-40ef-a19c-3a251055133e.jpg</url>
      <title>DEV Community: Stacie Taylor</title>
      <link>https://dev.to/the_real_stacie</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/the_real_stacie"/>
    <language>en</language>
    <item>
      <title>The Collab Lab turns 4 soon! And with time comes change.</title>
      <dc:creator>Stacie Taylor</dc:creator>
      <pubDate>Tue, 13 Jun 2023 03:22:42 +0000</pubDate>
      <link>https://dev.to/the-collab-lab/the-collab-lab-turns-4-soon-and-with-time-comes-change-2agm</link>
      <guid>https://dev.to/the-collab-lab/the-collab-lab-turns-4-soon-and-with-time-comes-change-2agm</guid>
      <description>&lt;p&gt;As of August, it will have been 4 years since we kicked off the first-ever project at The Collab Lab. We just wrapped up our 61st team! As of today, we’ve helped over 230 early-career developers—from incredibly diverse backgrounds—learn how professional software teams collaborate, teaching practical skills including pair programming, giving/receiving code reviews, and how to demo work to stakeholders, all of the stuff that’s all but impossible to simulate when you’re studying on your own.&lt;/p&gt;



&lt;h2&gt;
  
  
  What’s changing
&lt;/h2&gt;

&lt;p&gt;For the last 3 years or so, we’ve been following a cadence of one cohort per quarter where we run between 4 and 7 teams of 4 developers each. That worked well as long as we were content to execute the current program. What it didn’t allow us much time for was program and curriculum development.&lt;/p&gt;

&lt;p&gt;Not for nothing, that model was a big improvement over the early days when we’d kick off the next team when the current one was halfway through. 🤪🫠&lt;/p&gt;

&lt;p&gt;The existing structure served us well, as long as we didn’t want to make too many improvements to the program…&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“We’ve been wanting to make some meaningful changes to the structure of the program to better serve our community and given that we’re volunteer run, we need the extra time between cohorts to make these changes.” —Me to the Collab Lab board members in Q2 2023 😅&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Our program as it’s currently structured is 8 weeks long. About a year ago, we added an optional 2-week career development program to the end of each project term. That gave us just 2 weeks before the next round of applications would open up and we’d be back on the hamster wheel of providing direct service to the next group.&lt;/p&gt;

&lt;p&gt;So, with the enthusiastic consent of our Board of Advisors (&lt;a href="https://www.linkedin.com/in/chiamakaumeh"&gt;Chiamaka Umeh&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/fullybaked"&gt;David Baker&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/mxmason"&gt;EJ Mason&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/yolanda-haynes"&gt;Yolanda Haynes&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/mindyzwan"&gt;Mindy Zwanziger&lt;/a&gt;, &amp;amp; &lt;a href="https://www.linkedin.com/in/shelleymchardy"&gt;Shelley McHardy&lt;/a&gt;), we have decided to move from offering 4 cohorts per year to 2.&lt;/p&gt;

&lt;p&gt;Sometimes, less truly is more.&lt;/p&gt;

&lt;p&gt;By giving ourselves some breathing space between cohorts, we expect to create the capacity to make substantive changes to the program that will allow us to scale horizontally in a way that’s tough to pull off today. We fully expect that by the end of next year we will be able to serve even more early-career developers than we do today and at a higher level of quality.&lt;/p&gt;



&lt;h2&gt;
  
  
  What’s staying the same
&lt;/h2&gt;

&lt;p&gt;What will &lt;strong&gt;never&lt;/strong&gt; change as long as The Collab Lab exists is our commitment to helping early-career developers from diverse backgrounds make the jump into tech. In the current jobs environment, this is as tall a task as it’s ever been and we are more committed than ever to doing everything we can to ease that transition for as many people as possible.&lt;/p&gt;

</description>
      <category>nonprofit</category>
      <category>changemanagement</category>
      <category>volunteermanagement</category>
      <category>engineering</category>
    </item>
    <item>
      <title>Git: Are you an over-committer? Squash those commits!
</title>
      <dc:creator>Stacie Taylor</dc:creator>
      <pubDate>Sat, 17 Apr 2021 22:28:09 +0000</pubDate>
      <link>https://dev.to/the_real_stacie/git-are-you-an-over-committer-squash-those-commits-2klk</link>
      <guid>https://dev.to/the_real_stacie/git-are-you-an-over-committer-squash-those-commits-2klk</guid>
      <description>&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%2F07nk569g9oym90pax65x.jpeg" 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%2F07nk569g9oym90pax65x.jpeg" alt="Photo by Christin Hume on Unsplash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Photo by Christin Hume on Unsplash&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Are you an over-committer? Me too. Basically, anytime I complete some kind of task, I commit it with a message that details what I’ve done. I do this for a few reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I’ve read over and over again: “Commit a lot, commit often”&lt;/li&gt;
&lt;li&gt;I have kids and work at home. As I’m working, my kids could need me immediately at any second, and I want to make sure my work is saved.&lt;/li&gt;
&lt;li&gt;Those crazy kids also sometimes get access to the computer and get happy fingers while my projects are open, so I want to make sure I’ve got it all backed up.&lt;/li&gt;
&lt;li&gt;I often find myself working in short stints and having lots of commit messages helps me retrace my steps and offers me a sort of progress report.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I was recently told by someone who was reviewing my code that I commit too frequently. He suggested, “If you feel that it is helpful for you [to make incremental commits], I would recommend you check out squashing commits with Git.”&lt;/p&gt;

&lt;p&gt;After researching what squashing commits even meant, I realized it was the perfect way for me to have my cake and eat it too! It allows you to make as many smaller commits locally as you feel necessary, based on your own preference and workflow, and then squash them down into one clean commit so that your remote repo’s commit history is nice and tidy!&lt;/p&gt;

&lt;p&gt;Below, I’ve laid out a step-by-step guide on how to squash commits that can be followed by any Code Newbie!&lt;/p&gt;

&lt;h2&gt;
  
  
  Steps to squash your commits:
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;WARNING! Before you start, keep in mind that you should squash your commits BEFORE you ever push your changes to a remote repository. If you rewrite your history once others have made changes to it, you’re asking for trouble… or conflicts. Potentially lots of them!&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create and checkout a new branch where you will write your code: &lt;code&gt;git checkout -b [your_branch_here]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;As you work on your project, make as many commits as you’d like!&lt;/li&gt;
&lt;li&gt;Find out how many commits you want to squash! You will need the number of commits so that you can tell Git how far to go back during your rebase. The command below will get you the log of commits not including any that are available to master and you can count how many you’d like to squash: &lt;code&gt;git log [your_branch_here] — not master&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Run an interactive rebase. In the sample below, replace X with the number of commits you want to squash. This will rebase you X commits back: &lt;code&gt;git rebase -i HEAD~X&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The text editor will pop up and list your commits. &lt;code&gt;Shift + i&lt;/code&gt; to type. Replace &lt;code&gt;pick&lt;/code&gt; with &lt;code&gt;squash&lt;/code&gt; on the most recent commits. Make sure the first commit is still preceded with the &lt;code&gt;pick&lt;/code&gt; command. This basically tells Git to squash all of your most recent commits into your first commit.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pick first_commit
squash second_commit
squash third_commit
squash fourth_commit

# Your text editor will give you a bunch of other instructions and options here. Check them out. There is some really helpful information.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;esc&lt;/code&gt; to escape insert mode.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:wq&lt;/code&gt; to save your changes. (VIM)&lt;/li&gt;
&lt;li&gt;Another text editor screen will pop up and allow you to write a new commit message that will sum up all of your previous commit messages. Comment out all of the previous commit messages and write your new one.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# This is a combination of X commits.
# The first commit’s message is:
# First commit message

# This is the 2nd commit message:
# Second commit message

# This is the 3rd commit message:
# Third commit message

# This is the 4th commit message:
# Fourth commit message

New commit message here

# Git will list some other instructions and the changes you’re committing here.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;:wq&lt;/code&gt; to save and quit. (VIM)&lt;/li&gt;
&lt;li&gt;You can double check that it worked by running &lt;code&gt;git log&lt;/code&gt; again. You should see only your new single commit!&lt;/li&gt;
&lt;/ul&gt;


 

&lt;p&gt;There are multiple variations of this process and countless workflows and commit preferences among us. I am really interested in how you commit and how you squash (if you do). Please share your experiences so that we can all become more productive and efficient developers and team players!&lt;/p&gt;

</description>
      <category>github</category>
      <category>git</category>
      <category>terminal</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to resolve merge conflicts with git</title>
      <dc:creator>Stacie Taylor</dc:creator>
      <pubDate>Thu, 01 Oct 2020 00:26:48 +0000</pubDate>
      <link>https://dev.to/the_real_stacie/how-to-handle-merge-conflicts-with-git-1ked</link>
      <guid>https://dev.to/the_real_stacie/how-to-handle-merge-conflicts-with-git-1ked</guid>
      <description>&lt;p&gt;Dealing with messy merge conflicts can be a bit like navigating heavy traffic. With a bit of patience, forward-thinking, and sometimes a pal, you can resolve any conflict you're faced with. Take a deep breath and follow the steps below to get those resolutions in place!&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1
&lt;/h2&gt;

&lt;p&gt;Pull down all the latest code from the main branch of your remote repo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git fetch
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2
&lt;/h2&gt;

&lt;p&gt;Merge all that fresh new code into your feature branch locally.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git rebase origin/main
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3
&lt;/h2&gt;

&lt;p&gt;[Optional] Run this to get a high-level look at which files have conflicts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git status
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4
&lt;/h2&gt;

&lt;p&gt;Fix all the merge conflicts in your project. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to those files in your editor. You will see that it shows you the code that lives on the HEAD &lt;strong&gt;and&lt;/strong&gt; your branch's code. &lt;/li&gt;
&lt;li&gt;Keep the good code that you need when it asks you to choose and delete the code you don't want. This can be the most challenging part because you might be seeing code from your team that you don't recognize -- pair with your pals to decide what code goes and what code stays if necessary. &lt;/li&gt;
&lt;li&gt;When you see that the files that previously had conflicts are squared away, &lt;strong&gt;save&lt;/strong&gt; them!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 5
&lt;/h2&gt;

&lt;p&gt;Stage all the files that you fixed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add .
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 6
&lt;/h2&gt;

&lt;p&gt;Continue the rebase to see what's next.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git rebase --continue
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 7
&lt;/h2&gt;

&lt;p&gt;You may still have more conflicts to work through because the rebase is going to compare every commit that came down from the main branch to your feature branch. Keep the following steps 3-6 until you're taken back to your feature branch. &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 8
&lt;/h2&gt;

&lt;p&gt;Push your updated code up to your remote repository.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git push --force-with-lease
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note: &lt;code&gt;--force-with-lease&lt;/code&gt; is a safer option than &lt;code&gt;force&lt;/code&gt; because it will not overwrite any work on the remote branch if more commits were added to the remote branch. Read more &lt;a href="https://git-scm.com/docs/git-push"&gt;here&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>terminal</category>
      <category>thecollablab</category>
    </item>
    <item>
      <title>Team 9 Recap</title>
      <dc:creator>Stacie Taylor</dc:creator>
      <pubDate>Tue, 29 Sep 2020 04:19:03 +0000</pubDate>
      <link>https://dev.to/the-collab-lab/team-9-recap-5b4b</link>
      <guid>https://dev.to/the-collab-lab/team-9-recap-5b4b</guid>
      <description>&lt;p&gt;Every time a Collab Lab cohort wraps up, I swear it flew by faster than the one that came before it. The August 2020 cohort was no exception -- it went so quickly and I can’t believe we’ve tossed our tassels with another amazing group of developers! 🎓&lt;/p&gt;

&lt;p&gt;In the early days of The Collab Lab we only ran one team at a time. We’ve grown up quite a bit since then and we’re not stopping anytime soon. Our August 2020 cohort included 3 teams and I was lucky enough to mentor Team 9 alongside &lt;a href="https://twitter.com/yvesgurcan"&gt;Yves Gurcan&lt;/a&gt;, a first-time Collab Lab mentor and the head of our Tech Talk initiative, and &lt;a href="https://twitter.com/ScottBergler"&gt;Scott Bergler&lt;/a&gt;, a former Collabie who couldn’t get enough so he decided to hang around and offer his experience to help other developers grow! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--m1i45uNI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/mzgddol805qhrq5pca0v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--m1i45uNI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/mzgddol805qhrq5pca0v.png" alt="Team 9 at The Collab Lab" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Our participants included:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://twitter.com/lacrivella"&gt;Leigh-Ann Crivella&lt;/a&gt;, whose organizational skills and forward thinking led the team to so much success and, without a doubt, played a role in her landing her first developer role! Congrats, Leigh-Ann. We’re so proud of you.
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://twitter.com/basil_chicken"&gt;Lia Chen&lt;/a&gt;, who always demonstrates such curiosity when approaching code and tackles building new features and squashing bugs with great calculation. Nothing is gonna get by her! &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.linkedin.com/in/mabel-h-574025171/"&gt;Mabel Hernandez&lt;/a&gt;, who is incredibly thoughtful when it comes to solving problems and is always digging deep to understand her code. She is always ready to fill you in on the technical details during Q&amp;amp;A after demos! &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://twitter.com/Hsensation88"&gt;Fabrice Innocent&lt;/a&gt;, who came to the team with such ambition and blew us away with his dedication and tenacity. Fabrice totally crushed learning a new programming language and contributed some wonderfully fresh perspective to the team. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This team’s collaboration skills were so impressive. They kicked off the program and immediately started building a solid team that worked together to organize the work that needed to be done, squash tricky bugs, and build a really fantastic app. &lt;/p&gt;

&lt;p&gt;If you’re in search of some really incredible developers who have experience collaborating with great success in a remote and agile environment, these are your people. ✅ ✨ 👏&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>css</category>
      <category>thecollablab</category>
    </item>
    <item>
      <title>Cropping &amp; Zooming in on SVGs with viewBox</title>
      <dc:creator>Stacie Taylor</dc:creator>
      <pubDate>Fri, 14 Aug 2020 17:01:18 +0000</pubDate>
      <link>https://dev.to/the_real_stacie/cropping-zooming-in-on-svgs-with-viewbox-2gb6</link>
      <guid>https://dev.to/the_real_stacie/cropping-zooming-in-on-svgs-with-viewbox-2gb6</guid>
      <description>&lt;p&gt;When you build an SVG, you build your own little world. And what's the point of creating something beautiful if you're not gonna take pictures of it and show people (note: I recognize I'm letting my inner millennial show here). &lt;/p&gt;

&lt;p&gt;Within your &lt;code&gt;&amp;lt;svg&amp;gt;&lt;/code&gt; tags, you can build your little world! It can be bursting with life and color and all the most beautiful things. But then, you have to decide what you want to show your friends by taking the pictures. &lt;/p&gt;

&lt;p&gt;Think of the SVG's &lt;code&gt;viewBox&lt;/code&gt; attribute as your camera lens. Which pieces of your world do you want to capture on your camera for people to see? &lt;/p&gt;

&lt;p&gt;Take this image for example. This whole bakery might be what is inside the &lt;code&gt;&amp;lt;svg&amp;gt;&lt;/code&gt; tag. But you don't really need to show people the entire bakery at this time, you just wanna zoom in on these tasty little donuts — the real star of the show!&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%2Fi%2Frdc8eqp412tmkfc3if3c.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%2Fi%2Frdc8eqp412tmkfc3if3c.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, when you think of an SVG, you should think that the actual SVG itself could potentially have an infinite canvas, but what us humans can actually see is what is within the &lt;code&gt;viewBox&lt;/code&gt; that the developer has defined! &lt;/p&gt;

&lt;p&gt;Your &lt;code&gt;viewBox&lt;/code&gt; is what is in charge of zooming and panning your "camera lens" so we only show what we want to show. &lt;/p&gt;




&lt;p&gt;The value of the viewBox attribute is a list of four numbers: &lt;code&gt;min-x&lt;/code&gt;, &lt;code&gt;min-y&lt;/code&gt;, &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;min-x&lt;/code&gt; and &lt;code&gt;min-y&lt;/code&gt; are the top left corner of the &lt;code&gt;viewBox&lt;/code&gt; and define it's position. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;min-x&lt;/code&gt;: This will move your camera lens right and left — much like "trucking" in filmography. &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%2Fi%2F8o82i2zl2bihfe11u4yh.gif" 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%2Fi%2F8o82i2zl2bihfe11u4yh.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;min-y&lt;/code&gt;: This will move your camera lens up and down — much like "pedestal" in filmography. &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%2Fi%2Fd3s35jc732ita8se2zng.gif" 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%2Fi%2Fd3s35jc732ita8se2zng.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; are set to the number on "units" that are visible inside of your &lt;code&gt;viewBox&lt;/code&gt;. Changing these values will zoom in on our world! &lt;/p&gt;

&lt;p&gt;&lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; work off of each other, so you may need to work with both values depending on what you want to achieve. &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%2Fi%2F3qgnsrthlq9dq5mib8xm.gif" 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%2Fi%2F3qgnsrthlq9dq5mib8xm.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There you have it! Now, with the power of &lt;code&gt;viewBox&lt;/code&gt; attribute, you have to power to crop and zoom your SVG to show exactly what you want people to see. You might have also learned some new photography vocab as well that you can apply to your next Instagram story.&lt;/p&gt;

&lt;p&gt;There is a great video on the &lt;code&gt;viewBox&lt;/code&gt; attribute over &lt;a href="https://www.youtube.com/channel/UCVyRiMvfUNMA1UPlDPzG5Ow" rel="noopener noreferrer"&gt;here by DesignCourse&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And you can use a brilliant tool they've created to play around with the &lt;code&gt;viewBox&lt;/code&gt; attribute on your own SVGs &lt;a href="https://codepen.io/designcourse/live/mdydjBa" rel="noopener noreferrer"&gt;over here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>css</category>
      <category>svg</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Getting Started with SVGs</title>
      <dc:creator>Stacie Taylor</dc:creator>
      <pubDate>Wed, 12 Aug 2020 23:24:12 +0000</pubDate>
      <link>https://dev.to/the_real_stacie/getting-started-with-svgs-k1d</link>
      <guid>https://dev.to/the_real_stacie/getting-started-with-svgs-k1d</guid>
      <description>&lt;p&gt;Using Scalable Vector Graphics (SVG's) when building your web apps has some major benefits when compared to other graphic types! &lt;/p&gt;

&lt;h2&gt;
  
  
  Incredibly responsive:
&lt;/h2&gt;

&lt;p&gt;If you've ever spent time battling with making a pretty little graphic look perfect on all screen sizes, I feel you. SVGs are incredibly responsive because they are resolution-independent, meaning, unlike other file types (JPG, PNG, etc), SVG's can scale to any dimension without losing quality. Browsers just recalculate the math behind the image so that it won't get blurry.&lt;/p&gt;

&lt;p&gt;Raster images, on the other hand, can get blurry when we make them bigger because their small pixels are forced to stretch beyond their original size. &lt;/p&gt;

&lt;h2&gt;
  
  
  Super performant:
&lt;/h2&gt;

&lt;p&gt;When we use PNGs and JPGs, we're usually dealing with some really hefty file sizes. SVG's, on the other hand, are just code, so if optimized properly, they can have very small file sizes making your web app lightning fast! &lt;/p&gt;

&lt;p&gt;You can even take that speed a step further by swapping out your graphic for an inline SVG, reducing the number of HTTP requests being made. &lt;/p&gt;

&lt;h2&gt;
  
  
  Beautifully animated:
&lt;/h2&gt;

&lt;p&gt;Because SVG's can move smoothly and freely, all while maintaining their perfect quality, we're able to make them dance around the page in ways that can help really tell a story and engage our users like never before! &lt;/p&gt;

&lt;p&gt;Over the next 9 weeks, my pals and I are diving into learning more about SVG animation, but let's start with the basics of how to even create an SVG!  &lt;/p&gt;



&lt;h3&gt;
  
  
  Creating an SVG
&lt;/h3&gt;

&lt;p&gt;If you're going to build a really complex SVG, it's a good idea to use a drawing app that will allow you to export the SVG. But, really, it's all just code, so let's take a look at a really basic example! &lt;/p&gt;

&lt;p&gt;1) Start with your root SVG element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;svg&amp;gt;&amp;lt;/svg&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;2) Then we need to give the SVG viewport it's &lt;code&gt;height&lt;/code&gt; and &lt;code&gt;width&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;svg width="450px" height="100px"&amp;gt;
&amp;lt;/svg&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;At this point, the SVG's canvas dimensions are the exact same as the viewport dimensions we defined. &lt;/p&gt;

&lt;p&gt;3) Once we've got our SVG viewport created, we can start making it look pretty. Let's add a shape! &lt;/p&gt;

&lt;p&gt;There are a number of &lt;a href="https://www.w3.org/TR/SVG11/shapes.html"&gt;predefined shape elements&lt;/a&gt;, but let's just test out a rectangle for now. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start by using the &lt;code&gt;rect&lt;/code&gt; (rectangle) element. &lt;/li&gt;
&lt;li&gt;Then we need to tell it where on the SVG canvas it should start so we give it &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; coordinates.&lt;/li&gt;
&lt;li&gt;Give it some shape by defining the &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;And finally add some style!
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;svg width="450px" height="100px" viewBox="0 0 450 100"&amp;gt;
  &amp;lt;rect x="10" y="5" width="90" height="90" fill="pink" stroke="orange" /&amp;gt;
&amp;lt;/svg&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;At this point, you should have an SVG canvas (450px x 100px) with a square inside it (90 x 90) like this: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wKtxMzlL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/lw16ekuqdpww17mg1kw1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wKtxMzlL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/lw16ekuqdpww17mg1kw1.png" alt="SVG canvas that shows 450 x 100 as the diminsions"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--M26zsSEK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ive4jz0zgdkderp9mntq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--M26zsSEK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ive4jz0zgdkderp9mntq.png" alt="Square shape that shows dimensions of 90 x 90"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Excellent! We've got a nice little square, but there is so much more we can do here.  &lt;/p&gt;

&lt;p&gt;Up next we will take a look at how to scale SVG's with the &lt;code&gt;viewBox&lt;/code&gt; attribute. Stay tuned! &lt;/p&gt;

</description>
      <category>css</category>
      <category>svg</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Cohort 8 Recap</title>
      <dc:creator>Stacie Taylor</dc:creator>
      <pubDate>Tue, 04 Aug 2020 03:10:29 +0000</pubDate>
      <link>https://dev.to/the-collab-lab/team-8-recap-3na0</link>
      <guid>https://dev.to/the-collab-lab/team-8-recap-3na0</guid>
      <description>&lt;p&gt;Watching folx come to Collab Lab and grow their collaboration skills is, without a doubt, one of my favorite parts of life. We’ve just wrapped &lt;a href="https://the-collab-lab.codes/about-us/#cohort-8"&gt;Cohort 8&lt;/a&gt; and I am incredibly grateful to have gotten the chance to work on such a fun, ambitious team of developers! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QoQvzyKl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/7brv084hruutg8ojcmcz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QoQvzyKl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/7brv084hruutg8ojcmcz.png" alt="The Collab Lab Cohort 8 on a Zoom call" width="800" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The team:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🌺 &lt;a href="https://twitter.com/abidishajia"&gt;Shajia Abidi&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🌟 &lt;a href="https://twitter.com/lilymzhou"&gt;Lily Zhou&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🔮 &lt;a href="https://twitter.com/alilynnet"&gt;Ali Thompson&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;☀️ &lt;a href="https://twitter.com/Lukabaram"&gt;Luka Baramishvili&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The mentors:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🌼 &lt;a href="https://twitter.com/adriennefriend"&gt;Adrienne Lowe&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;✨ &lt;a href="https://twitter.com/the_real_stacie"&gt;Stacie Taylor&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💥 &lt;a href="https://twitter.com/segdeha"&gt;Andrew Hedges&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each member of this team is incredibly gracious and humble. Throughout their eight weeks together, they were always sharing credit for a job well done and lifting each other up! When it came to code reviews they were great about accepting and incorporating feedback and even proactively asking for it.&lt;/p&gt;

&lt;p&gt;Shajia, Lily, Ali, and Luka are all strong technically, but completely understood the importance of learning good team practices. They consistently inspired me with their organized and thoughtful weekly demos and their teamwork was absolutely inspiring. &lt;/p&gt;

&lt;p&gt;I enjoyed spending time getting to know each member of Team #8 and cannot wait to see what the future holds for them! &lt;/p&gt;

</description>
      <category>react</category>
      <category>firebase</category>
      <category>javascript</category>
      <category>css</category>
    </item>
    <item>
      <title>How to enable Preview Mode on an app powered by Next.js &amp; Contentful</title>
      <dc:creator>Stacie Taylor</dc:creator>
      <pubDate>Fri, 22 May 2020 04:00:29 +0000</pubDate>
      <link>https://dev.to/the_real_stacie/how-to-enable-preview-mode-on-an-app-powered-by-next-js-contentful-3d9p</link>
      <guid>https://dev.to/the_real_stacie/how-to-enable-preview-mode-on-an-app-powered-by-next-js-contentful-3d9p</guid>
      <description>&lt;h2&gt;
  
  
  What?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Fire up those IDEs:&lt;/strong&gt; This article will walk you through how to enable Preview Mode on a Next.js powered website or app that's content is managed with Contentful.&lt;/p&gt;



&lt;h2&gt;
  
  
  Why?
&lt;/h2&gt;

&lt;p&gt;You're probably here because you built your company a really dope Next.js powered app that manages it's content with &lt;a href="https://www.contentful.com/faq/about-contentful/#what-is-contentful"&gt;Contentful&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Great work! But, now those folks who create your engaging, captivating, money-making content want a way to preview what their drafted work would look like when it's live &lt;strong&gt;before&lt;/strong&gt; they publish it for all the world to see. &lt;/p&gt;

&lt;p&gt;Great news! You're in luck because you chose to build with two tools that both want you to preview your work -- good lookin' out, friends. 🎉&lt;/p&gt;



&lt;h2&gt;
  
  
  How?
&lt;/h2&gt;

&lt;p&gt;Of course, the configuration will vary based on all the intricacies of how you built your unique app, but this oughta give you a high-level of how Next.js &amp;amp; Contentful's preview features work together. So, let's take a look at a basic example on a blog site!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;At a high-level, this is how Preview Mode is functioning on this example blog:&lt;/strong&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All of the blog’s pages are statically generated and we’re querying &lt;a href="https://www.contentful.com/developers/docs/references/content-delivery-api/"&gt;Contentful's Content Delivery API&lt;/a&gt; for the blog data at build time.&lt;/li&gt;
&lt;li&gt;In Contentful, you can create a new unpublished blog post or make unpublished edits to an existing blog post.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uIyiRyzV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.zappy.app/8e4d459b8d2f1283fc416cb8efcfe621.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uIyiRyzV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.zappy.app/8e4d459b8d2f1283fc416cb8efcfe621.png" alt="https://cdn.zappy.app/8e4d459b8d2f1283fc416cb8efcfe621.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you want to preview the changes, click on the "Open Preview" button.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---MCz5PDQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.zappy.app/dc4976e38b1db9868dd87bc115c6c1e8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---MCz5PDQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.zappy.app/dc4976e38b1db9868dd87bc115c6c1e8.png" alt="https://cdn.zappy.app/dc4976e38b1db9868dd87bc115c6c1e8.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This will open a new tab in the browser, hit this blog's &lt;code&gt;api/preview&lt;/code&gt; route (that we will build below) that will trigger two Next.js preview mode cookies to be added to the browser, then will redirect the user back to the URL of the blog post they intend to preview.&lt;/li&gt;
&lt;li&gt;Any requests to Next.js containing these cookies will be seen as preview mode, and the pages that used to be statically generated (SSG) will now be served with server-side rendering (SSR). We are then able to query &lt;a href="https://www.contentful.com/developers/docs/references/content-preview-api/"&gt;Contentful's Content Preview API&lt;/a&gt; rather than the &lt;a href="https://www.contentful.com/developers/docs/references/content-delivery-api/"&gt;Content Delivery API&lt;/a&gt;, which will pick up all those unpublished changes.&lt;/li&gt;
&lt;li&gt;When the user is done previewing, you can build a handy dandy button in something like a Preview Mode banner so they can click to exit Preview Mode (which really just sends them through the blog's &lt;code&gt;api/preview-disable&lt;/code&gt; route, removing those two Next.js Preview Mode cookies) and redirect them back to the blog's non-Preview Mode page.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BDe4SzJg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.zappy.app/4a4cf133e4f05a5f52bbc0d3cb3fa940.png" alt="Preview Mode Banner"&gt;
&lt;/li&gt;
&lt;/ul&gt;



&lt;h2&gt;
  
  
  Let's dig into the details!
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Wanna know more about how exactly this was implemented? Read on...&lt;/em&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Set up Preview URL in Contentful
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;&lt;a href="https://www.contentful.com/help/setup-content-preview/"&gt;Contentful's Preview URL Documentation&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inside &lt;code&gt;Contentful &amp;gt; Settings &amp;gt; Content preview&lt;/code&gt;, set a preview URL on the content type that you want to preview. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;That preview URL needs to pass through the preview API in your Next.js app (&lt;code&gt;/blog&lt;/code&gt; in my case here) so that when that URL is visited, it will trigger preview cookies to be set that will tell Next.js to enable preview mode.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We then pass it the path to the content we want to preview (&lt;code&gt;blog/{slug}&lt;/code&gt; for example).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--J_Uw3Ef7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.zappy.app/df2eaa964fdd1496240f61bd85550ffc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--J_Uw3Ef7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.zappy.app/df2eaa964fdd1496240f61bd85550ffc.png" alt="Preview URL in Contentful"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Add the Preview Access Token to your code
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The content preview access token for your Contentful Space will return every single thing that the content delivery access token will &lt;strong&gt;+ DRAFTED CONTENT&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9KOKv8fK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.zappy.app/8ecf35b292be0ae7f085192169db859d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9KOKv8fK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.zappy.app/8ecf35b292be0ae7f085192169db859d.png" alt="Preview Access Token in Contentful"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inside the app's &lt;code&gt;next.config.js&lt;/code&gt;, we need to build the URL that will fetch data using the content preview access token like this:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&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="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;contentfulGraphQLUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`https://graphql.contentful.com/content/v1/spaces/&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="s2"&gt;?access_token=&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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;contentfulPreviewGraphQLUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`https://graphql.contentful.com/content/v1/spaces/&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="s2"&gt;?access_token=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;previewAccessToken&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Set up Preview Mode in Next.js
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&lt;a href="https://nextjs.org/docs/advanced-features/preview-mode"&gt;Next.js Preview Mode documentation&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create API route that will turn preview mode on&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;In the aforementioned documentation, it will show you how to create your preview API route. Inside this &lt;code&gt;api/preview&lt;/code&gt; file, you will call &lt;code&gt;setPreviewData&lt;/code&gt; on the response object.&lt;/li&gt;
&lt;li&gt;This will set two preview cookies in the browser that will essentially "turn preview mode on". Any requests to Next.js containing these cookies will be seen as preview mode, and the pages that used to be statically generated (SSG) will now be served with server-side rendering (SSR)&lt;/li&gt;
&lt;li&gt;You can then route the user to the actual blog post they wanted once the &lt;code&gt;setPreviewData&lt;/code&gt; has added those cookies and query Contentful's Content Preview API (rather than the Content Delivery API) and we will then be fetched the unpublished (draft) content so that we can preview it!
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// api/preview.tsx&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;NextApiRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;NextApiResponse&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;next&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Perform a server side redirect
 * https://nextjs.org/docs/basic-features/data-fetching#getserversideprops-server-side-rendering
 * https://nodejs.org/api/http.html#http_class_http_serverresponse
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;serverSideRedirect&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;ServerResponse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;destinationPath&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;statusCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;301&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;destinationPath&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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextApiRequest&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;NextApiResponse&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="c1"&gt;// Calling setPreviewData sets a preview cookies that turn on the preview mode.&lt;/span&gt;
  &lt;span class="c1"&gt;// Any requests to Next.js containing these cookies will be seen as preview mode,&lt;/span&gt;
  &lt;span class="c1"&gt;// and the behavior for statically generated pages will change.&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;setPreviewData&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;maxAge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// The preview mode cookies expire in 1 hour&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;slug&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&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;serverSideRedirect&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;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;blogArticle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;slug&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="mi"&gt;307&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;end&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;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create API route that will disable preview mode&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Just like you created the &lt;code&gt;preview&lt;/code&gt; route, you'll create a &lt;code&gt;preview-disable&lt;/code&gt; route.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Additionally: In the &lt;code&gt;api/preview&lt;/code&gt; file, when &lt;code&gt;setPreviewData&lt;/code&gt; is called, you can set a &lt;code&gt;maxAge&lt;/code&gt; so that the preview mode will expire after one hour as a means of disabling the preview mode. See code above.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;I might also suggest building a Preview Mode banner to allow your content folks the ability to manually disable preview mode. When they click this button, they should be sent through the &lt;code&gt;api/preview-disable&lt;/code&gt; route which removes the two Next.js Preview Mode cookies and redirects them back to the blog post's URL so that they will land on the published version of the post -- or hopefully a 404 if the content has never been published.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// api/preview-disable.tsx&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;NextApiRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;NextApiResponse&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;next&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Perform a server side redirect
 * https://nextjs.org/docs/basic-features/data-fetching#getserversideprops-server-side-rendering
 * https://nodejs.org/api/http.html#http_class_http_serverresponse
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;serverSideRedirect&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;ServerResponse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;destinationPath&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;statusCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;301&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;destinationPath&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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextApiRequest&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;NextApiResponse&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="c1"&gt;// Clears the preview mode cookies.&lt;/span&gt;
  &lt;span class="c1"&gt;// This function accepts no arguments.&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;clearPreviewData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;serverSideRedirect&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;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;referer&lt;/span&gt; &lt;span class="o"&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="mi"&gt;307&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;end&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;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BDe4SzJg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.zappy.app/4a4cf133e4f05a5f52bbc0d3cb3fa940.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BDe4SzJg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.zappy.app/4a4cf133e4f05a5f52bbc0d3cb3fa940.png" alt="Preview Mode Banner"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Dynamically choose the appropriate access token
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;When you request a page from a Next.js app that has &lt;code&gt;getStaticProps&lt;/code&gt; with the preview mode cookies set (via &lt;code&gt;res.setPreviewData&lt;/code&gt;), then &lt;code&gt;getStaticProps&lt;/code&gt; will be called at &lt;strong&gt;request time&lt;/strong&gt; (instead of at build time). WOWZA! Nifty hybrid, Next.js. High-five! &lt;/li&gt;
&lt;li&gt;Furthermore, it will be called with a &lt;code&gt;context&lt;/code&gt; object where &lt;code&gt;context.preview&lt;/code&gt; will be &lt;code&gt;true&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;You can then pass that preview boolean over to where your client is being created to specify which client to use. I'm using &lt;a href="https://formidable.com/open-source/urql/docs/"&gt;&lt;code&gt;urql&lt;/code&gt;&lt;/a&gt; (a blazingly fast, lightweight, and customizable GraphQL client) to make a &lt;code&gt;client&lt;/code&gt; AND a &lt;code&gt;previewClient&lt;/code&gt; and the value of that preview boolean will determine which client is used when we query Contentful.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&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;previewClient&lt;/span&gt; &lt;span class="o"&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;url&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;contentfulPreviewGraphQLUrl&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="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;createClient&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="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;contentfulGraphQLUrl&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;preview&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&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;preview&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;previewClient&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Query Contentful for preview data
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Now wherever in your code you're querying Contentful for that specific content, you'll need to pull that &lt;code&gt;preview&lt;/code&gt; boolean from the &lt;code&gt;context&lt;/code&gt; object and pass it along to the query so that Contentful knows whether or not to send drafted content along with the data.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blogArticleQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt;&lt;span class="s2"&gt;`
  query articleQuery($slug: String!, $preview: Boolean!) {
    article: blogArticleCollection(where: { slug: $slug }, preview: $preview) {
      ...
    }
  }
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;This will mean that if preview mode is off and &lt;code&gt;preview&lt;/code&gt; is false, the app will use the content delivery access token and URL. But if the &lt;code&gt;preview&lt;/code&gt; is true, it should use the content preview access token and URL and will send true along with the query to serve that preview/draft data!&lt;/li&gt;
&lt;/ul&gt;


 
&lt;h2&gt;
  
  
  The end!
&lt;/h2&gt;

&lt;p&gt;There you have it. That's how you give your content team the ability to preview their content! ✨ &lt;/p&gt;

&lt;p&gt;I realize this is a very heavy topic for such a short blog post, but I assure you Next.js &amp;amp; Contentful have incredible documentation on these processes. This article is intended to be a friendly little bridge between the two. When you start digging in, with the knowledge you have of your own app, I think you'll find it pretty exciting and fun to build! &lt;/p&gt;

&lt;p&gt;And of course, your Twitter dev community loves to share knowledge. Hit me up with questions and I'll see how I can help ya. ♥️ &lt;a href="https://twitter.com/the_real_stacie"&gt;@the_real_stacie&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer: don't try copy/paste with all this. It's totally picked apart to just hand over the basics. You'll want to understand what's happening in your code AND these codes snippets above well enough to know how it can fit into your masterpiece.&lt;/em&gt; &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>contentful</category>
      <category>nextjs</category>
      <category>ssg</category>
    </item>
  </channel>
</rss>
