<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ JAMstack - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ JAMstack - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Fri, 08 May 2026 16:50:22 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/jamstack/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ What is the Jamstack? Tutorial for Beginners ]]>
                </title>
                <description>
                    <![CDATA[ You may have heard the term Jamstack and have been wondering what it means. Well, the Jamstack is nothing more than a modern way of building web applications. Jamstack takes advantage of existing technologies – which we'll discuss in a minute. The re... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/jamstack-for-beginners/</link>
                <guid isPermaLink="false">66d45e0847a8245f78752a1e</guid>
                
                    <category>
                        <![CDATA[ api ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JAMstack ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ markup ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Applications ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Damilola Oladele ]]>
                </dc:creator>
                <pubDate>Thu, 10 Nov 2022 18:30:49 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/11/Damilola-Oladele-2.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>You may have heard the term Jamstack and have been wondering what it means. Well, the Jamstack is nothing more than a modern way of building web applications.</p>
<p>Jamstack takes advantage of existing technologies – which we'll discuss in a minute. The result is better performance, improved security, and easier scalability for web applications.</p>
<p>In this article, you'll learn what Jamstack means and the benefits of using this approach in your projects.</p>
<h2 id="heading-what-is-the-jamstack">What is the Jamstack?</h2>
<p>Jamstack is a web development architecture. Matt Biilmann, the CEO of Netlify, popularized it with his presentation at Smashing Conference 2016.</p>
<p>Jamstack is an acronym for Javascript, APIs, and Markup, and is a technology stack you use to build your apps.</p>
<p>This is like the MERN stack (MongoDB, ExpressJS, ReactJS and NodeJS) and the MEAN stack (MongoDB, ExpressJS, Angular and NodeJS) – just with different tools.</p>
<p>Now let's discuss the various components of a Jamstack web application:</p>
<h3 id="heading-javascript">Javascript</h3>
<p>Javascript is the core programming language of the web. It has been around for decades and you can use it both on the client side and the backend with NodeJS.</p>
<p>Javascript is the programming language you use for handling the client side of your Jamstack applications.</p>
<h3 id="heading-apis">APIs</h3>
<p>API is an acronym for <strong>Application Programming Interface</strong>. It's an interface which helps two or more computer programs communicate with each other.</p>
<p>In Jamstack apps, you use APIs to communicate with your backend.</p>
<h3 id="heading-markup">Markup</h3>
<p>Markup refers to standard text-encoding systems consisting of a set of symbols inserted into a text document. Examples of markup languages are <strong>HTML</strong>, <strong>XML</strong>, and templating languages such as <strong>JSX</strong>.</p>
<p>In the Jamstack, markup refers to the content of a Jamstack application. Note that we use markup here in its broader sense. It doesn't refer to text content only but also to the assets of the web application, such as images.</p>
<h2 id="heading-important-features-of-jamstack-apps">Important Features of Jamstack Apps</h2>
<p>To consider an application a Jamstack app, it should meet the following conditions:</p>
<h3 id="heading-distributed-architecture">Distributed Architecture</h3>
<p>This refers to the decoupling of the client side from the backend. The client side handles the presentation of the user interface, and the backend handles business logic and data.</p>
<p>Communication between the frontend and backend happens via a dedicated API. This means that a change or upgrade in one will not affect the other. This results in easier maintenance of the entire web application.</p>
<h3 id="heading-static-sites">Static Sites</h3>
<p>It is important for Jamstack applications to serve static web pages and not dynamic ones.</p>
<p>Traditional web applications are dynamic sites. This means that when you request a page, the backend will have to reach a database to retrieve the data. The data is then used to generate HTML files, and then sent back to the client.</p>
<p>The disadvantage of dynamic sites is how long it takes to complete these steps.</p>
<p>For static sites, the pages are already pre-rendered at build time. So every time you request a page, you get the pre-rendered page.</p>
<p>This eliminates the time that dynamic sites spend in obtaining data, generating HTML files, and sending it back to the client. You can serve your static sites from a <a target="_blank" href="https://www.cloudflare.com/learning/cdn/what-is-a-cdn/">content delivery network (CDN).</a> This will lead to improved speed and reduced costs.</p>
<p>Examples of static site generators that you can use for your Jamstack web applications include:</p>
<ul>
<li><p>NextJS</p>
</li>
<li><p>Gatsby</p>
</li>
<li><p>Hugo</p>
</li>
<li><p>Jekyll</p>
</li>
<li><p>Nuxt</p>
</li>
</ul>
<h2 id="heading-why-should-you-use-the-jamstack-for-your-web-applications">Why Should You Use the Jamstack for your Web Applications?</h2>
<p>Let's now discuss some of the reasons the Jamstack web architecture has become so popular in recent times and why you should consider adopting it:</p>
<h3 id="heading-jamstack-apps-are-scalable">Jamstack Apps Are Scalable</h3>
<p>You can serve most Jamstack applications from a CDN. This allows for the speedy transfer of assets needed for loading web pages.</p>
<p>As a result of the distributed nature of CDNs, your web application will also be able to handle more traffic at a reduced cost.</p>
<h3 id="heading-jamstack-apps-are-easy-to-maintain">Jamstack Apps Are Easy to Maintain</h3>
<p>Jamstack applications are easier to maintain since their client side is decoupled from their backends.</p>
<p>This means that you can maintain one part without requiring major modifications to the other.</p>
<h3 id="heading-jamstack-apps-load-faster">Jamstack Apps Load Faster</h3>
<p>As stated earlier, serving your site from a CDN increases the speed with which it loads.</p>
<p>Also, in Jamstack applications, web pages are prebuilt, saving time that would normally be spent retrieving and generating HTML files every time you make a request.</p>
<h3 id="heading-jamstack-apps-are-cheaper">Jamstack Apps Are Cheaper</h3>
<p>Since Jamstack applications are easier to maintain and deploy, they are cheaper compared to their traditional counterparts.</p>
<h3 id="heading-jamstack-apps-are-more-secure">Jamstack Apps Are More Secure</h3>
<p>Since you do not have to constantly maintain a server in Jamstack applications and the pages are constructed on read-only files (that is, the pages are static), you can worry less about the security of your applications.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Despite the fact that more and more projects are being built using the Jamstack architecture, we're still in the relatively early stages of its adoption.</p>
<p>I believe that more large and small businesses will adopt it in the near future in place of costly monolithic architectures.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Design Your Own Learning Plan for Any Tech Stack ]]>
                </title>
                <description>
                    <![CDATA[ By Kenny Rogers One of the most difficult things about getting started in a new career as a developer is figuring out exactly what you should be learning – and then translating that into an effective plan. There are so many resources out there for le... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-design-your-own-learning-plan-for-any-tech-stack/</link>
                <guid isPermaLink="false">66d45f66b3016bf139028d56</guid>
                
                    <category>
                        <![CDATA[ JAMstack ]]>
                    </category>
                
                    <category>
                        <![CDATA[ learning to code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ self-improvement  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 02 Jun 2021 21:18:15 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/05/FCC-Article-Cover--2-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Kenny Rogers</p>
<p>One of the most difficult things about getting started in a new career as a developer is figuring out exactly what you should be learning – and then translating that into an effective plan.</p>
<p>There are so many resources out there for learning, so lack of information is not the problem.</p>
<p>The problem is two-fold:</p>
<p>First, it's hard to gather all this information and turn it into a cohesive plan for systematically learning what you want to learn.</p>
<p>Second, it's hard to figure out how to take all these resources and actually learn from them instead of just being stuck in tutorial hell forever.</p>
<p>The struggle is that we get sucked into the step-by-step nature of tutorials and courses and it can be hard to break out of that and do our own thing without having plan to follow.</p>
<p>This guide is meant to help you learn how to put together your own learning plan so you can utilize tutorials and courses while still being able to break out of the set path and begin to forge your own.</p>
<p>It is impossible to genuinely learn to code by just following tutorials and courses over and over again.</p>
<p>At some point you have to step out of the comfort zone they provide and do something on your own.</p>
<p>My hope is that this guide will serve as a transition aid by guiding you towards creating your own learning path instead of telling you exactly what to do.</p>
<h2 id="heading-the-psychological-trap-of-step-by-step-paths">The Psychological Trap of Step-by-Step Paths</h2>
<p>Before we get into the practical methods, we need to talk about why people get stuck in tutorial hell, and how to get out of it.</p>
<p>For most people, the process goes something like this:</p>
<p>You go through tutorials, feeling great. You are breezing through the tutorial, building something from scratch.</p>
<p>Maybe you run into a few small bugs, but nothing you can't work through really quickly.</p>
<p>You go through a few of these, building some small projects along the way.</p>
<p>Then you go to start building something on your own and immediately hit a wall.</p>
<p>You can barely get the project started before you feel like you forgot everything you just learned.</p>
<p>You will feel like you are starting from zero. Like everything you just spent time learning went out the window.</p>
<p>You feel like you didn't learn, so you find more tutorials thinking you need them to learn more before you build something on your own.</p>
<p>And the cycle continues.</p>
<p>In reality you stopped struggling too soon.</p>
<p>The learning doesn't happen only in the tutorials. The learning happens in that moment when most people give up and go back to the tutorials.</p>
<p>That struggle. That feeling like you didn't actually know anything. That's the first step of the learning process.</p>
<p>Don't run from it. Lean into it.</p>
<p>It's a lot harder to do. It's comfortable and easy to slide back into the tutorials because completing them feels good. It makes you feel like you are learning.</p>
<p>But it's a dangerous trap to fall into because the real learning happens as soon as you stop being comfortable and start struggling to build something on your own.</p>
<p>So before we get into the practical steps of designing your own learning plan, please understand this and be ready for it.</p>
<p>There is no shortcut, no easy step-by-step solution. You just need to accept that you are going to struggle and be confused and not know what you are doing.</p>
<p>That is part of the process.</p>
<p>That is where the real learning is taking place.</p>
<p>Embrace it and push through it. The rewarding feeling of having built something from scratch that doesn't exist anywhere else is worth it.</p>
<p>And it's what will stand out to potential employers and clients when you're trying to find work as a professional developer.</p>
<h2 id="heading-how-to-decide-what-to-learn">How to Decide What to Learn</h2>
<p>I like examples and seeing specific implementations of concepts. So in this guide, I'll talk about a concept and then give an example of me going through the process of designing a learning plan for a tech stack I've been interested in for a while: <a target="_blank" href="https://blitzjs.com/">Blitz.js</a>.</p>
<p>In order to decide what you want to learn, you can take a few different criteria into account.</p>
<p>These will vary depending on where you are in your career.</p>
<p>If you are just getting started, I recommend choosing a stack with high potential for employability.</p>
<p>Right now I would recommend React for that.</p>
<p>If you are already familiar with React I would go for learning some Web3 and blockchain.</p>
<p>I'm 7 years into my career and am to the point where my main interest is exploring different emerging stacks that can make my job more efficient. For me that means I am interested in Blitz.js.</p>
<p>I love the idea of having a stack that has the same philosophy as Rails but is built on top of React and Next.js.</p>
<p>You may just be getting started and so you are primarily interested in learning how to build things with React so you can get your first job.</p>
<p>This will vary for each person, but the building blocks of that learning plan design will be the same.</p>
<h2 id="heading-get-some-initial-exposure-to-the-tech-stack">Get Some Initial Exposure to the Tech Stack</h2>
<p>The first step in learning any new stack is to simply be exposed to the basics of how it works. The best place to start with this is the official getting started tutorial provided by the stack.</p>
<p>Most stacks will have something like the getting started tutorial for <a target="_blank" href="https://blitzjs.com/docs/tutorial">Blitz</a> or <a target="_blank" href="https://reactjs.org/tutorial/tutorial.html">React</a>.</p>
<p>But if they don't, do a Google search for a beginner's tutorial for your stack.</p>
<p>After you go through the official tutorial glance through the docs. Don't try to read the docs straight through, just browse and glance to get a high-level overview.</p>
<p>Going through the tutorial will have the added benefit of exposing you to some of the ecosystem of your stack.</p>
<p>Almost everything you use will need at least some sort of other tool to work with.</p>
<p>Going through the tutorial and docs will help you be exposed to those initially, which will help in the next step.</p>
<h2 id="heading-research-the-supporting-components">Research the Supporting Components</h2>
<p>Now we have our initial exposure done. We are familiar with the basic concepts of the framework and at a very high level know how it works technologically.</p>
<p>The next step is to research the different supporting components we might want to use in building out a complete project.</p>
<p>So in looking at Blitz, I noticed that they have recipes for adding certain functionality to Blitz apps.</p>
<p>For example, they have a recipe for Tailwind CSS, which is a UI system I've used before but would like to be more proficient at.</p>
<p>So I'm going to add that to a list of supporting components.</p>
<p>Don't worry about learning it yet, just keep a list of other supporting tech you want to look into.</p>
<p>I'm also going to add Prisma and Render to that list, since Prisma is the database system that Blitz uses and Render is one of the recommended deployment tools.</p>
<p>That's all I'm going to put on my supporting components list for now, but this is an unusually short list because Blitz is designed to be an all-in-one framework.</p>
<p>If you are learning something more foundational, like React, you could have a potentially never-ending list of supporting components.</p>
<p>For now, just keep a running list of different tech you would like to learn more about and categorize it.</p>
<p>For example, if you chose React, you might want to learn Chakra UI, Gatsby, and Strapi CMS in order to build JAMstack sites. Those would be good things to add to a list of supporting components.</p>
<p>Remember, we aren't diving into these yet, as that would be too overwhelming. We're just making a list to research over time.</p>
<h2 id="heading-build-a-complete-project">Build a Complete Project</h2>
<p>Now it's time to find a course or tutorial that builds a complete project from scratch using your chosen technology. </p>
<p>This is to get introduced to how everything fits together and start understanding how the different components you have been researching all work to make something valuable.</p>
<p>Try to find something that utilizes some or all of the components you have been finding.</p>
<p>Don't worry if you can't find one that uses them all, that's fine. We really just want to find a source of learning that will allow us to see how this stack looks when building a complete project.</p>
<p>Google is your friend here, as are any groups or social media sites you are a part of.<br>I searched 'blitz complete project tutorial' on Google and found a few that look promising.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/image-90.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>If you chose React as your stack, I highly recommend the courses from <a target="_blank" href="https://wesbos.com/courses/">Wes Bos</a> and <a target="_blank" href="https://ui.dev/courses/">UI.dev</a>. They both focus on creating full projects and will be great for the kind of learning we're talking about here.</p>
<h2 id="heading-build-something-from-scratch">Build Something from Scratch</h2>
<p>This part is important. After that complete tutorial, stop. Don't do any more tutorials or courses until you build something from scratch.</p>
<p>Now we get into the hard part, but the part where the real learning takes place.</p>
<p>Take everything you have learned and apply it to building something on your own.</p>
<p>Use the resources as references, but only in the context of building your own thing.</p>
<p>Remember the trap we were talking about earlier. Don't fall into it.</p>
<p>Keep pushing forward through the struggle and work on your debugging and research skills.</p>
<p>Use the familiarity with the different tools you have been researching to slowly piece together a project from scratch.</p>
<p>Make it complete. Add a UI framework so the design looks relatively nice. Add some CI/CD and automated Git-based deployment. Make it usable.</p>
<p>If there are some tools you wish the tutorial/course you found had used, or even some you are interested in learning more about, use those instead.</p>
<p>Make your project different from the course so you can learn how to piece things together own your own.</p>
<p>Write some tests, add some CI/CD workflow, and get it deployed.</p>
<p>For example, Wes Bos has a Master Gatsby course that utilizes Sanity CMS and custom scoped CSS.</p>
<p>Maybe you are interested in building JAMstack sites so you decided to follow that course.</p>
<p>After that course you might try building your own JAMstack site using Tailwind and Strapi instead.</p>
<p>The point is to build something unique and on your own, referencing the content you have been reviewing up until this point as you need it.</p>
<p>How do you come up with ideas for things to build? Try to keep it simple and solve a very small problem you are specifically facing.</p>
<p>If you don't have a personal site, you could learn the JAMstack to build it.</p>
<p>Maybe one of your friends or family has a small hobby or business they've been wanting a website for, there's another great use case for JAMstack.</p>
<p>Maybe you've been struggling to make a certain change in your life because of a lack of tools, so you can build a tool to help solve it.</p>
<p>One of my first personal projects was an app I made called TinyThought. It was a simple Laravel app that helped me journal one sentence per day so I could build the habit.</p>
<p>To learn Blitz I'm thinking I might do something similar to track my strength training progress.</p>
<p>I'm implementing <a target="_blank" href="http://tinyhabits.com/">Tiny Habits</a> methodology in order to be consistent with doing pushups, squats, and chin-ups.</p>
<p>So I might create a simple tracking app that allows me to keep track of which days I completed the habit and how many of each exercise I did.</p>
<h2 id="heading-write-about-it">Write About It</h2>
<p>Then write up how you built it.</p>
<p>The writing is important.</p>
<p>Writing will solidify your learning and help you get clear on your process more than anything else.</p>
<p>To really solidify learning something, teach it to someone else.</p>
<p>So as you are going through the process of building your custom project, write down everything you are learning, challenges you are facing, and your process for building.</p>
<p>You can create a series or one long, in-depth post and publish it to DEV.to, freeCodeCamp, or your own blog for other people to learn from.</p>
<p>If you prefer video, you can make some videos and put them up on YouTube. The ultimate form of the content doesn't matter, as long as you are teaching the process while making it as clear as possible.</p>
<p>Teaching other people is by far the best way to solidify your own learning and make sure you actually understand what you are doing.</p>
<h2 id="heading-rinse-and-repeat">Rinse and Repeat</h2>
<p>Now rinse and repeat this process for every new piece of tech you want to learn.</p>
<p>It will solidify your knowledge and build your portfolio and online presence at the same time.</p>
<p>Once you have this process down, it will get easier and easier every time you want to learn something new. I highly recommend you follow a process similar to this when you want to learn a new stack.</p>
<p>The more you do it, the more you will learn and the more your portfolio and proof of skill will grow. This is how you can leverage learning to code into work as a professional developer.</p>
<p>For more actionable information like this on how to start and grow a successful dev career, check out my free 10-day email course, <a target="_blank" href="https://launchyourdevcareer.com">Launch Your Dev Career</a>. It's a step-by-step guide to landing your first job as a developer.</p>
<p>We go over how to build an online presence, networking, building an impressive portfolio, and more, all designed to help you launch and grow a successful, fulfilling career as a developer.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create an Image Gallery Using Gatsby and Cloudinary ]]>
                </title>
                <description>
                    <![CDATA[ According to Mathias Biilmann, the CEO & Co-founder of Netlify,"The JAMstack is a modern web development architecture based on client-side JavaScript, reusable APIs, and prebuilt Markup." The key aspects of a JAMstack application are the following: ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-an-image-gallery-gatsby-and-cloudinary/</link>
                <guid isPermaLink="false">66bdffd60b4523e3b8b9909e</guid>
                
                    <category>
                        <![CDATA[ Gatsby ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JAMstack ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tapas Adhikary ]]>
                </dc:creator>
                <pubDate>Mon, 12 Oct 2020 20:36:24 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/10/cover_1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>According to Mathias Biilmann, the CEO &amp; Co-founder of Netlify,"The <code>JAMstack</code> is a modern web development architecture based on client-side JavaScript, reusable APIs, and prebuilt Markup."</p>
<p>The key aspects of a <a target="_blank" href="https://blog.greenroots.info/jamstack-for-all-an-introduction-cke2fxc5800jvabs15lhn4a9x">JAMstack</a> application are the following:</p>
<ul>
<li>The entire app runs on a <strong>CDN (or ADN)</strong>. CDN stands for Content Delivery Network and an ADN is an Application Delivery Network.</li>
<li>Everything is in <strong>Git</strong>.</li>
<li><strong>Automated builds</strong> run with a workflow when developers push the code.</li>
<li>There's <strong>Automatic deployment</strong> of the pre-built markup to the CDN/ADN.</li>
<li>It's practically <strong>Serverless</strong>. To put it more clearly, we do not maintain any server-side applications but rather make use of already existing services (like email, media, database, search, and so on).</li>
</ul>
<p>And here's a fun fact: Many of the features that once required a custom back-end can now be done entirely on the front-end.</p>
<p>In this article, we will learn how to build a <a target="_blank" href="https://blog.greenroots.info/jamstack-for-all-an-introduction-cke2fxc5800jvabs15lhn4a9x">JAMstack</a> application that has:</p>
<ul>
<li>an API service to serve media files,</li>
<li>and a <a target="_blank" href="https://blog.greenroots.info/what-is-a-static-site-generator-and-how-to-select-one-cke9xtx5g006p58s11dzg2j16">Static Site Generator(SSG)</a> to create the pre-built markup.</li>
</ul>
<p>And finally we'll deploy it over a CDN.</p>
<h2 id="heading-so-what-are-we-building-today"><strong>So, what are we building today?</strong></h2>
<p>We will build an image gallery. I love movies, so I have decided to create an image gallery of my favorite actors. I have a fun name for it to: <code>imaginary</code>.</p>
<p>We will use a media management service called <a target="_blank" href="https://cloudinary.com/">Cloudinary</a> to host and manage our images. It also provides developer APIs to upload and fetch media such as images, videos, and so on</p>
<p>We will use a framework called <a target="_blank" href="https://www.gatsbyjs.com/">Gatsby</a> to build the front-end of the image gallery. <code>Gatsby</code> is a React-based open-source framework for creating websites and apps.</p>
<p>Finally, we will learn how to deploy the app to a CDN with an automatic build and deploy process. We will use <a target="_blank" href="https://www.netlify.com/">Netlify CDN</a> for this.</p>
<p>At the end of the article, our <code>imaginary</code> app will look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/snap.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Image Gallery app - Final Look</em></p>
<h2 id="heading-tldr"><strong>TL;DR</strong></h2>
<p>We will learn things with a step-by-step approach in this article. If you want to jump into the source code or demonstration sooner, here are links to them.</p>
<ul>
<li>You can access the image gallery demo from here: <a target="_blank" href="http://imaginary.netlify.app/">http://imaginary.netlify.app/</a></li>
<li>All the source code used in this article is in my GitHub repo. Feel free to follow it, as I keep updating the source code frequently. If you liked the work, please support it with a star. <a target="_blank" href="https://github.com/atapas/imaginary/tree/1-freecodecamp-poc">https://github.com/atapas/imaginary/tree/1-freecodecamp-poc</a></li>
</ul>
<p>Now let's get started.</p>
<h2 id="heading-how-to-set-up-cloudinary"><strong>How to Set Up Cloudinary</strong></h2>
<p>First, <a target="_blank" href="https://cloudinary.com/users/register/free">create an account</a> with <code>Cloudinary</code>. A free plan is more than enough for our image gallery application.</p>
<p>Login using your account credentials to get to the <code>Cloudinary</code> dashboard. Please note down the <code>Cloud name</code>, <code>API Key</code> and, <code>API Secret</code> as we'll need them in our application.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/cloudinary.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Next, upload the images of your choice to use them in the <code>image gallery</code>. You can create a folder and call it whatever you want. In my case, I have named it <code>artists</code> and uploaded the images into it.</p>
<p>Note that we'll use this folder name later when we integrate <code>Cloudinary</code> with <code>Gatsby</code>.</p>
<p>Please select each of the images and add a <code>Title</code> and <code>Description</code>. We will use these two bits of meta information as image captions and alt-text, respectively, in our image gallery.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/cludinary_photo_management.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>That's all. Please do not share the API secret and the key with anyone. Let's now go through the required setup for <code>Gatsby</code>.</p>
<h2 id="heading-how-to-set-up-gatsby"><strong>How to Set Up Gatsby</strong></h2>
<p>A <code>gatsby</code>-based project needs <code>node.js</code> to work. Make sure you have Node.js installed. You can download and install <code>node.js</code> from <a target="_blank" href="https://nodejs.org/en/download/">here</a>.</p>
<p>A successful install will show the Node version using this command:</p>
<pre><code class="lang-shell">node -v
</code></pre>
<h3 id="heading-create-a-project-directory"><strong>Create a project directory</strong></h3>
<p>Create a project directory to organize the source code. Let's create a directory with the name <code>imaginary</code>.</p>
<pre><code class="lang-shell">mkdir imaginary

cd imaginary
</code></pre>
<h3 id="heading-initialize-the-project"><strong>Initialize the project</strong></h3>
<p>There are plenty of <a target="_blank" href="https://www.gatsbyjs.com/starters/">starter projects</a> to create a <code>gatsby</code> app. While the starter projects simplify many complexities, at the same time they may be a bit overwhelming for a simple app like ours.</p>
<p>Keeping that in mind, we will initialize a simple <code>gatsby</code> project by ourselves.</p>
<p>Open a command prompt and type the following command to initialize a Node.js supported project:</p>
<pre><code class="lang-shell">npm init -y
</code></pre>
<h3 id="heading-gatsby-install-and-initial-setup"><strong>Gatsby: Install and initial setup</strong></h3>
<p>Install the <code>gatsby-cli</code> tool globally. This tool will help us work with the Gatsby environment.</p>
<pre><code class="lang-shell"> npm install -g gatsby-cli
</code></pre>
<p>Install the Gatsby, React, and ReactDOM dependencies. You can either use the <code>npm install</code> command as above or the <code>yarn add</code> command if you have yarn installed.</p>
<pre><code class="lang-shell"> yarn add gatsby react react-dom
</code></pre>
<p>Let's also add a <code>.gitignore</code> file with the following content:</p>
<pre><code class="lang-shell">.cache
public
node_modules
*.env
</code></pre>
<p>You can optionally create a README.md and LICENSE file. At this stage, our project should have these folders and files:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/image-14.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><code>Gatsby</code> projects need a special configuration file called <code>gatsby-config.js</code>. At this time, we will need an empty file. Create a file named <code>gatsby-config.js</code> with the following content:</p>
<pre><code class="lang-js"> <span class="hljs-built_in">module</span>.exports = {
  <span class="hljs-comment">// keep it empty    </span>
 }
</code></pre>
<p>Now it is time to create our first page with <code>Gatsby</code>. Create a folder named <code>src</code> at the root of the project folder. Create a sub-folder named <code>pages</code> under <code>src</code>. Create a file named <code>index.js</code> under <code>src/pages</code> with the following content:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;    

  <span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> () =&gt; {    
   <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;&gt;</span>    
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Images to load here...<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;/&gt;</span></span>        
    )    
  }
</code></pre>
<p>At this stage, our project files and folders should look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/image-16.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-lets-run-it"><strong>Let's run it</strong></h3>
<p>Try the following command in the command prompt to run the app locally:</p>
<pre><code class="lang-shell">gatsby develop
</code></pre>
<p>By default, a <code>gatsby</code> app runs on the <code>8000</code> port number. Open your favorite browser and access the app @ <a target="_blank" href="http://localhost:8000/">http://localhost:8000</a>.</p>
<p>You should see it running like you see in the screen-shot below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/image-15.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>That's all. Now, we've gotten both <code>Cloudinary</code> and <code>Gatsby</code> successfully set up. It's time to bring them together.</p>
<h2 id="heading-cloudinary-amp-gatsby-the-getting-together-story"><strong>Cloudinary &amp; Gatsby, the getting together story</strong></h2>
<p>The <code>Gatsby</code> framework has huge community support and there are many plug-ins to satisfy critical needs. In early 2020, the <code>Cloudinary</code> team <a target="_blank" href="https://cloudinary.com/blog/introducing_cloudinary_s_gatsby_plugins">introduced two super cool Gatsby plugins</a> to the dev community:</p>
<ul>
<li><a target="_blank" href="https://www.npmjs.com/package/gatsby-source-cloudinary"><code>Gatsby-Source-Cloudinary</code></a> - Helps in fetching the stored images at the build time from Cloudinary to a Gatsby app/site.</li>
<li><a target="_blank" href="https://www.npmjs.com/package/gatsby-transformer-cloudinary"><code>Gatsby-Transformer-Cloudinary</code></a> - Helps in uploading the local images from a Gatsby app/site to Cloudinary.</li>
</ul>
<p>As we are only interested in fetching the images to the image gallery here, we will just install the <code>gatsby-source-cloudinary</code> plug-in.</p>
<p>We will also install a utility package called <code>dotenv</code> to handle the environment variables (Secret Key, API key, and so on) locally.</p>
<p>Let's install them. Open a command prompt and use the following command:</p>
<pre><code class="lang-shell">yarn add dotenv gatsby-source-cloudinary
</code></pre>
<p>Now, follow these steps to fetch the images into our app.</p>
<ol>
<li>Create a <code>.env</code> file at the root of the project folder and add the following content to it. Please note that the values in the <code>key-value</code> pairs are available in the <code>Cloudinary</code> dashboard as we have seen before.</li>
</ol>
<pre><code class="lang-shell">CLOUDINARY_CLOUD_NAME=&lt;YOUR_CLOUDINARY_NAME&gt;
CLOUDINARY_API_KEY=&lt;YOUR_CLOUDINARY_API_KEY&gt;
CLOUDINARY_API_SECRET=&lt;YOUR_CLOUDINARY_API_SECRET&gt;
</code></pre>
<ol start="2">
<li>Edit the <code>gatby-config.js</code> file to add the following content:</li>
</ol>
<pre><code class="lang-js">
<span class="hljs-built_in">require</span>(<span class="hljs-string">'dotenv'</span>).config();

<span class="hljs-built_in">module</span>.exports = {

    <span class="hljs-attr">plugins</span>:[
        {
            <span class="hljs-attr">resolve</span>: <span class="hljs-string">`gatsby-source-cloudinary`</span>,
            <span class="hljs-attr">options</span>: {
              <span class="hljs-attr">cloudName</span>: process.env.CLOUDINARY_CLOUD_NAME,
              <span class="hljs-attr">apiKey</span>: process.env.CLOUDINARY_API_KEY,
              <span class="hljs-attr">apiSecret</span>: process.env.CLOUDINARY_API_SECRET,
              <span class="hljs-attr">resourceType</span>: <span class="hljs-string">`image`</span>,
              <span class="hljs-attr">prefix</span>: <span class="hljs-string">`artists/`</span> ,
              <span class="hljs-attr">context</span>: <span class="hljs-literal">true</span>,
              <span class="hljs-attr">tags</span>: <span class="hljs-literal">true</span>,
              <span class="hljs-attr">maxResults</span>: <span class="hljs-number">50</span>
            }
          }
    ]

}
</code></pre>
<p>There are a few things going on here. We are telling <code>gatsby</code> to use the <code>gatsby-source-cloudinary</code> plug-in with a few parameters.</p>
<p>The parameters <code>cloudName</code>, <code>apiKey</code> and <code>apiSecret</code> are fetched from the <code>.env</code> file using the <code>dotenv</code> package. We also specify the <code>resourceType</code> value as <code>image</code> as we are not interested in fetching other types of media.</p>
<p>The <code>prefix</code> parameter value should be the same as the image folder name in Cloudinary.</p>
<p>We specify <code>context</code> and <code>tags</code> as true to fetch the contextual metadata and tag information of an image. We also set the <code>maxResults</code> as 50 so that we do not get constrained with the default value of 10.</p>
<ol start="3">
<li>Next, create a folder called <code>components</code> under <code>src</code> and create a file called <code>Gallery.js</code> inside it. <code>Gatsby</code> uses <code>graphQL</code> to query the data from various sources like markdown, JSON, and Excel.  </li>
</ol>
<p>In our case, we will use <code>Cludinary</code> as a source to query the images using the  <code>gatsby-source-cloudinary</code> plug-in configured already.</p>
<ol start="4">
<li>Now edit the <code>Gallery.js</code> file and add the following content:</li>
</ol>
<pre><code class="lang-js">
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> {useStaticQuery, graphql} <span class="hljs-keyword">from</span> <span class="hljs-string">'gatsby'</span>;

<span class="hljs-keyword">const</span> Gallery = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> data = useStaticQuery(
        graphql<span class="hljs-string">`
        query CloudinaryImage {
            allCloudinaryMedia {
            edges {
                node {
                    secure_url
                    context {
                        custom {
                            alt
                            caption
                        }
                    }
                    resource_type
                }
            }
            }
        }`</span>
    );
    <span class="hljs-keyword">const</span> images = data.allCloudinaryMedia.edges;
    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"container"</span>&gt;</span>
            {images.map((image, index) =&gt; (
                <span class="hljs-tag">&lt;<span class="hljs-name">figure</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"wave"</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">index</span>}<span class="hljs-attr">-image</span>`}&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">img</span> 
                        <span class="hljs-attr">src</span>=<span class="hljs-string">{image.node.secure_url}</span> 
                        <span class="hljs-attr">alt</span>=<span class="hljs-string">{image.node.context.custom.alt}</span> &gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">img</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">figcaption</span>&gt;</span>{image.node.context.custom.caption}<span class="hljs-tag">&lt;/<span class="hljs-name">figcaption</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">figure</span>&gt;</span>
                ))
            }
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    )
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Gallery;
</code></pre>
<p>As we see above, we use a <code>graphQL</code> query to fetch the source image paths and the context information. We use the information to loop through and add the images with a caption.</p>
<ol start="5">
<li>The next step is to edit the <code>index.js</code> file to import the <code>Gallery.js</code> file and use it.</li>
</ol>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> Gallery <span class="hljs-keyword">from</span> <span class="hljs-string">'../components/Gallery'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> () =&gt; {    
    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;&gt;</span>    
        <span class="hljs-tag">&lt;<span class="hljs-name">Gallery</span> /&gt;</span>
      <span class="hljs-tag">&lt;/&gt;</span></span>        
    )    
}
</code></pre>
<p>If you are running the <code>gatsby develop</code> already, please stop it and run it again. Access the app again in the browser. You should see the app with all the images fetched from <code>Cloudinary</code>.</p>
<p>But wait, it doesn't look as elegant as was promised. We have to do some <code>css</code> work here.</p>
<p>Create a file called <code>gallery.css</code> under the folder <code>src\components</code> and add the following content in it:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">body</span> {
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#000000</span> <span class="hljs-built_in">url</span>(<span class="hljs-string">"https://res.cloudinary.com/atapas/image/upload/v1602214656/misc/6284_n48wtw.jpg"</span>) repeat-x center top;
    <span class="hljs-attribute">color</span>: <span class="hljs-number">#FFFFFF</span>;
}

<span class="hljs-selector-class">.container</span> {
    <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">55px</span>;
}

<span class="hljs-selector-class">.wave</span> {
    <span class="hljs-attribute">float</span>: left;
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">20px</span>;
    <span class="hljs-attribute">animation</span>: wave 
               ease-in-out 
               <span class="hljs-number">1s</span> 
               infinite 
               alternate;
    <span class="hljs-attribute">transform-origin</span>: center -<span class="hljs-number">20px</span>;
}

<span class="hljs-selector-class">.wave</span><span class="hljs-selector-pseudo">:hover</span> {
    <span class="hljs-attribute">animation-play-state</span>: paused;
}

<span class="hljs-selector-class">.wave</span> <span class="hljs-selector-tag">img</span> {
    <span class="hljs-attribute">border</span>: <span class="hljs-number">5px</span> solid <span class="hljs-number">#f8f8f8</span>;
    <span class="hljs-attribute">display</span>: block;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">200px</span>;
    <span class="hljs-attribute">height</span>: <span class="hljs-number">250px</span>;
    <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#000</span>;
}

<span class="hljs-selector-class">.wave</span> <span class="hljs-selector-tag">figcaption</span> {
    <span class="hljs-attribute">text-align</span>: center;
}

<span class="hljs-selector-class">.wave</span><span class="hljs-selector-pseudo">:after</span>{
    <span class="hljs-attribute">content</span>: <span class="hljs-string">''</span>;
    <span class="hljs-attribute">position</span>: absolute;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">20px</span>; 
    <span class="hljs-attribute">height</span>: <span class="hljs-number">20px</span>;
    <span class="hljs-attribute">border</span>: <span class="hljs-number">1.5px</span> solid <span class="hljs-number">#ffffff</span>;
    <span class="hljs-attribute">top</span>: -<span class="hljs-number">10px</span>; 
    <span class="hljs-attribute">left</span>: <span class="hljs-number">50%</span>;
    <span class="hljs-attribute">z-index</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">border-bottom</span>: none;
    <span class="hljs-attribute">border-right</span>: none;
    <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotate</span>(<span class="hljs-number">45deg</span>);
}

<span class="hljs-selector-class">.wave</span><span class="hljs-selector-pseudo">:before</span>{
    <span class="hljs-attribute">content</span>: <span class="hljs-string">''</span>;
    <span class="hljs-attribute">position</span>: absolute;
    <span class="hljs-attribute">top</span>: -<span class="hljs-number">23px</span>;
    <span class="hljs-attribute">left</span>: <span class="hljs-number">50%</span>;
    <span class="hljs-attribute">display</span>: block;
    <span class="hljs-attribute">height</span>: <span class="hljs-number">44px</span>;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">47px</span>;
    <span class="hljs-attribute">background-image</span>: <span class="hljs-built_in">url</span>(https://res.cloudinary.com/atapas/image/upload/v1602212639/misc/screw-head_oglfcu.png);
    <span class="hljs-attribute">background-size</span>: <span class="hljs-number">20px</span> <span class="hljs-number">20px</span>;
    <span class="hljs-attribute">background-repeat</span>: no-repeat;
    <span class="hljs-attribute">z-index</span>: <span class="hljs-number">16</span>;
}

<span class="hljs-keyword">@keyframes</span> wave {
    0% { <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotate</span>(<span class="hljs-number">3deg</span>); }
    100% { <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">rotate</span>(-<span class="hljs-number">3deg</span>); }
}
</code></pre>
<ol start="6">
<li>Import the <code>gallery.css</code> file into the <code>Gallery.js</code> file as</li>
</ol>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> <span class="hljs-string">'./gallery.css'</span>;
</code></pre>
<p>That's all. You should see the app looking much better than before as if the images are hanging from a wall with animation in them.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/snap-1.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-lets-deploy-the-app"><strong>Let's Deploy the App</strong></h2>
<p>The last step is to deploy the app publicly so that we show it off.</p>
<p>First, create a repository in GitHub and push the source code. Then create an account with <a target="_blank" href="https://www.netlify.com/">Netlify</a> to login.</p>
<p>Follow these simple steps to deploy your app to the Netlify CDN with built-in CI/CD support.</p>
<ul>
<li>Create a new site from Git</li>
<li>Authenticate to your <code>Github</code> account and select the image gallery project. In my case, the project name is <code>imaginary</code>.</li>
<li>In the next step, provide information about the build command as <code>gatsby build</code> and publish the directory as <code>public/</code>.</li>
<li>Next click on the <code>Site settings</code> to tell <code>netlify</code> about the <code>Cloudinary</code> cloud name, secret key, API key, and so on.</li>
<li>Browse to the <code>Environment</code> option and click on the <code>Edit variables</code> button.</li>
<li>Add three variables as shown below with the values shown in your <code>Cloudinary</code> dashboard.</li>
<li>Browse to the <code>Deploys</code> option and trigger a fresh deploy.</li>
<li>You can change the site name to something that meets your needs. In my case, it is <a target="_blank" href="https://imaginary.netlify.app/">https://imaginary.netlify.app/</a>:</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/1.netlify.png" alt="Image" width="600" height="400" loading="lazy">
<em>New site from Git</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/2.netlify.png" alt="Image" width="600" height="400" loading="lazy">
<em>Create a new site</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/3.netlify.png" alt="Image" width="600" height="400" loading="lazy">
<em>Parameters for the site</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/4.netlify.png" alt="Image" width="600" height="400" loading="lazy">
<em>Site settings</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/5.netlify.png" alt="Image" width="600" height="400" loading="lazy">
<em>Add environment variables</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/6.netlify.png" alt="Image" width="600" height="400" loading="lazy">
<em>Add all of them</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/7.netlify.png" alt="Image" width="600" height="400" loading="lazy">
<em>Trigger a fresh deploy</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/8.netlify.png" alt="Image" width="600" height="400" loading="lazy">
<em>Optionally to change the site name</em></p>
<p>Now we're done. We have the app up and running publicly.</p>
<h2 id="heading-in-summary"><strong>In Summary</strong></h2>
<p>Hope you enjoyed reading this article. In a future article we will see how to use the other gatsby-cloudinary plug-in to upload an image to the <code>Cloudinary</code> server to add to our image gallery.</p>
<p>You may also like these articles:</p>
<ul>
<li><a target="_blank" href="https://blog.greenroots.info/i-made-a-photo-gallery-with-css-animation-heres-what-i-learned-ckfzbk6v903ea2xs14l1942f7">I made a photo gallery with CSS animation. Here’s what I learned.</a></li>
<li><a target="_blank" href="https://blog.greenroots.info/jamstack-for-all-an-introduction-cke2fxc5800jvabs15lhn4a9x">JAMstack for All: An Introduction</a></li>
<li><a target="_blank" href="https://blog.greenroots.info/what-is-a-static-site-generator-and-how-to-select-one-cke9xtx5g006p58s11dzg2j16">What is a Static Site Generator and how to select one?</a></li>
</ul>
<p>If this article was useful, please share it so others can read it as well. You can @ me on Twitter (<a target="_blank" href="https://twitter.com/tapasadhikary">@tapasadhikary</a>) with comments, or feel free to follow me.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Jamstack Site with Next.js and Vercel - Jamstack Handbook ]]>
                </title>
                <description>
                    <![CDATA[ The Jamstack architecture is a modern approach to an old idea: making fast, static websites, but making them dynamic with tools like JavaScript.  How can we leverage the web framework Next.js and hosting platform Vercel to build and deploy performant... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-jamstack-site-with-next-js-and-vercel-jamstack-handbook/</link>
                <guid isPermaLink="false">66b8e34589963e292346f67b</guid>
                
                    <category>
                        <![CDATA[ JAMstack ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Thu, 17 Sep 2020 16:08:04 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/09/jamstack-handbook.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>The Jamstack architecture is a modern approach to an old idea: making fast, static websites, but making them dynamic with tools like JavaScript. </p>
<p>How can we leverage the web framework Next.js and hosting platform Vercel to build and deploy performant and reliable web apps?</p>
<p><em>Note: This is a preview of my <a target="_blank" href="https://jamstackhandbook.com/">Jamstack Handbook</a>, a guide to everything you need to know about the Jamstack. It has 3 tutorials, including this one. <a target="_blank" href="https://jamstackhandbook.com/">Get your copy</a> and learn how to build fast, dynamic apps with JavaScript and the static web.</em></p>
<ul>
<li><a class="post-section-overview" href="#heading-what-will-we-build">What will we build?</a></li>
<li><a class="post-section-overview" href="#heading-step-1-getting-started-with-a-nextjs-react-app">Step 1: Getting started with a Next.JS React app</a></li>
<li><a class="post-section-overview" href="#heading-step-2-setting-up-the-project-with-git">Step 2: Setting up the project with Git</a></li>
<li><a class="post-section-overview" href="#heading-step-3-deploying-nextjs-with-vercel">Step 3: Deploying Next.js with Vercel</a></li>
<li><a class="post-section-overview" href="#heading-what-did-we-just-deploy">What did we just deploy?</a></li>
<li><a class="post-section-overview" href="#heading-understanding-modern-ci-cd-with-git">Understanding modern CI / CD with Git</a></li>
<li><a class="post-section-overview" href="#heading-make-a-change-and-watch-it-automatically-deploy">Make a change and watch it automatically deploy</a></li>
<li><a class="post-section-overview" href="#heading-what-did-we-learn">What did we learn?</a></li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/9nV4pIrKmyE" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p><a target="_blank" href="https://nextjs.org/">Next.js</a> is a web framework that’s built and maintained by <a target="_blank" href="https://vercel.com/">Vercel</a>. Next.js makes it easy to spin up a new React application and provides a ton of features out of the box like server side rendering (SSR) and static site generation (SSG).</p>
<h2 id="heading-what-will-we-build">What will we build?</h2>
<p>Our project itself will be relatively simple. We’re going to use the default Next.js Starter as a way to easily bootstrap the project, learn how to configure Next.js to statically compile, and then deploy that project with our customizations to Vercel.</p>
<blockquote>
<p>A Starter is a template that allows developers to recreate that template from the command line. When installing the starter, the framework will set up the project and install all dependencies.</p>
</blockquote>
<h2 id="heading-step-1-getting-started-with-a-nextjs-react-app">Step 1: Getting started with a Next.JS React app</h2>
<p>To get started, we first want to navigate to the directory we want to create our project in.</p>
<p>We’ll use a Starter to create our project. To do this, we have two options for a package manager to use: yarn or npm. You can choose whichever you feel more comfortable with for the remainder of the walkthrough.</p>
<pre><code>yarn create next-app
# or
npx create-next-app
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2020/09/yarn-create-next-app.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Creating a new Next.js app</em></p>
<p>When running this command, Next.js will first ask you for a project name. Here we can use any name we want to identify the project. I’m going to use my-nextjs-app.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/nextjs-project-name.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Naming a Next.js project</em></p>
<p>Once installation is finished, we’re now ready to get started with Next.js.</p>
<p>Navigate in your terminal to the new directory where your project is located and run:</p>
<pre><code>yarn dev
# or
npm run dev
</code></pre><p>This will start your development server, which will make your new site available at <a target="_blank" href="http://localhost:3000">http://localhost:3000</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/nextjs-dev-server.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Starting Next.js development server</em></p>
<p>If you open up your <a target="_blank" href="http://localhost:3000">http://localhost:3000</a> address, you should now see the Next.js default project!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/nextjs-default-starter.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New Next.js app</em></p>
<h2 id="heading-step-2-setting-up-the-project-with-git">Step 2: Setting up the project with Git</h2>
<p>You'll want to set this next step up on your own. Create a new repository with your favorite Git provider that’s supported by Vercel.</p>
<p>At the time of writing this, <a target="_blank" href="https://vercel.com/docs/git-integrations">Vercel supports GitHub, Gitlab, and Bitbucket</a>.</p>
<p>If you’re choosing a provider for the first time, GitHub is a solid option and is easy to get started.</p>
<p>You’ll then want to add your project to that new repository and push the project up to Git.</p>
<blockquote>
<p>Need help? Check out “Adding an existing project to GitHub using the command line” <a target="_blank" href="https://docs.github.com/en/github/importing-your-projects-to-github/adding-an-existing-project-to-github-using-the-command-line">https://docs.github.com/en/github/importing-your-projects-to-github/adding-an-existing-project-to-github-using-the-command-line</a></p>
</blockquote>
<p>For the rest of this walkthrough, I’ll be referencing GitHub, but the instructions should be the same for any supported provider.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/nextjs-app-github.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Next.js app on GitHub</em></p>
<h2 id="heading-step-3-deploying-nextjs-with-vercel">Step 3: Deploying Next.js with Vercel</h2>
<p>Once your project is set up with GitHub, navigate to vercel.com and log in.</p>
<p>If you don’t already have a Vercel account, you should create one now. I would recommend creating an account with your GitHub account as it will help you import your project.</p>
<p>Inside the Vercel dashboard, click <strong>Import Project</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/vercel-import-project.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Import project to Vercel</em></p>
<p>Next, under Import Git Repository, click <strong>Continue</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/vercel-import-git-repository.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Import Git repository to Vercel</em></p>
<p>Vercel will now ask for the repository URL. This will be the homepage for the repository you just created for your project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/vercel-git-repo-url.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Add Git repo URL to Vercel</em></p>
<p>After you click Continue, Vercel has already detected that your project uses Next.js. This means that we don’t need to set up and custom configurations, and we can hit Deploy!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/vercel-deploy-nextjs.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Deploy Next.js project to Vercel</em></p>
<p>At this point, Vercel will get to work and start to build the new project and deploy it to their infrastructure.</p>
<p>Once it’s finished, it will congratulate you and give you a link to visit your site.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/vercel-new-site-deployed.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Vercel project successfully deployed</em></p>
<p>Click Visit and you’ll be directed to your project live on the internet:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/nextjs-app-on-vercel.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Next.js app live</em></p>
<h2 id="heading-what-did-we-just-deploy">What did we just deploy?</h2>
<p>We just created a new React app with Next.js and deployed it to Vercel.</p>
<p>We’ll walk through each specific step:</p>
<ul>
<li><strong>Create Next App:</strong> We first created a new Next.js project on our computer. This provided us with a new React application complete with dependencies and code to get started with a basic website.</li>
<li><strong>Add Project to Git:</strong> We added our new Next.js project to a Git repository online that’s supported by Vercel. This allows us to easily interface with the project with other services like Vercel.</li>
<li><strong>Connect Git to Vercel:</strong> We imported our project from Git into Vercel. This allowed Vercel to interact with our code.</li>
<li><strong>Build &amp; Deploy with Vercel:</strong> Vercel downloaded our code, was able to recognize it was a Next.js project, built our project, and deployed the compiled output to its infrastructure and made it available on the web.</li>
</ul>
<p>If you were waiting for more steps to get your project out to the world, there are none! The entry point for publishing a new React project is now lower than it’s ever been and Next.js and Vercel are helping you get there.</p>
<h2 id="heading-understanding-modern-ci-cd-with-git">Understanding modern CI / CD with Git</h2>
<p>Another benefit of modern infrastructure providers like Vercel, is that when utilizing GitHub as a service connection, Vercel can watch for changes on our main branch.</p>
<p>Once Vercel recognizes that a change was made, it will download the latest code and re-run the same process as we did the first time (aside from any caching and optimization).</p>
<p>This means that any time we have new changes to our production branch, they’ll automatically be deployed. </p>
<h2 id="heading-make-a-change-and-watch-it-automatically-deploy">Make a change and watch it automatically deploy</h2>
<p>To test out the automatic deployments, let’s make a change to our project.</p>
<p>Inside our project, let’s make a change to some of the page content inside of <code>pages/index.js</code>. I’m going to change the title to “Colby’s Next.js Project”.</p>
<pre><code class="lang-jsx">&lt;h1 className={styles.title}&gt;
  Colby<span class="hljs-string">'s Next.js App
&lt;/h1&gt;</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/colbys-nextjs-app.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Next.js app with change</em></p>
<p>Next, commit this change to your main Git branch and push it up to GitHub.</p>
<p>If you wait a few seconds and navigate back to <a target="_blank" href="https://vercel.com">vercel.com</a>, find your project and click on the Deployments tab.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/vercel-deployments.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Vercel deployment when change detected</em></p>
<p>You’ll see that your project is now running or might have already finished if you weren’t quick enough. Now if you open your website link again, you’ll see the changes deployed!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/deployed-nextjs-app-vercel.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Deployed changed Next.js app to Vercel</em></p>
<h2 id="heading-what-did-we-learn">What did we learn?</h2>
<p>Next.js is a web framework that allows us to quickly and easily spin up a new React application. </p>
<p>This, along with other similar frameworks, can be useful to get immediately productive instead of spending time building the project framework ourselves.</p>
<p>Vercel is a hosting and deployment platform that allows us to integrate with our favorite supported Git provider. Once connected, Vercel will download our project, build our project, and deploy the output to the internet.</p>
<p>Modern infrastructure tools like Vercel will watch for changes on our Git repository and will build and deploy our project so that we’re always seeing the latest version.</p>
<h2 id="heading-learn-more-about-the-jamstack">Learn more about the Jamstack!</h2>
<p>You can learn more about the Jamstack, including 2 more in depth tutorials, with my Jamstack Handbook.</p>
<p>
    <a href="https://jamstackhandbook.com/">
        <img src="https://www.freecodecamp.org/news/content/images/2020/09/jamstack-handbook-social.jpg" alt="Jamstack Handbook: Building fast, dynamic apps with Javascript and the static web" width="600" height="400" loading="lazy">
        Order at jamstackhandbook.com
    </a>
</p>

<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">? Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">? Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a>
    </li>
    <li>
      <a href="https://github.com/sponsors/colbyfayock">? Sponsor Me</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Enable Offline Mode for Your Gatsby Site ]]>
                </title>
                <description>
                    <![CDATA[ By Ondrej Polesny One of the reasons we create JAMstack sites is because of their great performance. Serving static files is easy and quick. But what if we upgrade the visitor's experience and make the site available offline? Looking at both recent r... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-enable-offline-mode-for-gatsby-site/</link>
                <guid isPermaLink="false">66d4608f9f2bec37e2da0662</guid>
                
                    <category>
                        <![CDATA[ Gatsby ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JAMstack ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 09 Jun 2020 15:15:41 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/06/gatsby-offline-article.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Ondrej Polesny</p>
<p>One of the reasons we create JAMstack sites is because of their great performance. Serving static files is easy and quick. But what if we upgrade the visitor's experience and make the site available offline?</p>
<p>Looking at both recent reports on the State of the JAMstack in 2020 (you can check out <a target="_blank" href="https://tracker.kontent.ai/942894/the-state-of-jamstack-report-2020">Kontent's report</a> and <a target="_blank" href="https://www.netlify.com/blog/2020/05/27/state-of-the-jamstack-survey-2020-first-results/">Netlify's report</a>) it's clear that performance is the main reason we are building static sites. </p>
<p>I call this fact a bit of a cheat. Performance benefit comes with the JAMstack by design, so it's like calling puppies cute. They're always cute because they're puppies.</p>
<p>If we're really serious about performance, though, even JAMstack sites can do better. But before we can dive into offline mode for Gatsby, we must understand how Gatsby serves pages:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/gatsby-site.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The visitor does not request every single HTML file from the server. Rather, Gatsby's JS client asks the server for the <em>page-data.json</em> of the respective page. That's how the visitor transitions into the requested page without that classic page reload. But even for that we need the network.</p>
<h2 id="heading-why-do-websites-even-need-an-offline-mode">Why do websites even need an offline mode?</h2>
<p>These days, everyone is online, right? An internet connection in mobile phones no longer seems like an option, but a requirement. We use apps like Whatsapp, Messenger, and others all the time. </p>
<p>But what if we step inside an elevator? What if we're walking to a car parked in an underground garage or driving through a tunnel? What if we're inside a plane that's about to take off?</p>
<p>No reception. That's what all these places share. And the only thing people can do with their phones without reception is to watch downloaded Netflix movies. Until you enable offline mode for your website.</p>
<h2 id="heading-how-does-it-work">How does it work?</h2>
<p>In a nutshell, we save the visitor the round-trip to the server and download all the necessary data in advance. And we install a ServiceWorker which acts as a server instead of a real remote server. </p>
<p>A ServiceWorker is a script that the visitor's browser runs in the background and enables features like push notifications and others. See <a target="_blank" href="https://developers.google.com/web/fundamentals/primers/service-workers">Google docs</a> for more information.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/gatsby-service-worker.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>With Gatsby, just like we're all used to, it's as simple as installing a plugin:</p>
<pre><code>npm i gatsby-offline-plugin --save
</code></pre><p>And adding it to the <code>gatsby-config.js</code>:</p>
<pre><code class="lang-javascript">plugins: [
    ...
    <span class="hljs-string">`gatsby-plugin-offline`</span>,
    ...
]
</code></pre>
<p>But every website uses many different types of assets, so typically, we need to take one additional step and configure the service worker.</p>
<h2 id="heading-assets-serving-strategies">Assets serving strategies</h2>
<p>Every website contains many assets ranging from CSS files through images and icons to web fonts and actual page data. </p>
<p>The service worker cannot really download all these assets during the first page load as that would go directly against the performance benefit. Visitors would also not be happy if their browsers started downloading 100MB of images the moment they decided to visit your photo gallery.</p>
<p>We can use regular expressions to target specific files and configure the service worker to treat them appropriately. Let's take a look at the available strategies:</p>
<h3 id="heading-cachefirst">CacheFirst</h3>
<p>Typical use: web fonts, stylesheets</p>
<p>The service worker checks the cache for the requested file. If the file's missing, it goes online to fetch it while storing it in the cache for future use.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/cache-first.png" alt="Image" width="600" height="400" loading="lazy">
<em>Image credit: <a target="_blank" href="https://developers.google.com/web/tools/workbox/modules/workbox-strategies">https://developers.google.com/web/tools/workbox/modules/workbox-strategies</a></em></p>
<h3 id="heading-cacheonly">CacheOnly</h3>
<p>Possible use: your own pre-caching logic</p>
<p>The service worker checks the cache for the requested file. If the file's missing, it returns an error.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/cache-only.png" alt="Image" width="600" height="400" loading="lazy">
<em>Image credit: <a target="_blank" href="https://developers.google.com/web/tools/workbox/modules/workbox-strategies">https://developers.google.com/web/tools/workbox/modules/workbox-strategies</a></em></p>
<h3 id="heading-networkfirst">NetworkFirst</h3>
<p>Typical use: non-critical API requests</p>
<p>The service worker goes online to fetch the requested file. If the network is down or server unresponsive, it falls back to the cache.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/network-first.png" alt="Image" width="600" height="400" loading="lazy">
<em>Image credit: <a target="_blank" href="https://developers.google.com/web/tools/workbox/modules/workbox-strategies">https://developers.google.com/web/tools/workbox/modules/workbox-strategies</a></em></p>
<h3 id="heading-networkonly">NetworkOnly</h3>
<p>Typical use: critical API requests</p>
<p>The service worker goes online to fetch the requested file. If the network is down or server unresponsive, it returns an error.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/network-only.png" alt="Image" width="600" height="400" loading="lazy">
<em>Image credit: <a target="_blank" href="https://developers.google.com/web/tools/workbox/modules/workbox-strategies">https://developers.google.com/web/tools/workbox/modules/workbox-strategies</a></em></p>
<h3 id="heading-stalewhilerevalidate">StaleWhileRevalidate</h3>
<p>Typical use: front-end assets, images</p>
<p>The service worker checks the cache for the requested file and provides it. Subsequently, it makes a network request to silently update the cache.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/stale-while-revalidate.png" alt="Image" width="600" height="400" loading="lazy">
<em>Image credit: <a target="_blank" href="https://developers.google.com/web/tools/workbox/modules/workbox-strategies">https://developers.google.com/web/tools/workbox/modules/workbox-strategies</a></em></p>
<h2 id="heading-configuring-the-gatsby-site">Configuring the Gatsby site</h2>
<p>A simple configuration of a Gatsby site that should work offline looks like this:</p>
<pre><code class="lang-javascript">{
    <span class="hljs-attr">resolve</span>: <span class="hljs-string">`gatsby-plugin-offline`</span>,
    <span class="hljs-attr">options</span>: {
        <span class="hljs-attr">precachePages</span>: [<span class="hljs-string">`/blog/*`</span>],
    },
}
</code></pre>
<p>This way I'm configuring the service worker to pre-cache all blog posts, which are all pages whose URL starts with <code>/blog/</code>. </p>
<p>Once the visitor accesses the index page with links to blog posts, they will be able to click-through to any of them without an active internet connection. That is, if you use the <code>Link</code> element in the implementation. Standard anchor tags make a browser go around the service worker and fetch data from remote.</p>
<p>The service worker will treat all assets according to its default configuration:</p>
<ul>
<li><strong>CacheFirst</strong><br>JS files, CSS files, everything inside folder "static/"</li>
<li><strong>NetworkFirst</strong><br><em>/page-data/</em>/page-data.json files</li>
<li><strong>StaleWhileRevalidate</strong><br>images, web font files, etc.</li>
</ul>
<p>So if you're worried that the service worker will fetch all assets of all blog posts, it will do so only after the visitor actually opens the blog post page. </p>
<p>The reason is, cache space and the visitor's internet connection bandwidth are limited. On the first page load, the visitor downloads all the site-wide assets like stylesheets, web fonts, icons, and others, so these assets will be available in the cache on subsequent loads. Images and other resources of pre-cached pages will be resolved once the page is requested and this can be changed only via custom logic.</p>
<p>So in which cases would you want to change the config? There were actually not many cases I could come up with, but I did stumble upon a few:</p>
<ul>
<li><strong>Assets provided from URLs without matching filename suffix</strong><br>Google serves CSS definitions of web fonts without the .css suffix and that is already covered by the default config. However, you may be serving images or other assets from URLs that don't have the appropriate suffix.</li>
<li><strong>Gain more control over the cache</strong><br>With some assets you want to be in charge of how long a certain item can reside in cache until it becomes expired.</li>
<li><strong>Exotic assets</strong><br>Alright, exotic may be a bit strong word :-) but web fonts in EOT format, pictures in HEIC format, short videos, songs, etc.</li>
</ul>
<p>In these cases you need to adjust the default configuration and define it within the plugin options:</p>
<pre><code class="lang-javascript">{
  <span class="hljs-attr">resolve</span>: <span class="hljs-string">`gatsby-plugin-offline`</span>,
  <span class="hljs-attr">options</span>: {
    <span class="hljs-attr">precachePages</span>: [<span class="hljs-string">`/blog/*`</span>],
    <span class="hljs-attr">runtimeCaching</span>: [
      <span class="hljs-comment">// previous definitions from the default config</span>
      (...),
      {
        <span class="hljs-attr">urlPattern</span>: <span class="hljs-regexp">/^https:\/\/fonts\.gstatic\.com/</span>,
        handler: <span class="hljs-string">'cacheFirst'</span>,
        <span class="hljs-attr">options</span>: {
          <span class="hljs-attr">cacheableResponse</span>: {
            <span class="hljs-attr">statuses</span>: [<span class="hljs-number">0</span>, <span class="hljs-number">200</span>]
          },
          <span class="hljs-attr">cacheName</span>: <span class="hljs-string">'google-fonts-webfonts'</span>,
          <span class="hljs-attr">expiration</span>: {
            <span class="hljs-attr">maxAgeSeconds</span>: <span class="hljs-number">60</span> * <span class="hljs-number">60</span>,
            <span class="hljs-attr">maxEntries</span>: <span class="hljs-number">30</span>
          }
        }
      },
    ]
  },
},
</code></pre>
<p>This additional config item will ensure that at most 30 Google fonts served from gstatic.com will be cached for a maximum duration of one hour and will be handled using the CacheFirst strategy.</p>
<h3 id="heading-build-the-site-before-testing">Build the Site Before Testing</h3>
<p>Once you are finished with the configuration, make sure to build and serve the site before testing the offline capabilities. They don't work in development mode.</p>
<pre><code>gatsby build &amp;&amp; gatsby serve
</code></pre><h2 id="heading-jamstack-performance-but">JAMstack = performance, but...</h2>
<p>In this article I showed you how to install and configure the offline plugin for Gatsby.</p>
<p> All JAMstack sites come with the great benefit of amazing performance by design. By adding offline capabilities, you are taking the browsing experience of your visitors to the next level compared to other JAMstack sites. The service worker configuration allows you to further fine-tune how each asset will be handled and cached.</p>
<p>If you're interested, you can find more information about the plugin in the <a target="_blank" href="https://www.gatsbyjs.org/packages/gatsby-plugin-offline/">Gatsby docs</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Hugo vs Jekyll: an Epic Battle of Static Site Generator Themes ]]>
                </title>
                <description>
                    <![CDATA[ In this article, we'll compare the nuances of creating themes for the top two static site generators. I recently took on the task of creating a documentation site theme for two projects. Both projects needed the same basic features, but one uses Jeky... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/hugo-vs-jekyll-battle-of-static-site-generator-themes/</link>
                <guid isPermaLink="false">66bd8f5f27629f4c5e1893b2</guid>
                
                    <category>
                        <![CDATA[ Hugo ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JAMstack ]]>
                    </category>
                
                    <category>
                        <![CDATA[ jekyll ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Static Site Generators ]]>
                    </category>
                
                    <category>
                        <![CDATA[ themes ]]>
                    </category>
                
                    <category>
                        <![CDATA[ website development, ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Victoria Drake ]]>
                </dc:creator>
                <pubDate>Mon, 27 Apr 2020 13:42:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/04/cover-2.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, we'll compare the nuances of creating themes for the top two static site generators.</p>
<p>I recently took on the task of creating a documentation site theme for two projects. Both projects needed the same basic features, but one uses Jekyll while the other uses Hugo.</p>
<p>In typical developer rationality, there was clearly only one option. I decided to create the same theme in both frameworks, and to give you, dear reader, a side-by-side comparison.</p>
<p>This post isn’t a comprehensive theme-building guide, but is rather intended to familiarize you with the process of building a theme in either generator. Here's what we'll cover:</p>
<ul>
<li>How theme files are organized</li>
<li>Where to put content</li>
<li>How templating works</li>
<li>Creating a top-level menu with the <code>pages</code> object</li>
<li>Creating a menu with nested links from a data list</li>
<li>Putting the template together</li>
<li>Creating styles</li>
<li>How to configure and deploy to GitHub Pages</li>
</ul>
<p>Here’s a crappy wireframe of the theme I’m going to create.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/wireframe.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>If you’re planning to build-along, it may be helpful to serve the theme locally as you build it – and both generators offer this functionality. For Jekyll, run <code>jekyll serve</code>, and for Hugo, <code>hugo serve</code>.</p>
<p>There are two main elements: the main content area, and the all-important sidebar menu. To create them, you’ll need template files that tell the site generator how to generate the HTML page. To organize theme template files in a sensible way, you first need to know what  directory structure the site generator expects.</p>
<h2 id="heading-how-theme-files-are-organized">How theme files are organized</h2>
<p>Jekyll supports gem-based themes, which users can install like any other Ruby gems. This method hides theme files in the gem, so for the purposes of this comparison, we aren’t using gem-based themes.</p>
<p>When you run <code>jekyll new-theme &lt;name&gt;</code>, Jekyll will scaffold a new theme for you. Here’s what those files look like:</p>
<pre><code class="lang-sh">.
├── assets
├── Gemfile
├── _includes
├── _layouts
│   ├── default.html
│   ├── page.html
│   └── post.html
├── LICENSE.txt
├── README.md
├── _sass
└── &lt;name&gt;.gemspec
</code></pre>
<p>The directory names are appropriately descriptive. The <code>_includes</code> directory is for small bits of code that you reuse in different places,  in much the same way you’d put butter on everything. (Just me?) </p>
<p>The <code>_layouts</code> directory contains templates for different types of pages on your site. The <code>_sass</code> folder is for <a target="_blank" href="https://sass-lang.com/documentation/syntax">Sass</a> files used to build your site’s stylesheet.</p>
<p>You can scaffold a new Hugo theme by running <code>hugo new theme &lt;name&gt;</code>. It has these files:</p>
<pre><code class="lang-sh">.
├── archetypes
│   └── default.md
├── layouts
│   ├── 404.html
│   ├── _default
│   │   ├── baseof.html
│   │   ├── list.html
│   │   └── single.html
│   ├── index.html
│   └── partials
│       ├── footer.html
│       ├── header.html
│       └── head.html
├── LICENSE
├── static
│   ├── css
│   └── js
└── theme.toml
</code></pre>
<p>You can see some similarities. Hugo’s page template files are tucked into <code>layouts/</code>. Note that the <code>_default</code> page type has files for a <code>list.html</code> and a <code>single.html</code>. </p>
<p>Unlike Jekyll, Hugo uses these specific file names to distinguish between <a target="_blank" href="https://gohugo.io/templates/lists/">list pages</a> (like a page with links to all your blog posts on it) and <a target="_blank" href="https://gohugo.io/templates/single-page-templates/">single pages</a> (like one of your blog posts). The <code>layouts/partials/</code> directory contains the buttery reusable bits, and stylesheet files have a spot picked out in <code>static/css/</code>.</p>
<p>These directory structures aren’t set in stone, as both site generators allow some measure of customization. For example, Jekyll lets  you define <a target="_blank" href="https://jekyllrb.com/docs/collections/">collections</a>, and Hugo makes use of <a target="_blank" href="https://gohugo.io/content-management/page-bundles/">page bundles</a>. These features let you organize your content multiple ways, but for now, let's look at where to put some simple pages.</p>
<h2 id="heading-where-to-put-content">Where to put content</h2>
<p>To create a site menu that looks like this:</p>
<pre><code class="lang-md">Introduction
<span class="hljs-code">    Getting Started
    Configuration
    Deploying
Advanced Usage
    All Configuration Settings
    Customizing
    Help and Support</span>
</code></pre>
<p>You’ll need two sections (“Introduction” and “Advanced Usage”) containing their respective subsections.</p>
<p>Jekyll isn’t strict with its content location. It expects pages in the root of your site, and will build whatever’s there. Here’s how you might organize these pages in your Jekyll site root:</p>
<pre><code class="lang-sh">.
├── 404.html
├── assets
├── Gemfile
├── _includes
├── index.markdown
├── intro
│   ├── config.md
│   ├── deploy.md
│   ├── index.md
│   └── quickstart.md
├── _layouts
│   ├── default.html
│   ├── page.html
│   └── post.html
├── LICENSE.txt
├── README.md
├── _sass
├── &lt;name&gt;.gemspec
└── usage
    ├── customizing.md
    ├── index.md
    ├── settings.md
    └── support.md
</code></pre>
<p>You can change the location of the site source in your <a target="_blank" href="https://jekyllrb.com/docs/configuration/default/">Jekyll configuration</a>.</p>
<p>In Hugo, all rendered content is expected in the <code>content/</code> folder. This prevents Hugo from trying to render pages you don’t want, such as <code>404.html</code>, as site content. Here’s how you might organize your <code>content/</code> directory in Hugo:</p>
<pre><code class="lang-sh">.
├── _index.md
├── intro
│   ├── config.md
│   ├── deploy.md
│   ├── _index.md
│   └── quickstart.md
└── usage
    ├── customizing.md
    ├── _index.md
    ├── settings.md
    └── support.md
</code></pre>
<p>To Hugo, <code>_index.md</code> and <code>index.md</code> mean different things. It can be helpful to know what kind of <a target="_blank" href="https://gohugo.io/content-management/page-bundles/">Page Bundle</a> you want for each section: Leaf, which has no children, or Branch.</p>
<p>Now that you have some idea of where to put things, let’s look at how to build a page template.</p>
<h2 id="heading-how-templating-works">How templating works</h2>
<p>Jekyll page templates are built with the <a target="_blank" href="https://jekyllrb.com/docs/liquid/">Liquid templating language</a>. It uses braces to output variable content to a page, such as the page’s title: <code>{{ page.title }}</code>.</p>
<p>Hugo’s templates also use braces, but they’re built with <a target="_blank" href="https://gohugo.io/templates/introduction/">Go Templates</a>. The syntax is similar, but different: <code>{{ .Title }}</code>.</p>
<p>Both Liquid and Go Templates can handle logic. Liquid uses <em>tags</em> syntax to denote logic operations:</p>
<pre><code class="lang-liquid">{% if user %}
  Hello {{ user.name }}!
{% endif %}
</code></pre>
<p>And Go Templates places its functions and arguments in its braces syntax:</p>
<pre><code class="lang-go">{{ <span class="hljs-keyword">if</span> .User }}
    Hello {{ .User }}!
{{ end }}
</code></pre>
<p>Templating languages allow you to build one  skeleton HTML page, then tell the site generator to put variable content in areas you define. Let’s compare two possible <code>default</code> page templates for Jekyll and Hugo.</p>
<p>Jekyll’s scaffold <code>default</code> theme is bare, so we’ll look at their starter theme <a target="_blank" href="https://github.com/jekyll/minima">Minima</a>. Here’s <code>_layouts/default.html</code> in Jekyll (Liquid):</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"{{ page.lang | default: site.lang | default: "</span><span class="hljs-attr">en</span>" }}"&gt;</span>

  {%- include head.html -%}

  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>

    {%- include header.html -%}

    <span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"page-content"</span> <span class="hljs-attr">aria-label</span>=<span class="hljs-string">"Content"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"wrapper"</span>&gt;</span>
        {{ content }}
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>

    {%- include footer.html -%}

  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>Here’s Hugo’s scaffold theme <code>layouts/_default/baseof.html</code> (Go Templates):</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
    {{- partial "head.html" . -}}
    <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
        {{- partial "header.html" . -}}
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"content"</span>&gt;</span>
        {{- block "main" . }}{{- end }}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        {{- partial "footer.html" . -}}
    <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>Different syntax, same idea. Both templates pull in reusable bits for <code>head.html</code>, <code>header.html</code>, and <code>footer.html</code>.  These show up on a lot of pages, so it makes sense not to have to  repeat yourself. </p>
<p>Both templates also have a spot for the main content, though the Jekyll template uses a variable (<code>{{ content }}</code>) while Hugo uses a block (<code>{{- block "main" . }}{{- end }}</code>). <a target="_blank" href="https://gohugo.io/templates/base/#readout">Blocks</a> are just another way Hugo lets you define reusable bits.</p>
<p>Now that you know how templating works, you can build the sidebar menu for the theme.</p>
<h2 id="heading-creating-a-top-level-menu-with-the-pages-object">Creating a top-level menu with the <code>pages</code> object</h2>
<p>You can programmatically create a top-level menu from your pages. It will look like this:</p>
<pre><code class="lang-md">Introduction
Advanced Usage
</code></pre>
<p>Let’s start with Jekyll. You can display links to site pages in your Liquid template by iterating through the <code>site.pages</code> object that Jekyll provides and building a list:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
    {% for page in site.pages %}
    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ page.url | absolute_url }}"</span>&gt;</span>{{ page.title }}<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    {% endfor %}
<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
</code></pre>
<p>This returns all of the site’s pages, including all the ones that you might not want, like <code>404.html</code>. You can filter for the pages you actually want with a couple more tags, such as conditionally including pages if they have a <code>section: true</code> parameter set:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
    {% for page in site.pages %}
    {%- if page.section -%}
    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ page.url | absolute_url }}"</span>&gt;</span>{{ page.title }}<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    {%- endif -%}
    {% endfor %}
<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
</code></pre>
<p>You can achieve the same effect with slightly less code in Hugo. Loop through Hugo’s <code>.Pages</code> object using Go Template’s <a target="_blank" href="https://golang.org/pkg/text/template/#hdr-Actions"><code>range</code> action</a>:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
{{ range .Pages }}
    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{.Permalink}}"</span>&gt;</span>{{.Title}}<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
{{ end }}
<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
</code></pre>
<p>This template uses the <code>.Pages</code> object to return all the top-level pages in <code>content/</code> of your Hugo site. Since Hugo uses a specific folder for the site content you want rendered, there’s no additional filtering necessary to build a simple menu of site pages.</p>
<h2 id="heading-creating-a-menu-with-nested-links-from-a-data-list">Creating a menu with nested links from a data list</h2>
<p>Both site generators can use a separately defined data list of links to render a menu in your template. This is more suitable for creating nested links, like this:</p>
<pre><code class="lang-md">Introduction
<span class="hljs-code">    Getting Started
    Configuration
    Deploying
Advanced Usage
    All Configuration Settings
    Customizing
    Help and Support</span>
</code></pre>
<p>Jekyll supports <a target="_blank" href="https://jekyllrb.com/docs/datafiles/">data files</a> in a few formats, including YAML. Here’s the definition for the menu above in <code>_data/menu.yml</code>:</p>
<pre><code class="lang-yml"><span class="hljs-attr">section:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">page:</span> <span class="hljs-string">Introduction</span>
    <span class="hljs-attr">url:</span> <span class="hljs-string">/intro</span>
    <span class="hljs-attr">subsection:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">page:</span> <span class="hljs-string">Getting</span> <span class="hljs-string">Started</span>
        <span class="hljs-attr">url:</span> <span class="hljs-string">/intro/quickstart</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">page:</span> <span class="hljs-string">Configuration</span>
        <span class="hljs-attr">url:</span> <span class="hljs-string">/intro/config</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">page:</span> <span class="hljs-string">Deploying</span>
        <span class="hljs-attr">url:</span> <span class="hljs-string">/intro/deploy</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">page:</span> <span class="hljs-string">Advanced</span> <span class="hljs-string">Usage</span>
    <span class="hljs-attr">url:</span> <span class="hljs-string">/usage</span>
    <span class="hljs-attr">subsection:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">page:</span> <span class="hljs-string">Customizing</span>
        <span class="hljs-attr">url:</span> <span class="hljs-string">/usage/customizing</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">page:</span> <span class="hljs-string">All</span> <span class="hljs-string">Configuration</span> <span class="hljs-string">Settings</span>
        <span class="hljs-attr">url:</span> <span class="hljs-string">/usage/settings</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">page:</span> <span class="hljs-string">Help</span> <span class="hljs-string">and</span> <span class="hljs-string">Support</span>
        <span class="hljs-attr">url:</span> <span class="hljs-string">/usage/support</span>
</code></pre>
<p>Here’s how to render the data in the sidebar template:</p>
<pre><code class="lang-html">{% for a in site.data.menu.section %}
<span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ a.url }}"</span>&gt;</span>{{ a.page }}<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
    {% for b in a.subsection %}
    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ b.url }}"</span>&gt;</span>{{ b.page }}<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    {% endfor %}
<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
{% endfor %}
</code></pre>
<p>This method allows you to build a custom menu, two nesting levels deep. The nesting levels are limited by the <code>for</code> loops in the template. For a recursive version that handles further levels of nesting, see <a target="_blank" href="https://jekyllrb.com/tutorials/navigation/#scenario-9-nested-tree-navigation-with-recursion">Nested tree navigation with recursion</a>.</p>
<p>Hugo does something similar with its <a target="_blank" href="https://gohugo.io/templates/menu-templates/#section-menu-for-lazy-bloggers">menu templates</a>. You can define menu links in your <a target="_blank" href="https://gohugo.io/getting-started/configuration/">Hugo site config</a>, and even add useful properties that Hugo understands, like weighting. Here’s a definition of the menu above in <code>config.yaml</code>:</p>
<pre><code class="lang-yml"><span class="hljs-attr">sectionPagesMenu:</span> <span class="hljs-string">main</span>

<span class="hljs-attr">menu:</span>  
  <span class="hljs-attr">main:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">identifier:</span> <span class="hljs-string">intro</span>
      <span class="hljs-attr">name:</span> <span class="hljs-string">Introduction</span>
      <span class="hljs-attr">url:</span> <span class="hljs-string">/intro/</span>
      <span class="hljs-attr">weight:</span> <span class="hljs-number">1</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Getting</span> <span class="hljs-string">Started</span>
      <span class="hljs-attr">parent:</span> <span class="hljs-string">intro</span>
      <span class="hljs-attr">url:</span> <span class="hljs-string">/intro/quickstart/</span>
      <span class="hljs-attr">weight:</span> <span class="hljs-number">1</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Configuration</span>
      <span class="hljs-attr">parent:</span> <span class="hljs-string">intro</span>
      <span class="hljs-attr">url:</span> <span class="hljs-string">/intro/config/</span>
      <span class="hljs-attr">weight:</span> <span class="hljs-number">2</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Deploying</span>
      <span class="hljs-attr">parent:</span> <span class="hljs-string">intro</span>
      <span class="hljs-attr">url:</span> <span class="hljs-string">/intro/deploy/</span>
      <span class="hljs-attr">weight:</span> <span class="hljs-number">3</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">identifier:</span> <span class="hljs-string">usage</span>
      <span class="hljs-attr">name:</span> <span class="hljs-string">Advanced</span> <span class="hljs-string">Usage</span>
      <span class="hljs-attr">url:</span> <span class="hljs-string">/usage/</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Customizing</span>
      <span class="hljs-attr">parent:</span> <span class="hljs-string">usage</span>
      <span class="hljs-attr">url:</span> <span class="hljs-string">/usage/customizing/</span>
      <span class="hljs-attr">weight:</span> <span class="hljs-number">2</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">All</span> <span class="hljs-string">Configuration</span> <span class="hljs-string">Settings</span>
      <span class="hljs-attr">parent:</span> <span class="hljs-string">usage</span>
      <span class="hljs-attr">url:</span> <span class="hljs-string">/usage/settings/</span>
      <span class="hljs-attr">weight:</span> <span class="hljs-number">1</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Help</span> <span class="hljs-string">and</span> <span class="hljs-string">Support</span>
      <span class="hljs-attr">parent:</span> <span class="hljs-string">usage</span>
      <span class="hljs-attr">url:</span> <span class="hljs-string">/usage/support/</span>
      <span class="hljs-attr">weight:</span> <span class="hljs-number">3</span>
</code></pre>
<p>Hugo uses the <code>identifier</code>, which must match the section name, along with the <code>parent</code> variable to handle nesting. Here’s how to render the menu in the sidebar template:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
    {{ range .Site.Menus.main }}
    {{ if .HasChildren }}
    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ .URL }}"</span>&gt;</span>{{ .Name }}<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"sub-menu"</span>&gt;</span>
        {{ range .Children }}
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ .URL }}"</span>&gt;</span>{{ .Name }}<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        {{ end }}
    <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
    {{ else }}
    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ .URL }}"</span>&gt;</span>{{ .Name }}<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    {{ end }}
    {{ end }}
<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
</code></pre>
<p>The <code>range</code> function iterates over the menu data, and Hugo’s <code>.Children</code> variable handles nested pages for you.</p>
<h2 id="heading-putting-the-template-together">Putting the template together</h2>
<p>With your menu in your reusable sidebar bit (<code>_includes/sidebar.html</code> for Jekyll and <code>partials/sidebar.html</code> for Hugo), you can add it to the <code>default.html</code> template.</p>
<p>In Jekyll:</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"{{ page.lang | default: site.lang | default: "</span><span class="hljs-attr">en</span>" }}"&gt;</span>

{%- include head.html -%}

<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    {%- include sidebar.html -%}

    {%- include header.html -%}

    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"content"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"page-content"</span> <span class="hljs-attr">aria-label</span>=<span class="hljs-string">"Content"</span>&gt;</span>
        {{ content }}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

    {%- include footer.html -%}

<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>In Hugo:</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
{{- partial "head.html" . -}}

<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    {{- partial "sidebar.html" . -}}

    {{- partial "header.html" . -}}
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"content"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"page-content"</span> <span class="hljs-attr">aria-label</span>=<span class="hljs-string">"Content"</span>&gt;</span>
        {{- block "main" . }}{{- end }}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    {{- partial "footer.html" . -}}
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>When the site is generated, each page will contain all the code from your <code>sidebar.html</code>.</p>
<h2 id="heading-create-a-stylesheet">Create a stylesheet</h2>
<p>Both site generators accept Sass for creating CSS stylesheets. Jekyll <a target="_blank" href="https://jekyllrb.com/docs/assets/">has Sass processing built in</a>, and Hugo uses <a target="_blank" href="https://gohugo.io/hugo-pipes/scss-sass/">Hugo Pipes</a>. Both options have some quirks.</p>
<h3 id="heading-sass-and-css-in-jekyll">Sass and CSS in Jekyll</h3>
<p>To process a Sass file in Jekyll, create your style definitions in the <code>_sass</code> directory. For example, in a file at <code>_sass/style-definitions.scss</code>:</p>
<pre><code class="lang-scss"><span class="hljs-variable">$background-color</span>: <span class="hljs-number">#eef</span> !default;
<span class="hljs-variable">$text-color</span>: <span class="hljs-number">#111</span> !default;

<span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-variable">$background-color</span>;
  <span class="hljs-attribute">color</span>: <span class="hljs-variable">$text-color</span>;
}
</code></pre>
<p>Jekyll won’t generate this file directly, as it only processes files with front matter. To create the end-result  filepath for your site’s stylesheet, use a placeholder with empty front matter where you want the <code>.css</code> file to appear. For example, <code>assets/css/style.scss</code>. In this file, simply import your styles:</p>
<pre><code class="lang-scss">---
---

<span class="hljs-keyword">@import</span> <span class="hljs-string">"style-definitions"</span>;
</code></pre>
<p>This rather hackish configuration has an upside: you can use Liquid template tags and variables in your placeholder file. This is a nice way to allow users to set variables from the site <code>_config.yml</code>, for example.</p>
<p>The resulting CSS stylesheet in your generated site has the path <code>/assets/css/style.css</code>. You can link to it in your site’s <code>head.html</code> using:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ "</span>/<span class="hljs-attr">assets</span>/<span class="hljs-attr">css</span>/<span class="hljs-attr">style.css</span>" | <span class="hljs-attr">relative_url</span> }}" <span class="hljs-attr">media</span>=<span class="hljs-string">"screen"</span>&gt;</span>
</code></pre>
<h3 id="heading-sass-and-hugo-pipes-in-hugo">Sass and Hugo Pipes in Hugo</h3>
<p>Hugo uses <a target="_blank" href="https://gohugo.io/hugo-pipes/scss-sass/">Hugo Pipes</a> to process Sass to CSS. You can achieve this by using Hugo’s asset processing function, <code>resources.ToCSS</code>, which expects a source in the <code>assets/</code> directory. It takes the SCSS file as an argument. </p>
<p>With your style definitions in a Sass file at <code>assets/sass/style.scss</code>, here’s how to get, process, and link your Sass in your theme’s <code>head.html</code>:</p>
<pre><code class="lang-html">{{ $style := resources.Get "/sass/style.scss" | resources.ToCSS }}
<span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ $style.RelPermalink }}"</span> <span class="hljs-attr">media</span>=<span class="hljs-string">"screen"</span>&gt;</span>
</code></pre>
<p>Hugo asset processing <a target="_blank" href="https://gohugo.io/troubleshooting/faq/#i-get-tocss--this-feature-is-not-available-in-your-current-hugo-version">requires extended Hugo</a>, which you may not have by default. You can get extended Hugo from the <a target="_blank" href="https://github.com/gohugoio/hugo/releases">releases page</a>.</p>
<h2 id="heading-configure-and-deploy-to-github-pages">Configure and deploy to GitHub Pages</h2>
<p>Before your site generator can build your site, it needs a  configuration file to set some necessary parameters. Configuration files  live in the site root directory. Among other settings, you can declare  the name of the theme to use when building the site.</p>
<h3 id="heading-configure-jekyll">Configure Jekyll</h3>
<p>Here’s a minimal <code>_config.yml</code> for Jekyll:</p>
<pre><code class="lang-yml"><span class="hljs-attr">title:</span> <span class="hljs-string">Your</span> <span class="hljs-string">awesome</span> <span class="hljs-string">title</span>
<span class="hljs-attr">description:</span> <span class="hljs-string">&gt;-</span> <span class="hljs-comment"># this means to ignore newlines until "baseurl:"</span>
  <span class="hljs-string">Write</span> <span class="hljs-string">an</span> <span class="hljs-string">awesome</span> <span class="hljs-string">description</span> <span class="hljs-string">for</span> <span class="hljs-string">your</span> <span class="hljs-string">new</span> <span class="hljs-string">site</span> <span class="hljs-string">here.</span> <span class="hljs-string">You</span> <span class="hljs-string">can</span> <span class="hljs-string">edit</span> <span class="hljs-string">this</span>
  <span class="hljs-string">line</span> <span class="hljs-string">in</span> <span class="hljs-string">_config.yml.</span> <span class="hljs-string">It</span> <span class="hljs-string">will</span> <span class="hljs-string">appear</span> <span class="hljs-string">in</span> <span class="hljs-string">your</span> <span class="hljs-string">document</span> <span class="hljs-string">head</span> <span class="hljs-string">meta</span> <span class="hljs-string">(for</span>
  <span class="hljs-string">Google</span> <span class="hljs-string">search</span> <span class="hljs-string">results)</span> <span class="hljs-string">and</span> <span class="hljs-string">in</span> <span class="hljs-string">your</span> <span class="hljs-string">feed.xml</span> <span class="hljs-string">site</span> <span class="hljs-string">description.</span>
<span class="hljs-attr">baseurl:</span> <span class="hljs-string">""</span> <span class="hljs-comment"># the subpath of your site, e.g. /blog</span>
<span class="hljs-attr">url:</span> <span class="hljs-string">""</span> <span class="hljs-comment"># the base hostname &amp; protocol for your site, e.g. http://example.com</span>
<span class="hljs-attr">theme:</span> <span class="hljs-comment"># for gem-based themes</span>
<span class="hljs-attr">remote_theme:</span> <span class="hljs-comment"># for themes hosted on GitHub, when used with GitHub Pages</span>
</code></pre>
<p>With <code>remote_theme</code>, any <a target="_blank" href="https://help.github.com/en/github/working-with-github-pages/adding-a-theme-to-your-github-pages-site-using-jekyll#adding-a-jekyll-theme-in-your-sites-_configyml-file">Jekyll theme hosted on GitHub can be used</a> with sites hosted on GitHub Pages.</p>
<p>Jekyll has a <a target="_blank" href="https://jekyllrb.com/docs/configuration/default/">default configuration</a>, so any parameters added to your configuration file will override the defaults. Here are <a target="_blank" href="https://jekyllrb.com/docs/configuration/options/">additional configuration settings</a>.</p>
<h3 id="heading-configure-hugo">Configure Hugo</h3>
<p>Here’s a minimal example of Hugo’s <code>config.yml</code>:</p>
<pre><code class="lang-yml"><span class="hljs-attr">baseURL:</span> <span class="hljs-string">https://example.com/</span> <span class="hljs-comment"># The full domain your site will live at</span>
<span class="hljs-attr">languageCode:</span> <span class="hljs-string">en-us</span>
<span class="hljs-attr">title:</span> <span class="hljs-string">Hugo</span> <span class="hljs-string">Docs</span> <span class="hljs-string">Site</span>
<span class="hljs-attr">theme:</span> <span class="hljs-comment"># theme name</span>
</code></pre>
<p>Hugo makes no assumptions, so if a necessary parameter is missing, you’ll see a warning when building or serving your site. Here are <a target="_blank" href="https://gohugo.io/getting-started/configuration/#all-configuration-settings">all configuration settings for Hugo</a>.</p>
<h3 id="heading-deploy-to-github-pages">Deploy to GitHub Pages</h3>
<p>Both generators build your site with a command.</p>
<p>For Jekyll, use <code>jekyll build</code>. See <a target="_blank" href="https://jekyllrb.com/docs/configuration/options/#build-command-options">further build options here</a>.</p>
<p>For Hugo, use <code>hugo</code>. You can run <code>hugo help</code> or see <a target="_blank" href="https://gohugo.io/getting-started/usage/#test-installation">further build options here</a>.</p>
<p>You’ll have to choose the source for your GitHub Pages site. Once done, your site will update each time you push a new build. Of course, you can also automate your GitHub Pages build using GitHub Actions. Here’s one for <a target="_blank" href="https://github.com/victoriadrake/hugo-latest-cd">building and deploying with Hugo</a>, and one for <a target="_blank" href="https://github.com/victoriadrake/jekyll-cd">building and deploying Jekyll</a>.</p>
<h2 id="heading-showtime">Showtime!</h2>
<p>All the substantial differences between these two generators are under the hood. All the same, let’s take a look at the finished themes, in two color variations.</p>
<p>Here’s Hugo:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/ogd_hugo.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Here's Jekyll:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/ogd_jekyll.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-wait-who-won">Wait who won?</h2>
<p>?</p>
<p>Both Hugo and Jekyll have their quirks and conveniences.</p>
<p>From this developer’s perspective, Jekyll is a workable choice for simple sites without complicated organizational needs. If you’re looking to render some one-page posts in an <a target="_blank" href="https://jekyllrb.com/docs/themes/">available theme</a> and host with GitHub Pages, Jekyll will get you up and running fairly quickly.</p>
<p>Personally, I use Hugo. I like the organizational capabilities of its Page Bundles, and it’s backed by a dedicated and conscientious team that really seems to strive to facilitate convenience for their users. This is evident in Hugo’s many functions, and handy tricks like <a target="_blank" href="https://gohugo.io/content-management/image-processing/">Image Processing</a> and <a target="_blank" href="https://gohugo.io/content-management/shortcodes/">Shortcodes</a>. They seem to release new fixes and versions about as often as I make a new cup of coffee - which, depending on your use case, may be fantastic, or annoying.</p>
<p>If you still can’t decide, don’t worry. The <a target="_blank" href="https://github.com/opengitdocs">OpenGitDocs documentation theme</a> I created is available for both Hugo and Jekyll. Start with one, switch later if you want. That’s the benefit of having options.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to set up a custom Mapbox basemap style with React Leaflet and Leaflet Gatsby Starter ]]>
                </title>
                <description>
                    <![CDATA[ Building maps can be pretty powerful, but often you’re stuck with open source options for the map imagery that might not help the readability of your data. How can we leverage Mapbox’s tile APIs to add a custom basemap to our React Leaflet app? What... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-set-up-a-custom-mapbox-basemap-with-gatsby-and-react-leaflet/</link>
                <guid isPermaLink="false">66b8e36647c23b7ae1ad0bdb</guid>
                
                    <category>
                        <![CDATA[ create-react-app ]]>
                    </category>
                
                    <category>
                        <![CDATA[ front end ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Front-end Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ frontend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Gatsby ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GatsbyJS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JAMstack ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ leaflet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ mapbox ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Mapping ]]>
                    </category>
                
                    <category>
                        <![CDATA[ maps ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ react-leaflet ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Wed, 08 Apr 2020 14:45:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-basemap-react-leaflet-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Building maps can be pretty powerful, but often you’re stuck with open source options for the map imagery that might not help the readability of your data. How can we leverage Mapbox’s tile APIs to add a custom basemap to our React Leaflet app?</p>
<ul>
<li><a class="post-section-overview" href="#heading-what-are-we-going-to-build">What are we going to build?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-mapbox">What is Mapbox?</a></li>
<li><a class="post-section-overview" href="#heading-part-1-creating-a-custom-mapbox-style">Part 1: Creating a custom Mapbox style</a></li>
<li><a class="post-section-overview" href="#heading-part-2-adding-a-custom-tilelayer-to-react-leaflet">Part 2: Adding a custom TileLayer to React Leaflet</a></li>
<li><a class="post-section-overview" href="#heading-part-3-adding-a-custom-basemap-to-gatsby-starter-leaflet">Part 3: Adding a custom basemap to Gatsby Starter Leaflet</a></li>
<li><a class="post-section-overview" href="#heading-securing-your-mapbox-key">Securing your Mapbox key</a></li>
<li><a class="post-section-overview" href="#heading-want-to-learn-more-about-maps">Want to learn more about maps?</a></li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/KcPJr1b_rv0" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-what-are-we-going-to-build">What are we going to build?</h2>
<p>We’re going to walk through creating a new basic <a target="_blank" href="https://www.mapbox.com/mapbox-studio/">Mapbox style</a> in our <a target="_blank" href="https://www.mapbox.com/">Mapbox</a> account. Once created, we’re going to use their <a target="_blank" href="https://docs.mapbox.com/api/maps/">Map API</a> to add a custom basemap to our <a target="_blank" href="https://react-leaflet.js.org/">React Leaflet</a> app.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/gatsby-starter-leaflet-with-mapbox-tilelayer.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Gatsby Starter Leaflet with Mapbox basemap</em></p>
<p>For our map, we’re going to use this <a target="_blank" href="https://github.com/colbyfayock/gatsby-starter-leaflet">Leaflet Gatsby Starter</a> I created that will allow you to easily spin up a new mapping app. Before we spin that up though, I’ll walk you through how to add it using only React Leaflet components.</p>
<h2 id="heading-a-mapping-app">A mapping app?</h2>
<p>Yup! Maps are used all around the world to study datasets for geographic locations. They're important tools for scientists and others that are trying to help the world.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/coronavirus-map-dashboard-demo.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Coronavirus (COVID-19) custom map</em></p>
<p>If you want to learn more about building a map and adding data to it, you can check out some of <a target="_blank" href="https://www.freecodecamp.org/news/author/colbyfayock/">my other articles</a> first such as creating a <a target="_blank" href="https://www.freecodecamp.org/news/how-to-create-a-coronavirus-covid-19-dashboard-map-app-in-react-with-gatsby-and-leaflet/">Coronavirus (COVID-19) map</a> or a <a target="_blank" href="https://www.freecodecamp.org/news/how-to-create-a-summer-road-trip-mapping-app-with-gatsby-and-leaflet/">Summer Road Trip map</a> as well as a little bit of inspiration about why <a target="_blank" href="https://www.freecodecamp.org/news/anyone-can-map-inspiration-and-an-introduction-to-the-world-of-mapping/">Anyone Can Map</a>.</p>
<h2 id="heading-what-is-mapbox">What is Mapbox?</h2>
<p>Mapbox is a mapping platform that allows its customers to create custom mapping solutions. They also leverage a variety of APIs that provide powerful capabilities for building map features.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-homepage.jpg" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://www.mapbox.com/">mapbox.com</a></em></p>
<p>For our purposes, we’re going to utilize their Map API, specifically their Static Tiles API, to serve a custom map style that we create.</p>
<h2 id="heading-part-1-creating-a-custom-mapbox-style">Part 1: Creating a custom Mapbox style</h2>
<p>To get the look and feel that we want for our map, it’s important to have a basemap that helps make our data present itself without distractions. Plus, sometimes it’s fun to have a custom map.</p>
<h3 id="heading-mapbox-account">Mapbox account</h3>
<p>The first thing we’ll need to set up our custom Mapbox style is to have an account. I'm not going to walk you through that process, but you can head over to <a target="_blank" href="https://www.mapbox.com/">Mapbox’s website</a> where you can sign up for free: <a target="_blank" href="https://www.mapbox.com/">mapbox.com</a></p>
<h3 id="heading-creating-a-new-custom-style">Creating a new custom style</h3>
<p>Creating a new style in Mapbox isn’t as hard as it sounds. While it can get really complex if you want something unique, we can copy one of Mapbox’s default styles to get started.</p>
<p>First, head over to Mapbox’s <a target="_blank" href="https://studio.mapbox.com/">Studio dashboard</a> by clicking your account link in the top right corner when logged in.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-studio.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Mapbox Studio</em></p>
<p>Once we’re on our Studio dashboard, we want to select the New Style button.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-studio-new-style.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Create a new style in Mapbox Studio</em></p>
<p>After clicking the button, a modal will pop up allowing you to choose a template. You can choose whatever you want here, but I’m going to choose Monochrome with a variation of Dark. And after you’ve selected your template, click the Customize button.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-studio-new-style-choose-template.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Select and customize a template for a new style in Mapbox Studio</em></p>
<p>And now we’re dropped into our customization UI.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-customize-style.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Mapbox customize style UI</em></p>
<p>From here, you can really do what you’d like. There are a ton of options to customize your map. It’s a little complex to try to dig in here, but <a target="_blank" href="https://docs.mapbox.com/studio-manual/overview/">Mapbox provides some resources</a> to try to help you get productive.</p>
<h3 id="heading-generating-a-mapbox-token">Generating a Mapbox token</h3>
<p>Once you’re happy with your new style and everything’s published, we want to generate a token that we’ll use for providing access to our Map.</p>
<p>Head on over to the Account section of the Mapbox dashboard.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-account.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Creating a new token in Mapbox</em></p>
<p>Mapbox provides you with a “default” token that you can use in your applications. You're free to use this, but I recommend creating a new token that you can provide a unique name, that way if you ever blow past the <a target="_blank" href="https://www.mapbox.com/pricing/">free tier</a> of Mapbox, you’ll be able to track your usage.</p>
<p>Additionally, it’s best to keep a separate token for each application, that way you can easily rotate an individual key, without having to update every application using it.</p>
<p>Once you click Create a token, you can set up the key how you’d like, with the scopes and permissions you choose, but for our purposes, you can leave all of the Public scopes checked for our map, which they do by default.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-create-token.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Create a new access token in Mapbox</em></p>
<h3 id="heading-configuring-our-custom-endpoint">Configuring our custom endpoint</h3>
<p>For this tutorial, we’re going to use <a target="_blank" href="https://docs.mapbox.com/api/maps/#static-tiles">Mapbox’s Static Tiles service</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-static-tiles-map-api.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Mapbox Static Tiles Maps API</em></p>
<p>Our endpoint will look like the following:</p>
<pre><code>https:<span class="hljs-comment">//api.mapbox.com/styles/v1/{username}/{style_id}/tiles/256/{z}/{x}/{y}@2x?access_token={access_token}</span>
</code></pre><p>There are a few parameters here we need to understand:</p>
<ul>
<li>username: this will be your Mapbox account’s username</li>
<li>style_id: this will be the ID of the style you created before</li>
<li>z, x, y: these are parameters that Leaflet programmatically swaps out, so we want to leave them as is</li>
<li>access_token: this is the Mapbox key you created above</li>
</ul>
<p>To find your username and style ID, we can use the Style URL for our new Mapbox style to get those values.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/mapbox-studio-style-url.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Finding the Style URL in Mapbox Studio</em></p>
<p>In my example, my Style URL looks like:</p>
<pre><code>mapbox:<span class="hljs-comment">//styles/colbyfayock/ck8lryjfq0jdo1ip9ctmuhc6p</span>
</code></pre><p><code>colbyfayock</code> is my username and <code>ck8lryjfq0jdo1ip9ctmuhc6p</code> is my style ID.</p>
<p>And once I update my endpoint parameters, the final tilepoint URL will look like:</p>
<pre><code>https:<span class="hljs-comment">//api.mapbox.com/styles/v1/colbyfayock/ck8lryjfq0jdo1ip9ctmuhc6p/tiles/256/{z}/{x}/{y}@2x?access_token=MYACCESSTOKEN</span>
</code></pre><h2 id="heading-part-2-adding-a-custom-tilelayer-to-react-leaflet">Part 2: Adding a custom TileLayer to React Leaflet</h2>
<p>When building a map with React Leaflet, your main component will be a <code>&lt;Map&gt;</code> that wraps the entirety of the app. This is what sets up your <a target="_blank" href="https://leafletjs.com/reference-1.6.0.html#map-example">Map instance</a> for <a target="_blank" href="https://leafletjs.com/">Leaflet</a>.</p>
<p>For our purposes here, we’re going to use the example on the <a target="_blank" href="https://react-leaflet.js.org/">React Leaflet homepage</a> as our starting point.</p>
<h3 id="heading-react-leaflet-tilelayer-component">React Leaflet TileLayer Component</h3>
<p>Inside of your <code>&lt;Map&gt;</code> component you include a <code>&lt;TileLayer&gt;</code> component, which defines the imagery of the world that you base your map upon.</p>
<p>The example on the React Leaflet homepage uses a public version of <a target="_blank" href="https://www.openstreetmap.org/">OpenStreetMap</a> as their TileLayer, which is an open source map project created and updated by people all around the world.</p>
<pre><code class="lang-react">&lt;Map center={position} zoom={13}&gt;
  &lt;TileLayer
    url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
    attribution="&amp;copy; &lt;a href=&amp;quot;http://osm.org/copyright&amp;quot;&gt;OpenStreetMap&lt;/a&gt; contributors"
  /&gt;
&lt;/Map&gt;
</code></pre>
<p>This gives you a basic map, but we want to swap in Mapbox so we can set up a custom look and feel for our map.</p>
<h3 id="heading-custom-mapbox-tilelayer">Custom Mapbox TileLayer</h3>
<p>To add our custom style, we’ll want to update the <code>url</code> and <code>attribution</code> props of the <code>TileLayer</code> component.</p>
<p>For URL, it will simply be the custom style endpoint we created earlier, so in my example, it looks like:</p>
<pre><code>https:<span class="hljs-comment">//api.mapbox.com/styles/v1/colbyfayock/ck8lryjfq0jdo1ip9ctmuhc6p/tiles/256/{z}/{x}/{y}@2x?access_token=MYACCESSTOKEN</span>
</code></pre><p>For attribution, we want to credit Mapbox as the service, so we want to set our attribution as:</p>
<pre><code><span class="hljs-built_in">Map</span> data &amp;copy; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">&amp;quot;https://www.openstreetmap.org/&amp;quot;</span>&gt;</span>OpenStreetMap<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span> contributors, <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">&amp;quot;https://creativecommons.org/licenses/by-sa/2.0/&amp;quot;</span>&gt;</span>CC-BY-SA<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span>, Imagery &amp;copy; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">&amp;quot;https://www.mapbox.com/&amp;quot;</span>&gt;</span>Mapbox<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span>
</code></pre><p>When plugged in to our <code>TileLayer</code>, our code should now look like this:</p>
<pre><code class="lang-react">&lt;Map center={position} zoom={13}&gt;
  &lt;TileLayer
    url="https://api.mapbox.com/styles/v1/colbyfayock/ck8lryjfq0jdo1ip9ctmuhc6p/tiles/256/{z}/{x}/{y}@2x?access_token=MYACCESSTOKEN"
    attribution="Map data &amp;copy; &lt;a href=&amp;quot;https://www.openstreetmap.org/&amp;quot;&gt;OpenStreetMap&lt;/a&gt; contributors, &lt;a href=&amp;quot;https://creativecommons.org/licenses/by-sa/2.0/&amp;quot;&gt;CC-BY-SA&lt;/a&gt;, Imagery &amp;copy; &lt;a href=&amp;quot;https://www.mapbox.com/&amp;quot;&gt;Mapbox&lt;/a&gt;"
  /&gt;
&lt;/Map&gt;
</code></pre>
<p>And once we open up our map, we should see our new basemap!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/react-leaflet-mapbox-basemap.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>React Leaflet with a Mapbox basemap</em></p>
<h3 id="heading-see-the-code">See the code!</h3>
<p>If you want to see how I did it, <a target="_blank" href="https://github.com/colbyfayock/my-mapbox-react-leaflet/commits/master">check out the diff commit by commit</a>.</p>
<p>The only caveat there is I created an <code>.env.development.local</code> file in the root of my project in which I stored a new environment variable called <code>REACT_APP_MAPBOX_KEY</code>  to store my Mapbox key.</p>
<h2 id="heading-part-3-adding-a-custom-basemap-to-gatsby-starter-leaflet">Part 3: Adding a custom basemap to Gatsby Starter Leaflet</h2>
<p>I’ve written <a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-coronavirus-covid-19-dashboard-map-app-with-gatsby-and-leaflet">a few</a> <a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-summer-road-trip-mapping-app-with-gatsby-and-leaflet">other</a> <a target="_blank" href="https://www.colbyfayock.com/2020/03/anyone-can-map-inspiration-and-an-introduction-to-the-world-of-mapping/">articles</a> on <a target="_blank" href="https://www.freecodecamp.org/news/easily-spin-up-a-mapping-app-in-react-with-leaflet/">how to get started</a> with my <a target="_blank" href="https://github.com/colbyfayock/gatsby-starter-leaflet">Leaflet Gatsby Starter</a>, but for this part, we’ll want to have a basic app spun up that we can use to change our <code>TileLayer</code> endpoint.</p>
<h3 id="heading-setting-up-our-react-leaflet-gatsby-app">Setting up our React Leaflet Gatsby app</h3>
<p>To get started, check out the instructions on the Starter github:</p>
<p><a target="_blank" href="https://github.com/colbyfayock/gatsby-starter-leaflet">https://github.com/colbyfayock/gatsby-starter-leaflet</a></p>
<p>Once you’re ready, you should have a basic mapping app ready to go!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/gatsby-starter-leaflet-in-browser.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New Leaflet Gatsby app in the browser</em></p>
<h3 id="heading-configuring-our-mapbox-service">Configuring our Mapbox service</h3>
<p>The first thing we’ll want to do is add Mapbox as a service in our <code>src/data/map-services.js</code> file.</p>
<p>Taking our custom endpoint URL that we created in Part 1, let’s set up a new object with a name of Mapbox, and with a url and attribution similar to what we did in Part 2.</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> mapServices = [
  {
    <span class="hljs-attr">name</span>: ‘OpenStreetMap’,
    <span class="hljs-attr">attribution</span>: <span class="hljs-string">'&amp;copy; &lt;a href="http://osm.org/copyright”&gt;OpenStreetMap&lt;/a&gt; contributors’,
    url: ‘https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png’
  },
  {
    name: ‘Mapbox’,
    attribution: ‘Map data &amp;copy; &lt;a href=&amp;quot;https://www.openstreetmap.org/&amp;quot;&gt;OpenStreetMap&lt;/a&gt; contributors, &lt;a href=&amp;quot;https://creativecommons.org/licenses/by-sa/2.0/&amp;quot;&gt;CC-BY-SA&lt;/a&gt;, Imagery &amp;copy; &lt;a href=&amp;quot;https://www.mapbox.com/&amp;quot;&gt;Mapbox&lt;/a&gt;’,
    url: `https://api.mapbox.com/styles/v1/colbyfayock/ck8c2foj72lqk1jnug0g2haw0/tiles/256/{z}/{x}/{y}@2x?access_token=MY_ACCESS_TOKEN`
  }
];</span>
</code></pre>
<h3 id="heading-using-our-mapbox-map-service">Using our Mapbox map service</h3>
<p>Once you have your Mapbox service set up, all that’s left is to open up the <code>src/pages/index.js</code> file, find the <code>mapSettings</code> object definition, and update the <code>defaultBaseMap</code> property to <code>Mapbox</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> mapSettings = {
  <span class="hljs-attr">center</span>: CENTER,
  <span class="hljs-attr">defaultBaseMap</span>: ‘Mapbox’,
  <span class="hljs-attr">zoom</span>: DEFAULT_ZOOM,
  mapEffect
};
</code></pre>
<p>Save that change, refresh the map in your browser, and you should now see your custom basemap style!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/gatsby-starter-leaflet-with-mapbox-tilelayer-in-browser.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Gatsby Starter Leaflet with custom Mapbox basemap in browser</em></p>
<h3 id="heading-see-the-code-1">See the code!</h3>
<p>If you want to see how I did it, <a target="_blank" href="https://github.com/colbyfayock/my-mapbox-gatsby-starter-leaflet/commit/9baa1b7003504dec5c938328ea9b54477f65ec58">check out the diff with the commit</a>.</p>
<p>The only caveat there is I created an <code>.env.development</code> file in the root of my project in which I stored a new environment variable called <code>GATSBY_MAPBOX_KEY</code>  to store my Mapbox key.</p>
<h2 id="heading-securing-your-mapbox-key">Securing your Mapbox key</h2>
<h3 id="heading-environment-variables">Environment variables</h3>
<p>Part of most development processes that use individual keys will generally set the keys up as environment variables. Environment variables are configured settings that don’t live in the code itself.</p>
<p>This is important because it prevents your key from being checked in to your code, which is bad from a security perspective, but it also allows you to provide a different key for different environments.</p>
<p>When generating your keys, try to keep this in mind, as it can save you in the long run.</p>
<h3 id="heading-locking-down-your-mapbox-key">Locking down your Mapbox key</h3>
<p>In your settings when creating a token or when editing a token, Mapbox allows you to specify only the URLs you want your key to be accessible from.</p>
<p>Though Mapbox has a generous free tier, you probably want to keep it locked down only to the URLs that you’re using it on. You can create multiple keys, where one could be for public use on your website and one would be for your local development.</p>
<p>This is helpful for instance, where you have a key that will never be used publicly for development purposes, but then you have a key that you deploy with, which can be locked down only to that URL.</p>
<p>If someone grabs your key, they could plug it into their own website and use up all of your free tier, potentially running up your bill!</p>
<h2 id="heading-want-to-learn-more-about-maps">Want to learn more about maps?</h2>
<p>You can check out a few of my other resources to get started:</p>
<ul>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-coronavirus-covid-19-dashboard-map-app-with-gatsby-and-leaflet">How to create a Coronavirus (COVID-19) Dashboard &amp; Map App in React with Gatsby and Leaflet</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/anyone-can-map-inspiration-and-an-introduction-to-the-world-of-mapping">Anyone Can Map! Inspiration and an introduction to the world of mapping</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2020/03/how-to-create-a-summer-road-trip-mapping-app-with-gatsby-and-leaflet">How to Create a Summer Road Trip Mapping App with Gatsby and Leaflet</a></li>
<li><a target="_blank" href="https://www.colbyfayock.com/2019/12/create-your-own-santa-tracker-with-gatsby-and-react-leaflet/">How to Create your own Santa Tracker with Gatsby and React Leaflet</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/easily-spin-up-a-mapping-app-in-react-with-leaflet/">How to build a mapping app in React the easy way with Leaflet</a></li>
</ul>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="600" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">? Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">?️ Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to host and deploy a static website or JAMstack app to AWS S3 and CloudFront ]]>
                </title>
                <description>
                    <![CDATA[ S3 and CloudFront are AWS cloud services that make serving static assets powerful and cheap. How can we host a simple static website or JAMstack app on it? A little about AWS What are the benefits of serving from S3 and CloudFront? Before we start, ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-host-and-deploy-a-static-website-or-jamstack-app-to-s3-and-cloudfront/</link>
                <guid isPermaLink="false">66bee8fdf53892da32acd273</guid>
                
                    <category>
                        <![CDATA[ AWS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ beginners guide ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Cloud ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Cloud Services ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Cloud Solutions ]]>
                    </category>
                
                    <category>
                        <![CDATA[ cloudfront ]]>
                    </category>
                
                    <category>
                        <![CDATA[ HTML ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JAMstack ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ S3 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Static Site Generators ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Tutorial ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Wed, 11 Mar 2020 13:16:31 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/03/static-website-in-aws-s3.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>S3 and CloudFront are AWS cloud services that make serving static assets powerful and cheap. How can we host a simple static website or JAMstack app on it?</p>
<ul>
<li><a class="post-section-overview" href="#heading-a-little-about-aws">A little about AWS</a></li>
<li><a class="post-section-overview" href="#heading-what-are-the-benefits-of-serving-from-s3-and-cloudfront">What are the benefits of serving from S3 and CloudFront?</a></li>
<li><a class="post-section-overview" href="#heading-before-we-start-youll-need-an-aws-account">Before we start, you’ll need an AWS account</a></li>
<li><a class="post-section-overview" href="#heading-storing-your-website-on-s3">Storing your website on S3</a></li>
<li><a class="post-section-overview" href="#heading-serving-your-website-on-s3">Serving your website on S3</a></li>
<li><a class="post-section-overview" href="#heading-distributing-your-website-on-cloudfront">Distributing your website on CloudFront</a></li>
<li><a class="post-section-overview" href="#heading-custom-domain-names">Custom domain names</a></li>
<li><a class="post-section-overview" href="#heading-advanced-aws-usage">Advanced AWS Usage</a></li>
<li><a class="post-section-overview" href="#heading-resources">Resources</a></li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/1lDGDzmbQWg" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-a-little-about-aws">A little about AWS</h2>
<p>If you’re not familiar, <a target="_blank" href="https://aws.amazon.com/">AWS</a> (Amazon Web Services) is a cloud service provider that gives developers opportunities to build pretty much anything they can imagine in the cloud.</p>
<p>Though their <a target="_blank" href="https://aws.amazon.com/products/">services</a> extend beyond the likes of <a target="_blank" href="https://aws.amazon.com/machine-learning/">machine learning</a> and <a target="_blank" href="https://aws.amazon.com/ai/">artificial intelligence</a>, we’re going to stick with the entry level services for the purpose of this guide that will allow us to easily host an HTML website.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/aws-services-overview.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Types of AWS services available</em></p>
<p>Building a site with S3 and CloudFront is a common recipe that small and high scale companies across the web use, but let’s break down what each service actually does.</p>
<h3 id="heading-object-storage-with-s3">Object storage with S3</h3>
<p><a target="_blank" href="https://aws.amazon.com/s3/">S3</a> (Simple Storage Service) acts as your hosting for your static website. Think of it like a hard drive in the cloud which we’re not able to use it for processing purposes, but rather for simple file storage and access.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/aws-s3-bucket-file-list.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>List of files from a static site in an AWS S3 bucket</em></p>
<p>When an app or website is compiled in static form, this is all we need to serve it to the people visiting our site. The HTML is sent in the initial request “as is” (unless there’s processing with your provider) and any additional work occurs after the page loads in the browser usually by JavaScript. This allows us to take this simple (and cheap) approach by serving these files from S3.</p>
<h3 id="heading-content-delivery-network-with-cloudfront">Content Delivery Network with CloudFront</h3>
<p><a target="_blank" href="https://aws.amazon.com/cloudfront/">CloudFront</a> works as a <a target="_blank" href="https://en.wikipedia.org/wiki/Content_delivery_network">CDN</a> (Content Delivery Network) that sits in front of your website, caching the files, and serving them directly to the people visiting your site.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/cdn-distribution-map.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>CDN Diagram</em></p>
<p>Where you host and serve your website from, typically called the origin, is the main source of your files and can serve the website itself. But putting a CDN in front of it provides the people accessing your content a shorter and faster way to make their request.</p>
<h2 id="heading-what-are-the-benefits-of-serving-from-s3-and-cloudfront">What are the benefits of serving from S3 and CloudFront?</h2>
<p>Given the rise in the <a target="_blank" href="https://jamstack.org/">JAMstack</a> era, many services are popping up that provide similar services for static sites that make it really easy to deploy. Some even come with a generous free tier like <a target="_blank" href="https://www.netlify.com/">Netlify</a> and <a target="_blank" href="https://zeit.co/">Zeit</a>!</p>
<p>But sometimes developers need a little bit more control over their services or they need to integrate into a larger cloud pipeline that’s already 99% percent in AWS, which is exactly where S3 shines. Also, chances are, during your first year you might still qualify for AWS’s <a target="_blank" href="https://aws.amazon.com/free/">free tier</a>.</p>
<h3 id="heading-fitting-in-to-the-aws-well-architected-framework">Fitting in to the AWS Well-Architected Framework</h3>
<p>As a lead provider in cloud services, AWS has published many guides to help developers and teams strive for excellence in their solutions in terms of performance, cost, and security.</p>
<p>One particular guideline is their 5 pillars of what they describe as a <a target="_blank" href="https://aws.amazon.com/architecture/well-architected/">“well-architected" infrastructure</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/aws-well-architected-framework.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>AWS Well-Architected Framework</em></p>
<p>By default, we check all of these boxes with our hosting solution by using S3 and CloudFront. Out of the box, the HTML and assets you serve will be fast, cheap, secure, and reliable.</p>
<h3 id="heading-the-beauty-of-static-and-jamstack-sites">The beauty of static and JAMstack sites</h3>
<p>Building on top of the pillars, what you’re actually serving is a static HTML file and group of assets that won’t require any type of rendering resources on the initial request. Before this, a common problem was having to worry about a site crashing due to heavy load. But with S3 and CloudFront, your website is infinitely scalable.</p>
<p>On a similar note, when that server scales up as it's trying to serve millions of hits on your post that went viral, so will your costs. Serving a static site is cheap and can greatly reduce the cost associated with running a web server.</p>
<h2 id="heading-before-we-start-youll-need-an-aws-account">Before we start, you’ll need an AWS account</h2>
<p>To work through this guide, you’ll need an AWS account. Luckily, it's free to create an account – you’ll only pay for the services used.</p>
<p>On top of that, AWS provides a generous free tier for some of its services. Some services provide only 12 months of a free tier (like S3) where others are always eligible for the free tier (like <a target="_blank" href="https://aws.amazon.com/lambda/">Lambda</a>), so make sure to do your homework so you don’t rack up an unexpectedly high bill.</p>
<p>To create your account, head over to the AWS website and then continue on to get started: <a target="_blank" href="https://aws.amazon.com/">https://aws.amazon.com/</a>.</p>
<h2 id="heading-storing-your-website-on-s3">Storing your website on S3</h2>
<p>To get started, we’re going to begin with a simple HTML file that will serve as our website. This will allow us to focus more on the process of hosting rather than the intricacies of the website itself.</p>
<h3 id="heading-creating-our-website-file">Creating our website file</h3>
<p>Begin by creating a new folder called <code>my-static-site</code>. Inside that folder, let's create a new file called <code>index.html</code> and add the following to the file:</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">“en”</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">“UTF-8”</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">“viewport”</span> <span class="hljs-attr">content</span>=<span class="hljs-string">“width</span>=<span class="hljs-string">device-width,</span> <span class="hljs-attr">initial-scale</span>=<span class="hljs-string">1.0”</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>My Static Website<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello World!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>This is my static website. ?<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>If you open this file from your computer in your favorite browser, you should now be seeing this.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/hello-world-local-website-file-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Hello World! Opening a local webpage</em></p>
<h3 id="heading-creating-a-new-bucket">Creating a new bucket</h3>
<p>Head on over to your AWS account, log in, and navigate to your <a target="_blank" href="https://s3.console.aws.amazon.com/s3/">S3 console</a>.</p>
<p>Once there, let’s create our bucket by clicking on the blue <strong>Create bucket</strong> button:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/aws-s3-create-bucket.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Creating a bucket in AWS S3</em></p>
<p>The first thing AWS wants us to do is enter a <strong>Bucket name</strong>. The bucket name must be globally unique, meaning, the name you use can be the only one in the world, so let’s try something like <code>[yourname]-static-website</code>, where I’ll use <code>colbyfayock-static-website</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/aws-s3-bucket-name.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Naming a bucket in AWS S3</em></p>
<p>Next, let’s set the <a target="_blank" href="https://aws.amazon.com/about-aws/global-infrastructure/regions_az/"><strong>Region</strong></a>. This is the geographic location where AWS will host the bucket and your website. You’re probably fine with the default, but if you’d like, you can select the location closest to you if it’s permitted. Since I’m in Virginia, I’m going to stick with my default of <strong>US East (N. Virginia)</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/aws-s3-bucket-region.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Setting the region of a bucket in AWS S3</em></p>
<p>Finally, hit the <strong>Create</strong> button on the bottom left of the page.</p>
<p><em>Note: even if you use the <code>[yourname]-static-website</code> pattern, there’s a chance the name will be taken. If it’s taken, AWS will show an error stating “Bucket name already exists,” at which point you’ll want to try a new name of your choosing.</em></p>
<p>Alternatively, you can hit <strong>Next</strong> for advanced usage, but for this guide, we’re okay with all of the defaults S3 provides.</p>
<p>If successful, you should now see your bucket in the list on the S3 console dashboard.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/aws-s3-bucket.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>New bucket in AWS S3</em></p>
<h3 id="heading-uploading-your-website-to-the-bucket">Uploading your website to the bucket</h3>
<p>Let’s navigate to our new bucket by clicking the row of our bucket. You’ll be greeted with a message stating “This bucket is empty. Upload new objects to get started,” so that’s what we’ll do.</p>
<p>Click the <strong>Upload</strong> button to get started.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/aws-s3-bucket-upload.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Uploading files to AWS S3</em></p>
<p>You’ll then see a popup that will ask you to upload a file. Click on the <strong>Add files</strong> button and select your <code>index.html</code> file we created earlier.</p>
<p>Once selected, click the <strong>Upload</strong> button on the bottom left.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/aws-s3-bucket-upload-files.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Selecting files to upload in AWS S3</em></p>
<p>And now your file is uploaded to S3!</p>
<h2 id="heading-serving-your-website-on-s3">Serving your website on S3</h2>
<p>If you try to navigate to your <code>index.html</code> file and open it, you’ll notice a big ugly "Access Denied" message.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/aws-s3-access-denied.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Access Denied to bucket file</em></p>
<p>This is because your file doesn’t currently have the permissions and settings necessary to serve the file to the public, so let’s fix that.</p>
<h3 id="heading-setting-up-your-bucket-as-a-website">Setting up your bucket as a website</h3>
<p>Navigate to the <strong>Properties</strong> tab inside of your bucket, then click <strong>Static website hosting</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/aws-s3-properties-static-hosting.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Setting up an AWS S3 bucket for statice website hosting</em></p>
<p>Once there, we want to do a few things:</p>
<ul>
<li>Note down the <strong>Endpoint</strong> at the top of the block. We’ll use this to access our site later (you can always find this here again)</li>
<li>Select the “Use this bucket to host a website” option</li>
<li>Enter <code>index.html</code> in the <strong>Index document</strong> field</li>
<li>Finally hit <strong>Save</strong></li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/aws-s3-static-website-configuration.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Configuring an AWS S3 bucket for static website hosting</em></p>
<h3 id="heading-setting-up-your-bucket-policy-and-permissions">Setting up your bucket policy and permissions</h3>
<p>Next, navigate to the <strong>Permissions</strong> tab. Here we’ll want to do 2 things: unblock all public access and add a Bucket Policy.</p>
<p>First, on the main page, let’s click <strong>Edit</strong> to unblock all access.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/aws-s3-bucket-permissions.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Configuring an AWS S3 bucket permissions</em></p>
<p>Then, uncheck the “Block all public access” checkbox and hit <strong>Save</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/aws-s3-bucket-block-access.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Allowing public access to an AWS S3 bucket</em></p>
<p>AWS will ask you to confirm these settings, as this may not always be what you want to do with your bucket. But for the purposes of hosting a website, we want the whole world to see, so type in the word “confirm” and hit the <strong>Confirm</strong> button.</p>
<p>After confirming, click the <strong>Bucket policy</strong> button and you’ll be taken to a text editor.</p>
<p>In this text box, we’ll want to paste the following snippet. Within this snippet, make sure to replace <code>[your-bucket-name]</code> with the name of your bucket, otherwise you will not be able to save this file.</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"Version"</span>:<span class="hljs-string">"2012-10-17"</span>,
  <span class="hljs-attr">"Statement"</span>:[{
    <span class="hljs-attr">"Sid"</span>:<span class="hljs-string">"PublicReadGetObject"</span>,
        <span class="hljs-attr">"Effect"</span>:<span class="hljs-string">"Allow"</span>,
      <span class="hljs-attr">"Principal"</span>: <span class="hljs-string">"*"</span>,
      <span class="hljs-attr">"Action"</span>:[<span class="hljs-string">"s3:GetObject"</span>],
      <span class="hljs-attr">"Resource"</span>:[<span class="hljs-string">"arn:aws:s3:::[your-bucket-name]/*”
      ]
    }
  ]
}</span>
</code></pre>
<p><a target="_blank" href="https://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteAccessPermissionsReqd.html#bucket-policy-static-site">This policy</a> states that it’s allowing the public to perform a GetObject request on the S3 resource, which is your S3 bucket.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/aws-s3-static-website-bucket-policy.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Setting up a public policy for an AWS S3 bucket</em></p>
<p>After you add the policy, click the <strong>Save</strong> button. Your should now see a message stating "This bucket has public access.”</p>
<h3 id="heading-previewing-your-new-bucket-website">Previewing your new bucket website</h3>
<p>If you noted down the Endpoint from your Properties page, you can now visit that address to see your website. The endpoint should look like this:</p>
<pre><code class="lang-plaintext">http://[your-bucket-name].s3-website-[region-id].amazonaws.com
</code></pre>
<p>If you didn’t, jump back up a few steps to remind yourself how to find it or look under the Properties tab.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/aws-s3-static-website.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Hello World! Opening an AWS S3 website</em></p>
<p>Congrats, you're halfway there! ?</p>
<h2 id="heading-distributing-your-website-on-cloudfront">Distributing your website on CloudFront</h2>
<p>Now that we have our static website being served from a bucket on S3, let’s take it up another level and serve it across the world using CloudFront.</p>
<h3 id="heading-creating-a-cloudfront-distribution">Creating a CloudFront distribution</h3>
<p>Navigate to your <a target="_blank" href="https://console.aws.amazon.com/cloudfront">CloudFront dashboard</a> and click the <strong>Create Distribution</strong> button.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/aws-cloudfront-create-distribution.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Creating a new distribution in AWS CloudFront</em></p>
<p>Next, select <strong>Get Started</strong> under the <strong>Web</strong> delivery method.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/aws-cloudfront-creating-web-distribution.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Getting started with an AWS CloudFront distribution with Web delivery</em></p>
<p>Here, we’ll enter a few custom parameters to get our distribution set up.</p>
<p>Click into the <strong>Origin Domain Name</strong> field. Once selected, a dropdown list should appear where you can select the S3 bucket you just created. Go ahead and select your S3 bucket.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/aws-cloudfront-distribution-origin-name-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Setting the origin domain name in AWS CloudFront to your bucket</em></p>
<p>While you can <a target="_blank" href="https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-values-specify.html">customize most of the settings</a> to your liking, for our purposes, we’re going to leave all as their default values except for one.</p>
<p>Scroll down to the <strong>Default Root Object</strong> field and type <code>index.html</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/aws-cloudfront-distribution-default-root-object-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Setting the Default Root Object for a distribution in AWS CloudFront</em></p>
<p>After, scroll down to the bottom and click <strong>Create Distribution</strong> in the bottom right.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/aws-cloudfront-setup-create-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Creating an AWS CloudFront distribution</em></p>
<h3 id="heading-previewing-your-new-cloudfront-distribution">Previewing your new CloudFront distribution</h3>
<p>After hitting the <strong>Create</strong> button, it will take some time for your distribution to be created and set up. You’ll notice on the <strong>CloudFront Distributions</strong> list page that the <strong>Status</strong> of your new distribution is <strong>In Progress</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/aws-cloudfront-distribution-in-progress-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>AWS CloudFront distribution deployment is In Progress</em></p>
<p>Once this completes, it will say <strong>Deployed</strong>. Then you can find your <strong>Domain Name</strong> in the same row.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/aws-cloudfront-distribution-deployed.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>AWS CloudFront distribution is Deployed</em></p>
<p>Using the value in the Domain Name column, open your distribution in your browser and success! You now are viewing your S3 bucket through CloudFront’s distribution network.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/aws-cloudfront-static-website-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Hello World! Opening an AWS CloudFront website</em></p>
<h2 id="heading-custom-domain-names">Custom domain names</h2>
<p>While most of us will probably want to use a custom domain name with our website, we’re not going to dive too deep into that this guide, as there are many ways to set that up depending on where you purchase your domain name.</p>
<p>However, here are a few things to consider.</p>
<h3 id="heading-https-ssl-certificate">HTTPS / SSL Certificate</h3>
<p>If you’re creating your CloudFront distribution to use with a custom domain name, you'll most likely want to configure your distribution with an <a target="_blank" href="https://www.cloudflare.com/learning/ssl/what-is-an-ssl-certificate/">SSL certificate</a> using AWS’s <a target="_blank" href="https://aws.amazon.com/certificate-manager/">Certificate Manager</a>. Alternatively you can provide your own certificate with tools like <a target="_blank" href="https://letsencrypt.org/">Let's Encrypt</a>, but by using ACM, AWS makes it easy to pull in the records for use with your distribution.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/fay.io-ssl-certificate.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Once in ACM, you’ll want to configure the certificate, map what domains and subdomains should match (typically <code>*.domain.com</code>), and then create your certificate to use with your distribution.</p>
<p>To get started, you can check out the AWS guide for <a target="_blank" href="https://docs.aws.amazon.com/acm/latest/userguide/gs-acm-request-public.html">requesting a public certificate</a>.</p>
<h3 id="heading-cnames-and-aliases">CNAMEs and Aliases</h3>
<p>A common approach to setting up a custom domain is to use a CNAME. CloudFront makes this pretty painless, as you’ll add it as a configuration option when you’re configuring your distribution.</p>
<p>To get started with setting up a CNAME in CloudFront, <a target="_blank" href="https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CNAMEs.html">see the AWS guide</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/fay.io-route53-alias.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>If you’re using <a target="_blank" href="https://aws.amazon.com/route53/">Route53</a> to manage your <a target="_blank" href="https://www.cloudflare.com/learning/dns/what-is-dns/">DNS</a>, you can then set up an A record (alias) to point to your distribution. You can learn more <a target="_blank" href="https://aws.amazon.com/premiumsupport/knowledge-center/route-53-create-alias-records/">using this guide</a>.</p>
<h2 id="heading-advanced-aws-usage">Advanced AWS Usage</h2>
<p>For this guide, we walked you through setting up a new static website and app using the AWS console. But whether you want to learn more, improve your deploy efficiency, or want to automate this process, you’ll want to take a it a step further with the AWS CLI or CloudFormation.</p>
<p>While we won’t walk you through how to use these tools here, we’ll get you started with a little bit of an idea of what you’re up against.</p>
<h3 id="heading-aws-cli">AWS CLI</h3>
<p>The <a target="_blank" href="https://aws.amazon.com/cli/">AWS CLI</a> allows someone to perform AWS operations from the command line. This can be incredibly powerful when you want to script out your resource creation or if you simply prefer to do all of your work from the terminal.</p>
<p>Once set up locally, you’ll be able to perform actions like creating a bucket using the following command:</p>
<pre><code class="lang-shell">aws s3api create-bucket —-bucket [your-bucket-name] —-region [bucket-region]
</code></pre>
<p>To get started, check out the AWS CLI <a target="_blank" href="https://github.com/aws/aws-cli">Github page</a> or the AWS CLI <a target="_blank" href="https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html">User Guide</a>    .</p>
<h3 id="heading-aws-cloudformation">AWS CloudFormation</h3>
<p>AWS preaches “infrastructure as code.” It’s the idea that you can spin up your infrastructure using something that’s written in a file, where in this particular case, it would be a CloudFormation template. This allows you to have a repeatable process that will be the same each time you perform the deploy.</p>
<p><a target="_blank" href="https://aws.amazon.com/cloudformation/">CloudFormation</a> allows you to set up a configuration file that will deploy the services and resources of your choosing by pointing to that file with the CLI or by uploading it in the console.</p>
<p>Here’s an <a target="_blank" href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/quickref-s3.html#scenario-s3-bucket-website">example from AWS</a> of what that looks like for a static S3 bucket that could serve as a website.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/aws-cloudformation-template-s3.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>AWS CloudFront template example</em></p>
<p>To get started, check out AWS’s CloudFormation <a target="_blank" href="https://aws.amazon.com/cloudformation/resources/templates/">example templates</a> or their <a target="_blank" href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/GettingStarted.Walkthrough.html">Get Started guide</a>.</p>
<h2 id="heading-resources">Resources</h2>
<p>If you’re interested in getting deeper into the AWS ecosystem, here are a few resources to get started:</p>
<ul>
<li><a target="_blank" href="https://www.freecodecamp.org/news/aws-certified-cloud-practitioner-training-2019-free-video-course/">AWS Certified Cloud Practitioner Training 2019 - A Free 4-hour Video Course</a> (freeCodeCamp.org)</li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/awscertified-challenge-free-path-aws-cloud-certifications/">Introducing The #AWSCertified Challenge: A Path to Your First AWS Certifications</a> (freeCodeCamp.org)</li>
<li><a target="_blank" href="https://aws.amazon.com/getting-started/tutorials/">10-Minute Tutorials</a> (AWS)</li>
<li><a target="_blank" href="https://acloud.guru/">A Cloud Guru</a> (Paid courses)</li>
<li><a target="_blank" href="https://aws.amazon.com/solutions/case-studies/">AWS Case Studies</a> (AWS)</li>
</ul>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="600" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">? Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">?️ Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ JAMstack Tutorial – How to Build Fast, Secure Websites – a Free 4-hour course ]]>
                </title>
                <description>
                    <![CDATA[ The JAMstack allows people to create websites that are simpler, faster, and more secure than other web development methods. Sites created with the JAMstack are delivered by pre-rendering files that are served directly from a CDN, removing the require... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/jamstack-full-course/</link>
                <guid isPermaLink="false">66b203bb712508eb1606786c</guid>
                
                    <category>
                        <![CDATA[ JAMstack ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Tue, 10 Mar 2020 18:25:26 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/03/jamstack.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>The JAMstack allows people to create websites that are simpler, faster, and more secure than other web development methods. Sites created with the JAMstack are delivered by pre-rendering files that are served directly from a CDN, removing the requirement to manage or run web servers.</p>
<p>We have released a full course on the JAMstack from Phil Hawksworth on the freeCodeCamp.org YouTube channel. Phil is part of the Developer Experience team at Netlify and is very experienced with the JAMstack.</p>
<p>First, you will learn what the JAMstack is and how it compares to other tech stacks. Then, you see how to use the JAMstack with six different examples, all demonstrating different ways to use the JAMstack. The examples continue to grow in scope throughout the course.</p>
<p>The six examples focus on the following topics:</p>
<ul>
<li>Creating a static site</li>
<li>Changing the DOM with JavaScript</li>
<li>Introducing a static site generator</li>
<li>Generating pages from a content API</li>
<li>Generating localized pages, with geo-IP routing at the CDN</li>
<li>Client-side rendering targeted API content</li>
</ul>
<p>At the end of the course, you will learn how start using the JAMstack in your own infrastructure. This will be especially helpful if you already have sites using a different architecture and you want to use the JAMstack next to it.</p>
<p>Watch the course below or on <a target="_blank" href="https://www.youtube.com/watch?v=A_l0qrPUJds">the freeCodeCamp.org YouTube channel</a> (4 hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/A_l0qrPUJds" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is the JAMstack and how do I get started? ]]>
                </title>
                <description>
                    <![CDATA[ JAMstack sites are all the rage right now in the web dev world. And rightfully so! But what exactly is it and how can we all take advantage of its benefits? What is this JAMstack? That’s not to be confused with serverless What makes up the JAMstack?... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-is-the-jamstack-and-how-do-i-host-my-website-on-it/</link>
                <guid isPermaLink="false">66b8e3a0682e4a25eed261a4</guid>
                
                    <category>
                        <![CDATA[ architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ front end ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Front-end Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ frontend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ HTML ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JAMstack ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Wed, 19 Feb 2020 15:45:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/02/what-is-jamstack-2.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>JAMstack sites are all the rage right now in the web dev world. And rightfully so! But what exactly is it and how can we all take advantage of its benefits?</p>
<ul>
<li><a class="post-section-overview" href="#heading-what-is-this-jamstack">What is this JAMstack?</a></li>
<li><a class="post-section-overview" href="#heading-thats-not-to-be-confused-with-serverless">That’s not to be confused with serverless</a></li>
<li><a class="post-section-overview" href="#heading-what-makes-up-the-jamstack">What makes up the JAMstack?</a></li>
<li><a class="post-section-overview" href="#heading-so-what-makes-a-jamstack-app-so-great">So what makes a JAMstack app so great?</a></li>
<li><a class="post-section-overview" href="#heading-is-my-website-considered-to-be-on-the-jamstack">Is my website considered to be on the JAMstack?</a></li>
<li><a class="post-section-overview" href="#heading-what-are-some-examples-of-jamstack">What are some examples of JAMstack?</a></li>
<li><a class="post-section-overview" href="#heading-what-are-some-tools-i-can-use-to-build-jamstack-sites-or-apps">What are some tools I can use to build JAMstack sites or apps?</a></li>
</ul>
<h2 id="heading-what-is-this-jamstack">What is this JAMstack?</h2>
<p>To start, <a target="_blank" href="https://jamstack.org/">JAMstack</a> is a software architecture and philosophy that adheres to the following components: Javascript, APIs, and Markup.</p>
<p>If this sounds familiar, it's because it is! That React app that you compile down with <a target="_blank" href="https://webpack.js.org/">Webpack</a> and ultimately serve from <a target="_blank" href="https://aws.amazon.com/s3/">S3</a>? Yup, that’s a JAMstack app. That simple HTML file that has no JavaScript and literally doesn’t do anything dynamic? Yup, that’s also a JAMstack app.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/bill-ted-air-guitar.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Bill and Ted play air guitars</em></p>
<h2 id="heading-thats-not-to-be-confused-with-serverless">That’s not to be confused with serverless</h2>
<p>If you’re coming more from the cloud side of things (think <a target="_blank" href="https://aws.amazon.com/">AWS</a>, <a target="_blank" href="https://cloud.google.com/">GCP</a>, <a target="_blank" href="https://azure.microsoft.com/">Azure</a>), you might be inclined to think of <a target="_blank" href="https://serverless-stack.com/chapters/what-is-serverless.html">serverless</a> and JAMstack as the same thing. Granted they have similarities in the philosophy of how resources are managed, such as hosting a site on S3. But a JAMstack app is not always going to be a serverless app.</p>
<p>Consider an app hosted in static storage on the cloud provider of your choice. Yes, you might be serving the app in a serverless way, but you might be dealing with an API that utilizes Wordpress or Rails, both of which are certainly not serverless.</p>
<p>Combining these philosophies can go a long way, but they shouldn’t be confused as the same.</p>
<h2 id="heading-what-makes-up-the-jamstack">What makes up the JAMstack?</h2>
<p>Back to the JAMstack: it's typically comprised of 3 components: Javascript, APIs, and Markup. Its <a target="_blank" href="https://snipcart.com/blog/jamstack">history stems</a> from growing the term "static site" into something more meaningful (and marketable). So while ultimately a static site is the end result, it's blown up to include first class tooling for every step of the way.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/jamstack-breakdown-3.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>JAMstack breakdown</em></p>
<p>While there aren't any specific set of tools that you need to use, or any tools at all beyond simple HTML, there are great examples of what can make up each part of the stack. Let's dive in a little bit to each component.</p>
<h3 id="heading-javascript">Javascript</h3>
<p>The component that’s probably done the most work to popularize the JAMstack is Javascript. Our favorite browser language allows us to provide all of the dynamic and interactive bits that we might not have if we’re serving plain HTML without it.</p>
<p>This is where a lot of times you’ll see UI frameworks like <a target="_blank" href="https://reactjs.org/">React</a>, <a target="_blank" href="https://vuejs.org/">Vue</a>, and newcomers like <a target="_blank" href="https://svelte.dev/">Svelte</a> come into play.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/react-component-example.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>"A Simple Component" example from <a target="_blank" href="https://reactjs.org/">reactjs.org </a></em></p>
<p>They make building apps simpler and more organized by providing component APIs and tooling that compile down to a simple HTML file (or a bunch of them). </p>
<p>Those HTML files include a group of assets like images, CSS, and the actual JS that ultimately get served to a browser via your favorite CDN (content delivery network).</p>
<h3 id="heading-apis">APIs</h3>
<p>Utilizing the strengths of APIs is core to how you make a JAMstack app dynamic. Whether it’s authentication or search, your application will use Javascript to make an HTTP request to another provider which will ultimately enhance the experience in one form or another.</p>
<p><a target="_blank" href="https://www.gatsbyjs.org/">Gatsby</a> coined the phrase "<a target="_blank" href="https://www.gatsbyjs.org/blog/2018-10-04-journey-to-the-content-mesh/">content mesh</a>" that does a pretty good job at describing the possibilities here.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/content-mesh-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://www.gatsbyjs.org/blog/2018-10-04-journey-to-the-content-mesh/">Content Mesh</a></em></p>
<p>You don’t necessarily have to reach out to only one host for an API, but you can reach out to as many as you need (but try not to go overboard).</p>
<p>For instance, if you have a headless <a target="_blank" href="https://wordpress.org/">Wordpress</a> API where you host your blog posts, a <a target="_blank" href="https://cloudinary.com/">Cloudinary</a> account where you store your specialized media, and an <a target="_blank" href="https://www.elastic.co/">Elasticsearch</a> instance that provides your search functionality, they all work together to provide a single experience to the people using your site.</p>
<h3 id="heading-markup">Markup</h3>
<p>This is the critical piece. Whether it’s your hand written HTML or the code that compiles down to the HTML, it's the first part you’re serving to the client. This is kind of a de facto piece of any website, but how you serve it is the most important piece.</p>
<p>To be considered a JAMstack app, the HTML needs to be served statically, which basically means not being dynamically rendered from a server. </p>
<p>If you’re piecing a page together and serving it with PHP, it’s probably not a JAMstack app. If you upload and serve a single HTML file from storage that constructs an app with Javascript, it sounds like a JAMstack app.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/aws-s3-static-files-gatsby.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Static output from Gatsby on AWS S3</em></p>
<p>But that doesn’t mean we have to always build 100% of the app within the browser. Tools like Gatsby and other <a target="_blank" href="https://www.staticgen.com/">static site generators</a> allow us to pull in some or all of our API sources at build time and render the pages out as HTML files.</p>
<p>Think if you have a Wordpress blog, we can pull in all of the posts and ultimately create a new HTML file for each post. That means we’re going to be able to serve a precompiled version of the page directly to the browser which usually equates to a quicker <a target="_blank" href="https://developers.google.com/web/tools/lighthouse/audits/first-contentful-paint">first paint</a> and faster experience for your visitor.</p>
<h3 id="heading-one-note-about-hosting">One note about "hosting"</h3>
<p>Using the term hosting here can be misleading if you’re new to the concept. Yeah, your site is technically getting hosted somewhere, but it’s not in the traditional sense. You don’t have a server that you’re maintaining where you upload your files to with an <a target="_blank" href="https://en.wikipedia.org/wiki/File_Transfer_Protocol">FTP</a> client like <a target="_blank" href="https://cyberduck.io/">Cyberduck</a>.</p>
<p>Instead, whether your doing it yourself with S3 or piping it into Netlify (which is actually <a target="_blank" href="https://www.netlify.com/blog/2018/05/14/how-netlify-migrated-to-a-fully-multi-cloud-infrastructure/">multi-cloud</a>), your HTML and static assets are getting served from object storage. On the tail end of that you typically have a CDN like <a target="_blank" href="https://www.cloudflare.com/">Cloudflare</a> which caches those files at locations all over the world making your pages load faster for the people visiting your site.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/cdn-distribution-map.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>CDN distribution map</em></p>
<h2 id="heading-so-what-makes-a-jamstack-app-so-great">So what makes a JAMstack app so great?</h2>
<p>JAMstack apps inherently satisfy most if not all of the <a target="_blank" href="https://aws.amazon.com/blogs/apn/the-5-pillars-of-the-aws-well-architected-framework/">5 pillars of the AWS Well-Architected Framework</a>. These are core concepts that AWS considers to deliver fast, secure, high-performing, resilient, and efficient infrastructure.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/aws-well-architected-framework.jpg" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://aws.amazon.com/architecture/well-architected/">AWS Well-Architected</a></em></p>
<p>Let’s see how…</p>
<h3 id="heading-speed">Speed</h3>
<p>The fact that you’re serving JAMstack apps as static files directly from a CDN (usually) makes it likely your app is going to load super fast. Gone are the days where the server has to spend time building the page before responding; now you serve the page as just plain HTML "as is" or with some type of client side hydration like you’d see with <a target="_blank" href="https://reactjs.org/">React</a>.</p>
<h3 id="heading-cost">Cost</h3>
<p>More often than not, JAMstack sites are going to run cheaper than their server side counterparts. Hosting static assets is cheap and now your page is being served at the same rate.</p>
<h3 id="heading-scalability">Scalability</h3>
<p>Since you’re serving your files off of static hosting, likely a CDN, that pretty much automatically gives you infinite scalability. Most providers will make this claim, meaning you’ll have no trouble letting any influx of people hitting your site in through the front door.</p>
<h3 id="heading-maintenance">Maintenance</h3>
<p>The foundation of your static site isn’t a server, meaning you don't need to maintain it. Whether it’s Netlify, S3, or any other provider, your static HTML, CSS, and JS are maintained for you headache-free.</p>
<h3 id="heading-security">Security</h3>
<p>Doubling down on the lack of server that you have to personally maintain, you don’t really need to worry as much about locking down ways for people to intrude. </p>
<p>Instead, you'll need to focus mostly on permissions to lock down private content and assure your users that their personal information isn't publicly available.</p>
<h3 id="heading-but-this-also-depends-on-your-apis">But this also depends on your APIs</h3>
<p>As much as these points strike true for the static aspects of your site, keep in mind you still might depend on some type of API for your client-side experience. </p>
<p>Try to take advantage of these requests at compile time when you can, such as with a static site generator. Otherwise you’ll need to weigh the amount of hits you’re making to a dynamic endpoint and how it impacts all of the points above for your overall experience.</p>
<h2 id="heading-is-my-website-considered-to-be-on-the-jamstack">Is my website considered to be on the JAMstack?</h2>
<p>We already talked about the 3 components (Javascript, APIs, Markup), but what we didn’t talk about is the fact that you don’t necessarily have to use all 3 of them in order to consider your site worthy of the JAM label.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/were-not-worthy.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Wayne's World "we're not worthy"</em></p>
<p>Really it all boils down to the Markup and how you serve it. Instead of your Rails app rendering your HTML for you, you might host a precompiled React app on S3 that reaches out to Rails via a set of APIs.</p>
<p>But you don’t even need to have APIs. You don’t even need to have Javascript! As long as you’re serving an HTML file without it having to be compiled on a server at request time (aka pre-rendering it), you’ve got yourself a JAMstack site.</p>
<h2 id="heading-what-are-some-examples-of-jamstack">What are some examples of JAMstack?</h2>
<h3 id="heading-freecodecamporg">freecodecamp.org</h3>
<p>Yes! freecodecamp.org and its learning portal <a target="_blank" href="https://www.freecodecamp.org/news/freecodecamp-jamstack/">is a JAMstack site</a> built on Gatsby. Even with the complexities of providing an app to take code courses with, freeCodeCamp is able to pull together the power of a static site generator and powerful APIs to bring people around the world the power of learning code.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/freecodecamp.jpg" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://www.freecodecamp.org/">https://www.freecodecamp.org/</a></em></p>
<p>You can see Quincy from freeCodeCamp talk more about this at the 2018 JAMstack_conf:<br><a target="_blank" href="https://www.youtube.com/watch?v=e5H7CI3yqPY">https://www.youtube.com/watch?v=e5H7CI3yqPY</a></p>
<p><em>Note: the News and Forum portals are not currently JAMstack sites.</em></p>
<h3 id="heading-impossible-foods">Impossible Foods</h3>
<p>The main website for <a target="_blank" href="https://impossiblefoods.com/">Impossible Foods</a> is no other than a Gatsby site! Everything from their recipes to their location finder are all compiled through our favorite "blazing fast" static site generator.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/impossible-foods.jpg" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://impossiblefoods.com/">https://impossiblefoods.com/</a></em></p>
<h3 id="heading-webdev">web.dev</h3>
<p>Google’s <a target="_blank" href="https://web.dev/">web.dev</a> resource center is built out using the growing <a target="_blank" href="https://www.11ty.dev/">11ty</a>. You can even find the code made open source at: <a target="_blank" href="https://github.com/GoogleChrome/web.dev">https://github.com/GoogleChrome/web.dev</a></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/google-web-dev-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://web.dev/">https://web.dev/</a></em></p>
<h2 id="heading-what-are-some-tools-i-can-use-to-build-jamstack-sites-or-apps">What are some tools I can use to build JAMstack sites or apps?</h2>
<p>The good news with all of this buzz is there are a ton of tools currently available and a ton more on the way. They might still be a little rough around the edges, but that’s because this is a brave new world of tooling and that takes some smoothing out to get just right.</p>
<h3 id="heading-constructing-your-app">Constructing your app</h3>
<p>This is the fun part. How are you going to build your app? With <a target="_blank" href="https://github.com/scullyio/scully">Scully</a> <a target="_blank" href="https://www.netlify.com/blog/2019/12/16/introducing-scully-the-angular-static-site-generator/">in the picture</a>, you can pretty much pick your favorite flavor of UI framework and get off the ground running. Here’s a few popular ones to get started, but by no means is it exhaustive.</p>
<ul>
<li><a target="_blank" href="https://www.11ty.dev/">11ty</a></li>
<li><a target="_blank" href="https://www.gatsbyjs.org/">Gatsby</a></li>
<li><a target="_blank" href="https://gohugo.io/">Hugo</a></li>
<li><a target="_blank" href="https://www.nift.cc/">Nift</a></li>
<li><a target="_blank" href="https://github.com/scullyio/scully">Scully</a> (for you Angular fans)</li>
<li><a target="_blank" href="https://www.staticgen.com">And many more…</a></li>
</ul>
<p><em>Need me to pick one?</em> Start with Gatsby and <a target="_blank" href="https://github.com/colbyfayock/gatsby-starter-sass">bootstrap with a simple starter</a>.</p>
<h3 id="heading-serving-your-app">Serving your app</h3>
<p>I like to think of this as the easy part depending on your setup. Tools like Netlify and Zeit make this a breeze to configure by hooking into your Github repo and building anytime a new commit gets pushed, but of course you have options like AWS if you want more control.</p>
<ul>
<li><a target="_blank" href="https://aws.amazon.com/getting-started/projects/host-static-website/">AWS</a></li>
<li><a target="_blank" href="https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-static-website">Azure</a></li>
<li><a target="_blank" href="https://cloud.google.com/storage/docs/hosting-static-website">GCP</a></li>
<li><a target="_blank" href="https://pages.github.com/">Github Pages</a></li>
<li><a target="_blank" href="https://www.netlify.com/">Netlify</a></li>
<li><a target="_blank" href="https://surge.sh/">Surge</a></li>
<li><a target="_blank" href="https://zeit.co/">Zeit</a></li>
</ul>
<p><em>Need me to pick one?</em> Start with Netlify and <a target="_blank" href="https://www.netlify.com/blog/2016/09/29/a-step-by-step-guide-deploying-on-netlify/">take 5 minutes to deploy</a> that Gatsby site.</p>
<h3 id="heading-making-your-app-dynamic">Making your app dynamic</h3>
<p>Really this can be anything that can be used as an API making requests from the browser. I’m not going to list a bunch of examples per type, but here are a few tools and places you can find some resources.</p>
<ul>
<li><a target="_blank" href="https://auth0.com/">Auth0</a> - Authentication</li>
<li><a target="_blank" href="https://cloudinary.com/">Cloudinary</a> - Media management</li>
<li><a target="_blank" href="https://analytics.google.com/analytics/web/#/">Google Analytics</a> - Web traffic analytics</li>
<li><a target="_blank" href="https://headlesscms.org/">headlesscms.org</a> - Endless list of headless CMSs</li>
<li><a target="_blank" href="https://www.sanity.io/">Sanity</a> - CMS</li>
<li><a target="_blank" href="https://serverless.com/">Serverless Framework</a> - DIY, easy to deploy serverless resources</li>
<li><a target="_blank" href="https://snipcart.com/">Snipcart</a> - Ecommerce</li>
<li><a target="_blank" href="https://stripe.com/">Stripe</a> - Payment management</li>
<li><a target="_blank" href="https://github.com/agarrharr/awesome-static-website-services">And a bunch of other resources…</a></li>
<li><a target="_blank" href="https://headlesscms.org/">And a bunch of other CMS choices…</a></li>
<li><a target="_blank" href="https://jamstack.wtf/">And some general info and tools...</a></li>
</ul>
<h3 id="heading-and-how-about-general-resources-to-learn">And how about general resources to learn?</h3>
<p>You can find a lot of resources to get up and running quickly in the JAMstack world.</p>
<ul>
<li><a target="_blank" href="https://www.freecodecamp.org/news/how-to-host-and-deploy-a-static-website-or-jamstack-app-to-s3-and-cloudfront/">How to host and deploy a static website or JAMstack app to AWS S3 and CloudFront</a> from me on freeCodeCamp</li>
<li><a target="_blank" href="https://www.netlify.com/blog/2016/02/24/a-step-by-step-guide-gatsby-on-netlify/">A Step-by-Step Guide: Gatsby on Netlify</a> from Netlify</li>
<li><a target="_blank" href="https://www.filamentgroup.com/lab/build-a-blog/">Build your own Blog from Scratch using Eleventy</a> from filament group</li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/a-beginners-guide-on-how-to-host-a-static-site-with-aws/">How to Host your Static Website with AWS - A Beginner's Guide</a> from freeCodeCamp</li>
<li><a target="_blank" href="https://snipcart.com/blog/hugo-tutorial-static-site-ecommerce">Hugo Tutorial: How to Build &amp; Host a (Very Fast) Static E-Commerce Site</a> from SnipCart</li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/building-jamstack-apps/">How to Build Authenticated Serverless JAMstack Apps with Gatsby and Netlify</a> from freeCodeCamp</li>
</ul>
<h2 id="heading-expect-to-see-more">Expect to see more</h2>
<p>Similar to its serverless counterpart, the days of JAMstack are young. As time goes on, we’ll be seeing the tooling mature and expand providing new exciting ways for us to quickly build fast sites that anyone can use.</p>
<p>Join in the conversation on Twitter and <a target="_blank" href="https://twitter.com/colbyfayock">let me know</a> what your favorite part of building a JAMstack site is!</p>
<h2 id="heading-missing-something">Missing something?</h2>
<p>Missing your favorite JAMstack tool or an awesome example? <a target="_blank" href="https://twitter.com/colbyfayock">Ping me on Twitter</a>!</p>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="600" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">? Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">?️ Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Become a Full Stack Web Developer – Handbook for Beginners ]]>
                </title>
                <description>
                    <![CDATA[ Full stack web developers are the Swiss Army knife of the code world. Having that designation means you can produce end to end solutions, which is a highly marketable and agile skillset. But what does it actually take to achieve that status? Whether ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-become-a-full-stack-web-developer-in-2020/</link>
                <guid isPermaLink="false">66b8e34247c23b7ae1ad0bd7</guid>
                
                    <category>
                        <![CDATA[ full stack ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JAMstack ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Wed, 05 Feb 2020 01:34:07 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/07/How-to-Become-a-Full-Stack-Web-Developer-Book-Cover--1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Full stack web developers are the Swiss Army knife of the code world. Having that designation means you can produce end to end solutions, which is a highly marketable and agile skillset. But what does it actually take to achieve that status?</p>
<p>Whether you're new, seasoned, or specialized in one end of the stack, there's a lot to digest here. Feel free to dive in from the top or bounce around to where you need the most support.</p>
<ul>
<li><a class="post-section-overview" href="#heading-first-off-what-really-makes-a-developer-full-stack">First off, what really makes a developer full stack?</a></li>
<li><a class="post-section-overview" href="#heading-before-we-dive-in-lets-talk-about-that-focus">Before we dive in, let’s talk about that focus</a></li>
<li><a class="post-section-overview" href="#heading-so-where-do-we-start">So where do we start?</a></li>
<li><a class="post-section-overview" href="#heading-front-end">Front End</a></li>
<li><a class="post-section-overview" href="#heading-back-end">Back End</a></li>
<li><a class="post-section-overview" href="#heading-devops-and-the-cloud">DevOps and the cloud</a></li>
<li><a class="post-section-overview" href="#heading-what-about-design">What about design?</a></li>
<li><a class="post-section-overview" href="#heading-other-things-if-youre-just-getting-started">Other things if you're just getting started</a></li>
<li><a class="post-section-overview" href="#heading-other-things-if-youre-looking-for-more">Other things if you're looking for more</a></li>
</ul>
<h2 id="heading-first-off-what-really-makes-a-developer-full-stack">First off, what really makes a developer full stack?</h2>
<p>It’s fun and buzzy to say any <a target="_blank" href="https://full-stack.netlify.com/">front end developer is a full stack developer</a>, but being able to deploy a website to <a target="_blank" href="https://www.netlify.com/">Netlify</a> doesn’t make you full stack. </p>
<p>This isn’t meant to be discouraging – just realistically, only having that experience won’t hold up well to that job title in your next interview. While you’re technically creating and deploying your work from start to finish, Netlify, <a target="_blank" href="https://zeit.co/">Zeit</a>, and other providers give you the power to do this with their magical tools that take the majority of the stack operations work out of the equation.</p>
<p>That’s not to take away from what we’re all able to accomplish now as front end devs. The growing movement to compile and deploy static websites has just made this process simpler on the later half of the stack with benefits across the board. </p>
<p>Additionally, with the flexibility of tooling options like being able to run JS on a server, our skillsets are able to transfer to more use cases than ever before.</p>
<h3 id="heading-where-we-came-from">Where we came from</h3>
<p>The web development landscape has been changing rapidly. <a target="_blank" href="https://wordpress.org/">Wordpress</a> has been king CMS for a little while now, representing over a third of websites who use a CMS and helping PHP gain popularity. But others worked off of homegrown solutions.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/wordpress-cms-share.jpg" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://trends.builtwith.com/cms">https://trends.builtwith.com/cms</a></em></p>
<p>These represented a more traditional web stack like <a target="_blank" href="https://en.wikipedia.org/wiki/LAMP_(software_bundle)">LAMP</a>. In these cases, you had web servers usually running some kind of content management system and a server side language (like PHP) that would interface with the databases and produce the code that would ultimately be delivered to the browser.</p>
<p>On top of that, you might have Javascript making some interactive features with CSS managing the display of the page. Now in some instances, having a managed Wordpress server is all you need for certain web hosts. But other larger sites would require another team to manage those services and the deploy pipeline for getting the code out to production.</p>
<h3 id="heading-where-we-are-and-where-were-going">Where we are and where we’re going</h3>
<p>While <a target="_blank" href="https://trends.builtwith.com/cms/WordPress">Wordpress isn’t going anywhere</a>, the <a target="_blank" href="https://aws.amazon.com/serverless/">serverless</a> and <a target="_blank" href="https://jamstack.org/">JAMstack</a> architectures are building momentum. For those unfamiliar, the idea isn’t that there are literally no servers, but it’s more about using servers that are managed for you in the cloud. </p>
<p>Services like <a target="_blank" href="https://aws.amazon.com/lambda/">AWS Lambda</a> let you build a “function” that processes simple input and output. Attach that to <a target="_blank" href="https://aws.amazon.com/api-gateway/">API Gateway</a> and you immediately have an endpoint you can interface with without ever having to actually manage a server. </p>
<p>Others like <a target="_blank" href="https://aws.amazon.com/s3/">S3</a> let you dump HTML, CSS, JS, images, and whatever other static assets into storage and serve the site directly from it. Nothing gets processed on the server, you’re simply serving the static files to the client.</p>
<p>The brilliant part about this is there’s a lot less overhead and it's typically a whole heck of a lot cheaper. Many cases, you’ll also get a huge performance boost, where serving a site from s3 will require less processing to get that <a target="_blank" href="https://developers.google.com/web/tools/lighthouse/audits/ttfb">first response to the browser</a>, which can directly equate to improved user experience.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/brett-rambo-thumbs-up.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Thumbs up to a good user experience!</em></p>
<p>This isn’t to push you to the JAMstack, but to show that the full stack paradigm is shifting and it’s something worth looking at. There still is a traditional sense of the difference in work, but it’s becoming a bit different.</p>
<p>DevOps teams now manage cloud resources and deploys. Backend developers now build APIs and code that interfaces with services using tools like lambda functions. And front end developers primarily work in Javascript building <a target="_blank" href="https://reactjs.org/">React</a> or <a target="_blank" href="https://vuejs.org/">Vue</a> apps that reach out to the services your backend developers created. Arguably, this might or might not include things like CSS, but that’s another can of worms about what title that work “officially” falls under (spoiler: depends on the team).</p>
<p>While there is still a split sense of duties, the line is blurring and makes it more manageable to spread your focus.</p>
<h2 id="heading-before-we-dive-in-lets-talk-about-that-focus">Before we dive in, let’s talk about that focus</h2>
<p>It can be pretty tempting to want to dive right in and cover the full spectrum of a full stack developer, but there’s something to be said about focus. This is the basis of the expression “<a target="_blank" href="https://en.wikipedia.org/wiki/Jack_of_all_trades,_master_of_none">jack of all trades, master of none</a>,” where you try to learn a little bit of each part of the full stack and never really master anything.</p>
<p>This can be dangerous when starting off trying to build your strengths as a new developer. So try to evaluate what type of learner you are and lend your focus where it matters. If you’re struggling with a spread out curriculum, that might not necessarily help get you the experience you need to land that first job or that dream job you’re reaching for. </p>
<p>A novel approach, for example, could be having an individual focus, but building the full stack skills around that strength. This might be a front end developer who can deploy their own web apps and continuing to build on that fundamental knowledge.</p>
<p>On top of that, part of being a full stack developer isn't necessarily being able to say that you know x, y, and z languages. Understanding code and software design concepts as well as being able to tackle any challenge at hand, stack aside, is what makes a great developer.</p>
<p>The bottom line, try to figure out what's best for you and don't let your high ambition get in the way of mastering your journey.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/mr-miyagi-approves.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Mr. Miyagi approves</em></p>
<h2 id="heading-so-where-do-we-start">So where do we start?</h2>
<p>For the purposes of this article, we’re going to keep with the traditional breakpoints of what break up the stack (front end, back end, etc.). Though <a target="_blank" href="https://medium.com/better-programming/2020-001-full-stack-pronounced-dead-355d7f78e733">some people say it's not really a thing anymore</a>, realistically, there are tons of jobs for full stack developers and day to day, they refer to the traditional breakpoints. "Full stack developer" definitely isn't going anywhere.</p>
<p>As far as the stack goes, we’re going to lean on the serverless / JAMstack architectures, as that’s just going to keep growing. And if you learn them, it will only make you more marketable with the number of jobs popping up around it.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/boomshakalaka.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Boomshakalaka!</em></p>
<p>As you'll notice below, this isn't meant to be all encompassing with every type of database and every type of rendering solution. A strong developer should be able to be flexible with their tooling, reaching to understand the concepts of their work rather than being single minded and only being able to be productive in one framework. </p>
<p>While you may be working in React and comfortable with it in your current job (that's okay!), your next job could be heavy on Vue or "surprise!" your team lead wants to rewrite the app in <a target="_blank" href="https://svelte.dev/">Svelte</a>. Try to understand why you're using a UI framework in the first place and how it's helping you solve the problem at hand.</p>
<p>Now let's get into it...</p>
<h2 id="heading-front-end">Front End</h2>
<p>The front end of a website or application is typically the UI that the person using your service interacts with. The biggest language player in the game is Javascript, where you’ll typically lean on UI libraries such as React or Vue to manage the components of your project.</p>
<p>Using these UI frameworks will allow you to create “components”, essentially blocks of code, that will end up producing HTML with the ability to create interactions and dynamic states right along with your code. This becomes really powerful, and while there might be a little curve to start, it becomes pretty delightful to work with once you get the hang of it.</p>
<p>Whether new to the field or well experienced, you might eventually run into jQuery. While it has it’s merits and has served the community well, Javascript’s native features have really grown and created less demand for the functionality jQuery was able to provide. Now devs lean on the UI frameworks and native Javascript instead. </p>
<p>So it’s good to understand what jQuery is, but I don’t recommend taking the time to learn it at this point. The good thing is, if you land a job that uses it, you can write native Javascript right along with jQuery, so learning vanilla Javascript itself is the right answer.</p>
<h3 id="heading-so-what-should-i-learn">So what should I learn?</h3>
<p>If you’re truly a beginner, take the time to learn basic HTML and CSS. It might not be as fun and attractive as digging right into Javascript, but <a target="_blank" href="https://www.freecodecamp.org/news/put-down-the-javascript-learn-html-css/">building upon the fundamentals</a> of what makes the web will be key to starting off on the right foot.</p>
<p>Next, learn Javascript. It will remain king for the foreseeable future. Javascript will provide the basis of any framework or library that you build upon, so getting to understand how the bits and pieces of the language itself works will help propel you through your journey of learning the front end side of things.</p>
<p>It will also make your life easier when you’re trying to understand some of the complexities of different patterns and the <a target="_blank" href="https://reactjs.org/docs/getting-started.html#javascript-resources">concepts behind the frameworks</a> you’ll use.</p>
<p>Speaking of frameworks, React and Vue are probably the best candidates given their popularity. React is the most popular out of the bunch and is just going to keep growing. Its team is constantly working to mature the framework and produce APIs that will help build modern, fast web apps.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/front-end-framework-usage.jpg" alt="Image" width="600" height="400" loading="lazy">
_<a target="_blank" href="https://2019.stateofjs.com/front-end-frameworks/#front_end_frameworks_section_overview">2019 State of JS Frameworks</a>_</p>
<p>Getting started with <a target="_blank" href="https://github.com/facebook/create-react-app">Create React App</a> or <a target="_blank" href="https://www.gatsbyjs.org/">Gatsby</a> will even help you easily spin up a React app and immediately get into a position where you can tinker around in the code.</p>
<p>While there would be benefits to call out CSS preprocessors and tools like Sass, there are a ton of solutions now for CSS including <a target="_blank" href="https://cssinjs.org/">CSS-in-JS</a>. </p>
<p>While putting CSS inside of JS has some <a target="_blank" href="https://www.freecodecamp.org/news/you-dont-need-css-in-js-why-i-use-stylesheets/">pros and cons</a>, it isn't necessarily worth pointing out what to use as a particular direction, as it's really going to be team dependent. </p>
<p>Understanding the basics and power of CSS and how to use it in it's vanilla form will help prepare you for utilizing it no matter the framework.</p>
<h3 id="heading-resources">Resources</h3>
<ul>
<li>freecodecamp.org Responsive Web Design Certification <a target="_blank" href="https://www.freecodecamp.org/learn">https://www.freecodecamp.org/learn</a></li>
<li>“Put Down the Javascript: Learn HTML &amp; CSS first“ <a target="_blank" href="https://www.freecodecamp.org/news/put-down-the-javascript-learn-html-css/">https://www.freecodecamp.org/news/put-down-the-javascript-learn-html-css/</a></li>
<li>MDN Intro to Javascript <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript">https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript</a></li>
<li>Just Javascript email course <a target="_blank" href="https://justjavascript.com/">https://justjavascript.com/</a></li>
<li>JSRobot Learning Game <a target="_blank" href="https://lab.reaal.me/jsrobot/">https://lab.reaal.me/jsrobot/</a></li>
<li>reactjs.org Intro to React <a target="_blank" href="https://reactjs.org/tutorial/tutorial.html">https://reactjs.org/tutorial/tutorial.html</a></li>
<li>gatsbyjs.org Tutorials <a target="_blank" href="https://www.gatsbyjs.org/tutorial/">https://www.gatsbyjs.org/tutorial/</a></li>
</ul>
<h2 id="heading-back-end">Back End</h2>
<p>In the JAMstack world, the back end will generally refer to the APIs that our front ends use to create dynamic experiences by interacting with endpoints from the client (like those in <a target="_blank" href="https://en.wikipedia.org/wiki/Create,_read,_update_and_delete">CRUD</a> APIs). Being able to make those requests from the client will remove the need to have to do any of that processing before the page is served to the browser.</p>
<p>Though you shouldn’t feel like you can only ever code in one language, being able to write in Javascript gives a nice advantage here, as you can grow into the fundamentals of working with the back end side of things with a familiar language (or vice versa with the front end). </p>
<p><a target="_blank" href="https://nodejs.org/en/">NodeJS</a> is a common runtime that you’ll find in most cloud environments as an option and will give you a similar experience to what you’d expect in a browser. The main difference is that you won’t have access to certain browser APIs nor will there be a <code>window</code> object and the APIs associated with it.</p>
<p>That said, Python is also <a target="_blank" href="https://pypl.github.io/PYPL.html">another popular language</a> and is growing, especially given its popularity in the data science and engineering community. PHP and Ruby, while both are valid and will give you options in the job market, don’t seem to be as popular and not as much on an overall <a target="_blank" href="https://madnight.github.io/githut/">upward trend</a> as Javascript and Python.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/language-popularity.jpg" alt="Image" width="600" height="400" loading="lazy">
_<a target="_blank" href="https://madnight.github.io/githut/#/pull_requests/2019/4">Popular languages on Github</a>_</p>
<p>With the language of your choice, your best bet will be learning how to create cloud services that your applications can interface with. </p>
<p>Creating a simple lambda that you can play around with, whether in AWS, Netlify, or any other cloud provider, will give you a good experience as to what you might expect when working in the field. </p>
<p>And even if you may not develop directly in a lambda in the job you find, you’ll be able to start getting familiar with concepts that are fundamental to working with the back end. And you'll ultimately use those functions to connect with other services and databases to create your own dynamic services.</p>
<h3 id="heading-so-what-should-i-learn-1">So what should I learn?</h3>
<p>If you’re already working on learning Javascript from the front end side of things, keep going by using Javascript for your backend. Spin up a lambda using <a target="_blank" href="https://docs.netlify.com/functions/overview/">Netlify functions</a>, where you just need to focus on the code and Netlify takes care of the rest (like actually getting your function built and deployed).</p>
<p>With your language of choice and first function, try to start working with other services within your code to get experience working with 3rd party APIs. </p>
<p>Maybe build an endpoint that can <a target="_blank" href="https://github.com/colbyfayock/tweet">send out a tweet</a> using the <a target="_blank" href="https://developer.twitter.com/en/docs">Twitter API</a> (but don’t abuse it). Learn how to create a database and set up your function to interface with it in a CRUD pattern, which will give you a more realistic use case for how a typical app might interact with a backend.</p>
<p>Your goal here should be creating services that your front end will interact with via an endpoint to perform operations for the person using your app. The good news is given the momentum of the cloud, you’ll have a ton of options, and <a target="_blank" href="https://aws.amazon.com/free/">free options</a> or tiers, to start playing around with.</p>
<h3 id="heading-resources-1">Resources</h3>
<ul>
<li>“Super simple start to serverless” <a target="_blank" href="https://kentcdodds.com/blog/super-simple-start-to-serverless">https://kentcdodds.com/blog/super-simple-start-to-serverless</a></li>
<li>“Building Serverless CRUD apps with Netlify Functions &amp; FaunaDB“ <a target="_blank" href="https://www.netlify.com/blog/2018/07/09/building-serverless-crud-apps-with-netlify-functions-faunadb/">https://www.netlify.com/blog/2018/07/09/building-serverless-crud-apps-with-netlify-functions-faunadb/</a></li>
</ul>
<h2 id="heading-devops-and-the-cloud">DevOps and the cloud</h2>
<p>DevOps stems from the need to be able to create solutions that smooth out and speed up the process of getting code from the people writing it to a deployed state. </p>
<p>This work can range from a lot of responsibilities to a few, whether it’s writing bash scripts for a custom solution or writing a <a target="_blank" href="https://aws.amazon.com/cloudformation/">CloudFormation</a> template that creates all of the resources needed for an app to run. </p>
<p>You’ll typically find this included as part of a larger orchestration of <a target="_blank" href="https://en.wikipedia.org/wiki/CI/CD">CI/CD</a> workflows which automate the build and deploy process.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/continuous-integration-continuous-deploy-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>CI / CD Pipeline</em></p>
<p>And this is constantly changing! Given the serverless boom, the <a target="_blank" href="https://serverless.com/">serverless framework</a> popped up which manages a lot of this for you in an easier way, which even lead AWS to create their own solution <a target="_blank" href="https://aws.amazon.com/serverless/sam/">SAM</a>. Tools like <a target="_blank" href="https://jenkins.io/">Jenkins</a> have been around for a bit for the CI/CD part of things, but now you’re seeing <a target="_blank" href="https://github.com/features/actions">Github</a>, <a target="_blank" href="https://about.gitlab.com/product/continuous-integration/">Gitlab</a>, and other source control providers provide their own solutions and tools like <a target="_blank" href="https://circleci.com/">CircleCI</a> that hook right into your project.</p>
<p>It’s also not perfect yet – writing CloudFormation templates is daunting. Writing automation scripts also isn’t the most fun, though it’s super rewarding when it works! </p>
<p>But this is getting better, which is where products like Netlify and Zeit fit in. While they root more from the static hosting side of things, where you compile your app and dump it into storage, their offerings are growing, like <a target="_blank" href="https://www.netlify.com/products/functions/">Netlify’s Functions</a> that are really just AWS Lambdas that are easier to set up and deploy to a fully functioning endpoint (it’s seriously super easy).</p>
<h3 id="heading-so-what-should-i-learn-2">So what should I learn?</h3>
<p>If this is your first time setting this kind of thing up, start with Netlify. Set up a React app or even just a simple HTML file in a Github repository, connect it to a new Netlify account, and watch it deploy.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/netlify-setup.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Easy spinup with <a target="_blank" href="https://www.netlify.com/">Netlify</a></em></p>
<p>From there, or if you have a little experience already, start getting curious about what’s going on behind the scenes. Netlify is likely taking your code, running the commands you set up (like <code>yarn build</code>) in a virtual environment, dumping the files built into storage like S3, and putting a CDN in front of it like CloudFront to serve from an endpoint. </p>
<p>First try doing that manually from your computer using the AWS console and their CLI, then write a script to automate the whole process integrating with Circle CI into your Github project instead of Netlify to get it actually deployed to AWS.</p>
<p>Taking that up a notch will include spinning up services that your back end might interface with. Do you have a database that your services use? You can automate spinning up that database using CloudFormation or bash scripts. </p>
<p>Treating your infrastructure as code with disposable, easily recreatable resources will help you and your projects become more flexible and have a better ability to spin back up in the event of failure.</p>
<p>And this all goes for any cloud or CI / CD provider, not just AWS and Circle CI. Pick your favorite cloud and workflow tool and run with it. The point is, start looking at your project’s needs and dig into what’s actually happening in the automated parts of the stack. This will help you learn more and become more resourceful for your project’s needs.</p>
<h3 id="heading-resources-2">Resources</h3>
<ul>
<li>“A Step-by-Step Guide: Deploying on Netlify” <a target="_blank" href="https://www.netlify.com/blog/2016/09/29/a-step-by-step-guide-deploying-on-netlify/">https://www.netlify.com/blog/2016/09/29/a-step-by-step-guide-deploying-on-netlify/</a></li>
<li>“Setting up a Static Website” <a target="_blank" href="https://docs.aws.amazon.com/AmazonS3/latest/dev/HostingWebsiteOnS3Setup.html">https://docs.aws.amazon.com/AmazonS3/latest/dev/HostingWebsiteOnS3Setup.html</a></li>
<li>“AWS Certified Cloud Practitioner Training 2019 - A Free 4-hour Video Course" <a target="_blank" href="https://www.freecodecamp.org/news/aws-certified-cloud-practitioner-training-2019-free-video-course/">https://www.freecodecamp.org/news/aws-certified-cloud-practitioner-training-2019-free-video-course/</a></li>
<li>See Javascript resources in Front End above</li>
</ul>
<h2 id="heading-what-about-design">What about design?</h2>
<p>Yes, you should understand design basics. No, you don’t need to be a designer.</p>
<p>There are many aspects about design that will accelerate your abilities as a developer. While we all know the visual and UX designers produce magic, having a basic understanding can prevent your application from becoming a huge disappointment.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/pied-piper-user-interface.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Fictional Pied Piper's app tanked because of a bad user experience</em></p>
<p>Everyone in the development process is working towards a goal that impacts an end user in one way or another. Being able to understand what needs your work is trying to solve and how that impacts users will help the team as a whole develop a more comprehensive end solution.</p>
<p>Consider a back end developer creating an API to allow someone to manage users in an app. The requirements of the API are pretty lean and only include the user’s name. Providing that as a single “name” field instead of “first” and “last” might not be the most intuitive solution for most. But it could be an oversight that complicates how the front end developer exposes that in the UI, which would make it a pain for the developer to display or could make it confusing for the end user to consume.</p>
<p>On top of all of that, design can directly impact conversion. If you're building in the ecommerce space, having a button that doesn’t look like a button can prevent people from adding a product to their cart. This, of course, will prevent a purchase, which is lost revenue. Understanding how to humanize the UI even in a basic sense can literally make your project more money or simply help someone use it more easily.</p>
<p>And more importantly, you want your site to be accessible. Many people have different needs, whether they can't see colors the same or can't hear the sounds your app produces, you want to recognize other's needs and try to design in a way that will make your app usable by everyone. </p>
<h3 id="heading-so-what-should-i-learn-3">So what should I learn?</h3>
<p>While I don’t expect you to take a whole course for it, try to be cognizant and curious. And maybe next time don’t skip that <a target="_blank" href="https://www.freecodecamp.org/news/tag/design/">design article</a> you saw pop up on the <a target="_blank" href="https://twitter.com/freecodecamp">freeCodeCamp twitter</a>.</p>
<p>When creating solutions, try to imagine how your work will be used. What will the other developers on your team need from your API? What will the people using your app need from your interface?</p>
<p>You can also try to get inspiration from what others are doing in your space. How would you expect an app to look when providing similar functionality? This isn’t license to copy or steal, but you should understand the needs their solution is solving. Consider why their Add to Cart button is so huge, why they’re giving users the ability to zoom in on a product photo, or how you can make a table design slightly more usable.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/dribbble-table-design.jpg" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://dribbble.com/search/shots/popular/product-design?q=table">"table" product design on Dribbble</a></em></p>
<p>As for accessibility, try to learn the basics. There's a growing amount of resources available to help you understand the needs of others. Try to understand what disabilities there are and how they might affect use of your app. Maybe look at a few common patterns about how to address those concerns. </p>
<p>More often than not, it's not too hard to incorporate, and if you get in the habit of doing it from the start, you won't even think about it the next time you build an app.</p>
<h3 id="heading-resources-3">Resources</h3>
<ul>
<li>Design for Developers <a target="_blank" href="https://thoughtbot.com/upcase/design-for-developers">https://thoughtbot.com/upcase/design-for-developers</a></li>
<li>Hack Design <a target="_blank" href="https://hackdesign.org">https://hackdesign.org</a></li>
<li>Design for Hackers <a target="_blank" href="https://designforhackers.com/">https://designforhackers.com/</a></li>
<li>Intro to Web Accessibility <a target="_blank" href="https://webaim.org/intro/">https://webaim.org/intro/</a></li>
</ul>
<h2 id="heading-other-things-if-youre-just-getting-started">Other things if you're just getting started</h2>
<p>A lot of this article assumes you have some of the basics down such as understanding what <a target="_blank" href="https://en.wikipedia.org/wiki/Git">git</a> and source control is or simply having your code editor set up. If you're truly just getting started, you're going to want to at least have a simple understanding of these concepts, as it'll quickly grow more challenging without them.</p>
<p>There's also something to be said about learning how to use your terminal. It can be overwhelming not to use a GUI if you're new, but once you get moving, you'll quickly find out you'll be more productive by using a terminal and a lot of projects require terminal use anyways.</p>
<h3 id="heading-so-what-should-i-learn-4">So what should I learn?</h3>
<p>First things first, get your code editor set up. <a target="_blank" href="https://code.visualstudio.com/">Visual Studio Code</a> is all the rage right now, but there are others that will serve you well depending on your preferences like <a target="_blank" href="https://atom.io/">Atom</a> or <a target="_blank" href="https://www.sublimetext.com/">Sublime Text</a>. You'll even find cloud based IDEs like <a target="_blank" href="https://repl.it/">Repl.it</a> or you can just get started with a lower barrier of entry by playing around in <a target="_blank" href="https://codepen.io/">CodePen</a> or <a target="_blank" href="https://jsfiddle.net/">JSFiddle</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/visual-studio-code-so-hot.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Visual Studio Code is so hot right now</em></p>
<p>Either way, once you're ready to get coding, you want to understand what source control is, where git is the biggest player right now. Git is a powerful tool that lets you track changes to code and become more productive collaborating with other developers.</p>
<p>You'll want to get familiar with some of the basic commands of git like adding new changes as well as what branches are and how to use them. Git is a huge world, you don't need to master it right away, you'll quickly learn there's an endless amount of new things to learn on your journey to mastering your git fu.</p>
<p>For a lot of tools you'll use, there are GUIs available like <a target="_blank" href="https://www.gitkraken.com/">GitKraken</a>, but you'll still be a bit limited with what you can do. Learning your way around the default terminals on your machine or downloading other options like <a target="_blank" href="https://iterm2.com/">iterm2</a> (my preference) or <a target="_blank" href="https://xtermjs.org/">Xterm.js</a> will be your best bet. Bonus: you'll feel like a movie hacker every time you use it (or is that just me?).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/hacking-swordfish.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Hugh Jackman hacking in Swordfish</em></p>
<h3 id="heading-resources-4">Resources</h3>
<ul>
<li>Getting Started with Visual Studio Code <a target="_blank" href="https://www.codecademy.com/articles/visual-studio-code">https://www.codecademy.com/articles/visual-studio-code</a></li>
<li>Git resources from Github <a target="_blank" href="https://try.github.io/">https://try.github.io/</a></li>
<li>Learn git by branching game <a target="_blank" href="https://learngitbranching.js.org/">https://learngitbranching.js.org/</a></li>
<li>Intro to the Mac Command Line <a target="_blank" href="https://blog.teamtreehouse.com/introduction-to-the-mac-os-x-command-line">https://blog.teamtreehouse.com/introduction-to-the-mac-os-x-command-line</a></li>
</ul>
<h2 id="heading-other-things-if-youre-looking-for-more">Other things if you're looking for more</h2>
<p>There's so much more you can quickly go down a rabbit hole with. Remember not to spread your focus and try not to overwhelm yourself. But if you're feeling pretty good about where you are, there are some other concepts that will only help as you tackle challenges in the real world.</p>
<h3 id="heading-testinghttpsenwikipediaorgwikisoftwaretesting-and-the-different-methodologies"><a target="_blank" href="https://en.wikipedia.org/wiki/Software_testing">Testing</a> and the different methodologies</h3>
<p>Writing code is one thing, but being able to set up effective tests will help harden your code and prevent bugs from getting out. You don't want to waste your future time or even cost your product money when the site goes down. Learning how to write tests and the different approaches is important to solidifying your code.</p>
<h3 id="heading-browser-tools-like-chrome-devtoolshttpsdevelopersgooglecomwebtoolschrome-devtools">Browser tools like <a target="_blank" href="https://developers.google.com/web/tools/chrome-devtools">Chrome DevTools</a></h3>
<p>One of the most powerful tools you can have when debugging, in my opinion, is being able to debug your application in the browser. </p>
<p>Whether it's looking at how the DOM is being rendered, <a target="_blank" href="https://developers.google.com/web/tools/chrome-devtools/inspect-styles/edit-styles">playing with the CSS</a>, or debugging your network requests, you'll learn quickly how to save time and more easily identify where the bug is coming from.</p>
<h3 id="heading-httphttpsdevelopersgooglecomwebfundamentalsperformancehttp2-and-how-to-debug-requests-in-the-network-panelhttpsdevelopersgooglecomwebtoolschrome-devtoolsnetwork"><a target="_blank" href="https://developers.google.com/web/fundamentals/performance/http2">HTTP</a> and how to debug requests in the <a target="_blank" href="https://developers.google.com/web/tools/chrome-devtools/network">network panel</a></h3>
<p>Given the web is based on the internet, your application will ultimately be making requests to other servers. When this happens, understanding the request chokepoints or simply how a request is being made can help you understand why your application seems laggy or why your save button isn't working. </p>
<p>Having a basic understanding of how requests works and how to visualize them for debugging will go a long way in your journey.</p>
<h3 id="heading-open-source-software-and-package-managers">Open Source Software and package managers</h3>
<p>This one's not as much of a skill or tool to learn as much as it is a way that software is distributed. As you start building code solutions, you'll find out that a lot of us lean on open source packages. Most of the time it's through <a target="_blank" href="https://www.npmjs.com/">npm</a> if you're writing Javascript, which helps us become more productive not having to reinvent the wheel each time. </p>
<p>Spend some time getting to understand the open source concept and even consider giving back by contributing to your favorite project. Lending a hand is usually super appreciated, will help you gain experience, and you might even be able to score some <a target="_blank" href="https://www.gatsbyjs.org/contributing/contributor-swag/">free swag on your first approved pull request</a>! Just be respectful out there, there's also a real person on the other side of the request.</p>
<h2 id="heading-what-else">What else?</h2>
<p>This list can go on forever as there's so much to the world of coding. What else do you think is important in one's journey to become a development master? Send me a <a target="_blank" href="https://twitter.com/colbyfayock">tweet or DM</a> if you think I'm missing something important!</p>
<h2 id="heading-youre-on-fire-pulling-it-all-together">You're on fire! Pulling it all together</h2>
<p>Given all of the experience you’ll have accumulated with the above, you should be in a position to be able to create an entire app from start to finish by yourself. Do you understand the power that you have?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/thanos-glove-1.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Thanos squeezing the gauntlet</em></p>
<p>This is where the fun starts. Try to create a new app – doesn’t matter what it is, just build something. The best thing you can do for learning is to gain experience by doing. Doesn't matter whether it’s one of the million todo tutorials you’ll find or by teaching yourself to code by building one of the largest social networks like the <a target="_blank" href="https://thenextweb.com/2012/04/10/instagrams-ceo-had-no-formal-programming-training-hes-a-marketer-who-learned-to-code-by-night/">creator of Instagram</a>.</p>
<p>From here, you should be able to create:</p>
<ul>
<li>A web app front end that runs in the browser</li>
<li>Backend services that your web app can make requests to via endpoints</li>
<li>Write a script to plug into a CI / CD tool to automate your build and deploy process</li>
<li>Bonus: making good decisions about how your interface looks so people can actually use it!</li>
</ul>
<p>Go forth and build! <a target="_blank" href="https://twitter.com/intent/tweet?text=My%20%23codejourney%20started%20with...%0A%0AHow%20to%20Become%20a%20Full%20Stack%20Web%20Developer%20in%20a%20JAMstack%202020%0A@colbyfayock%20@freecodecamp%0Ahttps%3A%2F%2Fwww.freecodecamp.org%2Fnews%2Fhow-to-become-a-full-stack-web-developer-in-2020">Share with us your development journey</a> on Twitter using hashtag #codejourney. We'd love to hear more about where you've been and what you've built or where you're going and what you want to build.</p>
<div id="colbyfayock-author-card">
  <p>
    <a href="https://twitter.com/colbyfayock">
      <img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" width="2000" height="400" loading="lazy">
    </a>
  </p>
  <ul>
    <li>
      <a href="https://twitter.com/colbyfayock">? Follow Me On Twitter</a>
    </li>
    <li>
      <a href="https://youtube.com/colbyfayock">?️ Subscribe To My Youtube</a>
    </li>
    <li>
      <a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a>
    </li>
  </ul>
</div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build Authenticated Serverless JAMstack Apps with Gatsby and Netlify ]]>
                </title>
                <description>
                    <![CDATA[ By swyx When interacting with a backend, a JAMstack app can do everything a mobile app can do, without the tyranny of the app store. This is a fundamental insight that goes as deep as the fight for a more open,  secure, decoupled, faster web. Static ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/building-jamstack-apps/</link>
                <guid isPermaLink="false">66d4614a4a0edd9b48e8358f</guid>
                
                    <category>
                        <![CDATA[ Gatsby ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JAMstack ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Netlify ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 11 Sep 2019 20:22:51 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/09/D1dQf4uWkAAAwkD.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By swyx</p>
<p>When interacting with a backend, a JAMstack app can do everything a mobile app can do, without the tyranny of the app store. This is a fundamental insight that goes as deep as the fight for a more open,  secure, decoupled, faster web.</p>
<p>Static site generators (SSGs) are traditionally used to generate markup HTML for static sites, and even <a target="_blank" href="https://css-tricks.com/lets-build-a-jamstack-e-commerce-store-with-netlify-functions/">e-commerce sites</a>, but the modern generation of JavaScript SSGs are enabling full-blown, blazing fast web apps. Gatsby uses JavaScript to rehydrate Markup into a fully dynamic React app - which means you can use APIs to do all sorts of dynamic functionality!</p>
<p>Let's see how we can incrementally add functionality to a Gatsby static site with Netlify Functions, and then add authentication with Netlify Identity to create a proper Gatsby app. We'll gradually build up to <a target="_blank" href="https://github.com/sw-yx/jamstack-hackathon-starter/">a full working demo</a> with:</p>
<ul>
<li>??Dynamic Clientside Pages in Gatsby</li>
<li>?Serverless Functions (with Netlify Dev)</li>
<li>??‍♂️Hide API Secrets from being exposed to Frontend</li>
<li>?Authentication (with Netlify Identity)</li>
<li>?Protected Routes</li>
<li>?Authenticated Serverless Functions (why not!)</li>
<li>?External Provider login with GitHub, Bitbucket, Google, etc.</li>
</ul>
<h2 id="heading-not-your-parents-static-site-generator">Not Your Parent's Static Site Generator</h2>
<p>Why would you use something like Gatsby over Jekyll or Hugo or one of the <a target="_blank" href="https://www.staticgen.com/">hundreds of Static Site Generators</a> out there? <a target="_blank" href="https://www.gatsbyjs.org/blog/2018-2-27-why-i-upgraded-my-website-to-gatsbyjs-from-jekyll/">There are many reasons</a>, but one of the unique selling points is how Gatsby helps you build <a target="_blank" href="https://www.gatsbyjs.org/docs/progressive-web-app/#progressive-web-app">"Static Progressive Web Apps"</a> with React.</p>
<p><a target="_blank" href="https://www.gatsbyjs.org/docs/production-app/#dom-hydration">Gatsby's ability to rehydrate</a> (what a delicious word!) the DOM means you can do incredibly dynamic things with JavaScript and React that would be much harder with legacy SSG's.</p>
<p>Let's say you have a typical static Gatsby site, like <a target="_blank" href="https://www.gatsbyjs.org/starters/gatsby-starter-default">gatsby-starter-default</a>. You can <code>npm run build</code> it, and it spits out a bunch of HTML files. Great! I can host that for free!</p>
<p>Now imagine your client comes to you and asks you to add some custom logic that needs to be executed on the server:</p>
<ul>
<li>Maybe you have third party API secrets you don't want to expose to your user.</li>
<li>Maybe you need <a target="_blank" href="https://alligator.io/nodejs/solve-cors-once-and-for-all-netlify-dev/">a serverside proxy to get around CORS issues</a>.</li>
<li>Maybe you need to ping a database to check your inventory.</li>
</ul>
<p><strong>Oh no! Now you have to rewrite everything and move to a Digital Ocean droplet!</strong></p>
<p>I'm kidding. No, you don't have to rewrite everything.</p>
<p>The beauty of serverless functions is that it is incrementally adoptable - <strong>your site grows with your needs</strong> - and with JavaScript you can rerender entire sections of your site based on live API data. Of course, the more you do this, the more resource intensive (in terms of bandwidth and computation) it can be, so there is a performance tradeoff. <strong>Your site should be as dynamic as you need it to be, but no more.</strong> Gatsby is perfect for this.</p>
<h2 id="heading-using-netlify-dev-to-add-serverless-functions">Using Netlify Dev to add Serverless Functions</h2>
<p><a target="_blank" href="https://www.netlify.com/docs/functions/?utm_source=blog&amp;utm_medium=freecodecamp&amp;utm_campaign=devex">Netlify Functions</a> are a great low configuration solution for adding serverless functionality to your Gatsby site.</p>
<p>We'll assume you have a Gatsby site ready to go already, preferably linked to a Git remote like GitHub. If you don't have one, fork and download <a target="_blank" href="https://app.netlify.com/start/deploy?repository=https://github.com/gatsbyjs/gatsby-starter-default">gatsby-starter-default</a>. Let's walk through the steps to add Netlify Functions:</p>
<ol>
<li><strong>Install Netlify CLI and login</strong>: </li>
</ol>
<pre><code class="lang-bash">npm i -g netlify-cli
netlify login <span class="hljs-comment"># to link your free Netlify account</span>
</code></pre>
<p>Pretty straightforward.</p>
<ol start="2">
<li><strong>Create your Netlify instance for your Gatsby site</strong>: </li>
</ol>
<pre><code class="lang-bash">netlify init
</code></pre>
<p>You will be prompted for a "build command", which for Gatsby is <code>yarn build</code>, and a "publish directory", which for Gatsby is <code>public</code>. You can also save this in a <a target="_blank" href="https://www.netlify.com/docs/netlify-toml-reference/?utm_source=blog&amp;utm_medium=freecodecamp&amp;utm_campaign=devex">netlify.toml config file</a>, or the CLI will create it for you:</p>
<pre><code class="lang-toml:title=netlify.toml">[build]
  command = "yarn build"
  functions = "functions"
  publish = "public"
</code></pre>
<p>As you can see in the above example, We'll also specify where we'll save our functions to the creatively named <code>functions</code> folder.</p>
<ol start="3">
<li><strong>Create your first Netlify Function</strong>: Netlify CLI has a <a target="_blank" href="https://github.com/netlify/cli/tree/master/src/functions-templates/js">set of templates</a> available to help you get started writing serverless functions. Just run:</li>
</ol>
<pre><code class="lang-bash">netlify <span class="hljs-built_in">functions</span>:create <span class="hljs-comment"># ntl functions:create also works</span>
</code></pre>
<p>You'll be presented with an autocomplete list. We'll pick the <code>token-hider</code> example for now. Once you select it, the CLI will copy out the necessary files, and install the necessary <code>axios</code> dependencies.</p>
<p>Notice that <code>token-hider.js</code> includes this line:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> { API_SECRET = <span class="hljs-string">"shiba"</span> } = process.env
</code></pre>
<p>This is meant to simulate API secrets that you don't want to expose to the frontend. You can set these as <a target="_blank" href="https://www.netlify.com/docs/continuous-deployment/?utm_source=blog&amp;utm_medium=freecodecamp&amp;utm_campaign=devex#environment-variables">build environment variables</a> on your site's Netlify Dashboard. You can name them whatever you like, and for the purposes of our demo we've provided a default, but of course feel free to modify this code however you like. It's Just JavaScript™!</p>
<ol start="4">
<li><strong>Make sure function dependencies are installed with <code>netlify-lambda</code></strong> (Optional but Recommended) </li>
</ol>
<p>Notice that your function comes with its own <code>package.json</code> and <code>node_modules</code>. This means each function can have their own independently managed dependencies, but you also need to make sure these dependencies are installed when you deploy or when someone else clones your repo. You can either check them into git (ugh!), or write a bash script to do this installation. But don't worry, there's a simple utility to automate this:</p>
<pre><code class="lang-bash">yarn add -D netlify-lambda
</code></pre>
<p>And add a postinstall script in <code>package.json</code> (this isn't Netlify specific, it is part of <a target="_blank" href="https://docs.npmjs.com/misc/scripts#description">how npm works</a>):</p>
<pre><code class="lang-js">  <span class="hljs-string">"scripts"</span>: {
    <span class="hljs-string">"postinstall"</span>: <span class="hljs-string">"netlify-lambda install"</span>
  },
</code></pre>
<ol start="5">
<li><strong>Fire up Gatsby and Functions with Netlify Dev</strong></li>
</ol>
<p><a target="_blank" href="https://www.netlify.com/blog/2019/04/09/netlify-dev-our-entire-platform-right-on-your-laptop/?utm_source=blog&amp;utm_medium=freecodecamp&amp;utm_campaign=devex">Netlify Dev</a> is the local proxy server embedded in the CLI that we will use to develop our Functions alongside our Gatsby app. You can start it like so:</p>
<pre><code class="lang-bash">netlify dev <span class="hljs-comment"># or ntl dev</span>
</code></pre>
<p>Your Gatsby app will now be accessible at <code>http://localhost:8888</code> and your function will be accessible at <code>http://localhost:8888/.netlify/function/token-hider</code>. Check it out in your browser!</p>
<p>How are both the Gatsby dev server and the Netlify Functions server both available on the same local port? How come the API_SECRET you set on the Netlify side is available in local development? The rough mental image you should have looks <a target="_blank" href="https://github.com/netlify/cli/blob/master/docs/netlify-dev.md">something like this</a>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/09/ASCCII-ART.png" alt="ASCCII-ART" width="600" height="400" loading="lazy"></p>
<p>You can hit your Netlify Function from anywhere in your Gatsby app! For example, in any event handler or lifecycle method, insert:</p>
<pre><code class="lang-js">fetch(<span class="hljs-string">"/.netlify/functions/token-hider"</span>)
  .then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> response.json())
  .then(<span class="hljs-built_in">console</span>.log)
</code></pre>
<p>and watch a list of dog images pop up in your console.  If you are new to React, I highly recommend <a target="_blank" href="https://reactjs.org/docs/handling-events.html">reading through the React docs</a> to understand where and how to insert event handlers so you can, for example, <a target="_blank" href="https://reactjs.org/docs/handling-events.html">respond to a button click</a>.</p>
<h2 id="heading-adding-authentication">Adding Authentication</h2>
<p>So, yes, your site can now be more dynamic than any static site: It can hit any database or API. You can hide API tokens from prying eyes. It runs rings around CORS (by the way, you can also use <a target="_blank" href="https://www.netlify.com/docs/redirects/?utm_source=blog&amp;utm_medium=freecodecamp&amp;utm_campaign=devex">Netlify Redirects</a> for that). But its not an <em>app</em> app. Yet!</p>
<p>The key thing about web apps (and, let's face it, the key thing users really pay for) is they all have some concept of <code>user</code>, and that brings with it all manner of complication from security to state management to <a target="_blank" href="https://www.netlify.com/docs/visitor-access-control/?utm_source=blog&amp;utm_medium=freecodecamp&amp;utm_campaign=devex#role-based-access-controls-with-jwt-tokens">role-based access control</a>. Entire routes need to be guarded by authentication, and sensitive content shielded from Gatsby's static generation. Sometimes there are things you -don't- want Google's spiders to see!</p>
<p>It's a different tier of concern, which makes it hard to write about in the same article as a typical Gatsby tutorial. But we're here to make apps, so let's bring it on!</p>
<h2 id="heading-adding-netlify-identity-and-authenticated-pages-to-gatsby">Adding Netlify Identity and Authenticated Pages to Gatsby</h2>
<ol>
<li><strong>Enable Netlify Identity</strong>: Netlify Identity doesn't come enabled by default. You'll have to head to your site admin (eg <code>https://app.netlify.com/sites/YOUR_AWESOME_SITE/identity</code>) to turn it on. <a target="_blank" href="https://www.netlify.com/docs/identity/?utm_source=blog&amp;utm_medium=freecodecamp&amp;utm_campaign=devex">Read the docs</a> for further info on what you can do, for example add Facebook or Google social sign-on!</li>
<li><strong>Install dependencies</strong>: <code>npm install gatsby-plugin-netlify-identity react-netlify-identity-widget  @reach/dialog @reach/tabs @reach/visually-hidden gatsby-plugin-create-client-paths</code></li>
<li><strong>Configure Gatsby</strong>: for dynamic-ness!</li>
</ol>
<pre><code class="lang-jsx:title=gatsby-config.js">// gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: `gatsby-plugin-create-client-paths`,
      options: { prefixes: [`/app/*`] },
    },
    {
      resolve: `gatsby-plugin-netlify-identity`,
      options: {
        url: "https://YOUR_AWESOME_SITE_INSTANCE_HERE.netlify.com",
      },
    },
  ],
}
</code></pre>
<p>This sets up everything under the <code>/app</code> route to be dynamic on the clientside, which means you can put it behind an authentication wall.</p>
<ol start="4">
<li><strong>Add the login widget</strong>: <a target="_blank" href="https://github.com/netlify/netlify-identity-widget"><code>netlify-identity-widget</code></a> is a framework-agnostic overlay that ships with a nice signup/login UI. However it is a 60kb package, so there is a 6kb alternative that simply assumes you're using React: <code>react-netlify-identity-widget</code>.</li>
</ol>
<p>The widget is implemented as an accessible modal with <code>@reach/dialog</code>, so you need to put it somewhere in your app:</p>
<pre><code class="lang-jsx:title=src/app/login.js">// src/app/login.js
import React from "react"
import { navigate } from "gatsby"

import { IdentityModal } from "react-netlify-identity-widget"
import "react-netlify-identity-widget/styles.css" // delete if you want to bring your own CSS

export default function Login() {
  const [dialog, setDialog] = React.useState(false)
  return (
    &lt;div&gt;
      &lt;h1&gt;Log in&lt;/h1&gt;
      &lt;button onClick={() =&gt; setDialog(true)}&gt;log in&lt;/button&gt;
      &lt;IdentityModal
        showDialog={dialog}
        onCloseDialog={() =&gt; setDialog(false)}
        onLogin={user =&gt; navigate("/app/profile")}
        onSignup={user =&gt; navigate("/app/profile")}
      /&gt;
    &lt;/div&gt;
  )
}
</code></pre>
<p><code>react-netlify-identity-widget</code> uses React Context, so it normally requires adding a Provider, but <code>gatsby-plugin-netlify-identity</code> already did that for you (that's its whole purpose!).</p>
<p>As you might expect, you can use that Context in the rest of your app. <code>react-netlify-identity-widget</code> exports a <a target="_blank" href="https://kentcdodds.com/blog/how-to-use-react-context-effectively">Custom Consumer Hook</a> called <code>useIdentityContext</code>, which helps do some runtime checks and makes TypeScript typing easier by removing an <code>undefined</code> check.</p>
<p><code>useIdentityContext</code> returns an <code>identity</code> object, and <a target="_blank" href="https://github.com/sw-yx/react-netlify-identity#user-content-usage">you can see the plethora of data and methods it exposes to you on the docs</a>. Let's use them to implement a <code>NavBar</code> component!</p>
<pre><code class="lang-jsx:title=src/app/components/NavBar.js">// src/app/components/NavBar.js
import React from "react"
import { Link, navigate } from "gatsby"
import { useIdentityContext } from "react-netlify-identity-widget"

export default function NavBar() {
  const { user, isLoggedIn, logoutUser } = useIdentityContext()
  let message = isLoggedIn
    ? `Hello, ${user.user_metadata &amp;&amp; user.user_metadata.full_name}`
    : "You are not logged in"
  const handleClick = async event =&gt; {
    event.preventDefault()
    await logoutUser()
    navigate(`/app/login`)
  }
  return (
    &lt;div&gt;
      &lt;span&gt;{message}&lt;/span&gt;
      &lt;nav&gt;
        &lt;span&gt;Navigate the app: &lt;/span&gt;
        &lt;Link to="/app/"&gt;Main&lt;/Link&gt;
        &lt;Link to="/app/profile"&gt;Profile&lt;/Link&gt;
        {isLoggedIn ? (&lt;a href="/" onClick={handleClick}&gt;Logout&lt;/a&gt;) : (&lt;Link to="/app/login"&gt;Login&lt;/Link&gt;)}
      &lt;/nav&gt;
    &lt;/div&gt;
  )
}
</code></pre>
<ol start="5">
<li><strong>Write the rest of your app</strong>: Because of our configuration in <code>gatsby-plugin-create-client-paths</code>, any sub paths in <code>src/pages/app</code> will be exempt from Gatsby static generation. To keep the dividing line between app and site crystal clear, I like to have all my dynamic Gatsby code in a dedicated <code>app</code> folder. This means you can use <code>@reach/router</code> with <code>react-netlify-identity-widget</code> to write a standard dynamic React app with private, authenticated routes. Here's some sample code to give you an idea of how to hook them up:</li>
</ol>
<pre><code class="lang-jsx:title=src/app/app.js">// src/app/app.js
import React from "react"
import { Router } from "@reach/router"
import Layout from "../components/layout"
import NavBar from "./components/NavBar"
import Profile from "./profile"
import Main from "./main"
import Login from "./login"
import { useIdentityContext } from "react-netlify-identity-widget"
import { navigate } from "gatsby"

function PrivateRoute(props) {
  const { isLoggedIn } = useIdentityContext()
  const { component: Component, location, ...rest } = props

  React.useEffect(
    () =&gt; {
      if (!isLoggedIn &amp;&amp; location.pathname !== `/app/login`) {
        // If the user is not logged in, redirect to the login page.
        navigate(`/app/login`)
      }
    },
    [isLoggedIn, location]
  )
  return isLoggedIn ? &lt;Component {...rest} /&gt; : null
}
function PublicRoute(props) {
  return &lt;div&gt;{props.children}&lt;/div&gt;
}

export default function App() {
  return (
    &lt;Layout&gt;
      &lt;NavBar /&gt;
      &lt;Router&gt;
        &lt;PrivateRoute path="/app/profile" component={Profile} /&gt;
        &lt;PublicRoute path="/app"&gt;
          &lt;PrivateRoute path="/" component={Main} /&gt;
          &lt;Login path="/login" /&gt;
        &lt;/PublicRoute&gt;
      &lt;/Router&gt;
    &lt;/Layout&gt;
  )
}
</code></pre>
<p>Phew that was a lot! but you should have a solid starting point for your app now :)</p>
<h2 id="heading-bonus-points-authenticated-netlify-functions">Bonus points: Authenticated Netlify Functions ?</h2>
<p>Just like <a target="_blank" href="<https://en.wikipedia.org/wiki/The_Prestige_(film)>">every magic act has a pledge, a turn, and a prestige</a>, I have one last tidbit for you. <a target="_blank" href="https://stackoverflow.com/questions/50277192/react-security-concerns-restricted-pages-in-app">Nothing on the client-side is safe</a>. Although you can send along Netlify Identity user ID's to your Netlify Function endpoints for authenticated access from your Gatsby App (for example in the body of a POST request), you'll never be truly sure if that flow is secure either from malicious users or snooping.</p>
<p>The best way to do authenticated actions inside serverless functions is to do it from <strong>inside</strong> the context of the function itself. Fortunately, <a target="_blank" href="https://www.netlify.com/docs/functions/?utm_source=blog&amp;utm_medium=freecodecamp&amp;utm_campaign=devex#identity-and-functions">Netlify Identity and Functions work seamlessly together</a>. All you have to do is to send along the user's <a target="_blank" href="https://jwt.io/">JWT</a> when hitting your endpoint:</p>
<pre><code class="lang-js"><span class="hljs-comment">// in your gatsby app</span>
<span class="hljs-keyword">const</span> { user } = useIdentityContext()
<span class="hljs-comment">// in an event handler</span>
fetch(<span class="hljs-string">"/.netlify/functions/auth-hello"</span>, {
  <span class="hljs-attr">headers</span>: {
    <span class="hljs-attr">Accept</span>: <span class="hljs-string">"application/json"</span>,
    <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>,
    <span class="hljs-attr">Authorization</span>: <span class="hljs-string">"Bearer "</span> + user.token.access_token, <span class="hljs-comment">// like this</span>
  },
}).then(<span class="hljs-comment">/* etc */</span>)
</code></pre>
<p>If even this is too much boilerplate, you can even use the fetch wrapper that ships with the <code>identity</code> object:</p>
<pre><code class="lang-js"><span class="hljs-comment">// in your gatsby app</span>
<span class="hljs-keyword">const</span> { authedFetch } = useIdentityContext()
<span class="hljs-comment">// in an event handler</span>
authedFetch(<span class="hljs-string">"/.netlify/functions/auth-hello"</span>).then(<span class="hljs-comment">/* etc */</span>)
</code></pre>
<p>And then inside your Netlify function, you can now check the <code>user</code> object or pass it on to your end API or database:</p>
<pre><code class="lang-js"><span class="hljs-built_in">module</span>.exports = { handler }
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handler</span>(<span class="hljs-params">event, context</span>) </span>{
  <span class="hljs-keyword">if</span> (context.clientContext) {
    <span class="hljs-keyword">const</span> { user } = context.clientContext
    <span class="hljs-comment">// you can get actual user metadata you can use!</span>
    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">statusCode</span>: <span class="hljs-number">200</span>,
      <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
        <span class="hljs-attr">msg</span>: <span class="hljs-string">"super secret info only available to authenticated users"</span>,
        user,
      })
    }
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">statusCode</span>: <span class="hljs-number">401</span>,
      <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
        <span class="hljs-attr">msg</span>:
          <span class="hljs-string">"Error: No authentication detected! Note that netlify-lambda doesn't locally emulate Netlify Identity."</span>,
      }),
    }
  }
}
</code></pre>
<h2 id="heading-gatsby-netlify-perfect-for-your-next-hackathon">Gatsby + Netlify - Perfect for your next Hackathon</h2>
<p>As you can see, it's a few steps to turn your static Gatsby sites into dynamic, authenticated, fully serverless apps with Netlify's free tools. This makes Gatsby a perfect tool for your next app. If you're at a hackathon, short on time, or just like to see a full working demo, check any of the following links.</p>
<ul>
<li><strong>Code:</strong> https://github.com/sw-yx/jamstack-hackathon-starter</li>
<li><strong>Starter:</strong> https://www.gatsbyjs.org/starters/jamstack-hackathon-starter</li>
<li><strong>Live Demo:</strong> https://jamstack-hackathon-starter.netlify.com/</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Handle Static Forms - The Client-side Way ]]>
                </title>
                <description>
                    <![CDATA[ Forms are interactive elements used to get input from the user for further processing. Most times, forms are just used to receive input that requires no processing but rather just receiving data, this might be a contact form, RSVP, get a quote e.t.c ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/handling-static-forms-the-client-side-way/</link>
                <guid isPermaLink="false">66d84e16ef84e4cc27cfbe27</guid>
                
                    <category>
                        <![CDATA[ forms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JAMstack ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Bolaji Ayodeji ]]>
                </dc:creator>
                <pubDate>Sun, 21 Jul 2019 20:58:47 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/07/1_NjU8ApeQC0wK4NgIaOjALw.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Forms are interactive elements used to get input from the user for further processing. Most times, forms are just used to receive input that requires no processing but rather just receiving data, this might be a contact form, RSVP, get a quote e.t.c</p>
<p>Traditionally, forms are managed with the help of a server (also known as server side), but this is more efficient when you’re processing the data from the form, maybe a user registration form where the form data is validated, authenticated and saved in a database.</p>
<p>When you’re building a simple form where you’re only receiving data from the user and not processing (i.e contact form) the goal is to get the data from the form and send to your company support email (e.g info@…, support@…)</p>
<p>Using a server here is not ideal and is only an overkill, a very common way of doing this is via <a target="_blank" href="https://github.com/PHPMailer/PHPMailer">PHPMailer</a> ( The classic email sending library for PHP). PHPMailer is used with PHP and requires a lot of boring server configurations. What if you’re just building a static site? There should be an easier way of doing this client side right?</p>
<p>In this article, I’ll introduce you to two methods of handling form data client side in static sites. There are other methods but I’ve used these two and considered them to be the best and easiest (no hard feelings :) ).</p>
<p>NO hectic configurations, NO servers, NO serious stuff, just build your form, do some little tweaks, the user submits and bingo it heads straight to your designated email. :)</p>
<h3 id="heading-starter-form">STARTER FORM</h3>
<p>For the purpose of this article, I’ve built a basic form with HTML5 and Bootstrap 4, you can fork it from the <a target="_blank" href="https://codepen.io/iambolajiayo/pen/MdGdex">Codepen below.</a></p>
<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codepen.io/iambolajiayo/embed/MdGdex" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodePen embed" scrolling="no" allowtransparency="true" allowfullscreen="true" loading="lazy"></iframe></div>
<p> </p>
<p>Currently, this form uses none of the methods we’ll talk about, at the end of the article, I’ll provide the full <code>code</code> for both methods, you can then update the form and test. I’ve added a little validation, don’t worry about that</p>
<p>Now, let’s get started!!</p>
<h3 id="heading-method-one">METHOD ONE</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/image-12.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><a target="_blank" href="http://formspree.io/">Formspree</a> provides functional HTML forms via their platform with no PHP or JavaScript. Send your form to their URL and it’ll be forwarded to your email. No PHP, Javascript or sign up required — perfect for static sites!</p>
<p>Wait!, wait!!, wait!!! it’s <a target="_blank" href="https://github.com/formspree/formspree">Open Sourced</a> too</p>
<h4 id="heading-form-handling-with-formspree">FORM HANDLING WITH FORMSPREE</h4>
<ul>
<li>Build your form, <a target="_blank" href="https://codepen.io/iambolajiayo/pen/MdGdex?editors=1010">we’ve done that already</a></li>
</ul>
<p>(Follow the next step and update this form to use this method)</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">action</span>=<span class="hljs-string">"https://formspree.io/you@email.com"</span> <span class="hljs-attr">method</span>=<span class="hljs-string">"POST"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"hidden"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"_subject"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"Bolaji's Form"</span>&gt;</span>                 
    <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"hidden"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"_next"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"/thanks.html"</span> &gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"name"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"_replyto"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"phone"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"Send"</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
</code></pre>
<p>Now let’s go over the new stuff added above.</p>
<ul>
<li><p>We changed the form’s action-attribute to <code>[https://formspree.io/you@email.com](https://formspree.io/you@email.com)</code> [replace <a target="_blank" href="mailto:your@email.com">your@email.com</a> with your own email.] This is simply sending your form data to formspree then to your email. Formspree is acting as a third party here.</p>
</li>
<li><p>I’ve added some name attributes to the input fields. This is just configuring each field so we can grab the data and send to formspree.</p>
</li>
</ul>
<p>— For Email address, I added a <strong>_replyto attribute</strong> (This just mean, you’ll be able to quickly reply to the user who originally submitted via email)</p>
<p>— I’ve added a <strong>_subject</strong> attribute. This value is used for the email’s subject so that you can quickly reply to submissions without having to edit the subject line each time.</p>
<p>— I’ve added a <strong>_next</strong> attribute. By default, after submitting a form the user is shown the Formspree “Thank You” page. You can provide an alternative URL for that page like so: <code>&lt;input type=”hidden” name=”_next” value=”/thanks.html" /&gt;</code></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*M2O2tR08URl1I2i5bVGU5Q.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/09/1_M2O2tR08URl1I2i5bVGU5Q.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>formspree default success page</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/09/1_nLA5m3_yjx4mmmJAmuu8Yg.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>custom success page I built for a client.</em></p>
<ul>
<li>We added a value attribute to the send button [<strong>value=”Send”</strong>]</li>
</ul>
<p>This is our Thanos, one snap at this button and your form is erased and its data sent to your email.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/09/1_hnEhoz4pSb4pNtzXD0pDpw.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>That’s all to using formspree :) Although there are other configuration settings for several other features, you can check <a target="_blank" href="https://formspree.io/">here</a>.</p>
<h4 id="heading-things-to-note">THINGS TO NOTE!</h4>
<ul>
<li><p>You don’t need to signup to use formspree, just add your action attribute and you’re good to go. You only signup if you want a <a target="_blank" href="https://formspree.io/plans">Paid plan</a>.</p>
</li>
<li><p>Make sure your form has the <code>method=”POST”</code> attribute</p>
</li>
<li><p>Formspree uses reCAPTCHA to identify spam submissions. After a user clicks our <em>Thanos</em>, they’ll have to do some CAPTCHA verification. Cool way of stopping spam submissions.</p>
</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/09/1_0mq3GFJ4_fRWnR5_vX1L5g.png" alt="Image" width="600" height="400" loading="lazy"></p>
<ul>
<li><p>After that, the form is sent to your designated email and the custom success page is displayed!</p>
</li>
<li><p>Formspree does not read your form data, they have no access to it, they’re just a delivery service, you send your parcel sealed to them, they deliver to your customer, cool right? :)</p>
</li>
<li><p>Formspree is free for 50 submissions per form per month ONLY! Need more, you can upgrade to the <a target="_blank" href="https://formspree.io/plans">Paid plan</a>.</p>
</li>
<li><p>Formspree has both Free and Paid plans. Paid plans have several other features like admin dashboard, unlimited submissions, AJAX handling e.t.c Paid plans and their features can be found <a target="_blank" href="https://formspree.io/plans">here</a></p>
</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/09/1_UZwPE17ZnWZym5qaDkYIwA.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>If you’re building a basic site, you shouldn’t worry about Paid plans, Paid plans are mostly needed by Enterprise applications and companies, the Free plan would cover all your needs. I use this for some client projects too :)</p>
<ul>
<li>Formspree premium users can submit forms via AJAX. Just set the Accept header to application/json. If you’re using jQuery this can be done like so:</li>
</ul>
<pre><code class="lang-js">    $.ajax({
        <span class="hljs-attr">url</span>: <span class="hljs-string">"https://formspree.io/FORM_ID"</span>,
        <span class="hljs-attr">method</span>: <span class="hljs-string">"POST"</span>,
        <span class="hljs-attr">data</span>: {<span class="hljs-attr">message</span>: <span class="hljs-string">"hello!"</span>},
        <span class="hljs-attr">dataType</span>: <span class="hljs-string">"json"</span>
    });
</code></pre>
<p>Well, this is for paid users :)</p>
<p>If you don’t use jQUERY like me and you’re tired of the lengthy AJAX default syntax, check out <a target="_blank" href="https://github.com/BolajiAyodeji/simple-ajax-library">simpleAJAX library</a>, a simple library I built for handling HTTP requests. Like so:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> http = <span class="hljs-keyword">new</span> simpleAJAX;

<span class="hljs-keyword">const</span> data = {
    <span class="hljs-string">"name"</span>: <span class="hljs-string">"Bolaji Ayodeji"</span>,
    <span class="hljs-string">"email"</span>: <span class="hljs-string">"hi@bolajiayodeji.com"</span>,
    <span class="hljs-string">"message"</span>: <span class="hljs-string">"hi"</span>
};
http.post(<span class="hljs-string">'https://formspree.io/FORM_ID'</span>, data,
<span class="hljs-function">(<span class="hljs-params">err, user</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span>(err) {
     <span class="hljs-built_in">console</span>.log(err)
    } <span class="hljs-keyword">else</span> {
     <span class="hljs-built_in">console</span>.log(user);
   }
 });
</code></pre>
<p>A star would make me happy! :)</p>
<p>If you're into React, <a target="_blank" href="https://zeit.co/">ZEIT</a> has a comprehensive guide on using Formspree with <a target="_blank" href="https://zeit.co/guides/deploying-react-forms-using-formspree-with-zeit-now">Create React App</a>, complete with deployment instructions. Highly recommended!</p>
<h3 id="heading-method-two">METHOD TWO</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/image-13.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><a target="_blank" href="https://www.netlify.com/">Netlify</a> offers form handling for sites deployed on their platform.</p>
<h4 id="heading-form-handling-with-netlify">FORM HANDLING WITH NETLIFY</h4>
<ul>
<li>Create an account on Netlify and deploy your site there.</li>
</ul>
<p>Please watch this 14min video by <a target="_blank" href="https://twitter.com/jamesqquick">@JamesQuick</a> below if you don’t know what Netlify is. Learn about all of the awesome features in Netlify like Continuous Deployment, Lambda Functions, Split Testing, Preview Branches, and more!</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/qAUX2A-W4Bc" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<ul>
<li>Now that you have deployed your site, let’s create the form again</li>
</ul>
<pre><code class="lang-html">    <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">action</span>=<span class="hljs-string">"/thanks.html"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"Bolaji's form"</span> <span class="hljs-attr">method</span>=<span class="hljs-string">"POST"</span> <span class="hljs-attr">data-netlify</span>=<span class="hljs-string">"true"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"name"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"phone"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
</code></pre>
<p>Now let’s go over the new stuff I added above.</p>
<ul>
<li><p>Netlify is quite easier, you simply add the <code>netlify</code> attribute <code>data-netlify="true"</code>to the <code>&lt;form&gt;</code> tag, and you can start receiving submissions in your Netlify site admin panel.</p>
</li>
<li><p>Here, the <code>action</code> attribute serves as your custom success page</p>
</li>
</ul>
<p>That’s all, your form submissions goes straight to your Netlify admin panel</p>
<p>Settings &gt; Build &amp; deploy &gt; Environment &gt; Environment variables</p>
<p>(Watch the video above if you don’t understand what the panel means)</p>
<p><strong>Things to note!</strong></p>
<ul>
<li><p>Your site must be hosted on netlify to use this method</p>
</li>
<li><p>You must add the netlify attribute for the form to work</p>
</li>
<li><p>You can find all submissions to your Netlify forms in the Forms tab of your site dashboard. <strong>Settings &gt; Forms</strong></p>
</li>
<li><p>Netlify has free and paid plans too</p>
</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/09/1__sg2Fo1r5gniCilQjBcMhA.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><a target="_blank" href="https://www.netlify.com/pricing/#features"><em>https://www.netlify.com/pricing</em></a></p>
<ul>
<li><p>Netlify has several built-in notification options for verified form submissions, including email and Slack notifications. <strong>(Only available in Paid plans)</strong>. You can find them in <strong>Settings &gt; Forms &gt; Form notifications</strong>.</p>
</li>
<li><p>Netlify also integrates with <a target="_blank" href="https://zapier.com/app/dashboard">Zapier</a>, so you can set up triggers that send your verified form submissions to any of the 500+ applications in their catalogue.</p>
</li>
<li><p>All notification emails are sent from <code>team@netlify.com</code>, and any replies to a notification will go to that address. If you would like to respond to a form submitter, you will need to enter their address manually.</p>
</li>
<li><p>Netlify Forms can receive files uploads via form submissions too :).</p>
</li>
</ul>
<p>To do this, add an input with <code>type="file"</code> to any form. When a form is submitted, a link to each uploaded file will be included in the form submission details.</p>
<ul>
<li>Netlify is limited to 100 submissions per month and 10MB uploads per month for the FREE plan, If you want more, you’ll need to upgrade</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/09/1_XaWaJi_I6eQq06_ogPEHUg.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>form submissions in the admin panel</em></p>
<p>And that’s all!!</p>
<h3 id="heading-final-html-form-code">FINAL HTML FORM CODE</h3>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!--formspree.html--&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">action</span>=<span class="hljs-string">"https://formspree.io/you@email.com"</span> <span class="hljs-attr">method</span>=<span class="hljs-string">"POST"</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"hidden"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"_subject"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"Bolaji's Form"</span>&gt;</span>                 
   <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"hidden"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"_next"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"/thanks.html"</span> &gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-group"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Name:<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"name"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Name"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"invalid-feedback"</span>&gt;</span>
         Name must be between 2 and 20 characters
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
   <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-group"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Email:<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Email address"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"invalid-feedback"</span>&gt;</span>
         Enter a valid email address
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
   <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-group"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Telephone:<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"phone"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Phone number"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"invalid-feedback"</span>&gt;</span>
         Enter a valid number
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
   <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"Send"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-info btn-block"</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
</code></pre>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!--netlify.html--&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">action</span>=<span class="hljs-string">"/thanks.html"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"Bolaji's form"</span> <span class="hljs-attr">method</span>=<span class="hljs-string">"POST"</span> <span class="hljs-attr">data-netlify</span>=<span class="hljs-string">"true"</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-group"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Name:<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"name"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Name"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"invalid-feedback"</span>&gt;</span>
         Name must be between 2 and 20 characters
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
   <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-group"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Email:<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Email address"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"invalid-feedback"</span>&gt;</span>
         Enter a valid email address
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
   <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-group"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Telephone:<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"phone"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Phone number"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"invalid-feedback"</span>&gt;</span>
         Enter a valid number
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
   <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"Send"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-info btn-block"</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
</code></pre>
<h3 id="heading-conclusion">CONCLUSION</h3>
<p>One thing to note about formspree is that the free version leaves your email address exposed to scrapers and bots so you might want to set up a temporary disposable email address while you use it. If you want to hide your email address by default, you’ll need to upgrade your plan.</p>
<p>Do you want extra practice? Watch this tutorial video below by <a target="_blank" href="https://medium.com/u/861216ad5921">Brad Traversy</a> and learn how to add a contact or any type of form to your website by using the Netlify form feature including file uploads and spam filtering. [Full guide + practical code]</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/6ElQ689HRcY" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<h3 id="heading-useful-links">Useful Links</h3>
<ul>
<li><p><a target="_blank" href="https://hashnode.com/util/redirect?url=https://www.netlify.com/docs/form-handling/">netlify.com/docs/form-handling</a></p>
</li>
<li><p><a target="_blank" href="https://hashnode.com/util/redirect?url=https://forestry.io/blog/5-ways-to-handle-forms-on-your-static-site/">forestry.io/blog/5-ways-to-handle-forms-on-..</a></p>
</li>
<li><p><a target="_blank" href="https://hashnode.com/util/redirect?url=https://gridsome.org/docs/guide-forms/">gridsome.org/docs/guide-forms</a></p>
</li>
<li><p><a target="_blank" href="https://hashnode.com/util/redirect?url=https://zeit.co/guides/deploying-react-forms-using-formspree-with-zeit-now">zeit.co/guides/deploying-react-forms-using-..</a></p>
</li>
<li><p><a target="_blank" href="https://hashnode.com/util/redirect?url=https://zeit.co/guides/deploying-statickit-with-zeit-now">zeit.co/guides/deploying-statickit-with-zei..</a></p>
</li>
</ul>
<p>Thanks for reading!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ An introduction to the JAMstack: the architecture of the modern web ]]>
                </title>
                <description>
                    <![CDATA[ I’m sure you’ve come across the word JAMstack before but you might not have understood what it really meant. I’ve seen this word before also but didn’t care to check it out until Egwuenu Gift organized JAMstack Lagos. I then realized that I’ve been b... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/an-introduction-to-the-jamstack-the-architecture-of-the-modern-web-c4a0d128d9ca/</link>
                <guid isPermaLink="false">66d84e07ef84e4cc27cfbe23</guid>
                
                    <category>
                        <![CDATA[ api ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JAMstack ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Bolaji Ayodeji ]]>
                </dc:creator>
                <pubDate>Fri, 17 May 2019 14:59:56 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*xYSNCnp6eh2ZDpwQtYL6qg.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>I’m sure you’ve come across the word JAMstack before but you might not have understood what it really meant. I’ve seen this word before also but didn’t care to check it out until <a target="_blank" href="https://www.freecodecamp.org/news/an-introduction-to-the-jamstack-the-architecture-of-the-modern-web-c4a0d128d9ca/undefined">Egwuenu Gift</a> organized <a target="_blank" href="https://twitter.com/jamstacklagos">JAMstack Lagos</a>. I then realized that I’ve been building JAMstack applications already.</p>
<p>JAMstack is a modern web development architecture. It is not a programming language or any form of tool. It is more of a web development practice aimed towards enforcing better performance, higher security, lower cost of scaling, and better developer experience.</p>
<p>In this article, I’ll introduce you to what JAMstack means, why you should care, best practices, and how to get started. ?</p>
<h3 id="heading-introduction">Introduction</h3>
<p><img src="https://cdn-media-1.freecodecamp.org/images/oE3wYE3Ygr1SlH2dTXkM5lXW-DyHPlmMrQww" alt="Image" width="800" height="375" loading="lazy"></p>
<p>According to the official <a target="_blank" href="https://jamstack.org/">JAMstack documentation</a>,</p>
<blockquote>
<p>JAMstack is a Modern web development architecture based on client-side JavaScript, reusable APIs, and prebuilt Markup.</p>
<p>When we talk about “The Stack,” we no longer talk about operating systems, specific web servers, backend programming languages, or databases.</p>
<p>The JAMstack is not about specific technologies. It’s a new way of building websites and apps that delivers better performance, higher security, lower cost of scaling, and a better developer experience.</p>
</blockquote>
<p><strong>JAMstack</strong> is a major trend in web development coined by <a target="_blank" href="https://twitter.com/biilmann">Mathias Biilman</a>, the CEO and co-founder of Netlify.</p>
<h3 id="heading-okay-chill-what-is-jamstack">Okay, chill! What is JAMstack?</h3>
<p>You might have come across specific terms like <strong>MEAN stack</strong> and <strong>MERN stack.</strong> These are just terms used to classify or group some certain technologies with the aim of achieving a particular goal.</p>
<p>JAMstack here stands for</p>
<p><strong>J</strong>avaScript</p>
<p><strong>A</strong>PI</p>
<p><strong>M</strong>arkup</p>
<blockquote>
<p>Stacks generally are just a combination of several technologies used to create a web or mobile application. So JAMstack is the combination of JavaScript, APIs and Markup. Pretty interesting right?</p>
</blockquote>
<p>JAMstack projects don’t rely on server-side code — they can be distributed instead of relying on a server. Served directly from a CDN, JAMstack apps unlock speed, performance and better the user experience.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/x0eO1iqvIRKPNsEtSkFvRuLu6CbSmo7OhcFH" alt="Image" width="800" height="390" loading="lazy"></p>
<h3 id="heading-useful-terms">Useful Terms</h3>
<p>I’ll be using these terms in this article frequently and I thought you should know their meanings (if you don’t already):</p>
<ul>
<li><p><strong>API</strong> is the acronym for Application Programming Interface, which is a software intermediary that allows two applications to talk to each other.</p>
</li>
<li><p><strong>CDN</strong> (content delivery network) is a system of distributed servers (network) that deliver pages and other Web content to a user, based on the geographic locations of the user, the origin of the webpage and the content delivery server.</p>
</li>
<li><p>A <strong>Server</strong> is a computer designed to process requests and deliver data to another computer over the internet or a local network.</p>
</li>
<li><p>A <strong>Database</strong> is a collection of information that is organized so that it can be easily accessed, managed, and updated</p>
</li>
</ul>
<h3 id="heading-why-jamstack">Why JAMstack?</h3>
<p><img src="https://cdn-media-1.freecodecamp.org/images/uHGkEXe8lXJsmj6cZNQmIW3bpsEzn0mU9Eun" alt="Image" width="800" height="546" loading="lazy"></p>
<p>Traditional websites or CMS sites (e.g WordPress, Drupal, etc.) rely heavily on servers, plugins and databases. But the JAMstack can load some JavaScript that receives data from an API, serving files from a CDN and markup generated using a static site generator during deploy time.</p>
<p>Sounds cool right?!</p>
<h4 id="heading-jamstack-is-fast">JAMstack is fast</h4>
<p>When it comes to minimizing the time of load, nothing beats pre-built files served over a CDN. JAMstack sites are super fast because the HTML is already generated during deploy time and just served via <a target="_blank" href="https://flaviocopes.com/cdn/">CDN</a> without any interference or backend delays.</p>
<h4 id="heading-jamstack-is-highly-secured">JAMstack is highly secured</h4>
<p>Everything works via an API and hence there are no database or security breaches. With server-side processes abstracted into micro service APIs, surface areas for attacks are reduced and so your site becomes highly secured.</p>
<h4 id="heading-jamstack-is-cheaper-and-easier-to-scale">JAMstack is cheaper and easier to scale</h4>
<p>JAMstack sites only contain just a few files with minimal sizes that can be served anywhere. Scaling is a matter of serving those files somewhere else or via CDNs.</p>
<h3 id="heading-jamstack-best-practices">JAMstack Best Practices</h3>
<ul>
<li><p>Use CDN to distribute your files rather than servers</p>
</li>
<li><p>Installing and contributing to your project should be easy and less complex. Use tools like npm and Git to ensure standard and faster setup.</p>
</li>
<li><p>Use build tools and make your project compatible for all browsers (e.g Babel, Browserify, Webpack, etc.)</p>
</li>
<li><p>Ensure your project is up to web standards and highly accessible</p>
</li>
<li><p>Ensure your build process is automated to reduce stress.</p>
</li>
<li><p>Make your deployment process automatic, you can use platforms like <a target="_blank" href="https://netlify.com">Netlify</a> to do this</p>
</li>
</ul>
<h3 id="heading-how-do-i-get-started">How do I Get Started?</h3>
<p>You can use some already built technologies to build JAMstack applications in a few minutes. Here are a few:</p>
<ul>
<li><p><a target="_blank" href="https://www.gatsbyjs.org/"><strong>Gatsby</strong></a><strong>:</strong> Gatsby is a free and open source framework based on React that helps developers build blazing fast <strong>websites and</strong> <strong>apps</strong></p>
</li>
<li><p><a target="_blank" href="https://nuxtjs.org/"><strong>NuxtJS</strong></a><strong>:</strong> NuxtJS is the Vue.js Framework for Universal applications, static generated applications, single page applications, progressive web apps and desktop apps</p>
</li>
<li><p><a target="_blank" href="http://gohugo.io"><strong>Hugo</strong></a><strong>:</strong> Hugo is the world’s fastest framework for building websites. It is one of the most popular open-source static site generators. With its amazing speed and flexibility, Hugo makes building websites fun again.</p>
</li>
<li><p><a target="_blank" href="https://www.netlifycms.org/"><strong>Netlify CMS</strong></a><strong>:</strong> Netlify CMS is an open source content management for your Git workflow which can be used with any static site generator for a faster and more flexible web project</p>
</li>
<li><p><a target="_blank" href="https://www.contentful.com"><strong>Contentful</strong></a><strong>:</strong> Contentful is a smarter and seamless content management system which provides editors and developers with a unified content thereby enhancing collaboration and ensuring digital products ship to the market faster.</p>
</li>
<li><p><a target="_blank" href="https://svelte.dev/"><strong>Svelte</strong></a><strong>:</strong> Svelte is a radical new approach to building user interfaces. Whereas traditional frameworks like React and Vue do the bulk of their work in the <em>browser</em>, Svelte shifts that work into a <em>compile step</em> that happens when you build your app.</p>
</li>
</ul>
<p><a target="_blank" href="https://www.staticgen.com/"><strong><em>and many more. . .</em></strong></a></p>
<h3 id="heading-useful-resources">Useful Resources</h3>
<ul>
<li><p><a target="_blank" href="https://jamstack.wtf/"><strong>JAMstack WTF</strong></a></p>
</li>
<li><p><a target="_blank" href="https://cosmicjs.com/blog/how-to-build-a-jamstack-website"><strong>How to Build a JAMstack Website</strong></a></p>
</li>
<li><p><a target="_blank" href="https://www.giftegwuenu.com/what-is-ja-mstack-and-why-you-should-try-it"><strong>What is JAMstack and why you should try it</strong></a></p>
</li>
<li><p><a target="_blank" href="https://www.contentful.com/r/knowledgebase/jamstack-cms/"><strong>A JAMstack-ready CMS</strong></a></p>
</li>
<li><p><a target="_blank" href="https://snipcart.com/blog/jamstack-clients-static-site-cms"><strong>JAMstack for Clients: On Benefits &amp; Static Site CMS</strong></a></p>
</li>
<li><p><a target="_blank" href="https://builtvisible.com/go-static-try-jamstack/"><strong>Go static: 5 reasons to try JAMstack on your next project</strong></a></p>
</li>
<li><p><a target="_blank" href="https://julian.is/article/static-websites-and-jamstack/"><strong>Static Websites + JAMstack = ❤</strong></a></p>
</li>
</ul>
<p>Find more resources <a target="_blank" href="https://jamstack.org/resources/">here</a></p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/uWTMEDEPw8c" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>JAMstack was invented as a way to put a nomenclature to the new way of building websites and apps that delivers better performance, higher security, lower cost of scaling, and a better developer experience.</p>
<p>JAMstack is not about specific technologies, it is a modern web development architecture based on client-side JavaScript, reusable APIs, and prebuilt Markup.</p>
<p>Join the <a target="_blank" href="https://jamstack.org/community/">JAMstack community</a> to learn more and get more updates.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/BoR0w2G9fjZDSJDFTlZoGE4gK810ODcs8vz3" alt="Image" width="800" height="533" loading="lazy"></p>
<blockquote>
<p>PS: This article was first published on my blog <a target="_blank" href="https://bolajiayodeji.com/an-introduction-to-the-jamstack-the-architecture-of-the-modern-web-c4a0d128d9ca">here</a></p>
</blockquote>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
