<?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[ Svelte - 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[ Svelte - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Mon, 25 May 2026 10:49:16 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/svelte/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Data Visualization Tools for Svelte Developers
 ]]>
                </title>
                <description>
                    <![CDATA[ Svelte is a front-end framework for building fast and interactive web applications. Unlike many other well-known frameworks, it doesn’t use a virtual DOM. Instead, it turns your code into efficient Ja ]]>
                </description>
                <link>https://www.freecodecamp.org/news/data-visualization-tools-for-svelte-developers/</link>
                <guid isPermaLink="false">69dd2445217f5dfcbd1e423d</guid>
                
                    <category>
                        <![CDATA[ data visualization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Svelte ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Daria Filozop ]]>
                </dc:creator>
                <pubDate>Mon, 13 Apr 2026 17:13:41 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/cd0a2c05-0604-46d2-a9c0-b914a187d492.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Svelte is a front-end framework for building fast and interactive web applications.</p>
<p>Unlike many other well-known frameworks, it doesn’t use a virtual DOM. Instead, it turns your code into efficient JavaScript during the build step, which makes apps smaller and faster. It also makes things reactive in a simple way, so it’s easier to manage data and keep your code clean.</p>
<p>Recently, the buzz around Svelte caught my attention. I wanted to understand what all the hype was about.</p>
<p>After polling <a href="https://www.reddit.com/r/webdevelopment/comments/1lpq27w/any_thoughts_about_svelte/?share_id=uMO0hMk04m4PJz8yk6lgf&amp;utm_content=2&amp;utm_medium=ios_app&amp;utm_name=ioscss&amp;utm_source=share&amp;utm_term=1">the Reddit community</a> for their opinions, their strong recommendations persuaded me to dive in and try it myself.</p>
<p>So, I did some more research to learn more about its distinctive features, and now I want to share this info with you here.</p>
<h2 id="heading-what-well-cover">What We’ll Cover:</h2>
<ul>
<li><p><a href="#heading-1-why-svelte-stands-out">1. Why Svelte Stands Out</a></p>
</li>
<li><p><a href="#heading-2-charts">2. Charts</a></p>
<ul>
<li><p><a href="#heading-layer-cake">Layer Cake</a></p>
</li>
<li><p><a href="#heading-fusioncharts">FusionCharts</a></p>
</li>
<li><p><a href="#heading-highcharts">Highcharts</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-3-pivot-tables">3. Pivot Tables</a></p>
<ul>
<li><a href="#heading-flexmonster">Flexmonster</a></li>
</ul>
</li>
<li><p><a href="#heading-4-grids">4. Grids</a></p>
<ul>
<li><a href="#heading-svar">SVAR</a></li>
</ul>
</li>
<li><p><a href="#heading-5-wrapping-up">5. Wrapping Up</a></p>
</li>
</ul>
<h2 id="heading-why-svelte-stands-out"><strong>Why Svelte Stands Out</strong></h2>
<p>One of Svelte's key features is that it has no virtual DOM and compiles your code during the build process. This makes your apps built with Svelte much faster compared to those built with other frameworks.</p>
<p>Svelte also makes apps reactive in a simple way by declaring variables. The code stays clean and easy to read, with scoped styles that don’t mix into other parts of the app.</p>
<p>It also has built-in animations and transitions, plus an easy store system for sharing state between components.</p>
<p>Beyond all this, Svelte focuses on accessibility, supports TypeScript, and delivers excellent performance thanks to its compile-time approach.</p>
<p>I think this <a href="https://github.com/sveltejs/svelte/discussions/10085">quote from Svelte creator Rich Harris</a> perfectly sums up his reason for creating this framework:</p>
<blockquote>
<p><em>“We're not trying to be the most popular framework; we're trying to be the best framework. Sometimes that means making choices that we believe in but that go against the grain of web development trends.”</em></p>
</blockquote>
<p>It seems like many developers admire this approach. According to the <a href="https://survey.stackoverflow.co/2025/technology#admired-and-desired">2025 StackOverflow Developer Survey</a>, Svelte is admired by 62.4% of respondents and desired by 11.1%. This suggests that it's catching up to more established frameworks like React, Angular, and Vue.</p>
<p>I've also noticed the continuous growth of the Svelte community. This expanding network provides strong support, with a variety of tools and libraries, and active channels on <a href="https://www.reddit.com/r/sveltejs/">Reddit</a> and <a href="https://discord.com/invite/svelte">Discord</a> where you can get advice from experienced developers.</p>
<p>My recent work on personal data visualization projects has shown me how powerful and enjoyable Svelte can be. But in my experience, there aren't yet many tools for working with Svelte. So to help my fellow developers, I’ve decided to share my experiences and recommend my 5 favorite data visualization tools that smoothly integrate with Svelte and work perfectly with it.</p>
<p>For convenience, I’ve divided them into three categories: Charts, Pivot Tables, and Grids. So, if you want to find something specific, you can go to the appropriate section.</p>
<h2 id="heading-charts"><strong>Charts</strong></h2>
<p>You use charts when you need to explain data clearly and visually, such as showing trends over time, comparing groups, or quickly highlighting key differences.</p>
<p>Here are some charting tools that integreat well with Svelte:</p>
<h3 id="heading-1-layer-cake"><strong>1.</strong> <a href="https://layercake.graphics/"><strong>Layer Cake</strong></a></h3>
<p>Layer Cake is an open-source graphics framework for Svelte that allows you to create a wide variety of charts, from columns to a multilayer map. On Reddit, the creator of LayerCake <a href="https://www.reddit.com/r/sveltejs/comments/194dfrg/comment/khhal06/">shares some insights</a> about his project:</p>
<blockquote>
<p><em>“It’s designed to give you the basic elements you need to make a responsive chart (D3 scales, SVG, canvas, etc) and lets you customize the rest in user-land.”</em></p>
</blockquote>
<p>The nice thing is that the creator actively responds to feedback, which helps make the product better.</p>
<p>LayerCake suggests using five types of components:</p>
<ul>
<li><p><a href="https://layercake.graphics/components#axis">Axis</a></p>
</li>
<li><p><a href="https://layercake.graphics/components#chart">Chart</a></p>
</li>
<li><p><a href="https://layercake.graphics/components#map">Map</a></p>
</li>
<li><p><a href="https://layercake.graphics/components#interaction">Interaction</a></p>
</li>
<li><p><a href="https://layercake.graphics/components#annotation">Annotation</a></p>
</li>
</ul>
<p>Also, <a href="https://github.com/mhkeller/layercake">with over 1.5k stars on GitHub</a>, the project is actively maintained and can be easily installed via npm.</p>
<p>Layer Cake is a good option when you need to build something unique rather than use pre-built chart templates.</p>
<p>License: MIT</p>
<h3 id="heading-2-fusioncharts"><strong>2.</strong> <a href="https://www.fusioncharts.com/svelte-charts?framework=svelte"><strong>FusionCharts</strong></a></h3>
<p>FusionCharts is a JavaScript charting library that suggests over 100 interactive charts and around 2,000 data-driven maps. It offers a special Svelte component called <a href="https://github.com/fusioncharts/svelte-fusioncharts">svelte-fusioncharts</a> that makes adding charts to apps simple.</p>
<p>FusionCharts is a commercial tool, but there's a trial version that you can use to try it out. You can also use it for free for non-commercial purposes (there will be a watermark).</p>
<p><a href="https://www.g2.com/products/fusioncharts/reviews">Based on user reviews on G2</a>, devs like FusionCharts for its extensive variety of chart types, its ability to handle large datasets quickly, and its easy implementation with strong customization options.</p>
<p>But they also report a decline in product support over the last few years, noting that fixing bugs can take a long time.</p>
<p>I really liked using their new <a href="https://www.fusioncharts.com/askfusiondev-ai">FusionDev AI</a> feature. It was super convenient to quickly get answers from the documentation and even some guidance on creating or customizing charts.</p>
<p>They work pretty well for business dashboards and enterprise apps that need a wide variety of ready-made charts and a quick setup (especially useful when working with large datasets).</p>
<p>License: Commercial</p>
<h3 id="heading-3-highcharts"><strong>3.</strong> <a href="https://www.highcharts.com/integrations/svelte/"><strong>Highcharts</strong></a></h3>
<p>Like FusionCharts, Highcharts is a commercial charting library that provides various chart types. <a href="https://www.g2.com/products/highcharts/reviews">Users highlight</a> its ease of use and effortless setup using simple code. It also has many customization options available.</p>
<p>While it may be pricier than some alternatives, many businesses find its advantages worthwhile: after all, 80 of the world's 100 largest companies use Highcharts. It's also a great option for non-commercial projects, which can use its free version.</p>
<p>Their wrapper <a href="https://github.com/highcharts/highcharts-svelte">@highcharts/svelte</a> lets you quickly integrate Highcharts into Svelte apps. It works with all their chart types and provides full customization.</p>
<p>Also, if you want an active community, Highcharts is a great option. They recently they created a <a href="https://discord.com/invite/xHxxcyyy6K">Discord server</a>, where you can share your projects or get inspiration for new ones.</p>
<p>Highcharts is a great choice for analytical platforms and financial dashboards. So if you need reliable, interactive charts with minimal effort, it's a perfect match.</p>
<p>License: Commercial</p>
<h2 id="heading-pivot-tables"><strong>Pivot Tables</strong></h2>
<p>You use pivot tables to quickly group and summarize big datasets. It lets you group data by categories, calculate totals or averages, and reorganize your information dynamically.</p>
<h3 id="heading-flexmonster"><a href="https://www.flexmonster.com/doc/integration-with-svelte/"><strong>Flexmonster</strong></a></h3>
<p>Flexmonster is a JavaScript pivot table library that allows you to quickly analyze and visualize data.</p>
<p>It's a commercial product, but it also has a full-featured trial version, plus they have a free entry license for dev purposes.</p>
<p><a href="https://www.g2.com/products/flexmonster-pivot-table-charts-component/reviews">From the reviews on G2</a> and <a href="https://www.capterra.com/p/138272/Flexmonster-Pivot-Table/">Capterra</a>, user feedback highlights a consistent trade-off: while the price is often cited as a con, the consensus is that its value justifies the cost. Users praise its speed, smooth integration with web apps, similarity to Excel, and ability to manage vast datasets without problems. People also cite the ability to create clear reports and exports.</p>
<p>As an enterprise solution, Flexmonster offers a wide range of options to customize reports entirely according to a project's specific needs. Also, the product is continuously updated, and customer support is one of its core strengths. Users consistently note that support is responsive, clear, and helpful, which ensures smooth adoption and reliable problem-solving.</p>
<p>Flexmonster now provides a wrapper for Svelte, which makes it easy to integrate pivot tables into Svelte apps without extra setup. They also provide a <a href="https://github.com/flexmonster/pivot-svelte">GitHub sample</a> that demonstrates many useful features. For example, it shows how to configure a pivot table, handle user interactions through events, work with Flexmonster's API, and much more. Altogether, it gives a clear picture of how to build a fully interactive reporting dashboard in a Svelte app.</p>
<p>By the way, <a href="https://youtu.be/rLJ5cyOVwl4?feature=shared">their video about integrating Flexmonster with Svelte</a> was the one I used, and it was very helpful.</p>
<p>Flexmonster also smoothly integrates with Highcharts and FusionCharts. You can find <a href="https://www.flexmonster.com/doc/available-tutorials-charts/">tutorials about these on their official webpage</a>.</p>
<p>Flexmonster is a great fit for a wide range of data-heavy applications. It’s a powerful engine for data visualization and analysis, and thanks to its flexibility and customization options, it can be easily integrated into almost any application, such as financial reporting, sales analysis, and audit systems.</p>
<p>License: Commercial</p>
<h2 id="heading-grids"><strong>Grids</strong></h2>
<p>A grid presents data in a structured table format, focusing on viewing, managing, and interacting with individual records.</p>
<h3 id="heading-svar"><a href="https://svar.dev/svelte/datagrid/"><strong>SVAR</strong></a></h3>
<p>SVAR is lightweight and compatible with Svelte's datagrid component, which helps you work quickly with big datasets.</p>
<p>It’s a relatively new tool, released in 2025, so there are fewer user reviews, but it seems to be growing in popularity. And for now, you can try it yourself because it’s completely free! It also covers all the key data viz use cases, like sorting, filtering, grouping, and editing data.</p>
<p>User support is one of SVAR’s strengths. The creators and community are active, and the <a href="https://forum.svar.dev/">SVAR Forum</a> offers reliable help whenever you need it.</p>
<p>So, it's a good option for apps that need to display and edit structured data, such as admin panels.</p>
<p>License: MIT</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>This was a small list of tools I recommend for data visualization while using Svelte. There are many more tools out there, but these stand out as stable, helpful, and easy to integrate. I hope that after reading this article, you’ve found the one that suits you the most.</p>
<p>Personally, these caught my attention because they're all pretty intuitive and provide powerful results. If you know other great tools, feel free to share your favorites with me!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Svelte i18n and Localization Made Easy ]]>
                </title>
                <description>
                    <![CDATA[ Apps are accessible worldwide. This means anyone from anywhere in the world can download your app.  So, if you want to cater to people everywhere, your app needs to support multiple languages.  Fortunately, Svelte is easy to work with, and it makes l... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/svelte-i18n-and-localization-made-easy/</link>
                <guid isPermaLink="false">6752020830d899211b5bda58</guid>
                
                    <category>
                        <![CDATA[ localization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Svelte ]]>
                    </category>
                
                    <category>
                        <![CDATA[ i18n ]]>
                    </category>
                
                    <category>
                        <![CDATA[ app development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ App Localization ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Alex Tray ]]>
                </dc:creator>
                <pubDate>Thu, 05 Dec 2024 19:42:00 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1733421094910/f2f91ab6-0717-4135-9f08-719f041471f6.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Apps are accessible worldwide. This means anyone from anywhere in the world can download your app. </p>
<p>So, if you want to cater to people everywhere, your app needs to support multiple languages. </p>
<p>Fortunately, Svelte is easy to work with, and it makes localization (l10n) and internationalization (i18n) quite straightforward. </p>
<p>But it lacks built-in i18n support—so you need to use a library like svelte-i18n or one of the others available. Let’s create a simple Svelte app to demonstrate how localization can be implemented. </p>
<p>We’ll create a welcome screen that can be used in both English and Spanish and then build some more advanced features.</p>
<dl>
<summary>Table of Contents</summary>
<ul>
<li>
  <a href="heading-what-makes-svelte-unique">What Makes Svelte Unique?</a></li>
  <li><a href="heading-how-to-localize-a-svelte-application">How to Localize a Svelte Application?</a></li>
  <li><a href="heading-adding-language-support">Adding Language Support</a></li>
  <li><a href="heading-updating-components-to-use-translations">Updating Components to Use Translations</a></li>
  <li><a href="heading-creating-a-language-switcher">Creating a Language Switcher</a></li>
  <li><a href="heading-adding-advanced-features">Adding Advanced Features</a></li>
<details>
  <li><a href="heading-formatting-numbers-and-currencies">Formatting Numbers and Currencies</a></li>
  <li><a href="heading-formatting-dates">Formatting Dates</a></li>
  <li><a href="heading-localizing-images">Localizing Images</a></li>
<details>
  <li><a href="heading-dynamic-image-paths">Dynamic Image Paths</a></li><li>
  </li><li><a href="heading-integrating-alternative-text-localization">Integrating Alternative Text Localization</a></li>
 <li><a href="heading-switching-svg-content-dynamically">Switching SVG Content Dynamically</a></li>
</details>
  <li><a href="heading-handling-multiple-forms-of-pluralization">Handling Multiple Forms of Pluralization</a></li>
  <li><a href="heading-handling-missing-translations">Handling Missing Translations</a></li>
</details>
  <li><a href="heading-making-your-app-production-ready">Making Your App Production-Ready</a></li>
 <li><a href="heading-best-practices-for-scaling-your-localization">Best Practices for Scaling Your Localization</a></li>
  <li><a href="heading-wrapping-up">Wrapping Up</a></li>
</ul>
</dl>

<h2 id="heading-what-makes-svelte-unique">What Makes Svelte Unique?</h2>
<p>Similar to <a target="_blank" href="https://centus.com/blog/vue-i18n">Vue i18n</a>, Svelte converts code to vanilla JS during the build process. This means your app ships with minimal code and offers excellent performance.</p>
<p>While other frameworks like React and Vue have longer startup times, Svelte’s compilation process changes that. It creates much smaller bundles, and apps run faster by default.</p>
<p>Svelte’s reactive syntax and lightweight nature make it an excellent choice for developers who want efficient, modern applications. </p>
<p>Its minimalism aligns well with the simplicity required in <a target="_blank" href="https://v2cloud.com/blog/best-programming-languages-for-cloud-computing"><strong>cloud development languages</strong></a>, ensuring that applications are lean, scalable, and optimized for cloud environments. </p>
<p>This minimalism also means you may not always have all the required built-in features. But pretty much all the limitations are resolved with the help of external libraries. </p>
<h2 id="heading-how-to-localize-a-svelte-application">How to Localize a Svelte Application</h2>
<p>Let’s jump right into creating a Svelte project now. I’ll create the project using the <code>npm create</code> command. Run the below commands one by one:</p>
<pre><code class="lang-javascript">npm create svelte@latest freecodecamp-localization-demo
cd freecodecamp-localization-demo
npm install
npm install svelte-i18n
</code></pre>
<p>The <code>npm create</code> command will prompt you with a few choices. Here’s what I’ve picked (but you can always adjust this based on your project requirements):</p>
<ul>
<li><p>Skeleton project: Select <strong>Yes</strong>.</p>
</li>
<li><p>Add TypeScript support: Select <strong>No</strong> (or Yes if you prefer TypeScript).</p>
</li>
<li><p>Add ESLint for code linting: Select <strong>Yes</strong>.</p>
</li>
<li><p>Add Prettier for code formatting: Select <strong>Yes</strong>.</p>
</li>
</ul>
<p>Now that we have our project set up, let's create a welcome component that we'll later enhance with translations. </p>
<p>Create a new file called Welcome.svelte in your src directory:</p>
<pre><code class="lang-javascript">&lt;!-- src/Welcome.svelte --&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">let</span> username;
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Welcome {username}!<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfcaW7fLzjbLa5ysYYu5FplhoGeVNmml9An_l0fcbEwQSxvg5mDbh3PY9b7etS6DESM7ZGdO_R5dqcYaDdgMaaQE2d7w1Q8eU4uAtIfKjHfm58buFwM-KLtJ_bv-x3XyqoYIOgfdQ?key=uXnvRGfJpBUiBb7CkgThtLro" alt="AD_4nXfcaW7fLzjbLa5ysYYu5FplhoGeVNmml9An_l0fcbEwQSxvg5mDbh3PY9b7etS6DESM7ZGdO_R5dqcYaDdgMaaQE2d7w1Q8eU4uAtIfKjHfm58buFwM-KLtJ_bv-x3XyqoYIOgfdQ?key=uXnvRGfJpBUiBb7CkgThtLro" width="1416" height="578" loading="lazy"></p>
<p>This component takes the username property (that I’ve passed from the App.svelte file) and displays a welcome message. </p>
<p>Simple enough for now, but what if your users speak different languages? Let’s add language support.</p>
<h2 id="heading-adding-language-support">Adding Language Support</h2>
<p>To do this, we need to create translation files for each language. Start by creating a new directory called <strong>locales</strong> in your <strong>src</strong> folder. Inside the <strong>locales</strong> folder, create two JSON files—<em>en.json</em> for English and <em>es.json</em> for Spanish.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// src/locales/en.json</span>
{
  <span class="hljs-string">"hello"</span>: <span class="hljs-string">"Hello {username}!"</span>,
  <span class="hljs-string">"buttons"</span>: {
    <span class="hljs-string">"save"</span>: <span class="hljs-string">"Save"</span>,
    <span class="hljs-string">"cancel"</span>: <span class="hljs-string">"Cancel"</span>
  }
}

<span class="hljs-comment">// src/locales/es.json  </span>
{
  <span class="hljs-string">"hello"</span>: <span class="hljs-string">"¡Hola {username}!"</span>,
  <span class="hljs-string">"buttons"</span>: {
    <span class="hljs-string">"save"</span>: <span class="hljs-string">"Guardar"</span>,
    <span class="hljs-string">"cancel"</span>: <span class="hljs-string">"Cancelar"</span>
  }
}
</code></pre>
<p>These files contain our translation strings.</p>
<p>Notice how we've organized them in a nested structure—this helps manage translations as your app grows. </p>
<p>The {username} and {count} placeholders will be replaced with actual values during runtime when we dynamically (or statically) pass the required values.</p>
<p>Next, we need to tell Svelte how to use these translations. For this, we need an <strong>i18n configuration</strong> file:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// src/i18n.js</span>
<span class="hljs-keyword">import</span> { register, init } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte-i18n'</span>;

register(<span class="hljs-string">'en'</span>, <span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'./locales/en.json'</span>));
register(<span class="hljs-string">'es'</span>, <span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'./locales/es.json'</span>));

init({
  <span class="hljs-attr">fallbackLocale</span>: <span class="hljs-string">'en'</span>,
  <span class="hljs-attr">initialLocale</span>: <span class="hljs-string">'en'</span>,
});
</code></pre>
<p>We’ve registered our translation files and set English as both the initial language and fallback language. The fallback language is used when a translation is missing in the selected language.</p>
<h2 id="heading-updating-components-to-use-translations">Updating Components to Use Translations</h2>
<p>Now we can update our welcome component to use the text from the JSON file:</p>
<pre><code class="lang-javascript">&lt;!-- src/Welcome.svelte --&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> {  } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte-i18n'</span>;
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">let</span> username;
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>{$('hello', { username })}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p>The <code>$_</code> function is a special helper from svelte-i18n that retrieves translated strings. </p>
<p>When we pass { username } as the second argument, it replaces the placeholder in our translation strings with the actual username.</p>
<h2 id="heading-creating-a-language-switcher">Creating a Language Switcher</h2>
<p>How would someone change the language, though? Let's create a simple language selector component:</p>
<pre><code class="lang-javascript">&lt;!-- src/LanguageSelect.svelte --&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> { locale } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte-i18n'</span>;

  <span class="hljs-keyword">const</span> languages = [
    { <span class="hljs-attr">code</span>: <span class="hljs-string">'en'</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'English'</span> },
    { <span class="hljs-attr">code</span>: <span class="hljs-string">'es'</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Español'</span> }
  ];
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
  {#each languages as { code, name }}
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{()</span> =&gt;</span> locale.set(code)}&gt;{name}<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
  {/each}
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p>The <strong>bind:value</strong> directive automatically updates the active language when users make a selection. </p>
<p>The locale store from svelte-i18n handles all the behind-the-scenes work of switching languages.</p>
<p>Now let's bring everything together in our main <strong>App</strong> component:</p>
<pre><code class="lang-javascript">&lt;!-- src/App.svelte --&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> { waitLocale } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte-i18n'</span>;
  <span class="hljs-keyword">import</span> Welcome <span class="hljs-keyword">from</span> <span class="hljs-string">'./Welcome.svelte'</span>;
  <span class="hljs-keyword">import</span> LanguageSelect <span class="hljs-keyword">from</span> <span class="hljs-string">'./LanguageSelect.svelte'</span>;

  <span class="hljs-keyword">const</span>  username = <span class="hljs-string">'developer'</span>;
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>

{#<span class="hljs-keyword">await</span> waitLocale()}
  &lt;p&gt;Loading...&lt;/p&gt;
{:then}
  &lt;main&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">LanguageSelect</span> /&gt;</span></span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Welcome</span> {<span class="hljs-attr">username</span>} /&gt;</span></span>
  &lt;/main&gt;
{/<span class="hljs-keyword">await</span>}
</code></pre>
<p>The <code>waitLocale</code> function ensures translations are loaded before showing content. This prevents flickering or missing translations when the app first loads.</p>
<h2 id="heading-adding-advanced-features">Adding Advanced Features</h2>
<p>As your app grows, you'll need to handle more complex scenarios. Let's look at some common requirements.</p>
<h3 id="heading-formatting-numbers-and-currencies">Formatting Numbers and Currencies</h3>
<p>Different countries handle numbers and currencies quite differently. So for instance, if you show the figure of a hundred thousand to someone from France, and someone from the USA, you’ll need to show the same figure differently. </p>
<p>France → 100 000,00 $</p>
<p>USA → $100,000.00</p>
<p>You see how the thousands are separated by a space and the decimal by a comma in France? Using the US number format will make it quite confusing for someone from France. Here are a few other examples.</p>
<ul>
<li><p>US uses periods for decimals (1,234.56)</p>
</li>
<li><p>Many European countries use commas for decimals and periods for thousands (1.234,56)</p>
</li>
<li><p>Some countries group digits differently (like 1,23,456 in India)</p>
</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-comment">// src/lib/formatUtils.js</span>
<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">formatCurrency</span>(<span class="hljs-params">amount, locale, currency = <span class="hljs-string">'USD'</span></span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Intl</span>.NumberFormat(locale, {
    <span class="hljs-attr">style</span>: <span class="hljs-string">'currency'</span>,
    currency
  }).format(amount);
}
</code></pre>
<p>You can now use these formatters in your components:</p>
<pre><code class="lang-javascript">&lt;!-- src/lib/PriceDisplay.svelte --&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> { formatCurrency } <span class="hljs-keyword">from</span> <span class="hljs-string">'./lib/formatUtils'</span>;
  <span class="hljs-keyword">let</span> price = <span class="hljs-number">1234.56</span>;
  <span class="hljs-keyword">let</span> locale = <span class="hljs-string">'en'</span>;
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Price: {formatCurrency(price, locale, 'USD')}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
</code></pre>
<p>With this setup, the app now adapts the currency formats to the different locales based on what outputs you ask from it:</p>
<ul>
<li><p>US: "$1,234.56", "1.2M", "15%"</p>
</li>
<li><p>German: "1.234,56 €", "1,2 Mio.", "15 %"</p>
</li>
</ul>
<h3 id="heading-formatting-dates">Formatting Dates</h3>
<p>Similar to currency and number formats, date are formatted differently across different locales. </p>
<p>So, while the US uses MM/DD/YYYY, many European countries use DD/MM/YYYY, and Japan often uses YYYY年MM月DD日. </p>
<p>Luckily, we don’t need to handle this manually. Similar to currency formatting, we have the <code>Intl.DateTimeFormat</code> function that accepts the locale and date in numeric format and returns the appropriately formatted date. </p>
<pre><code class="lang-javascript"><span class="hljs-comment">// src/lib/dateUtils.js</span>
<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">formatDate</span>(<span class="hljs-params">date, locale</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Intl</span>.DateTimeFormat(locale, {
    <span class="hljs-attr">year</span>: <span class="hljs-string">'numeric'</span>,
    <span class="hljs-attr">month</span>: <span class="hljs-string">'long'</span>,
    <span class="hljs-attr">day</span>: <span class="hljs-string">'numeric'</span>
  }).format(date);
}
</code></pre>
<p>You can now use this function in your Svelte app to display the dates correctly for each locale:</p>
<pre><code class="lang-javascript">&lt;!-- src/lib/DateDisplay.svelte --&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> { formatDate } <span class="hljs-keyword">from</span> <span class="hljs-string">'./lib/dateUtils'</span>;
  <span class="hljs-keyword">let</span> locale = <span class="hljs-string">'en'</span>;
  <span class="hljs-keyword">let</span> today = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>();
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Today's date: {formatDate(today, locale)}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
</code></pre>
<p>Once implemented, you’ll see the dates get formatted automatically, like below:</p>
<ul>
<li><p>English (US): "September 23, 2024"</p>
</li>
<li><p>Spanish: "23 de septiembre de 2024"</p>
</li>
<li><p>German: "23. September 2024"</p>
</li>
<li><p>Japanese: "2024年9月23日"</p>
</li>
</ul>
<h3 id="heading-localizing-images">Localizing Images</h3>
<p>Don’t forget that localization isn’t just about translating text—your images need attention, too. Culturally relevant visuals, region-specific content like maps or symbols, and adaptable image formats can make all the difference.</p>
<h4 id="heading-dynamic-image-paths"><strong>Dynamic Image Paths</strong></h4>
<p>Use Svelte's reactivity to dynamically load images based on the current locale. For example, you can store localized image paths in a JSON file or directly in your i18n configuration:</p>
<pre><code class="lang-javascript">{
  <span class="hljs-string">"en"</span>: { <span class="hljs-string">"logo"</span>: <span class="hljs-string">"/images/en/logo.png"</span> },
  <span class="hljs-string">"fr"</span>: { <span class="hljs-string">"logo"</span>: <span class="hljs-string">"/images/fr/logo.png"</span> }
}
</code></pre>
<p>Then, in your Svelte component:</p>
<pre><code class="lang-javascript">&lt;script&gt;
  <span class="hljs-keyword">import</span> { locale } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte-i18n'</span>;
  <span class="hljs-keyword">import</span> translations <span class="hljs-keyword">from</span> <span class="hljs-string">'./translations.json'</span>;

  $: imagePath = translations[$locale].logo;
&lt;/script&gt;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{imagePath}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Localized logo"</span> /&gt;</span></span>
</code></pre>
<h4 id="heading-integrating-alternative-text-localization"><strong>Integrating Alternative Text Localization</strong></h4>
<p>Ensure your images' alt attributes are also localized. You can achieve this by adding an additional field in your translations:</p>
<pre><code class="lang-javascript">{
  <span class="hljs-string">"en"</span>: { <span class="hljs-string">"logoAlt"</span>: <span class="hljs-string">"Company Logo"</span> },
  <span class="hljs-string">"fr"</span>: { <span class="hljs-string">"logoAlt"</span>: <span class="hljs-string">"Logo de l'entreprise"</span> }
}

Then bind the localized alt text dynamically
</code></pre>
<pre><code class="lang-javascript">
&lt;img src={imagePath} alt={translations[$locale].logoAlt} /&gt;
</code></pre>
<h4 id="heading-switching-svg-content-dynamically"><strong>Switching SVG Content Dynamically</strong></h4>
<p>If you need to localize content within SVGs, such as text or icons or want to <a target="_blank" href="https://www.adobe.com/express/feature/image/convert/svg">convert to SVG</a> format, consider using Svelte's templating for seamless integration.</p>
<pre><code class="lang-javascript">&lt;svg&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">text</span> <span class="hljs-attr">x</span>=<span class="hljs-string">"10"</span> <span class="hljs-attr">y</span>=<span class="hljs-string">"20"</span>&gt;</span>{$t('svgText')}<span class="hljs-tag">&lt;/<span class="hljs-name">text</span>&gt;</span></span>
&lt;/svg&gt;
</code></pre>
<p>This approach ensures your SVGs are directly rendered with localized text.</p>
<h3 id="heading-handling-multiple-forms-of-pluralization">Handling Multiple Forms of Pluralization</h3>
<p>While many languages have two forms of plurals (singular and plural), there are many languages with more than two forms, and some don’t pluralize. For example:</p>
<ul>
<li><p>Arabic has six forms</p>
</li>
<li><p>Japanese doesn't pluralize in the same way</p>
</li>
</ul>
<p>We can easily handle these differences using svelte-i18n's ICU message syntax. I’ve also added an example of how you can handle more than two forms when using Arabic.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// src/locales/en.json</span>
{
  <span class="hljs-string">"items"</span>: {
    <span class="hljs-string">"count"</span>: <span class="hljs-string">"{count, plural, =0 {No items} one {1 item} other {{count} items}}"</span>
  }
}

<span class="hljs-comment">// src/locales/es.json</span>

{
  <span class="hljs-string">"items"</span>: {
    <span class="hljs-string">"count"</span>: <span class="hljs-string">"{count, plural, =0 {Sin elementos} one {1 elemento} other {{count} elementos}}"</span>
  }
}

<span class="hljs-comment">// src/locales/ar.json</span>
{
  <span class="hljs-string">"items"</span>: {
    <span class="hljs-string">"count"</span>: <span class="hljs-string">"{count, plural, =0 {لا عناصر} one {عنصر واحد} two {عنصران} few {# عناصر} many {# عنصر} other {# عنصر}}"</span>,
  }
}
</code></pre>
<p>Now, let's create the pluralization component for our Svelte app where a button increments the count with every click.</p>
<pre><code class="lang-javascript">&lt;!-- src/lib/ItemCounter.svelte --&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> {  } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte-i18n'</span>;
  <span class="hljs-keyword">let</span> count = <span class="hljs-number">0</span>;
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{$('items.count', { count })}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{()</span> =&gt;</span> count++}&gt;Add Item<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{()</span> =&gt;</span> count--} disabled={count === 0}&gt;Remove Item<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
</code></pre>
<p>With this implemented, your app is fully ready to handle pluralization dynamically (as you’ll notice by clicking on the <strong>Add item</strong> button). </p>
<h3 id="heading-handling-missing-translations">Handling Missing Translations</h3>
<p>Sometimes, translations for certain keys might be missing. This can happen due to oversight, dynamic content, or incomplete translation files. To handle such scenarios gracefully, set up error handling using the <strong>missingKeyHandler</strong> option in <strong>svelte-i18n</strong>.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { register, init } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte-i18n'</span>;

register(<span class="hljs-string">'en'</span>, <span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'./locales/en.json'</span>));
register(<span class="hljs-string">'es'</span>, <span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'./locales/es.json'</span>));

init({
  <span class="hljs-attr">fallbackLocale</span>: <span class="hljs-string">'en'</span>,
  <span class="hljs-attr">initialLocale</span>: <span class="hljs-string">'en'</span>,
  <span class="hljs-attr">missingKeyHandler</span>: <span class="hljs-function">(<span class="hljs-params">locale, key</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.warn(<span class="hljs-string">`Missing translation: <span class="hljs-subst">${key}</span> (<span class="hljs-subst">${locale}</span>)`</span>);
    <span class="hljs-keyword">return</span> key; <span class="hljs-comment">// Display the key itself when translation is missing</span>
  }
});
</code></pre>
<p>This code logs a warning when a translation is missing and displays the key instead of showing nothing.</p>
<h2 id="heading-making-your-app-production-ready">Making Your App Production-Ready</h2>
<p>When preparing your app for real-world users, optimize it for localization by automatically detecting the user’s language. </p>
<p>You can use the browser’s <strong>navigator.language</strong> property to set the initial locale:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { init, getLocaleFromNavigator } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte-i18n'</span>;

init({
  <span class="hljs-attr">fallbackLocale</span>: <span class="hljs-string">'en'</span>,
  <span class="hljs-attr">initialLocale</span>: getLocaleFromNavigator(),
});
</code></pre>
<h2 id="heading-best-practices-for-scaling-your-localization">Best Practices for Scaling Your Localization</h2>
<ul>
<li><p><strong>Organize translations</strong>: Group related translations logically (for example, buttons, menus, notifications) and use consistent naming patterns for keys.</p>
</li>
<li><p><strong>Use a translation management platform:</strong> As your app grows, handling translation files manually starts becoming cumbersome. <a target="_blank" href="https://centus.com/">Translation management platforms</a> are purpose-built to solve this exact issue and help save hours every day, make it easy to collaborate on projects, and keep track of progress.</p>
</li>
<li><p><strong>Thorough testing</strong>: Test your app with real users across all supported languages. You also need to keep in mind the text length changes to avoid issues with layouts, especially with languages like German or Arabic, which can expand text significantly.</p>
</li>
<li><p><strong>Cultural considerations</strong>: Adapt your app for cultural norms, reading directions (for example, RTL for Arabic), and regional preferences (for example, date and currency formats). </p>
</li>
</ul>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>Localization might feel like a big task at first, but it’s totally worth it. It lets you reach more people and makes your app more inclusive.</p>
<p>Svelte and svelte-i18n streamline the process and keep it fun as you build your skills.</p>
<p>To keep it simple, start with the basics, such as adding translations and a language switcher. Advanced features like handling dates, currencies, and pluralization can follow as you gain confidence. </p>
<p>Take your time, test thoroughly, and build an app that feels natural for all the users you serve!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn SvelteKit in 2 hours ]]>
                </title>
                <description>
                    <![CDATA[ SvelteKit is the next evolution of Svelte, a modern JavaScript framework that compiles your code to highly efficient, vanilla JavaScript at build time. It's a great framework to learn for developers seeking to hone their skills or dive into modern we... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-sveltekit-full-course/</link>
                <guid isPermaLink="false">66b20519a5be9a107f43417c</guid>
                
                    <category>
                        <![CDATA[ Svelte ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Thu, 15 Feb 2024 18:47:48 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/02/sveltekitfull.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>SvelteKit is the next evolution of Svelte, a modern JavaScript framework that compiles your code to highly efficient, vanilla JavaScript at build time. It's a great framework to learn for developers seeking to hone their skills or dive into modern web frameworks.</p>
<p>We just posted a course on the freeCodeCamp.org YouTube channel that will teach you how to use both SvelteKit and TailwindCSS. Developed by James McArthur, this course is a great opportunity for beginners to build an awesome-looking landing page from scratch, covering everything from the initial setup to deployment.</p>
<h2 id="heading-introduction-to-sveltekit-amp-tailwindcss">Introduction to SvelteKit &amp; TailwindCSS</h2>
<p>Before diving into the course, let’s unpack what SvelteKit and TailwindCSS are.</p>
<h3 id="heading-sveltekit-the-fast-flexible-framework">SvelteKit: The Fast, Flexible Framework</h3>
<p>Unlike traditional frameworks that do most of the heavy lifting in the browser, Svelte shifts that work into the compile step, creating apps that are faster and lighter. SvelteKit takes this a step further, offering a framework for building server-side rendered (SSR) applications with Svelte. It's designed for greater flexibility, offering features like file-based routing, server-side rendering, static site generation, and seamless integration with various backends.</p>
<h3 id="heading-tailwindcss-the-utility-first-css-framework">TailwindCSS: The Utility-First CSS Framework</h3>
<p>TailwindCSS is a utility-first CSS framework that allows developers to style their sites directly within their HTML markup. It emphasizes rapid UI development by providing low-level utility classes that can be composed to build any design directly in your markup. This approach minimizes the need to write custom CSS, making it faster and easier to design responsive, custom-styled web pages without leaving your HTML.</p>
<h2 id="heading-building-a-web-application-with-sveltekit-amp-tailwindcss">Building a Web Application with SvelteKit &amp; TailwindCSS</h2>
<p>The course is structured to take you through the process of building a web application using these two powerful technologies. Here’s what you’ll learn:</p>
<h3 id="heading-setting-up-your-project">Setting Up Your Project</h3>
<p>The course begins with setting up a new SvelteKit project and integrating TailwindCSS. This foundational step is critical, ensuring you understand how to start a project from scratch and configure it for success.</p>
<h3 id="heading-designing-a-landing-page">Designing a Landing Page</h3>
<p>Once the setup is complete, James guides you through the process of designing a landing page. This section of the course emphasizes the utility of TailwindCSS in creating responsive, aesthetically pleasing designs with minimal effort. You’ll learn how to use utility classes to style your application, making the design process more intuitive and efficient.</p>
<h3 id="heading-implementing-features-with-sveltekit">Implementing Features with SvelteKit</h3>
<p>With the design in place, the course delves into SvelteKit’s capabilities, such as reactive variables, stores, and modules. These features enable you to create a dynamic, interactive user experience. You’ll explore how to make your landing page not just visually appealing, but also functional and responsive to user interactions.</p>
<h2 id="heading-deploying-your-landing-page">Deploying Your Landing Page</h2>
<p>The final section of the course covers the deployment of your landing page. James walks you through the process of deploying your project to the web, ensuring your work is accessible to the world. This includes choosing a hosting service, setting up your domain, and deploying your site using continuous integration and continuous deployment (CI/CD) pipelines.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>For developers looking to get hands-on with SvelteKit and TailwindCSS, this course offers a practical, project-based approach to learning. By building a landing page, you gain a deep understanding of these technologies in a real-world context. </p>
<p>You can watch the full course on <a target="_blank" href="https://youtu.be/vb7CgDcA_6U">the freeCodeCamp.org YouTube channel</a> (2-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/vb7CgDcA_6U" 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[ Learn SvelteKit and Tailwind CSS by Building a Web Portfolio ]]>
                </title>
                <description>
                    <![CDATA[ Whether you're a seasoned developer or just starting your journey in the world of web development, keeping up with the latest tools and frameworks is essential. And you can learn about two popular web dev tools in the new course we just posted on the... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-sveltekit-and-tailwind-css-by-building-a-web-portfolio/</link>
                <guid isPermaLink="false">66b20517297cd6de0bd54676</guid>
                
                    <category>
                        <![CDATA[ Svelte ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tailwind ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Tue, 03 Oct 2023 15:11:31 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/10/sveltekit.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Whether you're a seasoned developer or just starting your journey in the world of web development, keeping up with the latest tools and frameworks is essential.</p>
<p>And you can learn about two popular web dev tools in the new course we just posted on the freeCodeCamp.org YouTube channel. In this course, you'll learn how to create a web portfolio using SvelteKit &amp; TailwindCSS.</p>
<p>SvelteKit is more than just a flavor of the month; it's a game-changer in building web applications. It comes with built-in server-side rendering, routing, and many other features that simplify the developer's journey.</p>
<p>But what's web development without a touch of aesthetics? Enter Tailwind CSS. A utility-first CSS framework, Tailwind enables developers to rapidly craft custom user interfaces without getting bogged down by custom CSS.</p>
<p>The combination of SvelteKit and Tailwind CSS promises a development experience like no other, allowing for the creation of interactive, responsive, and beautiful web applications.</p>
<p>James McArthur created this course. He is a full-stack developer with a knack for creating engaging tutorials. James delves deep into the process of building a web portfolio from scratch, making it a perfect watch for those aiming to showcase their skills and projects to potential employers or simply wanting to mark their presence on the internet.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/image-3.png" alt="Image" width="600" height="400" loading="lazy">
<em>This is the front page of the page you will create.</em></p>
<p>The tutorial takes a hands-on approach, guiding viewers step by step. By the end of it, not only will you have a fully functional web portfolio, but you'll also have it live on the internet. As James amusingly puts it, "you can send it to your mum."</p>
<p>The portfolio demo features a captivating landing page for a fictitious character, Samuel Oak (or as James calls him, "fake small James"). It boasts aesthetically pleasing elements like particle animation effects that add depth and dynamism to the page. The navigation is seamless, leading to sections that display projects, an 'about me' segment, and a unique table that playfully yet effectively pitches you as the top candidate for job applications.</p>
<p>For anyone eager to establish a striking online presence, this course is a great place to start. Not only does it teach the technicalities of web development but also emphasizes the importance of aesthetics and user experience.</p>
<p>You can watch the full course on <a target="_blank" href="https://youtu.be/-2UjwQzxvBQ">the freeCodeCamp.org YouTube channel</a> (1-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/-2UjwQzxvBQ" 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[ How to Build a Calculator App with Svelte ]]>
                </title>
                <description>
                    <![CDATA[ Svelte is an open-source front-end JavaScript framework used for building web applications, designed to make developing interactive user interfaces more efficient and performant. Compared to other front-end frameworks like React, Vue, or Angular, it ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-calculator-app-with-svelte/</link>
                <guid isPermaLink="false">66d45d583dce891ac3a967a6</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Svelte ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Adejumo Ridwan Suleiman ]]>
                </dc:creator>
                <pubDate>Tue, 22 Aug 2023 15:48:35 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/08/WHATSAPP-DICTIONARY-CHATBOT--1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Svelte is an open-source front-end JavaScript framework used for building web applications, designed to make developing interactive user interfaces more efficient and performant.</p>
<p>Compared to other front-end frameworks like React, Vue, or Angular, it focuses on a different approach by compiling components.</p>
<p>In most traditional frameworks, you build components using a virtual DOM (Document Object Model) abstraction.</p>
<p>In these frameworks, changes to the UI are first made to a virtual representation of the UI which calculates the differences and updates the actual DOM accordingly. This process can introduce overhead and performance bottlenecks, especially for complex applications.</p>
<p>Svelte, on the other hand, takes a different approach.</p>
<p>It shifts much of the work to the build process, compiling components into highly optimized JavaScript code that directly manipulates the DOM during runtime.</p>
<p>Svelte applications have a smaller runtime footprint and can often achieve better performance compared to applications built with traditional frameworks.</p>
<p>In this tutorial, you will learn how to build a simple calculator using Svelte.</p>
<p>Unlike most frameworks, Svelte does not have a steep learning curve. A basic understanding of HTML, CSS and JavaScript is sufficient to grasp Svelte.</p>
<p>The following are the prerequisites for this tutorial:</p>
<ul>
<li><p>Basic knowledge of HTML, CSS and JavaScript</p>
</li>
<li><p>Willingness to learn</p>
</li>
</ul>
<p>You can experience how the calculator works <a target="_blank" href="https://svelte.dev/repl/cdf560babcf148639631872f27ba3275?version=4.2.0">here</a>.</p>
<h2 id="heading-how-to-plan-the-project">How to Plan the Project</h2>
<p>Those who fail to plan, plan to fail. It's a good practice to plan what you are building.</p>
<p>We want the calculator application to follow some criteria as follows:</p>
<ul>
<li><p>The calculator should have a user-friendly interface with buttons for digits (0-9), decimal point (.), and arithmetic operations (+, -, *, /).</p>
</li>
<li><p>It should display the current input and the result on the screen.</p>
</li>
<li><p>The calculator should support multiple arithmetic operations in sequence (for example: 2 + 3 * 5).</p>
</li>
<li><p>The user should be able to clear the input and reset the calculator.</p>
</li>
<li><p>The calculator should handle edge cases and prevent invalid inputs.</p>
</li>
</ul>
<p>Below is a design of how the calculator should look like. You can use tools like <a target="_blank" href="https://www.figma.com/">Figma</a> or <a target="_blank" href="https://helpx.adobe.com/xd/get-started.html">Adobe XD</a> to draw how you want your UI to look or sketch it on paper.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/image-118.png" alt="Image of the proposed Calculator to be built" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-build-the-user-interface">How to Build the User Interface</h2>
<p>The calculator you will build is a simple app using <a target="_blank" href="https://svelte.dev/repl/hello-world?version=4.2.0">Svelte REPL</a>. It's an interactive coding environment that allows you to play with Svelte without going through the hassle of getting it set up locally on your PC.</p>
<p>But if you to prefer to follow locally, ensure you have <a target="_blank" href="https://nodejs.org/en">Node.js</a> installed, and run the following code on your terminal:</p>
<pre><code class="lang-shell">npm create svelte@latest &lt;name-of-your-app&gt;
cd myapp
npm install
npm run dev
</code></pre>
<p>You can read more <a target="_blank" href="https://svelte.dev/docs/introduction">here</a> on how to get started.</p>
<p>Svelte allows you to build apps based on components written in a <code>.svelte file</code>. A web application contains components such as buttons, headers and so on.</p>
<p>Svelte simplifies this process by allowing you to create it once and reuse it in any part of your application. Most web applications contain one or more components.</p>
<p>The main application is in <code>App.svelte</code>, which contains the main code for the calculator app you are about to build.</p>
<p>When you open the <a target="_blank" href="https://svelte.dev/repl/hello-world?version=4.2.0">Svelte REPL</a>, you can see the default application prints <em>Hello World</em> on the screen:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
    <span class="hljs-keyword">let</span> name = <span class="hljs-string">'world'</span>;
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello {name}!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/image-119.png" alt="Image displaying the Hello World app" width="600" height="400" loading="lazy"></p>
<p>A <code>.svelte</code> file contains JavaScript, HTML and CSS.</p>
<p>The JavaScript, is written in the <code>&lt;script&gt;...&lt;/script&gt;</code> tag, while you can write the HTML code below it, and apply CSS styling in the <code>&lt;style&gt;...&lt;/style&gt;</code> tag.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
    <span class="hljs-keyword">let</span> name = <span class="hljs-string">'world'</span>;
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello {name}!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
    <span class="hljs-selector-tag">h1</span>{
        <span class="hljs-attribute">background</span>: red;
    }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/image-120.png" alt="Image of the result of the above code, Hello World is printed with a red background" width="600" height="400" loading="lazy"></p>
<p>Variables declared in the script tag are displayed using the curly parentheses <code>{}</code>. Just like you can see <code>Hello Word</code> displayed using the <code>name</code> variable.</p>
<p>Now let's start building the application, copy and paste the following code into <code>App.svelte</code>:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"calculator"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"display"</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">"buttons"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>7<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>8<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>9<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span>&gt;</span>+<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>4<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>5<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>6<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span>&gt;</span>-<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>1<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>2<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>3<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span>&gt;</span>*<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>0<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>.<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"clear"</span>&gt;</span>C<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span>&gt;</span>/<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"equals"</span>&gt;</span>=<span class="hljs-tag">&lt;/<span class="hljs-name">button</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>&gt;</span>

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

<span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/image-121.png" alt="Image showing result of the above code, the buttons are all layed out horizontally without any styling" width="600" height="400" loading="lazy"></p>
<p>If you have done that, you have created two divs – <code>calculator</code> and <code>display</code>. <code>calculator</code> is the parent div that contains <code>display</code> and the calculator <code>buttons</code>.</p>
<p>All arithmetic operations carry the class name <code>operator</code>. The clear sign also has the class name <code>clear</code>, and the equal sign has the class name <code>equals</code>.</p>
<p>You might not see the display now because we haven't applied CSS styling.</p>
<p>Inside the <code>&lt;style&gt;&lt;/style&gt;</code> tag, paste the code below:</p>
<pre><code class="lang-javascript">&lt;script&gt;

&lt;/script&gt;

...

&lt;style&gt;
.calculator {
    <span class="hljs-attr">display</span>: inline-block;
    border: <span class="hljs-number">1</span>px solid #ccc;
    padding: <span class="hljs-number">10</span>px;
    border-radius: <span class="hljs-number">5</span>px;
    box-shadow: <span class="hljs-number">0</span> <span class="hljs-number">2</span>px <span class="hljs-number">5</span>px rgba(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.1</span>);
}

.display {
    font-size: <span class="hljs-number">24</span>px;
    border: <span class="hljs-number">1</span>px solid #ccc;
    height: <span class="hljs-number">24</span>px;
    padding: <span class="hljs-number">10</span>px;
    margin-bottom: <span class="hljs-number">10</span>px;
    width: <span class="hljs-number">300</span>px;
    text-align: right;
}
&lt;/style&gt;
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/image-122.png" alt="Image showing the styling applied on the two divs calculator and display" width="600" height="400" loading="lazy"></p>
<p>Now let's style the buttons into a grid of four columns.</p>
<p>Update the <code>&lt;style&gt;&lt;/style&gt;</code> tag with the <code>buttons</code> and <code>button</code> style below:</p>
<pre><code class="lang-html">...

<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
 ...
<span class="hljs-selector-class">.buttons</span> {
    <span class="hljs-attribute">display</span>: grid;
    <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">repeat</span>(<span class="hljs-number">4</span>, <span class="hljs-number">75px</span>);
    <span class="hljs-attribute">gap</span>: <span class="hljs-number">5px</span>;
}

<span class="hljs-selector-tag">button</span> {
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">18px</span>;
    <span class="hljs-attribute">border</span>: none;
    <span class="hljs-attribute">cursor</span>: pointer;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">5px</span>;
    <span class="hljs-attribute">font-family</span>: Arial, sans-serif;
    <span class="hljs-attribute">text-align</span>: center;
}
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p>Note that <code>buttons</code> is the class name for the div containing the various HTML <code>button</code> tags.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/image-123.png" alt="Image displaying the 4 column grid of the buttons div" width="600" height="400" loading="lazy"></p>
<p>Next, let's style the buttons to improve user experience for anyone using the calculator and make the equal button occupy the empty spaces.</p>
<p>Update the <code>&lt;style&gt;&lt;/style&gt;</code> tag as follows:</p>
<pre><code class="lang-html">...
<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
 ...
 <span class="hljs-selector-class">.operator</span>{
    <span class="hljs-attribute">border</span>: <span class="hljs-number">0px</span> solid <span class="hljs-number">#A46D19</span>;
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#F90</span>;
}
<span class="hljs-selector-class">.clear</span>{
    <span class="hljs-attribute">border</span>: <span class="hljs-number">0px</span> solid <span class="hljs-number">#000</span>;
    <span class="hljs-attribute">background</span>: red;
}
<span class="hljs-selector-class">.equals</span>{
    <span class="hljs-attribute">border</span>: <span class="hljs-number">0px</span> solid <span class="hljs-number">#000</span>;
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#245BE9</span>;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">320px</span>
}
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/image-124.png" alt="Image showing the calculator ui, with an orange colour giving to the aritmetic buttons, red to the clear button and blue to the equal sign button. The equal sign button is also extended to fill up the space shown earlier" width="600" height="400" loading="lazy"></p>
<p>Not done yet, one last thing to do.</p>
<p>You need to include hovering effect on all buttons, allowing a user to know when the mouse is on a particular button. This will make for a better user experience.</p>
<p>Update the <code>&lt;style&gt;&lt;/style&gt;</code> tag as follows:</p>
<pre><code class="lang-html">...
<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
    ...
<span class="hljs-selector-class">.operator</span><span class="hljs-selector-pseudo">:hover</span>{
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#FFD700</span>;
}
<span class="hljs-selector-class">.clear</span><span class="hljs-selector-pseudo">:hover</span> {
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#FFC0CB</span> ;
}
<span class="hljs-selector-class">.equals</span><span class="hljs-selector-pseudo">:hover</span> {
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#ADD8E6</span>; 
}
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/image-125.png" alt="Image showin hovering effect on the equals sign" width="600" height="400" loading="lazy"></p>
<p>Now we are done with the calculator's user interface.</p>
<p>If you did everything right, your code should look like this:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"calculator"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"display"</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">"buttons"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>7<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>8<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>9<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span>&gt;</span>+<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>4<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>5<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>6<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span>&gt;</span>-<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>1<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>2<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>3<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span>&gt;</span>*<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>0<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>.<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"clear"</span>&gt;</span>C<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span>&gt;</span>/<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"equals"</span>&gt;</span>=<span class="hljs-tag">&lt;/<span class="hljs-name">button</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>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
<span class="hljs-selector-class">.calculator</span> {
    <span class="hljs-attribute">display</span>: inline-block;
    <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid <span class="hljs-number">#ccc</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">5px</span>;
    <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-number">2px</span> <span class="hljs-number">5px</span> <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.1</span>);
}

<span class="hljs-selector-class">.display</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">24px</span>;
    <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid <span class="hljs-number">#ccc</span>;
    <span class="hljs-attribute">height</span>: <span class="hljs-number">24px</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">300px</span>;
    <span class="hljs-attribute">text-align</span>: right;
}
<span class="hljs-selector-class">.buttons</span> {
    <span class="hljs-attribute">display</span>: grid;
    <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">repeat</span>(<span class="hljs-number">4</span>, <span class="hljs-number">75px</span>);
    <span class="hljs-attribute">gap</span>: <span class="hljs-number">5px</span>;
}

<span class="hljs-selector-tag">button</span> {
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">18px</span>;
    <span class="hljs-attribute">border</span>: none;
    <span class="hljs-attribute">cursor</span>: pointer;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">5px</span>;
    <span class="hljs-attribute">font-family</span>: Arial, sans-serif;
    <span class="hljs-attribute">text-align</span>: center;
}
<span class="hljs-selector-class">.operator</span>{
    <span class="hljs-attribute">border</span>: <span class="hljs-number">0px</span> solid <span class="hljs-number">#A46D19</span>;
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#F90</span>;
}
<span class="hljs-selector-class">.clear</span>{
    <span class="hljs-attribute">border</span>: <span class="hljs-number">0px</span> solid <span class="hljs-number">#000</span>;
    <span class="hljs-attribute">background</span>: red;
}
<span class="hljs-selector-class">.equals</span>{
    <span class="hljs-attribute">border</span>: <span class="hljs-number">0px</span> solid <span class="hljs-number">#000</span>;
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#245BE9</span>;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">320px</span>
}
<span class="hljs-selector-class">.operator</span><span class="hljs-selector-pseudo">:hover</span>{
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#FFD700</span>;
}
<span class="hljs-selector-class">.clear</span><span class="hljs-selector-pseudo">:hover</span> {
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#FFC0CB</span> ;
}
<span class="hljs-selector-class">.equals</span><span class="hljs-selector-pseudo">:hover</span> {
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#ADD8E6</span>; 
}
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p>Now let's start cooking!</p>
<h2 id="heading-how-to-handle-interactivity">How to Handle Interactivity</h2>
<p>Now that you have finished with the UI, let's make the calculator interactive by starting with the number buttons.</p>
<p>Copy and paste the following code into the <code>&lt;script&gt;&lt;/script&gt;</code> tag in <code>App.svelte</code>:</p>
<pre><code class="lang-javascript">&lt;script&gt;
    <span class="hljs-keyword">let</span> display_number = <span class="hljs-string">""</span>;
    <span class="hljs-keyword">const</span> select = <span class="hljs-function">(<span class="hljs-params">num</span>) =&gt;</span> <span class="hljs-function">() =&gt;</span> (display_number += num);
    <span class="hljs-keyword">const</span> clear = <span class="hljs-function">() =&gt;</span> (display_number = <span class="hljs-string">""</span>);
&lt;/script&gt;
...
...
</code></pre>
<ul>
<li><p><code>display_number</code> is the number displayed on the calculator screen.</p>
</li>
<li><p><code>select</code> is the function that allows any number clicked, to appear on the screen.</p>
</li>
<li><p><code>clear</code> is the function that clears the screen, resetting the value of display number to an empty string.</p>
</li>
</ul>
<p>Note that <code>display_number</code> is a string data type. Later on you will learn how to convert it to a numeric data type and perform calculations with it.</p>
<p>Next let's implement the <code>select</code> and <code>clear</code> function into the HTML.</p>
<p>Modify the HTML as follows:</p>
<pre><code class="lang-html">...
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"calculator"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"display"</span>&gt;</span>{display_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> <span class="hljs-attr">class</span>=<span class="hljs-string">"buttons"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(7)}</span>&gt;</span>7<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(8)}</span>&gt;</span>8<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(9)}</span>&gt;</span>9<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span> &gt;</span>+<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(4)}</span>&gt;</span>4<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(5)}</span>&gt;</span>5<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(6)}</span>&gt;</span>6<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span> &gt;</span>-<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(1)}</span>&gt;</span>1<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(2)}</span>&gt;</span>2<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(3)}</span>&gt;</span>3<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span>&gt;</span>*<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(0)}</span>&gt;</span>0<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(</span>"<span class="hljs-attr">.</span>")}&gt;</span>.<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{clear}</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"clear"</span>&gt;</span>C<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span>&gt;</span>/<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"equals"</span> &gt;</span>=<span class="hljs-tag">&lt;/<span class="hljs-name">button</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>&gt;</span>

...
</code></pre>
<p>Svelte <code>on:click</code> directive allows you attach an event handler to an element, so that when you call the <code>select</code> function for an element, it displays the number of that element appended to the previous value.</p>
<p>The <code>clear</code> button also has the event handler clear, to clear the screen and reset to <code>""</code> anytime it's called.</p>
<p>If you get everything right, you should see the value of the buttons clicked on the screen.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/image-126.png" alt="Image showing the numbers displaying on the screen when clicked." width="600" height="400" loading="lazy"></p>
<p>Let's create an event handler to perform an addition function and display the result. This will serve as the basis for all other operations in the calculator.</p>
<p>Update the <code>&lt;script&gt;&lt;/script&gt;</code> tag as follows:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
    ...
    let operand;
    <span class="hljs-keyword">let</span> result;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addition</span>(<span class="hljs-params"></span>) </span>{
        operand = <span class="hljs-built_in">Number</span>(display_number);
        display_number = <span class="hljs-string">""</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">equals</span>(<span class="hljs-params"></span>) </span>{
        display_number = <span class="hljs-built_in">Number</span>(display_number);
        result = operand + display_number
        display_number = result.toString()
    }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
...
...
</code></pre>
<p>When performing calculations, you can have two or more operands – <code>operand</code> is the variable where the previous operand is stored, while <code>display_number</code> contains the current operand.</p>
<p><code>result</code> is the final result after performing an arithmetic operation.</p>
<p>The <code>addition</code> function takes the initial value displayed, converts it to a <code>Number</code> and stores it in the new variable <code>operand</code>, which resets <code>display_number</code> to its initial value <code>""</code>.</p>
<p>The <code>equals</code> function takes the new currently displayed number, adds it to <code>operand</code> and saves it as the final <code>result</code>. <code>result</code> is now converted to a <code>string</code> and saved as <code>display_number</code> so it appears on the screen.</p>
<p>Note that the <code>equals</code> function converts <code>result</code> to a string. When you want to use it for another calculation, the <code>addition</code> function will handle the conversion to a <code>Number</code>.</p>
<p>Try performing an addition operation to see if you got it right.</p>
<p>By now, <code>App.svelte</code> should look like this:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
    <span class="hljs-keyword">let</span> display_number = <span class="hljs-string">""</span>;
    <span class="hljs-keyword">const</span> select = <span class="hljs-function">(<span class="hljs-params">num</span>) =&gt;</span> <span class="hljs-function">() =&gt;</span> (display_number += num);
    <span class="hljs-keyword">const</span> clear = <span class="hljs-function">() =&gt;</span> (display_number = <span class="hljs-string">""</span>);

    <span class="hljs-keyword">let</span> operand;
    <span class="hljs-keyword">let</span> result;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addition</span>(<span class="hljs-params"></span>) </span>{
            operand = <span class="hljs-built_in">Number</span>(display_number);
            display_number = <span class="hljs-string">""</span>;
      }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">equals</span>(<span class="hljs-params"></span>) </span>{
            display_number = <span class="hljs-built_in">Number</span>(display_number);
            result = operand + display_number
            display_number = result.toString()
      }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"calculator"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"display"</span>&gt;</span>{display_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> <span class="hljs-attr">class</span>=<span class="hljs-string">"buttons"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(7)}</span>&gt;</span>7<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(8)}</span>&gt;</span>8<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(9)}</span>&gt;</span>9<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{addition}</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span> &gt;</span>+<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(4)}</span>&gt;</span>4<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(5)}</span>&gt;</span>5<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(6)}</span>&gt;</span>6<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span> &gt;</span>-<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(1)}</span>&gt;</span>1<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(2)}</span>&gt;</span>2<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(3)}</span>&gt;</span>3<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span>&gt;</span>*<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(0)}</span>&gt;</span>0<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(</span>"<span class="hljs-attr">.</span>")}&gt;</span>.<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{clear}</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"clear"</span>&gt;</span>C<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"operator"</span>&gt;</span>/<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{equals}</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"equals"</span> &gt;</span>=<span class="hljs-tag">&lt;/<span class="hljs-name">button</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>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
<span class="hljs-selector-class">.calculator</span> {
    <span class="hljs-attribute">display</span>: inline-block;
    <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid <span class="hljs-number">#ccc</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">5px</span>;
    <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-number">2px</span> <span class="hljs-number">5px</span> <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.1</span>);
}

<span class="hljs-selector-class">.display</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">24px</span>;
    <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid <span class="hljs-number">#ccc</span>;
    <span class="hljs-attribute">height</span>: <span class="hljs-number">24px</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">300px</span>;
    <span class="hljs-attribute">text-align</span>: right;
}
<span class="hljs-selector-class">.buttons</span> {
    <span class="hljs-attribute">display</span>: grid;
    <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">repeat</span>(<span class="hljs-number">4</span>, <span class="hljs-number">75px</span>);
    <span class="hljs-attribute">gap</span>: <span class="hljs-number">5px</span>;
}

<span class="hljs-selector-tag">button</span> {
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">18px</span>;
    <span class="hljs-attribute">border</span>: none;
    <span class="hljs-attribute">cursor</span>: pointer;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">5px</span>;
    <span class="hljs-attribute">font-family</span>: Arial, sans-serif;
    <span class="hljs-attribute">text-align</span>: center;
}
<span class="hljs-selector-class">.operator</span>{
    <span class="hljs-attribute">border</span>: <span class="hljs-number">0px</span> solid <span class="hljs-number">#A46D19</span>;
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#F90</span>;
}
<span class="hljs-selector-class">.clear</span>{
    <span class="hljs-attribute">border</span>: <span class="hljs-number">0px</span> solid <span class="hljs-number">#000</span>;
    <span class="hljs-attribute">background</span>: red;
}
<span class="hljs-selector-class">.equals</span>{
    <span class="hljs-attribute">border</span>: <span class="hljs-number">0px</span> solid <span class="hljs-number">#000</span>;
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#245BE9</span>;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">320px</span>
}
<span class="hljs-selector-class">.operator</span><span class="hljs-selector-pseudo">:hover</span>{
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#FFD700</span>;
}
<span class="hljs-selector-class">.clear</span><span class="hljs-selector-pseudo">:hover</span> {
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#FFC0CB</span> ;
}
<span class="hljs-selector-class">.equals</span><span class="hljs-selector-pseudo">:hover</span> {
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#ADD8E6</span>; 
}
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p>Let's improve the code to support other operations – subtraction, multiplication and division:</p>
<pre><code class="lang-javascript">&lt;script&gt;
...
let operator;
<span class="hljs-keyword">let</span> operators = [<span class="hljs-string">"+"</span>, <span class="hljs-string">"-"</span>, <span class="hljs-string">"*"</span>, <span class="hljs-string">"/"</span>];

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">operation</span>(<span class="hljs-params">sign</span>) </span>{
        operand = <span class="hljs-built_in">Number</span>(display_number);
        operator = sign;
        display_number = <span class="hljs-string">""</span>;
  }

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">equals</span>(<span class="hljs-params"></span>) </span>{
    display_number = <span class="hljs-built_in">Number</span>(display_number);
    <span class="hljs-keyword">if</span> (operator === <span class="hljs-string">"+"</span>) {
      result = operand + display_number;
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (operator === <span class="hljs-string">"-"</span>) {
      result = operand - display_number;
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (operator === <span class="hljs-string">"*"</span>) {
      result = operand * display_number;
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (operator === <span class="hljs-string">"/"</span>) {
      result = operand / display_number;
    }
display_number = result.toString()
&lt;/script&gt;
...
...
</code></pre>
<p>The <code>addition</code> function changes to <code>operation</code>, which supports the <code>sign</code> argument.</p>
<p>The <code>equals</code> function performs operations based on the value of the sign argument in the function operation.</p>
<p>Update the HTML code to add event handlers to the various arithmetic operations:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"calculator"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"display"</span>&gt;</span>{display_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> <span class="hljs-attr">class</span>=<span class="hljs-string">"buttons"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(7)}</span>&gt;</span>7<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(8)}</span>&gt;</span>8<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(9)}</span>&gt;</span>9<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{()</span> =&gt;</span> operation(operators[0])} class="operator" &gt;+<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(4)}</span>&gt;</span>4<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(5)}</span>&gt;</span>5<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(6)}</span>&gt;</span>6<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{()</span> =&gt;</span> operation(operators[1])} class="operator" &gt;-<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(1)}</span>&gt;</span>1<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(2)}</span>&gt;</span>2<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(3)}</span>&gt;</span>3<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{()</span> =&gt;</span> operation(operators[2])} class="operator"&gt;*<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(0)}</span>&gt;</span>0<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{select(</span>"<span class="hljs-attr">.</span>")}&gt;</span>.<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{clear}</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"clear"</span>&gt;</span>C<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{()</span> =&gt;</span> operation(operators[3])} class="operator"&gt;/<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{equals}</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"equals"</span> &gt;</span>=<span class="hljs-tag">&lt;/<span class="hljs-name">button</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>&gt;</span>
</code></pre>
<p>Each function takes its sign value by accessing the respective sign in <code>operator</code>s.</p>
<p>We now have a working calculator.</p>
<p>Now, how do we handle something like this?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/image-144.png" alt="The image shows the numbers going out of the display borders" width="600" height="400" loading="lazy"></p>
<p>The above is a bug where the numbers exceed the display boundaries.</p>
<p>To solve this error, update the <code>display</code> div as follows:</p>
<pre><code class="lang-html">...
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"calculator"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"display"</span>&gt;</span>{display_number.length <span class="hljs-tag">&lt; <span class="hljs-attr">23</span>? <span class="hljs-attr">display_number:</span> <span class="hljs-attr">display_number.substring</span>(<span class="hljs-attr">0</span>,<span class="hljs-attr">23</span>)}&lt;/<span class="hljs-attr">div</span>&gt;</span>
    ...
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
...
</code></pre>
<p>If the length of <code>display_number</code> is greater than <code>22</code>, which is the number of digits the display screen can contain, the first twenty-two characters is selected.</p>
<p>This will fix the above bug.</p>
<h2 id="heading-challenge">Challenge</h2>
<p>You can further extend the calculator by:</p>
<ul>
<li><p>Adding advanced mathematical and scientific operations.</p>
</li>
<li><p>Giving room for users to use their keyboard to input values.</p>
</li>
<li><p>Displaying the arithmetic operations on screen, before calculating.</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, you have learned how to use Svelte to create interactivity in a web app. And you also learned about Svelte event handlers.</p>
<p>You can further your current Svelte knowledge by visiting the official <a target="_blank" href="https://svelte.dev/docs/introduction">documentation</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn Svelte in 23 Hours ]]>
                </title>
                <description>
                    <![CDATA[ Svelte is a front-end JavaScript framework for making interactive webpages. Svelte has grown in popularity quite a bit over the last few years. We just published a free 23-hour course on the freeCodeCamp.org YouTube channel that will teach you how to... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-svelte-complete-course/</link>
                <guid isPermaLink="false">66b20514dc300c9dddc01252</guid>
                
                    <category>
                        <![CDATA[ Svelte ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Mon, 17 Oct 2022 15:14:47 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/10/svelte-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Svelte is a front-end JavaScript framework for making interactive webpages. Svelte has grown in popularity quite a bit over the last few years.</p>
<p>We just published a free 23-hour course on the freeCodeCamp.org YouTube channel that will teach you how to use Svelte.</p>
<p>Li Hau Tan developed this course. Li is a core maintainer of Svelte so he is the perfect person to teach this course.</p>
<p>Lee starts at the absolute beginning with creating your first Svelte component and continues on to teach every concept you need to know to develop applications using Svelte.</p>
<p>Here are all the topics covered in this comprehensive course:</p>
<ul>
<li>Introduction</li>
<li>Writing your 1st Svelte component</li>
<li>Style your Svelte component</li>
<li>Adding data to Svelte component</li>
<li>Reactivity in Svelte</li>
<li>Attaching events in Svelte</li>
<li>Reactive Declarations and Statements</li>
<li>tick()</li>
<li>Component and props</li>
<li>Component events</li>
<li>Forwarding component events</li>
<li>class: directive</li>
<li>Binding</li>
<li>bind:group</li>
<li>bind:this</li>
<li>Component Lifecycle</li>
<li>onMount</li>
<li>{#if} block</li>
<li>{#each} block</li>
<li>keyed {#each} block</li>
<li>keyed {#each} visualised</li>
<li>{#await} block</li>
<li>{#key} block</li>
<li>Context</li>
<li>Communicating through Context</li>
<li>Intro to Svelte store</li>
<li>Writable store</li>
<li>Readable store</li>
<li>Svelte store contract</li>
<li>Redux store as Svelte store</li>
<li>Valtio state as Svelte store</li>
<li>XState as Svelte store</li>
<li>DOM events as Svelte store</li>
<li>Immer for immutable Svelte store</li>
<li>derived() Svelte store</li>
<li>tweened() Svelte store</li>
<li>tweened() and spring()</li>
<li>Higher Order Store</li>
<li>RxJS as Svelte store</li>
<li>Reactive class property using stores</li>
<li>Undo / Redo with Svelte store</li>
<li>Reactive Context</li>
<li>tips to manage complex store</li>
<li>get() Svelte store value</li>
<li>Store vs Context</li>
<li>Intro to Svelte action</li>
<li>Dynamic parameter in Svelte action</li>
<li>What if Svelte action does not exists?</li>
<li>Integrating UI library with Svelte action</li>
<li>Reusing event listeners with Svelte action</li>
<li>Creating events with Svelte action</li>
<li>The order of Svelte action</li>
<li>use:clickOutside</li>
<li>use:tooltip</li>
<li>use:viewport</li>
<li>use:popper with Popper</li>
<li>use:lazyImage</li>
<li>Ensemble Actions</li>
<li></li>
<li>Passing data across </li>
<li>Slot forwarding</li>
<li>$$slots</li>
<li>Infinite List</li>
<li>Tabs</li>
<li><p>$$props and $$</p>restProps</li>
<li>Lazy Component</li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li>Passing CSS Custom Properties to Component</li>
<li>{@html}</li>
<li>{@debug}</li>
<li></li>
<li>Intro to Svelte transitions</li>
<li>Coordinating transitions</li>
<li>Transition Events</li>
<li>Easing</li>
<li>Accessible transitions</li>
<li>Solid color swipe transition</li>
<li>Flipboard transition</li>
<li>Client-side component API</li>
<li>SSR component API</li>
<li>Svelte compiler API</li>
<li>Svelte preprocess API</li>
<li>Hydrating Svelte component</li>
<li>svelte/register</li>
<li>Conclusion</li>
</ul>
<p>Watch the full course below or on <a target="_blank" href="https://youtu.be/UGBJHYpHPvA">the freeCodeCamp.org YouTube channel</a> (23-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/UGBJHYpHPvA" 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[ How to Do Test-Driven Development with Svelte and Vitest – A Project-Based Tutorial ]]>
                </title>
                <description>
                    <![CDATA[ By Sriram Thiagarajan Test Driven Development (TDD) is one of the best ways to make sure your code is high quality and works like it's supposed to work. It can also help you create reliable builds during continuous deployments.  In this post, we will... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-do-test-driven-development-with-svelte-and-vitest/</link>
                <guid isPermaLink="false">66d461492472e5ed2fa07bbd</guid>
                
                    <category>
                        <![CDATA[ Svelte ]]>
                    </category>
                
                    <category>
                        <![CDATA[ TDD (Test-driven development) ]]>
                    </category>
                
                    <category>
                        <![CDATA[ test driven development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ vite ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 19 Sep 2022 17:20:38 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/09/SvelteVitestTDDPoster.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Sriram Thiagarajan</p>
<p>Test Driven Development (TDD) is one of the best ways to make sure your code is high quality and works like it's supposed to work. It can also help you create reliable builds during continuous deployments. </p>
<p>In this post, we will learn how to create a Svelte application using TDD methods.</p>
<h2 id="heading-what-were-building">What We're Building</h2>
<p>We are going to build a vertical tabs component where we can switch between three tabs. We are going to build this component by writing test cases first and developing the component functionality after that to make the tests more effective.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/FinalComponent-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Final implementation</em></p>
<h2 id="heading-prerequisite">Prerequisite</h2>
<p>I will explain all the steps needed to create an app and you can follow along with the code. It's great if you have basic programming knowledge and fundamental knowledge of HTML and CSS for this tutorial.</p>
<p>Also, you'll need to have Node.js installed. You can <a target="_blank" href="https://nodejs.org/en/">see how to do that here</a> if you don't have it already.</p>
<h2 id="heading-what-is-test-driven-development">What is Test-Driven Development?</h2>
<p>The basic idea of test-driven development, or TDD, is to write the test before you implement the actual functionality. This helps you clearly figure out what you're developing and how it works. </p>
<p>You first watch the test fail, and then you write the code to make it pass. This ensures that there are no false positive tests in your code.</p>
<p>TDD is a methodology you can apply to any programming language. It is more prevalent when developing backend applications that contain business logic that you can easily test. </p>
<p>The good news is, you can apply similar techniques to test your front-end applications as well.</p>
<h2 id="heading-three-stages-of-tdd">Three stages of TDD</h2>
<p>The three stages of TDD are:</p>
<ol>
<li>Red stage – Write the test and watch it fail</li>
<li>Green stage – Write the minimum code required to make the test pass</li>
<li>Refactor – Cleanup and refactor the code to make it more robust</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/TDDStages.png" alt="Image" width="600" height="400" loading="lazy">
<em>Three stages of TDD</em></p>
<h2 id="heading-what-is-vitest">What is Vitest?</h2>
<p>Vitest is an up-and-coming testing framework which has similar functionality to Jest. </p>
<p>Since we are using Vite as our build tool for Svelte in this tutorial, Vitest has very good integration with Vite and offers a similar testing environment without needing extra configuration.</p>
<h2 id="heading-how-to-create-a-svelte-application">How to Create a Svelte Application</h2>
<p>We are going to create a Svelte application using Vite as the build tool. You can do that with this command:</p>
<pre><code>npm create vite@latest
</code></pre><p>This will create a new project, and you can follow the steps below to create and setup the project:</p>
<ol>
<li>Enter the name of the project. This will also create a new folder with the project name. In this example, I will add the project name as <code>svelte-tdd-vitest</code>.</li>
<li>You can select the framework in the next step. Let's choose <code>svelte</code> as the framework.</li>
<li>Then you can enter the variant of the framework. We can choose the <code>TypeScript</code> variant for this article. If you are not comfortable with TypeScript, you can also choose <code>JavaScript</code> in this option.</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/ProjectInit.png" alt="Image" width="600" height="400" loading="lazy">
<em>Initialise Svelte project with Vite</em></p>
<p>You can then follow the helpful steps provided in the terminal to install the dependencies and start the application. Run the following command:</p>
<pre><code>cd svelte-tdd-vitest
npm install
npm run dev
</code></pre><p><code>npm install</code> will install the dependencies of the project. </p>
<p><code>npm run dev</code> will start the development server. You should see the app running in the port specified in the terminal.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/ViteServerStartCmd.png" alt="Image" width="600" height="400" loading="lazy">
<em>Vite Server started using npm run dev</em></p>
<p>Congrats, you can now see the starter app running in your browser. You can open the project in your favourite Code Editor and start working.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/SvelteViteStarter.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-set-up-vitest">How to Set Up Vitest</h2>
<p>You can add Vitest to the project right now as a dev dependency. This means that Vitest will not be packaged into the production build of the application since you will be running the test in your local environment.</p>
<pre><code>npm install -D vitest
</code></pre><p>Vitest can read the config of Vite inside the <code>vite.config.js</code> file and prepare the test environment similar to the build environment. This makes the test more reliable. So you can reuse the Vite config file and add more options for the configuration of Vitest.</p>
<p>You can also override the config for the Vitest by creating a new file called <code>vitest.config.js</code> in the project root. So now, create a new file called <code>vitest.config.js</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">'vitest/config'</span>
<span class="hljs-keyword">import</span> { svelte } <span class="hljs-keyword">from</span> <span class="hljs-string">'@sveltejs/vite-plugin-svelte'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  <span class="hljs-attr">plugins</span>: [
    svelte({ <span class="hljs-attr">hot</span>: !process.env.VITEST }),
  ],
  <span class="hljs-attr">test</span>: {
    <span class="hljs-attr">environment</span>: <span class="hljs-string">'jsdom'</span>,
  }
})
</code></pre>
<p>There are a couple of configs we are adding to the file</p>
<ol>
<li>We are disabling Svelte's hot module reload when tests are running. </li>
<li>We are defining the environment for running the test as <code>jsdom</code>. It helps in mocking the DOM API and running the tests in a reliable method.</li>
</ol>
<p>In order to use the <code>jsdom</code> you need to add it as an Dev Dependency as well. So let's install that package using the terminal.</p>
<pre><code>npm install -D jsdom
</code></pre><p>After installation, let's add a couple of scripts to the <code>package.json</code> file to start the Vitest test from the <code>npm</code> command line:</p>
<pre><code class="lang-json"><span class="hljs-string">"scripts"</span>: {
    ...
    <span class="hljs-attr">"test"</span>: <span class="hljs-string">"vitest"</span>,
        <span class="hljs-attr">"coverage"</span>: <span class="hljs-string">"vitest run --coverage"</span>
}
</code></pre>
<h2 id="heading-how-to-create-the-first-test">How to Create the First Test</h2>
<p>You now have all the setup needed to write your first test. Create a new file called <code>sample.spec.ts</code> inside the <code>lib</code> directory.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> {describe, test, expect } <span class="hljs-keyword">from</span> <span class="hljs-string">'vitest'</span>;

describe(<span class="hljs-string">"Example File"</span>, <span class="hljs-function">() =&gt;</span> {
    test(<span class="hljs-string">"Sample test"</span>, <span class="hljs-function">() =&gt;</span> {
        expect(<span class="hljs-number">1</span> + <span class="hljs-number">3</span>).equal(<span class="hljs-number">4</span>);
    });
});
</code></pre>
<p>Let's break down the different functions used to create this test file:</p>
<ol>
<li><code>describe</code> – you use this to group similar test together and benchmark tests when generating your reports. It takes a name and a function that contains the group of tests.</li>
<li><code>test</code> – Represents a single test. It can contain multiple expectations within it. It is created by passing a name of the test and the function to run the test.</li>
<li><code>expect</code> – Represents the expression which you're testing.</li>
</ol>
<p>There are multiple different ways to write your test based on what you are testing. You can have a look at the complete API for Vitest in the <a target="_blank" href="https://vitest.dev/api/">official API Reference</a>.</p>
<p>Let's run the test using the following npm command:</p>
<pre><code>npm run test
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2022/09/NpmRunFirstTest.png" alt="Image" width="600" height="400" loading="lazy">
<em>Running the test</em></p>
<h2 id="heading-how-to-add-the-global-test-config">How to Add the Global Test Config</h2>
<p>You are going to be using the <code>describe</code>, <code>test</code>, and <code>expect</code> functions a lot in the test files and it might be verbose to import them in all the test files. So Vitest has a nice config where you can set these global imports and so you don't have to add them to each file. </p>
<p>So let's update the <code>vitest.config.js</code> file with this configuration:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  ...
  test: {
    ...
    globals: <span class="hljs-literal">true</span>
  }
})
</code></pre>
<p>After adding this <code>globals</code> equals true line in your config, you can now remove the imports in your spec file. </p>
<p>If you are using TypeScript, your TypeScript compiler will complain in your spec file. You can solve that by adding the following line to your <code>tsconfig.json</code> file:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"extends"</span>: <span class="hljs-string">"@tsconfig/svelte/tsconfig.json"</span>,
  <span class="hljs-attr">"compilerOptions"</span>: {
    ...
    <span class="hljs-attr">"types"</span>: [<span class="hljs-string">"vitest/globals"</span>]
  },
}
</code></pre>
<p>Now your test can look like this. This is not a huge upgrade for this small file, but when you have lots of spec files, this config change is useful.</p>
<pre><code class="lang-javascript">describe(<span class="hljs-string">"Example File"</span>, <span class="hljs-function">() =&gt;</span> {
    it(<span class="hljs-string">"Sample test"</span>, <span class="hljs-function">() =&gt;</span> {
        expect(<span class="hljs-number">1</span> + <span class="hljs-number">3</span>).equal(<span class="hljs-number">4</span>);
    });
});
</code></pre>
<h2 id="heading-how-to-create-a-svelte-component">How to Create a Svelte Component</h2>
<p>We will create a new svelte component called <code>VerticalTabs.svelte</code>. The requirements are to create a vertical tab component that can contain a few items and for the user to be able to select a particular tab to view its content in the right side.</p>
<p>The component will be divided into two parts. The left side displays all the tabs. The right side displays the content based on the tab.</p>
<p>Let's create the basic HTML and CSS styles needed for the component. We will add the functionality to switch tabs after writing the tests.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"vertical-tab-container"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"vertical-tab"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>First Tab<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>Second Tab<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>Third Tab<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"vertical-tab-content"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>First Tab Heading<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Lorem ipsum dolor sit amet consectetur adipisicing elit. Autem aut deserunt veniam tempora deleniti quos reprehenderit natus. Animi, obcaecati dolorum, culpa, maiores maxime ullam soluta unde rerum nihil temporibus quibusdam!<span class="hljs-tag">&lt;/<span class="hljs-name">p</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>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
    <span class="hljs-selector-class">.vertical-tab-container</span> {
        <span class="hljs-attribute">display</span>: flex;
        <span class="hljs-attribute">flex-direction</span>: row;
        <span class="hljs-attribute">align-items</span>: center;
        <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid gray;
        <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">1rem</span>;
    }

    <span class="hljs-selector-class">.vertical-tab</span> {
        <span class="hljs-attribute">margin</span>: <span class="hljs-number">0px</span>;
        <span class="hljs-attribute">padding</span>: <span class="hljs-number">3rem</span>;
        <span class="hljs-attribute">list-style</span>: none;
        <span class="hljs-attribute">border-right</span>: <span class="hljs-number">1px</span> solid gray
    }

    <span class="hljs-selector-class">.vertical-tab</span> <span class="hljs-selector-tag">li</span> {
        <span class="hljs-attribute">margin</span>: <span class="hljs-number">2rem</span> <span class="hljs-number">0</span>;
    }

    <span class="hljs-selector-class">.vertical-tab-content</span> {
        <span class="hljs-attribute">flex</span>:<span class="hljs-number">1</span>
    }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p>In this code, you are adding simple elements like an unordered list to display the list of tabs. You are styling it in the <code>&lt;style&gt;</code> tag which will be locally scoped CSS for this component.</p>
<p>Then, you are adding <code>&lt;h2&gt;</code> tag to display the tab heading and a paragraph tag <code>&lt;p&gt;</code> to show more dummy text for the tab. You're using <code>flex</code> to show the two items side by side and the property of <code>flex: 1</code> on the content will make that container take all the remaining available space to expand.</p>
<p>The component should look like the below image:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/VerticalTabInitial-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Vertical Tab initial</em></p>
<h2 id="heading-how-to-mount-the-svelte-component-in-test">How to Mount the Svelte Component in Test</h2>
<p>Now you need to create the first test for the component by mounting the svelte component and then checking to see if you can find the "First Tab" text in the component. </p>
<p>So create a new spec file called <code>VerticalTabs.spec.ts</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> VerticalTabs <span class="hljs-keyword">from</span> <span class="hljs-string">"./VerticalTabs.svelte"</span>;

describe(<span class="hljs-string">"VerticalTabs Component"</span>, <span class="hljs-function">() =&gt;</span> {

    test(<span class="hljs-string">"should render the component"</span>, <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-comment">// Create a new container for the test</span>
        <span class="hljs-keyword">const</span> host = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">'div'</span>);

        <span class="hljs-comment">// Append the new container in the HTML body</span>
        <span class="hljs-built_in">document</span>.body.appendChild(host);

        <span class="hljs-comment">// Create an instance of the vertical tab</span>
        <span class="hljs-keyword">const</span> instance = <span class="hljs-keyword">new</span> VerticalTabs({ <span class="hljs-attr">target</span>: host });

        <span class="hljs-comment">// Check if the instance has value</span>
        expect(instance).toBeTruthy()

        <span class="hljs-comment">// Test if we can find the "First Tab Heading"</span>
        expect(host.innerHTML).toContain(<span class="hljs-string">"First Tab Heading"</span>)

    });

})
</code></pre>
<p>In order to mount the Svelte component, you need to first create a <code>div</code> container and attach that <code>div</code> to the <code>body</code> of the HTML document. Then you need to attach your component to the <code>div</code>. You can then test the <code>innerHTML</code> of the main container to see if you have the required content.</p>
<p>Now this test should pass since you have the <code>First Tab Heading</code> content displayed in the component.</p>
<p>Going through this long process in all the steps might prove to be difficult. So let's add another package to make the job easier. The package is <code>testing-library/svelte</code> and it provides more features to make the assertions easy and less verbose.</p>
<h2 id="heading-how-to-use-the-svelte-testing-library">How to Use the Svelte Testing Library</h2>
<p>First, you'll need to install the library:</p>
<pre><code>npm install -D @testing-library/svelte
</code></pre><p>Let's update the previous test to make it less verbose and let <code>testing-library</code> handle all the heavy lifting for us. You can use the <code>render</code> function to add the component to the testing page.</p>
<pre><code><span class="hljs-keyword">import</span> VerticalTabs <span class="hljs-keyword">from</span> <span class="hljs-string">"./VerticalTabs.svelte"</span>;
<span class="hljs-keyword">import</span> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">'@testing-library/svelte'</span>;

describe(<span class="hljs-string">"VerticalTabs Component"</span>, <span class="hljs-function">() =&gt;</span> {

    test(<span class="hljs-string">"should render the component"</span>, <span class="hljs-function">() =&gt;</span> {

        render(VerticalTabs);

        <span class="hljs-keyword">const</span> firstTabNode = screen.getByText(<span class="hljs-regexp">/First Tab Heading/i</span>)

        expect(firstTabNode).toBeTruthy()
    });

})
</code></pre><p>After the <code>render</code> function, add the component to the testing page. You can use the <code>screen</code> object imported from the library to query the nodes that are rendered.</p>
<p>There are multiple methods inside this object to make testing easy, and you will use one of the methods to get the text in the component.</p>
<p><code>getByText</code> will return the instance of a given text. You are expecting the node to contain some value.</p>
<p>There are three main ways to retrieve the element in the testing library, and each serves a different purpose:</p>
<ol>
<li>getByText – This will throw an error when the text is not found and the test will fail</li>
<li>queryByText – This will return null when the text is not found</li>
<li>findByText – This will also throw an error when the text is not found and you can use it when doing async tests where the element will take some time to appear/disappear</li>
</ol>
<p>You can find a useful summary of these helper functions in the <a target="_blank" href="https://testing-library.com/docs/queries/about">official docs page</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/QueriesSummary.png" alt="Image" width="600" height="400" loading="lazy">
<em>Summary screenshot from Official docs of testing library</em></p>
<p>You can find more details on this API in this <a target="_blank" href="https://testing-library.com/docs/svelte-testing-library/api">official page</a>.</p>
<h2 id="heading-how-to-build-the-tab-switching-feature">How to Build the Tab Switching Feature</h2>
<p>We will start adding the feature to switch tabs in the component and test the component by writing the test first.</p>
<h3 id="heading-red-stage">Red stage</h3>
<p>Let's write a test the switch to a different tab on click of the "Second Tab" list item. </p>
<p>Since we don't have this functionality implemented, we will fail this test first and that's okay. Once we fail the test, we should write the logic to make it pass in the next step. </p>
<p>So let's write a failing test:</p>
<pre><code>test(<span class="hljs-string">"should switch tabs"</span>, <span class="hljs-keyword">async</span> () =&gt; {
        render(VerticalTabs);

        <span class="hljs-keyword">const</span> secondTabElement = screen.getByText(<span class="hljs-regexp">/Second Tab/i</span>);

        fireEvent.click(secondTabElement)

        <span class="hljs-keyword">await</span> screen.findByText(<span class="hljs-regexp">/Second Tab Heading/i</span>);
})
</code></pre><p>We are using the <code>fireEvent</code> from the testing library to simulate the click of the element. We can make the test <code>async</code> and <code>await</code> for the element since the text will change after the element is clicked.</p>
<p>You should have a failing test now:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/TestFailing.png" alt="Image" width="600" height="400" loading="lazy">
<em>Test failing unable to find the content</em></p>
<h3 id="heading-green-stage">Green stage</h3>
<p>Let's add the logic to change the tab in the Svelte component. We can do that easily by creating a <code>selectedIndex</code> variable and changing its value based on the selected tab.</p>
<pre><code>&lt;script lang=<span class="hljs-string">"ts"</span>&gt;
    <span class="hljs-keyword">let</span> selectedIndex = <span class="hljs-number">0</span>;

    <span class="hljs-keyword">const</span> changeSecondTab = <span class="hljs-function">() =&gt;</span> {
        selectedIndex = <span class="hljs-number">1</span>;
    }
&lt;/script&gt;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"vertical-tab-container"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"vertical-tab"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>First Tab<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{()</span> =&gt;</span> changeSecondTab()}&gt;Second Tab<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>Third Tab<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"vertical-tab-content"</span>&gt;</span>
        {#if selectedIndex == 0}
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>First Tab Heading<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        {:else if selectedIndex == 1}
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Second Tab Heading<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        {/if}
    <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>
</code></pre><p><strong>Note: This is not the best implementation.</strong> It is only meant for showing that you can do minimal work to make the test pass. We will clean it up in the next stage</p>
<p>We have a method <code>changeSecondTab</code> that will change the <code>selectedIndex</code> value to 1 which will make the <code>#if</code> condition to change the tab. Even though it is not the best solution to handle all cases, we have a starting point.</p>
<p>Let's look at the test now. It should be working:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/TestPassed.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-refactor">Refactor</h3>
<p>Let's fix the implementation to make it more generic and have it work for all three tabs. We can also add an indicator to show which tab is currently selected.</p>
<pre><code class="lang-javascript">&lt;script lang=<span class="hljs-string">"ts"</span>&gt;
    <span class="hljs-keyword">let</span> selectedIndex = <span class="hljs-number">0</span>;

    <span class="hljs-keyword">const</span> changeTab = <span class="hljs-function">(<span class="hljs-params">index: number</span>) =&gt;</span> {
        selectedIndex = index;
    }
&lt;/script&gt;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"vertical-tab-container"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"vertical-tab"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class:selected</span>=<span class="hljs-string">{selectedIndex</span> == <span class="hljs-string">0}</span> 
            <span class="hljs-attr">on:click</span>=<span class="hljs-string">{()</span> =&gt;</span> changeTab(0)}&gt;First Tab<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class:selected</span>=<span class="hljs-string">{selectedIndex</span> == <span class="hljs-string">1}</span> 
            <span class="hljs-attr">on:click</span>=<span class="hljs-string">{()</span> =&gt;</span> changeTab(1)}&gt;Second Tab<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class:selected</span>=<span class="hljs-string">{selectedIndex</span> == <span class="hljs-string">2}</span> 
            <span class="hljs-attr">on:click</span>=<span class="hljs-string">{()</span> =&gt;</span> changeTab(2)}&gt;Third Tab<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"vertical-tab-content"</span>&gt;</span>
        {#if selectedIndex == 0}
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>First Tab Heading<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        {:else if selectedIndex == 1}
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Second Tab Heading<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        {:else}
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Third Tab Heading<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        {/if}
    <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>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
    ...
    <span class="hljs-selector-class">.selected</span> {
        <span class="hljs-attribute">color</span>: blue;
    }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span></span>
</code></pre>
<p>We have created a method <code>changeTab</code> that will be called on the click of each element and then change the <code>selectedIndex</code>. This will cause the <code>#if</code> logic to change the tab based on its value.</p>
<p>We also have <code>class:selected</code> followed by an expression and when the expression becomes true, the <code>selected</code> class is added to the element. So we have added one more CSS class and we made the text colour blue to show the selected tab.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/FinalComponent.png" alt="Image" width="600" height="400" loading="lazy">
<em>Finished vertical tabs component</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/image-375.png" alt="Image" width="600" height="400" loading="lazy">
<em>Test after finishing refactor</em></p>
<p>We have now confirmed that the test is also passing after the refactor. You can continue this process to add more tests and features to your component.</p>
<h2 id="heading-how-to-add-animation">How to Add Animation</h2>
<p>Svelte makes it easy to add animation when content is changed. You can make use of the <code>transition</code> directive to add pre-built animation to your application.</p>
<p>So let's add a fly animation when the content changes. You can import the fly animation from <code>svelte/transition</code> and then add it to the element using <code>transition:fly</code>. This will add the default fly animation when the content flies out and new content flies in. Such a neat effect with just a single line of code!</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { fly } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte/transition'</span>;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"vertical-tab-content"</span> &gt;</span>
        {#if selectedIndex == 0}
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">transition:fly</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>First Tab Heading<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        {:else if selectedIndex == 1}
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">transition:fly</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Second Tab Heading<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        {:else}
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">transition:fly</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Third Tab Heading<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        {/if}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p>Animation brings life to your application and helps it stand out. I am a big fan of the simple animation transition system in Svelte.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, you have learned how to create a new component using test-driven development methodology. Please share your feedback on this post and let me know your thoughts.</p>
<p>Thanks for reading! You can contact me on Twitter <a target="_blank" href="https://twitter.com/sriram_thiagar">@sriram_thiagar</a>. I regularly post articles on my blog <a target="_blank" href="https://www.eternaldev.com/">eternaldev.com</a> if you want to read more articles from me.</p>
<p>Hello everyone. I am Sriram, and I work as a Full Stack developer. I like to share my learning with others. I have been <a target="_blank" href="https://www.eternaldev.com/">blogging</a> for more than a year now on my website.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Build your Developer Portfolio and Blog from Scratch with Svelte and GraphCMS – A Complete Guide ]]>
                </title>
                <description>
                    <![CDATA[ By Scott Spence A developer portfolio is a great way to showcase your current skill level to potential employers.  This guide will go from hello world to a fully-featured portfolio project to show your current projects with images and links to source... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-your-developer-portfolio-from-scratch-with-sveltekit-and-graphcms/</link>
                <guid isPermaLink="false">66d8521be0db794d56c01c09</guid>
                
                    <category>
                        <![CDATA[ GitHub ]]>
                    </category>
                
                    <category>
                        <![CDATA[ graphcms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ portfolio ]]>
                    </category>
                
                    <category>
                        <![CDATA[ projects ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Svelte ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 06 Jan 2022 16:12:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/12/simon-abrams-k_T9Zj3SE8k-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Scott Spence</p>
<p>A developer portfolio is a great way to showcase your current skill level to potential employers. </p>
<p>This guide will go from hello world to a fully-featured portfolio project to show your current projects with images and links to source code. You'll also build an accompanying blog where you can detail what you have learned along the way.</p>
<p>Hi 👋, my name is <a target="_blank" href="https://scottspence.com">Scott</a>, and I have been blogging about my journey through web development since July 2016. </p>
<p>I'm a freeCodeCamp alumnus – I started my freeCodeCamp journey back in 2016 – and have been a professional developer since March, 2018. </p>
<p>I have written about <a target="_blank" href="https://www.freecodecamp.org/news/build-a-developer-blog-from-scratch-with-gatsby-and-mdx/">how to build a Gatsby blog from scratch in the past</a> and want to take you through doing the same again, this time with Svelte!</p>
<p>This quite an extensive guide (33 sections!) so I've added a table of content's to help you navigate around the post:</p>
<ul>
<li><a class="post-section-overview" href="#heading-what-were-going-to-build">What we're going to build</a></li>
<li><a class="post-section-overview" href="#heading-whos-this-guide-for">Who's this guide for?</a></li>
<li><a class="post-section-overview" href="#heading-the-stack-what-technology-well-be-using">The stack (what technology we'll be using)</a></li>
<li><a class="post-section-overview" href="#heading-what-is-svelte">What is Svelte?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-sveltekit">What is SvelteKit?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-vite">What is Vite?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-graphql">What is GraphQL?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-graphcms">What is GraphCMS?</a></li>
<li><a class="post-section-overview" href="#heading-how-to-set-up-graphcms">How to Set Up GraphCMS</a></li>
<li><a class="post-section-overview" href="#heading-how-to-query-content">How to Query Content</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-your-svelte-project">How to Create Your Svelte Project</a></li>
<li><a class="post-section-overview" href="#heading-how-to-show-graphql-data-on-the-index-page">How to Show GraphQL Data on the Index Page</a></li>
<li><a class="post-section-overview" href="#heading-how-to-add-markup-for-the-index-page">How to Add Markup for the Index Page</a></li>
<li><a class="post-section-overview" href="#heading-how-to-build-the-first-svelte-component">How to Build the First Svelte Component</a></li>
<li><a class="post-section-overview" href="#heading-how-to-style-in-svelte">How to Style in Svelte</a></li>
<li><a class="post-section-overview" href="#heading-how-to-style-with-tailwind-and-daisyui">How to Style with Tailwind and DaisyUI</a></li>
<li><a class="post-section-overview" href="#heading-how-to-style-the-projects-component">How to Style the Projects Component</a></li>
<li><a class="post-section-overview" href="#heading-how-to-use-the-sveltekit-layout-file">How to Use the SvelteKit <code>__layout</code> File</a></li>
<li><a class="post-section-overview" href="#heading-how-to-build-the-landing-page-with-projects-listed">How to Build the Landing Page with Projects Listed</a></li>
<li><a class="post-section-overview" href="#heading-how-to-use-sveltekit-routing">How to Use SvelteKit Routing</a></li>
<li><a class="post-section-overview" href="#heading-how-to-build-the-blog">How to Build the Blog</a></li>
<li><a class="post-section-overview" href="#heading-how-to-build-the-navbar-and-footer-components">How to Build the Navbar and Footer Components</a></li>
<li><a class="post-section-overview" href="#heading-how-to-add-a-theme-switch">How to Add a Theme Switch</a></li>
<li><a class="post-section-overview" href="#heading-how-to-add-the-about-page">How to Add the About Page</a></li>
<li><a class="post-section-overview" href="#heading-how-to-make-a-sitemap">How to Make a Sitemap</a></li>
<li><a class="post-section-overview" href="#heading-robotstxt">Robots.txt</a></li>
<li><a class="post-section-overview" href="#heading-rss-feed-generation">RSS Feed Generation</a></li>
<li><a class="post-section-overview" href="#heading-email-signup-with-revue">Email Signup with Revue</a></li>
<li><a class="post-section-overview" href="#heading-continuous-deployment-with-vercel">Continuous Deployment with Vercel</a></li>
<li><a class="post-section-overview" href="#heading-google-search-console">Google Search Console</a></li>
<li><a class="post-section-overview" href="#heading-resources">Resources</a></li>
<li><a class="post-section-overview" href="#heading-what-we-have-accomplished">What we have accomplished</a></li>
</ul>
<h2 id="heading-what-were-going-to-build"><strong>What we're going to build</strong></h2>
<p>We will build a fully-featured portfolio and blog with the framework that took the top spot for most loved framework on the Stack Overflow developer survey in 2021 – Svelte.</p>
<p>Using Svelte with GraphCMS means you can control the adding and removing of content on your site without the need to push any changes to Git.</p>
<p>Features:</p>
<ul>
<li>Landing page with projects listed</li>
<li>Blog</li>
<li>Theme switch</li>
<li>Sitemap</li>
<li>RSS feed generation</li>
<li>Robots.txt</li>
<li>Continuous Deployment with Vercel</li>
<li>Build integrations to publish and build the site on content changes</li>
</ul>
<p>There's also an optional email signup section with resources mentioned, but it's not essential to this project we're about to start. You can find resources for that toward the end.</p>
<p>One thing that's typically not covered with guides like this is actual deployment and getting your site on search engines like Google. But here, I'll be going through the whole process so you can have something you will be proud of at the end.</p>
<p>If you want to take it a step further with analytics, then check out my guide on configuring a Svelte project with Fathom Analytics, the privacy-first analytics provider. But I didn't include it here, as it's a paid feature and out of the scope of free.</p>
<h3 id="heading-prerequisites"><strong>Prerequisites</strong></h3>
<p>This guide comes with a few presumptions for the reader:</p>
<ul>
<li>An understanding of HTML, CSS, and JavaScript (the holy trinity of web development)</li>
<li>A GitHub account or similar (GitLab or Bitbucket). Not essential but some hosting services require you to connect a Git repository.</li>
<li>A development environment, Node.js installed on your machine version 14+, a terminal, and a text editor like VS Code.</li>
<li>There are browser options like <a target="_blank" href="https://github.com/features/codespaces">GitHub codespaces</a> or <a target="_blank" href="https://www.gitpod.io/">Gitpod</a> if you don't have these configured.</li>
</ul>
<p>If you don't have a development environment set up there's no need to worry – you can use Gitpod to spin up an environment with this link: <a target="_blank" href="http://gitpod.io/#https://github.com/spences10/sveltekit-skeleton">http://gitpod.io/#https://github.com/spences10/sveltekit-skeleton</a></p>
<p>This will get you started with the SvelteKit skeleton which is created when you use the CLI to create a new SvelteKit project.</p>
<p>I'll be using Microsoft's <a target="_blank" href="https://code.visualstudio.com/">Visual Studio Code</a> (VS Code) along with the VS Code integrated Git client.</p>
<p>There'll be a Git commit at the end of each section. This is optional but helps get you into the habit of committing regularly. It's also useful for when you want to deploy the project at the end. </p>
<h2 id="heading-whos-this-guide-for"><strong>Who's this guide for?</strong></h2>
<p>If you are well on your way through the freeCodeCamp curriculum and want to have something to show where your current skill level is, this guide will be a great accompaniment.</p>
<p>This guide will give you all you need to get started with Svelte and give you the confidence to start making your own projects with it.</p>
<h2 id="heading-the-stack-what-technology-well-be-using">The stack (what technology we'll be using)</h2>
<p>Although I have mentioned a lot of the technology we'll be using, I'll take this opportunity to list out what we'll be using whilst we go through this guide.</p>
<ul>
<li>SvelteKit – the framework we'll use to create the pages and components</li>
<li>Tailwind + daisyUI – how we'll style the project</li>
<li>Tailwind CSS Typography to take care of styling the text content</li>
<li>Marked to convert the Markdown content to HTML </li>
<li>GraphCMS – where we'll store the content for the project details and blog posts</li>
<li>graphql-request – used to query data from the GraphCMS API</li>
</ul>
<h2 id="heading-what-is-svelte"><strong>What is Svelte?</strong></h2>
<p>Svelte is a component framework that allows you to write pages and components in what you're used to – HTML, CSS and JavaScript. It is an open-source front end compiler created by <a target="_blank" href="https://twitter.com/Rich_Harris">Rich Harris</a> and maintained by the Svelte core team members. </p>
<p>Note that it is a compiler. This means that all the HTML, CSS, and JavaScript are built up-front into standalone JavaScript modules that reduces the load on the client (the browser).</p>
<p>It's compiled, rather than shipping a JavaScript run-time to the browser like React or Vue. This produces a much leaner project being shipped to the browser.</p>
<h2 id="heading-what-is-sveltekit">What is SvelteKit?</h2>
<p>SvelteKit is a framework that has the Svelte language at it's core with some added features. These include file-based routing, endpoints, and layouts, to name a few.</p>
<p>Endpoints in SvelteKit are modules that you can write in JavaScript to create HTTP methods (get, post, delete), which can be accessed in SvelteKit via the SvelteKit fetch API. More on this later.</p>
<h2 id="heading-what-is-vite">What is Vite?</h2>
<p>Vite is the build tool you use to compile SvelteKit projects. Vite was created by Evan You, the creator of Vue. Vite is framework-agnostic and a great addition to the SvelteKit toolset.</p>
<h2 id="heading-what-is-graphql"><strong>What is GraphQL?</strong></h2>
<p>GraphQL is a query language for APIs, giving users and clients the flexibility to ask for the data they need when they need it. </p>
<p>A GraphQL query looks like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/12/image-1.png" alt="A GraphQL query displaying the query on the left and the results on the right" width="600" height="400" loading="lazy">
<em>A GraphQL query displaying the query on the left and the results on the right</em></p>
<p>On the left is the <code>query</code> which is for the name field in the project model with the <code>"data"</code> being returned in the resulting query on the right.</p>
<p>The query returned in JavaScript Object Notation (JSON) is what can be consumed by the client (a browser, a mobile app, an in store display or a fridge).</p>
<h2 id="heading-what-is-graphcms"><strong>What is GraphCMS?</strong></h2>
<p>GraphCMS is a headless GraphQL-based Content Management System (CMS) that will let you spin up a back end for your content delivery. </p>
<p>You can do this in minutes with the click of a button from one of the provided templates or you can build your own schema with the simple user interface (UI).</p>
<h2 id="heading-how-to-set-up-graphcms"><strong>How to Set Up GraphCMS</strong></h2>
<p>The team over at GraphCMS created a template for this, so setting up the backend for this is a one click deploy.</p>
<p>You'll need to log into <a target="_blank" href="https://auth.graphcms.com/">GraphCMS</a> first. You can log in with your GitHub account or authenticate via other means.</p>
<p>Once you are logged in you will be presented with your GraphCMS dashboard. If this is your first time using GraphCMS you can scroll down the page to "Developer Portfolio &amp; Blog" in the "Create a new project" section. Select "Developer Portfolio &amp; Blog" and click "+ Create project".</p>
<p>We're then prompted to give our project a name. I'm going to call it "Portfolio and Blog", and the description can be left blank for now. You can pick the data centre closest to you for where your project will be hosted. I'm in the UK so I'll pick the UK data centre.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-5.png" alt="Image" width="600" height="400" loading="lazy">
<em>Pick your data centre</em></p>
<p>Note, if you are adding your own content then toggle "Include template content?" on.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-6.png" alt="Image" width="600" height="400" loading="lazy">
<em>Leave this toggled if you are going to add your content at a later date.</em></p>
<p>As a side note, all content for GraphCMS is served from a globally distributed CDN so there's no need to worry about latency for users not near your specified data centre.</p>
<p>Click the "Create project" button at the bottom of the page.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/12/image-21.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Once the project has finished being provisioned you are presented with what plan you want to use. Pick the community "Free forever" plan.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/12/image-22.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>There will be another prompt to ask you if you want to invite teammates. Just select "Invite later".</p>
<p>The GraphCMS dashboard will look like this. All of the project sections are on the panel on the left. In the next section we'll be taking a look at those.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/12/image-24.png" alt="Image" width="600" height="400" loading="lazy">
<em>The GraphCMS dashboard with arrows pointing to the Schema, Content, Assets and API Playground sections.</em></p>
<h2 id="heading-how-to-query-content">How to Query Content</h2>
<p>Let's make our first GraphQL query. This is going to be a list of all the projects added to the CMS that are in the project model.</p>
<p>Go to the API playground and enter the following GraphQL query into the "New Query" tab in the GraphQL playground.</p>
<pre><code class="lang-graphql"><span class="hljs-keyword">query</span> GetProjects {
  projects {
    name
    slug
    description
    demo
    sourceCode
    image {
      url
    }
  }
}
</code></pre>
<p>This query is selecting the <code>projects</code> model then each field that is contained in that model. </p>
<h2 id="heading-how-to-create-your-svelte-project"><strong>How to Create Your Svelte Project</strong></h2>
<p>If you're using Gitpod you can skip to creating a <code>.env</code> file. If you're setting up locally then let's get started. From the terminal we can create our project with the following <code>npm</code> command:</p>
<pre><code class="lang-bash">npm init svelte@next my-developer-portfolio
</code></pre>
<p>From the CLI I'll pick the following options:</p>
<pre><code class="lang-bash">? Which Svelte app template? › - Use arrow-keys. Return to submit.
    SvelteKit demo app
❯   Skeleton project
? Use TypeScript? › No
? Add ESLint <span class="hljs-keyword">for</span> code linting? › No
? Add Prettier <span class="hljs-keyword">for</span> code formatting? › Yes
</code></pre>
<p>I'll follow the rest of the instructions from the CLI. If you take a look at the output from the CLI you'll also notice a couple of other features we'll be taking advantage of soon. Here's what my output looks like:</p>
<pre><code class="lang-bash">Your project is ready!
✔ Prettier
  https://prettier.io/docs/en/options.html
  https://github.com/sveltejs/prettier-plugin-svelte<span class="hljs-comment">#options</span>

Install community-maintained integrations:
  https://github.com/svelte-add/svelte-adders

Next steps:
  1: <span class="hljs-built_in">cd</span> my-developer-portfolio
  2: npm install (or pnpm install, etc)
  3: git init &amp;&amp; git add -A &amp;&amp; git commit -m <span class="hljs-string">"Initial commit"</span> (optional)
  4: npm run dev -- --open

To close the dev server, hit Ctrl-C

Stuck? Visit us at https://svelte.dev/chat
</code></pre>
<p>Take note of the "Install community-maintained integrations" section with Svelte Adders – we'll be using one of those later for adding Tailwind.</p>
<p>Now to change directory (CD) into the project folder, initialise a Git repository, and install the dependencies:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># cd into project directory</span>
<span class="hljs-built_in">cd</span> my-developer-portfolio
<span class="hljs-comment"># initialise a new git repo and make first commit</span>
git init &amp;&amp; git add -A &amp;&amp; git commit -m <span class="hljs-string">"Initial commit"</span>
<span class="hljs-comment"># install dependencies</span>
npm install <span class="hljs-comment"># or 'npm i' for shorthand</span>
</code></pre>
<p>I'll open my text editor and check out the project. I have VS Code installed so using the <code>code</code> command will open it and the <code>.</code> specified the current directory:</p>
<pre><code class="lang-bash">code .
</code></pre>
<p>Time to check that everything is up and running as expected, so let's spin up the dev server:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># start the dev server</span>
npm run dev
</code></pre>
<p>Now that we've validated everything is working as expected, it's time to make a <code>.env</code> file. This is where the GraphQL API URL is going to live. You can create the file with your text editor user interface (UI) if you choose. I'll be using the following command from the root of my project to create the file:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Ctrl-c to stop the dev server</span>
touch .env
<span class="hljs-built_in">echo</span> VITE_GRAPHQL_API= &gt;&gt; .env
</code></pre>
<p>That command from the terminal is creating a <code>.env</code> file then adding <code>VITE_GRAPHQL_API=</code> into that file.</p>
<p>In the <code>.env</code> file, add the "Content API" URL from the GraphCMS project. </p>
<p>The settings panel can be accessed form the sidebar:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-7.png" alt="Image" width="600" height="400" loading="lazy">
<em>GraphCMS project settings</em></p>
<p>Then "API access": </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-8.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Then click on the "Content API" URL. This will copy it to the clipboard for you:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-9.png" alt="Image" width="600" height="400" loading="lazy">
<em>Select the content API URL</em></p>
<p>Now add that to the <code>.env</code> file. It should now look something like this:</p>
<pre><code class="lang-env">VITE_GRAPHQL_API=https://api-region.graphcms.com/v2/projectid/master
</code></pre>
<h2 id="heading-how-to-show-graphql-data-on-the-index-page">How to Show GraphQL Data on the Index Page</h2>
<p>Let's make our first request to our GraphQL API!</p>
<p>First up, to get some data on the page we're going to make the request to the GraphQL API from the index page.</p>
<p>To do that we'll need to install a couple of dependencies, <code>graphql-request</code> and <code>graphql</code>. <code>graphql-request</code> is what we'll be using to send our GraphQL queries to the GraphQL API. <code>graphql</code> is the JavaScript implementation of the GraphQL language.</p>
<pre><code class="lang-bash">npm i -D graphql-request graphql
</code></pre>
<p>Note the <code>-D</code> in the install command there. That's because Svelte doesn't need any run-time dependencies as it compiles the code upfront before sending it to the browser.</p>
<p>Let's start by adding a script block with the context of module <code>&lt;script context="module"&gt;</code> and import the <code>gql</code> tag and the <code>GraphQLClient</code> from <code>graphql-request</code>. </p>
<p>We'll also define a SvelteKit load function. This is so we can grab the data from the API before the page mounts (loads). </p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">context</span>=<span class="hljs-string">"module"</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">import</span> { gql, GraphQLClient } <span class="hljs-keyword">from</span> <span class="hljs-string">'graphql-request'</span>

  <span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> load = <span class="hljs-keyword">async</span> () =&gt; {

  }
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>
</code></pre>
<p>Inside the SvelteKit <code>load</code> function we can then define a new GraphQL client. The client accepts a URL (the GraphCMS API URL) and an options object. </p>
<p>We're going to put in the <code>VITE_GRAPHQL_API</code> we created earlier. Note that the variable starts with <code>VITE_</code> which means that Vite can use this variable. We'll need to import it with <code>import.meta.env</code>, and it should look a lot like this:</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">context</span>=<span class="hljs-string">"module"</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">import</span> { gql, GraphQLClient } <span class="hljs-keyword">from</span> <span class="hljs-string">'graphql-request'</span>

  <span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> load = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> client = <span class="hljs-keyword">new</span> GraphQLClient(
      <span class="hljs-keyword">import</span>.meta.env.VITE_GRAPHQL_API
    )
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>
</code></pre>
<p>Now that the client is defined we can use it to pass a query to the GraphCMS GraphQL API.</p>
<p>Taking the query we made earlier to query for all projects, we can add that to a <code>query</code> variable to use with the GraphQL client we defined.</p>
<p>The query uses the GraphQL <code>gql</code> language tag inside backticks <code>gql```. Then we can destructure the projects from the</code>await`'ed response we get from the GraphQL client:  </p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">context</span>=<span class="hljs-string">"module"</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">import</span> { gql, GraphQLClient } <span class="hljs-keyword">from</span> <span class="hljs-string">'graphql-request'</span>

  <span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> load = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> client = <span class="hljs-keyword">new</span> GraphQLClient(
      <span class="hljs-keyword">import</span>.meta.env.VITE_GRAPHQL_API
    )

    <span class="hljs-keyword">const</span> query = gql<span class="hljs-string">`
      query GetProjects {
        projects {
          name
          slug
          description
          demo
          sourceCode
          image {
            url
          }
        }
      }
    `</span>

    <span class="hljs-keyword">const</span> { projects } = <span class="hljs-keyword">await</span> client.request(query)
  }
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>
</code></pre>
<p>Now that the client has the query, we can return the data from the response of the client <code>projects</code> and return them as props for the page to use.</p>
<p>The data from the GraphQL API can now be passed to the page as <code>props</code> in the return of the <code>load</code> function: </p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">context</span>=<span class="hljs-string">"module"</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">import</span> { gql, GraphQLClient } <span class="hljs-keyword">from</span> <span class="hljs-string">'graphql-request'</span>

  <span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> load = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> client = <span class="hljs-keyword">new</span> GraphQLClient(
      <span class="hljs-keyword">import</span>.meta.env.VITE_GRAPHQL_API
    )

    <span class="hljs-keyword">const</span> query = gql<span class="hljs-string">`
      query GetProjects {
        projects {
          name
          slug
          description
          demo
          sourceCode
          image {
            url
          }
        }
      }
    `</span>

    <span class="hljs-keyword">const</span> { projects } = <span class="hljs-keyword">await</span> client.request(query)

    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">props</span>: {
        projects,
      },
    }
  }
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>
</code></pre>
<p>Now that the data is being returned we need to bring that into the page.</p>
<p>We can do that in the <code>&lt;script&gt;</code> tags on the page. So yes there two sets of script tags – the first <code>&lt;script context="module"&gt;</code> to run the SvelteKit <code>load</code> function before the page loads (or mounts), then the regular <code>&lt;script&gt;</code> tags to define any JavaScript needed on the <code>index.svelte</code> file and to also to accept the <code>props</code> which is <code>projects</code>.</p>
<p>In the last section here we're accepting the <code>projects</code> returned from the <code>load</code> function with <code>export let projects</code> in the <code>&lt;script&gt;</code> tags. Now that variable can be used in the page.</p>
<p>For illustration purposes I'm adding the <code>projects</code> variable into a <code>&lt;pre&gt;</code> tag and stringifying the results with <code>{JSON.stringify(projects, null, 2)}</code>. This is temporary so that we can validate and visualise the data coming into the page. </p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">context</span>=<span class="hljs-string">"module"</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">import</span> { gql, GraphQLClient } <span class="hljs-keyword">from</span> <span class="hljs-string">'graphql-request'</span>

  <span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> load = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> client = <span class="hljs-keyword">new</span> GraphQLClient(
      <span class="hljs-keyword">import</span>.meta.env.VITE_GRAPHQL_API
    )

    <span class="hljs-keyword">const</span> query = gql<span class="hljs-string">`
      query GetProjects {
        projects {
          name
          slug
          description
          demo
          sourceCode
          image {
            url
          }
        }
      }
    `</span>

    <span class="hljs-keyword">const</span> { projects } = <span class="hljs-keyword">await</span> client.request(query)

    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">props</span>: {
        projects,
      },
    }
  }
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">let</span> projects
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">pre</span>&gt;</span></span><span class="javascript">{<span class="hljs-built_in">JSON</span>.stringify(projects, <span class="hljs-literal">null</span>, <span class="hljs-number">2</span>)}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">pre</span>&gt;</span></span>
</code></pre>
<p>Time to start up the dev server and see how things look now:</p>
<pre><code class="lang-bash">npm run dev
</code></pre>
<p>Here's the output which looks really similar to the Projects GraphQL output in the GraphQL playground we made earlier:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/12/image-48.png" alt="Image" width="600" height="400" loading="lazy">
<em>localhost output after running <code>npm run dev</code></em></p>
<p>I know I really walked you through every step of that one. That's to highlight the different sections of what we're doing.</p>
<p>This will be a similar pattern for the rest of of the project.  </p>
<p>The following steps will look like this: </p>
<ol>
<li>Make a GraphQL query to define the data needed.</li>
<li>Give that query to the GraphQL client.</li>
<li>Work with the returned data from the client in the page.</li>
</ol>
<h3 id="heading-refactor-the-graphql-client">Refactor the GraphQL client</h3>
<p>As we'll be using the GraphQL client in more than one page, it's time to move that out into its own file so that it can be reused throughout the project.</p>
<p>Svelte has a <code>lib</code> folder for files that are reused throughout the project but there's not a folder (or directory if you prefer that term) for that yet – so it's time to create one. We can create a <code>graphql-client.js</code> file for the GraphQL client to go in:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># make the folder</span>
mkdir src/lib
<span class="hljs-comment"># create the file</span>
touch src/lib/graphql-client.js
</code></pre>
<p>Now to move out the client from the index page to the newly created <code>src/lib/graphql-client.js</code> file:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { GraphQLClient } <span class="hljs-keyword">from</span> <span class="hljs-string">'graphql-request'</span>
<span class="hljs-keyword">const</span> GRAPHQL_ENDPOINT = <span class="hljs-keyword">import</span>.meta.env.VITE_GRAPHQL_API

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> client = <span class="hljs-keyword">new</span> GraphQLClient(GRAPHQL_ENDPOINT)
</code></pre>
<p>In the <code>src/routes/index.svelte</code> I can remove the initialisation of the client and import the client from its newly created file in the lib folder. </p>
<p>Here's the difference. If you're not familiar with a Git diff, then the <code>+</code> and <code>-</code> next to the lines means that those lines are added (<code>+</code> ) or removed (<code>-</code>):</p>
<pre><code class="lang-git">&lt;script context="module"&gt;
+  import { client } from '$lib/graphql-client'
-  import { gql, GraphQLClient } from 'graphql-request'
+  import { gql } from 'graphql-request'

  export const load = async () =&gt; {
-   const client = new GraphQLClient(import.meta.env.VITE_GRAPHQL_API)

    const query = gql`
      query GetProjects {
        projects {
          name
          slug
          description
          demo
          sourceCode
          image {
            url
          }
        }
      }
    `

    const { projects } = await client.request(query)

    return {
      props: {
        projects,
      },
    }
  }
&lt;/script&gt;

&lt;script&gt;
  export let projects
&lt;/script&gt;

&lt;pre&gt;{JSON.stringify(projects, null, 2)}&lt;/pre&gt;
</code></pre>
<p>With that done we can start using the refactored client in our index page.</p>
<p>Let's commit our changes to Git before moving onto the next section:</p>
<pre><code class="lang-git">git add .
git commit -m "Show GraphQL data on index page"
</code></pre>
<h2 id="heading-how-to-add-markup-for-the-index-page">How to Add M<strong>arkup</strong> for the Index Page</h2>
<p>Up until now we've really only displayed the data from the API endpoint in a pre tag. Time to change that by breaking up the data returned from the GraphQL API into sections on the index page.</p>
<p>So let's start by removing the <code>&lt;pre&gt;</code> tag, adding in a <code>&lt;h1&gt;</code> for the page title, then in a <code>&lt;div&gt;</code> we can use one of the Svelte expressions to loop through the data with Svelte <code>{#each}</code>.</p>
<p>The each expression takes in the <code>projects</code> object. Then you can work with a variable for that, let's say <code>project</code>, and you can reference the various properties on that variable.</p>
<p>Here's an example of how that could look:</p>
<pre><code class="lang-svelte"><span class="javascript">{</span><span class="hljs-keyword">#each</span><span class="javascript"> projects <span class="hljs-keyword">as</span> project}</span><span class="xml">
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=</span></span><span class="javascript">{project.image[<span class="hljs-number">0</span>].url}</span><span class="xml"><span class="hljs-tag"> <span class="hljs-attr">alt</span>=</span></span><span class="javascript">{project.name}</span><span class="xml"><span class="hljs-tag"> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=</span></span><span class="javascript">{<span class="hljs-string">`/projects/<span class="hljs-subst">${project.slug}</span>`</span>}</span><span class="xml"><span class="hljs-tag">&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span></span><span class="javascript">{project.name}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
          </span><span class="javascript">{project.description.slice(<span class="hljs-number">0</span>, <span class="hljs-number">80</span>)}</span><span class="xml">...
        <span class="hljs-tag">&lt;/<span class="hljs-name">p</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">a</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</span><span class="javascript">{</span><span class="hljs-keyword">/each</span><span class="javascript">}</span>
</code></pre>
<p>To take it a step further we can de-structure the properties from that part of the loop so there's no need to reference the specific properties from <code>project</code>.</p>
<p>Note that the <code>image.url</code> is also being de-structured here as well.</p>
<p>So instead of <code>{#each projects as project}</code> we can do this <code>{#each projects as { name, slug, description, image }}</code>.</p>
<p>Here's how the <code>src/routes/index.svelte</code> file should look now:</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">context</span>=<span class="hljs-string">"module"</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">import</span> { client } <span class="hljs-keyword">from</span> <span class="hljs-string">'$lib/graphql-client'</span>
  <span class="hljs-keyword">import</span> { gql } <span class="hljs-keyword">from</span> <span class="hljs-string">'graphql-request'</span>

  <span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> load = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> query = gql<span class="hljs-string">`
      query GetProjects {
        projects {
          name
          slug
          description
          tags
          demo
          sourceCode
          image {
            url
          }
        }
      }
    `</span>
    <span class="hljs-keyword">const</span> { projects } = <span class="hljs-keyword">await</span> client.request(query)

    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">props</span>: {
        projects,
      },
    }
  }
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">let</span> projects
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Recent Projects by Me<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
  </span><span class="javascript">{</span><span class="hljs-keyword">#each</span><span class="javascript"> projects <span class="hljs-keyword">as</span> { name, slug, description, image }}</span><span class="xml">
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=</span></span><span class="javascript">{image[<span class="hljs-number">0</span>].url}</span><span class="xml"><span class="hljs-tag"> <span class="hljs-attr">alt</span>=</span></span><span class="javascript">{name}</span><span class="xml"><span class="hljs-tag"> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=</span></span><span class="javascript">{<span class="hljs-string">`/projects/<span class="hljs-subst">${slug}</span>`</span>}</span><span class="xml"><span class="hljs-tag">&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span></span><span class="javascript">{name}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
            </span><span class="javascript">{description.slice(<span class="hljs-number">0</span>, <span class="hljs-number">80</span>)}</span><span class="xml">...
          <span class="hljs-tag">&lt;/<span class="hljs-name">p</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">a</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  </span><span class="javascript">{</span><span class="hljs-keyword">/each</span><span class="javascript">}</span><span class="xml">
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<h2 id="heading-how-to-build-the-first-svelte-component">How to Build the First Svelte Component</h2>
<p>What we're going to do now is make our first Svelte component. This will be for the project card we made in the last code block.</p>
<p>This is so we can reuse that code in other parts of the project. So, it's going to be everything inside the <code>{#each}</code> loop we did to display each project on the index page, this section here:</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=</span></span><span class="javascript">{image[<span class="hljs-number">0</span>].url}</span><span class="xml"><span class="hljs-tag"> <span class="hljs-attr">alt</span>=</span></span><span class="javascript">{name}</span><span class="xml"><span class="hljs-tag"> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=</span></span><span class="javascript">{<span class="hljs-string">`/projects/<span class="hljs-subst">${slug}</span>`</span>}</span><span class="xml"><span class="hljs-tag">&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span></span><span class="javascript">{name}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
        </span><span class="javascript">{description.slice(<span class="hljs-number">0</span>, <span class="hljs-number">80</span>)}</span><span class="xml">...
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</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">a</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p>Let's create a <code>lib</code> folder and a <code>project-card.svelte</code> component to go in that folder:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># make components folder</span>
mkdir src/lib/components
<span class="hljs-comment"># create the component file</span>
touch src/lib/components/project-card.svelte
</code></pre>
<p>In that file we can now add in the markup for the project card:</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=</span></span><span class="javascript">{image[<span class="hljs-number">0</span>].url}</span><span class="xml"><span class="hljs-tag"> <span class="hljs-attr">alt</span>=</span></span><span class="javascript">{name}</span><span class="xml"><span class="hljs-tag"> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=</span></span><span class="javascript">{<span class="hljs-string">`/projects/<span class="hljs-subst">${slug}</span>`</span>}</span><span class="xml"><span class="hljs-tag">&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span></span><span class="javascript">{name}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
        </span><span class="javascript">{description.slice(<span class="hljs-number">0</span>, <span class="hljs-number">80</span>)}</span><span class="xml">...
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</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">a</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p>The markup at the moment has the variables for the image URL, the project name, and description. Currently this won't work because those variables are not referenced anywhere.</p>
<p>Inside some <code>&lt;script&gt;</code> tags we can define the variables that are expected by the component.</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">let</span> url = <span class="hljs-string">''</span>
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">let</span> name = <span class="hljs-string">''</span>
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">let</span> slug = <span class="hljs-string">''</span>
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">let</span> description = <span class="hljs-string">''</span>
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</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">img</span> <span class="hljs-attr">src</span>=</span></span><span class="javascript">{url}</span><span class="xml"><span class="hljs-tag"> <span class="hljs-attr">alt</span>=</span></span><span class="javascript">{name}</span><span class="xml"><span class="hljs-tag"> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=</span></span><span class="javascript">{<span class="hljs-string">`/projects/<span class="hljs-subst">${slug}</span>`</span>}</span><span class="xml"><span class="hljs-tag">&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span></span><span class="javascript">{name}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
        </span><span class="javascript">{description.slice(<span class="hljs-number">0</span>, <span class="hljs-number">80</span>)}</span><span class="xml">...
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</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">a</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p>With the component now ready to accept the variables for the project, we can pass them into the component on the index page.</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">context</span>=<span class="hljs-string">"module"</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">import</span> ProjectCard <span class="hljs-keyword">from</span> <span class="hljs-string">'$lib/components/project-card.svelte'</span>
  <span class="hljs-keyword">import</span> { client } <span class="hljs-keyword">from</span> <span class="hljs-string">'$lib/graphql-client'</span>
  <span class="hljs-keyword">import</span> { gql } <span class="hljs-keyword">from</span> <span class="hljs-string">'graphql-request'</span>

  <span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> load = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> query = gql<span class="hljs-string">`
      query GetProjects {
        projects {
          name
          slug
          description
          tags
          demo
          sourceCode
          image {
            url
          }
        }
      }
    `</span>
    <span class="hljs-keyword">const</span> { projects } = <span class="hljs-keyword">await</span> client.request(query)

    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">props</span>: {
        projects,
      },
    }
  }
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">let</span> projects
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Recent Projects by Me<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
  </span><span class="javascript">{</span><span class="hljs-keyword">#each</span><span class="javascript"> projects <span class="hljs-keyword">as</span> { name, slug, description, image }}</span><span class="xml">
    <span class="hljs-tag">&lt;<span class="hljs-name">ProjectCard</span> </span></span><span class="javascript">{name}</span><span class="xml"><span class="hljs-tag"> </span></span><span class="javascript">{description}</span><span class="xml"><span class="hljs-tag"> <span class="hljs-attr">url</span>=</span></span><span class="javascript">{image[<span class="hljs-number">0</span>].url}</span><span class="xml"><span class="hljs-tag"> </span></span><span class="javascript">{slug}</span><span class="xml"><span class="hljs-tag"> /&gt;</span>
  </span><span class="javascript">{</span><span class="hljs-keyword">/each</span><span class="javascript">}</span><span class="xml">
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p>The component is being imported between the <code>&lt;script&gt;</code> tags, and then the individual variables from the loop are being passed into it.</p>
<p>Let's take a quick look at the variables being passed. They could be defined like this:</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ProjectCard</span>
  <span class="hljs-attr">name</span>=</span></span><span class="javascript">{name}</span><span class="xml"><span class="hljs-tag">
  <span class="hljs-attr">description</span>=</span></span><span class="javascript">{description}</span><span class="xml"><span class="hljs-tag">
  <span class="hljs-attr">url</span>=</span></span><span class="javascript">{image[<span class="hljs-number">0</span>].url}</span><span class="xml"><span class="hljs-tag">
  <span class="hljs-attr">slug</span>=</span></span><span class="javascript">{slug}</span><span class="xml"><span class="hljs-tag">
/&gt;</span></span>
</code></pre>
<p>Because the expected props on the component are the same as what's being passed, then there is no need to label the props. So this is what we can use:</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ProjectCard</span> </span></span><span class="javascript">{name}</span><span class="xml"><span class="hljs-tag"> </span></span><span class="javascript">{description}</span><span class="xml"><span class="hljs-tag"> <span class="hljs-attr">url</span>=</span></span><span class="javascript">{image[<span class="hljs-number">0</span>].url}</span><span class="xml"><span class="hljs-tag"> </span></span><span class="javascript">{slug}</span><span class="xml"><span class="hljs-tag"> /&gt;</span></span>
</code></pre>
<p>Note that the <code>image</code> property is an array (as the project can take multiple images) so we're referencing the first index of that array.</p>
<p>Let's commit this before moving onto the next section:</p>
<pre><code class="lang-git">git add .
git commit -m "Add first component"
</code></pre>
<h2 id="heading-how-to-style-in-svelte">How to Style in Svelte</h2>
<p>With Svelte being a superset of HTML, this means that you can style your <code>.svelte</code> files the same way you would in HTML files.</p>
<p>Adding some <code>&lt;style&gt;</code> tags at the bottom of the file means you can style the elements on the page:</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Hello Svelte<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span></span><span class="css">
  <span class="hljs-selector-tag">p</span> {
    <span class="hljs-attribute">color</span>: red;
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">2rem</span>;
  }
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span></span>
</code></pre>
<p>This will style all the <code>&lt;p&gt;</code> elements in that file with red font and a font size of 2rem.</p>
<p>You get a lot of control this way, allowing you to specify stiles to that file alone.</p>
<p>This is just an example, and it's not how I will be doing the styling for this project. I'm instead opting for Tailwind CSS.</p>
<h2 id="heading-how-to-style-with-tailwind-and-daisyui">How to Style with Tailwind and DaisyUI</h2>
<p>Styling is a very opinionated and personal subject, so what I'll be doing may not fit with what you have in mind.</p>
<p>For that reason I'll keep styling to a minimum and try not to focus too much on it.</p>
<p>I'll be using <a target="_blank" href="https://tailwindcss.com/">Tailwind CSS</a> and <a target="_blank" href="https://daisyui.com/">daisyUI</a> for the speed at which I can create components and styles. If this isn't for you, you can continue styling as suggested in the last section.</p>
<p>I am going to be using <code>svelte-add</code> to configure the project to use TailwindCSS. The Svelte Adders project I mentioned earlier does all the configuration for you with an <code>npm</code> command:</p>
<pre><code class="lang-bash">npx svelte-add@latest tailwindcss
<span class="hljs-comment"># install configured dependencies</span>
npm i
</code></pre>
<p>The <code>svelte-add</code> command configured the project for use with Tailwind. It also added a file in <code>src/routes</code> called <code>__layout.svelte</code> – we'll come to this shortly. For now know that it's there, and we will be using it in an upcoming section.</p>
<p>I'm also going to be using a couple of TailwindCSS plugins – these are daisyUI and the TailwindCSS Typography plugin.</p>
<p>daisyUI is a great resource for pre-made components, and you can pick out a number of them from the site. Which is what I'll be doing for the header and footer components.</p>
<p>Tailwind CSS Typography is really useful for styling the content we're getting back from the API. It's a great set of defaults from the Tailwind Labs team.</p>
<p>I'll install them via the terminal:</p>
<pre><code class="lang-bash">npm i -D @tailwindcss/typography daisyui
</code></pre>
<p>Then I can configure them in the <code>tailwind.config.cjs</code> file:</p>
<pre><code class="lang-js">plugins: [
  <span class="hljs-built_in">require</span>(<span class="hljs-string">'@tailwindcss/typography'</span>),
  <span class="hljs-built_in">require</span>(<span class="hljs-string">'daisyui'</span>),
],
</code></pre>
<p>There's some additional configuration needed for the TailwindCSS Typography plugin to remove the max width. Here's what the full <code>tailwind.config.cjs</code> looks like:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> config = {
  <span class="hljs-attr">content</span>: [<span class="hljs-string">'./src/**/*.{html,js,svelte,ts}'</span>],

  <span class="hljs-attr">theme</span>: {
    <span class="hljs-attr">extend</span>: {
      <span class="hljs-attr">typography</span>: {
        <span class="hljs-attr">DEFAULT</span>: {
          <span class="hljs-attr">css</span>: {
            <span class="hljs-attr">maxWidth</span>: <span class="hljs-literal">null</span>,
          },
        },
      },
    },
  },

  <span class="hljs-attr">plugins</span>: [<span class="hljs-built_in">require</span>(<span class="hljs-string">'@tailwindcss/typography'</span>), <span class="hljs-built_in">require</span>(<span class="hljs-string">'daisyui'</span>)],
}

<span class="hljs-built_in">module</span>.exports = config
</code></pre>
<p>Let's spin up the dev server and validate the install. The project font will be different now.</p>
<p>Commit the changes and we'll move onto the next section:</p>
<pre><code class="lang-git">git add .
git commit -m "Add Tailwind CSS and daisyUI"
</code></pre>
<h2 id="heading-how-to-style-the-projects-component">How to Style the Projects Component</h2>
<p>Ok, now I can add in some styles for the <code>src/components/project-card.svelte</code> file.</p>
<p>This uses several Tailwind classes, and will probably be as much as we deviate from the pre-packaged classes we get from daisyUI:</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">let</span> url = <span class="hljs-string">''</span>
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">let</span> name = <span class="hljs-string">''</span>
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">let</span> slug = <span class="hljs-string">''</span>
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">let</span> description = <span class="hljs-string">''</span>
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"relative group card shadow-2xl col-span-2"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=</span></span><span class="javascript">{url}</span><span class="xml"><span class="hljs-tag"> <span class="hljs-attr">alt</span>=</span></span><span class="javascript">{name}</span><span class="xml"><span class="hljs-tag"> <span class="hljs-attr">class</span>=<span class="hljs-string">"object-cover h-full"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=</span></span><span class="javascript">{<span class="hljs-string">`/projects/<span class="hljs-subst">${slug}</span>`</span>}</span><span class="xml"><span class="hljs-tag">&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span>
      <span class="hljs-attr">class</span>=<span class="hljs-string">"absolute bottom-0 left-0 right-0 lg:opacity-0 group-hover:opacity-100 bg-primary p-4 duration-300 text-primary-content"</span>
    &gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"font-bold lg:text-xl"</span>&gt;</span></span><span class="javascript">{name}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-sm lg:text-xl"</span>&gt;</span>
        </span><span class="javascript">{description.slice(<span class="hljs-number">0</span>, <span class="hljs-number">80</span>)}</span><span class="xml">...
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</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">a</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p>On the containing div we're adding a <code>relative</code> position then using the Tailwind <code>group</code> class to apply the <code>group-hover</code> on the div containing the description content.</p>
<p>Because the containing div has a <code>relative</code> position on it we can then <code>absolute</code>ly position the description div at the bottom of the containing div with <code>bottom-0</code>, <code>left-0</code> and <code>right-0</code> so it spans the bottom of the containing div.</p>
<p>The <code>lg:</code> class is so that when the user is on a smaller screen, the div shows regardless of mouse hover.  </p>
<p>Let's commit that to Git an move onto the next section:</p>
<pre><code class="lang-git">git add .
git commit -m "Style Projects component"
</code></pre>
<h2 id="heading-how-to-use-the-sveltekit-layout-file">How to Use the SvelteKit <code>__layout</code> File</h2>
<p>For global styles we can use the special SvelteKit <code>__layout.svelte</code> file. We can use it to control the global styles and also to get external information you want to pass down to any pages or components used in the project. </p>
<p>For now let's add some container classes for responsive screen sizes:</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">import</span> <span class="hljs-string">'../app.css'</span>
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container max-w-3xl mx-auto px-4 mb-20"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">slot</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span></span>
</code></pre>
<p>Commit that to Git, then onto the next section:</p>
<pre><code class="lang-git">git add .
git commit -m "Add layout container CSS classes"
</code></pre>
<h2 id="heading-how-to-build-the-landing-page-with-projects-listed"><strong>How to Build the Landing Page with Projects Listed</strong></h2>
<p>Let's get started with the landing page. On the landing page we're going to want to display some information about the Author and the Projects.</p>
<p>We already have the projects query defined and in use on the <code>src/routes/index.svelte</code> page. We're also going to want to get data from the <code>author</code> model for use in the index page.</p>
<p>What we're going to need to do is create another GraphQL query for the author in the load function of the <code>src/routes/index.svelte</code> page. Let's hop on over to the GraphCMS GraphQL playground and define that now:</p>
<pre><code class="lang-graphql"><span class="hljs-keyword">query</span> GetAuthors {
  authors {
    name
    intro
    bio
    slug
    picture {
      url
    }
  }
}
</code></pre>
<p>Ok, so, we have a projects query and an authors query. Onto getting data with these two queries now!</p>
<p>To achieve this we're going to use the JavaScript <code>[Promise.all](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all)</code> method to get the data from both endpoints and return them for use in the project.</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">context</span>=<span class="hljs-string">"module"</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">import</span> ProjectCard <span class="hljs-keyword">from</span> <span class="hljs-string">'$lib/components/project-card.svelte'</span>
  <span class="hljs-keyword">import</span> { client } <span class="hljs-keyword">from</span> <span class="hljs-string">'$lib/graphql-client'</span>
  <span class="hljs-keyword">import</span> { gql } <span class="hljs-keyword">from</span> <span class="hljs-string">'graphql-request'</span>

  <span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> load = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> authorsQuery = gql<span class="hljs-string">`
      query GetAuthors {
        authors {
          name
          intro
          bio
          slug
          picture {
            url
          }
        }
      }
    `</span>
    <span class="hljs-keyword">const</span> projectsQuery = gql<span class="hljs-string">`
      query GetProjects {
        projects {
          name
          slug
          description
          tags
          demo
          sourceCode
          image {
            url
          }
        }
      }
    `</span>
    <span class="hljs-keyword">const</span> [authorReq, projectsReq] = <span class="hljs-keyword">await</span> <span class="hljs-built_in">Promise</span>.all([
      client.request(authorsQuery),
      client.request(projectsQuery),
    ])
    <span class="hljs-keyword">const</span> { authors } = authorReq
    <span class="hljs-keyword">const</span> { projects } = projectsReq

    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">props</span>: {
        projects,
        authors,
      },
    }
  }
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">let</span> projects
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">let</span> authors
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"font-bold text-center mb-20 text-5xl"</span>&gt;</span>
  Welcome to my Portfolio
<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>

</span><span class="javascript">{</span><span class="hljs-keyword">#each</span><span class="javascript"> authors <span class="hljs-keyword">as</span> { name, intro, <span class="hljs-attr">picture</span>: { url } }</span><span class="xml">}
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex mb-40 items-end"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mr-6"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-3xl mb-4 font-bold tracking-wider"</span>&gt;</span></span><span class="javascript">{name}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-xl mb-4"</span>&gt;</span></span><span class="javascript">{intro}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">p</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">img</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mask mask-squircle h-48"</span> <span class="hljs-attr">src</span>=</span></span><span class="javascript">{url}</span><span class="xml"><span class="hljs-tag"> <span class="hljs-attr">alt</span>=</span></span><span class="javascript">{name}</span><span class="xml"><span class="hljs-tag"> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</span><span class="javascript">{</span><span class="hljs-keyword">/each</span><span class="javascript">}</span><span class="xml">

<span class="hljs-tag">&lt;<span class="hljs-name">div</span>
  <span class="hljs-attr">class</span>=<span class="hljs-string">"grid gap-10 md:grid-cols-4 md:px-10 lg:grid-cols-6 lg:-mx-52"</span>
&gt;</span>
  </span><span class="javascript">{</span><span class="hljs-keyword">#each</span><span class="javascript"> projects <span class="hljs-keyword">as</span> { name, slug, description, image }}</span><span class="xml">
    <span class="hljs-tag">&lt;<span class="hljs-name">ProjectCard</span> </span></span><span class="javascript">{name}</span><span class="xml"><span class="hljs-tag"> </span></span><span class="javascript">{description}</span><span class="xml"><span class="hljs-tag"> <span class="hljs-attr">url</span>=</span></span><span class="javascript">{image[<span class="hljs-number">0</span>].url}</span><span class="xml"><span class="hljs-tag"> </span></span><span class="javascript">{slug}</span><span class="xml"><span class="hljs-tag"> /&gt;</span>
  </span><span class="javascript">{</span><span class="hljs-keyword">/each</span><span class="javascript">}</span><span class="xml">
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p>Wow! There's a lot in here now.</p>
<p>Those two GraphQL queries are really taking up a lot of space in that load function. Let's take a minute to refactor them out of here so they can be used elsewhere. It'll also help clean up this page as it's getting a bit busy now with GraphQL queries taking up most of the file.</p>
<h3 id="heading-how-to-refactor-the-graphql-queries">How to Refactor the GraphQL Queries</h3>
<p>Let's grab those two queries at the top of the file there, these two:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> authorsQuery = gql<span class="hljs-string">`
  query GetAuthors {
    authors {
      name
      intro
      bio
      slug
      picture {
        url
      }
    }
  }
`</span>
<span class="hljs-keyword">const</span> projectsQuery = gql<span class="hljs-string">`
  query GetProjects {
    projects {
      name
      slug
      description
      tags
      demo
      sourceCode
      image {
        url
      }
    }
  }
`</span>
</code></pre>
<p>And add them to their own JavaScript file. Let's create that now:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># create the graphql-queries.js file</span>
touch src/lib/graphql-queries.js
</code></pre>
<p>Then we can take the queries from the <code>src/routes/index.svelte</code> file and add them in there:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { gql } <span class="hljs-keyword">from</span> <span class="hljs-string">'graphql-request'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> authorsQuery = gql<span class="hljs-string">`
  query GetAuthors {
    authors {
      name
      intro
      bio
      slug
      picture {
        url
      }
    }
  }
`</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> projectsQuery = gql<span class="hljs-string">`
  query GetProjects {
    projects {
      name
      slug
      description
      tags
      demo
      sourceCode
      image {
        url
      }
    }
  }
`</span>
</code></pre>
<p>Note that they now have <code>export</code> in front of the <code>const</code>. This is so they can be exported from this file for use in the <code>src/routes.index.svelte</code> file.</p>
<p>In the <code>src/routes.index.svelte</code> I can now import those queries, cleaning up the file a little by removing all the noise of the queries in the load function. Here's what it should look like now:</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">context</span>=<span class="hljs-string">"module"</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">import</span> ProjectCard <span class="hljs-keyword">from</span> <span class="hljs-string">'$lib/components/project-card.svelte'</span>
  <span class="hljs-keyword">import</span> { client } <span class="hljs-keyword">from</span> <span class="hljs-string">'$lib/graphql-client'</span>
  <span class="hljs-keyword">import</span> { authorsQuery, projectsQuery } <span class="hljs-keyword">from</span> <span class="hljs-string">'$lib/graphql-queries'</span>

  <span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> load = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> [authorReq, projectsReq] = <span class="hljs-keyword">await</span> <span class="hljs-built_in">Promise</span>.all([
      client.request(authorsQuery),
      client.request(projectsQuery),
    ])
    <span class="hljs-keyword">const</span> { authors } = authorReq
    <span class="hljs-keyword">const</span> { projects } = projectsReq

    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">props</span>: {
        projects,
        authors,
      },
    }
  }
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">let</span> projects
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">let</span> authors
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">svelte:head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>My Portfolio project<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">svelte:head</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"font-bold text-center mb-20 text-5xl"</span>&gt;</span>
  Welcome to my Portfolio
<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>

</span><span class="javascript">{</span><span class="hljs-keyword">#each</span><span class="javascript"> authors <span class="hljs-keyword">as</span> { name, intro, <span class="hljs-attr">picture</span>: { url } }</span><span class="xml">}
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex mb-40 items-end"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mr-6"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-3xl mb-4 font-bold tracking-wider"</span>&gt;</span></span><span class="javascript">{name}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-xl mb-4"</span>&gt;</span></span><span class="javascript">{intro}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">p</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">img</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mask mask-squircle h-48"</span> <span class="hljs-attr">src</span>=</span></span><span class="javascript">{url}</span><span class="xml"><span class="hljs-tag"> <span class="hljs-attr">alt</span>=</span></span><span class="javascript">{name}</span><span class="xml"><span class="hljs-tag"> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</span><span class="javascript">{</span><span class="hljs-keyword">/each</span><span class="javascript">}</span><span class="xml">

<span class="hljs-tag">&lt;<span class="hljs-name">div</span>
  <span class="hljs-attr">class</span>=<span class="hljs-string">"grid gap-10 md:grid-cols-4 md:px-10 lg:grid-cols-6 lg:-mx-52"</span>
&gt;</span>
  </span><span class="javascript">{</span><span class="hljs-keyword">#each</span><span class="javascript"> projects <span class="hljs-keyword">as</span> { name, slug, description, image }}</span><span class="xml">
    <span class="hljs-tag">&lt;<span class="hljs-name">ProjectCard</span> </span></span><span class="javascript">{name}</span><span class="xml"><span class="hljs-tag"> </span></span><span class="javascript">{description}</span><span class="xml"><span class="hljs-tag"> <span class="hljs-attr">url</span>=</span></span><span class="javascript">{image[<span class="hljs-number">0</span>].url}</span><span class="xml"><span class="hljs-tag"> </span></span><span class="javascript">{slug}</span><span class="xml"><span class="hljs-tag"> /&gt;</span>
  </span><span class="javascript">{</span><span class="hljs-keyword">/each</span><span class="javascript">}</span><span class="xml">
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p>Whoa! What's this <code>&lt;svelte:head&gt;</code> doing here? </p>
<p>The <a target="_blank" href="https://svelte.dev/docs#template-syntax-svelte-head">Svelte Head API</a> allows us to add HTML meta data to the project – so, tags like the page title like in the above example but also meta tags for Google, Facebook, and Twitter. Also <a target="_blank" href="https://webmonetization.org/">monetization</a>.</p>
<p>This implementation will give the browser tab a title of "My Portfolio project".</p>
<p>Apart from the head component being added in here, we're also using the data from the <code>authors</code> query to display the data from the authors model on GraphCMS. </p>
<p>Commit the changes to Git:</p>
<pre><code class="lang-git">git add .
git commit -m "Landing page with projects listed"
</code></pre>
<p>Ok, nice – we've got our landing page sorted.</p>
<h2 id="heading-how-to-use-sveltekit-routing">How to Use SvelteKit Routing</h2>
<p>Now we have a nice landing page with links to projects. But clicking on a link will take us to a 404 page. That's because the route for that page doesn't exist yet.</p>
<p>Let's create that now. We'll be using SvelteKit <a target="_blank" href="https://kit.svelte.dev/docs#routing-pages">file-based routing</a> to do this.</p>
<p>We'll need to create a file which will take the <code>slug</code> from the projects card and use that for the path for the project. We can make the file first:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># make the projects folder</span>
mkdir src/routes/projects
<span class="hljs-comment"># create the [slug].svelte file</span>
touch src/routes/projects/<span class="hljs-string">'[slug]'</span>.svelte
</code></pre>
<p>In the <code>src/routes/projects/[slug].svelte</code> we can define a SvelteKit load function which receives a context variable. Let's first take a look at what we get in the context variable:</p>
<pre><code class="lang-js">&lt;script context=<span class="hljs-string">"module"</span>&gt;
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> load = <span class="hljs-keyword">async</span> context =&gt; {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'====================='</span>)
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'context'</span>, context)
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'====================='</span>)
    <span class="hljs-keyword">return</span> {}
  }
&lt;/script&gt;
</code></pre>
<p>Refreshing the route for <a target="_blank" href="http://localhost:3000/projects/survey-form"><code>localhost:3000/projects/survey-form</code></a> will give output in the terminal like this:</p>
<pre><code class="lang-text">=====================
context {
  url: URL {
    href: 'http://localhost:3000/projects/survey-form',
    origin: 'http://localhost:3000',
    protocol: 'http:',
    username: '',
    password: '',
    host: 'localhost:3000',
    hostname: 'localhost',
    port: '3000',
    pathname: '/projects/survey-form',
    search: '',
    searchParams: URLSearchParams {},
    hash: ''
  },
  params: { slug: 'survey-form' },
  props: {},
  session: [Getter],
  fetch: [AsyncFunction: fetch],
  stuff: {}
}
=====================
</code></pre>
<p>What we're interested in here is the <code>params.slug</code> property which we can use to make a query to the GraphQL API.</p>
<p>Let's hop on over to the GraphQL playground in our GraphCMS project. There, we'll make a query to filter on a project where the <code>slug</code> matches what's being returned from the SvelteKit load function here:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/12/image-42.png" alt="GraphQL query to query for project where slug matches &quot;survey-form&quot;" width="600" height="400" loading="lazy">
<em>GraphQL query to query for project where slug matches "survey-form"</em></p>
<p>In the image, here I've defined a query to filter on the <code>slug</code> field where <code>"survey-form"</code> is being passed to the query.</p>
<p>That's great for that one query, but we want a way to pass variables to the query for each individual project slug we have. Let's take a look at using variables in GraphQL now.</p>
<p>I'll add some parenthesis to the end of the query name, and in those parenthesis I'll define a variable <code>query GetProject($slug: String!) {</code>. The <code>$</code> denotes it's a variable while the <code>: String!</code> denotes the data type of the variable.</p>
<p>Because GraphQL is strongly typed, this needs to be defined so that GraphQL knows how it can use the variable. The exclamation point <code>!</code> at the end indicates that the variable is required for the query to work.</p>
<p>Now I can use the variable in place of the hardcoded <code>"survey-form"</code> I used previously:</p>
<pre><code class="lang-graphql"><span class="hljs-keyword">query</span> GetProject(<span class="hljs-variable">$slug</span>: String!) {
  project(<span class="hljs-symbol">where:</span> {<span class="hljs-symbol">slug:</span> <span class="hljs-variable">$slug</span>}) {
    name
    description
    tags
    demo
    sourceCode
    image {
      url
    }
  }
}
</code></pre>
<p>If I try run that query now I get the following error:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"errors"</span>: [
    {
      <span class="hljs-attr">"message"</span>: <span class="hljs-string">"variable 'slug' must be defined"</span>
    }
  ],
  <span class="hljs-attr">"data"</span>: <span class="hljs-literal">null</span>,
}
</code></pre>
<p>So to get this running in the GraphQL playground here, I can use the "QUERY VARIABLES" panel you may have noticed in the last image. Clicking on that will open the panel and I can add in the variable value there:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/12/image-43.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Now with the slug variable defined in the query panel I'm able to run the query.</p>
<p>Ok that's great! How do I use that in the project?</p>
<p>Great question! I want a way to pass that query variable to the GraphQL client with the query. </p>
<p>We can do this much the same way we did it for the index page. This is the same repeating pattern now – and this time we're going to accept the <code>slug</code> variable to use in the query I've defined.</p>
<p>Before we get to that, let's add that project query to the <code>src/lib/graphql-queries.js</code> file:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { gql } <span class="hljs-keyword">from</span> <span class="hljs-string">'graphql-request'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> authorsQuery = gql<span class="hljs-string">`
  query GetAuthors {
    authors {
      name
      intro
      bio
      slug
      picture {
        url
      }
    }
  }
`</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> projectsQuery = gql<span class="hljs-string">`
  query GetProjects {
    projects {
      name
      slug
      description
      tags
      demo
      sourceCode
      image {
        url
      }
    }
  }
`</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> projectQuery = gql<span class="hljs-string">`
  query GetProject($slug: String!) {
    project(where: { slug: $slug }) {
      name
      slug
      description
      tags
      demo
      sourceCode
      image {
        url
      }
    }
  }
`</span>
</code></pre>
<p> So, there's a bit of repetition going on in this file, now, with the <code>name</code>, <code>slug</code>, <code>description</code>, <code>tags</code>, <code>demo</code>, <code>sourceCode</code> and <code>image.url</code> being repeated in both the <code>Projects</code> and <code>Project</code> queries.</p>
<p>We can use a <a target="_blank" href="https://graphql.org/learn/queries/#fragments">GraphQL fragment</a> here to re-use the fields on the model. Here's what it looks like:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> PROJECT_FRAGMENT = gql<span class="hljs-string">`
  fragment ProjectDetails on Project {
    name
    slug
    description
    tags
    demo
    sourceCode
    image {
      url
    }
  }
`</span>
</code></pre>
<p>All the fields are in one query now, the fragment is named <code>ProjectDetails</code> and that is <code>on</code> the <code>Project</code> model. Now that can be used in the <code>Projects</code> and <code>Project</code> queries by spreading (<code>...</code>) the <code>ProjectDetails</code> into the queries:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { gql } <span class="hljs-keyword">from</span> <span class="hljs-string">'graphql-request'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> authorsQuery = gql<span class="hljs-string">`
  query GetAuthors {
    authors {
      name
      intro
      bio
      slug
      picture {
        url
      }
    }
  }
`</span>

<span class="hljs-keyword">const</span> PROJECT_FRAGMENT = gql<span class="hljs-string">`
  fragment ProjectDetails on Project {
    name
    slug
    description
    tags
    demo
    sourceCode
    image {
      url
    }
  }
`</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> projectsQuery = gql<span class="hljs-string">`
  <span class="hljs-subst">${PROJECT_FRAGMENT}</span>
  query GetProjects {
    projects {
      ...ProjectDetails
    }
  }
`</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> projectQuery = gql<span class="hljs-string">`
  <span class="hljs-subst">${PROJECT_FRAGMENT}</span>
  query GetProject($slug: String!) {
    project(where: { slug: $slug }) {
      ...ProjectDetails
    }
  }
`</span>
</code></pre>
<p>One thing I'm going to need to do now, before we go any further, is use a dependency for the Markdown content of the project description.</p>
<p>This is to take the Markdown content for the project description and turn it into HTML so that it can be presented on the page. I'm going to use <code>marked</code> here:</p>
<pre><code class="lang-bash">npm i -D marked
</code></pre>
<p>Now that the query is defined we can use it in the <code>src/routes/projects/[slug].svelte</code> file:</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">context</span>=<span class="hljs-string">"module"</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">import</span> { client } <span class="hljs-keyword">from</span> <span class="hljs-string">'$lib/graphql-client'</span>
  <span class="hljs-keyword">import</span> { projectQuery } <span class="hljs-keyword">from</span> <span class="hljs-string">'$lib/graphql-queries'</span>
  <span class="hljs-keyword">import</span> { marked } <span class="hljs-keyword">from</span> <span class="hljs-string">'marked'</span>

  <span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> load = <span class="hljs-keyword">async</span> ({ params }) =&gt; {
    <span class="hljs-keyword">const</span> { slug } = params
    <span class="hljs-keyword">const</span> variables = { slug }
    <span class="hljs-keyword">const</span> { project } = <span class="hljs-keyword">await</span> client.request(projectQuery, variables)

    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">props</span>: {
        project,
      },
    }
  }
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">let</span> project
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">svelte:head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>My Portfolio | </span><span class="javascript">{project.name}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">svelte:head</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"sm:-mx-5 md:-mx-10 lg:-mx-20 xl:-mx-38 mb-5"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">img</span>
    <span class="hljs-attr">class</span>=<span class="hljs-string">"rounded-lg"</span>
    <span class="hljs-attr">src</span>=</span></span><span class="javascript">{project.image[<span class="hljs-number">0</span>].url}</span><span class="xml"><span class="hljs-tag">
    <span class="hljs-attr">alt</span>=</span></span><span class="javascript">{project.title}</span><span class="xml"><span class="hljs-tag">
  /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-4xl font-semibold mb-5"</span>&gt;</span></span><span class="javascript">{project.name}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mb-5 flex justify-between"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    </span><span class="javascript">{</span><span class="hljs-keyword">#if</span><span class="javascript"> project.tags}</span><span class="xml">
      </span><span class="javascript">{</span><span class="hljs-keyword">#each</span><span class="javascript"> project.tags <span class="hljs-keyword">as</span> tag}</span><span class="xml">
        <span class="hljs-tag">&lt;<span class="hljs-name">span</span>
          <span class="hljs-attr">class</span>=<span class="hljs-string">"badge badge-primary mr-2 hover:bg-primary-focus cursor-pointer"</span>
          &gt;</span></span><span class="javascript">{tag}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>
        &gt;</span>
      </span><span class="javascript">{</span><span class="hljs-keyword">/each</span><span class="javascript">}</span><span class="xml">
    </span><span class="javascript">{</span><span class="hljs-keyword">/if</span><span class="javascript">}</span><span class="xml">
  <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">"mb-5 prose flex prose-a:text-primary hover:prose-a:text-primary-focus"</span>
&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mr-5"</span> <span class="hljs-attr">href</span>=</span></span><span class="javascript">{project.demo}</span><span class="xml"><span class="hljs-tag">&gt;</span>Demo<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=</span></span><span class="javascript">{project.sourceCode}</span><span class="xml"><span class="hljs-tag">&gt;</span>Source Code<span class="hljs-tag">&lt;/<span class="hljs-name">a</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">article</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"prose prose-xl"</span>&gt;</span>
  </span><span class="javascript">{</span><span class="hljs-keyword">@html</span><span class="javascript"> marked(project.description)}</span><span class="xml">
<span class="hljs-tag">&lt;/<span class="hljs-name">article</span>&gt;</span></span>
</code></pre>
<p>In the <code>src/routes/projects/[slug].svelte</code> file we're doing pretty much the same as we did with the <code>src/routes/index.svelte</code> file except we're using <code>params: { slug }</code> to pass the slug value to the GraphQL client to get the data relating to that slug.</p>
<p><code>{@html}</code> is used to display the contents as HTML. Use this with caution if you do not trust the source of the HTML – but in our case we know we can trust the HTML because we put it there! 😊 </p>
<p>Let's get that committed to Git before moving on:</p>
<pre><code class="lang-git">git add .
git commit -m "Add project page using SvelteKit routing"
</code></pre>
<h3 id="heading-how-to-build-the-projects-index-page">How to Build the Projects Index Page</h3>
<p>Now to create an index for the projects. It's much like the landing page, but this time it's only to list out the projects.</p>
<p>I'll create an index for the projects route:</p>
<pre><code class="lang-bash">touch src/routes/projects/index.svelte
</code></pre>
<p>Now navigating to <code>localhost:3000/projects</code> will show that file.</p>
<p>Time to repeat the pattern used to get the projects list on the index page but without the author information:</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">context</span>=<span class="hljs-string">"module"</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">import</span> ProjectCard <span class="hljs-keyword">from</span> <span class="hljs-string">'$lib/components/project-card.svelte'</span>
  <span class="hljs-keyword">import</span> { client } <span class="hljs-keyword">from</span> <span class="hljs-string">'$lib/graphql-client'</span>
  <span class="hljs-keyword">import</span> { projectsQuery } <span class="hljs-keyword">from</span> <span class="hljs-string">'$lib/graphql-queries'</span>

  <span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> load = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> { projects } = <span class="hljs-keyword">await</span> client.request(projectsQuery)

    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">props</span>: {
        projects,
      },
    }
  }
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">let</span> projects
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">svelte:head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>My Portfolio projects<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">svelte:head</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"font-bold mb-20 text-center text-5xl"</span>&gt;</span>
  Recent Projects by Me
<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span>
  <span class="hljs-attr">class</span>=<span class="hljs-string">"grid gap-10 md:grid-cols-4 md:px-10 lg:grid-cols-6 lg:-mx-52"</span>
&gt;</span>
  </span><span class="javascript">{</span><span class="hljs-keyword">#each</span><span class="javascript"> projects <span class="hljs-keyword">as</span> { name, slug, description, image }, index}</span><span class="xml">
    <span class="hljs-tag">&lt;<span class="hljs-name">ProjectCard</span>
      </span></span><span class="javascript">{name}</span><span class="xml"><span class="hljs-tag">
      </span></span><span class="javascript">{description}</span><span class="xml"><span class="hljs-tag">
      <span class="hljs-attr">url</span>=</span></span><span class="javascript">{image[<span class="hljs-number">0</span>].url}</span><span class="xml"><span class="hljs-tag">
      </span></span><span class="javascript">{index}</span><span class="xml"><span class="hljs-tag">
      </span></span><span class="javascript">{slug}</span><span class="xml"><span class="hljs-tag">
    /&gt;</span>
  </span><span class="javascript">{</span><span class="hljs-keyword">/each</span><span class="javascript">}</span><span class="xml">
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p>Nice! Now navigating to <code>localhost:3000/projects</code> gives us a dedicated projects page.</p>
<p>Let's move on to repeating these patterns we've learned for the blog index page and the individual blog posts.</p>
<p>Commit to Git the current changes before moving on:</p>
<pre><code class="lang-git">git add .
git commit -m "Add projects index page"
</code></pre>
<h2 id="heading-how-to-build-the-blog"><strong>How to Build the Blog</strong></h2>
<p>Time for the blog now. This is pretty much the same approach as with the projects, but let's go through the process again.</p>
<ol>
<li>Make a GraphQL query to define the data needed.</li>
<li>Give that query to the GraphQL client.</li>
<li>Work with the returned data from the client in the page.</li>
</ol>
<p>Make a GraphQL query for the posts. As we'll be following the same pattern as with the projects (query for all projects and filter for a specific project) we can make a GraphQL fragment for the data we want to get, both on all posts and a single post.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> POST_FRAGMENT = gql<span class="hljs-string">`
  fragment PostDetails on Post {
    title
    slug
    date
    content
    tags
    coverImage {
      url
    }
    authors {
      name
    }
  }
`</span>
</code></pre>
<p>We can then use the same pattern as before where we use the fragment in both a Posts and Post query:</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> postsQuery = gql<span class="hljs-string">`
  <span class="hljs-subst">${POST_FRAGMENT}</span>
  query GetPosts {
    posts {
      ...PostDetails
    }
  }
`</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> postQuery = gql<span class="hljs-string">`
  <span class="hljs-subst">${POST_FRAGMENT}</span>
  query GetPost($slug: String!) {
    post(where: { slug: $slug }) {
      ...PostDetails
    }
  }
`</span>
</code></pre>
<p>With the <code>POST_FRAGMENT</code> and <code>postsQuery</code> and <code>postQuery</code> added to the <code>src/lib/graphql-queries.js</code> file we can make a posts route then add in a <code>[slug].svelte</code> file and a <code>index.svelte</code> file.</p>
<pre><code class="lang-bash">mkdir src/routes/posts
touch src/routes/posts/{<span class="hljs-string">'[slug]'</span>.svelte,index.svelte}
</code></pre>
<p>Let's tackle the posts index page first then we can move onto individual posts with the slug file.</p>
<p>The first section we have done a few times now, defining a SvelteKit load function then using the GraphQL client to query for the posts:</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">context</span>=<span class="hljs-string">"module"</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">import</span> { client } <span class="hljs-keyword">from</span> <span class="hljs-string">'$lib/graphql-client'</span>
  <span class="hljs-keyword">import</span> { postsQuery } <span class="hljs-keyword">from</span> <span class="hljs-string">'$lib/graphql-queries'</span>
  <span class="hljs-keyword">import</span> { marked } <span class="hljs-keyword">from</span> <span class="hljs-string">'marked'</span>

  <span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> load = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> { posts } = <span class="hljs-keyword">await</span> client.request(postsQuery)

    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">props</span>: {
        posts,
      },
    }
  }
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">let</span> posts
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">svelte:head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Portfolio | Blog<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">svelte:head</span>&gt;</span></span>
</code></pre>
<p>Now we need to add the markup for the page. Using the daisyUI card classes, we can define a pretty decent looking card, then loop through the posts tags and finally link out to the post page.</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-4xl mb-10 font-extrabold"</span>&gt;</span>Blog posts<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>

</span><span class="javascript">{</span><span class="hljs-keyword">#each</span><span class="javascript"> posts <span class="hljs-keyword">as</span> { title, slug, content, coverImage, tags }}</span><span class="xml">
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card text-center shadow-2xl mb-20"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">figure</span> <span class="hljs-attr">class</span>=<span class="hljs-string">""</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span>
        <span class="hljs-attr">class</span>=<span class="hljs-string">""</span>
        <span class="hljs-attr">src</span>=</span></span><span class="javascript">{coverImage.url}</span><span class="xml"><span class="hljs-tag">
        <span class="hljs-attr">alt</span>=</span></span><span class="javascript">{<span class="hljs-string">`Cover image for <span class="hljs-subst">${title}</span>`</span>}</span><span class="xml"><span class="hljs-tag">
      /&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> <span class="hljs-attr">class</span>=<span class="hljs-string">"card-body prose"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"title"</span>&gt;</span></span><span class="javascript">{title}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      </span><span class="javascript">{</span><span class="hljs-keyword">@html</span><span class="javascript"> marked(content).slice(<span class="hljs-number">0</span>, <span class="hljs-number">150</span>)}</span><span class="xml">
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex justify-center mt-5 space-x-2"</span>&gt;</span>
        </span><span class="javascript">{</span><span class="hljs-keyword">#each</span><span class="javascript"> tags <span class="hljs-keyword">as</span> tag}</span><span class="xml">
          <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"badge badge-primary"</span>&gt;</span></span><span class="javascript">{tag}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
        </span><span class="javascript">{</span><span class="hljs-keyword">/each</span><span class="javascript">}</span><span class="xml">
      <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">"justify-center card-actions"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=</span></span><span class="javascript">{<span class="hljs-string">`/posts/<span class="hljs-subst">${slug}</span>`</span>}</span><span class="xml"><span class="hljs-tag"> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-outline btn-primary"</span>
          &gt;</span>Read <span class="hljs-symbol">&amp;rArr;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</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>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</span><span class="javascript">{</span><span class="hljs-keyword">/each</span><span class="javascript">}</span>
</code></pre>
<p>Time to repeat that pattern again!</p>
<p>SvelteKit load function using the GraphQL client passing in the post query and variable coming from the page params: </p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">context</span>=<span class="hljs-string">"module"</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">import</span> { client } <span class="hljs-keyword">from</span> <span class="hljs-string">'$lib/graphql-client'</span>
  <span class="hljs-keyword">import</span> { postQuery } <span class="hljs-keyword">from</span> <span class="hljs-string">'$lib/graphql-queries'</span>
  <span class="hljs-keyword">import</span> { marked } <span class="hljs-keyword">from</span> <span class="hljs-string">'marked'</span>

  <span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> load = <span class="hljs-keyword">async</span> ({ params }) =&gt; {
    <span class="hljs-keyword">const</span> { slug } = params
    <span class="hljs-keyword">const</span> variables = { slug }
    <span class="hljs-keyword">const</span> { post } = <span class="hljs-keyword">await</span> client.request(postQuery, variables)

    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">props</span>: {
        post,
      },
    }
  }
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">let</span> post

  <span class="hljs-keyword">const</span> { title, date, tags, content, coverImage } = post
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">svelte:head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Blog | </span><span class="javascript">{title}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">svelte:head</span>&gt;</span></span>
</code></pre>
<p>Then for the markup on the page, utilising the Tailwind CSS Typography classes here for beautiful markup:</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"sm:-mx-5 md:-mx-10 lg:-mx-20 xl:-mx-38 mb-5"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">img</span>
    <span class="hljs-attr">class</span>=<span class="hljs-string">"rounded-xl"</span>
    <span class="hljs-attr">src</span>=</span></span><span class="javascript">{coverImage.url}</span><span class="xml"><span class="hljs-tag">
    <span class="hljs-attr">alt</span>=</span></span><span class="javascript">{<span class="hljs-string">`Cover image for <span class="hljs-subst">${title}</span>`</span>}</span><span class="xml"><span class="hljs-tag">
  /&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">"prose prose-xl"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span></span><span class="javascript">{title}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">h1</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">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-secondary text-xs tracking-widest font-semibold"</span>&gt;</span>
  </span><span class="javascript">{<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(date).toDateString()}</span><span class="xml">
<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mb-5 flex justify-between"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    </span><span class="javascript">{</span><span class="hljs-keyword">#if</span><span class="javascript"> tags}</span><span class="xml">
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mt-5 space-x-2"</span>&gt;</span>
        </span><span class="javascript">{</span><span class="hljs-keyword">#each</span><span class="javascript"> tags <span class="hljs-keyword">as</span> tag}</span><span class="xml">
          <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"badge badge-primary"</span>&gt;</span></span><span class="javascript">{tag}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
        </span><span class="javascript">{</span><span class="hljs-keyword">/each</span><span class="javascript">}</span><span class="xml">
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    </span><span class="javascript">{</span><span class="hljs-keyword">/if</span><span class="javascript">}</span><span class="xml">
  <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">article</span> <span class="hljs-attr">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"prose prose-lg"</span>&gt;</span>
  </span><span class="javascript">{</span><span class="hljs-keyword">@html</span><span class="javascript"> marked(content)}</span><span class="xml">
<span class="hljs-tag">&lt;/<span class="hljs-name">article</span>&gt;</span></span>
</code></pre>
<p>Commit our changes now:</p>
<pre><code class="lang-git">git add .
git commit -m "Add posts index page and slug page"
</code></pre>
<p>Ok, now we have a lot of pages on the site to look at, but no way to navigate around them yet.</p>
<h2 id="heading-how-to-build-the-navbar-and-footer-components">How to Build the Navbar and Footer Components</h2>
<p>I'm going to grab some pre-made components now from daisyUI for the <a target="_blank" href="https://daisyui.com/components/footer">footer</a> and <a target="_blank" href="https://daisyui.com/components/navbar">navbar</a>. Let's create the files first before hopping over to the daisyUI site to grab them:</p>
<pre><code class="lang-bash">touch src/lib/components/{footer.svelte,navbar.svelte}
</code></pre>
<p> Those curly braces in that command create both the files for us.</p>
<h3 id="heading-how-to-make-the-footer-component">How to Make the Footer Component</h3>
<p>First up, we can do the footer component. I'll be using the second of the <code>footer footer-center</code> components on the daisyUI components footer section. This is what it looks like:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/12/image-49.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>And here's the markup for that component:</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">footer</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"p-10 footer bg-base-200 text-base-content footer-center"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"grid grid-flow-col gap-4"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"link link-hover"</span>&gt;</span>About us<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span> 
    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"link link-hover"</span>&gt;</span>Contact<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span> 
    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"link link-hover"</span>&gt;</span>Jobs<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span> 
    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"link link-hover"</span>&gt;</span>Press kit<span class="hljs-tag">&lt;/<span class="hljs-name">a</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>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"grid grid-flow-col gap-4"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">"http://www.w3.org/2000/svg"</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"24"</span> <span class="hljs-attr">height</span>=<span class="hljs-string">"24"</span> <span class="hljs-attr">viewBox</span>=<span class="hljs-string">"0 0 24 24"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"fill-current"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">path</span> <span class="hljs-attr">d</span>=<span class="hljs-string">"M24 4.557c-.883.392-1.832.656-2.828.775 1.017-.609 1.798-1.574 2.165-2.724-.951.564-2.005.974-3.127 1.195-.897-.957-2.178-1.555-3.594-1.555-3.179 0-5.515 2.966-4.797 6.045-4.091-.205-7.719-2.165-10.148-5.144-1.29 2.213-.669 5.108 1.523 6.574-.806-.026-1.566-.247-2.229-.616-.054 2.281 1.581 4.415 3.949 4.89-.693.188-1.452.232-2.224.084.626 1.956 2.444 3.379 4.6 3.419-2.07 1.623-4.678 2.348-7.29 2.04 2.179 1.397 4.768 2.212 7.548 2.212 9.142 0 14.307-7.721 13.995-14.646.962-.695 1.797-1.562 2.457-2.549z"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">path</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">"http://www.w3.org/2000/svg"</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"24"</span> <span class="hljs-attr">height</span>=<span class="hljs-string">"24"</span> <span class="hljs-attr">viewBox</span>=<span class="hljs-string">"0 0 24 24"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"fill-current"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">path</span> <span class="hljs-attr">d</span>=<span class="hljs-string">"M19.615 3.184c-3.604-.246-11.631-.245-15.23 0-3.897.266-4.356 2.62-4.385 8.816.029 6.185.484 8.549 4.385 8.816 3.6.245 11.626.246 15.23 0 3.897-.266 4.356-2.62 4.385-8.816-.029-6.185-.484-8.549-4.385-8.816zm-10.615 12.816v-8l8 3.993-8 4.007z"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">path</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span> 
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">"http://www.w3.org/2000/svg"</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"24"</span> <span class="hljs-attr">height</span>=<span class="hljs-string">"24"</span> <span class="hljs-attr">viewBox</span>=<span class="hljs-string">"0 0 24 24"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"fill-current"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">path</span> <span class="hljs-attr">d</span>=<span class="hljs-string">"M9 8h-3v4h3v12h5v-12h3.642l.358-4h-4v-1.667c0-.955.192-1.333 1.115-1.333h2.885v-5h-3.808c-3.596 0-5.192 1.583-5.192 4.615v3.385z"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">path</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">a</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>&gt;</span> 
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Copyright © 2021 - All right reserved by ACME Industries Ltd<span class="hljs-tag">&lt;/<span class="hljs-name">p</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">footer</span>&gt;</span></span>
</code></pre>
<p>One thing to note here: if you don't like the SVGs directly in the HTML here, they can be abstracted out into their own components and imported into the footer file. Because Svelte is a superset of HTML, this makes breaking up large files into manageable components possible.</p>
<p>Let's do that now to reduce the file size and make it easier to parse. So, first I'll create the icon files:</p>
<pre><code class="lang-bash">touch src/lib/components/{twitter-icon.svelte,you-tube-icon.svelte,facebook-icon.svelte}
</code></pre>
<p>Now I can remove the <code>&lt;svg&gt;</code> tags from the footer component, and add them to their respective files.</p>
<p>Here's what the Twitter one looks like. You can repeat this for the remaining components:</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">svg</span>
  <span class="hljs-attr">xmlns</span>=<span class="hljs-string">"http://www.w3.org/2000/svg"</span>
  <span class="hljs-attr">width</span>=<span class="hljs-string">"24"</span>
  <span class="hljs-attr">height</span>=<span class="hljs-string">"24"</span>
  <span class="hljs-attr">viewBox</span>=<span class="hljs-string">"0 0 24 24"</span>
  <span class="hljs-attr">class</span>=<span class="hljs-string">"fill-current"</span>
&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">path</span>
    <span class="hljs-attr">d</span>=<span class="hljs-string">"M24 4.557c-.883.392-1.832.656-2.828.775 1.017-.609 1.798-1.574 2.165-2.724-.951.564-2.005.974-3.127 1.195-.897-.957-2.178-1.555-3.594-1.555-3.179 0-5.515 2.966-4.797 6.045-4.091-.205-7.719-2.165-10.148-5.144-1.29 2.213-.669 5.108 1.523 6.574-.806-.026-1.566-.247-2.229-.616-.054 2.281 1.581 4.415 3.949 4.89-.693.188-1.452.232-2.224.084.626 1.956 2.444 3.379 4.6 3.419-2.07 1.623-4.678 2.348-7.29 2.04 2.179 1.397 4.768 2.212 7.548 2.212 9.142 0 14.307-7.721 13.995-14.646.962-.695 1.797-1.562 2.457-2.549z"</span>
  /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span></span>
</code></pre>
<p>There's a few bit's with this we want to change before we use it in our project here.</p>
<p>In the footer element, change the background from <code>bg-base-200</code> to <code>bg-primary</code> and change <code>text-base-content</code> to <code>text-primary-content</code>.</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">footer</span>
  <span class="hljs-attr">class</span>=<span class="hljs-string">"p-10 footer bg-primary text-primary-content footer-center"</span>
&gt;</span></span>
</code></pre>
<p>Then there's the links to be added in the next section:</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"grid grid-flow-col gap-4"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"link link-hover"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/projects"</span>&gt;</span>Portfolio<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"link link-hover"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/posts"</span>&gt;</span>Blog<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"link link-hover"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/about"</span>&gt;</span>About<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p>You can add in the hard-links to the social providers for now. Although they are available in the Social model.</p>
<p>For the copyright section at the end of the file, I'll add in some JavaScript to get the current year so there's no need to worry about updating this again.</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
  Copyright <span class="hljs-symbol">&amp;copy;</span> </span><span class="javascript">{<span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getFullYear()}</span>`</span>}</span><span class="xml"> - All right reserved
  by ME
<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
</code></pre>
<p>Here's the adjusted file now:</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">import</span> FacebookIcon <span class="hljs-keyword">from</span> <span class="hljs-string">'./facebook-icon.svelte'</span>
  <span class="hljs-keyword">import</span> TwitterIcon <span class="hljs-keyword">from</span> <span class="hljs-string">'./twitter-icon.svelte'</span>
  <span class="hljs-keyword">import</span> YouTubeIcon <span class="hljs-keyword">from</span> <span class="hljs-string">'./you-tube-icon.svelte'</span>
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">footer</span>
  <span class="hljs-attr">class</span>=<span class="hljs-string">"p-10 footer bg-primary text-primary-content footer-center"</span>
&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"grid grid-flow-col gap-4"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"link link-hover"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/projects"</span>&gt;</span>Portfolio<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"link link-hover"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/posts"</span>&gt;</span>Blog<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"link link-hover"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/about"</span>&gt;</span>About<span class="hljs-tag">&lt;/<span class="hljs-name">a</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>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"grid grid-flow-col gap-4"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://twitter.com"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">TwitterIcon</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://youtube.com"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">YouTubeIcon</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://facebook.com"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">FacebookIcon</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">a</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>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
      Copyright <span class="hljs-symbol">&amp;copy;</span> </span><span class="javascript">{<span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getFullYear()}</span>`</span>}</span><span class="xml"> - All right reserved
      by ME
    <span class="hljs-tag">&lt;/<span class="hljs-name">p</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">footer</span>&gt;</span></span>
</code></pre>
<p>With the imported SVGs there's a lot of noise removed from the file and it's a lot nicer to read.</p>
<p>Now that we have our footer component we're going to want to have it persisted across route (page) changes. The <code>__layout.svelte</code> file is the perfect place for this so let's go and add it in there:</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">import</span> Footer <span class="hljs-keyword">from</span> <span class="hljs-string">'$lib/components/footer.svelte'</span>
  <span class="hljs-keyword">import</span> <span class="hljs-string">'../app.css'</span>
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container max-w-3xl mx-auto px-4 mb-20"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">slot</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">Footer</span> /&gt;</span></span>
</code></pre>
<p>Let's commit our footer component to Git then move onto the next section:</p>
<pre><code class="lang-git">git add .
git commit -m "Add footer component"
</code></pre>
<h3 id="heading-how-to-make-the-navbar-component">How to Make the Navbar Component</h3>
<p>Now for the navbar component, I'll be using the second to last of the <code>navbar</code> components on the daisyUI components navbar section. This is what it looks like:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/12/image-50.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>There's a lot of SVGs in this example that I'm not going to be using, so I'll remove them. Keep them if you prefer, but for the sake of readability I'll be removing them. There only really needs to be links in there for the Portfolio page, Blog page, and the About page.</p>
<p>Here's what the markup looks like for it with the SVGs removed:</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>
  <span class="hljs-attr">class</span>=<span class="hljs-string">"navbar mb-2 shadow-lg bg-neutral text-neutral-content rounded-box"</span>
&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex-1 px-2 mx-2"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-lg font-bold"</span>&gt;</span>Portfolio and Blog<span class="hljs-tag">&lt;/<span class="hljs-name">span</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">"flex-none hidden px-2 mx-2 lg:flex"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex items-stretch"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-ghost btn-sm rounded-btn"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/projects"</span>&gt;</span>
        Portfolio
      <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-ghost btn-sm rounded-btn"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/posts"</span>
        &gt;</span>Blog<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>
      &gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-ghost btn-sm rounded-btn"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/about"</span>
        &gt;</span>About<span class="hljs-tag">&lt;/<span class="hljs-name">a</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>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p>Note that I have added <code>href</code> tags here to point to the various pages in the project.</p>
<p>We should add that in the same place as the footer in the <code>__layout.svelte</code> file so we can see the changes as we go through building this component:</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">import</span> Footer <span class="hljs-keyword">from</span> <span class="hljs-string">'$lib/components/footer.svelte'</span>
  <span class="hljs-keyword">import</span> Navbar <span class="hljs-keyword">from</span> <span class="hljs-string">'$lib/components/navbar.svelte'</span>
  <span class="hljs-keyword">import</span> <span class="hljs-string">'../app.css'</span>
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">Navbar</span> /&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container max-w-3xl mx-auto px-4 mb-20"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">slot</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">Footer</span> /&gt;</span></span>
</code></pre>
<p>Some more changes to add to this now: I'll increase <code>mb-2</code> up to <code>mb-16</code>, and also I'll remove <code>rounded-box</code> and replace it with a sticky class so the navbar persists on scrolling through long pages <code>sticky top-0 z-10</code>. </p>
<p>One last thing to do is replace the <code>&lt;span&gt;</code> tag with "Portfolio and Blog" in it to an <code>a</code> tag so that we can navigate back to the home page by clicking there:</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-lg font-bold"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span>&gt;</span>Portfolio and Blog<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span></span>
</code></pre>
<p>Here's what the file looks like now:</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>
  <span class="hljs-attr">class</span>=<span class="hljs-string">"navbar mb-16 shadow-lg bg-neutral text-neutral-content sticky top-0 z-10"</span>
&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex-1 px-2 mx-2"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-lg font-bold"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span>&gt;</span>Portfolio and Blog<span class="hljs-tag">&lt;/<span class="hljs-name">a</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">"flex-none hidden px-2 mx-2 lg:flex"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex items-stretch"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-ghost btn-sm rounded-btn"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/projects"</span>&gt;</span>
        Portfolio
      <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-ghost btn-sm rounded-btn"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/posts"</span>
        &gt;</span>Blog<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>
      &gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-ghost btn-sm rounded-btn"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/about"</span>
        &gt;</span>About<span class="hljs-tag">&lt;/<span class="hljs-name">a</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>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p>Very nice! But wait – what about smaller screen sizes? You may have noticed that if you're on a smaller screen, the links for Portfolio, Blog, and About are missing.</p>
<p>In the class for the containing div on the links <code>flex-none hidden px-2 mx-2 lg:flex</code>, this is going to hide the elements until the screen size gets to the large breakpoint (<code>lg:</code>), then the display will be set to <code>flex</code>.</p>
<p>Let's use some additional daisyUI classes from the dropdown section to show when the screen size is below <code>lg:</code> </p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"dropdown dropdown-left lg:hidden"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">tabindex</span>=<span class="hljs-string">"0"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"m-1 btn"</span>&gt;</span>Links<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>
    <span class="hljs-attr">tabindex</span>=<span class="hljs-string">"0"</span>
    <span class="hljs-attr">class</span>=<span class="hljs-string">"bg-neutral rounded-box shadow text-neutral-content p-2 w-52 menu dropdown-content "</span>
  &gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-ghost btn-sm rounded-btn"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/projects"</span>&gt;</span>
      Portfolio
    <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-ghost btn-sm rounded-btn"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/posts"</span>&gt;</span>
      Blog
    <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-ghost btn-sm rounded-btn"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/about"</span>&gt;</span>
      About
    <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>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p>So when the screen size is below the <code>lg:</code> Tailwind breakpoint the above <code>dropdown</code>, classes will be shown.</p>
<p>Here's what the full file looks like:</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>
  <span class="hljs-attr">class</span>=<span class="hljs-string">"navbar mb-16 shadow-lg bg-neutral text-neutral-content sticky top-0 z-10"</span>
&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex-1 px-2 mx-2"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-lg font-bold"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span>&gt;</span>Portfolio and Blog<span class="hljs-tag">&lt;/<span class="hljs-name">a</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">"dropdown dropdown-left lg:hidden"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">tabindex</span>=<span class="hljs-string">"0"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"m-1 btn"</span>&gt;</span>Links<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>
      <span class="hljs-attr">tabindex</span>=<span class="hljs-string">"0"</span>
      <span class="hljs-attr">class</span>=<span class="hljs-string">"bg-neutral rounded-box shadow text-neutral-content p-2 w-52 menu dropdown-content "</span>
    &gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-ghost btn-sm rounded-btn"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/projects"</span>&gt;</span>
        Portfolio
      <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-ghost btn-sm rounded-btn"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/posts"</span>&gt;</span>
        Blog
      <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-ghost btn-sm rounded-btn"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/about"</span>&gt;</span>
        About
      <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>
  <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">"flex-none hidden px-2 mx-2 lg:flex"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex items-stretch"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-ghost btn-sm rounded-btn"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/projects"</span>&gt;</span>
        Portfolio
      <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-ghost btn-sm rounded-btn"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/posts"</span>
        &gt;</span>Blog<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>
      &gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-ghost btn-sm rounded-btn"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/about"</span>
        &gt;</span>About<span class="hljs-tag">&lt;/<span class="hljs-name">a</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>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p>Sweet! We've now got a nice responsive nav menu for mobile users.</p>
<p>Time to commit the changes we've made to Git:</p>
<pre><code class="lang-git">git add .
git commit -m "Add navbar component"
</code></pre>
<p>Footer and navbar sorted, now let's move onto the theme switch.</p>
<h2 id="heading-how-to-add-a-theme-switch"><strong>How to Add a Theme Switch</strong></h2>
<p>All modern sites have a theme switch, so let's take a look at implementing that on our site. Saadeghi (the creator of daisyUI) has made the really nice package to take care of this for us called <a target="_blank" href="https://github.com/saadeghi/theme-change"><code>theme-change</code></a> so we should install that now:</p>
<pre><code class="lang-bash">npm i -D theme-change
</code></pre>
<p>Now we can use that in the <code>__layout.svelte</code> file like this:</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">import</span> Footer <span class="hljs-keyword">from</span> <span class="hljs-string">'$lib/components/footer.svelte'</span>
  <span class="hljs-keyword">import</span> Navbar <span class="hljs-keyword">from</span> <span class="hljs-string">'$lib/components/navbar.svelte'</span>
  <span class="hljs-keyword">import</span> { onMount } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte'</span>
  <span class="hljs-keyword">import</span> { themeChange } <span class="hljs-keyword">from</span> <span class="hljs-string">'theme-change'</span>
  <span class="hljs-keyword">import</span> <span class="hljs-string">'../app.css'</span>

  onMount(<span class="hljs-keyword">async</span> () =&gt; {
    themeChange(<span class="hljs-literal">false</span>)
  })
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">Navbar</span> /&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container max-w-3xl mx-auto px-4 mb-20"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">slot</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">Footer</span> /&gt;</span></span>
</code></pre>
<p>So, let's break this down and see what's happening here. The <code>onMount</code> is code run once the page is visible in the browser (once it's loaded/mounted). Once the page has loaded then we're initialising <code>themeChange</code>. This will change the <code>data-act-class</code> for the desired theme.</p>
<p>Currently there's no way to set it, so let's change that now on the <code>src/app.html</code> 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> <span class="hljs-attr">data-theme</span>=<span class="hljs-string">"dracula"</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">"description"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">""</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"icon"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/favicon.png"</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=device-width, initial-scale=1"</span>
    /&gt;</span>
    %svelte.head%
  <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">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"svelte"</span>&gt;</span>%svelte.body%<span class="hljs-tag">&lt;/<span class="hljs-name">div</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>Here we're adding the default theme of Dracula on the containing <code>html</code> for the whole project with <code>data-theme="dracula"</code>. You can play about with this with all the provided themes from daisyUI – try changing <code>dracula</code> to <code>corporate</code> and see it change!</p>
<p>Ok, that's nice, but how do I change it? Right – let's do that now. Rather than fill up the post with more code I'm going to link to a GitHub repository that has it already packaged up for us in <a target="_blank" href="https://github.com/spences10/sveltekit-theme-switch/blob/main/src/lib/theme-select.svelte">SvelteKit theme switch</a>. That component is an HTML select element that has all the daisyUI themes listed in it.</p>
<p>Copy the contents of that file and add it to a <code>theme-select.svelte</code> component, which doesn't exist yet – so, let's create that now:</p>
<pre><code class="lang-bash">touch src/lib/components/theme-select.svelte
</code></pre>
<p>Remove the <code>class="mb-8"</code> from the containing div and add in some additional styles to the select element. Here's the diff:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/12/image-55.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Now that we have a theme select component, we should add it somewhere accessible throughout the project. Where do you think that should go? You guessed it – the <code>navbar.svelte</code> file:</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">import</span> ThemeSelect <span class="hljs-keyword">from</span> <span class="hljs-string">'./theme-select.svelte'</span>
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span>
  <span class="hljs-attr">class</span>=<span class="hljs-string">"navbar mb-16 shadow-lg bg-neutral text-neutral-content sticky top-0 z-10"</span>
&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex-1 px-2 mx-2"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-lg font-bold"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span>&gt;</span> Portfolio and Blog <span class="hljs-tag">&lt;/<span class="hljs-name">a</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">"dropdown dropdown-left lg:hidden"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">tabindex</span>=<span class="hljs-string">"0"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"m-1 btn"</span>&gt;</span>Links<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>
      <span class="hljs-attr">tabindex</span>=<span class="hljs-string">"0"</span>
      <span class="hljs-attr">class</span>=<span class="hljs-string">"bg-neutral rounded-box shadow text-neutral-content p-2 w-52 menu dropdown-content "</span>
    &gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-ghost btn-sm rounded-btn"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/projects"</span>&gt;</span>
        Portfolio
      <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-ghost btn-sm rounded-btn"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/posts"</span>&gt;</span>
        Blog
      <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-ghost btn-sm rounded-btn"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/about"</span>&gt;</span>
        About
      <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>
  <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">"flex-none hidden px-2 mx-2 lg:flex"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex items-stretch"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-ghost btn-sm rounded-btn"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/projects"</span>&gt;</span>
        Portfolio
      <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-ghost btn-sm rounded-btn"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/posts"</span>&gt;</span>
        Blog
      <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-ghost btn-sm rounded-btn"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/about"</span>&gt;</span>
        About
      <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"px-4"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">ThemeSelect</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>&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>&gt;</span></span>
</code></pre>
<p>So here, we're importing the <code>ThemeSelect</code> component and adding in a containing div for the theme select at the end of our pages list.</p>
<p>You can also add it so it is available on mobile view if you so choose.</p>
<p>Commit the changes to Git:</p>
<pre><code class="lang-git">git add .
git commit -m "Add theme select to navbar"
</code></pre>
<h2 id="heading-how-to-add-the-about-page">How to Add the About Page</h2>
<p>Let's add in that about page we're linking to in the navbar.</p>
<pre><code class="lang-bash">touch src/routes/about.svelte
</code></pre>
<p>In this page we can use the <code>authorsQuery</code> we created for the home page to display the author information. Here's the full file:</p>
<pre><code class="lang-svelte"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">context</span>=<span class="hljs-string">"module"</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">import</span> { client } <span class="hljs-keyword">from</span> <span class="hljs-string">'$lib/graphql-client'</span>
  <span class="hljs-keyword">import</span> { authorsQuery } <span class="hljs-keyword">from</span> <span class="hljs-string">'$lib/graphql-queries'</span>
  <span class="hljs-keyword">import</span> { marked } <span class="hljs-keyword">from</span> <span class="hljs-string">'marked'</span>

  <span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> load = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> { authors } = <span class="hljs-keyword">await</span> client.request(authorsQuery)

    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">props</span>: {
        authors,
      },
    }
  }
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span></span><span class="javascript">
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">let</span> authors
  <span class="hljs-keyword">const</span> {
    name,
    intro,
    bio,
    <span class="hljs-attr">picture</span>: { url },
  } = authors[<span class="hljs-number">0</span>]
</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">svelte:head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>My Portfolio project | About </span><span class="javascript">{name}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">svelte:head</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"font-bold text-center mb-20 text-5xl"</span>&gt;</span>About Me<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex mb-40 items-end"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mr-6"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-3xl mb-4 font-bold tracking-wider"</span>&gt;</span></span><span class="javascript">{name}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-xl mb-4"</span>&gt;</span></span><span class="javascript">{intro}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">p</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">img</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mask mask-squircle h-48"</span> <span class="hljs-attr">src</span>=</span></span><span class="javascript">{url}</span><span class="xml"><span class="hljs-tag"> <span class="hljs-attr">alt</span>=</span></span><span class="javascript">{name}</span><span class="xml"><span class="hljs-tag"> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">article</span> <span class="hljs-attr">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"prose prose-lg"</span>&gt;</span>
  </span><span class="javascript">{</span><span class="hljs-keyword">@html</span><span class="javascript"> marked(bio)}</span><span class="xml">
<span class="hljs-tag">&lt;/<span class="hljs-name">article</span>&gt;</span></span>
</code></pre>
<p>Now to commit those changes to Git:</p>
<pre><code class="lang-git">git add .
git commit -m "Add about page"
</code></pre>
<h2 id="heading-how-to-make-a-sitemap">How to Make a Sitemap</h2>
<p><strong>OPTIONAL</strong>: Let search engines know what's on your site. A sitemap will help web crawlers know the contents of your site.</p>
<p>I have made an <a target="_blank" href="https://scottspence.com/posts/make-a-sitemap-with-sveltekit">extensive post</a> on how to create a sitemap with SvelteKit if you want to take a look at that for more detail.</p>
<p>This is a SvelteKit endpoint that will return an XML file detailing the contents of the site.</p>
<p>If you want to create one, then make a file for it:</p>
<pre><code class="lang-bash">touch src/routes/sitemap.xml.js
</code></pre>
<p>Here's the full file:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { client } <span class="hljs-keyword">from</span> <span class="hljs-string">'$lib/graphql-client'</span>
<span class="hljs-keyword">import</span> { gql } <span class="hljs-keyword">from</span> <span class="hljs-string">'graphql-request'</span>

<span class="hljs-keyword">const</span> website = <span class="hljs-string">'https://www.myporfolioproject.com'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> get = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">const</span> query = gql<span class="hljs-string">`
    query Posts {
      posts {
        title
        slug
      }
    }
  `</span>
  <span class="hljs-keyword">const</span> { posts } = <span class="hljs-keyword">await</span> client.request(query)
  <span class="hljs-keyword">const</span> pages = [<span class="hljs-string">`about`</span>]
  <span class="hljs-keyword">const</span> body = sitemap(posts, pages)

  <span class="hljs-keyword">const</span> headers = {
    <span class="hljs-string">'Cache-Control'</span>: <span class="hljs-string">'max-age=0, s-maxage=3600'</span>,
    <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/xml'</span>,
  }
  <span class="hljs-keyword">return</span> {
    headers,
    body,
  }
}

<span class="hljs-keyword">const</span> sitemap = <span class="hljs-function">(<span class="hljs-params">
  posts,
  pages
</span>) =&gt;</span> <span class="hljs-string">`&lt;?xml version="1.0" encoding="UTF-8" ?&gt;
&lt;urlset
  xmlns="https://www.sitemaps.org/schemas/sitemap/0.9"
  xmlns:news="https://www.google.com/schemas/sitemap-news/0.9"
  xmlns:xhtml="https://www.w3.org/1999/xhtml"
  xmlns:mobile="https://www.google.com/schemas/sitemap-mobile/1.0"
  xmlns:image="https://www.google.com/schemas/sitemap-image/1.1"
  xmlns:video="https://www.google.com/schemas/sitemap-video/1.1"
&gt;
  &lt;url&gt;
    &lt;loc&gt;<span class="hljs-subst">${website}</span>&lt;/loc&gt;
    &lt;changefreq&gt;daily&lt;/changefreq&gt;
    &lt;priority&gt;0.7&lt;/priority&gt;
  &lt;/url&gt;
  <span class="hljs-subst">${pages
    .map(
      page =&gt; <span class="hljs-string">`
  &lt;url&gt;
    &lt;loc&gt;<span class="hljs-subst">${website}</span>/<span class="hljs-subst">${page}</span>&lt;/loc&gt;
    &lt;changefreq&gt;daily&lt;/changefreq&gt;
    &lt;priority&gt;0.7&lt;/priority&gt;
  &lt;/url&gt;
  `</span>
    )
    .join(<span class="hljs-string">''</span>)}</span>
  <span class="hljs-subst">${posts
    .map(
      post =&gt; <span class="hljs-string">`
  &lt;url&gt;
    &lt;loc&gt;<span class="hljs-subst">${website}</span>/posts/<span class="hljs-subst">${post.slug}</span>&lt;/loc&gt;
    &lt;changefreq&gt;daily&lt;/changefreq&gt;
    &lt;priority&gt;0.7&lt;/priority&gt;
  &lt;/url&gt;
  `</span>
    )
    .join(<span class="hljs-string">''</span>)}</span>
&lt;/urlset&gt;`</span>
</code></pre>
<p>This is a simplified version to generate a sitemap. If you want the full version then you can check out the <a target="_blank" href="https://github.com/GraphCMS/graphcms-sveltekit-portfolio-and-blog-starter">source code for the project</a>.</p>
<p>A little more detail on this file now. Similar to how we can have pages and components in SvelteKit, we can also have endpoints. Endpoints in SvelteKit can handle HTTP methods like get, post, and delete.</p>
<p>A quick note on the file notation here: the <code>.xml.js</code> may look a bit odd. This is so that SvelteKit can understand the return type of the endpoint. In this case we want to return XML, but there are other types you can use, like JSON.</p>
<p>In that function we're defining a <code>get</code> function, adding a GraphQL query for the posts, then returning the posts from the query for use in the XML. </p>
<h3 id="heading-how-to-use-a-sveltekit-endpoint">How to Use a SvelteKit Endpoint</h3>
<p>Now that we've defined our endpoint in <code>src/routes/sitemap.xml.js</code> we can access the data right away. By going to that route in the browser we can see the data returned from that endpoint.</p>
<p>From the browser, go to <code>localhost:3000/sitemap.xml</code> – this will give us the data back from the GraphQL API on our GraphCMS project.</p>
<h2 id="heading-robotstxt"><strong>Robots.txt</strong></h2>
<p><strong>OPTIONAL</strong>: Let search engine robots know what to index. This tells web crawlers like the Googlebot what to and what not to index on your site.</p>
<p>Pages you might not want to index could be things like an admin panel or settings page.</p>
<p>The robots.txt can go in the static folder. Let's create the file now:</p>
<pre><code class="lang-bash">touch static/robots.txt
</code></pre>
<p>In the case of this project, it's ok for the Googlebot to crawl it all. So our <code>robots.txt</code> file can look like this:</p>
<pre><code class="lang-txt"># https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:
</code></pre>
<p>This is saying to the web crawler to index everything on the site.</p>
<h2 id="heading-rss-feed-generation"><strong>RSS Feed Generation</strong></h2>
<p><strong>OPTIONAL</strong>: Let users have changes made to your site show up in their RSS apps. Again I'll leave this up to you to implement. Much in the same way as the sitemap was created, you can implement a SvelteKit endpoint to generate the XML needed for an RSS feed.</p>
<pre><code class="lang-bash">touch src/routes/rss.xml.js
</code></pre>
<p>Here's an example file:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { client } <span class="hljs-keyword">from</span> <span class="hljs-string">'$lib/graphql-client'</span>
<span class="hljs-keyword">import</span> { gql } <span class="hljs-keyword">from</span> <span class="hljs-string">'graphql-request'</span>

<span class="hljs-keyword">const</span> name = <span class="hljs-string">'My Portfolio'</span>
<span class="hljs-keyword">const</span> website = <span class="hljs-string">'https://myportfolio.com'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> get = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">const</span> query = gql<span class="hljs-string">`
    query Posts {
      posts {
        title
        slug
      }
    }
  `</span>
  <span class="hljs-keyword">const</span> { posts } = <span class="hljs-keyword">await</span> client.request(query)
  <span class="hljs-keyword">const</span> body = xml(posts)

  <span class="hljs-keyword">const</span> headers = {
    <span class="hljs-string">'Cache-Control'</span>: <span class="hljs-string">'max-age=0, s-maxage=3600'</span>,
    <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/xml'</span>,
  }
  <span class="hljs-keyword">return</span> {
    headers,
    body,
  }
}

<span class="hljs-keyword">const</span> xml =
  <span class="hljs-function"><span class="hljs-params">posts</span> =&gt;</span> <span class="hljs-string">`&lt;rss xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:atom="https://www.w3.org/2005/Atom" version="2.0"&gt;
  &lt;channel&gt;
    &lt;title&gt;<span class="hljs-subst">${name}</span>&lt;/title&gt;
    &lt;link&gt;<span class="hljs-subst">${website}</span>&lt;/link&gt;
    &lt;description&gt;This is my portfolio!&lt;/description&gt;
    <span class="hljs-subst">${posts
      .map(
        post =&gt;
          <span class="hljs-string">`
        &lt;item&gt;
          &lt;title&gt;<span class="hljs-subst">${post.title}</span>&lt;/title&gt;
          &lt;description&gt;This is my portfolio!&lt;/description&gt;
          &lt;link&gt;<span class="hljs-subst">${website}</span>/posts/<span class="hljs-subst">${post.slug}</span>/&lt;/link&gt;
          &lt;pubDate&gt;<span class="hljs-subst">${<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(post.date)}</span>&lt;/pubDate&gt;
          &lt;content:encoded&gt;<span class="hljs-subst">${post.previewHtml}</span> 
            &lt;div style="margin-top: 50px; font-style: italic;"&gt;
              &lt;strong&gt;
                &lt;a href="<span class="hljs-subst">${website}</span>/posts/<span class="hljs-subst">${post.slug}</span>"&gt;
                  Keep reading
                &lt;/a&gt;
              &lt;/strong&gt;  
            &lt;/div&gt;
          &lt;/content:encoded&gt;
        &lt;/item&gt;
      `</span>
      )
      .join(<span class="hljs-string">''</span>)}</span>
  &lt;/channel&gt;
&lt;/rss&gt;`</span>
</code></pre>
<p>There's a lot to unpack in that, so what I have done is made an extensive post on <a target="_blank" href="https://scottspence.com/posts/make-an-rss-feed-with-sveltekit">setting up an RSS feed on your SvelteKit site</a>. This will give you all the information you need to get set up.</p>
<h2 id="heading-email-signup-with-revue"><strong>Email Signup with Revue</strong></h2>
<p><strong>OPTIONAL</strong>: If you want to take this a step further with endpoints, you can add a newsletter sign up page using the Revue API. I've <a target="_blank" href="https://scottspence.com/posts/email-form-submission-with-sveltekit">detailed that in a post</a> if you want to take that route.</p>
<p>There's also a great <a target="_blank" href="https://www.youtube.com/watch?v=mBXEnakkUIM">video from WebJeda</a> on collecting Google forms data in a SvelteKit project if you want to take that route.</p>
<h2 id="heading-continuous-deployment-with-vercel"><strong>Continuous Deployment with Vercel</strong></h2>
<p>If you have been following along up to this point (thank you by the way 🙏), you might be wondering why we've been making Git commits at the end of each section. Well all that has been leading up to this section.</p>
<p>I'll be using <a target="_blank" href="https://vercel.com">Vercel</a> for deployment. If you don't already have an account you can <a target="_blank" href="https://vercel.com/signup">sign up</a> with your preferred provider – I'll be using GitHub.</p>
<p>If you want to deploy your site as it is, right now, you can use the Vercel CLI using:</p>
<pre><code class="lang-bash">npx vercel
</code></pre>
<p>No need to install the CLI, as it's all done for you with the npx command. You'll be walked through the deployment by the CLI. </p>
<p>Here's the output from running the command and selecting the default for each question (enter):</p>
<pre><code class="lang-bash">? Set up and deploy “~/repos/my-developer-portfolio”? [Y/n] y
? Which scope <span class="hljs-keyword">do</span> you want to deploy to? Scott Spence
? Link to existing project? [y/N] n
? What’s your project’s name? my-developer-portfolio
? In <span class="hljs-built_in">which</span> directory is your code located? ./
Auto-detected Project Settings (SvelteKit):
- Build Command: svelte-kit build
- Output Directory: public
- Development Command: svelte-kit dev --port <span class="hljs-variable">$PORT</span>
? Want to override the settings? [y/N] n
🔗 Linked to spences10/my-developer-portfolio (created .vercel and added it to .gitignore)
🔍 Inspect: https://vercel.com/spences10/my-developer-portfolio/78bRRjiweZsipYbu8Q4Bg9JRmvGR [2s]
</code></pre>
<p>Now going to the URL from the CLI indicated with <code>🔍 Inspect</code> I can watch the project being built on Vercel. Great, our site is up and running! This is a one time deployment though, so if there are future changes then I'll need to use the CLI again.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-10.png" alt="Image" width="600" height="400" loading="lazy">
<em>Vercel deployment preview page</em></p>
<p>You may have noticed on the deploy preview page on Vercel that there is a section that says "No repository".</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-11.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We can add a GitHub repository so that any future changes that are made to the project will be built when the changes are pushed to GitHub.</p>
<p>So, first up we need to add our project to GitHub – let's do that now. If you're already logged into GitHub you can go to the <a target="_blank" href="https://github.com/new">new repository link</a> that you can get to by clicking the plus icon in the far right corner in GitHub.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-12.png" alt="Image" width="600" height="400" loading="lazy">
<em>New repository link</em></p>
<p>In the new page add in the details for the project:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-13.png" alt="Image" width="600" height="400" loading="lazy">
<em>New GitHub project with description</em></p>
<p>Then click the "Create repository" button:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-14.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-15.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The next screen will give you the Git commands you need. As the project is already created, I can use the second set of commands:</p>
<pre><code class="lang-bash">git remote add origin git@github.com:spences10/my-developer-portfolio.git
git branch -M main
git push -u origin main
</code></pre>
<p>Note that if you're following along, you'll need to take the commands given to you on your repository page rather than using the ones mentioned here, as that will point to my GitHub <code>spences10</code>.</p>
<p>Now that the repo is created on GitHub, I can connect it to Vercel. From the deploy preview page I can select the project by clicking the project name in the header:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-16.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>This will take me to the project dashboard:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-17.png" alt="Image" width="600" height="400" loading="lazy">
<em>Vercel project dashboard</em></p>
<p>From here I can click on the "Connect Git repository" button which will take me to the Git section in the project settings:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-18.png" alt="Image" width="600" height="400" loading="lazy">
<em>Connect a Git repository in the Vercel settings menu</em></p>
<p>Clicking GitHub will bring up a list of projects:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-19.png" alt="Image" width="600" height="400" loading="lazy">
<em>Select the GitHub repository to link</em></p>
<p>Clicking the "Connect" button will connect the repository. You may have also noticed the "Domains" setting here as well. You can configure your domain here or change the current name with a <code>.vercel.app</code> domain.</p>
<p>One other thing to note here is the "Environment Variables" section in the settings. This will need to have the <code>VITE_GRAPHQL_API</code> environment variable added here:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-20.png" alt="Image" width="600" height="400" loading="lazy">
_Add VITE_GRAPHQL<em>API environment variable to the Vercel settings</em></p>
<p>Now any time there are any changes pushed to GitHub, Vercel will build the site.</p>
<h2 id="heading-how-to-publish-and-build-on-content-changes">How to Publish and Build on Content Changes</h2>
<p>Rather than having to push a change to GitHub to create a new build of the project when only the content has changed, you can do this with a GraphCMS integration.</p>
<p>From the Settings panel in GraphCMS, go to the integrations section:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-21.png" alt="Image" width="600" height="400" loading="lazy">
<em>Select the integrations section in the settings panel</em></p>
<p>Click on the Vercel integration – there's also integrations for Netlify and Gatsby Cloud:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-26.png" alt="Image" width="600" height="400" loading="lazy">
<em>Click on the Vercel integration</em></p>
<p>Click "Enable" for the Vercel integration:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-23.png" alt="Image" width="600" height="400" loading="lazy">
<em>Enable the Vercel integration</em></p>
<p>Click the "Connect to Vercel" button when prompted:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-24.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Click "Authorise GraphCMS" to make deployments for you on Vercel:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-25.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>In the "Build projects" section, select your Vercel project from the dropdown selection. The "Display name" is what will appear in the side panel on your content pages. The branch name is the branch you want to deploy to Vercel from GitHub – I use <code>main</code> for the production branch.</p>
<p>There's also an option to specify what models you want to have the integration enabled on. In this case I'm using them all, so selecting "Select all" then finally clicking the "Enable" button:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-28.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>If I now go to the content section on the GraphCMS project and select a content model to edit an entry, there's a "Start building Production" button that will kick off a new build any time it's clicked.</p>
<p>Here's the Author model and the Vercel integration on the right hand panel:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-29.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-google-search-console">Google Search Console</h2>
<p><strong>OPTIONAL</strong>: This is an optional step if you own your own domain. A good way to have your site ranked on the search engines is to use the Google search console.</p>
<p><a target="_blank" href="https://search.google.com/search-console">https://search.google.com/search-console</a></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-32.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-33.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Add the TXT record to your domain using the Vercel CLI. You can add it manually in the domains section of Vercel as well:</p>
<pre><code class="lang-bash">vercel dns add my-developer-portfolio.com @ TXT google-site-verification=g99pqa_kSHiq6AzLtk4HF00tyJhQVt1gGzfUoJQrTPQ
</code></pre>
<p>Once your site has been verified, you can add in your sitemap and click the submit button.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/01/image-34.png" alt="Image" width="600" height="400" loading="lazy">
<em>Add sitemap to Google search console</em></p>
<p>That's it! You'll now need to wait for the Googlebot to do it's thing and index your site. You should start seeing search queries coming in over time.</p>
<h2 id="heading-resources"><strong>Resources</strong></h2>
<p>Here are some of the resources I used to make the content on the blog I created throughout this guide.</p>
<ul>
<li>Images with <a target="_blank" href="https://lorem.space/api">Lorem.space - placeholder image generator</a></li>
<li>Markdown with <a target="_blank" href="https://jaspervdj.be/lorem-markdownum/">Lorem Markdownum (jaspervdj.be)</a></li>
<li>Bio generation with <a target="_blank" href="https://www.character-generator.org.uk/bio/">Character Biography Generator (character-generator.org.uk)</a></li>
<li>Ideal cover image sizes: <a target="_blank" href="https://buffer.com/library/ideal-cover-photo-size/">The Ideal Cover Photo Size for Each of the Major Social Media Platforms (buffer.com)</a></li>
</ul>
<p>You can check these links for further information on Svelte and SvelteKit</p>
<ul>
<li><a target="_blank" href="https://kit.svelte.dev/docs">https://kit.svelte.dev/docs</a></li>
<li><a target="_blank" href="https://svelte.dev/docs">https://svelte.dev/docs</a></li>
</ul>
<p>If you want the source code for this project then you can check out the GitHub repo <a target="_blank" href="https://github.com/GraphCMS/graphcms-sveltekit-portfolio-and-blog-starter">for all the code</a>. If you have any issues then feel free to log an issue or reach out on <a target="_blank" href="https://twitter.com/spences10">Twitter</a>.</p>
<h2 id="heading-what-we-have-accomplished">What we have accomplished</h2>
<p>Time to recap what we've achieved here. We have gone from hello world through to fully featured portfolio and blog!</p>
<p>We covered getting data from a GraphQL API and displaying that data on a page of the project. We then implemented a GraphQL client to retrieve only the data we needed.</p>
<p>We added the all important sitemap so that the site could be discovered and indexed by search engines like Google.</p>
<p>An optional touch was adding in an RSS feed so that anyone that uses an RSS reader can be notified of any new content that is added to the site.</p>
<p>Finally we deployed our finished project to Vercel for the world to see.</p>
<h2 id="heading-thanks">Thanks</h2>
<p>Thank you so much for taking the time to go through this guide. I hope it gave you all you need to start making your own projects with Svelte.</p>
<p>If you like the content you can check out much more from me on my <a target="_blank" href="https://scottspence.com">blog</a> or you can follow me on <a target="_blank" href="https://twitter.com/spences10">Twitter</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Become a Full Stack Developer with Svelte, Postgres, Vercel, and Gitpod ]]>
                </title>
                <description>
                    <![CDATA[ Full stack web development includes the backend that happens on a server and the frontend that happens on a web browser. New tools are making it easier than ever to create a full stack web app. We just published a full stack web development course on... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/become-a-full-stack-developer-with-svelte/</link>
                <guid isPermaLink="false">66b200bb712508eb16067808</guid>
                
                    <category>
                        <![CDATA[ Svelte ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Mon, 13 Dec 2021 16:23:09 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/12/fullstack.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Full stack web development includes the backend that happens on a server and the frontend that happens on a web browser. New tools are making it easier than ever to create a full stack web app.</p>
<p>We just published a full stack web development course on the freeCodeCamp.org YouTube channel. And the best part: it can all be done in a browser using Gitpod.</p>
<p>Mike Nikles developed this course. Mike is a senior developer at Gitpod and a great teacher. </p>
<p>This course covers everything from creating a new repository to deploying to production, and you will learn the reason for every line of code. The Svelte JavaScript framework is used for the frontend with Postgres as the database. The app is deployed using Vercel and Railway.</p>
<p>Here are all the sections covered in this course:</p>
<ul>
<li>The Gitpod developer environment</li>
<li>Project Overview</li>
<li>Project Architecture</li>
<li>Initialize the application</li>
<li>Intro to SvelteKit</li>
<li>Configure Gitpod</li>
<li>Develop HTML structure</li>
<li>Apply CSS styles</li>
<li>Develop CRUD endpoints: GET and POST</li>
<li>Develop CRUD endpoints: DELETE</li>
<li>Develop CRUD endpoints: PATCH - Edit Text</li>
<li>Develop CRUD endpoints: PATCH - Mark as Done</li>
<li>Enhance HTML forms</li>
<li>Install &amp; start the dev database</li>
<li>Use Prisma ORM</li>
<li>Update API to use Prisma</li>
<li>Deploy Database on Railway</li>
<li>Deploy web app &amp; API on Vercel</li>
<li>Project review</li>
</ul>
<p>Watch the full course below or on the <a target="_blank" href="https://youtu.be/OUzaUJ3gEug">freeCodeCamp.org YouTube channel</a> (7-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/OUzaUJ3gEug" 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[ Learn Svelte in 5 Minutes ]]>
                </title>
                <description>
                    <![CDATA[ By Leanne Rybintsev This article gives you a lightning-speed overview of Svelte - a Javascript framework which lets you write less code, use no virtual DOM, and create truly reactive apps.  As if that's not enough, Svelte is super-intuitive too! Buil... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-svelte-in-5-minutes/</link>
                <guid isPermaLink="false">66d460143a8352b6c5a2aaa2</guid>
                
                    <category>
                        <![CDATA[ framework ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Svelte ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 08 Jun 2020 20:49:08 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/06/Screenshot-2020-06-06-at-16.10.39.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Leanne Rybintsev</p>
<p>This article gives you a lightning-speed overview of Svelte - a Javascript framework which lets you write less code, use no virtual DOM, and create truly reactive apps. </p>
<p>As if that's not enough, Svelte is super-intuitive too! Built with developers in mind, it is designed to make coding easier, bug-squashing quicker, and a developer's work life generally happier. </p>
<p>If that sounds right up your street, then read on!</p>
<p>While 5 minutes won't be enough to teach you Svelte in depth, it does allow for a solid overview of the basics, including:</p>
<ul>
<li>Components</li>
<li>Importing and Exporting</li>
<li>Templating</li>
<li>Event handling</li>
<li>Event dispatching</li>
<li>Reactivity</li>
</ul>
<p>If you want to find out more about Svelte after reading this article, check out <a target="_blank" href="https://scrimba.com/course/glearnsvelte?utm_source=dev.to&amp;utm_medium=referral&amp;utm_campaign=glearnsvelte_5_minute_article">the full course</a> over on Scrimba. There, you'll learn about even more Svelte features and have the chance to road test your new skills with a bunch of interactive challenges. </p>
<p>For now, let's get started on the basics!</p>
<h2 id="heading-components">Components</h2>
<p><a target="_blank" href="https://scrimba.com/p/pG6X6UG/cNDg9yHB?utm_source=dev.to&amp;utm_medium=referral&amp;utm_campaign=glearnsvelte_5_minute_article"><img src="https://dev-to-uploads.s3.amazonaws.com/i/e8ej7929dpa3u9tzsm0u.png" alt="DOM displaying Svelte component" width="339" height="254" loading="lazy"></a>
<em>(Click the image to access the course.)</em></p>
<p>First, we'll take a look at how to build a Svelte component, which can contain three parts; <code>&lt;script&gt;</code>, which contains Javascript, <code>&lt;style&gt;</code>, which contains CSS and the HTML, which uses the JS from the <code>&lt;script&gt;</code> tag. </p>
<pre><code class="lang-js">&lt;script&gt;
    <span class="hljs-keyword">let</span> say = <span class="hljs-string">'hi'</span>;
&lt;/script&gt;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
    <span class="hljs-selector-tag">div</span> {
        <span class="hljs-attribute">color</span>: red;
    }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span></span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    Say: {say}
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p><strong>Note:</strong> The bare minimum needed for a Svelte component is the HTML, so the app will still work without the <code>&lt;script&gt;</code> and <code>&lt;style&gt;</code> tags.</p>
<h2 id="heading-importing-and-exporting">Importing and Exporting</h2>
<p>One big benefit of using frameworks is the ability to modularise code by splitting it into separate components. Components are then imported into the main app using <code>import</code> keyword: </p>
<pre><code class="lang-js">  <span class="hljs-keyword">import</span> Face <span class="hljs-keyword">from</span> <span class="hljs-string">'./Face.svelte'</span>;
</code></pre>
<p>Unlike with other frameworks, the <code>export</code> keyword is not required to use a component elsewhere in an app. Instead, it is used to pass parameters, or props, from parent elements to their children. </p>
<p>For example, we can set a size prop with a default size in our component:</p>
<pre><code class="lang-js">&lt;script&gt;
    <span class="hljs-keyword">export</span> <span class="hljs-keyword">let</span> size = <span class="hljs-number">1</span>;
&lt;/script&gt;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"font-size: {size}em"</span>&gt;</span>=)<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p>This allows us to easily adjust the size of the imported component over in our <code>App.svelte</code> file: </p>
<pre><code class="lang-js">&lt;script&gt;
    <span class="hljs-keyword">import</span> Face <span class="hljs-keyword">from</span> <span class="hljs-string">'./Face.svelte'</span>;
&lt;/script&gt;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Face</span> <span class="hljs-attr">size</span>=<span class="hljs-string">"4"</span> /&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Face</span> <span class="hljs-attr">size</span>=<span class="hljs-string">"10"</span> /&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Face</span> /&gt;</span></span>
</code></pre>
<p>The various sizes appear on the DOM as follows:</p>
<p><a target="_blank" href="https://scrimba.com/p/pG6X6UG/cbDNVncg?utm_source=dev.to&amp;utm_medium=referral&amp;utm_campaign=glearnsvelte_5_minute_article"><img src="https://dev-to-uploads.s3.amazonaws.com/i/3aecnw1qq3xpcck19agr.png" alt="component imported with various sizes using props" width="368" height="431" loading="lazy"></a>
<em>(Click the image to access the course.)</em></p>
<p>Head over to <a target="_blank" href="https://scrimba.com/p/pG6X6UG/cbDNVncg?utm_source=dev.to&amp;utm_medium=referral&amp;utm_campaign=glearnsvelte_5_minute_article">the course on Scrimba</a> to view and play around with the full code. </p>
<h2 id="heading-templating">Templating</h2>
<p>The Svelte <a target="_blank" href="https://scrimba.com/p/pG6X6UG/cMZrQds2?utm_source=dev.to&amp;utm_medium=referral&amp;utm_campaign=glearnsvelte_5_minute_article">templating syntax</a> is a great feature which lets us add if statements and for loops to our HTML.</p>
<p>The syntax for an if statement looks like this:</p>
<pre><code class="lang-js">&lt;Container&gt;
    {#<span class="hljs-keyword">if</span> say}
        &lt;div&gt;
            Hi!
        &lt;/div&gt;

    {/<span class="hljs-keyword">if</span>}
&lt;/Container&gt;
</code></pre>
<p>While a for loop is as follows:</p>
<pre><code class="lang-js">{#each [<span class="hljs-number">2</span>,<span class="hljs-number">1</span>,<span class="hljs-number">0</span>] <span class="hljs-keyword">as</span> faceIndex}
        &lt;Face index={faceIndex} /&gt;
    {/each}
</code></pre>
<h2 id="heading-event-handling">Event handling</h2>
<p>To allow the user to interact with our app, we need event handlers. In <a target="_blank" href="https://scrimba.com/p/pG6X6UG/caZ3J6U3?utm_source=dev.to&amp;utm_medium=referral&amp;utm_campaign=glearnsvelte_5_minute_article">this scrim</a>, we see how to add a simple <code>on:click</code> to a <code>&lt;button&gt;</code> to show our app's header:</p>
<pre><code class="lang-js">&lt;button on:click={<span class="hljs-function">() =&gt;</span> {showHeader = <span class="hljs-literal">true</span>}}&gt;show&lt;/button&gt;
</code></pre>
<p>And what a header it is..!
<a target="_blank" href="https://scrimba.com/p/pG6X6UG/caZ3J6U3?utm_source=dev.to&amp;utm_medium=referral&amp;utm_campaign=glearnsvelte_5_minute_article"><img src="https://dev-to-uploads.s3.amazonaws.com/i/czgdba1dpkzu552kq2hq.png" alt="header made visible on the DOM with an event handler" width="404" height="379" loading="lazy"></a>
<em>(Click the image to access the course.)</em></p>
<p>There is a gotcha with this, though - it only works with the native HTML <code>&lt;button&gt;</code> tag and not imported components called <code>&lt;Button&gt;</code>. </p>
<p>Luckily, we can work around this by using <strong>event forwarding</strong>, i.e. adding an <code>on:click</code> to the native <code>&lt;button&gt;</code> tag in its component file:</p>
<pre><code class="lang-js">&lt;button on:click&gt;
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">slot</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">slot</span>&gt;</span></span>
&lt;/button&gt;
</code></pre>
<h2 id="heading-event-dispatching">Event dispatching</h2>
<p><a target="_blank" href="https://scrimba.com/p/pG6X6UG/cD4bKDuD?utm_source=dev.to&amp;utm_medium=referral&amp;utm_campaign=glearnsvelte_5_minute_article"><img src="https://dev-to-uploads.s3.amazonaws.com/i/w203a2wxgn1brk5ss6i4.png" alt="Hide and show buttons created with event dispatcher" width="404" height="381" loading="lazy"></a>
<em>(Click the image to access the course.)</em>
Event dispatching is a great feature of Svelte which increases code usability by allowing us to use the same element for more than one action.</p>
<p>In <a target="_blank" href="https://scrimba.com/p/pG6X6UG/cD4bKDuD?utm_source=dev.to&amp;utm_medium=referral&amp;utm_campaign=glearnsvelte_5_minute_article">this scrim</a>, we learn how to use one <code>&lt;Button&gt;</code> component to both show and hide an element. </p>
<p>We create an event dispatcher in the <code>&lt;Button&gt;</code> component file like this:</p>
<pre><code class="lang-js">&lt;script&gt;
    <span class="hljs-keyword">import</span> {createEventDispatcher} <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte'</span>;
    <span class="hljs-keyword">const</span> dispatch = createEventDispatcher();    
&lt;/script&gt;
</code></pre>
<p>We then add the dispatcher to our native HTML <code>&lt;button&gt;</code> like this:</p>
<pre><code class="lang-js">&lt;button on:click={<span class="hljs-function">() =&gt;</span> dispatch(<span class="hljs-string">'show'</span>)}&gt;
    Show
&lt;/button&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{()</span> =&gt;</span> dispatch('hide')}&gt;
    Hide
<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
</code></pre>
<p>Lastly, we declare the button's functionality options in the <code>App.svelte</code> file as follows: </p>
<pre><code class="lang-js">&lt;Buttons on:show={<span class="hljs-function">() =&gt;</span> {showHeader = <span class="hljs-literal">true</span>}} on:hide={<span class="hljs-function">() =&gt;</span> {showHeader = <span class="hljs-literal">false</span>}} /&gt;
</code></pre>
<p>We can refactor this by passing values up through the dispatch using the event variable (<code>e</code>). In this case, the <code>&lt;Button&gt;</code> in our <code>App.svelte</code> file looks like this:</p>
<pre><code class="lang-js">&lt;Buttons on:click={<span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {showHeader = e.detail}} /&gt;
</code></pre>
<p>While the native HTML <code>&lt;button&gt;</code>s in our component file look like this:</p>
<pre><code class="lang-js">&lt;button on:click={<span class="hljs-function">() =&gt;</span> dispatch(<span class="hljs-string">'click'</span>, <span class="hljs-literal">true</span>)}&gt;
    Show
&lt;/button&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{()</span> =&gt;</span> dispatch('click', false)}&gt;
    Hide
<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
</code></pre>
<h2 id="heading-reactivity">Reactivity</h2>
<p>If you want a piece of code to rerun every time its associated variable is updated, then Svelte's unique feature, <a target="_blank" href="https://scrimba.com/p/pG6X6UG/caZ3yBAB?utm_source=dev.to&amp;utm_medium=referral&amp;utm_campaign=glearnsvelte_5_minute_article">the reactive statement</a>, is for you. We declare a reactive statement with <code>$:</code> as follows: </p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> score = <span class="hljs-number">0</span>;
    $: smileySays = <span class="hljs-string">'Hi there, your score is: '</span> + score;
</code></pre>
<p>It's also possible to run if statements inside reactive statements. The code to do so looks like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> score = <span class="hljs-number">0</span>;
    $: smileySays = <span class="hljs-string">'Hi there, your score is: '</span> + score;
    $: <span class="hljs-keyword">if</span> (score &lt; <span class="hljs-number">-4</span>) smileySays = <span class="hljs-string">'Wow your score is low!'</span>
</code></pre>
<p>That's about all the features we can cram into our 5-minute tour of Svelte. I hope you found it useful and are inspired to try out the framework for yourself and test your new-found skills. </p>
<p>Don't forget to check out the full course <a target="_blank" href="https://scrimba.com/course/glearnsvelte?utm_source=dev.to&amp;utm_medium=referral&amp;utm_campaign=glearnsvelte_5_minute_article">over at Scrimba</a> to find out about even more Svelte features and give the coding challenges a try.</p>
<p>Wherever your coding journey takes you next, happy learning :) </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Want to Learn Svelte? Here's a Free 16-Part Course by Noah Kaufman ]]>
                </title>
                <description>
                    <![CDATA[ By Per Harald Borgen If you're looking to learn a new Javascript framework which allows you to write less code, use no virtual DOM, and create truly reactive apps, then Svelte is for you. What is Svelte? Svelte is a Javascript framework, a compiler, ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/want-to-learn-svelte-heres-our-free-15-part-course-by-noah-kaufman/</link>
                <guid isPermaLink="false">66d8527929e30bc0ad4775b2</guid>
                
                    <category>
                        <![CDATA[ Scrimba ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Svelte ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 14 May 2020 22:09:51 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/04/jm6s35gtdtf5rijq0uqm.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Per Harald Borgen</p>
<p>If you're looking to learn a new Javascript framework which allows you to write less code, use no virtual DOM, and create truly reactive apps, then Svelte is for you.</p>
<h2 id="heading-what-is-svelte">What is Svelte?</h2>
<p>Svelte is a Javascript framework, a compiler, and a language. Unlike other Frameworks such as React and Vue which do much of their work in the browser, Svelte does its work in the compile step. This results in highly efficient code and a potentially faster run-time on the client-side.</p>
<p>Svelte offers faster development, faster web pages, and a better developer experience - the creators of Svelte created it with other developers in mind). </p>
<p>On top of this, knowing Svelte will help you stand out to potential employers and shows that you're interested in newer technologies.</p>
<h2 id="heading-great-tell-me-about-svelte">Great! Tell me about Svelte.</h2>
<p>This article takes you through Scrimba's brand-new <a target="_blank" href="https://scrimba.com/playlist/pG6X6UG?utm_source=fcc&amp;utm_medium=referral&amp;utm_campaign=glearnsvelte_launch_article">16-part Svelte course</a> which covers the following essential topics to put you well on your way to becoming a Svelte master:</p>
<ul>
<li>Components</li>
<li>Importing/exporting</li>
<li>Slots</li>
<li>Template</li>
<li>Event Handling</li>
<li>Event Dispatching</li>
<li>Buttons</li>
<li>Reactivity</li>
<li>Binding</li>
</ul>
<p>The course is delivered through a series of interactive screencasts, allowing you to practice your new skills and truly embed your learning.</p>
<p>Finishing up with an in-depth Final Project which consolidates all the skills learned along the way, the course helps you build the muscle memory needed to become an effective Svelte developer. </p>
<p>It is led by is Noah Kaufman, a Senior Frontend Developer from San Francisco, California with an M.S in Computational Linguistics.</p>
<p>If this sounds right up your street, <a target="_blank" href="https://scrimba.com/g/glearnsvelte?utm_source=fcc&amp;utm_medium=referral&amp;utm_campaign=glearnsvelte_launch_article">head on over to the course</a> on Scrimba and read on to find out more.</p>
<h2 id="heading-components">Components</h2>
<p>In Svelte, everything exists inside a component, and the first cast shows what the anatomy of these components looks like. </p>
<p>The component has three optional parts; <code>&lt;script&gt;</code>, which contains Javascript, <code>&lt;style&gt;</code> which contains CSS, and finally some HTML, which is able to use the JS from the <code>&lt;script&gt;</code> tag.</p>
<pre><code class="lang-js">&lt;script&gt;
    <span class="hljs-keyword">let</span> say = <span class="hljs-string">'hi'</span>;
&lt;/script&gt;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
    <span class="hljs-selector-tag">div</span> {
        <span class="hljs-attribute">color</span>: red;
    }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span></span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    Say: {say}
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<h2 id="heading-importing-and-exporting">Importing and Exporting</h2>
<p>Here, we take a quick look at how to import and export components so they can be used elsewhere in our app.</p>
<p>Components are imported with the <code>import</code> keyword:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> Face <span class="hljs-keyword">from</span> <span class="hljs-string">"./Face.svelte"</span>;
</code></pre>
<p>While the <code>export</code> keyword allows other components to change components on import:</p>
<pre><code class="lang-js">&lt;script&gt;
    <span class="hljs-keyword">export</span> <span class="hljs-keyword">let</span> size;
&lt;/script&gt;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"font-size: {size}em"</span>&gt;</span>=)<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<h2 id="heading-challenge-1">Challenge 1</h2>
<p>In this cast, Noah challenges us to put our new Svelte skills to the test. No spoilers here, so <a target="_blank" href="https://scrimba.com/p/pG6X6UG/cvdpNRU8?utm_source=fcc&amp;utm_medium=referral&amp;utm_campaign=glearnsvelte_launch_article">click through to the course</a> to give the challenge a try and check the solution.</p>
<h2 id="heading-slots">Slots</h2>
<p>Slots allow us to place elements inside components. For example, inserting a <code>&lt;slot&gt;</code> into a <code>&lt;div&gt;</code> with the class <code>Container</code> allows us to place as many elements as we want into the <code>&lt;Container&gt;</code> component:</p>
<pre><code class="lang-js">&lt;div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"Container"</span>&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">slot</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">slot</span>&gt;</span></span>
&lt;/div&gt;
</code></pre>
<p>The newly-placed elements are children of the component:</p>
<pre><code class="lang-js">&lt;Container&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Say: {say}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>

  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Face</span> <span class="hljs-attr">index</span>=<span class="hljs-string">{0}</span> /&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Face</span> /&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Face</span> <span class="hljs-attr">index</span>=<span class="hljs-string">{2}</span> /&gt;</span></span>
&lt;/Container&gt;
</code></pre>
<h2 id="heading-templating">Templating</h2>
<p>The Svelte templating syntax allows us to add if statements and for loops to our HTML. That's right, to our HTML!</p>
<p>An if statement looks like this:</p>
<pre><code class="lang-js">&lt;Container&gt;
    {#<span class="hljs-keyword">if</span> say}
        &lt;div&gt;
            Hi!
        &lt;/div&gt;

    {/<span class="hljs-keyword">if</span>}
&lt;/Container&gt;
</code></pre>
<p>While a for loop looks like this:</p>
<pre><code class="lang-js">{#each [<span class="hljs-number">2</span>,<span class="hljs-number">1</span>,<span class="hljs-number">0</span>] <span class="hljs-keyword">as</span> faceIndex}
        &lt;Face index={faceIndex} /&gt;
    {/each}
</code></pre>
<h2 id="heading-making-header-challenge-2">Making Header - Challenge 2</h2>
<p>In this challenge, we use what we've just learned about Svelte templating to add a Header to our app. <a target="_blank" href="https://scrimba.com/p/pG6X6UG/cGmeLzsR?utm_source=fcc&amp;utm_medium=referral&amp;utm_campaign=glearnsvelte_launch_article">Check out the course</a> to try it out for yourself and check your answer.</p>
<h2 id="heading-event-handling">Event Handling</h2>
<p>Next up, Noah shows us a simple inline event handler, which allows the user to show the app's header at the click of a button.</p>
<pre><code class="lang-js">&lt;button
  <span class="hljs-attr">on</span>:click={<span class="hljs-function">() =&gt;</span> {
    showHeader = <span class="hljs-literal">true</span>;
  }}
&gt;
  show
&lt;/button&gt;
</code></pre>
<p>However, if we use a <code>&lt;Button&gt;</code> component rather than a native HTML button, this kind of <code>on:click</code> handler won't work. We can fix this with <strong>event forwarding</strong>, i.e. adding a plain <code>on:click</code> to the native <code>&lt;button&gt;</code> in the component file:</p>
<pre><code class="lang-js">&lt;button on:click&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">slot</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">slot</span>&gt;</span></span>
&lt;/button&gt;
</code></pre>
<h2 id="heading-event-dispatching">Event Dispatching</h2>
<p>Event dispatching allows a component to emit more than one type of event, for example, the same <code>&lt;Button&gt;</code> component can be used both to show an element and to hide it.</p>
<p>We create an event dispatcher like this:</p>
<pre><code class="lang-js">&lt;script&gt;
  <span class="hljs-keyword">import</span> {createEventDispatcher} <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte'</span>; <span class="hljs-keyword">const</span> dispatch =
  createEventDispatcher();
&lt;/script&gt;
</code></pre>
<p>We then add it to native HTML <code>&lt;button&gt;</code> like this:</p>
<pre><code class="lang-js">&lt;button on:click={<span class="hljs-function">() =&gt;</span> dispatch(<span class="hljs-string">'show'</span>)}&gt;
    Show
&lt;/button&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{()</span> =&gt;</span> dispatch('hide')}&gt;
    Hide
<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
</code></pre>
<p>Finally we define the <code>&lt;Button&gt;</code>'s functionality options in the <code>App.svelte</code> file like this:</p>
<pre><code class="lang-js">&lt;Buttons
  <span class="hljs-attr">on</span>:show={<span class="hljs-function">() =&gt;</span> {
    showHeader = <span class="hljs-literal">true</span>;
  }}
  <span class="hljs-attr">on</span>:hide={<span class="hljs-function">() =&gt;</span> {
    showHeader = <span class="hljs-literal">false</span>;
  }}
/&gt;
</code></pre>
<p>The same outcome can also be achieved by passing values (in this case <code>true</code> and <code>false</code>) up through the dispatch. The values can then be accessed through the event variable <code>e</code>.</p>
<pre><code>&lt;button on:click={<span class="hljs-function">() =&gt;</span> dispatch(<span class="hljs-string">'click'</span>, <span class="hljs-literal">true</span>)}&gt;
    Show
&lt;/button&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{()</span> =&gt;</span> dispatch('click', false)}&gt;
    Hide
<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
</code></pre><pre><code class="lang-js">&lt;Container&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Buttons</span>
    <span class="hljs-attr">on:click</span>=<span class="hljs-string">{(e)</span> =&gt;</span> {
      showHeader = e.detail;
    }}
  /&gt;</span>
&lt;/Container&gt;
</code></pre>
<h2 id="heading-buttons-challenge-3">Buttons - Challenge 3</h2>
<p>Our third challenge is more involved than the previous two and puts our new knowledge of event dispatchers to the test. To help us along, Noah breaks the challenge down into bitesize chunks:</p>
<pre><code class="lang-js">&lt;!-- Challenge <span class="hljs-number">3</span> -
<span class="hljs-number">1.</span> add a prop <span class="hljs-keyword">in</span> Buttons.svelte called buttons which is a list <span class="hljs-keyword">of</span> objects like:
[{<span class="hljs-attr">value</span>: <span class="hljs-string">''</span>, <span class="hljs-attr">text</span>: <span class="hljs-string">''</span>}, ...etc]
<span class="hljs-number">2.</span> use #each to turn all the objects into buttons that:
    a. have innerHTML equal to the .text <span class="hljs-keyword">of</span> the object.
    b. dispatch a click event that passes the .value <span class="hljs-keyword">of</span> the object.
<span class="hljs-number">3.</span> Handle the event <span class="hljs-keyword">in</span> App.svelte to update the score.
--&gt;
</code></pre>
<p><a target="_blank" href="https://scrimba.com/p/pG6X6UG/cp342mTV?utm_source=fcc&amp;utm_medium=referral&amp;utm_campaign=glearnsvelte_launch_article">Head over to the course</a> now to give it a try and see the solution.</p>
<h2 id="heading-reactivity">Reactivity</h2>
<p>Reactive statements are a unique feature of Svelte which tell a piece of code to re-run each time a variable within that code is updated. </p>
<p>For example, the code below will run each time the score variable is changed (note that we declare a reactive statement with <code>$:</code>).</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> score = <span class="hljs-number">0</span>;
$: smileySays = <span class="hljs-string">"Hi there, your score is: "</span> + score;
</code></pre>
<p>We can also run if statements inside reactive statements:</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> score = <span class="hljs-number">0</span>;
$: smileySays = <span class="hljs-string">"Hi there, your score is: "</span> + score;
$: <span class="hljs-keyword">if</span> (score &lt; <span class="hljs-number">-4</span>) smileySays = <span class="hljs-string">"Wow your score is low!"</span>;
</code></pre>
<h2 id="heading-reactive-challenge-challenge-4">Reactive Challenge - Challenge 4</h2>
<p>We can now test our new skills by completing the Reactive Challenge, which brings us one step closer to being ready for the final project.</p>
<p>Once again, Noah splits the challenge into smaller parts to help us on our way:</p>
<pre><code class="lang-js">&lt;!-- Challenge <span class="hljs-number">4</span> -
<span class="hljs-number">1.</span> add happyScore and storyIndex (both equal <span class="hljs-number">0</span>)
<span class="hljs-number">2.</span> smileySays and buttons get updated whenever storyIndex changes
<span class="hljs-number">3.</span> add clickHandler <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">that</span> <span class="hljs-title">increments</span> <span class="hljs-title">storyIndex</span> <span class="hljs-title">and</span> <span class="hljs-title">adds</span> <span class="hljs-title">e</span>.<span class="hljs-title">detail</span>.<span class="hljs-title">value</span> <span class="hljs-title">to</span> <span class="hljs-title">the</span> <span class="hljs-title">happyScore</span> --&gt;</span>
</code></pre>
<p><a target="_blank" href="https://scrimba.com/p/pG6X6UG/cgKqRDt9?utm_source=fcc&amp;utm_medium=referral&amp;utm_campaign=glearnsvelte_launch_article">Click through to the course</a> to try it out and check your answer.</p>
<h2 id="heading-a-bit-more-reactivity">A Bit More Reactivity</h2>
<p>Next up, Noah gives us another example of using Reactive Statements, an emoji face which changes according the current <code>happyScore</code> variable:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> faceList = [
  <span class="hljs-string">"?"</span>,
  <span class="hljs-string">"?"</span>,
  <span class="hljs-string">"?"</span>,
  <span class="hljs-string">"?"</span>,
  <span class="hljs-string">"?"</span>,
  <span class="hljs-string">"?"</span>,
  <span class="hljs-string">"?"</span>,
  <span class="hljs-string">"?"</span>,
  <span class="hljs-string">"?"</span>,
  <span class="hljs-string">"?"</span>,
  <span class="hljs-string">"?"</span>,
];
$: index = happyScore + <span class="hljs-number">5</span>;
</code></pre>
<p>Similarly to the previous examples, the code runs each time the 'happyScore' variable changes, so a Reactive Statement is just the right tool for the job.</p>
<h2 id="heading-binding">Binding</h2>
<p>Binding allows a user to update a variable (in this case called <code>name</code>) by entering a value into an <code>&lt;input&gt;</code> field. As binding is a two-way process, changing the variable also updates the <code>&lt;input&gt;</code>'s value:</p>
<p>We bind values like this:</p>
<pre><code class="lang-js">&lt;script&gt;
    <span class="hljs-keyword">import</span> Face <span class="hljs-keyword">from</span> <span class="hljs-string">'./Face.svelte'</span>;
    <span class="hljs-keyword">import</span> Container <span class="hljs-keyword">from</span> <span class="hljs-string">'./Container.svelte'</span>;
    <span class="hljs-keyword">import</span> story <span class="hljs-keyword">from</span> <span class="hljs-string">'./story'</span>;

    <span class="hljs-keyword">let</span> showHeader = <span class="hljs-literal">false</span>;
    <span class="hljs-keyword">let</span> storyIndex = <span class="hljs-number">0</span>;
    $: smileySays = story[storyIndex].smileySays;
    <span class="hljs-comment">//variable name below:</span>
    <span class="hljs-keyword">let</span> name = <span class="hljs-string">''</span>;
&lt;/script&gt;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Container</span>&gt;</span>
    //binding declared below:
    <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">bind:value</span>=<span class="hljs-string">{name}</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{name}, {smileySays}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">Container</span>&gt;</span></span>
</code></pre>
<p>As well as binding variables, it's also possible to bind values from objects, lists or components.</p>
<h2 id="heading-final-project">Final Project</h2>
<p><a target="_blank" href="https://scrimba.com/p/pG6X6UG/cgKK4yhG?utm_source=fcc&amp;utm_medium=referral&amp;utm_campaign=glearnsvelte_launch_article"><img src="https://dev-to-uploads.s3.amazonaws.com/i/mzg89uwkqt4yd0t4ghdz.png" alt="Final Project" width="569" height="503" loading="lazy"></a>
<em>Click the image to access the final project.</em></p>
<p>Well done for making it through the course! We wrap things up with a final project which ties together all the skills we've learned along the way. </p>
<p>Once again Noah breaks it down into smaller chunks to help us through:</p>
<pre><code class="lang-js">&lt;!-- Final Challenge
<span class="hljs-number">1.</span> The header appears <span class="hljs-keyword">if</span> the user chooses Svelte answer
(HINT: happyScore will be greater than <span class="hljs-number">0</span> <span class="hljs-keyword">if</span> they answer Svelte)
<span class="hljs-number">2.</span> Display final message depending on happyScore
<span class="hljs-number">3.</span> Implement the Reset functionality
--&gt;
</code></pre>
<p><a target="_blank" href="https://scrimba.com/p/pG6X6UG/cgKK4yhG?utm_source=fcc&amp;utm_medium=referral&amp;utm_campaign=glearnsvelte_launch_article">Check out the cast</a> to test out your news Svelte skills and see the solution.</p>
<h2 id="heading-outro">Outro</h2>
<p>That brings us to the end of the course. Great job for finishing it! And if you're eager to learn more Svelte, do check out the official docs at <a target="_blank" href="https://svelte.dev/">svelte.dev</a> for topics like: <code>Context</code>, <code>Stores</code>, <code>Lifecycle methods</code>, <code>Actions</code>, <code>Sapper</code> and more.</p>
<p>You can also follow my <a target="_blank" href="https://www.youtube.com/channel/UCg6SQd5jnWo5Y70rZD9SQFA">SvelteMaster Youtube Channel</a> and do sign up for the <a target="_blank" href="https://rebrand.ly/sveltebootcamp">Scrimba Svelte Bootcamp</a> to be the first to know about the launch and any discounts.</p>
<p>I hope you've found it useful and can put your brand-new knowledge to good use very soon.</p>
<p>In the meantime, why not <a target="_blank" href="https://scrimba.com/?utm_source=fcc&amp;utm_medium=referral&amp;utm_campaign=glearnsvelte_launch_article">head over to Scrimba</a> to see what other courses are on offer to help you reach your coding goals?</p>
<p>If you also want to hang out with your fellow learners or chat with more experienced folks and the creators of Scrimba courses, do join our <a target="_blank" href="https://discord.gg/mF6PcNU">Scrimba Discord server</a>.</p>
<p>Happy learning :)</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/SU25upz4WCI" 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[ The Svelte Handbook – Learn Svelte for Beginners ]]>
                </title>
                <description>
                    <![CDATA[ I wrote this book to help you quickly learn Svelte and get familiar with how it works. The ideal reader of the book has zero knowledge of Svelte, has maybe used Vue or React, but is looking for something more, or a new approach to things. Svelte is v... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/the-svelte-handbook/</link>
                <guid isPermaLink="false">66bb5abf3c5ab240beb8cdbf</guid>
                
                    <category>
                        <![CDATA[ frontend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ handbook ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Svelte ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Flavio Copes ]]>
                </dc:creator>
                <pubDate>Tue, 22 Oct 2019 11:37:47 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/10/Screen-Shot-2019-10-21-at-18.39.28.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>I wrote this book to help you quickly learn Svelte and get familiar with how it works.</p>
<p>The ideal reader of the book has zero knowledge of Svelte, has maybe used Vue or React, but is looking for <em>something</em> <em>more</em>, or a new approach to things.</p>
<p>Svelte is very much worth looking into, because it provides a refreshing point of view and several unique features to the Web.</p>
<p>Thank you for getting this ebook. I hope it will help you learn more about Svelte!</p>
<p>You can reach me on Twitter <a target="_blank" href="https://twitter.com/flaviocopes">@flaviocopes</a>. My website is <a target="_blank" href="https://flaviocopes.com/">flaviocopes.com</a>.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><a class="post-section-overview" href="#heading-introduction-to-svelte">Introduction to Svelte</a></li>
<li><a class="post-section-overview" href="#heading-svelte-components">Svelte Components</a></li>
<li><a class="post-section-overview" href="#heading-handling-state-in-svelte">Handling State in Svelte</a></li>
<li><a class="post-section-overview" href="#heading-svelte-reactivity">Svelte Reactivity</a></li>
<li><a class="post-section-overview" href="#heading-svelte-props">Svelte Props</a></li>
<li><a class="post-section-overview" href="#heading-cross-component-state-management-in-svelte">Cross-component State Management</a></li>
<li><a class="post-section-overview" href="#heading-slots">Slots</a></li>
<li><a class="post-section-overview" href="#heading-svelte-lifecycle-events">Svelte Lifecycle events</a></li>
<li><a class="post-section-overview" href="#heading-svelte-bindings">Svelte Bindings</a></li>
<li><a class="post-section-overview" href="#heading-conditional-logic-in-templates">Conditional Logic in Templates</a></li>
<li><a class="post-section-overview" href="#heading-looping-in-svelte-templates">Looping in Svelte Templates</a></li>
<li><a class="post-section-overview" href="#heading-promises-in-svelte-templates">Promises in Svelte Templates</a></li>
<li><a class="post-section-overview" href="#heading-working-with-events-in-svelte">Working with Events in Svelte</a></li>
<li><a class="post-section-overview" href="#heading-where-to-go-from-here">Where To Go From Here</a></li>
</ul>
<h2 id="heading-introduction-to-svelte">Introduction to Svelte</h2>
<p>Svelte is an exciting web frontend framework that you can use to build web applications.</p>
<p>If you're just starting out, Svelte is a great choice as your first frontend framework.</p>
<p>If you are already experienced in React, Vue.js, Angular or another frontend frameworks you will be pleasantly surprised by Svelte.</p>
<p>Compared to React, Vue, Angular and other frameworks, an app built using Svelte is <strong>compiled</strong> beforehand so you don't have to serve the whole framework to every one of your site visitors.</p>
<p>As a result, the fruition of the experience is smoother, consumes less bandwidth, and everything feels faster and more lightweight.</p>
<p>At deployment, Svelte disappears and all you get is plain (and fast!) JavaScript.</p>
<p>This is just the tip of the iceberg. Let's get into it!</p>
<p><a target="_blank" href="https://thevalleyofcode.com/download/svelte/">You can get a PDF and ePub version of this Svelte Handbook</a></p>
<h3 id="heading-how-to-get-started-with-svelte">How to get started with Svelte</h3>
<p>To use Svelte, you need to have Node.js installed because all the tooling we're going to use is based on Node.</p>
<blockquote>
<p>Make sure you also check out my <a target="_blank" href="https://thevalleyofcode.com/node/">Node.js Handbook</a></p>
</blockquote>
<p>One little tip I have is that the Svelte website provides a very cool "playground" to test out Svelte at <a target="_blank" href="https://svelte.dev/repl">https://svelte.dev/repl</a>.</p>
<p>It's pretty cool to test small Svelte apps and to experiment with things.</p>
<p>With the terminal, go into the folder where you usually keep your code, for example <code>dev</code> folder in your home.</p>
<p>Run this command on your computer:</p>
<pre><code class="lang-sh">npm create vite@latest helloworld -- --template svelte
</code></pre>
<p>This sets up everything you need to get started with your first Svelte application. I called it <code>helloworld</code> so you will see a folder with that name.</p>
<p>Go into that folder with <code>cd helloworld</code> and then run</p>
<pre><code class="lang-sh">npm install
</code></pre>
<p>and when this ends:</p>
<pre><code class="lang-sh">npm run dev
</code></pre>
<p>This runs our new Svelte site in development mode, starting the app on localhost on port 5173:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/Screen-Shot-2022-07-20-at-20.01.29.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>If you point your browser there, you'll see the sample project showing up:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/Screen-Shot-2022-07-20-at-20.04.08.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You're now ready to open the code in your favorite editor, for example <strong>VS Code</strong>.</p>
<p>You can do that running <code>code .</code> in the folder, if you've installed the <a target="_blank" href="https://code.visualstudio.com/docs/editor/command-line">The Visual Studio Code command-line interface</a>.</p>
<p>As soon as you open the project in the the editor, VS Code will prompt you to install the <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode">Svelte for VS Code</a> extension (if it doesn't, go to the extensions panel and search it):</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/Screen-Shot-2022-07-20-at-20.09.04.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Install it, as it provides the code highlighter and other features:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/Screen-Shot-2022-07-20-at-20.10.11.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Now back to the project!</p>
<p>Open the <code>src</code> folder, you will see a few files in there. The main one, pun intended, is <code>main.js</code>, where the Svelte application is set up:</p>
<p>This file is the entry point and initializes the main App component, which is defined in <code>App.svelte</code>:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> svelteLogo <span class="hljs-keyword">from</span> <span class="hljs-string">'./assets/svelte.svg'</span>
  <span class="hljs-keyword">import</span> Counter <span class="hljs-keyword">from</span> <span class="hljs-string">'./lib/Counter.svelte'</span>
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">main</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">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://vitejs.dev"</span> <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"/vite.svg"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"logo"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Vite Logo"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://svelte.dev"</span> <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{svelteLogo}"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"logo svelte"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Svelte Logo"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">a</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">h1</span>&gt;</span>Vite + Svelte<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Counter</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">p</span>&gt;</span>
    Check out
    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://github.com/sveltejs/kit#readme"</span> <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>
      &gt;</span>SvelteKit<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>
    &gt;</span>, the official Svelte app framework powered by Vite!
  <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"read-the-docs"</span>&gt;</span>Click on the Vite and Svelte logos to learn more<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
  <span class="hljs-selector-class">.logo</span> {
    <span class="hljs-attribute">height</span>: <span class="hljs-number">6em</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">1.5em</span>;
    <span class="hljs-attribute">will-change</span>: filter;
  }
  <span class="hljs-selector-class">.logo</span><span class="hljs-selector-pseudo">:hover</span> {
    <span class="hljs-attribute">filter</span>: <span class="hljs-built_in">drop-shadow</span>(<span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">2em</span> #<span class="hljs-number">646</span>cffaa);
  }
  <span class="hljs-selector-class">.logo</span><span class="hljs-selector-class">.svelte</span><span class="hljs-selector-pseudo">:hover</span> {
    <span class="hljs-attribute">filter</span>: <span class="hljs-built_in">drop-shadow</span>(<span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">2em</span> #ff3e00aa);
  }
  <span class="hljs-selector-class">.read-the-docs</span> {
    <span class="hljs-attribute">color</span>: <span class="hljs-number">#888</span>;
  }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p>See, we have 3 main sections:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

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

<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p>This is what we call a <strong>single file component</strong>, a single file that determines all about our component:</p>
<ul>
<li>the markup (the HTML)</li>
<li>the behavior (the JavaScript)</li>
<li>the style (the CSS)</li>
</ul>
<p>This structure will be the base for all your Svelte components.</p>
<h2 id="heading-svelte-components">Svelte Components</h2>
<p>Modern Web development is very much focused on components, and Svelte is no different.</p>
<p>What is a component? A component is an atomic part of the application that is self-contained and optionally references other components to compose its output.</p>
<p>In other words, it's an atomic part of the application.</p>
<p>A form can be a component.</p>
<p>An input element can be a component.</p>
<p>The whole application is a component.</p>
<p>Svelte components contain all that's needed to render a piece of the UI.</p>
<p>Every Svelte component is declared in a <code>.svelte</code> file, and in there you'll find the content (markup), the behavior (JavaScript), and the presentation (CSS) without having to define separate files.</p>
<p>Which is a good way to define a piece of the UI because you don't need to search for the items that affect the same element across various files.</p>
<p>Here's a sample component, which we'll store in a file called <code>Dog.svelte</code>:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">let</span> name
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
  <span class="hljs-selector-tag">h1</span> {
    <span class="hljs-attribute">color</span>: purple;
  }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>The dog name is {name}!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
</code></pre>
<p>JavaScript code must be put in the <code>script</code> tag.</p>
<p>The CSS you have in the <code>style</code> tag is <strong>scoped</strong> to the component and does not "leak" outside.</p>
<p>If another component has an <code>h1</code> tag, this style will not affect that.</p>
<p>This is very handy when reusing components you already wrote for other applications, for example, or when you include Open Source libraries published by other people.</p>
<p>For example you can include a date picker component built by someone else and none of the stylings of the component will affect the rest of the application.</p>
<p>And in the same way, none of the CSS you wrote will modify the look of the date picker.</p>
<h3 id="heading-importing-the-component-in-other-components">Importing the component in other components</h3>
<p>A component can be used by other components.</p>
<p>Other components can now import the <code>Dog</code> component we wrote in their code.</p>
<p>For example here's a <code>House</code> component:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> Dog <span class="hljs-keyword">from</span> <span class="hljs-string">'./Dog.svelte'</span>
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>You can now import and use the Dog component, as if it was an HTML tag:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> Dog <span class="hljs-keyword">from</span> <span class="hljs-string">'./Dog.svelte'</span>
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">Dog</span> /&gt;</span>
</code></pre>
<h3 id="heading-exporting-specific-functions-from-a-component">Exporting specific functions from a component</h3>
<p>As you saw above, to export the component we didn't have to do anything, because the component itself is the <strong>default export</strong>.</p>
<p>What if you want to export something other than the component markup and its associated and built-in functionality?</p>
<p>You must write all the functions you want to export from a special <code>script</code> tag with the <code>context="module"</code> attribute.</p>
<p>Here's an example. Say you have a Button component in <code>Button.svelte</code>:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>A button<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
</code></pre>
<p>and you want to provide other components the ability to change the color of the button.</p>
<blockquote>
<p>A better solution for this use case is to use props, which is something we'll talk about in the next chapter. But stick with me for this example</p>
</blockquote>
<p>You can provide a function, called <code>changeColor</code>.</p>
<p>You write and export it in this special <code>script</code> tag:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">context</span>=<span class="hljs-string">"module"</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">changeColor</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-comment">//...logic to change color..</span>
  }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>A button<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
</code></pre>
<p>Note that you can have another "normal" script tag, in the component.</p>
<p>Now other components can import Button, which is the default export, and the <code>changeColor</code> function too:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> Button, { changeColor } <span class="hljs-keyword">from</span> <span class="hljs-string">'./Button.svelte'</span>
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>Now that is probably a silly example, but knowing you can use this functionality can be quite helpful.</p>
<h2 id="heading-handling-state-in-svelte">Handling State in Svelte</h2>
<p>Every component, in addition to defining the markup, the CSS and the JavaScript logic, can host its own <strong>state</strong>.</p>
<p>What is state? State is any data that's needed to make the component render what it's rendering.</p>
<p>For example, if a form input field has the string "test" written into it, there'll be a variable somewhere holding this value. That's the state of the input field.</p>
<p>The field is selected? A variable somewhere will register this fact. And so on.</p>
<p>State is defined in the <code>script</code> part of a component:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">let</span> count = <span class="hljs-number">0</span>
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>To update the value of a state variable all you need is an assignment. A simple JavaScript assignment, for example using the <code>=</code> operator.</p>
<p>Say you have a <code>count</code> variable. You can increment that using, simply, <code>count = count + 1</code>, or even <code>count++</code>:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">let</span> count = <span class="hljs-number">0</span>

  <span class="hljs-keyword">const</span> incrementCount = <span class="hljs-function">() =&gt;</span> {
    count++
  }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

{count} <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">"{incrementCount}"</span>&gt;</span>+1<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
</code></pre>
<p>I find this one of the refreshing parts of Svelte, as in React for example you'd have to use the <code>useState()</code> hook, and use a setter function any time you want to update the value of the state variable.</p>
<p>This is more intuitive and much more "JavaScript-like" syntax.</p>
<p>We need to be aware of one thing, which is learned pretty quickly: we must also make an assignment when changing the value.</p>
<p>Svelte always wants an assignment, otherwise it might not recognize that the state changed.</p>
<p>For simple values like strings and numbers, that's mostly a given, because all methods on String return new strings, and same for numbers - they are immutable.</p>
<p>But for arrays? We can't use methods that alter the array. Like <code>push()</code>, <code>pop()</code>, <code>shift()</code>, <code>splice()</code>... because there's no assignment. They change the inner data structure, but Svelte can't detect that.</p>
<p>Well, you <em>can</em> still use them, but after you've done your operation, you can use a "trick" and reassign the variable to itself, like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> list = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]
list.push(<span class="hljs-number">4</span>)
list = list
</code></pre>
<p>It's is a bit counter-intuitive, compared to what I just said before, but it's a quirk you'll remember with experience.</p>
<p>Of course you could use alternatives that avoid you this situation, for example instead of using <code>Array.push()</code> you can use the spread operator to add an item:</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> list = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]
list = [...list, <span class="hljs-number">4</span>]
</code></pre>
<h2 id="heading-svelte-reactivity">Svelte Reactivity</h2>
<p>In Svelte you can listen for changes in the component state, and update other variables.</p>
<p>For example if you have a <code>count</code> variable:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">let</span> count = <span class="hljs-number">0</span>
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>and you update it by clicking a button:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">let</span> count = <span class="hljs-number">0</span>

  <span class="hljs-keyword">const</span> incrementCount = <span class="hljs-function">() =&gt;</span> {
    count = count + <span class="hljs-number">1</span>
  }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

{count} <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">"{incrementCount}"</span>&gt;</span>+1<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
</code></pre>
<p>You can listen for changes on <code>count</code> using the special syntax <code>$:</code> which defines a new block that Svelte will re-run when any variable referenced into it changes.</p>
<p>Here's an example:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">let</span> count = <span class="hljs-number">0</span>

  <span class="hljs-keyword">const</span> incrementCount = <span class="hljs-function">() =&gt;</span> {
    count = count + <span class="hljs-number">1</span>
  }

  <span class="hljs-attr">$</span>: <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${count}</span>`</span>)
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

{count} <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">"{incrementCount}"</span>&gt;</span>+1<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
</code></pre>
<p>I used the block:</p>
<pre><code class="lang-js">$: <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${count}</span>`</span>)
</code></pre>
<p>You can write more than one of them:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-attr">$</span>: <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`the count is <span class="hljs-subst">${count}</span>`</span>)
  <span class="hljs-attr">$</span>: <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`double the count is <span class="hljs-subst">${count * <span class="hljs-number">2</span>}</span>`</span>)
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>And you can also add a <strong>block</strong> (opening and closing curly brackets <code>{}</code>) to group more than one statement:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-attr">$</span>: {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`the count is <span class="hljs-subst">${count}</span>`</span>)
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`double the count is <span class="hljs-subst">${count * <span class="hljs-number">2</span>}</span>`</span>)
  }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>I used a <code>console.log()</code> call in there, but you can update other variables too:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">let</span> count = <span class="hljs-number">0</span>
  <span class="hljs-keyword">let</span> double = <span class="hljs-number">0</span>

  <span class="hljs-attr">$</span>: {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`the count is <span class="hljs-subst">${count}</span>`</span>)
    double = count * <span class="hljs-number">2</span>
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`double the count is <span class="hljs-subst">${double}</span>`</span>)
  }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<h2 id="heading-svelte-props">Svelte Props</h2>
<p>You can import a Svelte component into any other component using the syntax <code>import name from 'path'</code>, like this:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> SignupForm <span class="hljs-keyword">from</span> <span class="hljs-string">'./SignupForm.svelte'</span>
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<blockquote>
<p>The path is relative to the current component path. <code>./</code> means "this same folder". You'd use <code>../</code> to go back one folder, and so on.</p>
</blockquote>
<p>Once you do so, you can use the newly imported component in the markup, like an HTML tag:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">SignupForm</span> /&gt;</span>
</code></pre>
<p>In this way, you are forming a parent/child relationship between the two components: the one that imports, and the one that is imported.</p>
<p>Often you want to have the parent component pass data to the child component.</p>
<p>You can do so using <strong>props</strong>. Props behave similarly to attributes in plain HTML, and they are a one-way form of communication.</p>
<p>In this example we pass the <code>disabled</code> prop, passing the JavaScript value <code>true</code> to it:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">SignupForm</span> <span class="hljs-attr">disabled</span>=<span class="hljs-string">"{true}"</span> /&gt;</span>
</code></pre>
<p>In the SignupForm component, you need to <strong>export</strong> the <code>disabled</code> prop, in this way:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">let</span> disabled
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>This is the way you express the fact that the prop is exposed to parent components.</p>
<p>When using the component, you can pass a variable instead of a value, to change it dynamically:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> SignupForm <span class="hljs-keyword">from</span> <span class="hljs-string">'./SignupForm.svelte'</span>
  <span class="hljs-keyword">let</span> disabled = <span class="hljs-literal">true</span>
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">SignupForm</span> {<span class="hljs-attr">disabled</span>} /&gt;</span>
</code></pre>
<blockquote>
<p>Note I used <code>{disabled}</code> as a handy shorthand form for <code>disabled={disabled}</code></p>
</blockquote>
<p>When the <code>disabled</code> variable value changes, the child component will be updated with the new prop value. Example:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> SignupForm <span class="hljs-keyword">from</span> <span class="hljs-string">'./SignupForm.svelte'</span>
  <span class="hljs-keyword">let</span> disabled = <span class="hljs-literal">true</span>
  <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
    disabled = <span class="hljs-literal">false</span>
  }, <span class="hljs-number">2000</span>)
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">SignupForm</span> {<span class="hljs-attr">disabled</span>} /&gt;</span>
</code></pre>
<h2 id="heading-cross-component-state-management-in-svelte">Cross-component State Management in Svelte</h2>
<p>We've already seen how Svelte makes handling the state of a single component very easy.</p>
<p>But how do we pass state around across components?</p>
<h3 id="heading-passing-state-around-using-props">Passing state around using props</h3>
<p>The first strategy is common to other UI frameworks and it's passing state around using props, <strong>lifting the state up</strong>.</p>
<p>When a component needs to share data with another, the state can be moved up in the components tree until there's a common parent to those components.</p>
<p>The state needs to be passed down until it reaches all the components that need this state information.</p>
<p>This is done using <strong>props</strong>, and it's a technique that I think is the best as it's simple.</p>
<h3 id="heading-the-context-api">The context API</h3>
<p>However, there are cases where props are not practical. Perhaps 2 components are so distant in the components tree that we'd have to move state up to the top-level component.</p>
<p>In this case, another technique can be used and it's called <strong>context API</strong>, and it's ideal when you want to let multiple components communicate with descendants, but you don't want to pass props around.</p>
<p>The context API is provided by 2 functions which are provided by the <code>svelte</code> package: <code>getContext</code> and <code>setContext</code>.</p>
<p>You set an object in the context, associating it to a key:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> { setContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte'</span>

  <span class="hljs-keyword">const</span> someObject = {}

  setContext(<span class="hljs-string">'someKey'</span>, someObject)
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>In another component you can use <code>getContext</code> to retrieve the object assigned to a key:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> { getContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte'</span>

  <span class="hljs-keyword">const</span> someObject = getContext(<span class="hljs-string">'someKey'</span>)
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>You can only use <code>getContext</code> to retrieve a key either in the component that used <code>setContext</code> or in one of its descendants.</p>
<p>If you want to let two components living in 2 different component trees communicate there's another tool for us: <strong>stores</strong>.</p>
<h3 id="heading-using-svelte-stores">Using Svelte stores</h3>
<p>Svelte stores are a great tool to handle your app state when components need to talk to each other without passing props around too much.</p>
<p>You must first import <code>writable</code> from <code>svelte/store</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { writable } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte/store'</span>
</code></pre>
<p>and create a store variable using the <code>writable()</code> function, passing the default value as the first argument:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> username = writable(<span class="hljs-string">'Guest'</span>)
</code></pre>
<p>This can be put into a separate file which you can import into multiple components, for example, called <code>store.js</code> (it's not a component, so it can be in a <code>.js</code> file instead of <code>.svelte</code>):</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { writable } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte/store'</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> username = writable(<span class="hljs-string">'Guest'</span>)
</code></pre>
<p>Any other component now loading this file can access the store:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> { username } <span class="hljs-keyword">from</span> <span class="hljs-string">'./store.js'</span>
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>Now the value of this variable can be set to a new value using <code>set()</code>, passing the new value as the first argument:</p>
<pre><code class="lang-js">username.set(<span class="hljs-string">'new username'</span>)
</code></pre>
<p>And it can be updated using the <code>update()</code> function, which differs from <code>set()</code> because you don't just pass the new value to it - you run a callback function that is passed the current value as its argument:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> newUsername = <span class="hljs-string">'new username!'</span>
username.update(<span class="hljs-function">(<span class="hljs-params">existing</span>) =&gt;</span> newUsername)
</code></pre>
<p>You can add more logic here:</p>
<pre><code class="lang-js">username.update(<span class="hljs-function">(<span class="hljs-params">existing</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Updating username from <span class="hljs-subst">${existing}</span> to <span class="hljs-subst">${newUsername}</span>`</span>)
  <span class="hljs-keyword">return</span> newUsername
})
</code></pre>
<p>To get the value of the store variable <em>once</em>, you can use the <code>get()</code> function exported by <code>svelte/store</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { writable, get } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte/store'</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> username = writable(<span class="hljs-string">'Guest'</span>)
get(username) <span class="hljs-comment">//'Guest'</span>
</code></pre>
<p>To create a reactive variable that's updated whenever the store value changes instead, you can prepend the store variable using <code>$</code> (in this example <code>$username</code>). Using that will make the component re-render whenever the stored value changes.</p>
<blockquote>
<p>Svelte considers <code>$</code> to be a reserved value and will prevent you to use it for things that are not related to stores values (which might lead to confusion), so if you are used to prepending DOM references using <code>$</code>, don't do it in Svelte.</p>
<p>Another option, best suited if you need to execute some logic when the variable changes, is to use the <code>subscribe()</code> method of <code>username</code>:</p>
</blockquote>
<pre><code class="lang-js">username.subscribe(<span class="hljs-function">(<span class="hljs-params">newValue</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(newValue)
})
</code></pre>
<p>In addition to writable stores, Svelte provides 2 special kinds of stores: <strong>readable stores</strong> and <strong>derived stores</strong>.</p>
<h3 id="heading-svelte-readable-stores">Svelte Readable Stores</h3>
<p>Readable stores are special because they can't be updated from the outside - there's no <code>set()</code> or <code>update()</code> method. Instead, once you set the initial state, they can't be modified from the outside.</p>
<p>The official Svelte docs show an interesting example using a timer to update a date. I can think of setting up a timer to fetch a resource from the network, perform an API call, get data from the filesystem (using a local Node.js server) or anything else that can be set up autonomously.</p>
<p>In this case instead of using <code>writable()</code> to initialize the store variable, we use <code>readable()</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { readable } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte/store'</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> count = readable(<span class="hljs-number">0</span>)
</code></pre>
<p>You can provide a function after the default value, that will be responsible for updating it. This function receives the <code>set</code> function to modify the value:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> { readable } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte/store'</span>
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> count = readable(<span class="hljs-number">0</span>, <span class="hljs-function">(<span class="hljs-params">set</span>) =&gt;</span> {
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
      set(<span class="hljs-number">1</span>)
    }, <span class="hljs-number">1000</span>)
  })
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>In this case, we update the value from 0 to 1 after 1 second.</p>
<p>You can setup an interval in this function, too:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { readable, get } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte/store'</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> count = readable(<span class="hljs-number">0</span>, <span class="hljs-function">(<span class="hljs-params">set</span>) =&gt;</span> {
  <span class="hljs-built_in">setInterval</span>(<span class="hljs-function">() =&gt;</span> {
    set(get(count) + <span class="hljs-number">1</span>)
  }, <span class="hljs-number">1000</span>)
})
</code></pre>
<p>You can use this in another component like this:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> { count } <span class="hljs-keyword">from</span> <span class="hljs-string">'./store.js'</span>
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

{$count}
</code></pre>
<h3 id="heading-svelte-derived-stores">Svelte Derived Stores</h3>
<p>A derived store allows you to create a new store value that depends on the value of an existing store.</p>
<p>You can do so using the <code>derived()</code> function exported by <code>svelte/store</code> which takes as its first parameter the existing store value, and as a second parameter a function which receives that store value as its first parameter:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { writable, derived } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte/store'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> username = writable(<span class="hljs-string">'Guest'</span>)

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> welcomeMessage = derived(username, <span class="hljs-function">(<span class="hljs-params">$username</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="hljs-string">`Welcome <span class="hljs-subst">${$username}</span>`</span>
})
</code></pre>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> { username, welcomeMessage } <span class="hljs-keyword">from</span> <span class="hljs-string">'./store.js'</span>
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

{$username} {$welcomeMessage}
</code></pre>
<h2 id="heading-slots">Slots</h2>
<p>Slots are a handy way to let you define components that can be composed together.</p>
<p>And vice versa, depending on your point of view, slots are a handy way to configure a component you are importing.</p>
<p>Here's how they work.</p>
<p>In a component you can define a slot using the <code>&lt;slot /&gt;</code> (or <code>&lt;slot&gt;&lt;/slot&gt;</code>) syntax.</p>
<p>Here's a <code>Button.svelte</code> component that simply prints a <code>&lt;button&gt;</code> HTML tag:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">slot</span> /&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
</code></pre>
<blockquote>
<p>For React developers, this is basically the same as <code>&lt;button&gt;{props.children}&lt;/button&gt;</code></p>
</blockquote>
<p>Any component importing it can define content that is going to be put into the slot by adding it into the component's opening and closing tags:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> Button <span class="hljs-keyword">from</span> <span class="hljs-string">'./Button.svelte'</span>
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>Insert this into the slot<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
</code></pre>
<p>You can define a default, which is used if the slot is not filled:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">slot</span>&gt;</span> Default text for the button <span class="hljs-tag">&lt;/<span class="hljs-name">slot</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
</code></pre>
<p>You can have more than one slot in a component, and you can distinguish one from the other using named slots. The single unnamed slot will be the default one:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">slot</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"before"</span> /&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">slot</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">slot</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"after"</span> /&gt;</span>
</code></pre>
<p>Here's how you would use it:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> Button <span class="hljs-keyword">from</span> <span class="hljs-string">'./Button.svelte'</span>
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>
  Insert this into the slot
  <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"before"</span>&gt;</span>Add this before<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"after"</span>&gt;</span>Add this after<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
</code></pre>
<p>And this would render the following to the DOM:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"before"</span>&gt;</span>Add this before<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>Insert this into the slot<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"after"</span>&gt;</span>Add this after<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
</code></pre>
<h2 id="heading-svelte-lifecycle-events">Svelte Lifecycle events</h2>
<p>Every component in Svelte fires several lifecycle events that we can hook on, to help us implement the functionality we have in mind.</p>
<p>In particular, we have</p>
<ul>
<li><code>onMount</code> fired after the component is rendered</li>
<li><code>onDestroy</code> fired after the component is destroyed</li>
<li><code>beforeUpdate</code> fired before the DOM is updated</li>
<li><code>afterUpdate</code> fired after the DOM is updated</li>
</ul>
<p>We can schedule functions to happen when these events are fired by Svelte.</p>
<p>We don't have access to any of those methods by default, but we need to import them from the <code>svelte</code> package:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> { onMount, onDestroy, beforeUpdate, afterUpdate } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte'</span>
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>A common scenario for <code>onMount</code> is to fetch data from other sources.</p>
<p>Here's a sample usage of <code>onMount</code>:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> { onMount } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte'</span>

  onMount(<span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-comment">//do something on mount</span>
  })
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p><code>onDestroy</code> allows us to clean up data or stop any operation we might have started at the component initialization, like timers or scheduled periodic functions using <code>setInterval</code>.</p>
<p>One particular thing to notice is that if we return a function from <code>onMount</code>, that serves the same functionality of <code>onDestroy</code> - it's run when the component is destroyed:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> { onMount } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte'</span>

  onMount(<span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-comment">//do something on mount</span>

    <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-comment">//do something on destroy</span>
    }
  })
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>Here's a practical example that sets a periodic function to run on mount, and removes it on destroy:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> { onMount } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte'</span>

  onMount(<span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> interval = <span class="hljs-built_in">setInterval</span>(<span class="hljs-function">() =&gt;</span> {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'hey, just checking!'</span>)
    }, <span class="hljs-number">1000</span>)

    <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-built_in">clearInterval</span>(interval)
    }
  })
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<h2 id="heading-svelte-bindings">Svelte Bindings</h2>
<p>Using Svelte you can create a two-way binding between data and the UI.</p>
<p>Many other Web frameworks can provide two-way bindings, it's a very common UI design pattern.</p>
<p>They are especially useful with forms.</p>
<h3 id="heading-bindvalue">bind:value</h3>
<p>Let's start with the most common form of binding you'll often use, which you can apply using <code>bind:value</code>. You take a variable from the component state, and you bind it to a form field:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">let</span> name = <span class="hljs-string">''</span>
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">bind:value</span>=<span class="hljs-string">"{name}"</span> /&gt;</span>
</code></pre>
<p>Now if <code>name</code> changes the input field will update its value. And the opposite is true, as well: if the form is updated by the user, the <code>name</code> variable value changes.</p>
<blockquote>
<p>Just be aware that the variable must be defined using <code>let/var</code> and not <code>const</code>, otherwise it can't be updated by Svelte, as <code>const</code> defines a variable with a value that can't be reassigned.</p>
</blockquote>
<p><code>bind:value</code> works on all flavors of input fields (<code>type="number"</code>, <code>type="email"</code> and so on), but it also works for other kind of fields, like <code>textarea</code> and <code>select</code> (more on <code>select</code> later).</p>
<h3 id="heading-checkboxes-and-radio-buttons">Checkboxes and radio buttons</h3>
<p>Checkboxes and radio inputs (<code>input</code> elements with <code>type="checkbox"</code> or <code>type="radio"</code>) allow those 3 bindings:</p>
<ul>
<li><code>bind:checked</code></li>
<li><code>bind:group</code></li>
<li><code>bind:indeterminate</code></li>
</ul>
<p><code>bind:checked</code> allows us to bind a value to the checked state of the element:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">let</span> isChecked
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"checkbox"</span> <span class="hljs-attr">bind:checked</span>=<span class="hljs-string">"{isChecked}"</span> /&gt;</span>
</code></pre>
<p><code>bind:group</code> is handy with checkboxes and radio inputs, because those are very often used in groups. Using <code>bind:group</code> you can associate a JavaScript array to a list of checkboxes, and have it populated based on the choices made by the user.</p>
<p>Here's an example. The <code>goodDogs</code> array populates based on the checkboxes I tick:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">let</span> goodDogs = []
  <span class="hljs-keyword">let</span> dogs = [<span class="hljs-string">'Roger'</span>, <span class="hljs-string">'Syd'</span>]
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Who's a good dog?<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
  {#each dogs as dog}
  <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>{dog} <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"checkbox"</span> <span class="hljs-attr">bind:group</span>=<span class="hljs-string">"{goodDogs}"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"{dog}"</span> /&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
  {/each}
<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Good dogs according to me:<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
  {#each goodDogs as dog}
  <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>{dog}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
  {/each}
<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
</code></pre>
<p><a target="_blank" href="https://svelte.dev/repl/059c1b5edffc4b058ad36301dd7a1a58">See the example</a></p>
<p><code>bind:indeterminate</code> allows us to bind to the <code>indeterminate</code> state of an element (if you want to learn more head to <a target="_blank" href="https://css-tricks.com/indeterminate-checkboxes/">https://css-tricks.com/indeterminate-checkboxes/</a>)</p>
<h3 id="heading-select-fields">Select fields</h3>
<p><code>bind:value</code> also works for the <code>select</code> form field to get the selected value automatically assigned to the value of a variable:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">let</span> selected
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">bind:value</span>=<span class="hljs-string">"{selected}"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"1"</span>&gt;</span>1<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"2"</span>&gt;</span>2<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"3"</span>&gt;</span>3<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span>

{selected}
</code></pre>
<p>The cool thing is that if you generate options dynamically from an array of objects, the selected option is now an object, not a string:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">let</span> selected

  <span class="hljs-keyword">const</span> dogs = [{ <span class="hljs-attr">name</span>: <span class="hljs-string">'Roger'</span> }, { <span class="hljs-attr">name</span>: <span class="hljs-string">'Syd'</span> }]
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>List of possible good dogs:<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">bind:value</span>=<span class="hljs-string">"{selected}"</span>&gt;</span>
  {#each dogs as dog}
  <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"{dog}"</span>&gt;</span>{dog.name}<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
  {/each}
<span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span>

{#if selected}
<span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Dog selected: {selected.name}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
{/if}
</code></pre>
<p><a target="_blank" href="https://svelte.dev/repl/7e06f9b7becd4c57880db5ed184ea0f3">See this example</a></p>
<p><code>select</code> also allows the <code>multiple</code> attribute:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">let</span> selected = []

  <span class="hljs-keyword">const</span> goodDogs = [{ <span class="hljs-attr">name</span>: <span class="hljs-string">'Roger'</span> }, { <span class="hljs-attr">name</span>: <span class="hljs-string">'Syd'</span> }]
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>List of possible good dogs:<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">multiple</span> <span class="hljs-attr">bind:value</span>=<span class="hljs-string">"{selected}"</span>&gt;</span>
  {#each goodDogs as goodDog}
  <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"{goodDog}"</span>&gt;</span>{goodDog.name}<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
  {/each}
<span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span>

{#if selected.length}
<span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Good dog selected:<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
  {#each selected as dog}
  <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>{dog.name}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
  {/each}
<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
{/if}
</code></pre>
<p><a target="_blank" href="https://svelte.dev/repl/b003248e87f04919a2f9fed63dbdab8c">See this example</a></p>
<h3 id="heading-other-bindings">Other bindings</h3>
<p>Depending on the HTML tag you are working on, you can apply different kinds of bindings.</p>
<p><code>bind:files</code> is a binding valid on <code>type="file"</code> input elements, to bind the list of selected files.</p>
<p>The <code>details</code> HTML element allows the use of <code>bind:open</code> to bind its open/close value.</p>
<p>The <code>audio</code> and <code>video</code> media HTML tags allow to bind several of their properties: <code>currentTime</code>, <code>duration</code>, <code>paused</code>, <code>buffered</code>, <code>seekable</code>, <code>played</code>, <code>volume</code>, <code>playbackRate</code>.</p>
<p><code>textContent</code> and <code>innerHTML</code> can be bound on <code>contenteditable</code> fields.</p>
<p>All things very useful for those specific HTML elements.</p>
<h3 id="heading-read-only-bindings">Read-only bindings</h3>
<p><code>offsetWidth</code>, <code>offsetHeight</code>, <code>clientWidth</code>, <code>clientHeight</code> can be bound, read only, on any block level HTML element, excluding void tags (like <code>br</code>) and elements that are set to be inline (<code>display: inline</code>).</p>
<h3 id="heading-get-a-reference-to-the-html-element-in-javascript">Get a reference to the HTML element in JavaScript</h3>
<p><code>bind:this</code> is a special kind of binding that allows you to get a reference to an HTML element and bind it to a JavaScript variable:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">let</span> myInputField
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">bind:this</span>=<span class="hljs-string">"{myInputField}"</span> /&gt;</span>
</code></pre>
<p>This is handy when you need to apply logic to elements after you mount them, for example, using the <code>onMount()</code> lifecycle event callback.</p>
<h3 id="heading-binding-components-props">Binding components props</h3>
<p>Using <code>bind:</code> you can bind a value to any prop that a component exposes.</p>
<p>Say you have a <code>Car.svelte</code> component:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
<span class="hljs-keyword">export</span> <span class="hljs-keyword">let</span> inMovement = <span class="hljs-literal">false</span>
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{()</span> =&gt;</span> inMovement = true }&gt;Start car<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
</code></pre>
<p>You can import the component and bind the <code>inMovement</code> prop:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> Car <span class="hljs-keyword">from</span> <span class="hljs-string">'./Car.svelte'</span>

  <span class="hljs-keyword">let</span> carInMovement
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">Car</span> <span class="hljs-attr">bind:inMovement</span>=<span class="hljs-string">"{carInMovement}"</span> /&gt;</span>

{carInMovement}
</code></pre>
<p>This can allow for interesting scenarios.</p>
<h2 id="heading-conditional-logic-in-templates">Conditional Logic in Templates</h2>
<p>In a Svelte component, when it comes to rendering HTML you can work with some specific syntax to craft the UI you need at every stage of the application lifecycle.</p>
<p>In particular, we'll now explore conditional structures.</p>
<p>The problem is this: you want to be able to look at a value/expression, and if that points to a true value do something if that points to a false value then do something else.</p>
<p>Svelte provides us a very powerful set of control structures.</p>
<p>The first is <strong>if</strong>:</p>
<pre><code class="lang-html">{#if isRed}
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Red<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
{/if}
</code></pre>
<p>There is an opening <code>{#if}</code> and an ending <code>{/if}</code>. The opening markup checks for a value or statement to be truthy. In this case <code>isRed</code> can be a boolean with a <code>true</code> value:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">let</span> isRed = <span class="hljs-literal">true</span>
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>An empty string is falsy, but a string with some content is truthy.</p>
<p>0 is falsy, but a number &gt; 0 is truthy.</p>
<p>The boolean value <code>true</code> is truthy, of course, and <code>false</code> is falsy.</p>
<p>If the opening markup is not satisfied (a falsy value is provided), then nothing happens.</p>
<p>To do something else if that's not satisfied, we use the appropriately called <code>else</code> statement:</p>
<pre><code class="lang-html">{#if isRed}
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Red<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
{:else}
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Not red<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
{/if}
</code></pre>
<p>Either the first block is rendered in the template or the second one. There's no other option.</p>
<p>You can use any JavaScript expression into the <code>if</code> block condition, so you can negate an option using the <code>!</code> operator:</p>
<pre><code class="lang-html">{#if !isRed}
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Not red<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
{:else}
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Red<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
{/if}
</code></pre>
<p>Now, inside the <code>else</code> you might want to check for an additional condition. That's where the <code>{:else if somethingElse}</code> syntax comes along:</p>
<pre><code class="lang-html">{#if isRed}
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Red<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
{:else if isGreen}
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Green<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
{:else}
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Not red nor green<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
{/if}
</code></pre>
<p>You can have many of these blocks, not just one, and you can nest them. Here's a more complex example:</p>
<pre><code class="lang-html">{#if isRed}
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Red<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
{:else if isGreen}
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Green<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
{:else if isBlue}
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>It is blue<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
{:else} {#if isDog}
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>It is a dog<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
{/if} {/if}
</code></pre>
<h2 id="heading-looping-in-svelte-templates">Looping in Svelte Templates</h2>
<p>In Svelte templates you can create a loop using the <code>{#each}{/each}</code> syntax:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">let</span> dogs = [<span class="hljs-string">'Roger'</span>, <span class="hljs-string">'Syd'</span>]
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

{#each dogs as dog}
<span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>{dog}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
{/each}
</code></pre>
<p>If you are familiar with other frameworks that use templates, it's a very similar syntax.</p>
<p>You can get the index of the iteration using:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">let</span> dogs = [<span class="hljs-string">'Roger'</span>, <span class="hljs-string">'Syd'</span>]
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

{#each dogs as dog, index}
<span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>{index}: {dog}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
{/each}
</code></pre>
<p>(indexes start at 0)</p>
<p>When dynamically editing the lists removing and adding elements, you should always pass an identifier in lists, to prevent issues.</p>
<p>You do so using this syntax:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">let</span> dogs = [<span class="hljs-string">'Roger'</span>, <span class="hljs-string">'Syd'</span>]
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

{#each dogs as dog (dog)}
<span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>{dog}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
{/each}

<span class="hljs-comment">&lt;!-- with the index --&gt;</span>
{#each dogs as dog, index (dog)}
<span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>{dog}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
{/each}
</code></pre>
<p>You can pass an object, too, but if your list has a unique identifier for each element, it's best to use it:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">let</span> dogs = [
    { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Roger'</span> },
    { <span class="hljs-attr">id</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Syd'</span> },
  ]
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

{#each dogs as dog (dog.id)}
<span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>{dog.name}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
{/each}

<span class="hljs-comment">&lt;!-- with the index --&gt;</span>
{#each dogs as dog, index (dog.id)}
<span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>{dog.name}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
{/each}
</code></pre>
<h2 id="heading-promises-in-svelte-templates">Promises in Svelte Templates</h2>
<p>Promises are an awesome tool we have at our disposal to work with asynchronous events in JavaScript.</p>
<p>The relatively recent introduction of the <code>await</code> syntax in ES2017 made using promises even simpler.</p>
<p>Svelte provides us the <code>{#await}</code> syntax in templates to directly work with promises at the template level.</p>
<p>We can wait for promises to resolve, and define a different UI for the various states of a promise: unresolved, resolved and rejected.</p>
<p>Here's how it works. We define a promise, and using the <code>{#await}</code> block we wait for it to resolve.</p>
<p>Once the promise resolves, the result is passed to the <code>{:then}</code> block:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">const</span> fetchImage = (<span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'https://dog.ceo/api/breeds/image/random'</span>)
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> response.json()
  })()
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

{#await fetchImage}
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>...waiting<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
{:then data}
<span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{data.message}"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Dog image"</span> /&gt;</span>
{/await}
</code></pre>
<p>You can detect a promise rejection by adding a <code>{:catch}</code> block:</p>
<pre><code class="lang-html">{#await fetchImage}
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>...waiting<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
{:then data}
<span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{data.message}"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Dog image"</span> /&gt;</span>
{:catch error}
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>An error occurred!<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
{/await}
</code></pre>
<p><a target="_blank" href="https://svelte.dev/repl/70e61d6cc91345cdaca2db9b7077a941">Run the example</a></p>
<h2 id="heading-working-with-events-in-svelte">Working with Events in Svelte</h2>
<h3 id="heading-listening-to-dom-events">Listening to DOM events</h3>
<p>In Svelte you can define a listener for a DOM event directly in the template, using the <code>on:&lt;event&gt;</code> syntax.</p>
<p>For example, to listen to the <code>click</code> event, you will pass a function to the <code>on:click</code> attribute.</p>
<p>To listen to the <code>onmousemove</code> event, you'll pass a function to the <code>on:mousemove</code> attribute.</p>
<p>Here's an example with the handling function defined inline:</p>
<pre><code class="lang-js">&lt;button
  <span class="hljs-attr">on</span>:click={<span class="hljs-function">() =&gt;</span> {
    alert(<span class="hljs-string">'clicked'</span>)
  }}
&gt;
  Click me
&lt;/button&gt;
</code></pre>
<p>and here's another example with the handling function defined in the <code>script</code> section of the component:</p>
<pre><code class="lang-js">&lt;script&gt;
<span class="hljs-keyword">const</span> doSomething = <span class="hljs-function">() =&gt;</span> {
  alert(<span class="hljs-string">'clicked'</span>)
}
&lt;/script&gt;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{doSomething}</span>&gt;</span>Click me<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
</code></pre>
<p>I prefer inline when the code is not too verbose. If it's just 2-3 lines, for example, otherwise I'd move that up in the script section.</p>
<p>Svelte passes the event handler as the argument of the function, which is handy if you need to stop propagation or to reference something in the <a target="_blank" href="https://flaviocopes.com/javascript-events/#the-event-object">Event object</a>:</p>
<pre><code class="lang-js">&lt;script&gt;
<span class="hljs-keyword">const</span> doSomething = <span class="hljs-function"><span class="hljs-params">event</span> =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(event)
  alert(<span class="hljs-string">'clicked'</span>)
}
&lt;/script&gt;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{doSomething}</span>&gt;</span>Click me<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
</code></pre>
<p>Now, I mentioned "stop propagation". That's a very common thing to do, to stop form submit events for example. Svelte provides us <strong>modifiers</strong>, a way to apply it directly without manually doing it.<br><code>stopPropagation</code> and <code>preventDefault</code> are the 2 modifiers you'll use the most, I think.</p>
<p>You apply a modifier like this: <code>&lt;button on:click|stopPropagation|preventDefault={doSomething}&gt;Click me&lt;/button&gt;</code></p>
<p>There are other modifiers, which are more niche. <code>capture</code> enables <a target="_blank" href="https://flaviocopes.com/javascript-events/#event-bubbling-and-event-capturing">capturing events instead of bubbling</a>, <code>once</code> only fires the event once, <code>self</code> only fires the event if the target of the event is this object (removing it from the bubbling/capturing hierarchy).</p>
<h3 id="heading-creating-your-events-in-components">Creating your events in components</h3>
<p>What's interesting is that we can create custom events in components, and use the same syntax of built-in DOM events.</p>
<p>To do so, we must import the <code>createEventDispatcher</code> function from the <code>svelte</code> package and call it to get an event dispatcher:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> { createEventDispatcher } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte'</span>
  <span class="hljs-keyword">const</span> dispatch = createEventDispatcher()
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>Once we do so, we can call the <code>dispatch()</code> function, passing a string that identifies the event (which we'll use for the <code>on:</code> syntax in other components that use this):</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> { createEventDispatcher } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte'</span>
  <span class="hljs-keyword">const</span> dispatch = createEventDispatcher()

  <span class="hljs-comment">//when it's time to trigger the event</span>
  dispatch(<span class="hljs-string">'eventName'</span>)
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>Now other components can use ours using</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">ComponentName</span> <span class="hljs-attr">on:eventName</span>=<span class="hljs-string">{event</span> =&gt;</span> { //do something }} /&gt;
</code></pre>
<p>You can also pass an object to the event, passing a second parameter to <code>dispatch()</code>:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> { createEventDispatcher } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte'</span>
  <span class="hljs-keyword">const</span> dispatch = createEventDispatcher()
  <span class="hljs-keyword">const</span> value = <span class="hljs-string">'something'</span>

  <span class="hljs-comment">//when it's time to trigger the event</span>
  dispatch(<span class="hljs-string">'eventName'</span>, value)

  <span class="hljs-comment">//or</span>

  dispatch(<span class="hljs-string">'eventName'</span>, {
    <span class="hljs-attr">someProperty</span>: value,
  })
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>the object passed by <code>dispatch()</code> is available on the <code>event</code> object.</p>
<h2 id="heading-where-to-go-from-here">Where To Go From Here</h2>
<p>I hope this little handbook was useful to shine a light on what Svelte can do for you, and I hope you are now interested to learn more about it!</p>
<p>I can now point you to two places to learn more:</p>
<ul>
<li><a target="_blank" href="https://svelte.dev/">The official Svelte website</a></li>
<li><a target="_blank" href="https://kit.svelte.dev/">SvelteKit</a>, an awesome framework built on top of Svelte that lets you build server-side rendered apps with Node.js and Svelte</li>
</ul>
<p><a target="_blank" href="https://thevalleyofcode.com/download/svelte/">You can get a PDF and ePub version of this Svelte Handbook</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn Svelte in 1 hour with this free course, then decide for yourself whether it's better than React ]]>
                </title>
                <description>
                    <![CDATA[ Learn Svelte in this full video tutorial from Classsed. You will build your first Svelte app that uses multiple routes, handles forms and consumes a full CRUD API. Svelte is a new approach to building user interfaces. It is a framework that really is... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/svelte-video-tutorial/</link>
                <guid isPermaLink="false">66b2068439b555ffda8bfeb8</guid>
                
                    <category>
                        <![CDATA[ Svelte ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Fri, 26 Jul 2019 15:17:19 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/07/svelte.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Learn Svelte in this full video tutorial from <a target="_blank" href="https://www.youtube.com/channel/UC2-slOJImuSc20Drbf88qvg">Classsed</a>. You will build your first Svelte app that uses multiple routes, handles forms and consumes a full CRUD API.</p>
<p>Svelte is a new approach to building user interfaces. It is a framework that really isn't a framework. Whereas traditional frameworks like React and Vue do the bulk of their work in the browser, Svelte shifts that work into a compile step that happens when you build your app.</p>
<p>After watching this video tutorial, you will have a good idea about how Svelte works. And you may even decide you like it more than React or Vue.</p>
<p>You can watch the full video course on the <a target="_blank" href="https://www.youtube.com/watch?v=vhGiGqZ78Rs">freeCodeCamp.org YouTube channel</a> (1 hour watch).</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
