<?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: Dustin Myers</title>
    <description>The latest articles on DEV Community by Dustin Myers (@dustinmyers).</description>
    <link>https://dev.to/dustinmyers</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%2F181585%2Fc229992e-0690-4069-9d10-0951deac0342.png</url>
      <title>DEV Community: Dustin Myers</title>
      <link>https://dev.to/dustinmyers</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dustinmyers"/>
    <language>en</language>
    <item>
      <title>The Frontend Developer Is Dead (And That’s Good)</title>
      <dc:creator>Dustin Myers</dc:creator>
      <pubDate>Wed, 25 Feb 2026 18:55:28 +0000</pubDate>
      <link>https://dev.to/dustinmyers/the-frontend-developer-is-dead-and-thats-good-1f43</link>
      <guid>https://dev.to/dustinmyers/the-frontend-developer-is-dead-and-thats-good-1f43</guid>
      <description>&lt;p&gt;In 2026, “frontend developer” doesn’t mean what it used to.&lt;/p&gt;

&lt;p&gt;And that’s a good thing.&lt;/p&gt;

&lt;p&gt;Over the past few years, AI has moved from novelty to daily workflow. It scaffolds components, writes tests, refactors functions, and explains unfamiliar codebases in seconds. What used to take hours now takes minutes.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If your definition of frontend engineering is “write components from a design file,” then yes — AI is coming for that role.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But the job isn’t disappearing.&lt;/p&gt;

&lt;p&gt;It’s evolving.&lt;/p&gt;

&lt;p&gt;And the engineers who understand that evolution are becoming more valuable, not less.&lt;/p&gt;




&lt;h2&gt;
  
  
  AI Has Already Changed the Nature of Coding Work
&lt;/h2&gt;

&lt;p&gt;We don’t have to speculate about AI’s impact — we have data.&lt;/p&gt;

&lt;p&gt;According to &lt;strong&gt;GitHub’s 2023 Copilot study&lt;/strong&gt;, developers using GitHub Copilot completed tasks &lt;strong&gt;up to 55% faster&lt;/strong&gt; than those who did not use it [1]. In follow-up research, GitHub reported that developers accept &lt;strong&gt;around 30–40% of AI-generated suggestions&lt;/strong&gt; in supported languages [2].&lt;/p&gt;

&lt;p&gt;Meanwhile, &lt;strong&gt;McKinsey (2023)&lt;/strong&gt; estimated that generative AI could automate &lt;strong&gt;20–45% of activities in software engineering&lt;/strong&gt;, particularly routine and boilerplate-heavy tasks [3].&lt;/p&gt;

&lt;p&gt;What does that include?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scaffolding UI components
&lt;/li&gt;
&lt;li&gt;Writing basic state management
&lt;/li&gt;
&lt;li&gt;Generating test stubs
&lt;/li&gt;
&lt;li&gt;Refactoring small functions
&lt;/li&gt;
&lt;li&gt;Translating design tokens to styles
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That work used to represent a large portion of frontend development.&lt;/p&gt;

&lt;p&gt;Today, it’s increasingly automated.&lt;/p&gt;

&lt;p&gt;But that was never the highest-leverage part of the job.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ykoimjn1fmsqbh8eatq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ykoimjn1fmsqbh8eatq.png" alt="half the image is an AI assembly line, the other half, a developer thinking about systems at a large board" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  AI Is Exceptional at Execution — Not at Judgment
&lt;/h2&gt;

&lt;p&gt;AI generates code.&lt;/p&gt;

&lt;p&gt;It does not own consequences.&lt;/p&gt;

&lt;p&gt;Multiple studies highlight this distinction:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stanford &amp;amp; MIT research (2023)&lt;/strong&gt; on AI-assisted productivity showed strong gains in execution speed, but also emphasized that human oversight remains essential for quality control and decision-making [4].
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gartner (2024)&lt;/strong&gt; projected that while AI will generate the majority of new application code by 2028, human engineers will still be required to define architecture, governance, and system constraints [5].&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI does not:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Negotiate tradeoffs between performance and velocity
&lt;/li&gt;
&lt;li&gt;Decide when abstraction is premature
&lt;/li&gt;
&lt;li&gt;Understand internal company politics
&lt;/li&gt;
&lt;li&gt;Anticipate long-term architectural debt
&lt;/li&gt;
&lt;li&gt;Translate ambiguous business requirements into sustainable systems
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It produces answers.&lt;/p&gt;

&lt;p&gt;It does not design systems.&lt;/p&gt;

&lt;p&gt;That distinction matters.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  The Shift: From Code Producer to Systems Thinker
&lt;/h2&gt;

&lt;p&gt;If AI lowers the barrier to execution, the bar for thinking goes up.&lt;/p&gt;

&lt;p&gt;The future-proof frontend engineer in 2026 excels at three things:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Designing Constraints
&lt;/h3&gt;

&lt;p&gt;Good systems are not just built — they are constrained.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Where does state live?&lt;/li&gt;
&lt;li&gt;What patterns are mandatory?&lt;/li&gt;
&lt;li&gt;What performance budget is enforced?&lt;/li&gt;
&lt;li&gt;What architectural decisions are irreversible?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI follows rules extremely well.&lt;/p&gt;

&lt;p&gt;Humans define them.&lt;/p&gt;

&lt;p&gt;In organizations adopting AI-assisted development, engineering leaders increasingly emphasize &lt;strong&gt;governance, architecture, and guardrails&lt;/strong&gt; as primary responsibilities for senior engineers [5].&lt;/p&gt;

&lt;p&gt;The more you define clear system boundaries, the more AI becomes a multiplier instead of a liability.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Translating Business Problems into Technical Leverage
&lt;/h3&gt;

&lt;p&gt;Founders and executives don’t care about hooks or styling strategies.&lt;/p&gt;

&lt;p&gt;They care about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Revenue
&lt;/li&gt;
&lt;li&gt;Speed to market
&lt;/li&gt;
&lt;li&gt;Reliability
&lt;/li&gt;
&lt;li&gt;Risk
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;According to the &lt;strong&gt;Stack Overflow Developer Survey (2024)&lt;/strong&gt;, over 70% of professional developers report using or planning to use AI tools, but many also report concerns about maintainability and correctness [6].&lt;/p&gt;

&lt;p&gt;That signals a shift:&lt;/p&gt;

&lt;p&gt;AI increases output.&lt;br&gt;
Senior engineers ensure that output aligns with business outcomes.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reducing API calls reduces infrastructure cost.&lt;/li&gt;
&lt;li&gt;Improving perceived load time increases conversion.&lt;/li&gt;
&lt;li&gt;Creating reusable primitives accelerates feature velocity.&lt;/li&gt;
&lt;li&gt;Instrumenting user behavior improves roadmap accuracy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s not “frontend implementation.”&lt;/p&gt;

&lt;p&gt;That’s business leverage.&lt;/p&gt;

&lt;p&gt;And leverage is hard to automate.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Directing AI Instead of Competing With It
&lt;/h3&gt;

&lt;p&gt;A 2023 MIT study on AI-augmented knowledge work found that high performers using AI increased their output significantly, while lower performers benefited even more — but only when guided appropriately [4].&lt;/p&gt;

&lt;p&gt;The implication is clear:&lt;/p&gt;

&lt;p&gt;The engineers who thrive are not the fastest typists.&lt;/p&gt;

&lt;p&gt;They are the best directors.&lt;/p&gt;

&lt;p&gt;They:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Structure context clearly
&lt;/li&gt;
&lt;li&gt;Define architectural constraints before prompting
&lt;/li&gt;
&lt;li&gt;Review AI output for long-term system health
&lt;/li&gt;
&lt;li&gt;Eliminate low-leverage work through automation
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI is not your competition.&lt;/p&gt;

&lt;p&gt;It is your force multiplier.&lt;/p&gt;

&lt;p&gt;But only if your thinking operates above the level of code generation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu5hp80wywact40jvdpha.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu5hp80wywact40jvdpha.png" alt="Group of tech professionals in a conference room, frontend engineer presenting" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Identity Shift for Frontend Engineers
&lt;/h2&gt;

&lt;p&gt;There is understandable anxiety in the industry.&lt;/p&gt;

&lt;p&gt;“Will AI make my role obsolete?”&lt;/p&gt;

&lt;p&gt;History suggests otherwise.&lt;/p&gt;

&lt;p&gt;Automation rarely eliminates entire professions; it transforms them. The World Economic Forum’s &lt;strong&gt;Future of Jobs Report (2023)&lt;/strong&gt; predicts both displacement and significant job creation as roles evolve toward higher-order skills [7].&lt;/p&gt;

&lt;p&gt;Frontend engineering is experiencing exactly that.&lt;/p&gt;

&lt;p&gt;Framework knowledge alone is no longer a moat.&lt;/p&gt;

&lt;p&gt;Your value is not:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React&lt;/li&gt;
&lt;li&gt;Vue&lt;/li&gt;
&lt;li&gt;Svelte&lt;/li&gt;
&lt;li&gt;Tailwind&lt;/li&gt;
&lt;li&gt;Any specific tool&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your value is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Decision-making under constraint
&lt;/li&gt;
&lt;li&gt;Translating ambiguity into clarity
&lt;/li&gt;
&lt;li&gt;Designing maintainable systems
&lt;/li&gt;
&lt;li&gt;Reducing long-term complexity
&lt;/li&gt;
&lt;li&gt;Increasing business leverage
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The framework changes.&lt;/p&gt;

&lt;p&gt;Leverage does not.&lt;/p&gt;




&lt;h2&gt;
  
  
  What This Means for Mid-Level Engineers
&lt;/h2&gt;

&lt;p&gt;This is actually good news.&lt;/p&gt;

&lt;p&gt;AI lowers the barrier to execution.&lt;/p&gt;

&lt;p&gt;That means you can spend more time learning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;System design principles
&lt;/li&gt;
&lt;li&gt;Performance tradeoffs
&lt;/li&gt;
&lt;li&gt;Data flow architecture
&lt;/li&gt;
&lt;li&gt;Observability and instrumentation
&lt;/li&gt;
&lt;li&gt;Business impact modeling
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If AI handles 30–40% of repetitive code generation [2], you can redirect that time toward architectural growth.&lt;/p&gt;

&lt;p&gt;That’s a faster path to seniority — if you use it intentionally.&lt;/p&gt;




&lt;h2&gt;
  
  
  What This Means for Engineering Leaders
&lt;/h2&gt;

&lt;p&gt;AI is redefining what “senior” means.&lt;/p&gt;

&lt;p&gt;Gartner predicts that by 2028, &lt;strong&gt;75% of enterprise software engineers will use AI code assistants daily&lt;/strong&gt; [5].&lt;/p&gt;

&lt;p&gt;When that happens, evaluation criteria change.&lt;/p&gt;

&lt;p&gt;Senior engineers will be the ones who:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Define system boundaries AI can safely operate within
&lt;/li&gt;
&lt;li&gt;Protect long-term maintainability
&lt;/li&gt;
&lt;li&gt;Improve velocity through tooling
&lt;/li&gt;
&lt;li&gt;Elevate conversations to product and business impact
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Typing speed is no longer a differentiator.&lt;/p&gt;

&lt;p&gt;Judgment is.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  The Frontend Developer Isn’t Dead. The Old Definition Is.
&lt;/h2&gt;

&lt;p&gt;The market doesn’t need more component assemblers.&lt;/p&gt;

&lt;p&gt;It needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Systems thinkers
&lt;/li&gt;
&lt;li&gt;Product-aware engineers
&lt;/li&gt;
&lt;li&gt;Constraint designers
&lt;/li&gt;
&lt;li&gt;AI-native leaders
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The good news?&lt;/p&gt;

&lt;p&gt;That work is more strategic.&lt;br&gt;
More creative.&lt;br&gt;
And significantly harder to replace.&lt;/p&gt;

&lt;p&gt;If AI can generate your components, good.&lt;/p&gt;

&lt;p&gt;Now you’re free to design the system.&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;GitHub. &lt;em&gt;Research: Quantifying GitHub Copilot’s Impact on Developer Productivity and Happiness&lt;/em&gt;, 2023.
&lt;/li&gt;
&lt;li&gt;GitHub. &lt;em&gt;The State of AI in Software Development&lt;/em&gt;, 2023–2024 reports.
&lt;/li&gt;
&lt;li&gt;McKinsey &amp;amp; Company. &lt;em&gt;The Economic Potential of Generative AI&lt;/em&gt;, 2023.
&lt;/li&gt;
&lt;li&gt;Brynjolfsson, E., Li, D., Raymond, L. &lt;em&gt;Generative AI at Work&lt;/em&gt;, Stanford &amp;amp; MIT, 2023.
&lt;/li&gt;
&lt;li&gt;Gartner. &lt;em&gt;Top Strategic Technology Trends and AI in Software Engineering Forecasts&lt;/em&gt;, 2024.
&lt;/li&gt;
&lt;li&gt;Stack Overflow. &lt;em&gt;Developer Survey 2024&lt;/em&gt;.
&lt;/li&gt;
&lt;li&gt;World Economic Forum. &lt;em&gt;Future of Jobs Report 2023&lt;/em&gt;.
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>frontend</category>
      <category>ai</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>What Even Is A Dispatch Function?</title>
      <dc:creator>Dustin Myers</dc:creator>
      <pubDate>Sat, 15 Feb 2020 16:02:23 +0000</pubDate>
      <link>https://dev.to/dustinmyers/what-even-is-a-dispatch-function-27ma</link>
      <guid>https://dev.to/dustinmyers/what-even-is-a-dispatch-function-27ma</guid>
      <description>&lt;p&gt;Learning redux? Or &lt;code&gt;useReducer&lt;/code&gt;? Then chances are you've been frustrated by the black magic that is the &lt;code&gt;dispatch&lt;/code&gt; function 🧙‍♂️! Well, luckily you have found this post. I will help you understand what happens under-the-hood and remove the mystery behind &lt;code&gt;dispatch&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1551269901-5c5e14c25df7%3Fixlib%3Drb-1.2.1%26q%3D85%26fm%3Djpg%26crop%3Dentropy%26cs%3Dsrgb" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1551269901-5c5e14c25df7%3Fixlib%3Drb-1.2.1%26q%3D85%26fm%3Djpg%26crop%3Dentropy%26cs%3Dsrgb" alt="https://images.unsplash.com/photo-1551269901-5c5e14c25df7?ixlib=rb-1.2.1&amp;amp;q=85&amp;amp;fm=jpg&amp;amp;crop=entropy&amp;amp;cs=srgb" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What makes dispatch so hard?
&lt;/h2&gt;

&lt;p&gt;There are a couple of reasons that learning Redux or the reducer hooks can be confusing. &lt;/p&gt;

&lt;p&gt;First - both flows rely on a programming paradigm called "functional programming". Thinking in this way requires you to switch your mental model of how to manage data in your application. &lt;em&gt;For more on functional programming, read the first half of this article - &lt;a href="https://blog.bitsrc.io/functional-programming-in-javascript-how-and-why-94e7a97343b" rel="noopener noreferrer"&gt;Functional Programming in JavaScript: How and Why&lt;/a&gt;&lt;/em&gt;. The basic idea here that makes these patterns hard is that data is flowing from function to function, and often changes shape a little (or even a lot 😬) before your state is updated and the component re-renders.&lt;/p&gt;

&lt;p&gt;Second - both flows "abstract" some of the logic into different functions. Think about it. If you're using Redux, you call an action creator function and &lt;strong&gt;POOF&lt;/strong&gt;... a reducer is called and &lt;code&gt;state&lt;/code&gt; and an &lt;code&gt;action object&lt;/code&gt; are passed in. Like, what the heck?!? 😡 The reducer hook flow has one less layer of abstraction, but there is still some there that adds to the confusion. &lt;/p&gt;

&lt;h2&gt;
  
  
  Rebuilding dispatch
&lt;/h2&gt;

&lt;p&gt;I think looking at how the dispatch function is built really helps remove the mystery behind reducers. So let's build a simple implementation of dispatch to see the logic that is abstracted out of our view. We start with the function definition.&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;function&lt;/span&gt; &lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wooooo 🎉! We're doing great so far 😁. Next step, we will add &lt;code&gt;action&lt;/code&gt; as a parameter for the function.&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;function&lt;/span&gt; &lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, with this, we know that when the dispatch function is called, it will be passed an action object as an argument. If you're using &lt;code&gt;useReducer&lt;/code&gt; or &lt;code&gt;useDispatch&lt;/code&gt;, you already know this. Upon some kind of event occurring in the UI, &lt;em&gt;you&lt;/em&gt;, not the Redux library, call the dispatch function like this: &lt;code&gt;dispatch({ type: 'ACTION_TYPE' })&lt;/code&gt;. If you're using Redux and the &lt;code&gt;connect&lt;/code&gt; function, even that part is abstracted away from your view and it’s the Redux library that calls the dispatch function. We’ll talk more on that towards the end. Let's continue though.&lt;/p&gt;

&lt;p&gt;Now we need to do a couple of checks. We need to make sure that the action object that is passed in is an object, and that it has a &lt;code&gt;type&lt;/code&gt; property. If either of those is not true, we will throw an error. When a reducer function is written, it assumes that those are both true.&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;function&lt;/span&gt; &lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// check that the action argument is an object&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;actions must be plain object.&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="c1"&gt;// check that the action object has a 'type' property&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;undefined&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Actions may not have an undefined "type" property.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Good. Now we can build our reducers with confidence knowing that any action that is dispatched will be an object and will have a "type" property.&lt;/p&gt;

&lt;p&gt;Now the exciting part! The next thing we will do is call the reducer &lt;em&gt;from within the dispatch function&lt;/em&gt;. This is the abstraction part that hides from our view of what is happening behind-the-scenes. There are a couple of points that we need to cover before we can write this though. &lt;/p&gt;

&lt;p&gt;The dispatch function is in the same scope as the current state of the app. So that means that inside the dispatch function, we have access to an object called &lt;code&gt;currentState&lt;/code&gt; that &lt;em&gt;is&lt;/em&gt; the current state in our app.&lt;/p&gt;

&lt;p&gt;In that same scope is the reducer function that we have written and passed into &lt;code&gt;createStore&lt;/code&gt; or &lt;code&gt;useReducer&lt;/code&gt;. So the dispatch function also has access to &lt;code&gt;reducer&lt;/code&gt; - our reducer function (no matter what we called it) that we passed in. That means that the dispatch function can invoke the reducer function.&lt;/p&gt;

&lt;p&gt;Here’s a very simplified version of what that looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="c1"&gt;// 😮 yep, it’s createStore! But that’s for another article… &lt;/span&gt;

  &lt;span class="c1"&gt;// state will be initialized then stored here&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

  &lt;span class="c1"&gt;// your reducer, or combined reducers, will be accessible here&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reducer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// dispatch function in the same scope will have access to the most current state and your reducer(s)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&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;// … all the codes&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🤯 I know, I know… really cool to see what it looks like under-the-hood, right? Functions and objects. Welcome to functional programming in JavaScript! Once you see it written out like this, it starts to come together! But there is still just a little more to explore.&lt;/p&gt;

&lt;p&gt;Let's think about everything that we've learned so far and combine that new knowledge with what we know about reducers. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;dispatch&lt;/code&gt; has access to &lt;code&gt;currentState&lt;/code&gt; and &lt;code&gt;reducer&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;When &lt;code&gt;dispatch&lt;/code&gt; is called, it receives an action object as an argument. &lt;/li&gt;
&lt;li&gt;A reducer function, when invoked, is passed two arguments - &lt;code&gt;state&lt;/code&gt; (meaning the current state) and &lt;code&gt;action&lt;/code&gt;. 
See where I'm going with this? &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inside &lt;code&gt;dispatch&lt;/code&gt; we will now call &lt;code&gt;reducer&lt;/code&gt; and pass in &lt;code&gt;currentState&lt;/code&gt; and the &lt;code&gt;action&lt;/code&gt; object.&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;function&lt;/span&gt; &lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// check that the action argument is an object&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;actions must be plain object.&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="c1"&gt;// check that the action object has a 'type' property&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;undefined&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Actions may not have an undefined "type" property.&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="c1"&gt;// call the reducer and pass in currentState and action&lt;/span&gt;
  &lt;span class="c1"&gt;// reducer and currentState are within scope, action is the parameter passed into the function&lt;/span&gt;
  &lt;span class="nf"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&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;Look at that closely... when an action is dispatched, or in other words, when we invoke &lt;code&gt;dispatch&lt;/code&gt; and pass in an action object, the &lt;code&gt;dispatch&lt;/code&gt; function calls our reducer and passes in the current state and the action object! 🤩 It's all starting to make sense!&lt;/p&gt;

&lt;p&gt;Well, there's one last part to this - updating the state. Think about how you write a reducer function. What does it return? It returns a new state object, right? You've followed immutable principles to return a &lt;em&gt;copy&lt;/em&gt; of the old state, updated with new data based on whichever action you had dispatched. So when the &lt;code&gt;dispatch&lt;/code&gt; function does this - &lt;code&gt;reducer(currentState, action);&lt;/code&gt; - that function call is going to return a brand new state object. Our dispatch function here needs to update currentState with the new state object that is returned by calling the reducer.&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;function&lt;/span&gt; &lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// check that the action argument is an object&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;actions must be plain object.&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="c1"&gt;// check that the action object has a 'type' property&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;undefined&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Actions may not have an undefined "type" property.&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="c1"&gt;// call the reducer and pass in currentState and action&lt;/span&gt;
  &lt;span class="c1"&gt;// capture the new state object in currentState, thus updating the state&lt;/span&gt;
  &lt;span class="nx"&gt;currentState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&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;And voila! We have built a simple implementation of the &lt;code&gt;dispatch&lt;/code&gt; function. Now, of course, there is more to this in the actual implementations. In Redux, &lt;code&gt;dispatch&lt;/code&gt; needs to tell the app that the state has been updated. This happens through listeners and subscriptions. In the &lt;code&gt;useReducer&lt;/code&gt; hook, React recognizes that the state was updated and re-renders the component. The updated state is then returned to the component from where the &lt;code&gt;useReducer&lt;/code&gt; hook was called.&lt;/p&gt;

&lt;p&gt;Regardless of the extra implementations, building out the &lt;code&gt;dispatch&lt;/code&gt; function here will really help us understand what is happening under-the-hood when we call &lt;code&gt;dispatch&lt;/code&gt; from our components.&lt;/p&gt;

&lt;h2&gt;
  
  
  Redux and action creators
&lt;/h2&gt;

&lt;p&gt;If you're using Redux and &lt;code&gt;connect&lt;/code&gt;, there is one more layer of abstraction to explore. With the &lt;code&gt;connect&lt;/code&gt; function, you pass action creators into an object in the &lt;code&gt;connect&lt;/code&gt; function. The action creators are then passed to the component via props. In your component, when you call the action creator, it will call dispatch for you. That's the added layer of abstraction. Let's look at what &lt;code&gt;connect&lt;/code&gt; does under-the-hood (again in a simplified version).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// inside the connect function implementation&lt;/span&gt;
&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;actionCreator&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, &lt;code&gt;connect&lt;/code&gt; wraps the &lt;code&gt;dispatch&lt;/code&gt; function &lt;em&gt;around&lt;/em&gt; the action creator call. When the action creator is invoked, it returns an action. So the above evaluates down to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ACTION_TYPE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which we now understand will call the reducer! Wooo! 🚀&lt;/p&gt;

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

&lt;p&gt;Hopefully, this helps remove the black magic of reducers and dispatch! If you think through the logic flow, you will realize that this is all about functions calling functions and passing data around. And now that the black magic of Redux has been removed a bit, you can get back to the fun part of building web apps with React and Redux ⚛️!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>redux</category>
      <category>usereducer</category>
    </item>
    <item>
      <title>Using The Request Body With Serverless Functions</title>
      <dc:creator>Dustin Myers</dc:creator>
      <pubDate>Sun, 09 Feb 2020 01:10:14 +0000</pubDate>
      <link>https://dev.to/dustinmyers/using-the-request-body-with-serverless-functions-220a</link>
      <guid>https://dev.to/dustinmyers/using-the-request-body-with-serverless-functions-220a</guid>
      <description>&lt;p&gt;Harnessing the request body within serverless functions really expands what we can do with our apps.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1431440869543-efaf3388c585%3Fixlib%3Drb-1.2.1%26q%3D85%26fm%3Djpg%26crop%3Dentropy%26cs%3Dsrgb" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1431440869543-efaf3388c585%3Fixlib%3Drb-1.2.1%26q%3D85%26fm%3Djpg%26crop%3Dentropy%26cs%3Dsrgb" alt="https://images.unsplash.com/photo-1431440869543-efaf3388c585?ixlib=rb-1.2.1&amp;amp;q=85&amp;amp;fm=jpg&amp;amp;crop=entropy&amp;amp;cs=srgb" width="760" height="506"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Greater Power
&lt;/h2&gt;

&lt;p&gt;So far we have seen the most basic setup for serverless functions - returning a set of hardcoded data. In this tutorial, we will look at what we can do with serverless functions to create a more complicated application.&lt;/p&gt;

&lt;p&gt;We will be using the Star Wars API (&lt;a href="https://swapi.py4e.com/" rel="noopener noreferrer"&gt;SWAPI&lt;/a&gt;) to build a multi-page application that will display a list of Star Wars characters, let your user click on the character to open the character page. We will use serverless functions for two purposes here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Avoid any CORS issues&lt;/li&gt;
&lt;li&gt;Add character images to the data provided by SWAPI, since the data does not include images&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We will need to harness the power of the serverless functions request body as built by Zeit to achieve these lofty goals. Let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Hosting On Zeit
&lt;/h2&gt;

&lt;p&gt;The starting code for this tutorial is in this &lt;a href="https://github.com/dustinmyers/star-wars-serverless" rel="noopener noreferrer"&gt;repo here&lt;/a&gt; and the deployed instance &lt;a href="//star-wars-serverless.now.sh"&gt;here&lt;/a&gt;. You will need to fork it so you can connect it to a Zeit project. Go ahead and fork it now, then clone the repository to your own machine. From there, use the &lt;code&gt;now cli&lt;/code&gt; (&lt;a href="https://zeit.co/download" rel="noopener noreferrer"&gt;download instructions&lt;/a&gt;) to deploy the app to Zeit. This will create a new project on Zeit and deploy it for you.&lt;/p&gt;

&lt;p&gt;This app is built with Zeit's Next.js template. This will allow us to open a dev environment on our own machines for testing and debugging our serverless functions, while still giving us the full Zeit workflow and continuous development environment.&lt;/p&gt;

&lt;p&gt;After you have cloned the repo, install the dependencies with &lt;code&gt;yarn&lt;/code&gt;. Then fire up the app with &lt;code&gt;yarn run dev&lt;/code&gt;. This gives you a link you can open up in your browser. You can now use the browser for debugging the Next.js app, and the terminal for debugging your serverless functions. &lt;/p&gt;

&lt;h2&gt;
  
  
  Refactoring To Use Serverless Functions
&lt;/h2&gt;

&lt;p&gt;Right now, the app works to display the list of characters, but it is just making the fetch request to SWAPI in the component. Take a look at &lt;code&gt;/pages/index.js&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you are unfamiliar with data fetching in a Next.js app, check out their &lt;a href="https://nextjs.org/docs/basic-features/data-fetching" rel="noopener noreferrer"&gt;docs&lt;/a&gt; on the subject. We are following those patterns in this app.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Instead of the component calling SWAPI,  we want to make a request from the app to a serverless function and have the serverless function make the request to SWAPI for us. This will allow us to achieve the two things listed above.&lt;/p&gt;

&lt;p&gt;Let's go ahead and refactor this to use a serverless function.&lt;/p&gt;

&lt;h3&gt;
  
  
  File structure
&lt;/h3&gt;

&lt;p&gt;/pages/&lt;strong&gt;api directory&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;To start out, add an &lt;code&gt;/api&lt;/code&gt; directory inside the &lt;code&gt;/pages&lt;/code&gt; directory. Zeit will use this directory to build and host the serverless functions in the cloud. Each file in this directory will be a single serverless function and will be the endpoint that the app can use to make HTTP requests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;get-character-list.js&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now inside &lt;code&gt;/pages/api&lt;/code&gt; add a new file called &lt;code&gt;get-character-list.js&lt;/code&gt;. Remember adding API files in the last tutorial? Just like that, we can send HTTP requests to the serverless function that will be housed in this file using the endpoint &lt;code&gt;"/api/get-character-list"&lt;/code&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  The serverless function
&lt;/h3&gt;

&lt;p&gt;Now let's build the &lt;code&gt;get-character-list&lt;/code&gt; function. The function will start out like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="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;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside this function is where we want to fetch the data for the star wars characters. Then we will return the array of characters to the client.&lt;/p&gt;

&lt;p&gt;I have set up a &lt;code&gt;fetchCharacters&lt;/code&gt; function outside of the default function. I call that from the default function and then use the &lt;code&gt;res&lt;/code&gt; object to return the character data. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note that we are using "node-fetch" here to give us our wonderful &lt;code&gt;fetch&lt;/code&gt; syntax as this is a node function.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&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;node-fetch&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;fetchCharacters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://swapi.py4e.com/api/people/&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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;results&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="k"&gt;async &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;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&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;characters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchCharacters&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="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;characters&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;error&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="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside the serverless function, let's add a couple of console.logs so you can see the function at work within your terminal.&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;fetch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&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;node-fetch&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;fetchCharacters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://swapi.py4e.com/api/people/&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// ADD ONE HERE&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&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;results&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="k"&gt;async &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;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&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;characters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchCharacters&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// ADD ONE HERE&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;characters&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="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;characters&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;error&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="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you have a chance to watch those logs happen, go ahead and remove them, then move on to the next step.&lt;/p&gt;

&lt;h3&gt;
  
  
  Updating the Next.js app
&lt;/h3&gt;

&lt;p&gt;Now that we have our serverless function in place, let's update the call that is happening in &lt;code&gt;/pages/index.js&lt;/code&gt;. We need to change the path we provided to &lt;code&gt;useSWR&lt;/code&gt; to our serverless function endpoint - &lt;code&gt;"/api/get-character-list"&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Notice though, that our serverless function is changing the object that will be sent to our app. Inside the effect hook that is setting the data to state, we need to update that as well to expect an object with a &lt;code&gt;characters&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We're getting our data through the serverless function! 😁🎉🔥&lt;/strong&gt;&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Adding thumbnail images
&lt;/h3&gt;

&lt;p&gt;The final step for our list page is to add thumbnail images to the data before our serverless function returns the characters to the app. I have collected images for you. You're welcome!&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const images = [
  "https://boundingintocomics.com/files/2019/05/2019.05.15-06.10-boundingintocomics-5cdc56295fdf4.png",
  "https://img.cinemablend.com/filter:scale/quill/7/e/9/b/6/f/7e9b6f625b1f06b8c70fe19107bf62bc0f44b6eb.jpg?mw=600",
  "https://www.sideshow.com/storage/product-images/2172/r2-d2-deluxe_star-wars_feature.jpg",
  "https://s.yimg.com/ny/api/res/1.2/soTg5zMneth9YIQz0ae_cw--~A/YXBwaWQ9aGlnaGxhbmRlcjtzbT0xO3c9ODAw/https://images.fatherly.com/wp-content/uploads/2018/12/darthvader-header.jpg?q=65&amp;amp;amp;enable=upscale&amp;amp;amp;w=1200",
  "https://www2.pictures.zimbio.com/mp/oHGHV7BhCfvl.jpg",
  "https://i.ytimg.com/vi/5UW1PIplmlc/maxresdefault.jpg",
  "https://pm1.narvii.com/6293/db859b249381c30a6be8f8242046105e552cd54d_00.jpg",
  "https://lumiere-a.akamaihd.net/v1/images/r5-d4_main_image_7d5f078e.jpeg?region=374%2C0%2C1186%2C666&amp;amp;width=960",
  "https://lumiere-a.akamaihd.net/v1/images/image_606ff7f7.jpeg?region=0%2C0%2C1560%2C878&amp;amp;width=960",
  "https://s.abcnews.com/images/Entertainment/ht_alec_guinness_obi_wan_kenobi_star_wars_jc_160415_16x9_992.jpg"
];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Add this array to your serverless function file, then add a &lt;code&gt;.map()&lt;/code&gt; to add these images to the data before you send it back.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&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;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchCharacters&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="c1"&gt;// Map over chatacters to add the thumbnail image&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;characters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;character&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;character&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;thumbnail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;images&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="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="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;characters&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;error&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="nf"&gt;log&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="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check out the results!&lt;/p&gt;

&lt;h2&gt;
  
  
  Using The Request Object
&lt;/h2&gt;

&lt;p&gt;Now we will build out the character page. You may have noticed that clicking on a character card navigates you to a character page. The character page URL has a dynamic param &lt;code&gt;/:id&lt;/code&gt;. In the &lt;code&gt;/pages/Character/[id].js&lt;/code&gt; file we are using Next.js' &lt;code&gt;useRouter&lt;/code&gt; hook to get the id param from the URL. &lt;/p&gt;

&lt;p&gt;We want to make a request to another serverless function which will fetch the character data for us. That function will take in the id of the character we clicked on via query parameters.&lt;/p&gt;

&lt;h3&gt;
  
  
  The serverless function file/endpoint
&lt;/h3&gt;

&lt;p&gt;The file structure here will be the same as we've seen thus far. So go ahead and set up a file called &lt;code&gt;/pages/api/get-character-by-id.js&lt;/code&gt;. Add a serverless function there. Just have it return some dummy data, like &lt;code&gt;{ message: 'hello' }&lt;/code&gt; for now. Next add the same &lt;code&gt;useSWR&lt;/code&gt; and &lt;code&gt;fetcher&lt;/code&gt; functions to &lt;code&gt;[id].js&lt;/code&gt;. Make a request to the new function to make sure it's working.&lt;/p&gt;

&lt;p&gt;Once you see the request happen (you can check it in the network tab in your browser) we can build in the query param and make a request to SWAPI for the character's data.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Query Param
&lt;/h3&gt;

&lt;p&gt;The request URL from the page will add a query param for the id. Our endpoint will change to this -&lt;code&gt;/api/get-character-by-id?id=${id}&lt;/code&gt;. Then we can grab the id in the serverless function like this - &lt;code&gt;const { id } = req.query&lt;/code&gt;. Easy peasy! &lt;/p&gt;

&lt;h3&gt;
  
  
  Your turn
&lt;/h3&gt;

&lt;p&gt;Using what you've built so far, and what we just learned about the query param, build out the HTTP request in your component to make a request with the query param. In your serverless function, grab that param from the &lt;code&gt;req&lt;/code&gt; object and fetch the data you need from SWAPI, adding the id to the end of the URL (e.g. for Luke Skywalker, your request URL to SWAPI should be &lt;a href="https://swapi.py4e.com/api/people/" rel="noopener noreferrer"&gt;&lt;code&gt;https://swapi.py4e.com/api/people/1&lt;/code&gt;&lt;/a&gt;). When the data returns, add the correct image to the object and return the data to your app. Finally, build out your component as a character page to display the character data.&lt;/p&gt;

&lt;p&gt;Go ahead, get working on that. I'll wait! When you're done, scroll down to see my implementation.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;Great job! Aren't serverless functions awesome! Here is how I implemented everything for this page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// get-character-by-id.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&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;node-fetch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// probably should move this to a util file now and just import it :)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://boundingintocomics.com/files/2019/05/2019.05.15-06.10-boundingintocomics-5cdc56295fdf4.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://img.cinemablend.com/filter:scale/quill/7/e/9/b/6/f/7e9b6f625b1f06b8c70fe19107bf62bc0f44b6eb.jpg?mw=600&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://www.sideshow.com/storage/product-images/2172/r2-d2-deluxe_star-wars_feature.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://s.yimg.com/ny/api/res/1.2/soTg5zMneth9YIQz0ae_cw--~A/YXBwaWQ9aGlnaGxhbmRlcjtzbT0xO3c9ODAw/https://images.fatherly.com/wp-content/uploads/2018/12/darthvader-header.jpg?q=65&amp;amp;amp;enable=upscale&amp;amp;amp;w=1200&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://www2.pictures.zimbio.com/mp/oHGHV7BhCfvl.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://i.ytimg.com/vi/5UW1PIplmlc/maxresdefault.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://pm1.narvii.com/6293/db859b249381c30a6be8f8242046105e552cd54d_00.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://lumiere-a.akamaihd.net/v1/images/r5-d4_main_image_7d5f078e.jpeg?region=374%2C0%2C1186%2C666&amp;amp;width=960&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://lumiere-a.akamaihd.net/v1/images/image_606ff7f7.jpeg?region=0%2C0%2C1560%2C878&amp;amp;width=960&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://s.abcnews.com/images/Entertainment/ht_alec_guinness_obi_wan_kenobi_star_wars_jc_160415_16x9_992.jpg&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;fetchCharacter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://swapi.py4e.com/api/people/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="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="c1"&gt;// Make sure that id is present&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;id&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="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;No id sent - add a query param for the id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// fetch the character data and add the image to it&lt;/span&gt;
  &lt;span class="k"&gt;try&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;character&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchCharacter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="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="nx"&gt;character&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;thumbnail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;images&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;character&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;error&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="nf"&gt;log&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="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;error&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// [id].js&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useRouter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next/router&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unfetch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;useSWR&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;swr&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Character.module.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetcher&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&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;json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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;json&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;Character&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="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;character&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCharacter&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRouter&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;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;router&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="c1"&gt;// fetch data using SWR&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;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSWR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/get-character-by-id?id=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetcher&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setCharacter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;character&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="c1"&gt;// render loading message if no data yet&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;character&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Fetching character data...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"App"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;article&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;characterPage&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;character&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;thumbnail&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;character&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;character&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;article&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Character&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;There we have it! I did not add much to the character page here so that the code block would be somewhat short. But hopefully, you have built it out to display all of the character's cool data! Drop a link to your hosted site in the comments when you finish! Final code can be found in &lt;a href="https://github.com/dustinmyers/star-wars-serverless/tree/solution" rel="noopener noreferrer"&gt;here&lt;/a&gt; and the final deployment &lt;a href="//star-wars-serverless-git-solution.dustint314.now.sh"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>serverless</category>
      <category>nextjs</category>
      <category>react</category>
      <category>zeit</category>
    </item>
    <item>
      <title>Hello World with Serverless Functions</title>
      <dc:creator>Dustin Myers</dc:creator>
      <pubDate>Fri, 07 Feb 2020 04:47:27 +0000</pubDate>
      <link>https://dev.to/dustinmyers/hello-world-with-serverless-functions-46mk</link>
      <guid>https://dev.to/dustinmyers/hello-world-with-serverless-functions-46mk</guid>
      <description>&lt;p&gt;Technologies used in this post:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React&lt;/li&gt;
&lt;li&gt;Next.js&lt;/li&gt;
&lt;li&gt;Node Serverless Functions&lt;/li&gt;
&lt;li&gt;Zeit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This post assumes a basic knowledge of React, Next.js, and Node. However, if you have no knowledge of Next.js, that is okay. If you know React, you can still follow along here. Just recognize that the file structure will be different, and there are &lt;em&gt;small&lt;/em&gt; differences in the component files. That is another topic for another day, however 😁.&lt;/p&gt;

&lt;h2&gt;
  
  
  All About Workflows
&lt;/h2&gt;

&lt;p&gt;Zeit's platform is focused on building workflows for the everyday developer. They provide a production-ready, continuous development platform for anyone from brand new devs, to hobbyists, all the way to Enterprise companies like Hulu.&lt;/p&gt;

&lt;p&gt;Starting a React project using Next.js and spinning up serverless node functions is incredibly simple. It truly is an amazing world we live in!&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting a Next.js Project
&lt;/h2&gt;

&lt;p&gt;As Zeit is all about workflows, they have made it so simple to begin a new project. To follow the tutorial here, you'll need to set up a new account on their website, &lt;a href="https://zeit.co" rel="noopener noreferrer"&gt;zeit.co&lt;/a&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 - Choose a template
&lt;/h3&gt;

&lt;p&gt;Once you are logged in, and in the dashboard, you will see a &lt;code&gt;New Project&lt;/code&gt; button at the top right. Click that button, then scroll down to the "From a template" section. The Next.js template is the first on the list of templates here.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftk-assets.lambdaschool.com%2F06040209-a03e-43ba-8054-9164df41d5f8_ScreenShot2020-02-06at11.09.28AM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftk-assets.lambdaschool.com%2F06040209-a03e-43ba-8054-9164df41d5f8_ScreenShot2020-02-06at11.09.28AM.png" alt="List of templates" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on that template to navigate to the configuration page. &lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 - Name your project
&lt;/h3&gt;

&lt;p&gt;Here you will be able to name your project and also see a live example of the web app that is created with this template.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftk-assets.lambdaschool.com%2Ff51c05b7-7af4-4043-9a4c-62c79cf98b69_ScreenShot2020-02-06at11.12.23AM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftk-assets.lambdaschool.com%2Ff51c05b7-7af4-4043-9a4c-62c79cf98b69_ScreenShot2020-02-06at11.12.23AM.png" alt="tamplate overiew and creation page" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After giving your new project a name, click &lt;code&gt;Continue&lt;/code&gt; to move to the last step in the creation process. &lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3 - Create a repo and deploy
&lt;/h3&gt;

&lt;p&gt;The card in the UI now lets you create a Git repository, name the repository, and make it private if you wish. You will want to make a repo for this tutorial so you can clone the project onto your computer and work on it alongside me.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Also note that you should keep the name of the repo the same as the Zeit project.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Go ahead and hit &lt;code&gt;Deploy&lt;/code&gt;!&lt;/p&gt;

&lt;h3&gt;
  
  
  What is happening?
&lt;/h3&gt;

&lt;p&gt;Behind the scenes here, Zeit will set up a modern React application powered by Next.js, add the repository to your GitHub account, and deploy the project on the Zeit platform. After clicking &lt;code&gt;Deploy&lt;/code&gt; you will be navigated to your project's deployment page, where you can watch the progress of the build and deployment.&lt;/p&gt;

&lt;p&gt;After the project is deployed, you'll be able to view the deployment overview by clicking the URL under the "Deployment" header. Also, if you click on the preview image, a new tab will be opened where you can view the web app itself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftk-assets.lambdaschool.com%2Fdb868a07-6ba9-4a4c-9d3a-5815155a1a53_ScreenShot2020-02-06at11.37.03AM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftk-assets.lambdaschool.com%2Fdb868a07-6ba9-4a4c-9d3a-5815155a1a53_ScreenShot2020-02-06at11.37.03AM.png" alt="Deployment overview page" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this point, go to your repository and clone the project onto your machine. Then you'll be ready to add your first serverless function!&lt;/p&gt;

&lt;h2&gt;
  
  
  Serverless Functions
&lt;/h2&gt;

&lt;p&gt;According to Zeit's &lt;a href="https://zeit.co/docs/v2/serverless-functions/introduction" rel="noopener noreferrer"&gt;docs&lt;/a&gt;, serverless functions "are pieces of code written with backend languages that take an HTTP request and provide a response". Let's look at our project and find the serverless function that was built out already that the React app consumes to get a current timestamp. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftk-assets.lambdaschool.com%2F2a9e8405-7b6a-4dac-a092-1148ba3365c1_ScreenShot2020-02-06at11.43.41AM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftk-assets.lambdaschool.com%2F2a9e8405-7b6a-4dac-a092-1148ba3365c1_ScreenShot2020-02-06at11.43.41AM.png" alt="image of web app with arrow pointing to timestamp and text saying this was fetched from a serverless function" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In your project, you will see a &lt;code&gt;/pages&lt;/code&gt; directory, and inside that, an &lt;code&gt;/api&lt;/code&gt; directory. Go ahead and open &lt;code&gt;date.js&lt;/code&gt; that is found in &lt;code&gt;/api&lt;/code&gt;. Here is your first glimpse at a serverless function!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftk-assets.lambdaschool.com%2Fa71273ec-cdd2-4c7f-a4a8-bb5f800fdd97_serverless.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftk-assets.lambdaschool.com%2Fa71273ec-cdd2-4c7f-a4a8-bb5f800fdd97_serverless.png" alt="serverless function code" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is just a node function that, as mentioned, takes an HTTP request and returns the current time. Let's take a look at how these functions work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Serverless Function Setup
&lt;/h2&gt;

&lt;p&gt;As shown above, the serverless function in our Next.js app is simply an exported function that receives a &lt;code&gt;req&lt;/code&gt; and a &lt;code&gt;res&lt;/code&gt; object, just like node API endpoints. It is important to note that this actually isn't using Express to build these objects. Zeit has built these objects to mirror what Express does, but it is not Express.&lt;/p&gt;

&lt;p&gt;When the HTTP request comes in, this function calls &lt;code&gt;res.json&lt;/code&gt; to return the date stamp from the time the request came in. So Zeit allows our React app to make an async HTTP request to this function and will wait for the data to be returned. Let's see how that is set up on the client-side.&lt;/p&gt;

&lt;h2&gt;
  
  
  React App Setup
&lt;/h2&gt;

&lt;p&gt;Looking at the node function, at first glance it isn't intuitive how you would make a request to that function. What's the endpoint? How do you pass data to it? &lt;/p&gt;

&lt;p&gt;It's actually a really cool setup. The deployed (or even the development) instance knows that files in the &lt;code&gt;/api&lt;/code&gt; directory are serverless functions. It builds the functions in the cloud, and then any request that goes out to &lt;code&gt;/api/[file-name]&lt;/code&gt; is sent to that function.&lt;/p&gt;

&lt;p&gt;So there is one single endpoint for each file, and one function for each endpoint. And we can make any HTTP requests to those functions by passing in the file name in the endpoint URL. &lt;/p&gt;

&lt;p&gt;Here is the fetch call that is happening in our Next.js app in the &lt;code&gt;/pages/index.js&lt;/code&gt; file. Do you remember the name of the file that is housing the serverless function? Go ahead and look at it. That's right! It's &lt;code&gt;date.js&lt;/code&gt;. So the React app makes a GET request to &lt;code&gt;/api/date&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftk-assets.lambdaschool.com%2Fb585e434-4363-49e2-bf7a-617198714ece_carbon.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftk-assets.lambdaschool.com%2Fb585e434-4363-49e2-bf7a-617198714ece_carbon.png" alt="React coding making a request to the serverless function" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's as simple as that! The call goes out asynchronously to the serverless function, awaits for the function to return the date, then sets the date to state so it can be displayed in the UI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing Your First Serverless Function
&lt;/h2&gt;

&lt;p&gt;Now that you have seen this work, I want you to add this code to the JSX in your React app. Instead of the header saying "Welcome to Next!", I want it to greet you by name. So let's add some state and the extra piece in the JSX:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftk-assets.lambdaschool.com%2Fb8cd0cfb-bb5f-4001-8805-d6b74ac3355c_add-state.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftk-assets.lambdaschool.com%2Fb8cd0cfb-bb5f-4001-8805-d6b74ac3355c_add-state.png" alt="Code to add a state property called name and display that name in the UI" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have that added, follow these tasks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a new serverless file and function that will return your name (you can shape that data however you would like&lt;/li&gt;
&lt;li&gt;Build a new &lt;code&gt;useEffect&lt;/code&gt; hook that will query that new function to get the name back&lt;/li&gt;
&lt;li&gt;Set the returned name to state so it will display in the header&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Don't scroll down! Try this out on your own first before you see my implementation below 😁&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.tenor.com%2Fimages%2Fc8e4fcf06801572f496e02954df31612%2Ftenor.gif%3Fitemid%3D15057094" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.tenor.com%2Fimages%2Fc8e4fcf06801572f496e02954df31612%2Ftenor.gif%3Fitemid%3D15057094" alt="Gif that says Don't cheat!" width="498" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My Code
&lt;/h2&gt;

&lt;p&gt;How'd you do? Did you get it working? Here is how I implemented this. I added a file called &lt;code&gt;get-name.js&lt;/code&gt; in the &lt;code&gt;/api&lt;/code&gt; directory. The serverless function in that file looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftk-assets.lambdaschool.com%2Ffaa1ccc4-4f39-420f-85cd-0813489b5748_serverless-name.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftk-assets.lambdaschool.com%2Ffaa1ccc4-4f39-420f-85cd-0813489b5748_serverless-name.png" alt="serverless function that returns a name object with my name" width="800" height="400"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Then I fetched the data like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftk-assets.lambdaschool.com%2Fb1e30f7e-ff20-4807-8f4f-03deee829f79_name-effect.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftk-assets.lambdaschool.com%2Fb1e30f7e-ff20-4807-8f4f-03deee829f79_name-effect.png" alt="code that shows an effect hook for calling the new serverless function" width="800" height="400"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Is that about what you had? Share what you did differently in the comments!&lt;/p&gt;

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

&lt;p&gt;Now you know how to add serverless functions to a React app using Next.js and Zeit. The simplicity of the workflow makes this so easy. I love the developer experience and have found that I can build features so much faster with these amazing tools. Let me know what use cases you find for serverless functions, and how you're liking Zeit and Next.js!&lt;/p&gt;

</description>
      <category>react</category>
      <category>serverless</category>
      <category>zeit</category>
      <category>nextjs</category>
    </item>
  </channel>
</rss>
