<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Rui Sousa</title>
    <description>The latest articles on Forem by Rui Sousa (@itzami).</description>
    <link>https://forem.com/itzami</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F265256%2F04e9ce80-a4aa-411c-a4b6-f39f019d1123.jpg</url>
      <title>Forem: Rui Sousa</title>
      <link>https://forem.com/itzami</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/itzami"/>
    <language>en</language>
    <item>
      <title>How to build a blog with NodeJS</title>
      <dc:creator>Rui Sousa</dc:creator>
      <pubDate>Thu, 31 Oct 2024 17:02:21 +0000</pubDate>
      <link>https://forem.com/itzami/how-to-build-a-blog-with-nodejs-3n5c</link>
      <guid>https://forem.com/itzami/how-to-build-a-blog-with-nodejs-3n5c</guid>
      <description>&lt;p&gt;&lt;em&gt;Just want the code? Visit the &lt;a href="https://github.com/ItzaMi/nodejs-blog-starter" rel="noopener noreferrer"&gt;repo&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you're looking to start a blog (or if you're thinking of redesigning yours although you haven't posted in 2 years), you'll stumble upon &lt;a href="https://gohugo.io//" rel="noopener noreferrer"&gt;a&lt;/a&gt; &lt;a href="https://vercel.com/templates/next.js/blog-starter-kit" rel="noopener noreferrer"&gt;lot&lt;/a&gt; &lt;a href="https://jekyllrb.com/" rel="noopener noreferrer"&gt;of&lt;/a&gt; &lt;a href="https://www.11ty.dev/" rel="noopener noreferrer"&gt;options&lt;/a&gt; and it can be incredibly daunting; and if you stumble with the newest &lt;a href="https://www.joshwcomeau.com/blog/how-i-built-my-blog-v2/" rel="noopener noreferrer"&gt;Josh's post about his stack&lt;/a&gt; it is easy to feel overwhelmed with the shown stack.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But you shouldn't feel like that and starting small is key to being sustainable&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And how do I know that? Because I feel that sense of feeling overwhelmed as well!&lt;br&gt;
At this date, this website is done with &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;NextJS&lt;/a&gt;, &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Contentful&lt;/a&gt;, and &lt;a href="https://en.wikipedia.org/wiki/Markdown" rel="noopener noreferrer"&gt;Markdown&lt;/a&gt; and while adding posts to it is not particularly hard, maintaining it is!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I haven't added anything code-related to this website since &lt;a href="https://github.com/ItzaMi/itzami-blog/commit/a60c8e0fe30498d5b140c0576a3893ed7768930e" rel="noopener noreferrer"&gt;2021&lt;/a&gt; and at this point I don't even know if I'm able to run it locally (and I'm reticent even to try it out)!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For this 👆 particular reason, I want to preach for a simple stack; something that endures the test of time; something that 'just works'; so let's jump right into it, shall we?&lt;/p&gt;
&lt;h2&gt;
  
  
  Start that project!
&lt;/h2&gt;

&lt;p&gt;Keep in mind that this project will be very, very barebones but it should give you a good foundation for you to develop on top of it and &lt;a href="https://www.youtube.com/watch?v=byq2K2IYMlI" rel="noopener noreferrer"&gt;reach for the sky&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We'll start by initializing a Node project inside a chosen folder (&lt;code&gt;nodejs-blog&lt;/code&gt; for me) with and installing a couple of dependencies that I feel like will make our lives easier, like &lt;a href="https://expressjs.com/" rel="noopener noreferrer"&gt;Express&lt;/a&gt;, &lt;a href="https://github.com/tj/ejs" rel="noopener noreferrer"&gt;EJS&lt;/a&gt;, &lt;a href="https://marked.js.org/" rel="noopener noreferrer"&gt;Marked&lt;/a&gt;, the good ol' &lt;a href="https://www.npmjs.com/package/body-parser" rel="noopener noreferrer"&gt;body-parser&lt;/a&gt; and &lt;a href="https://github.com/jonschlinkert/gray-matter" rel="noopener noreferrer"&gt;gray-matter&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm init
npm &lt;span class="nb"&gt;install &lt;/span&gt;body-parser ejs express marked gray-matter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explaining the dependencies
&lt;/h3&gt;

&lt;p&gt;The reason why I chose to add EJS into the mix was to make things a bit easier for me, by taking advantage of templates and just writing less code overall. If you're not familiar with it, just wait. It's pretty cool! &lt;/p&gt;

&lt;p&gt;For &lt;code&gt;Marked&lt;/code&gt; and &lt;code&gt;gray-matter&lt;/code&gt;, it's pretty simple: markdown rules and I want my posts to have proper metadata, which I plan to create with &lt;a href="https://daily-dev-tips.com/posts/what-exactly-is-frontmatter/" rel="noopener noreferrer"&gt;frontmatter&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alright, back at it!
&lt;/h2&gt;

&lt;p&gt;Now open your project in your favourite IDE and create your &lt;code&gt;main.js&lt;/code&gt; file. I know that we'll want the following routes: &lt;code&gt;/&lt;/code&gt;, &lt;code&gt;/:post&lt;/code&gt;, and that we'll need to have relevant stuff on the &lt;code&gt;public&lt;/code&gt; folder, so our initial &lt;code&gt;main.js&lt;/code&gt; can look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// main.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;marked&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;marked&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;matter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gray-matter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;static&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;view engine&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ejs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/:post&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server is running on http://localhost:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pretty straightforward, right? The idea is to have the list of posts on my &lt;code&gt;home&lt;/code&gt; (or &lt;code&gt;/&lt;/code&gt;) and just have individual pages for my posts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Time to template like you never templated before!
&lt;/h2&gt;

&lt;p&gt;With the base setup out of the way, we also need a base structure and EJS will provide that.&lt;br&gt;
Start by creating a folder named &lt;code&gt;views&lt;/code&gt;; this will be the root of your &lt;em&gt;pages&lt;/em&gt;, so to speak, which means that you can create a &lt;code&gt;home.ejs&lt;/code&gt; and a &lt;code&gt;post.ejs&lt;/code&gt; inside it just to mark the two types of pages that we'll have.&lt;/p&gt;

&lt;p&gt;Create also a folder, inside &lt;code&gt;views&lt;/code&gt;, named &lt;code&gt;partials&lt;/code&gt;; you can think of it as our &lt;em&gt;components&lt;/em&gt; and you can already create 3 files here: &lt;code&gt;header.ejs&lt;/code&gt;, &lt;code&gt;footer.ejs&lt;/code&gt; and &lt;code&gt;head.ejs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is the base structure of our blog: 2 pages and 3 components, that's it. All the rest will be dealt with inside &lt;code&gt;main.js&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  The &lt;code&gt;partials&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Like I've mentioned, templates allow us to not have to repeat as much code as we would have to if we were creating each page by hand, and our setup provides us exactly with a ease of mind regarding that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// head.ejs
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang="en"&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;meta charset="UTF-8" /&amp;gt;
    &amp;lt;meta http-equiv="X-UA-Compatible" content="IE=edge" /&amp;gt;
    &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1.0" /&amp;gt;
    &amp;lt;title&amp;gt;Here's my blog&amp;lt;/title&amp;gt;
  &amp;lt;/head&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// footer.ejs
    &amp;lt;/main&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// header.ejs
&amp;lt;body&amp;gt;
  &amp;lt;main&amp;gt;
    &amp;lt;header&amp;gt;
      &amp;lt;a href="/"&amp;gt;Blog&amp;lt;/a&amp;gt;
    &amp;lt;/header&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Basically, the regular &lt;code&gt;head&lt;/code&gt; at, well, &lt;code&gt;head&lt;/code&gt;, the closing tags at &lt;code&gt;footer&lt;/code&gt; and the &lt;em&gt;navbar&lt;/em&gt;, and opening tags at &lt;code&gt;header&lt;/code&gt;. Pretty simple, right?&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;views&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Now that we have our &lt;em&gt;components&lt;/em&gt; we can get the pages going.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// home.ejs
&amp;lt;%- include('./partials/head') %&amp;gt;
&amp;lt;%- include('./partials/header') %&amp;gt;
&amp;lt;div&amp;gt;
  &amp;lt;h2&amp;gt;The posts:&amp;lt;/h2&amp;gt;
  &amp;lt;ul&amp;gt;
    &amp;lt;% posts.forEach((post)=&amp;gt; { %&amp;gt;
    &amp;lt;li&amp;gt;
      &amp;lt;a href="&amp;lt;%= post.link %&amp;gt;"&amp;gt;&amp;lt;%= post.title %&amp;gt;&amp;lt;/a&amp;gt;
    &amp;lt;/li&amp;gt;
    &amp;lt;% }) %&amp;gt;
  &amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;%- include('./partials/footer') %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// post.ejs
&amp;lt;%- include('./partials/head') %&amp;gt;
&amp;lt;%- include('./partials/header') %&amp;gt;
&amp;lt;h1&amp;gt;&amp;lt;%= frontmatter.title %&amp;gt;&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;%= frontmatter.date %&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;%= frontmatter.author %&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;%- content %&amp;gt;
&amp;lt;%- include('./partials/footer') %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yeah, it looks pretty weird but just know that the &lt;code&gt;include&lt;/code&gt; brings the &lt;code&gt;partials&lt;/code&gt; into our views and that there's extra syntax to make it work (go to the &lt;a href="https://ejs.co/#docs" rel="noopener noreferrer"&gt;docs&lt;/a&gt; if you're interested in how it works).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;&amp;lt;%-&lt;/code&gt; allows us to not double-escape our HTML ( try it out with &lt;code&gt;&amp;lt;%&lt;/code&gt; or &lt;code&gt;&amp;lt;%=&lt;/code&gt; at the end and see what happens) and the &lt;code&gt;forEach()&lt;/code&gt;, well, does exactly what a &lt;code&gt;forEach&lt;/code&gt; does. Nothing particularly new here, just a different way of writing stuff that you already know!&lt;/p&gt;

&lt;p&gt;But, rejoice, you've now interacted with a new tool! 💃&lt;/p&gt;

&lt;h2&gt;
  
  
  The blog posts! 📄
&lt;/h2&gt;

&lt;p&gt;At the root of your project create a &lt;code&gt;posts&lt;/code&gt; folder and your first &lt;code&gt;blog-post-1.md&lt;/code&gt; inside of it with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Blog&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;post&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1"&lt;/span&gt;
&lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2024-10-31&lt;/span&gt;
&lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Rui&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Sousa"&lt;/span&gt;
&lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Here's&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;first&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;blog&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;post"&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gh"&gt;# A blog post&lt;/span&gt;

Here's my first blog post!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What's inside the &lt;code&gt;---&lt;/code&gt; is our &lt;code&gt;frontmatter&lt;/code&gt;, and you'll get to use it right away!&lt;/p&gt;

&lt;h2&gt;
  
  
  Time to see some stuff on the screen!
&lt;/h2&gt;

&lt;p&gt;Back to our &lt;code&gt;main.js&lt;/code&gt;, we'll first deal with the &lt;code&gt;/&lt;/code&gt; route. As we've seen, we want to be able to get our posts and loop over them to display info about them on the screen.&lt;/p&gt;

&lt;p&gt;To simplify stuff I'll leave comments next to each relevant line instead of writing huge blocks of text explaining stuff! 😄&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// main.js&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// we get the folder with the `posts`&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;postsDir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;posts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// we reach inside the folder&lt;/span&gt;
  &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;postsDir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// check for any errors&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error reading posts directory&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt;
       &lt;span class="c1"&gt;// for the retrieved files we filter those that are markdown `.md`&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;endsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.md&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="c1"&gt;// afterwards we'll map over each one to parse the info&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// we get its path so we can read its content&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;postsDir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// we retrieve the frontmatter content (`matter()` deals with that for us)&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;frontmatter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;matter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileContent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// we get the post file name to use as the slug for our link&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;postName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;basename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.md&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// we return two properties (`title` and `link`) that we've already seen inside `home.ejs` inside the `forEach` loop&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;frontmatter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;postName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;link&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;postName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// we render the `home.ejs` file and pass the property `posts` (that we run through the `forEach` loop&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;home&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now run &lt;code&gt;node main.js&lt;/code&gt; in your terminal and visit &lt;code&gt;localhost:3000&lt;/code&gt;. You should see your &lt;code&gt;/&lt;/code&gt; route populated with links to the markdown files that you created! 💃&lt;/p&gt;

&lt;p&gt;There's a lot to digest there so, please, try every code line by yourself and see if it makes sense. Try to do different stuff, actually! Get the &lt;code&gt;summary&lt;/code&gt; for your posts and find a way of displaying it inside the &lt;code&gt;home.ejs&lt;/code&gt; file. Go crazy with it! Attach image urls and also try to display them. PLAY WITH IT!&lt;/p&gt;

&lt;p&gt;Now, for the &lt;code&gt;/post&lt;/code&gt; itself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// main.js&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/:post&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// via the params of the request we get the post identifier (in this case the slug)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;postName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// now instead of grabbing the `posts` folder, we make sure to grab a file that has the same `filename` of our route inside the `posts` folder&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;postPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;posts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;postName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.md`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// we jump inside the file&lt;/span&gt;
  &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;postPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// once again we check for any errors&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Post not found&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// we fetch the content of the post and its frontmatter&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;frontmatter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;matter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// we use `marked` to render the `htmlContent` (very important if you have `code blocks`, links, and other interesting stuff&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;htmlContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;marked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// we tell to render the `post.ejs` file and pass two properties, `content` and `frontmatter` that we'll pick and render inside our file &lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;post&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;htmlContent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;frontmatter&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once again, run &lt;code&gt;node main.js&lt;/code&gt;, and choose one of the links in the homepage. You should see your markdown file rendered as HTML!&lt;/p&gt;

&lt;p&gt;As before, try stuff out; add elements to the markdown and see how they render; add new fields to the frontmatter and also get them to show.&lt;/p&gt;

&lt;p&gt;You're now the proud owner of a blog made with Node! 💃&lt;/p&gt;

&lt;h2&gt;
  
  
  That's it
&lt;/h2&gt;

&lt;p&gt;There's a lot more that we could do here but that's out of the scope, isn't it? We got something working, with what we intended to do, and that is perfect. Now it's your turn to ✨ make it shine ✨&lt;br&gt;
See if you can change the &lt;code&gt;head.ejs&lt;/code&gt; info by passing properties to it! Ideally, the tab name would change with the chosen content. And we should also have proper metadata when we share the website on social media so we also need that frontmatter info inside the &lt;code&gt;head&lt;/code&gt;. Sounds like a good challenge, uh? 😎&lt;/p&gt;

&lt;p&gt;As always, if you have any doubts, feel free to reach me via &lt;a href="https://twitter.com/HeyItzaMi" rel="noopener noreferrer"&gt;X&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>An intro to Appwrite | Building a To-do list with SvelteKit</title>
      <dc:creator>Rui Sousa</dc:creator>
      <pubDate>Sun, 07 Jan 2024 21:48:56 +0000</pubDate>
      <link>https://forem.com/itzami/an-intro-to-appwrite-building-a-to-do-list-with-sveltekit-3m9b</link>
      <guid>https://forem.com/itzami/an-intro-to-appwrite-building-a-to-do-list-with-sveltekit-3m9b</guid>
      <description>&lt;p&gt;A to-do list is the playground for experimenting with a new technology, right? It ain't much but it allows you not only to understand the basics but also to get familiar with the docs for any extra 💫 &lt;em&gt;dazzle&lt;/em&gt; 💫 that you may want to add.&lt;br&gt;
And that's exactly what we'll do with &lt;a href="https://appwrite.io/"&gt;Appwrite&lt;/a&gt;!&lt;/p&gt;
&lt;h2&gt;
  
  
  What is Appwrite?
&lt;/h2&gt;

&lt;p&gt;Appwrite is an open-source BaaS (Backend as a Service), and it provides pretty much all the tools that you might need to get a backend up-and-running, such as Authentication, Databases, Functions and Storages; since there's no point in repeating what has already been said by others, please check &lt;a href="https://dev.to/appwrite/30daysofappwrite-appwrite-database-22an"&gt;this blog post&lt;/a&gt; to learn more about how Appwrite is structured and how it works.&lt;/p&gt;
&lt;h2&gt;
  
  
  Starting the project
&lt;/h2&gt;

&lt;p&gt;We'll need, of course, to start a Svelte project so let's follow &lt;a href="https://kit.svelte.dev/docs/creating-a-project"&gt;their walkthrough&lt;/a&gt; to do so.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm create svelte@latest svelte-appwrite-todo-app
&lt;span class="nb"&gt;cd &lt;/span&gt;svelte-appwrite-todo-app
npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just make sure to select the &lt;code&gt;Skeleton&lt;/code&gt; option since we don't need the &lt;code&gt;Demo&lt;/code&gt; code for what we're doing.&lt;/p&gt;

&lt;p&gt;Once you have the project running, let's now initialize a project on Appwrite. We can also follow &lt;a href="https://appwrite.io/docs/quick-starts/sveltekit"&gt;their guide&lt;/a&gt; for that; just make sure to stop before &lt;code&gt;step 5&lt;/code&gt; since we don't need to get into the &lt;code&gt;Login page&lt;/code&gt; setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Appwrite structure and config
&lt;/h2&gt;

&lt;p&gt;Alright, we should now have a base project to start working on and we're ready to extend it. We'll start on Appwrite's side!&lt;br&gt;
Head over to your Appwrite console and select your project in there. Head over to &lt;code&gt;Databases&lt;/code&gt; and you'll see an empty table.&lt;/p&gt;

&lt;p&gt;&lt;a href="//images.ctfassets.net/jmotdpsipbdp/5th8t9MHUXXkh2tiMtpV6g/1680d17fd0a8dea885c727aaf2a054d9/appwrite-1.png" class="article-body-image-wrapper"&gt;&lt;img src="//images.ctfassets.net/jmotdpsipbdp/5th8t9MHUXXkh2tiMtpV6g/1680d17fd0a8dea885c727aaf2a054d9/appwrite-1.png" alt="Appwrite Database console"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's create a new database (name it whatever you want but I'll call mine &lt;code&gt;Todos&lt;/code&gt;). After that, you'll be sent to a new screen for the &lt;code&gt;Collections&lt;/code&gt;; if you followed Appwrite's &lt;a href="https://dev.to/appwrite/30daysofappwrite-appwrite-database-22an"&gt;blog post&lt;/a&gt;, you'll know that &lt;code&gt;Collections&lt;/code&gt; are groups of &lt;code&gt;Documents&lt;/code&gt; - for our app this means that &lt;code&gt;todos&lt;/code&gt; (notice that it's all lowercase, different from the &lt;code&gt;Todos&lt;/code&gt; database name) is our &lt;code&gt;collection&lt;/code&gt; and each &lt;code&gt;document&lt;/code&gt; will be a &lt;code&gt;todo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Create your &lt;code&gt;collection&lt;/code&gt; and you should see a new screen for the &lt;code&gt;documents&lt;/code&gt; (currently empty) inside that said &lt;code&gt;collection&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="//images.ctfassets.net/jmotdpsipbdp/2RYfeTEmohlcP1E2LpWkBg/16523f73b93b45ab39a3291b91ac6d7e/appwrite-2.png" class="article-body-image-wrapper"&gt;&lt;img src="//images.ctfassets.net/jmotdpsipbdp/2RYfeTEmohlcP1E2LpWkBg/16523f73b93b45ab39a3291b91ac6d7e/appwrite-2.png" alt="Appwrite console for the documents"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, you won't be able to create any document because we need to define the properties (or &lt;code&gt;attributes&lt;/code&gt;, in the Appwrite's console) that will compose each document. We'll create 3 different attributes: &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt; and &lt;code&gt;isCompleted&lt;/code&gt;. &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;description&lt;/code&gt; will be &lt;code&gt;strings&lt;/code&gt; and &lt;code&gt;isCompleted&lt;/code&gt; will be of type &lt;code&gt;boolean&lt;/code&gt;, and the 3 will be set as &lt;code&gt;required&lt;/code&gt; - just follow the different prompts that Appwrite provides for creating an attribute but make sure that the types match the tutorial.&lt;/p&gt;

&lt;p&gt;&lt;a href="//images.ctfassets.net/jmotdpsipbdp/m4vhyrTNzOdxv5iZIr1J1/1a0950ebc9ee133f559df3337ee6fa1f/appwrite-3.png" class="article-body-image-wrapper"&gt;&lt;img src="//images.ctfassets.net/jmotdpsipbdp/m4vhyrTNzOdxv5iZIr1J1/1a0950ebc9ee133f559df3337ee6fa1f/appwrite-3.png" alt="Creating attributes for a document inside Appwrite"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we're ready to start creating documents and we'll do that from our codebase, of course! 💃&lt;/p&gt;
&lt;h2&gt;
  
  
  Connecting our created database to the code
&lt;/h2&gt;

&lt;p&gt;We'll be working with databases' ids and different info that should be secured so I would advise you to create a &lt;code&gt;.env&lt;/code&gt; file to store said info. We'll do this by installing &lt;a href="https://www.npmjs.com/package/dotenv"&gt;dotenv&lt;/a&gt; into our project and use it accordingly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;dotenv &lt;span class="nt"&gt;--save&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now on the codebase, create a &lt;code&gt;.env&lt;/code&gt; file and fill in the info for each variable that I show here (go back to the &lt;a href="https://appwrite.io/docs/quick-starts/sveltekit"&gt;Appwrite guide&lt;/a&gt; if you get lost on where the &lt;code&gt;ids&lt;/code&gt; are):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;APPWRITE_PROJECT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;APPWRITE_ENDPOINT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;APPWRITE_DATABASE_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;APPWRITE_COLLECTION_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On our &lt;code&gt;appwrite.ts&lt;/code&gt; file (or &lt;code&gt;.js&lt;/code&gt;, as you wish, just remember to remove the types from your code if you're not using &lt;code&gt;Typescript&lt;/code&gt;) we can now replace the hardcoded values for your variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Client&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;appwrite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;APPWRITE_ENDPOINT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;APPWRITE_PROJECT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;APPWRITE_DATABASE_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;APPWRITE_COLLECTION_ID&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$env/static/private&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setEndpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;APPWRITE_ENDPOINT&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;setProject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;APPWRITE_PROJECT_ID&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I've removed the &lt;code&gt;Account&lt;/code&gt; definition because we won't need it (for this tutorial) and changed the exports a bit just due to preference.&lt;/p&gt;

&lt;p&gt;Now, if you try to start a project, you'll be invited with a blank page with an error and if you look at your terminal you'll see &lt;code&gt;AppwriteException: The current user is not authorized to perform the requested action.&lt;/code&gt; By default, Appwrite doesn't make assumptions about who can access which database or which collections so everything will be blank (aka, no one can access anything) so we need to solve this.&lt;/p&gt;

&lt;p&gt;Head over to your &lt;code&gt;collection&lt;/code&gt; and choose &lt;code&gt;Settings&lt;/code&gt;. Scroll to &lt;code&gt;Permissions&lt;/code&gt; and create a new role; for this tutorial we can start by selecting &lt;code&gt;All guests&lt;/code&gt; and allowing for them to perform any action.&lt;/p&gt;

&lt;p&gt;&lt;a href="//images.ctfassets.net/jmotdpsipbdp/25GZJOg89IBvIC7jjhZ0IR/3f98a0da0c3578a642f588a0296a41b8/appwrite-4.png" class="article-body-image-wrapper"&gt;&lt;img src="//images.ctfassets.net/jmotdpsipbdp/25GZJOg89IBvIC7jjhZ0IR/3f98a0da0c3578a642f588a0296a41b8/appwrite-4.png" alt="Set permissions for role in Appwrite"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;⚠️ For an actual app you wouldn't want to have this kind of role performing all kind of destructive actions but it works well enough for this tutorial.&lt;/p&gt;

&lt;p&gt;Now, if you refresh your app in the browser, the error should have disappeared! Congrats, you've made your app extremely insecure (&lt;em&gt;I'm just kidding!&lt;/em&gt; 😄)!&lt;/p&gt;

&lt;h2&gt;
  
  
  Finally, some actual code 😄
&lt;/h2&gt;

&lt;p&gt;Now, our app will look incredibly boring but it will be plenty for this tutorial.&lt;br&gt;
For starters, please copy &amp;amp; paste the following code into &lt;code&gt;src/routes/+page.svelte&lt;/code&gt; for the initial look:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight svelte"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;main&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"column"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"todos-container box column"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;SvelteKit Appwrite To-do App&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"POST"&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"?/create"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"box column"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"input-container column"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Title&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"title"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"input-container column"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"description"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Description&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"description"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;Add Todo&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;main&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;480px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;'Segoe UI'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Tahoma&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Geneva&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Verdana&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#3e4850&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="py"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nc"&gt;.box&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#ccc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;8px&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;79&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;91&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nc"&gt;.column&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;flex-direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nc"&gt;.todos-container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="py"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nc"&gt;.todo-container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="py"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.2em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nc"&gt;.todo-container&lt;/span&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;:last-of-type&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;padding-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nl"&gt;border-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#ccc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nc"&gt;.title&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nc"&gt;.description&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.8rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#717378&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="py"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nc"&gt;.input-container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="py"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.8rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#717378&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#ccc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#151c29&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We now have a foundation for our work and we're ready to make our first API call - getting the to-dos from our &lt;code&gt;collection&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We'll start by going into our &lt;code&gt;appwrite.ts&lt;/code&gt; file and create and export our function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;[...]&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getToDosFromDatabase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getToDosFromDatabase&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, what do we need to do in our function? We need to get inside our &lt;code&gt;database&lt;/code&gt;, pick the collection that has the to-dos and be able to grab all of them! Appwrite offers an &lt;a href="https://appwrite.io/docs/products/databases/quick-start"&gt;excellent documentation&lt;/a&gt; and examples for all your needs so you shouln't have a problem doing so but let's go step-by-step.&lt;/p&gt;

&lt;p&gt;To work with Appwrite databases, their API offers a &lt;code&gt;Database&lt;/code&gt; class that has the necessary methods, so we can start by adding it to our &lt;code&gt;appwrite.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;[...]&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;databases&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Databases&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;[...]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if you look at &lt;a href="https://appwrite.io/docs/references/cloud/client-web/databases#listDocuments"&gt;their documentation&lt;/a&gt; you'll find the &lt;code&gt;listDocuments&lt;/code&gt; method, which is exactly what we need. It takes our &lt;code&gt;APPWRITE_DATABASE_ID&lt;/code&gt; and &lt;code&gt;APPWRITE_COLLECTION_ID&lt;/code&gt; and an additional optional argument to provide extra context to our query to filter it out; for us, the two required arguments are more than enough and our &lt;code&gt;getToDosFromDatabase&lt;/code&gt; will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getToDosFromDatabase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;documents&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;databases&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listDocuments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;APPWRITE_DATABASE_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;APPWRITE_COLLECTION_ID&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'm solely getting the &lt;code&gt;documents&lt;/code&gt; from the response because I don't really have a need for the full object that comes as a result, which provides a &lt;code&gt;total&lt;/code&gt; and the &lt;code&gt;documents&lt;/code&gt;!&lt;br&gt;
With that, our &lt;code&gt;appwrite.ts&lt;/code&gt; will now look like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Databases&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ID&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;appwrite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;APPWRITE_ENDPOINT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;APPWRITE_PROJECT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;APPWRITE_DATABASE_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;APPWRITE_COLLECTION_ID&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$env/static/private&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;databases&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Databases&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setEndpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;APPWRITE_ENDPOINT&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;setProject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;APPWRITE_PROJECT_ID&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getToDosFromDatabase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;documents&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;databases&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listDocuments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;APPWRITE_DATABASE_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;APPWRITE_COLLECTION_ID&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getToDosFromDatabase&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alright, so, where do we plug this &lt;code&gt;getToDosFromDatabase&lt;/code&gt;? Svelte has &lt;a href="https://kit.svelte.dev/docs/load"&gt;a couple of ways&lt;/a&gt; of loading data, but, to cut it short, we'll use a &lt;code&gt;+page.server.ts&lt;/code&gt;; my reasoning is that we're dealing with the &lt;code&gt;ids&lt;/code&gt; of our &lt;code&gt;project&lt;/code&gt;, &lt;code&gt;database&lt;/code&gt;, and &lt;code&gt;collection&lt;/code&gt; and that's not really something that we really want to expose to the user. Also, we're gonna have some &lt;a href="https://kit.svelte.dev/docs/form-actions"&gt;form actions&lt;/a&gt; and we need a &lt;code&gt;.server.ts&lt;/code&gt; file anyway!&lt;/p&gt;

&lt;p&gt;So, on the same level as our &lt;code&gt;+page.svelte&lt;/code&gt; we create a &lt;code&gt;+page.server.ts&lt;/code&gt; and in it we can have a &lt;code&gt;load()&lt;/code&gt; function where we call our &lt;code&gt;getToDosFromDatabase&lt;/code&gt;, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getToDosFromDatabase&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$lib/appwrite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getToDosFromDatabase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;todos&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're now able to get the data from the &lt;code&gt;return&lt;/code&gt; via the &lt;code&gt;data&lt;/code&gt; property on our route and we can render stuff accordingly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight svelte"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;main&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"column"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"todos-container box column"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;SvelteKit Appwrite To-do App&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;#if&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todos&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;#each&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todos&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"todo-container column"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"description"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;/each&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"empty-message"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        There are no To-dos. Create your first one!
      &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;/if&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"POST"&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"?/create"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"box column"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    [...]
    &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;[...]&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, if there's &lt;code&gt;data&lt;/code&gt; and there are &lt;code&gt;todos&lt;/code&gt; in &lt;code&gt;data&lt;/code&gt;, we render each of them; if there's not, we just display a message saying so. At this point you &lt;em&gt;should&lt;/em&gt; be able to see the &lt;code&gt;empty-message&lt;/code&gt; paragraph, so, that's a good guiding star!&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's mutate stuff, shall we?
&lt;/h2&gt;

&lt;p&gt;Ok, we can now connect to our database and get the non-existent documents in our collection, but we want to actually place stuff there and doing that via the Appwrite dashboard is not very &lt;em&gt;mega frontend dev&lt;/em&gt; of us, so let's fix that!&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Databases()&lt;/code&gt; class also provides a &lt;a href="https://appwrite.io/docs/references/cloud/client-web/databases#createDocument"&gt;createDocument()&lt;/a&gt; method, and by identifying our &lt;code&gt;database&lt;/code&gt; and our &lt;code&gt;collection&lt;/code&gt; &lt;code&gt;ids&lt;/code&gt;, we can use it! On our &lt;code&gt;appwrite.ts&lt;/code&gt; we add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;[...]&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createTodo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;databases&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;APPWRITE_DATABASE_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;APPWRITE_COLLECTION_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;isCompleted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getToDosFromDatabase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createTodo&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, should be obvious on what's happening here but let's summarize it: &lt;code&gt;createTodo&lt;/code&gt; takes a &lt;code&gt;title&lt;/code&gt; and a &lt;code&gt;description&lt;/code&gt; argument and we create an object (aka, a &lt;code&gt;document&lt;/code&gt; entry on our &lt;code&gt;collection&lt;/code&gt;) with the expected structure: &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt;, and the &lt;code&gt;isCompleted&lt;/code&gt; property that should start as &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So, to connect stuff up... I've already added the &lt;code&gt;form&lt;/code&gt; with its &lt;code&gt;action&lt;/code&gt; on our &lt;code&gt;+page.svelte&lt;/code&gt; code so stuff there is done, and, like I mentioned before, it's going to be on the &lt;code&gt;+page.server.ts&lt;/code&gt; that we'll work with the form actions.&lt;/p&gt;

&lt;p&gt;Looking at our &lt;code&gt;form&lt;/code&gt; element you'll see that the expected action is &lt;code&gt;create&lt;/code&gt; so we can start by that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;[...]&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;actions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we need to get the &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;description&lt;/code&gt; and send them as arguments on our &lt;code&gt;createTodo&lt;/code&gt;; with Svelte and its actions, it is expected that you access the form info via the &lt;code&gt;request&lt;/code&gt; property.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getToDosFromDatabase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createTodo&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$lib/appwrite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;[...]&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;actions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Title and description are required&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Try your form now, I'll wait! ... ... ... &lt;strong&gt;Pretty cool, uh?&lt;/strong&gt; 😜&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to go next?
&lt;/h2&gt;

&lt;p&gt;This post is already pretty long so I'm cutting it short right here; I might do a part 2 for the &lt;code&gt;isCompleted&lt;/code&gt; attribut and for the authentication (remember the permissions? Yeah, we definitely don't want to release an app with that) but I would like to offer you the challenge of figuring it out for yourself.&lt;br&gt;
You can find the full code &lt;a href="https://github.com/ItzaMi/svelte-appwrite-todo-app"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The challenge
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;We're missing a way to set a to-do as complete but we already have a &lt;code&gt;isCompleted&lt;/code&gt; attribute. Look into &lt;a href="https://appwrite.io/docs/references/cloud/client-web/databases"&gt;Appwrite's documentation&lt;/a&gt; to figure out if there's a way of updating a document; once you have the method, create a function for it on the &lt;code&gt;appwrite.ts&lt;/code&gt; and then find a way to connect it to the to-do that you want to mark!&lt;/li&gt;
&lt;li&gt;Due to the way we set our permissions, anyone can change the to-dos and add more to the list and that's a huge problem! This is a &lt;strong&gt;much bigger challenge&lt;/strong&gt; but, ideally, there would be a way to &lt;a href="https://appwrite.io/docs/products/auth/quick-start"&gt;authenticate a user&lt;/a&gt; and we would change the permissions on our &lt;code&gt;collection&lt;/code&gt; to allow just &lt;code&gt;users&lt;/code&gt; (or maybe even just a specific role) to update the &lt;code&gt;to-dos&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Are you up to the challenge? 😉 I promise you won't regret it if you follow it through!&lt;/p&gt;

&lt;h2&gt;
  
  
  And that's it!
&lt;/h2&gt;

&lt;p&gt;Hopefully I've spiked your interest for Appwrite with this post and you're now eager to add a new tool to your belt! 💃&lt;br&gt;
As always, if you have any doubts, feel free to reach me via &lt;a href="https://twitter.com/HeyItzaMi"&gt;X&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Build a Quote Generator with JavaScript: Your first API project</title>
      <dc:creator>Rui Sousa</dc:creator>
      <pubDate>Wed, 02 Mar 2022 19:13:14 +0000</pubDate>
      <link>https://forem.com/itzami/build-a-quote-generator-with-javascript-your-first-api-project-2mco</link>
      <guid>https://forem.com/itzami/build-a-quote-generator-with-javascript-your-first-api-project-2mco</guid>
      <description>&lt;p&gt;If you’ve never worked with an API (Application Programming Interface) before, WELCOME! I assure you that this is going to be an excellent first time! 😄&lt;/p&gt;

&lt;p&gt;The purpose of this tutorial is simple: to allow you to work with an API by making a single request and display its info on the screen. That’s it! No tricks! And we’ll probably do it in like 10 lines of JavaScript 🤘 How exciting is that?&lt;/p&gt;

&lt;p&gt;So, to summarize, in this tutorial you’ll learn a bunch of stuff like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;selecting elements on the DOM&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;onClick&lt;/code&gt; events&lt;/li&gt;
&lt;li&gt;trigger a &lt;code&gt;fetch&lt;/code&gt; for an API&lt;/li&gt;
&lt;li&gt;displaying info in empty elements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're really just interested on the code, here's a link to the &lt;strong&gt;&lt;a href="https://codepen.io/ItzaMi/pen/vYgdXgL"&gt;CodePen&lt;/a&gt;&lt;/strong&gt; with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s an API?
&lt;/h2&gt;

&lt;p&gt;We should clarify on what’s an API if that’s something new to you.&lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Introduction"&gt;API&lt;/a&gt;&lt;/strong&gt; is an intermediary that allows for two applications to talk between them, and it will have a set of functions that allow applications to access data and interact with external software components, operating systems, or services.&lt;/p&gt;

&lt;p&gt;The most widely practical example to describe an API is the following: think of a waiter at a restaurant. When you (&lt;em&gt;application 1&lt;/em&gt;) get at a restaurant, you place your order (&lt;em&gt;request&lt;/em&gt;) with the waiter (&lt;em&gt;API&lt;/em&gt;) and he tells the kitchen (&lt;em&gt;application 2&lt;/em&gt;); the kitchen then makes your order, gives it to the waiter and the waiter gives it to you (&lt;em&gt;response&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;In our tutorial we’ll use an API that &lt;strong&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data"&gt;fetches data from a server&lt;/a&gt;&lt;/strong&gt; and we’ll use the &lt;strong&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API"&gt;Fetch API&lt;/a&gt;&lt;/strong&gt; to facilitate that communication (that means that we’ll actually be using &lt;strong&gt;two&lt;/strong&gt; APIs in this tutorial 😦).&lt;/p&gt;

&lt;p&gt;That’s enough theory for now but if you do have any doubts, please message me on &lt;a href="https://twitter.com/HeyItzaMi"&gt;&lt;strong&gt;Twitter&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting with the HTML
&lt;/h2&gt;

&lt;p&gt;Every web app needs its HTML and ours is no different! Our HTML for this application is incredibly straight forward and all you need is a &lt;code&gt;button&lt;/code&gt; and a &lt;code&gt;div&lt;/code&gt; with an &lt;code&gt;id&lt;/code&gt;. So your &lt;code&gt;HTML&lt;/code&gt; will look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;onclick=&lt;/span&gt;&lt;span class="s"&gt;'getQuote()'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Get quote&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;'insertQuoteHere'&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it, job done! We can now move to the interesting part! 😄&lt;/p&gt;

&lt;h2&gt;
  
  
  The JavaScript
&lt;/h2&gt;

&lt;p&gt;Most of the APIs require you to deal with secrets but that’s out of the scope of this tutorial so we’ll be using a completely free one called &lt;strong&gt;&lt;a href="https://kanye.rest/"&gt;kanye.rest&lt;/a&gt;&lt;/strong&gt; (I know, I know 😅).&lt;/p&gt;

&lt;h3&gt;
  
  
  Get our &lt;code&gt;div&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;So, the first thing that we’ll need to do is to get our &lt;code&gt;&amp;lt;div id='insertQuoteHere' /&amp;gt;&lt;/code&gt; because we need it readily availably to insert our quote into it. For that we’ll use &lt;strong&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById"&gt;getElementById()&lt;/a&gt;&lt;/strong&gt; (if you don’t know what that is, it’s a method that will an object that represents the element with the &lt;code&gt;id&lt;/code&gt; that we pass as parameter.&lt;/p&gt;

&lt;p&gt;So, in this case, this is going to be our first line of JavaScript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;divWithQuote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;insertQuoteHere&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create our function
&lt;/h3&gt;

&lt;p&gt;We need to create our &lt;code&gt;getQuote()&lt;/code&gt; function and this function will do the request and print the data into our &lt;code&gt;divWithQuote&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You’ll see me using an &lt;strong&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions"&gt;arrow function&lt;/a&gt;&lt;/strong&gt; but you can use a regular function expression.&lt;/p&gt;

&lt;p&gt;Let’s declare our empty function&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getQuote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The request
&lt;/h3&gt;

&lt;p&gt;Now that we have our function, we’ll run the &lt;code&gt;fetch()&lt;/code&gt; function provided by the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch"&gt;&lt;strong&gt;Fetch API&lt;/strong&gt;&lt;/a&gt;, which will fetch (well, duh!) our data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getQuote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.kanye.rest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you know click on the button, you won’t see anything happening, BUT... Congratulations, you just made your first request! 🎉&lt;/p&gt;

&lt;p&gt;Now let’s deal with its data! 😄&lt;/p&gt;

&lt;p&gt;The basic format for any fetch request is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;API_URL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, some stuff here may look weird so let’s go through them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then"&gt;then()&lt;/a&gt; method will wait for a response from the request and execute whatever is inside it&lt;/li&gt;
&lt;li&gt;Our &lt;code&gt;response&lt;/code&gt; will look like an HTTP response, which means that, we need to extract the content from it and that’s why we use the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Response/json"&gt;json()&lt;/a&gt; method&lt;/li&gt;
&lt;li&gt;After that extraction is complete, we can then deal with the parsed data and actual make something with it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this settled, we can now adapt this format to our code and it will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getQuote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.kanye.rest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you know click the button and open your console you should see the data, which will look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;quote&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Life is the ultimate gift&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I want to take this opportunity to say how important it is to be curious about anything that you do with code.&lt;/p&gt;

&lt;p&gt;LOG EVERYTHING! LEARN WHAT YOU’RE WORKING WITH! PLAY WITH IT!&lt;/p&gt;

&lt;p&gt;Code might be confusing and scary but the best way of dealing with that it to play with it and get to know it so don’t be afraid to throw random &lt;code&gt;console.log()&lt;/code&gt; around! 😄&lt;/p&gt;

&lt;h3&gt;
  
  
  From data to HTML
&lt;/h3&gt;

&lt;p&gt;We’ve basically done everything that we need for our application to work. All we’re missing is to get that &lt;code&gt;quote&lt;/code&gt; into our HTML and to do that we’ll use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML"&gt;innerHTML&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;While logging our &lt;code&gt;data&lt;/code&gt; we can see that there’s an object inside with a single property (&lt;code&gt;quote&lt;/code&gt;) so we can reference it by doing &lt;code&gt;data.quote&lt;/code&gt; and we’ll get its value by doing so! This means that we can do the same for our &lt;code&gt;innerHTML&lt;/code&gt;, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;divWithQuote&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So our JavaScript will look like this in it’s entirety:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;divWithQuote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;insertQuoteHere&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getQuote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.kanye.rest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;divWithQuote&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;quote&lt;/span&gt; &lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you know press the button you should see a quote appearing on your div! 🎉 Here’s the working code 👇&lt;br&gt;
&lt;strong&gt;&lt;a href="https://codepen.io/ItzaMi/pen/vYgdXgL"&gt;CodePen&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  And that’s it!
&lt;/h2&gt;

&lt;p&gt;You’ve successfully created a quote generator! Well done! 😄&lt;/p&gt;

&lt;p&gt;Hopefully you’ve learn how to work with APIs and you’re know able to dive deeper into how they work and what’s possible to do with them. 💪&lt;/p&gt;

&lt;p&gt;Let me know what you thought about this post and feel free to follow me on &lt;strong&gt;&lt;a href="https://twitter.com/HeyItzaMi"&gt;Twitter&lt;/a&gt;&lt;/strong&gt; 🤘&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Create your own SvelteKit Blog with this starter</title>
      <dc:creator>Rui Sousa</dc:creator>
      <pubDate>Mon, 17 Jan 2022 20:24:38 +0000</pubDate>
      <link>https://forem.com/itzami/create-your-own-sveltekit-blog-with-this-starter-5538</link>
      <guid>https://forem.com/itzami/create-your-own-sveltekit-blog-with-this-starter-5538</guid>
      <description>&lt;p&gt;I was curious to see how &lt;a href="https://kit.svelte.dev/"&gt;SvelteKit&lt;/a&gt; behaved as the foundation for a blog, and, with my work, it was obvious to me that I should share this starter since it might help someone / inspire someone to experiment with Svelte!&lt;/p&gt;

&lt;p&gt;With this starter, you get the barebones for you to create your own blog website using Svelte and Markdown! 🎉&lt;/p&gt;

&lt;p&gt;Here's the starter link 👉 &lt;a href="https://github.com/ItzaMi/sveltekit-markdown-blog-starter"&gt;https://github.com/ItzaMi/sveltekit-markdown-blog-starter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have any doubts, please reach out here in the comments or send me a DM to &lt;a href="https://twitter.com/HeyItzaMi"&gt;my Twitter&lt;/a&gt; 😄&lt;/p&gt;

</description>
      <category>svelte</category>
      <category>github</category>
      <category>blog</category>
    </item>
    <item>
      <title>'Ship it then quit it' syndrome</title>
      <dc:creator>Rui Sousa</dc:creator>
      <pubDate>Tue, 04 Jan 2022 20:10:23 +0000</pubDate>
      <link>https://forem.com/itzami/ship-it-then-quit-it-syndrome-593o</link>
      <guid>https://forem.com/itzami/ship-it-then-quit-it-syndrome-593o</guid>
      <description>&lt;p&gt;In 2021 I built and tried to launch two projects: &lt;a href="https://noting.netlify.app/"&gt;Noting&lt;/a&gt; and &lt;a href="https://beautifulcss.dev/"&gt;BeautifulCSS&lt;/a&gt;.&lt;br&gt;
Although &lt;strong&gt;BeautifulCSS&lt;/strong&gt; had its (small) success when I launched it, it soon ended. And all because I never learned how to properly maintain projects...&lt;/p&gt;

&lt;h3&gt;
  
  
  The dilemma
&lt;/h3&gt;

&lt;p&gt;Anyone that is involved in some sort of developer’s community has heard about ‘shipping their projects’. This isn’t exactly a bad way of thinking since throwing your projects out there allows you to get feedback and improve them. But... What happens after you launch a project?&lt;/p&gt;

&lt;p&gt;Honestly? Not much. It's just there.&lt;/p&gt;

&lt;p&gt;And that's the issue!&lt;/p&gt;

&lt;p&gt;While we often hear that's is &lt;em&gt;great&lt;/em&gt; to ship your project early, no one explains what you should do next.&lt;/p&gt;

&lt;p&gt;No one tells you how you should have a roadmap or have a marketing strategy! No one tells you how you should probably have started talking about your project like 2 years ago! And no one tells you how you should start building an audience way before launching a project!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you don't do any of the things that I mentioned above, your project will most likely not stand the test of time.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What I've learned
&lt;/h3&gt;

&lt;p&gt;I've learned, this year, that building your project with love isn't enough. It seems that that's the last thing that is needed to ship a project. &lt;strong&gt;Crazy, uh?&lt;/strong&gt;&lt;br&gt;
Your project needs, more than attention, &lt;strong&gt;intentionality&lt;/strong&gt;. You need to sell it! Advertise it! Talk about it almost daily! Build the proper hype around it!&lt;/p&gt;

&lt;p&gt;Now I know better. I've learned with it. I guess that's also a benefit of &lt;strong&gt;shipping early&lt;/strong&gt;: it allows you to learn from your mistakes and I most certainly learned with mine.&lt;/p&gt;

&lt;p&gt;I learned that I need to take a step back before building something that I want to release to the world.&lt;/p&gt;

&lt;p&gt;Most importantly, I learned that I need to plan them rigorously. If I don't do it, I'll end up with a single goal for them, &lt;strong&gt;ship them and wait for the feedback&lt;/strong&gt;, and that doesn't allow me to build on top of what I launch. With that single goal, I'll end up being reactive and, I feel like that's no way of building any type of project! At least not one that you learned to love!&lt;/p&gt;

&lt;h3&gt;
  
  
  What I'll do in the future
&lt;/h3&gt;

&lt;p&gt;First things first, I need to engage with the community! Build connections, make friends, grow along with other people, learn with people that failed and with people that had immense success!&lt;br&gt;
After that, I'll start creating a clear roadmap for my projects. Not just a development roadmap. A &lt;strong&gt;product roadmap&lt;/strong&gt;! Something that allows me to build consistently, share it with the world and, ultimately, build enough interest around it (my two big inspirations for this are &lt;a href="https://twitter.com/tdinh_me"&gt;Tony Dinh&lt;/a&gt; and &lt;a href="https://twitter.com/d__raptis"&gt;Jim Raptis&lt;/a&gt; - honestly, they are wild; it's amazing to see them build in public!).&lt;/p&gt;

&lt;h3&gt;
  
  
  And that's it!
&lt;/h3&gt;

&lt;p&gt;The title of this blog post ended up being a bit dramatic (&lt;strong&gt;'Ship it then quit it' syndrome&lt;/strong&gt; - drama much?) but I think it fully represents this behavior. It's something that inherently happens (at least for me) if you don't live (again, is this dramatic?) with intention. Hopefully, this post will serve as a stepping stone for 2022!&lt;/p&gt;

&lt;p&gt;Let me know what you thought about this post and feel free to follow me on &lt;a href="https://twitter.com/HeyItzaMi"&gt;Twitter&lt;/a&gt; 🤘&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>programming</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>How to add a Google Font to your Gatsby + Tailwind project</title>
      <dc:creator>Rui Sousa</dc:creator>
      <pubDate>Wed, 13 Oct 2021 07:41:18 +0000</pubDate>
      <link>https://forem.com/itzami/how-to-add-a-google-font-to-your-gatsby-tailwind-project-gle</link>
      <guid>https://forem.com/itzami/how-to-add-a-google-font-to-your-gatsby-tailwind-project-gle</guid>
      <description>&lt;p&gt;While I was building the first version of &lt;a href="https://www.itzami.com/"&gt;itzami.com&lt;/a&gt;, I found myself having a hard time finding out on the internet how I could import a &lt;a href="https://fonts.google.com/"&gt;Google Font&lt;/a&gt; into my website that was using &lt;a href="https://www.gatsbyjs.com/"&gt;GatsbyJS&lt;/a&gt; and &lt;a href="https://tailwindcss.com/"&gt;TailwindCSS&lt;/a&gt;. (and the tutorials I found all told me to install a dependency). With some trial and error I was finally able to achieve it and with this blog post I hope to make the job a lot easier for everybody that tries to do the same! It's incredibly easy to do it but since I haven't seen anyone mention it so clearly, why not do it myself?&lt;/p&gt;

&lt;h2&gt;
  
  
  First step: Grab your font!
&lt;/h2&gt;

&lt;p&gt;You probably already know how to do this but let's do a refresh on it: to get a font (or font-family) from &lt;a href="https://fonts.google.com/"&gt;Google Fonts&lt;/a&gt; you must first go into the website (&lt;em&gt;duh!&lt;/em&gt;) and choose your prefered font (I know, this tutorial is like, super high-level!). Let's pretend it's &lt;a href="https://fonts.google.com/specimen/Festive"&gt;Festive&lt;/a&gt;.&lt;br&gt;
Within your chosen font, there are a lot of styles but for this blog post I'll just pick &lt;strong&gt;Regular 400&lt;/strong&gt;. Tick the &lt;em&gt;Select this style&lt;/em&gt; and a sidebar should appear. We won't use the the &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt; but we will use the &lt;code&gt;@import&lt;/code&gt; so you should see something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="sx"&gt;url('https://fonts.googleapis.com/css2?family=Festive&amp;amp;display=swap')&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is all you need from Google Fonts!&lt;/p&gt;

&lt;h2&gt;
  
  
  Second step: Paste it on &lt;code&gt;index.css&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;I recommend that you follow Gatsby's tutorial on &lt;a href="https://www.gatsbyjs.com/docs/how-to/styling/tailwind-css/"&gt;how to install Tailwind on a project&lt;/a&gt; since it will give you all the initial files that you need.&lt;br&gt;
Once you finish your setup your &lt;code&gt;index.css&lt;/code&gt; will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;utilities&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, on this exact file, we'll add our recently acquired &lt;code&gt;@import&lt;/code&gt; so your &lt;code&gt;index.css&lt;/code&gt; should now look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;utilities&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="sx"&gt;url('https://fonts.googleapis.com/css2?family=Festive&amp;amp;display=swap')&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the setup on &lt;code&gt;index.css&lt;/code&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Third step: Extend your &lt;code&gt;fontFamily&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Now that you're correctly importing your new font, you need to be able to use it on your code via &lt;code&gt;className&lt;/code&gt; so you must add it customize your Tailwind configuration. To do this we'll simply extend our &lt;code&gt;fontFamily&lt;/code&gt; to include this new font and we'll do it on our &lt;code&gt;tailwind.config.js&lt;/code&gt;. This means that your file will have following structure inside &lt;code&gt;extend&lt;/code&gt; (among other stuff that you might have added):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;purge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="na"&gt;darkMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// or 'media' or 'class'&lt;/span&gt;
  &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;fontFamily&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;festive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;'Festive', cursive&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;variants&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Be sure to copy the exact string that you find on your Google font page on the &lt;code&gt;CSS rules to specify families&lt;/code&gt; section. Our &lt;code&gt;festive&lt;/code&gt; here is what we type when we want to style any text with this new font.&lt;/p&gt;

&lt;h2&gt;
  
  
  You're done, baby!
&lt;/h2&gt;

&lt;p&gt;Now you can freely use your new Google Font wherever you want by adding a new class that looks like &lt;code&gt;font-festive&lt;/code&gt;! So, to style, let's say, an &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;, you would do something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;className=&lt;/span&gt;&lt;span class="s"&gt;"font-festive"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Hello there!&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Now make it appear everywhere!
&lt;/h2&gt;

&lt;p&gt;Now that we know how to add a font to any element, it's also time to add this font to our entire app. To do so, we just need to style our &lt;code&gt;body&lt;/code&gt; on our &lt;code&gt;index.css&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;'Festive'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;cursive&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now your entire app will appear with the new font and you don't really need to declare it on any element! Isn't that cool?&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap up!
&lt;/h2&gt;

&lt;p&gt;And that's it! Now you can freely add a Google Font to your GatsbyJS + TailwindCSS project with no issue whatsoever!&lt;br&gt;
Let me know what you thought about this post and feel free to follow me on &lt;a href="https://twitter.com/HeyItzaMi"&gt;Twitter&lt;/a&gt; 🤘&lt;/p&gt;

</description>
      <category>tailwindcss</category>
      <category>gatsby</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Announcing 'Beautiful CSS'</title>
      <dc:creator>Rui Sousa</dc:creator>
      <pubDate>Tue, 28 Sep 2021 08:37:41 +0000</pubDate>
      <link>https://forem.com/itzami/announcing-beautiful-css-3p26</link>
      <guid>https://forem.com/itzami/announcing-beautiful-css-3p26</guid>
      <description>&lt;p&gt;This week I launched a tool,  &lt;a href="https://beautifulcss.dev/"&gt;Beautiful CSS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You just have to click on any of the components and it will copy its style to your clipboard so you can use it freely!&lt;/p&gt;

&lt;p&gt;I intend to increase its library so that it becomes the ultimate front-end developer tool!&lt;/p&gt;

&lt;p&gt;It's also on ProductHunt if you want to upvote it 👉 &lt;a href="https://www.producthunt.com/posts/beautiful-css"&gt;https://www.producthunt.com/posts/beautiful-css&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Any feedback is very much appreciated! 🤘&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>css</category>
      <category>showdev</category>
    </item>
    <item>
      <title>How to build an accordion with JavaScript</title>
      <dc:creator>Rui Sousa</dc:creator>
      <pubDate>Thu, 03 Jun 2021 17:55:22 +0000</pubDate>
      <link>https://forem.com/itzami/how-to-build-an-accordion-with-javascript-10bj</link>
      <guid>https://forem.com/itzami/how-to-build-an-accordion-with-javascript-10bj</guid>
      <description>&lt;p&gt;I've seen some people battle with accordions in the past and, well, it wasn't pretty. BUT... It's completely understandable! An accordion has a whole lot going on and on a first sight it seems like all the functionalities will be pretty hard to develop.&lt;/p&gt;

&lt;p&gt;Well... I'm here to prove that that is wrong and I want to help you build your very best JavaScript accordion 😄 And in this tutorial you'll learn a bunch of stuff like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;selecting elements on the DOM&lt;/li&gt;
&lt;li&gt;forEach loops&lt;/li&gt;
&lt;li&gt;event listeners&lt;/li&gt;
&lt;li&gt;toggling class lists&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're really just interested on the code, here's a link to the &lt;a href="https://codepen.io/ItzaMi/pen/bGgaOEr" rel="noopener noreferrer"&gt;CodePen&lt;/a&gt; with it. I also have a YouTube video for it if you're more of a visual person 👇&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/4w2bcqb25VQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;So, with all of that out of the way, let's start this post 😎&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting with the HTML
&lt;/h2&gt;

&lt;p&gt;We'll start by create a basic structure of the HTML. And here it's pretty straight forward. You'll want a &lt;code&gt;wrapping &amp;lt;div&amp;gt;&lt;/code&gt; that will hold your &lt;em&gt;accordion component&lt;/em&gt; and inside it you'll have different &lt;em&gt;accordion items&lt;/em&gt;. Inside each &lt;em&gt;item&lt;/em&gt; you'll want to have two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the content that will always show (it can be just a &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; or it can be an entire &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; that will have the content that will &lt;em&gt;collapse&lt;/em&gt; (AKA, that will appear and disappear when you press &lt;strong&gt;1)&lt;/strong&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A made a image to illustrate the basic structure and I advise you, specially when you're starting, to sketch out what you're intending to build since it makes it easier to split everything into smaller parts so you can work on them separately.&lt;/p&gt;

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

&lt;p&gt;So, now that we have our structure, we can build it. In my example below, as you can see I have the mentioned &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; that has everything inside and that's our &lt;em&gt;accordion component&lt;/em&gt; and inside each I have an &lt;code&gt;accordionTitle&lt;/code&gt;, which represents the content that will always be showing, and a &lt;code&gt;accordionContent&lt;/code&gt; that will be the content that will appear and disappear. You can change up the HTML elements that you use (maybe you would prefer to use &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt;) but that's on you! And that's our HTML 🎉&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Accordion&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"accordionItem"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;h2&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"accordionTitle"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Tab 1&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"accordionContent"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Information here&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"accordionItem"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;h2&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"accordionTitle"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Tab 2&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"accordionContent"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Information here&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"accordionItem"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;h2&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"accordionTitle"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Tab 3&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"accordionContent"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Information here&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A step further with our CSS
&lt;/h2&gt;

&lt;p&gt;We have our HTML up and that's great but that's not an accordion. We have at least to hide &lt;code&gt;accordionContent&lt;/code&gt; to at least make it look like one so that's what we're going to do. We simply want to hide that content on this step so what we're going to add to our CSS is the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;40em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.accordionTitle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;-moz-user-select&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;-webkit-user-select&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;-ms-user-select&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;user-select&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.accordionTitle&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;.accordionContent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The styling for the &lt;code&gt;body&lt;/code&gt; and &lt;code&gt;.accordionTitle&lt;/code&gt; it's just a matter of preference. I noticed, when clicking on &lt;code&gt;.accordionTitle&lt;/code&gt; that I was getting highlighted text and I didn't wanted that so I chose to remove it with &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/user-select" rel="noopener noreferrer"&gt;user-select&lt;/a&gt; and since I wanted for the user to know that this element was clickable, I changed the cursor that appears when you over it to a pointer. That's it.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;.accordionTitle + .accordionContent&lt;/code&gt; is what matters and, honestly, the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_combinator" rel="noopener noreferrer"&gt;adjacent sibling combinator&lt;/a&gt; is pretty much all you want here. It will style your &lt;code&gt;.accordionContent&lt;/code&gt; based on if it immediately follows &lt;code&gt;.accordionTitle&lt;/code&gt; and, on for my accordion structure, it's just what I need.&lt;/p&gt;

&lt;p&gt;For now, this is the CSS that we'll need. We'll make some changes to it once we start working on our JavaScript but we'll get there right away!&lt;/p&gt;

&lt;h2&gt;
  
  
  It's alive... With JavaScript (and some CSS)
&lt;/h2&gt;

&lt;p&gt;So, we've hidden our content but now we want to show it when we click on &lt;code&gt;accordionTitle&lt;/code&gt; (or show it if it's showing, of course). So we want to grab this &lt;code&gt;accordionTitle&lt;/code&gt; class and add an &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/EventListener" rel="noopener noreferrer"&gt;event listener&lt;/a&gt; to it, in this case a &lt;em&gt;click event&lt;/em&gt;, and then some magic will end happening!&lt;/p&gt;

&lt;p&gt;So, on our JavaScript we'll grab all the elements on our HTMl that have this &lt;code&gt;.accordionTitle&lt;/code&gt; and we'll do it with &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll" rel="noopener noreferrer"&gt;querySelectorAll()&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;accordionTitles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.accordionTitle&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This piece of codes grabs all the elements that have this class name and returns a &lt;code&gt;NodeList&lt;/code&gt;. A &lt;code&gt;NodeList&lt;/code&gt; is an object that has a collection of &lt;code&gt;nodes&lt;/code&gt; in it which, in this case, it's our elements that have the &lt;code&gt;.accordionTitle&lt;/code&gt; in them, which means, our &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now that we have our elements, we need to add to each of them a click event and for that we'll use a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach" rel="noopener noreferrer"&gt;forEach&lt;/a&gt; loop.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;forEach&lt;/code&gt; loop allows us to go through each element of an array (or, in this case, the NodeList) and do something to it. It's very similar to a &lt;code&gt;.map()&lt;/code&gt; but, unlike &lt;code&gt;.map()&lt;/code&gt;, it will not return anything from it because any &lt;code&gt;return&lt;/code&gt; inside a &lt;code&gt;forEach&lt;/code&gt; will be discarded. I'm using the &lt;code&gt;forEach&lt;/code&gt; because I want to use the original data from my array/nodeList and do something with it instead of changing it.&lt;/p&gt;

&lt;p&gt;So, we'll do something like the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;accordionTitles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accordionTitle&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, inside these brackets we can define what we're doing with each item, our &lt;code&gt;accordionTitle&lt;/code&gt;, and we know that we want for something to happen when we click on them so we'll add an &lt;code&gt;eventListener&lt;/code&gt; to them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;accordionTitles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accordionTitle&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;accordionTitle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's we saying that, when we click on an &lt;code&gt;accordionTitle&lt;/code&gt; something will happen and we'll define what happens inside these new brackets.&lt;/p&gt;

&lt;p&gt;So... We know that now our &lt;code&gt;div&lt;/code&gt; with the content is hidden and we want to show it so... how can we do that? Here's my approach to it:&lt;/p&gt;

&lt;p&gt;On our CSS we're currently hiding the content based on our &lt;code&gt;.accordionTitle&lt;/code&gt; element and I want to keep that logic to show it as well. Which means that I want to alter our &lt;code&gt;.accordionTitle&lt;/code&gt; in some way that it allow for our &lt;code&gt;.accordionContent&lt;/code&gt; to have a different styling (throwback to the &lt;em&gt;adjacent sibling combinator&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;On the JavaScript we'll change the &lt;code&gt;classList&lt;/code&gt; of our &lt;code&gt;accordionTitle&lt;/code&gt; by adding (or removing) a new class called &lt;code&gt;is-open&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;accordionTitles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accordionTitle&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;accordionTitle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;accordionTitle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;is-open&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, what's my way of thinking here?&lt;br&gt;
If I can add a class to my &lt;code&gt;accordionTitle&lt;/code&gt;, and I'm controlling this &lt;strong&gt;accordion content  with that same element on my CSS, I can add a new CSS rule which tells my code that, when the &lt;code&gt;.accordionTitle&lt;/code&gt; also has the class &lt;code&gt;is-open&lt;/code&gt;, then the &lt;code&gt;.accordionContent&lt;/code&gt; that comes immediately after it should have a &lt;code&gt;display: block&lt;/code&gt; and it looks like this.&lt;br&gt;

&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.accordionTitle.is-open&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;.accordionContent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;So, once again, I'm controlling &lt;code&gt;.accordionContent&lt;/code&gt; visibility, or presence, with &lt;code&gt;.accordionTitle&lt;/code&gt; and by &lt;strong&gt;toggling a new class&lt;/strong&gt; to &lt;code&gt;.accordionTitle&lt;/code&gt;, I'm able to show and hide &lt;code&gt;.accordionContent&lt;/code&gt; as I wish.&lt;/p&gt;

&lt;p&gt;And now, it just works, if you would try it. And you have a fully functioning accordion with very few lines of JavaScript, two classes in the HTML and pretty much just two CSS rules. Isn't that amazing? 🤯&lt;/p&gt;
&lt;h2&gt;
  
  
  Let's go even further
&lt;/h2&gt;

&lt;p&gt;Currently our code allows us to open and close any tab but all the others that might be open stay like that and that's not really the &lt;em&gt;perfect accordion&lt;/em&gt; so let's work on it, shall we?&lt;br&gt;
Currently we're toggling each element independently but that's not what we want. We want to check if there are already any element that are open already and we want to remove that property so this is what I'm going to do:&lt;/p&gt;

&lt;p&gt;I'll start by removing our &lt;code&gt;toggle&lt;/code&gt; and first I want to create an &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else" rel="noopener noreferrer"&gt;if/else&lt;/a&gt; statement. On my &lt;code&gt;if&lt;/code&gt; I want to check if the &lt;code&gt;accordionTitle&lt;/code&gt; has the class &lt;code&gt;is-open&lt;/code&gt; and, if it does, I want to remove it. We'll do the following on our JavaScript&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accordionTitle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;is-open&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;accordionTitle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;is-open&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Now, my &lt;code&gt;else&lt;/code&gt; will be responsible for adding the &lt;code&gt;is-open&lt;/code&gt; class and we can do it like this&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;accordionTitle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;is-open&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;At this point we're basically at the same level that we were with the &lt;code&gt;toggle&lt;/code&gt;. Now, on this &lt;code&gt;else&lt;/code&gt; statement I want to see if there are any other elements with the &lt;code&gt;.is-open&lt;/code&gt; class and, if there are, I want to remove it and we can do it like this.&lt;/p&gt;

&lt;p&gt;First we do a &lt;code&gt;querySelectorAll&lt;/code&gt; for all the elements with the &lt;code&gt;.is-open&lt;/code&gt; class like this&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;accordionTitlesWithIsOpen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.is-open&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Then we'll need to run a new &lt;code&gt;forEach&lt;/code&gt; loop to iterate over each element so we can remove the class and that looks something like this&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;accordionTitlesWithIsOpen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accordionTitleWithIsOpen&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;accordionTitleWithIsOpen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;is-open&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;And we're done! Now once you click on a tab the other will close and we have a fully functioning accordion! 🎉🕺&lt;br&gt;
Here's the working code 👇&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/ItzaMi/embed/bGgaOEr?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Here's a challenge for you
&lt;/h2&gt;

&lt;p&gt;I would like to challenge you to do something now: using what you've learned so far, I would like for you to create a button that would close and open all the tabs. Are you up for the challenge? If you are, send me your code to my &lt;a href="https://twitter.com/HeyItzaMi" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; 😄&lt;/p&gt;

&lt;h2&gt;
  
  
  And that's it!
&lt;/h2&gt;

&lt;p&gt;Hopefully, you learned everything you need to know about building your own JavaScript Accordion and you understood that it's not that hard to make something that rocks 💪&lt;br&gt;
Let me know what you thought about this post and feel free to follow me on &lt;a href="https://twitter.com/HeyItzaMi" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; 🤘&lt;/p&gt;

&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>tutorial</category>
      <category>html</category>
      <category>css</category>
    </item>
    <item>
      <title>Creating an Accordion | HTML, CSS, JavaScript | Tutorial</title>
      <dc:creator>Rui Sousa</dc:creator>
      <pubDate>Sun, 25 Apr 2021 19:52:37 +0000</pubDate>
      <link>https://forem.com/itzami/creating-an-accordion-html-css-javascript-tutorial-3gk8</link>
      <guid>https://forem.com/itzami/creating-an-accordion-html-css-javascript-tutorial-3gk8</guid>
      <description>&lt;p&gt;In this tutorial I show you, step by step, how can build a fully functioning accordion using HTML, CSS, and JavaScript.&lt;/p&gt;

&lt;p&gt;It's the perfect tutorial for any beginner since I'll show my thought process and we'll end up with a functioning accordion that opens one tab at a time!&lt;/p&gt;

&lt;p&gt;Check out the video here&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/4w2bcqb25VQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>Boost your CSS animations with Intersection Observer API</title>
      <dc:creator>Rui Sousa</dc:creator>
      <pubDate>Sun, 07 Feb 2021 13:15:47 +0000</pubDate>
      <link>https://forem.com/itzami/boost-your-css-animations-with-intersection-observer-api-k3m</link>
      <guid>https://forem.com/itzami/boost-your-css-animations-with-intersection-observer-api-k3m</guid>
      <description>&lt;p&gt;CSS animations can be a pain in the 🍑, and what's even worst is to trigger them at the exact moment. For that exact reason, &lt;em&gt;and if I may be perfectly honest with you&lt;/em&gt;, I opt for not using them most of the time. However...&lt;/p&gt;

&lt;h2&gt;
  
  
  Presenting: Intersection Observer API
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Before starting, if you need a refresher on what's an API, &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Introduction"&gt;this&lt;/a&gt; is a good place to get info on it&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You may think that I'm out of my mind for suggesting that you should use an API for animating CSS but hear me out... &lt;a href="https://github.blog/2021-01-29-making-githubs-new-homepage-fast-and-performant/"&gt;GitHub&lt;/a&gt; uses it to make their homepage more performant and faster so you know it must be good!&lt;/p&gt;

&lt;p&gt;When we usually want to check an element's position in the window we might end up using stuff like &lt;code&gt;elem.clientTop&lt;/code&gt;, &lt;code&gt;elem.offsetTop&lt;/code&gt; or even &lt;code&gt;elem.getBoundingClientRect()&lt;/code&gt; but the truth is that these properties/methods will trigger the browser to calculate the required style and layout (check the whole list of properties that target this and a further explanation &lt;a href="https://gist.github.com/paulirish/5d52fb081b3570c81e3a"&gt;here&lt;/a&gt;) which creates a performance bottleneck.&lt;/p&gt;

&lt;p&gt;A way to circumvent this is by using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API"&gt;Intersection Observer API&lt;/a&gt;, which, according to the MDN documentation, 'provides a way to asynchronously observe changes in the intersection of a target element with an ancestor element or with a top-level document's viewport.'. So, basically, we'll just monitor if an element will enter/exit another element/the viewport and that's way easier for the browser to process.&lt;/p&gt;

&lt;h2&gt;
  
  
  So... How do you do it?
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver"&gt;IntersectionObserver interface&lt;/a&gt; can be created very easily and all you have to do is to pass a callback to it and some options. The &lt;strong&gt;callback&lt;/strong&gt; is what decides what will happen to the list of &lt;em&gt;IntersectionObserverEntry&lt;/em&gt; objects and the &lt;strong&gt;options&lt;/strong&gt; allow you to control the circumstances in which the &lt;em&gt;callback&lt;/em&gt; will be called (please refer to the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API"&gt;MDN documentation&lt;/a&gt; for full details on this).&lt;/p&gt;

&lt;p&gt;For example purposes only, we'll not define our &lt;strong&gt;options&lt;/strong&gt; (which will make them adopt some default values) and we'll simply work with our &lt;strong&gt;callback&lt;/strong&gt;, so our initial setup would be something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;expansionObserver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;IntersectionObserver&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;intersectionRatio&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// something here&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// something here&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have our &lt;em&gt;expansionObserver&lt;/em&gt;, we need to grab the elements that we want to animate. For this we'll use &lt;code&gt;document.querySelectorAll()&lt;/code&gt; and we'll get all the elements with the class &lt;code&gt;.expand&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So, on our HTML it would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"section-one"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"section-two"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"expand"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Hello&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And our JavaScript would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;elementsToExpand&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.expand&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this, we need to tell the &lt;code&gt;IntersectionObserver&lt;/code&gt; that we want to &lt;code&gt;observe&lt;/code&gt; these elements, and since we're using &lt;code&gt;querySelectorAll()&lt;/code&gt; we need to loop over &lt;code&gt;elementsToExpand&lt;/code&gt; and we'll use a &lt;code&gt;forEach()&lt;/code&gt; for it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;elementsToExpand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;expansionObserver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To finish our JavaScript part, we need to fill the &lt;code&gt;if/else&lt;/code&gt; statement we wrote on our callback. Here we'll want to style our &lt;code&gt;elementsToExpand&lt;/code&gt; with the animation that they should have like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;expansionObserver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;IntersectionObserver&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;intersectionRatio&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`expansion 2s ease-in-out`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, this is the whole behaviour that you have to recreate and now all we have to do is to define in our CSS this &lt;code&gt;expansion&lt;/code&gt; animation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@keyframes&lt;/span&gt; &lt;span class="n"&gt;expansion&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nt"&gt;from&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;scaleY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nt"&gt;to&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;scaleY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we're done! You can now check the full example preview and play around with it on &lt;a href="https://codesandbox.io/s/billowing-paper-lm0ij?file=/index.html:310-352"&gt;CodeSandbox&lt;/a&gt;! I've added an extra element with a different animation so you could get a full grip of what's happening! 😄&lt;/p&gt;

&lt;h2&gt;
  
  
  And that's it!
&lt;/h2&gt;

&lt;p&gt;What did you think about the &lt;code&gt;Intersection Observer API&lt;/code&gt;? Will you give it a try on your next project?&lt;br&gt;
Let me know what you thought about this post and feel free to follow me on &lt;a href="https://twitter.com/HeyItzaMi"&gt;Twitter&lt;/a&gt; 🤘&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>codenewbie</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>I built a note-taking app with markdown and local storage using ReactJS</title>
      <dc:creator>Rui Sousa</dc:creator>
      <pubDate>Wed, 13 Jan 2021 19:58:06 +0000</pubDate>
      <link>https://forem.com/itzami/i-built-a-note-taking-app-with-markdown-and-local-storage-using-reactjs-1bd4</link>
      <guid>https://forem.com/itzami/i-built-a-note-taking-app-with-markdown-and-local-storage-using-reactjs-1bd4</guid>
      <description>&lt;p&gt;There are tons of note taking apps out there but I wanted to build mine to see how hard it actually was and during the holidays &lt;strong&gt;I did it!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://noting.netlify.app/"&gt;Take a look at it here&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So, Noting is built with ReactJS, TailwindCSS and uses &lt;a href="https://github.com/uiwjs/react-md-editor"&gt;@uiw/react-md-editor&lt;/a&gt; as the Markdown editor. It also has local storage. And has dark mode, because Tailwind really makes that easy&lt;/p&gt;

&lt;p&gt;It's a very simple app but I do believe it covers everything I wanted it to have so I'm incredibly happy for it!&lt;/p&gt;

&lt;p&gt;There's absolutely no reason for me to brand this project with an actual name, cover and what not but I got into the mentality of "It's a real product and I really need to finish it" and it kept me accountable!&lt;/p&gt;

&lt;p&gt;If you have any doubts or suggestions, please comment them here!&lt;/p&gt;

&lt;p&gt;Also, I enjoy building in public so, if you're interested, you can follow me on &lt;a href="https://twitter.com/HeyItzaMi?s=09"&gt;Twitter&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>react</category>
      <category>showdev</category>
      <category>sideprojects</category>
      <category>portfolio</category>
    </item>
    <item>
      <title>How I use Notion as a developer</title>
      <dc:creator>Rui Sousa</dc:creator>
      <pubDate>Tue, 08 Dec 2020 09:57:22 +0000</pubDate>
      <link>https://forem.com/itzami/how-i-use-notion-as-a-developer-36lc</link>
      <guid>https://forem.com/itzami/how-i-use-notion-as-a-developer-36lc</guid>
      <description>&lt;p&gt;&lt;a href="https://www.notion.so/" rel="noopener noreferrer"&gt;Notion&lt;/a&gt; is an amazing tool that helps you organize your work and you can pretty much adjust to all of your needs. Also, there are &lt;a href="https://www.notion.so/Notion-Template-Gallery-181e961aeb5c4ee6915307c0dfd5156d" rel="noopener noreferrer"&gt;a lot of templates&lt;/a&gt; to choose from made by incredibly creative people.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;My Overall Setup&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Foxhg33965373j0r3rh7w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Foxhg33965373j0r3rh7w.png" alt="My Overall Setup"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I use Notion for a lot of stuff (activity tracker, money manager, diary) but it all started when I realized that I had way too many development blog posts saved in my browser's bookmarks. Once I took a clear look at them I said to myself&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There's no way I would ever find here, even if I wanted&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, something had to be done about it and that's when I started using Notion! My first database was &lt;strong&gt;Reading List&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Reading List&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ft8ty1hflruynr0njev1y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ft8ty1hflruynr0njev1y.png" alt="Reading List"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Reading List&lt;/strong&gt; serves as my organized collection where I put the articles or tutorials that I find interesting for stuff that will surely be useful for my career. More than being a collection of stuff that I haven't read before, it's a collection of stuff that I know will always be useful for me and that I should always take into consideration.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Yes, a Google search might serve the same purpose but here I'm capable to organize the info as I want&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And that's what I do. Since Notion allows you to add tags and filters, it's the perfect way to only what you actually want to see, which facilitates search. I also ended up using Gallery mode because, for me, having a list of links isn't particularly interesting and I want something that is eye-popping and I can find easily. I would say that the images do the trick!&lt;/p&gt;

&lt;p&gt;However, I ended up realizing that not everything belongs to the Reading List and they are just stuff that I find around the internet that seems interesting but I don't really have time to read them right when I find them so that's where &lt;strong&gt;Quick Links&lt;/strong&gt; appear!&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Quick Links&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F39r3t9f31wq8i7aib44d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F39r3t9f31wq8i7aib44d.png" alt="Quick Links"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick Links&lt;/strong&gt; pretty much represents what I don't want my &lt;strong&gt;Reading List&lt;/strong&gt; to look like but when you're on your phone you don't have time to make an incredible-looking database. Instead, you just copy &amp;amp; paste the link and title and you're all set for when you actually have time to study whatever you've found.&lt;br&gt;
It basically serves as a triage for whatever comes into my Notion. The material does the check-in here and then they are properly dropped in their own place! I try to have this page as clean as possible since I don't want to repeat my mistake with the bookmarks!&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Task List&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F18w3mgaa05kem00722ti.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F18w3mgaa05kem00722ti.png" alt="Task List"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I don't like to program my day or even week but, sometimes, when you actually want to have side-projects, you need to organize your life! If you don't, you'll never find the time to work on them so that's why this Task List exists. I mostly use pen and paper for work but for my side projects, considering that I only have the weekends to work on them, it's a great tool and helps me assess the project's progression.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Blog&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fa0nfemzhgg2nbowwwj39.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fa0nfemzhgg2nbowwwj39.png" alt="Blog"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I think this one is self-descriptive but I write all my content on Notion before assessing if it's good enough to be published. It's also where I take note of topics that I might want to cover or links to other blog posts that I may want to expand upon.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Note Taking&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3laizhf0xco0kv967bny.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3laizhf0xco0kv967bny.png" alt="Note Taking"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here stands the important notes that I take (well, duh!) from my &lt;strong&gt;Reading List&lt;/strong&gt; or books. Some things aren't worth taking notes on and some others deserve a special place to which I can quickly refer to. For example, &lt;strong&gt;&lt;em&gt;Rework&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;The Opinionated Guide to React&lt;/em&gt;&lt;/strong&gt; are two books that I read, enjoyed, and took some notes along the way and I want to preserve them without having to get to the original material again!&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;App Ideas&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2w1ojcx88nryly8geby3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2w1ojcx88nryly8geby3.png" alt="App Ideas"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I guess that we all have this section on a paper, note app on the phone, or a word document but here stands my quirky ideas for apps, including with technologies that I have no idea on how to work with. Some are supposed to be personal projects, others might turn into actual products. The important part for me here is that I classify these projects on their type (personal or product) and degree of execution (&lt;em&gt;"As of now, how easily can I build it and how motivated am I to do so?"&lt;/em&gt;). For me, the degree of execution plays a huge part in it because while all ideas are great, I may just not feel incline to elaborate on them... but I don't want to lose them as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Learning X&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fznnrdvduylyydez291ff.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fznnrdvduylyydez291ff.png" alt="Learning X"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is basically a sub-division of &lt;strong&gt;Note Taking&lt;/strong&gt; but I also insert here resources for these specific technologies. I'm still starting to build a system for this section but at least I have a visible section for something that I'm currently learning and that's the important part!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;That's pretty much it!&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you read this far, thank you so much for it! Hopefully, this post ends up helping something that might need some organization in their life!&lt;br&gt;
I usually ramble a lot on &lt;a href="https://twitter.com/HeyItzaMi" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; so you can find me there!&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>tutorial</category>
      <category>writing</category>
    </item>
  </channel>
</rss>
