<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Deno - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Deno - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Mon, 18 May 2026 22:35:31 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/deno/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Lume SSG Handbook – How to Create a Static Blog with Lume ]]>
                </title>
                <description>
                    <![CDATA[ Lume is a new static site generator based on Deno. Deno is a JavaScript-based run-time environment that supports TypeScript.  Lume is not built around any specific language. It supports Markdown, Nunjucks, TypeScript, and JavaScript by default. Lume ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-a-static-blog-with-lume/</link>
                <guid isPermaLink="false">66d038af5ea8b15c90716651</guid>
                
                    <category>
                        <![CDATA[ Deno ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Static Site Generators ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Rajdeep Singh ]]>
                </dc:creator>
                <pubDate>Fri, 18 Nov 2022 17:06:55 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/11/Create-a-Static-Blog-with-Lume.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Lume is a new static site generator based on Deno. Deno is a JavaScript-based run-time environment that supports TypeScript. </p>
<p>Lume is not built around any specific language. It supports Markdown, Nunjucks, TypeScript, and JavaScript by default. Lume also supports plugins. Some plugins come preinstalled by default. This is why Lume itself is template-language agnostic.</p>
<p>Before learning more about Lume, let's discuss Deno and consider some important Deno features.</p>
<h2 id="heading-what-is-deno">What is Deno?</h2>
<p>Deno is an alternative to Node.js built by <a target="_blank" href="https://en.wikipedia.org/wiki/Ryan_Dahl">Ryan Dahl</a> (who also developed Node). Deno is based on the Rust programming language, and the second main component in Deno is the JavaScript V8 engine for WebAssembly.</p>
<p>Deno has many cool features – it's fast, secure by default, is compatible with web assembly and has TypeScript support, has in-built development tools, and more. Deno also supports Node.js APIs so you can use all npm packaged with Deno.</p>
<p>In Deno, you do not need to create a configuration file to run a simple program. You simply deploy your website instantly with a second on-edge network. But my final favorite feature is the new <code>node_modules</code> folder in the workspace. Deno caches all the packages locally and uses them, which is very fast compared to Node.</p>
<p>You can check out the <a target="_blank" href="https://minimalist-blog.deno.dev/">demo blog website here,</a> and all the <a target="_blank" href="https://github.com/officialrajdeepsingh/Minimalist-blog">code is available on GitHub here</a>.</p>
<p>Now let's dive into the tutorial.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><a class="post-section-overview" href="#heading-lume-markdown">Lume + Markdown</a></li>
<li><a class="post-section-overview" href="#heading-why-is-lume-special">Why is Lume special?</a></li>
<li><a class="post-section-overview" href="#heading-how-does-lume-compare-to-other-static-site-generators">How does Lume compare to other static site generators?</a></li>
<li><a class="post-section-overview" href="#heading-how-to-start-a-new-project-with-lume">How to start a new project with Lume</a></li>
<li><a class="post-section-overview" href="#heading-lume-folder-structure">Lume folder structure</a></li>
<li><a class="post-section-overview" href="#additional-folders">Additional folders</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-global-data">How to create global data</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-a-dynamic-page">How to create a dynamic page</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-a-home-and-pagination-page">How to create a Home and Pagination page</a></li>
<li><a class="post-section-overview" href="#heading-how-to-build-an-articles-page">How to build an articles page</a></li>
<li><a class="post-section-overview" href="#heading-how-to-generate-a-category-page">How to generate a category page</a></li>
<li><a class="post-section-overview" href="#heading-how-to-generate-a-tag-page">How to generate a tag page</a></li>
<li><a class="post-section-overview" href="#heading-how-to-enable-search-functionality">How to enable search functionality</a></li>
<li><a class="post-section-overview" href="#heading-how-to-install-page-find">How to install page find</a></li>
<li><a class="post-section-overview" href="#heading-lume-seo">Lume SEO</a></li>
<li><a class="post-section-overview" href="#heading-lume-sitemap">Lume Sitemap</a></li>
<li><a class="post-section-overview" href="#heading-lume-plugins">Lume plugins</a></li>
<li><a class="post-section-overview" href="#heading-how-to-enable-comments">How to enable comments</a></li>
<li><a class="post-section-overview" href="#heading-how-to-use-netlify-cms-with-lume">How to use Netlify CMS with Lume</a></li>
<li><a class="post-section-overview" href="#heading-how-to-deploy-your-blog-with-deno-deploy">How to deploly your blog with Deno Deploy</a></li>
<li><a class="post-section-overview" href="#github-pages">Github pages</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ol>
<h2 id="heading-lume-markdown">Lume + Markdown</h2>
<p>Lume is a new static site generator based on Deno created and maintained by <a target="_blank" href="https://github.com/oscarotero">Óscar Otero</a>. Lume uses <strong>markdown-it</strong> as the default markdown. You can use the <a target="_blank" href="https://lume.land/plugins/remark/">remark plugin</a> to change the default markdown.  </p>
<p>Markdown is a language that helps to write documents, readme files, and blogs on the internet. <a target="_blank" href="https://en.wikipedia.org/wiki/John_Gruber">John Gruber</a> created markdown in 2004.</p>
<p><strong>Markdown-it</strong> is similar to <a target="_blank" href="https://github.github.com/gfm/">GitHub-flavored Markdown</a> (GFM) markdown. GFM and <a target="_blank" href="https://github.com/markdown-it/markdown-it">markdown-it</a> both follow the exact <a target="_blank" href="https://commonmark.org/">markdown specifications</a>. </p>
<p>If you've worked with GitHub and written README files, that means you are likely familiar with GFM markdown. If you don't like the default (markdown-it) markdown, you can change the markdown with the remark plugin.</p>
<p>There are tons of static site generators. So why is Lume special? What does it provide compared to other static site generators? Let's find out.</p>
<h2 id="heading-why-is-lume-special">Why is Lume special?</h2>
<p>As you know, Lume is built on Deno, and Deno is a Node.js alternative—that is why Lume provides lots of features out of the box. </p>
<p>Lume works similarly to a GitHub readme file. If you're familiar with writing one of those (and using markdown), you do not need to learn anything else to write articles and documentation with Lume.</p>
<p>Here are some benefits of Lume:</p>
<ol>
<li>Lume supports multiple template engines like Markdown, <a target="_blank" href="https://lume.land/plugins/nunjucks/">Nunjucks</a>, <a target="_blank" href="https://lume.land/plugins/eta/">Eta</a>, <a target="_blank" href="https://lume.land/plugins/jsx/">JSX</a>, <a target="_blank" href="https://lume.land/plugins/liquid/">Liquid</a>, or <a target="_blank" href="https://lume.land/plugins/pug/">Pug</a>.</li>
<li>It supports multiple authors</li>
<li>It has code syntax highlighting</li>
<li>There's great SEO support</li>
<li>Lume supports multiple languages</li>
<li>It has Windi CSS support</li>
<li>There's pagination and component support</li>
<li>It supports minifying JavaScript, HTML, CSS, and SASS</li>
<li>It has relations support</li>
<li>There is the built-in search functionality</li>
<li>It supports Netlify CMS</li>
<li>It supports images and SVGs</li>
<li>There's Remark.js plugin support</li>
<li>You can deploy with Netlify, Vercel, GitLab Pages, and the GitHub page.</li>
</ol>
<h2 id="heading-how-does-lume-compare-to-other-static-site-generators">How Does Lume Compare to Other Static Site Generators?</h2>
<p>Lume is a new static site generator compared to others, but it comes with many configuration options, and you can do anything with it. You don't even need to use any third-party plugins. </p>
<p>With Lume processors and preprocessors, you can easily manipulate the HTML code with the JavaScript DOM API. Other static site generators support a few template engines, but Lume supports many template engines like JavaScript, JSX, Nunjucks, Eta, JSX, Liquid, and Pug.</p>
<p>Note that Lume can seem tough to get started with for beginners. But if you're following my article, just make sure to <a target="_blank" href="https://github.com/officialrajdeepsingh/Minimalist-blog">open the code</a> which will make things much clearer for you.</p>
<h2 id="heading-how-to-start-a-new-project-with-lume">How to Start a New Project with Lume</h2>
<p>You can set up a new project with the Lume CLI with this command:</p>
<pre><code class="lang-bash">deno run -Ar https://deno.land/x/lume/init.ts
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/lume-installation-low.gif" alt="Lume installation demo" width="600" height="400" loading="lazy">
<em>Lume installation demo</em></p>
<h4 id="heading-follow-these-steps">Follow these steps:</h4>
<ol>
<li>First, create an empty  <code>mkdir lume-deno</code> folder project.</li>
<li>Then run the lume <code>init.ts</code> command.</li>
<li>Select an available plugin from the list.</li>
</ol>
<p>And you should be up and running.</p>
<h2 id="heading-lume-folder-structure">Lume Folder Structure</h2>
<p>After the installation finished, we saw three files:</p>
<ol>
<li><code>_config file</code> is used to configure Lume.</li>
<li><code>deno.json</code> is a defined script or task for Deno.</li>
<li><code>import_map.json</code> is to help you import a Deno package for the internet.</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/folder-struture-1.png" alt="lume default folder structure " width="600" height="400" loading="lazy">
<em>lume default folder structure</em></p>
<h3 id="heading-how-to-run-the-lume-server">How to run the Lume server</h3>
<p>To run a local development server, you'll use the <code>deno task lume --serve</code> command. To build a website, run the <code>deno task build</code> command.</p>
<p>If you face a 404 - not found error, you can create a <code>index.njk</code> file within the root folder.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/lume404-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>In the <code>index.njk</code> file, paste the following code.</p>
<pre><code class="lang-nunjucks">---
title: "hello"
---
hello world
</code></pre>
<p>And you'll see the following output:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/hello-world-lume-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Lume hello-world</em></p>
<h3 id="heading-additional-folders">Additional folders:</h3>
<ol>
<li><code>posts</code> folder is not a compulsory folder. It contains all your posts' markdown files.</li>
<li><code>pages</code> folder is not a compulsory folder. It has all your pages' markdown files.</li>
<li><code>author</code> folder is not a compulsory folder. It has all your author markdown files.</li>
<li><code>_components</code> folder is a <strong>compulsory</strong> folder. It has all your components.</li>
<li><code>_includes</code>  folder is a <strong>compulsory</strong> folder. It contains your layout and templates for your site.</li>
<li><code>images</code> folder is not a compulsory folder. It contains all your images.</li>
</ol>
<p>The posts, pages, authors, and images folders are optional. You can rename these folders according to your wishes. The <code>_components</code> and <code>_includes</code> folders are mandatory and you don't rename them.</p>
<p>The difference between components, layout, and template are as follows:</p>
<ul>
<li>The components are reusable code</li>
<li>The layout and template are not reusable like components.</li>
</ul>
<h2 id="heading-how-to-create-global-data">How to Create Global Data</h2>
<p>In Lume, you can create a data variable, which has access to the entire website by all template engines.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Set a variable</span>
site.data(<span class="hljs-string">"post_per_page"</span>, <span class="hljs-number">10</span>);

<span class="hljs-comment">// Set a function</span>
site.data(<span class="hljs-string">"randomNumber"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-built_in">Math</span>.random();
});
</code></pre>
<h4 id="heading-how-to-create-posts-pages-and-author-markdown-files">How to create posts, pages, and author markdown files</h4>
<p>You create posts, pages, and author folders in the root folder. Then, inside every folder, you write markdown files.</p>
<p>You can access all posts, pages, and authors by file name on the browser:</p>
<ol>
<li><code>localhost:3000/posts/your-title.html</code></li>
<li><code>localhost:3000/pages/your-pages.html</code></li>
<li><code>localhost:3000/author/your-author.html</code></li>
</ol>
<p>Suppose you need a demo post, pages, and author markdown for a project or template. Then, you can use <a target="_blank" href="https://github.com/officialrajdeepsingh/Demo-markdown-posts">demo-markdown posts</a> for your project. It is free and open source, and you can create your own template.</p>
<h3 id="heading-how-to-create-a-dynamic-page">How to create a dynamic page</h3>
<p>In Lume, <code>.tmpl.js</code> and <code>.tmpl.ts</code> extensions use JS and TS as <a target="_blank" href="https://lume.land/plugins/modules/">template engines</a>. You can use them with regular pages or dynamic pages to create categories, tags, pagination, and so on for your website.</p>
<h3 id="heading-how-to-create-a-home-and-pagination-page">How to create a home and pagination page</h3>
<p>The home page is based on pagination, and pagination is based on posts. Lume dynamically generates the pagination. </p>
<p>In Lume, I chose nunjucks and JavaScript to create my demo website. Nunjucks is the default template engine. You can easily change the default Nunjucks engine with another template engine with copy-paste code.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/Home-page-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>home page</em></p>
<p>Lume provides a JavaScript template function that helps create dynamic web pages. If you create a home page for the site, you need to create an <code>index.tmpl.js</code> file in your root or src folder. Lume also supports an src folder to organize your project. In my demo project, I'm not using the <code>src</code> folder.</p>
<p>The  <code>*.tmpl.js</code> is an extension of a <a target="_blank" href="https://lume.land/plugins/modules/#creating-pages">JavaScript template</a> that helps create dynamic pages for websites. It comes pre-installed in Lume with the <a target="_blank" href="https://lume.land/plugins/modules/">modules plugin</a>.</p>
<p>For example, the following code creates pagination for your website. But the layout comes from the <code>_includes</code> folder.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// index.tmpl.js</span>

<span class="hljs-comment">// title for SEO</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> title = <span class="hljs-string">"Minimalist blog"</span>
<span class="hljs-comment">// description for SEO</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> description = <span class="hljs-string">"Minimalist blog theme is liteweight and work with lume."</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span>* (<span class="hljs-params">{ search, paginate }</span>) </span>{

<span class="hljs-comment">//  Get all posts of type article.</span>
  <span class="hljs-keyword">const</span> posts = search.pages(<span class="hljs-string">"type=article"</span>, <span class="hljs-string">"date=desc"</span>);

  <span class="hljs-comment">// Configation for pagination</span>
  <span class="hljs-keyword">const</span> options = {
    <span class="hljs-comment">// Page 1 is the homepage, set "/" as url</span>
    <span class="hljs-attr">url</span>: <span class="hljs-function">(<span class="hljs-params">n</span>) =&gt;</span> n === <span class="hljs-number">1</span> ? <span class="hljs-string">"/"</span> : <span class="hljs-string">`/page/<span class="hljs-subst">${n}</span>/`</span>,
    <span class="hljs-comment">// par page posts</span>
    <span class="hljs-attr">size</span>: <span class="hljs-number">7</span>,
  };

  <span class="hljs-comment">// Yield the pages, but the index needs a different layout</span>
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> page <span class="hljs-keyword">of</span> paginate(posts, options)) {

    <span class="hljs-comment">//  if home page, use diffrent layout "/"</span>
    <span class="hljs-keyword">if</span> (page.pagination.page === <span class="hljs-number">1</span>) {
      page.menu = {<span class="hljs-attr">visible</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">order</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">title</span>:<span class="hljs-string">"Home"</span> }
      page.title = <span class="hljs-string">"Home page"</span>

      <span class="hljs-comment">//  comes from _includes folder</span>

      page.layout = <span class="hljs-string">"layouts/home.njk"</span>;
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-comment">// Render diffrent layout if it is not home page page "/page/2","/page/3",etc</span>
      page.title = <span class="hljs-string">"Pagination page"</span>

      page.layout = <span class="hljs-string">"layouts/home.njk"</span>;
    }

    <span class="hljs-keyword">yield</span> page;
  }

}
</code></pre>
<p>‌Lume has a <a target="_blank" href="https://lume.land/plugins/search/">search plugin</a> that helps you search pages. In my demo blog, I search all pages base on the type. </p>
<p>In my all posts folder, all posts are defined in <code>type=article</code>, the author is described in <code>type=author</code>, and pages are defined in <code>type=page</code> . The search plugin is pre-installed with Lume.</p>
<p>On <code>index.tmpl.js</code> file, you can get all pages that have the type "article" (<code>type=article</code> ) using the following code:  <code>const posts = search.pages("type=article", "date=desc");</code>. The <code>search.pages("type=article", "date=desc")</code> function only returns those that have <code>type=article</code> .</p>
<p>The  <code>layouts/base.njk</code> layout file contains an HTML base and includes a header and footer for the website.</p>
<pre><code class="lang-nuckjunks">&lt;!doctype html&gt;
&lt;html lang="en"&gt;
  &lt;head&gt;
    &lt;meta charset="utf-8"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    &lt;title&gt;{{ title }}&lt;/title&gt;
    &lt;meta name="description" content="{{ description or site.description }}"&gt;
   &lt;/head&gt;
  &lt;body&gt;

    {% include "layouts/header.njk" %}

    &lt;main class="{{ bodyClass }}"&gt;
      {{ content | safe }}
    &lt;/main&gt;

    {% include "layouts/footer.njk" %}

  &lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>Inside the <code>{{ content | safe }}</code>, Lume renders other HTML, like cards, articles, home templates, Tag and category pages, and so on.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// rest code ...</span>
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> page <span class="hljs-keyword">of</span> paginate(posts, options)) {
  }
<span class="hljs-comment">// rest code ...</span>
</code></pre>
<p>I used the for loop on the <code>index.tmp.js</code> file that helps get all the posts and send them to the <code>layouts/home.njk</code> file and the <code>layouts/home.njk</code> file. You get all posts from the result, and then pass them to the <code>card.njk</code> template.</p>
<pre><code class="lang-nunjucks">---
layout: layouts/base.njk
---

{% for post in results %}
    {% include "templates/card.njk" %}
{% else %}
    &lt;h2&gt; Posts is empty &lt;/h2&gt;
{% endfor %}

{% include "templates/pagnation.njk" %}
</code></pre>
<p>‌The <code>templates/card.njk</code>  file runs for all blogs and generates HTML for each blog. Your card looks like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/card.njk-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>card.njk</em></p>
<p>In <code>card.js</code> template, you can access it using <code>{{}}</code> curly brackets. Get the title using <code>{{post.data.title}}</code> and <code>{{post.data.description}}</code>.</p>
<p>In my demo blog, I'm getting only the first category to show inside the card. So I use a defined filter  <code>_config.ts</code> and use it with <code>|</code> symbols. Inside <code>card.njk</code> we get a zero index or first value in from categories with the following code: <code>{{ post.data.category | category }}</code>.</p>
<p>To get the author on <code>card.njk</code> I define the <a target="_blank" href="https://lume.land/plugins/relations/">relationship</a> between the article and the author type, which you can learn about from the docs.</p>
<pre><code class="lang-nuckjunks">&lt;div class="container px-6 py-10 mx-auto"&gt;

    &lt;div class="mt-8 lg:-mx-6 lg:flex lg:items-center"&gt;

        &lt;img class="object-cover border-none w-full lg:mx-6 lg:w-1/2 rounded-xl h-72 lg:h-96" src="{{ post.data.image }}" alt="{{ post.data.title }}"&gt;

        &lt;div class="mt-6 lg:w-1/2 lg:mt-0 lg:mx-6 "&gt;

            &lt;a class="text-sm text-blue-500 uppercase" href="/category/{{ post.data.category | category }}" &gt;
                {{ post.data.category | category }}
            &lt;/a&gt;

            &lt;a href="{{ post.data.url }}" class="block mt-4 text-2xl font-semibold text-gray-800 hover:text-gray-500 dark:text-white md:text-3xl"&gt;{{ post.data.title }}&lt;/a&gt;

            &lt;p class="mt-3 text-sm text-gray-500 dark:text-gray-300 md:text-sm"&gt;
                {{ post.data.description }}
            &lt;/p&gt;

            &lt;a href="{{  post.data.url }}" class="inline-block p-2 bg-blue-700 mt-4 text-white hover:bg-blue-500"&gt;Read more&lt;/a&gt;


            &lt;div class="flex items-center mt-6"&gt;

                {% if post.data.author.length &lt;= 2 %}

                    {% for author in post.data.author %}

                        &lt;img class="border-none object-cover object-center w-10 h-10 rounded-full" src="{{ author.image}}" alt="{{ author.author_name}}"&gt;

                        &lt;div class="mx-4"&gt;
                            &lt;a href="{{author.url}}" class="text-sm text-gray-700 dark:text-gray-200"&gt;
                                {{ author.author_name}}&lt;/a&gt;
                            &lt;p class="text-sm text-gray-500 dark:text-gray-400"&gt;
                                {{author.job}}
                            &lt;/p&gt;
                        &lt;/div&gt;
                    {% endfor %}
                {% else %}

                    &lt;img class="border-none object-cover object-center w-10 h-10 rounded-full" src="{{ post.data.author.image}}" alt="{{ post.data.author.name}}"&gt;

                    &lt;div class="mx-4"&gt;
                        &lt;a href="{{ post.data.author.url}}" class="text-sm text-gray-700 dark:text-gray-200"&gt;
                            {{ post.data.author.author_name}}&lt;/a&gt;
                        &lt;p class="text-sm text-gray-500 dark:text-gray-400"&gt;
                            {{post.data.author.job}}
                        &lt;/p&gt;
                    &lt;/div&gt;
                {% endif %}

            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;
</code></pre>
<p>The <code>{{ title }}</code> and <code>{{description}}</code> both show the markdown file title and description. To show the category, I used a filter to show a single category on the article page and define the filter on <code>_config.ts</code> file. I also show single and multiple authors with For loop. Every card has its own <code>post.data.url</code> property, after the user clicks on the read more button user ago respected the article read page. To show the image, I used <code>{{ post.data.image }}</code> property. I also show single and multiple authors with For loop on <code>card.njk</code> file.</p>
<h2 id="heading-how-to-build-an-articles-page">How to Build an Articles Page</h2>
<p>I know the page containing the article content is one of the most important for a blog. It's where readers should spend most of their time rather than the website's home page.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/random-blog-title-lume-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<pre><code class="lang-markdown">---
category:
<span class="hljs-bullet">  -</span> Blog
date: 2022-03-20T13:09:24Z
description: Dolor excepteur ad ad fugiat Lorem consectetur velit excepteur duis qui.
image: /images/dice.jpg
tags:
<span class="hljs-bullet">  -</span> npm
<span class="hljs-bullet">  -</span> npm cli
<span class="hljs-bullet">  -</span> npm install command
title: Random blog Title for markdown.
draft: false
author<span class="hljs-emphasis">_id: 1
type: article
layout: templates/article.njk
---

Laboris consequat elit ad excepteur. Ipsum duis amet dolore voluptate dolore consequat ullamco incididunt ullamco. Dolore laborum cupidatat dolor ipsum reprehenderit excepteur cupidatat dolore.

## First
Cupidatat non amet irure esse quis aute qui enim. Est qui ullamco proident consequat aute reprehenderit eiusmod nisi. Laboris ullamco fugiat sint occaecat.

## Second 
Irure fugiat officia non esse esse irure eu sint commodo quis amet. Dolor culpa non amet elit adipisicing exercitation ex anim velit ipsum.

## conclusion
Culpa irure eiusmod labore ut proident sit enim laborum nulla voluptate eu. Id tempor velit cillum pariatur est laboris ipsum ad. Sint nostrud nostrud laboris Lorem consequat tempor voluptate dolore velit. Commodo elit nulla commodo pariatur. Deserunt ipsum fugiat id ipsum pariatur cupidatat magna ex. Fugiat aliquip nisi laboris aliquip velit velit id quis eu reprehenderit excepteur fugiat.</span>
</code></pre>
<p>I created an article in the posts folder under <code>type=article</code> . The <code>author_id</code> defines the relation between the author and the article.</p>
<p>I used <code>templates/article.njk</code> as the layout for my articles page. You can design yours as per your requirements. You can design the article title, description, author card, and tags as well. </p>
<pre><code class="lang-nuckjunks">---
layout: layouts/base.njk
---
&lt;article class="container mx-auto p-2"&gt;
  &lt;div class="flex flex-col"&gt;

    &lt;h1 class="text-2xl text-black mt-3"&gt;{{ title }}&lt;/h1&gt;
    &lt;p class="text-xl mt-1 text-gray-600"&gt;{{ description }}&lt;/p&gt;

    {% if author %}
      &lt;div class="flex flex-row mt-4"&gt;


        {% if author.length &lt;= 2 %}

          {% for author in author %}

            &lt;img class="border-none object-cover object-center w-10 h-10 rounded-full" src="{{ author.image}}" alt="{{ author.author_name}}"&gt;

            &lt;div class="mx-4"&gt;
              &lt;a href="{{author.url}}" class="text-sm text-gray-700 dark:text-gray-200"&gt;
                {{ author.author_name}}&lt;/a&gt;
              &lt;p class="text-sm text-gray-500 dark:text-gray-400"&gt;
                {{author.job}}
              &lt;/p&gt;
            &lt;/div&gt;
          {% endfor %}

        {% else %}

          &lt;img class="border-none object-cover object-center w-10 h-10 rounded-full" src="{{ author.image}}" alt="{{ author.name}}"&gt;

          &lt;div class="mx-4"&gt;
            &lt;a href="{{ author.url}}" class="text-sm text-gray-700 dark:text-gray-200"&gt;
              {{ author.author_name}}&lt;/a&gt;
            &lt;p class="text-sm text-gray-500 dark:text-gray-400"&gt;
              {{ author.job}}
            &lt;/p&gt;
          &lt;/div&gt;
        {% endif %}

      &lt;/div&gt;

    {% endif %}

      &lt;nav class="flex flex-row my-5"&gt;
        {% for tag in tags %}
          &lt;a href="/tag/{{ tag.trim().toLowerCase().split(' ').join("-") }}/" class=" bg-blue-500 text-black p-2  mx-1"&gt;{{ tag }}&lt;/a&gt;
        {% endfor %}
      &lt;/nav&gt;

    &lt;time class="mt-2" datetime="{{ date | date('DATETIME') }}"&gt;
      {{ date | date('HUMAN_DATE') }}
    &lt;/time&gt;


  &lt;/div&gt;

  &lt;div class="mt-4"&gt;
    {{ content | safe }}
  &lt;/div&gt;
&lt;/article&gt;

{%- set previousPost = search.previousPage(url, "type=article") %}

{% if previousPost %}
  &lt;ul class="flex flex-row w-full mt-10 justify-between p-4"&gt;
    {%- if previousPost %}
      &lt;li class="w-6/12 text-left"&gt;
      ← Previous: &lt;a href="{{ previousPost.data.url }}" rel="prev"&gt;{{ previousPost.data.title }}&lt;/a&gt;
      &lt;/li&gt;
    {% endif %}

    {%- set nextPost = search.nextPage(url, "type=article") %}
    {%- if nextPost %}
      &lt;li class="w-6/12 text-right"&gt;
        &lt;strong&gt;Next: &lt;a href="{{ nextPost.data.url }}" rel="next"&gt;{{ nextPost.data.title }}&lt;/a&gt; →&lt;/strong&gt;
      &lt;/li&gt;
    {% endif %}
  &lt;/ul&gt;
{% endif %}

&lt;div class="container p-2 mx-auto mt-6"&gt; 

{# ==== #}
{#  Addding the utteranc Commenting script #}
{# ==== #}

&lt;h1 class="text-center text-2xl my-3"&gt; Comment &lt;/h1&gt; 

&lt;script src="https://utteranc.es/client.js"
        repo="officialrajdeepsingh/Minimalist-blog"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async&gt;
&lt;/script&gt;
&lt;/div&gt;
</code></pre>
<p>The <code>layouts/base.njk</code> file is the base file for our blog (which I've already explained). The <code>{{ title }}</code> and <code>{{description}}</code> both show the markdown file title and description. </p>
<p>To show tags on the article page, I used a for loop. I also showed single and multiple authors with the for loop. </p>
<p>To convert the date into a human-readable format, I used Lume date plugin and wrapped it with a date filter that looks like this: <code>{{ date | date('HUMAN_DATE') }}</code>. To show all markdown paragraphs, I used <code>{{ content | safe }}</code> . </p>
<p>For pagination, I used the Lume pagination plugin, and with the <code>search.previousPage(url, "type=article")</code> function, I showed the next and previous posts on the article page. For comments, I used <a class="post-section-overview" href="#heading-how-to-enable-comments">utteranc.es</a>.</p>
<h2 id="heading-how-to-generate-a-category-page">How to Generate a Category Page</h2>
<p>In Lume, you create a dynamic category based on article type. Lume also provides inbuilt functionality called a JavaScript template engine that helps you create a  dynamic page. It is similar to creating pagination functionality.</p>
<p>In Lume, there's a special file called <code>.tmpl.js</code> that helps you create a dynamic category.</p>
<pre><code class="lang-nunjucks">export const layout = "layouts/category.njk";

export default function* (props) {


  const { search }= props

  for (const category of search.values("category") ) {

    yield {
      url: `/category/${category}/`,
      title: `Categoryed ${category}`,
      type:"category",
      category,
    };

  }

}
</code></pre>
<p>In lume <code>search.values()</code> have a function that helps you find a category using markdown meta tags and sends data into the <code>layout/category.njk</code> file. It will generate all categories with the following URLs like  <code>/category/android/</code> , <code>/category/android-phone/</code> , <code>/category/human/</code> and so on.</p>
<h2 id="heading-how-to-generate-a-tag-page">How to Generate a Tag Page</h2>
<p>Generating a dynamic tags page is similar to a category. Lume provides a special <code>search.tags()</code> function to generate tags:</p>
<pre><code class="lang-nunjucks">export const layout = "layouts/tag.njk";

export default function* ({ search }) {

  for (const tag of search.tags()) {
    yield {
      url: `/tag/${tag}/`,
      title: `Tagged ${tag}`,
      type: "tag",
      tag,
    };
  }
}
</code></pre>
<p>The following code generates all tags with the following URLs like <code>/tag/android/</code>, <code>/tag/android-phone/</code>, <code>/tag/human/</code> and so on.</p>
<h2 id="heading-how-to-enable-search-functionality">How to Enable Search Functionality</h2>
<p>Lume has many in-built plugins which provide an excellent development experience. You can solve lots of problems with Lume plugins, and they allow you to add and remove features easily.</p>
<p>Lume provides inbuilt search functionality for the site. You enable it with the lume page find plugin.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/lume-serachbar-1.png" alt="Add a search bar in lume" width="600" height="400" loading="lazy">
<em>Add a search bar in lume</em></p>
<h3 id="heading-how-to-install-page-find">How to Install Page Find</h3>
<p>The Lume page finds plugin provides you with a search bar. Simply copy the following code and paste it into the <code>_config.ts</code> file and restart your server.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> pagefind <span class="hljs-keyword">from</span> <span class="hljs-string">"lume/plugins/pagefind.ts"</span>;
</code></pre>
<h4 id="heading-how-to-configure-the-page-find-plugin">How to configure the page find plugin</h4>
<p>You configure the plugin in the <code>_config.ts</code> fil. You can also change the default config.</p>
<pre><code><span class="hljs-comment">// rest of code ...</span>
<span class="hljs-keyword">import</span> lume <span class="hljs-keyword">from</span> <span class="hljs-string">"lume/mod.ts"</span>;
<span class="hljs-keyword">import</span> pagefind <span class="hljs-keyword">from</span> <span class="hljs-string">"lume/plugins/pagefind.ts"</span>;

<span class="hljs-keyword">const</span> site = lume();

<span class="hljs-comment">// config the pagefind plugin with default config</span>
site.use(pagefind());

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

<span class="hljs-comment">// change the default config in pagefind plugin</span>
site.use(pagefind({
  <span class="hljs-attr">ui</span>: {
    <span class="hljs-attr">containerId</span>: <span class="hljs-string">"search"</span>,
    <span class="hljs-attr">showImages</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">showEmptyFilters</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">resetStyles</span>: <span class="hljs-literal">true</span>,
  },
}));

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> site;
</code></pre><h2 id="heading-lume-seo">Lume SEO</h2>
<p>Lume has a plugin to help with SEO called metas. With the plugin, you can easily add various SEO-friendly configurations.</p>
<h3 id="heading-how-to-install-metas">How to install metas</h3>
<p>You install all plugins within the <code>config.ts</code> file. Copy the following code and paste it into the <code>config.ts</code> file, then restart the server.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> metas <span class="hljs-keyword">from</span> <span class="hljs-string">"lume/plugins/metas.ts"</span>;
</code></pre>
<h4 id="heading-how-to-configure-metas">How to configure metas</h4>
<p>You can configure metas in various ways in the  <code>_config.ts</code> file. See the comments below:</p>
<pre><code><span class="hljs-keyword">import</span> lume <span class="hljs-keyword">from</span> <span class="hljs-string">"lume/mod.ts"</span>;

<span class="hljs-comment">// install metas plugin for SEO</span>
<span class="hljs-keyword">import</span> metas <span class="hljs-keyword">from</span> <span class="hljs-string">"lume/plugins/metas.ts"</span>;

<span class="hljs-keyword">const</span> site = lume();

<span class="hljs-comment">// config the metas plugin with default config</span>
site.use(metas());

or

<span class="hljs-comment">// add custom config </span>
site.use(metas({
  <span class="hljs-attr">defaultPageData</span>: {
    <span class="hljs-attr">title</span>: <span class="hljs-string">"title"</span>, <span class="hljs-comment">// Use the `title` value as fallback.</span>
  },
}));


<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> site;
</code></pre><h3 id="heading-how-to-use-the-metas-seo-plugin-in-lume">How to Use the Metas SEO Plugin in Lume</h3>
<p>To use the SEO metas plugin, you'll need to create a <code>_data.yml</code> file in the root of the project folder and paste the following code into it:</p>
<pre><code>metas:
  site: Minimalist blog
  <span class="hljs-attr">twitter</span>: <span class="hljs-string">"@Official_R_deep"</span>
  <span class="hljs-attr">icon</span>: <span class="hljs-regexp">/images/i</span>con.png
  <span class="hljs-attr">lang</span>: en
  <span class="hljs-attr">generator</span>: <span class="hljs-literal">true</span>

<span class="hljs-attr">mergedKeys</span>:
  metas: object
</code></pre><p>The following code helps you create all the various SEO tags for your website, and you can easily extend it with the <a target="_blank" href="https://lume.land/plugins/metas/">metas plugin</a> in Lume.</p>
<h3 id="heading-lume-sitemap">Lume Sitemap</h3>
<p>Lume has a plugin called <a target="_blank" href="https://lume.land/plugins/sitemap/">sitemap</a>. This plugin helps you create sitemaps for your blog. With Lume 13 you do not need to create a sitemap manually. </p>
<h4 id="heading-how-to-install-the-sitemap-plugin">How to install the sitemap plugin</h4>
<p>You install all plugins within the <code>config.ts</code> file. Copy the following code and paste it into the <code>config.ts</code> file, then restart the server.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> sitemap <span class="hljs-keyword">from</span> <span class="hljs-string">"lume/plugins/sitemap.ts"</span>;
</code></pre>
<h4 id="heading-how-to-configure-the-sitemap-plugin">How to configure the sitemap plugin</h4>
<p>You can configure the sitemap plugin in various ways in the <code>_config.ts</code> file. See the comments below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> lume <span class="hljs-keyword">from</span> <span class="hljs-string">"lume/mod.ts"</span>;
<span class="hljs-keyword">import</span> sitemap <span class="hljs-keyword">from</span> <span class="hljs-string">"lume/plugins/sitemap.ts"</span>;

<span class="hljs-keyword">const</span> site = lume();

site.use(sitemap());

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

<span class="hljs-comment">// add custom config </span>
site.use(sitemap({
  <span class="hljs-attr">filename</span>: <span class="hljs-string">"my-sitemap.xml"</span>, <span class="hljs-comment">// to change the sitemap filename</span>
  <span class="hljs-attr">query</span>: <span class="hljs-string">"indexable=true"</span>, <span class="hljs-comment">// Select only pages with the indexable attribute as true</span>
  <span class="hljs-attr">sort</span>: <span class="hljs-string">"date=desc"</span>, <span class="hljs-comment">// To sort by data in ascendent order</span>
}));

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> site;
</code></pre>
<h3 id="heading-how-to-use-the-sitemap-plugin-in-lume">How to use the sitemap plugin in Lume</h3>
<p>You do not need any special file to use the site map plugin. Simply add the plugin after calling the plugin in <code>config.ts</code> and it'll start working on your site. This creates the <code>sitemap.xml</code> file and you can change the file name with a custom configuration in <code>_config.ts</code> file.</p>
<h3 id="heading-how-to-access-the-sitemap-on-the-website">How to access the sitemap on the website</h3>
<p>You can access the sitemap with the filename, for example by default in the localhost <code>[http://localhost:3000/sitemap.xml](http://localhost:3000/sitemap.xml)</code> and production <code>[http://my-domain-name/sitemap.xml](http://localhost:3000/sitemap.xml)</code> . </p>
<h2 id="heading-lume-plugins">Lume Plugins</h2>
<p>Lume comes with <a target="_blank" href="https://lume.land/plugins/?status=all">inbuilt plugins</a>, but you can easily add or remove features according to your requirements. You do not need all the stuff on your site – you can configure everything as you wish. </p>
<p>You can add more template engines, minify HTML, CSS, and JavaScript with plugins, enable code highlighting, date manipulation, image manipulation, SVG support, and more. </p>
<p>You can also easily create your own plugins with lume. <a target="_blank" href="https://lume.land/docs/advanced/plugins/">Lume also provides excellent documentation</a> where you can learn more.</p>
<h2 id="heading-how-to-enable-comments">How to Enable Comments</h2>
<p>To add comments on your Lume site, I think <a target="_blank" href="https://utteranc.es/">utteranc.es</a> is the best choice for all static site generators. utteranc.es is an open-source commenting system based on GitHub. It looks like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/enable-coments-on-minimalist-blog.deno-1.png" alt="Enable comment in lume" width="600" height="400" loading="lazy">
<em>Enable comment</em></p>
<p>If you want to enable comments on the site, the first step is to install an <a target="_blank" href="https://github.com/apps/utterances">utterances application</a> on GitHub. Then, copy and paste the following code into the article read file or where you show comments on the site. </p>
<pre><code class="lang-javascript">&lt;script src=<span class="hljs-string">"https://utteranc.es/client.js"</span>
        repo=<span class="hljs-string">"officialrajdeepsingh/Minimalist-blog"</span>
        issue-term=<span class="hljs-string">"pathname"</span>
        theme=<span class="hljs-string">"github-light"</span>
        crossorigin=<span class="hljs-string">"anonymous"</span>
        <span class="hljs-keyword">async</span>&gt;
&lt;/script&gt;
</code></pre>
<p>Next, you'll need to change the utterance comment script. The first change in the repo <code>repo="your-github-repo"</code> name is compulsory. The others are not. You can adjust according to your requirements – for example, changing the theme, issue term, and so on. </p>
<p>To read more about utterance, here's a <a target="_blank" href="https://joshcollinsworth.com/blog/add-blog-comments-static-site">great article written by Josh Collinsworth</a>.</p>
<p>The best approach is to add utterance comments in lume and then read the <a target="_blank" href="https://github.com/lumeland/lume/discussions/312">GitHub discussion</a>.</p>
<h2 id="heading-how-to-use-netlify-cms-with-lume">How to Use Netlify CMS with Lume</h2>
<p>Netlify CMS is an open-source content management system. You can easily integrate Netlify with Lume using the <a target="_blank" href="https://lume.land/plugins/netlify_cms/">netllify_cms</a> plugin. It is provided by Lume, and you just need to install it and copy/paste the code.</p>
<h3 id="heading-how-to-install-the-netlify-plugin">How to Install the Netlify Plugin</h3>
<p>Import the Netlify plugin in your <code>_config.ts</code> file to use it like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> lume <span class="hljs-keyword">from</span> <span class="hljs-string">"lume/mod.ts"</span>;
<span class="hljs-keyword">import</span> netlifyCMS <span class="hljs-keyword">from</span> <span class="hljs-string">"lume/plugins/netlify_cms.ts"</span>;

<span class="hljs-keyword">const</span> site = lume();

site.use(netlifyCMS());

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> site;
</code></pre>
<p>To configure it, you'll need to create a <code>/_data/netlify_cms.yml</code> file in the root level and then paste the following code after restarting your server:</p>
<pre><code class="lang-yml"><span class="hljs-attr">backend:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">git-gateway</span>
  <span class="hljs-attr">branch:</span> <span class="hljs-string">master</span>

<span class="hljs-attr">media_folder:</span> <span class="hljs-string">statics</span>

<span class="hljs-attr">collections:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">label:</span> <span class="hljs-string">Posts</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">posts</span>
    <span class="hljs-attr">description:</span> <span class="hljs-string">List</span> <span class="hljs-string">of</span> <span class="hljs-string">posts</span>
    <span class="hljs-attr">folder:</span> <span class="hljs-string">posts</span>
    <span class="hljs-attr">extension:</span> <span class="hljs-string">md</span>
    <span class="hljs-attr">create:</span> <span class="hljs-literal">true</span>
    <span class="hljs-attr">fields:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">label:</span> <span class="hljs-string">Title</span>
        <span class="hljs-attr">name:</span> <span class="hljs-string">title</span>
        <span class="hljs-attr">widget:</span> <span class="hljs-string">string</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">label:</span> <span class="hljs-string">Content</span>
        <span class="hljs-attr">name:</span> <span class="hljs-string">body</span>
        <span class="hljs-attr">widget:</span> <span class="hljs-string">markdown</span>
</code></pre>
<p>Netlify will ask you for permissions for the CMS proxy. Type <code>npx netlify-cms-proxy-server</code>  in a terminal, press enter or <code>type y</code>, and your Netlify CMS will start running locally on <a target="_blank" href="http://localhost:3000/admin">http://localhost:3000/admin</a> URL. Now your Lume blog is ready for deployment on Netlify. </p>
<h2 id="heading-how-to-deploy-your-blog-with-deno-deploy">How to Deploy Your Blog with Deno Deploy</h2>
<p>You can deploy Lume on various platforms such as Deno Deploy, GitHub Pages, Gitlab Pages, Netlify, Vercel, Fleek, AWS Amplify, and Cloudflare Pages. Lume also provides <a target="_blank" href="https://lume.land/docs/advanced/deployment/">excellent documentation on deployment</a>. </p>
<p>In this article, I'm deploying my Lume blog with Deno Deploy (and we'll also see how to do it with GitHub pages). Deno Deploy is an official platform built by the Deno team to deploy Deno-based applications.</p>
<p>Before deploying your Lume blog on Deno Deploy, make sure you create a <code>server.ts</code> file in the root level.</p>
<pre><code class="lang-javascript">
<span class="hljs-keyword">import</span> Server <span class="hljs-keyword">from</span> <span class="hljs-string">"lume/core/server.ts"</span>;

<span class="hljs-keyword">const</span> server = <span class="hljs-keyword">new</span> Server({
  <span class="hljs-attr">port</span>: <span class="hljs-number">8000</span>,
  <span class="hljs-attr">root</span>: <span class="hljs-string">`<span class="hljs-subst">${Deno.cwd()}</span>/_site`</span>,
});

server.start();

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Listening on http://localhost:8000"</span>);
</code></pre>
<h4 id="heading-deployment-steps">Deployment Steps:</h4>
<ol>
<li>Create an account on Deno Deploy.</li>
<li>Push your local code to GitHub and then select the <code>server.ts</code> file. Deno Deploy automatically creates a site based on the <code>server.ts</code> the file.</li>
<li>Make sure to first create a custom <code>server.ts</code> file. Then move to the next step.</li>
<li>The easiest way to deploy your site is with GitHub Actions. Create a new <code>.github/workflows/deno.yml</code> file in your project root level and paste the following code into it:</li>
</ol>
<pre><code class="lang-yml"><span class="hljs-attr">name:</span> <span class="hljs-string">Deploy</span>
<span class="hljs-attr">on:</span> [<span class="hljs-string">push</span>]

<span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">deploy:</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">Deploy</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>
    <span class="hljs-attr">permissions:</span>
      <span class="hljs-attr">id-token:</span> <span class="hljs-string">write</span> <span class="hljs-comment"># Needed for auth with Deno Deploy</span>
      <span class="hljs-attr">contents:</span> <span class="hljs-string">read</span> <span class="hljs-comment"># Needed to clone the repository</span>

    <span class="hljs-attr">steps:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Clone</span> <span class="hljs-string">repository</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v3</span>

      <span class="hljs-comment"># <span class="hljs-doctag">TODO:</span> add a build step here</span>

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Upload</span> <span class="hljs-string">to</span> <span class="hljs-string">Deno</span> <span class="hljs-string">Deploy</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">denoland/deployctl@v1</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">project:</span> <span class="hljs-string">"minimalist-blog"</span>
          <span class="hljs-attr">entrypoint:</span> <span class="hljs-string">"./serve.ts"</span>
</code></pre>
<h2 id="heading-how-to-deploy-your-blog-with-github-pages">How to Deploy Your Blog with Github Pages</h2>
<p>GitHub Pages are free static sites you can use to host pages. You can also deploy your Lume blog it. The process of deployment is pretty easy. </p>
<p>To deploy Lume on GitHub pages you need to have GitHub Actions set up. </p>
<h4 id="heading-deployment-steps-1">Deployment Steps</h4>
<ol>
<li>It's best if you have a GitHub repository so you can convert your local website to GitHub Pages.</li>
<li>Create a new repo and push all your local code into it.</li>
<li>Create a new <code>.github/workflows/deno.yml</code> in your project root level, then paste the following code into it and push it into the GitHub repo. The GitHub action runs based on the <code>github.yml</code> action and it generates a GitHub page. </li>
</ol>
<pre><code class="lang-yml"><span class="hljs-attr">name:</span> <span class="hljs-string">Publish</span> <span class="hljs-string">on</span> <span class="hljs-string">GitHub</span> <span class="hljs-string">Pages</span>

<span class="hljs-attr">on:</span>
  <span class="hljs-attr">push:</span>
    <span class="hljs-attr">branches:</span> [ <span class="hljs-string">main</span> ]

<span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">build:</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>

    <span class="hljs-attr">steps:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Clone</span> <span class="hljs-string">repository</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v3</span>

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Setup</span> <span class="hljs-string">Deno</span> <span class="hljs-string">environment</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">denoland/setup-deno@v1</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">deno-version:</span> <span class="hljs-string">v1.x</span>

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Build</span> <span class="hljs-string">site</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">deno</span> <span class="hljs-string">task</span> <span class="hljs-string">build</span>

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Deploy</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">crazy-max/ghaction-github-pages@v3</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">build_dir:</span> <span class="hljs-string">_site</span>
        <span class="hljs-attr">env:</span>
          <span class="hljs-attr">GITHUB_TOKEN:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.MY_GITHUB_TOKEN_PAGE</span> <span class="hljs-string">}}</span>
</code></pre>
<p>You need a GitHub token to deploy your Lume website to GitHub pages. This is a required part of the setup. I found <a target="_blank" href="https://dev.to/github/the-githubtoken-in-github-actions-how-it-works-change-permissions-customizations-3cgp">a great article written by Davide</a> that can help you learn more about GitHub Actions and how to create one.</p>
<p>GitHub Actions takes two or three minutes to finish hosting your website on GitHub Pages. </p>
<p>Check out the <a target="_blank" href="https://github.com/officialrajdeepsingh/minimalist-blog-github-page">GitHub repository</a> to learn how to configure the GitHub workflow for GitHub pages. You can also see a live demo <a target="_blank" href="https://officialrajdeepsingh.github.io/minimalist-blog-github-page/">website on the GitHub page</a>.</p>
<p>A quick note: if you deploy your Lume site on GitHub pages and your image does not show on the website, there are two possible reasons for this:</p>
<ol>
<li>If all image names aren't in lowercase, you might get an error. To resolve the error, convert your image names into lowercase with this command: <code>your.github.com/your-reponame/images/my-image.png</code></li>
<li>If you're using the <code>base_path</code> and <code>relative_urls</code> Lume plugins in your project and <code>relative_urls</code> is redundant, and then you'll need to remove the <code>relative_urls</code> plugin in your project. Your image should now work fine.</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Lume is an easy-to-learn and feature-rich static site generator. You can do anything you imagine with it. Lume gives you a lot of freedom with the code.</p>
<p>The Lume community is not as big as those of Hugo, 11ty, Jekyll, and other tools. But, the Lume maintainers actively reply to everybody who comments in the GitHub discussion. Without a strong community, this tool should be able to create a strong impact.</p>
<p>One challenge with Lume is that it's tough to get started for beginners and is more suited to intermediate and advanced developers. If you're jumping right into using Lume as a beginner, you might struggle with a lack of background knowledge about how static site generators work. </p>
<p>Because of this, it's helpful to have a <strong>little bit of knowledge</strong> about Nuckjunks, JSX, and other template engines that work based on markdown. Once you gain this experience, then you'll easily be able to use Lume to design your markdown-based blog. </p>
<p>I recommend using the <a target="_blank" href="https://lume.land/plugins/mdx/">lume MDX plugin</a> for markdown. You can use JSX-based components inside the markdown file, and you can create beautiful code blocks, tip blocks, and so on.</p>
<p>I highly encourage all developers to try Lume out. If you have problems with Lume, you can reach out to its creator on the <a target="_blank" href="https://github.com/lumeland/lume/discussions">GitHub discussion</a> and the <a target="_blank" href="https://discord.com/invite/YbTmpACHWB">Discord server</a>. </p>
<p>If your course is about Computer science, Bioinformatics, and Biotechnology. You can join my free <a target="_blank" href="https://www.getrevue.co/profile/officialrajdeepsingh">newsletter</a>. </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use SurrealDb with the Fresh Framework and Deno ]]>
                </title>
                <description>
                    <![CDATA[ SurrealDB is a newly launched database that has recently started gaining popularity in the programming world. SurrealDB was built with the Rust language and was created by Tobie Morgan Hitchcock and Jaime Morgan Hitchcock. SurrealDB's new database co... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-surrealdb-with-fresh-framework/</link>
                <guid isPermaLink="false">66d038b6dac44f94fd94e9d4</guid>
                
                    <category>
                        <![CDATA[ database ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Deno ]]>
                    </category>
                
                    <category>
                        <![CDATA[ TypeScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Rajdeep Singh ]]>
                </dc:creator>
                <pubDate>Fri, 23 Sep 2022 17:51:53 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/09/Surreal-DB--and-deno-fresh-CMS--4-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>SurrealDB is a newly launched database that has recently started gaining popularity in the programming world.</p>
<p>SurrealDB was built with the Rust language and was created by <a target="_blank" href="https://www.linkedin.com/in/tobiemorganhitchcock/">Tobie Morgan Hitchcock</a> and <a target="_blank" href="https://www.linkedin.com/in/jaimemorganhitchcock/">Jaime Morgan Hitchcock</a>.</p>
<p>SurrealDB's new database comes with many features, but I'm most interested in the <a target="_blank" href="https://surrealdb.com/docs/integration/libraries/deno">Deno surrealDB</a> library.</p>
<p>In this article, we'll create a simple todo app with the <a target="_blank" href="https://fresh.deno.dev/">Fresh framework</a> and SurrealDB database. We'll use the Fresh framework to build out the API with surrealDB.</p>
<p>The Fresh framework is a new JavaScript framework introduced by Deno itself. Fresh uses the <a target="_blank" href="https://preactjs.com/">Preact library</a> to design and build components. Fresh comes with inbuilt TypeScript and Tailwind CSS support and <strong>Island-based</strong> architecture. There's also no configuration needed.</p>
<p>Deno and Fresh are <strong>production ready</strong>. So you can build any web app and deploy it with one single click. But keep in mind that SurrealDB may not be. According to their docs, SurrealDB is production ready but the documentation is not super clear on the issue.</p>
<p>All the code is <a target="_blank" href="https://github.com/officialrajdeepsingh/surrealDb-deno">available on GitHub.</a></p>
<h3 id="heading-heres-a-demo-of-what-well-be-building">Here's a Demo of What We'll be Building:</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/tododemo.gif" alt="TODO Application demo" width="600" height="400" loading="lazy">
<em>TODO Application demo</em></p>
<h2 id="heading-how-to-install-surrealdb-deno-and-the-fresh-framework">How to Install SurrealDB, Deno, and the Fresh Framework</h2>
<p>There are three requirements to follow along with this tutorial: the first is having <strong>Deno</strong> installed, the second is having the <strong>SurrealDB database</strong>, and the last one is using the Fresh framework.</p>
<p>First, we'll install the <a target="_blank" href="https://surrealdb.com/">surrealDB</a> database and the <a target="_blank" href="https://fresh.deno.dev/">Fresh framework</a> with Deno. You can skip this part if you have already installed both Deno and the SurrealDB packages.</p>
<h3 id="heading-how-to-install-the-surrealdb-database-on-linux">How to Install the SurrealDB database on Linux</h3>
<p>The SurreadDB installation process is pretty easy for all operating systems. For example, in Linux, you can install the database with one single curl command.</p>
<p>If you have a different operating system, I suggest reading the <a target="_blank" href="https://surrealdb.com/install">SurrealDB installation</a> docs.</p>
<p>In Linux, use this command:</p>
<pre><code class="lang-bash">curl -sSf https://install.surrealdb.com | sh
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/surrealdb.png" alt="Install the SurrealDB database in Linux." width="600" height="400" loading="lazy">
<em>Install the SurrealDB database in Linux.</em></p>
<p>To start the surrealDB database in Linux, run the following command:</p>
<pre><code>surreal start --log debug --user root --pass root memory
</code></pre><ol>
<li>You use the <code>--user</code> flag for your username. In my case, my username is root.</li>
<li>You use the <code>--pass</code> flag for your password. In my case, my password is root.</li>
</ol>
<p>To learn more about all the flags or options, run <code>surreal start --help</code>  command. This is what you'll see:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/Screenshot-from-2022-09-19-20-00-50.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Now you're ready to use the SurrealDB database.</p>
<h3 id="heading-how-to-install-deno-on-linux">How to Install Deno on Linux</h3>
<p>Deno is a newer JavaScript run time environment. It's fast and secure when you compare it to Node.js. </p>
<p>To learn more about Deno, you can <a target="_blank" href="https://www.freecodecamp.org/news/intro-to-deno/">read this helpful tutorial I found</a> on freeCodeCamp written by Brian Barrow.</p>
<p>To install Deno on Linux, you need one command:</p>
<pre><code class="lang-deno">curl -fsSL https://deno.land/install.sh | sh
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/install-deno-with-curl-command.png" alt="Install deno in Linux" width="600" height="400" loading="lazy">
<em>Install deno in Linux</em></p>
<h3 id="heading-how-to-install-the-fresh-framework-with-deno">How to Install the Fresh Framework with Deno</h3>
<p>Fresh is a new JavaScript framework based on Deno. The Fresh framework supports TypeScript by default. In addition, Fresh sends zero DB of JavaScript by default to the client. </p>
<p>You can set up a Fresh project with the following command:</p>
<pre><code class="lang-deno">deno run -A -r https://fresh.deno.dev my-new-fresh-project
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/Install-surrealDB-deno.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You can run a local development server with <code>deno task start</code> . </p>
<p><strong>Note</strong> that both the Fresh framework and SurrealDB use the same <code>8000</code> port. In the SurrealDB, I didn't find any document about port changing. But in Fresh, you can easily change the port inside <code>main.ts</code> file. Then, without changing the port, your Fresh localhost redirects the SurrealDB local host. </p>
<p>For example, you can change the port in Fresh like this:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// change port in main.ts</span>

<span class="hljs-keyword">await</span> start(manifest, { <span class="hljs-attr">port</span>:<span class="hljs-number">3002</span>, <span class="hljs-attr">plugins</span>: [twindPlugin(twindConfig)] });
</code></pre>
<h2 id="heading-fresh-framework-project-structure">Fresh Framework Project Structure</h2>
<p>The project folder structure is pretty straightforward. For this project, we must follow the folder and file structure to create a todo list app with SurrealDB.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/folder-strutucre.png" alt="Image" width="600" height="400" loading="lazy">
<em>File and folder structure</em></p>
<p>Let's further discuss some essential files here:</p>
<ol>
<li>The components folder helps contain all custom components built with Preact.</li>
<li>In the <code>deno.json</code> file you add tasks and the importMap file. Tasks are similar to scripts in Node, and in the importMap section, you pass a JSON file that contains all your import packages from Deno.</li>
<li><code>dev.ts</code> is a file created only for development.</li>
<li><code>fresh.gen.ts</code> generates and updates <strong>automatically</strong> based on <code>dev.ts</code>. It includes all routes, islands, and other configurations.</li>
<li>The <code>import_map.json</code> file contains imports of all packages which you need to run your project.</li>
<li>Islands enable client-side browser-based interactivity in Fresh. Basically, with the island folder, you send JavaScript to the browser. By default, the Fresh framework sends zero KB JavaScript.  </li>
<li><code>main.ts</code> is the main entry point that helps start your application.</li>
<li>The <code>routes</code> folder handles your path and API. It is similar to the Next.js pages folder.</li>
<li>The <code>static</code> folder contains all static files like JavaScript, images, and fonts under a root directory. All are accessed by reference and start with the base URL (<code>/</code>). For example, <code>/logo.svg</code>.</li>
<li><code>twind.config.ts</code> configures Tailwind CSS</li>
<li>The <code>utility</code> folder contains the database configuration. </li>
</ol>
<p>You can learn more about folder structure from Fresh's <a target="_blank" href="https://fresh.deno.dev/docs/getting-started/create-a-project">official docs</a>.</p>
<p>Again, to run a local development server, use the command <code>deno task start</code> .</p>
<h2 id="heading-how-to-install-the-surrealdb-database-library-in-the-fresh-framework">How to Install the SurrealDB Database Library in the Fresh Framework</h2>
<p>You need the Deno-based <a target="_blank" href="https://surrealdb.com/docs/integration/libraries/deno">surrealDB librar</a>y (module). It's a SurrealDB library created by the SurrealDB team. </p>
<p>The SurrealDB library (module) helps you connect your application to your database. The surrealDB module connects your local and remote databases very easily. </p>
<p>To install the SurrealDB module in the Fresh framework, simply copy the following code and paste it into <code>import_map.json</code> file:</p>
<pre><code>  <span class="hljs-string">"surrealdb"</span> : <span class="hljs-string">"https://deno.land/x/surrealdb@v0.2.0/mod.ts"</span>
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2022/09/import-package-in-fresh-cms.png" alt="Install deno module in fresh framework" width="600" height="400" loading="lazy">
_Paste the following code into <code>import_map.json file</code>_</p>
<h3 id="heading-how-to-setup-the-surrealdb-database-in-fresh">How to Setup the SurrealDB Database in Fresh</h3>
<p>The first step is to create a setup file for the SurrealDB database. The setup file helps you connect the Fresh framework to the SurrealDB database.</p>
<p>In my case, I create a database setup in a separate <code>utility/database.ts</code> file. The separate file helps reduce your code and is easier to manage.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// utility/database.ts</span>

<span class="hljs-comment">//  import surrealdb </span>
<span class="hljs-keyword">import</span> Surreal <span class="hljs-keyword">from</span> <span class="hljs-string">"surrealdb"</span>;

<span class="hljs-comment">// load Environment Variables</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">"https://deno.land/x/dotenv@v3.2.0/load.ts"</span>;

<span class="hljs-comment">// get DATABASE_URL url</span>
<span class="hljs-keyword">const</span> domain = Deno.env.get(<span class="hljs-string">"DATABASE_URL"</span>)

<span class="hljs-comment">// surreal database</span>
<span class="hljs-keyword">const</span> db = <span class="hljs-keyword">new</span> Surreal(domain);

<span class="hljs-comment">// signin</span>
<span class="hljs-keyword">await</span> db.signin({
    user: <span class="hljs-string">'root'</span>,
    pass: <span class="hljs-string">'root'</span>,
});



<span class="hljs-comment">//  Select a specific namespace /  database</span>
<span class="hljs-keyword">await</span> db.use(<span class="hljs-string">'test'</span>, <span class="hljs-string">'test'</span>);

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> db
</code></pre>
<p>To connect the database, ensure that your database is running and your password and username match your database conditionals.</p>
<p>For example, run your local SurrealDB user name and password that's the same as in your <code>utility/database.ts</code> file.</p>
<pre><code>surreal start --log debug --user root --pass root memory
</code></pre><h2 id="heading-how-to-use-surrealdb-module-library-methods">How to Use SurrealDB Module (Library) Methods</h2>
<p>The SurrealDB module comes with inbuilt methods. All the methods help you perform CURD operations on the SurrealDB database. These methods allow you to <strong>create</strong> quickly and <strong>get</strong>, <strong>update</strong>, and <strong>delete</strong> things from the database.</p>
<p>In this article, we'll use four methods which are <code>create()</code> , <code>update()</code> , <code>delete()</code> and <code>select()</code>.</p>
<p>There are other methods provided by SurrealDB, which you can read about on the <a target="_blank" href="https://surrealdb.com/docs/integration/libraries/deno">surrealDB module documentation page</a>.</p>
<h3 id="heading-how-to-create-the-api-endpoints">How to Create the API Endpoints</h3>
<p>To create a Todo app, you need four endpoints. We'll use the Fresh framework to create APIs. All the API routes go in the <code>routes/api</code> folder. </p>
<ol>
<li>Get</li>
<li>Post</li>
<li>Isdone (Update)</li>
<li>Delete</li>
</ol>
<h3 id="heading-the-get-api">The Get API</h3>
<p>The Get API lets you show all data from the todo table. To access all data from Todo table, you need a <code>select()</code> function provided by the SurrealDB module.</p>
<pre><code class="lang-get.ts">import { HandlerContext } from "$fresh/server.ts";
import db from "../../utility/database.ts";


export async function handler(_req: Request, _ctx: HandlerContext) {

    try {
        // get all todo list
        const todo = await db.select("todo");

        // return todo 
        return Response.json(JSON.stringify(todo))

    } catch (error) {

        return new Response(error);
    }


}
</code></pre>
<h3 id="heading-the-post-api">The Post API</h3>
<p>In the Post API, you'll create a new todo based on the title. All the todos are saved inside the todo table. With the get API, you access all todos from the todo table.</p>
<p>To create a new todo item in the database, you can use the SurrealDB module's inbuilt <code>create()</code> function.</p>
<pre><code class="lang-post.ts">import { HandlerContext } from "$fresh/server.ts";

// import module uuid from deno 
import * as mod from "https://deno.land/std@0.156.0/uuid/mod.ts";

// import database 
import db from "../../utility/database.ts";


export async function handler(_req: Request, _ctx: HandlerContext) {
    // get url
    const url = new URL(_req.url);

    // get title from url
    const title = url.searchParams.get("title") || "";

    try {

        // Create a new person with a random id

        const NAMESPACE_URL = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";

        // create a unique uuid for demo purposes
        const uuid = await mod.v5.generate(NAMESPACE_URL, new TextEncoder().encode("python.org"));

        // create new data based on value
        const created = await db.create("todo", {
            uuid: uuid,
            title: title,
            isDone: false
        });

        // return data
        return Response.json({ sucessfull: "your data submit sucessfully", created })

    } catch (error) {

        return new Response(error);
    }


}
</code></pre>
<h3 id="heading-the-isdone-update-api">The Isdone (Update) API</h3>
<p>The Isdone API helps to update the todo items inside the todo table. To update data from the table the surrealDB module provides an inbuilt <code>update</code> function for this. </p>
<p>With the <code>update</code> function, you can promptly update the todos by one or more items in one request.</p>
<pre><code class="lang-isdone.ts">import { HandlerContext } from "$fresh/server.ts";

// import database 
import db from "../../utility/database.ts";



export async function handler(_req: Request, _ctx: HandlerContext) {
// get URL
  const url = new URL(_req.url);
  // get todo id based on id we update todo.
  const todoid = url.searchParams.get("todoID") || "";
  // get title
  const todoTitle = url.searchParams.get("todoTitle") || "";
  // get uuid
  const todoUuid = url.searchParams.get("todoUuid") || "";


    try {

        // update the todo
        const person = await db.update(todoid, {
            isDone: true,
            title: todoTitle,
            uuid: todoUuid
        });

        return Response.json({sucessfull:"your data submit sucessfully ",person})

    } catch (error) {

        return new Response(error);
    }


}
</code></pre>
<h3 id="heading-the-delete-api">The Delete API</h3>
<p>You use the Delete API to delete a todo from the todo list. You'll use the inbuilt <code>delete()</code> function. With this inbuilt function, you can quickly delete a todo based on the todo's id.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { HandlerContext } <span class="hljs-keyword">from</span> <span class="hljs-string">"$fresh/server.ts"</span>;

<span class="hljs-comment">// import database </span>
<span class="hljs-keyword">import</span> db <span class="hljs-keyword">from</span> <span class="hljs-string">"../../utility/database.ts"</span>;



<span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handler</span>(<span class="hljs-params">_req: Request, _ctx: HandlerContext</span>) </span>{
    <span class="hljs-comment">// get url</span>
    <span class="hljs-keyword">const</span> url = <span class="hljs-keyword">new</span> URL(_req.url);

    <span class="hljs-comment">// get todo id – based on id we delete todo.</span>
    <span class="hljs-keyword">const</span> todoid = url.searchParams.get(<span class="hljs-string">"todoID"</span>) || <span class="hljs-string">""</span>;


    <span class="hljs-keyword">try</span> {

        <span class="hljs-comment">// delete specified todo item </span>
        <span class="hljs-keyword">await</span> db.delete(todoid);

        <span class="hljs-keyword">return</span> Response.json({ <span class="hljs-attr">sucessfull</span>: <span class="hljs-string">"your data submit sucessfully "</span> })

    } <span class="hljs-keyword">catch</span> (error) {

        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Response(error);
    }

}
</code></pre>
<h2 id="heading-how-to-create-the-ui-for-the-todo-app">How to Create the UI for the Todo App</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/todo-UI.png.png" alt="Image" width="600" height="400" loading="lazy">
<em>UI for dashboard</em></p>
<p>The <strong><code>Box.tsx</code></strong> and <strong><code>Item.tsx</code></strong> files come from an island folder. Both files are known as components. In both components, we need JavaScript integration. For that reason, we create both components inside the island folder.</p>
<h3 id="heading-index-page">Index page</h3>
<p>The index page shows that both the <code>Box.tsx</code> and <code>Item.tsx</code> files come from the island. We'll design the home (Index) page layout with them.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Handlers } <span class="hljs-keyword">from</span> <span class="hljs-string">"$fresh/server.ts"</span>;

<span class="hljs-comment">//  Import Box components from island</span>
<span class="hljs-keyword">import</span> Box <span class="hljs-keyword">from</span> <span class="hljs-string">"../islands/Box.tsx"</span>;

<span class="hljs-comment">//  Import Item components from island</span>
<span class="hljs-keyword">import</span> Item <span class="hljs-keyword">from</span> <span class="hljs-string">"../islands/Item.tsx"</span>;

<span class="hljs-comment">// to load Environment variable </span>
<span class="hljs-keyword">import</span> <span class="hljs-string">"https://deno.land/x/dotenv@v3.2.0/load.ts"</span>;

<span class="hljs-comment">// get Environment variable </span>
<span class="hljs-keyword">let</span> domain= Deno.env.get(<span class="hljs-string">"DOMAIN"</span>)


<span class="hljs-keyword">interface</span> todo {
  id: <span class="hljs-built_in">string</span>;
  title:<span class="hljs-built_in">string</span>;
  isDone:<span class="hljs-built_in">boolean</span>
}

<span class="hljs-comment">//  Call get API with fresh handler</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> handler: Handlers&lt;todo | <span class="hljs-literal">null</span>&gt; = {

  <span class="hljs-keyword">async</span> GET(_, ctx) {

    <span class="hljs-comment">// call get api</span>
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(domain + <span class="hljs-string">"/api/get"</span>).then(      
      <span class="hljs-function">(<span class="hljs-params">response</span>)=&gt;</span> response.json()
    ).then(
      <span class="hljs-function">(<span class="hljs-params">response</span>)=&gt;</span> <span class="hljs-built_in">JSON</span>.parse(response)
    ).catch(
      <span class="hljs-function"><span class="hljs-params">error</span>=&gt;</span> <span class="hljs-built_in">console</span>.log(error)
    );

    <span class="hljs-comment">//  pass data into component props</span>
    <span class="hljs-keyword">return</span> ctx.render(response);
  }
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params">{data}: { data: <span class="hljs-built_in">any</span>; }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"h-screen w-screen flex flex-col items-center justify-center bg-blue-600 font-sans"</span>&gt;
      &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"flex flex-row w-4/6 justify-center mx-auto"</span>&gt;
        &lt;h2 <span class="hljs-keyword">class</span>=<span class="hljs-string">"m-2 p-1 text-5xl font-mono font-serif cursor-pointer"</span>&gt;Deno&lt;/h2&gt;
        &lt;h2 <span class="hljs-keyword">class</span>=<span class="hljs-string">"m-2 p-1 text-5xl font-mono font-serif cursor-pointer"</span>&gt;SurrealDB&lt;/h2&gt;
      &lt;/div&gt;

      &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"bg-white rounded shadow container mx-auto p-3 m-4 w-3/6 lg:w-3/6 xl:w-3/6 md:w-3/6 2xl:w-3/6 "</span>&gt;
            &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">" flex mb-4 flex-col py-2"</span>&gt;
                &lt;h1 <span class="hljs-keyword">class</span>=<span class="hljs-string">"text-gray-500  text-lg"</span>&gt;Todo List&lt;/h1&gt;
                &lt;Box/&gt;
            &lt;/div&gt;
            &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"p-2"</span>&gt;
              {
                data.map( <span class="hljs-function">(<span class="hljs-params">item: <span class="hljs-built_in">any</span></span>) =&gt;</span> 
                  &lt;Item item={item} /&gt;
                )
              }
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<h3 id="heading-the-boxtsx-component">The Box.tsx Component</h3>
<p>The Box component helps call the post API and create a new todo in the database. <code>Box.tsx</code> is an island-based component that's created with Preact. Preact is similar to React, but Preact is a lightweight version of the library.</p>
<p>On the Box component, we get the value in the input with the onChange Event. Then, after the user clicks on the add button, we call the post API to create a new todo in the SurrealDB database.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/Box.tsx-in-index.png" alt="Design the box component with fresh framework" width="600" height="400" loading="lazy">
<em>Design the box component with fresh framework</em></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"preact/hooks"</span>;

<span class="hljs-comment">// import Notification from components</span>
<span class="hljs-keyword">import</span> Notification <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Notification.tsx"</span>;

interface todo {
    <span class="hljs-attr">id</span>: string;
    title: string;
    isDone: boolean
}


<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Box</span>(<span class="hljs-params">{ data }: { data: any; }</span>) </span>{

    <span class="hljs-comment">//  title</span>
    <span class="hljs-keyword">const</span> [title, setTitle] = useState(<span class="hljs-string">""</span>);

    <span class="hljs-comment">// show Notification based on success</span>
    <span class="hljs-keyword">const</span> [successful, setSuccessful] = useState(<span class="hljs-literal">false</span>);


    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">submit</span>(<span class="hljs-params"></span>) </span>{

        <span class="hljs-keyword">if</span> (title) {
            <span class="hljs-comment">//  call post api </span>
            fetch(<span class="hljs-string">`/api/post?title=<span class="hljs-subst">${<span class="hljs-built_in">encodeURIComponent</span>(title)}</span>`</span>)
                .then(<span class="hljs-function">(<span class="hljs-params">res</span>) =&gt;</span> res.json())
                .then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
                    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"your data submit sucessfully "</span>);

                    <span class="hljs-comment">// change false to true</span>
                    setSuccessful(<span class="hljs-literal">true</span>)
                });
        }
    }



    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Notification</span>  <span class="hljs-attr">successful</span>=<span class="hljs-string">{successful}</span>  <span class="hljs-attr">setSuccessful</span>=<span class="hljs-string">{setSuccessful}</span> /&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex mt-4 justify-between"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(event)</span> =&gt;</span> setTitle(event.currentTarget.value)} class="shadow appearance-none border rounded w-full py-2 px-3 mr-4 text-gray-600" placeholder="Add Todo" /&gt;
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{submit}</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex-shrink p-2 border-2 rounded text-purple-500 border-purple-500 hover:text-white hover:bg-purple-500 w-24"</span>&gt;</span>Add<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/&gt;</span></span>
    );
}
</code></pre>
<h3 id="heading-the-itemtsx-component">The Item.tsx Component</h3>
<p>Item component calls two APIs – one is the delete API and the second is the update API. The delete API deletes an item from the todo table and the update API updates item in the todo table in the database.</p>
<p><code>Item.tsx</code> is an island component similar to the Box component. The item component is also built with Preact.</p>
<p>Our first button changes based on whether the todo is complete or pending, and the second button deletes the todo based on the Todo's ID. </p>
<p>First, we get the value in the input with the onChange Event. And after the user clicks on the add button, we call the post API to create a new todo in the SurrealDB database.</p>
<p>When the remove button gets clicked, we call the delete API with the todo ID to delete the todo from the database. When the Not Done button gets clicked, we call the Isdone API to update Isdone in the database.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/Item.tsx.png" alt="Item component in fresh framework" width="600" height="400" loading="lazy">
<em>Item component in the fresh framework</em></p>
<pre><code><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"preact/hooks"</span>;

<span class="hljs-comment">// import Notification from components</span>
<span class="hljs-keyword">import</span> Notification <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Notification.tsx"</span>;

interface todo {
    <span class="hljs-attr">id</span>: string;
    title: string;
    isDone: boolean
}


<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Item</span>(<span class="hljs-params">{ item }</span>) </span>{

    <span class="hljs-comment">// todo</span>
    <span class="hljs-keyword">const</span> [todo, setTodoID] = useState(
        {
            <span class="hljs-attr">id</span>: item.id,
            <span class="hljs-attr">title</span>: item.title,
            <span class="hljs-attr">uuid</span>: item.uuid
        }
    );

    <span class="hljs-comment">// show Notification based on success</span>
    <span class="hljs-keyword">const</span> [successful, setSuccessful] = useState(<span class="hljs-literal">false</span>);

    <span class="hljs-comment">//  delete dfunction</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">deleteItem</span>(<span class="hljs-params"></span>) </span>{

        <span class="hljs-keyword">if</span> (todo.id) {
            <span class="hljs-comment">//  call delete api</span>
            fetch(<span class="hljs-string">`/api/delete?todoID=<span class="hljs-subst">${<span class="hljs-built_in">encodeURIComponent</span>(todo.id)}</span>`</span>)
                .then(<span class="hljs-function">(<span class="hljs-params">res</span>) =&gt;</span> res.json())
                .then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
                    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"your data submit sucessfully "</span>);
                    setSuccessful(<span class="hljs-literal">true</span>)
                });
        }
    }


    <span class="hljs-comment">// isdone</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isDone</span>(<span class="hljs-params"></span>) </span>{

        <span class="hljs-keyword">if</span> (todo.id) {
            <span class="hljs-comment">//  call isdone api</span>
            fetch(<span class="hljs-string">`/api/isdone?todoID=<span class="hljs-subst">${<span class="hljs-built_in">encodeURIComponent</span>(todo.id)}</span>&amp;todoTitle=<span class="hljs-subst">${<span class="hljs-built_in">encodeURIComponent</span>(todo.title)}</span>&amp;todoUuid=<span class="hljs-subst">${<span class="hljs-built_in">encodeURIComponent</span>(todo.uuid)}</span>`</span>)
                .then(<span class="hljs-function">(<span class="hljs-params">res</span>) =&gt;</span> res.json())
                .then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
                    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"your data submit sucessfully "</span>);
                    setSuccessful(<span class="hljs-literal">true</span>)
                });
        }
    }

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">Notification</span> <span class="hljs-attr">successful</span>=<span class="hljs-string">{successful}</span> <span class="hljs-attr">setSuccessful</span>=<span class="hljs-string">{setSuccessful}</span> /&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex mb-4 items-center"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">item.isDone</span> === <span class="hljs-string">false</span> ? "<span class="hljs-attr">w-full</span> <span class="hljs-attr">text-green-500</span> <span class="hljs-attr">cursor-pointer</span>" <span class="hljs-attr">:</span> " <span class="hljs-attr">w-full</span> <span class="hljs-attr">line-through</span> <span class="hljs-attr">decoration-purple-600</span> <span class="hljs-attr">text-green-500</span> <span class="hljs-attr">cursor-pointer</span>"}`}&gt;</span>{item.title}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{isDone}</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex-shrink p-2 ml-4 mr-2 border-2 rounded hover:text-white text-gray-500 border-gray-500 hover:bg-gray-500 w-32"</span>&gt;</span>
                    {item.isDone === true ? "Done" : " Not done"}
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{deleteItem}</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex-shrink p-2 ml-2 border-2 rounded text-red-500 border-red-500 hover:text-white hover:bg-red-500 w-24"</span>&gt;</span>Remove<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/&gt;</span></span>
    );
}
</code></pre><p>And there you have it - we've implemented all our functionality in our Todo app.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>SurrealDB is a helpful database, and I hope you enjoyed learning about it in this tutorial. </p>
<p>There are often a lot of requirements to start working with other databases, but SurrealDB is very simple. You need one command to start the database locally and work with it. It is a new revolution in databases. </p>
<p>The big problem is that SurrealDB is not clear on whether it comes with production capabilities. As of right now, it doesn't seem to fulfill the one-click production-ready web app (like MongoDB Atlas, for example). </p>
<p>You can deploy SurrealDB with a Docker image. The problem is that documents are sometimes not enough info for a new developer (for example, how to change passwords and users in a Docker container). </p>
<p>Without cloud Infrastructure, you would not be able to deploy the application with SuurealDB. <strong>So for that reason, I did not provide a live demo of the Todo app</strong>. But I know that in the future, SuurealDB will change the future of databases.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create a Static Markdown Blog with Deno and Deploy It ]]>
                </title>
                <description>
                    <![CDATA[ Deno is a runtime for JavaScript and TypeScript. The creator of Node.js built it, and while Node is built with C and C++, Deno is built with the Rust language. You might be wondering what some of the main differences between Node and Deno are. Well, ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-a-blog-with-deno/</link>
                <guid isPermaLink="false">66d038acd6e6a35e9f8e697d</guid>
                
                    <category>
                        <![CDATA[ blog ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Deno ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ markdown ]]>
                    </category>
                
                    <category>
                        <![CDATA[ TypeScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Rajdeep Singh ]]>
                </dc:creator>
                <pubDate>Tue, 13 Sep 2022 16:46:28 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/09/Create-a-Static-Markdown-Blog-with-Deno--1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Deno is a runtime for JavaScript and TypeScript. The creator of Node.js built it, and while Node is built with C and C++, Deno is built with the Rust language.</p>
<p>You might be wondering what some of the main differences between Node and Deno are. Well, Rust is a low-level language similar to C and Java. It helps make Deno super fast, and Deno is also more secure than Node.</p>
<p>In this article, we will build a static markdown blog with Deno in less than five minutes. In the end, we'll deploy the markdown blog with Deno deploy.</p>
<p>We'll use Deno's third-party <a target="_blank" href="https://deno.land/x/blog">blog package</a> created by Ryan Dahl and another contributor for the blog</p>
<p>With the Deno blog module, you can create a fantastic blazing-fast blog. Then you can set up and deploy the blog with two lines of code. And it takes less than five minutes to configure it.</p>
<h3 id="heading-what-is-markdown">What is markdown?</h3>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/Markdown">Markdown</a> is a lightweight markup language. It helps create consistently formatted text. To start working in markdown, you need an IDE that supports markdown and you'll need to create a file with a <code>.md</code> extension. Markdown typically supports written documents, blogs, and so on. </p>
<p>Some examples of documents written in Markdown are GitHub and npm READMEs, the React.js, and many more.</p>
<p>The Deno blog module (Package) comes with markdown support and lets you create a static blog. This module comes with lots of features, like:</p>
<ol>
<li>Markdown support.</li>
<li>Auto refresh. Any change in a markdown file automatically builds and reloads your website in the browser.</li>
<li>You can customize the header and add comments and a footer section.</li>
<li>It supports SEO, SEO markup, and an inbuilt feed (sitemap).</li>
<li>iFrames support with markdown files.</li>
<li>It has built-in Preact, TypeScript, and Tailwind CSS support.</li>
<li>It allows multiple authors </li>
<li>It has middleware and redirects pathname support </li>
<li>It comes with server-side Google Analytics support</li>
</ol>
<p>Here's a <a target="_blank" href="https://deno-markdown-blog.deno.dev/">demo of the blog we'll build and deploy:</a></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/denoblogdemo.gif" alt="deno blog demo" width="600" height="400" loading="lazy">
<em>deno blog demo</em></p>
<p>All the code is <a target="_blank" href="https://github.com/officialrajdeepsingh/deno-markdown-blog">available on GitHub</a>.</p>
<h3 id="heading-here-are-the-steps-well-follow">Here are the steps we'll follow:</h3>
<ol>
<li>How to install and setup the blog</li>
<li>How to understand the folder structure</li>
<li>How to start the local developer server</li>
<li>How to add more configuration to the blog.</li>
<li>How to deploy with Deno</li>
</ol>
<h2 id="heading-how-to-install-and-setup-the-blog">How to Install and Setup the Blog</h2>
<p>First, you'll need to install the Deno blog module. The blog module comes with the init command to create a new blog setup. It looks like this:</p>
<pre><code>deno run -r --allow-read --allow-write https:<span class="hljs-comment">//deno.land/x/blog/init.ts my-deno-demo-blog-name</span>
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2022/09/create-deno-blog.png" alt="Create a blog setup with the deno blog module" width="600" height="400" loading="lazy">
<em>Create a blog setup with the deno blog module</em></p>
<h2 id="heading-how-to-understand-the-folder-structure">How to Understand the Folder Structure</h2>
<p>The beauty of Deno is that you only need a few files to start a project. For the markdown blog, you need only four files:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/deno-blog-folder-structure--1-.png" alt="deno folder structure" width="600" height="400" loading="lazy">
<em>deno folder structure</em></p>
<p>Let's go through each file in the above folder structure:</p>
<ul>
<li>In the <code>deno.jsonc</code> file you add tasks and the importMap file. Tasks are similar to scripts in Node, and in the importMap section, you pass a JSON file that contains all your import packages from Deno.</li>
<li>The <code>import_map.json</code> file contains imports of all packages which you need to run your project.</li>
<li>The <code>posts</code> folder contains all markdown files.</li>
<li>The <code>main.tsx</code> file contains all configurations for the blog module.</li>
</ul>
<h2 id="heading-how-to-start-the-local-developer-server">How to Start the Local Developer Server</h2>
<p>After installation is complete, run the local development server with the <code>deno task dev</code> command.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/run-deno-blog.png" alt="Run deno local development server" width="600" height="400" loading="lazy">
<em>Run deno local development server</em></p>
<h2 id="heading-how-to-add-more-configuration-to-the-blog">How to Add More Configuration to the Blog</h2>
<p>The blog module default comes with the following configuration in the <code>main.tsx</code> file. You can easily change blog configurations according to your requirements.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// main.tsx</span>

<span class="hljs-keyword">import</span> blog, { ga, redirects, h } <span class="hljs-keyword">from</span> <span class="hljs-string">"blog"</span>;

blog({
  title: <span class="hljs-string">"My Blog"</span>,
  description: <span class="hljs-string">"This is my new blog."</span>,
  <span class="hljs-comment">// header: &lt;header&gt;Your custom header&lt;/header&gt;,</span>
  <span class="hljs-comment">// section: &lt;section&gt;Your custom section&lt;/section&gt;,</span>
  <span class="hljs-comment">// footer: &lt;footer&gt;Your custom footer&lt;/footer&gt;,</span>
  avatar: <span class="hljs-string">"https://deno-avatar.deno.dev/avatar/blog.svg"</span>,
  avatarClass: <span class="hljs-string">"rounded-full"</span>,
  author: <span class="hljs-string">"An author"</span>,

  <span class="hljs-comment">// middlewares: [</span>

    <span class="hljs-comment">// If you want to set up Google Analytics, paste your GA key here.</span>
    <span class="hljs-comment">// ga("UA-XXXXXXXX-X"),</span>

    <span class="hljs-comment">// If you want to provide some redirections, you can specify them here,</span>
    <span class="hljs-comment">// pathname specified in a key will redirect to pathname in the value.</span>
    <span class="hljs-comment">// redirects({</span>
    <span class="hljs-comment">//  "/hello_world.html": "/hello_world",</span>
    <span class="hljs-comment">// }),</span>

  <span class="hljs-comment">// ]</span>
});
</code></pre>
<h3 id="heading-custom-configuration">Custom configuration</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/denoblog.png" alt="Demo of custom configuration" width="600" height="400" loading="lazy">
<em>Demo of custom configuration</em></p>
<p>With custom configuration, you can make your website look however you want – even like the example above. In addition, you can quickly add more custom configurations to your blog. </p>
<p>For example, you can change the default header, footer, title, author, theme, custom style, links, section, and so on. Here's some code to do that:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// main.tsx</span>

<span class="hljs-comment">/** <span class="hljs-doctag">@jsx </span>h */</span>
<span class="hljs-keyword">import</span> blog, { h } <span class="hljs-keyword">from</span> <span class="hljs-string">"blog"</span>;
<span class="hljs-keyword">import</span> { Section } <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Section.jsx'</span>;

blog({
  <span class="hljs-attr">author</span>: <span class="hljs-string">"Rajdeep singh"</span>,
  <span class="hljs-attr">title</span>: <span class="hljs-string">"Hello, my name is Rajdeep Singh"</span>,
  <span class="hljs-attr">description</span>: <span class="hljs-string">"Nice to meet you"</span>,
  <span class="hljs-attr">avatar</span>:<span class="hljs-string">"assets/logos/profile.jpg"</span>,
  <span class="hljs-attr">avatarClass</span>: <span class="hljs-string">"rounded-full"</span>,
  <span class="hljs-attr">coverTextColor</span>:<span class="hljs-string">"white"</span>,
  <span class="hljs-attr">links</span>: [
    { <span class="hljs-attr">title</span>: <span class="hljs-string">"Email"</span>, <span class="hljs-attr">url</span>: <span class="hljs-string">"mailto:officialrajdeepsingh@gmail.com"</span> },
    { <span class="hljs-attr">title</span>: <span class="hljs-string">"GitHub"</span>, <span class="hljs-attr">url</span>: <span class="hljs-string">"https://github.com/officialrajdeepsingh"</span> },
    { <span class="hljs-attr">title</span>: <span class="hljs-string">"Twitter"</span>, <span class="hljs-attr">url</span>: <span class="hljs-string">"https://twitter.com/Official_R_deep"</span> },
    { <span class="hljs-attr">title</span>: <span class="hljs-string">"Linkedin"</span>, <span class="hljs-attr">url</span>: <span class="hljs-string">"https://www.linkedin.com/in/officalrajdeepsingh/"</span> },
  ],
  <span class="hljs-attr">lang</span>: <span class="hljs-string">"en"</span>,
  <span class="hljs-attr">favicon</span>: <span class="hljs-string">"favicon.ico"</span>,
  <span class="hljs-attr">section</span>: <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Section</span>/&gt;</span></span>,
  theme:<span class="hljs-string">"auto"</span>,
  <span class="hljs-attr">cover</span>:<span class="hljs-string">"assets/logos/backgroundbanner.png"</span>,
  <span class="hljs-attr">ogImage</span>: {
    <span class="hljs-attr">url</span>: <span class="hljs-string">"http://localhost:8000/assets/logos/Frame.png"</span>,
    <span class="hljs-attr">twitterCard</span>:  <span class="hljs-string">"summary_large_image"</span> 
  },
  <span class="hljs-attr">style</span>:<span class="hljs-string">".markdown-body ul, .markdown-body ol { list-style: disc !important;}"</span>
});
</code></pre>
<p>Markdown files support various types of frontMatter. The most common and widely used fontMatter types are:</p>
<ol>
<li>YAML: YAML is identified by opening and closing <code>---</code>.</li>
<li>JSON: JSON is identified by '<code>{</code>' and '<code>}</code>'.</li>
<li>TOML: TOML is identified by opening and closing <code>+++</code>.</li>
</ol>
<p>The most common frontMatter is <a target="_blank" href="https://yaml.org/">YAML</a>. The YAML frontMatter support markdown file is everywhere. But <strong>the Deno blog module only supports yml frontMatter</strong>. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/markdownfile.png" alt="yml front matter example" width="600" height="400" loading="lazy">
<em>yml front matter example</em></p>
<p>The Markdown file is divided into two sections. The first section is the header (frontMatter), and the second is the body section.</p>
<p>The header section contains all metadata for the article. All the metadata is written inside three dashes (<code>---</code>) both opening and closing – for example, post title, tag, description, publish date, and so on. </p>
<p>Finally, in the body section, you write your article body and explain it.</p>
<pre><code class="lang-markdown">// hello-world.md

---
author : "Rajdeep Singh"
publish<span class="hljs-emphasis">_date : "2020-11-10T11:42:46Z"
description : "Easy Ways Add CSS in Next.js #SeriesPart2"
og:image : "assets/images/next.js-add-css-code.jpg"
tags : ["Next.js", "Next", "Next.js Framework", "Next.js Tutorial", "React.js", "react.js tutorial"]
title : "How To Add CSS In Next js?"
allow_</span>iframes: true
cover<span class="hljs-emphasis">_html: <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"assets/images/next.js-add-css-code.jpg"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"How To Add CSS In Next js"</span> /&gt;</span></span>
pathname: "hello-world"
---

First blog post created with the Deno blog package. It is an amazing package you can use to create markdown blogs with Tailwind CSS. 

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">iframe</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"560"</span> <span class="hljs-attr">height</span>=<span class="hljs-string">"315"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://www.youtube-nocookie.com/embed/3NR9Spj0DmQ"</span> <span class="hljs-attr">title</span>=<span class="hljs-string">"YouTube video player"</span> <span class="hljs-attr">frameborder</span>=<span class="hljs-string">"0"</span> <span class="hljs-attr">allow</span>=<span class="hljs-string">"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"</span> <span class="hljs-attr">allowfullscreen</span>&gt;</span></span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">iframe</span>&gt;</span></span>


```javascript
console.log("hello world")</span>
</code></pre>
<pre><code>
The Deno blog <span class="hljs-built_in">module</span> supports the following YML FrontMatter fields <span class="hljs-keyword">in</span> a markdown file:

<span class="hljs-number">1.</span> author (string): The <span class="hljs-string">`author`</span> contains the names <span class="hljs-keyword">of</span> the authors. For example, <span class="hljs-string">`author : "Rajdeep singh , deno"`</span>
<span class="hljs-number">2.</span> publish_date(<span class="hljs-built_in">Date</span>):  The <span class="hljs-string">`publish_date`</span> is required <span class="hljs-keyword">for</span> the article.
<span class="hljs-number">3.</span> description (string): The <span class="hljs-string">`description`</span> is required <span class="hljs-keyword">for</span> the description.
<span class="hljs-number">4.</span> og:image(string): The <span class="hljs-string">`og:image`</span> is not required. It is used <span class="hljs-keyword">for</span> <span class="hljs-string">`&lt;meta property="og:image" content="assets/images/Title-tag-In-HTML-5.jpg"&gt;`</span>
<span class="hljs-number">5.</span> tags(string[]): The <span class="hljs-string">`tags`</span> are just keywords used <span class="hljs-keyword">for</span> SEO. They<span class="hljs-string">'re not compulsory.
6. title(string): The `title` is required for the heading.
7. allow_iframes( boolean ): the `allow_iframes` allows you to use `iframe` HTML.
8. pathname( string ): pathname is not required. For example, `http://yourdomain.com/hello-world` after your domain `hello-world` is your pathname
9. cover_html(string): The `cover_html` contains the HTML for the blog.</span>
</code></pre><p>author : "Rajdeep Singh , Rajvinder singh"
publish_date : "2022-03-20T13:09:24Z"
description : "Npm install command help to install package from npmjs.org"
og:image : "assets/images/npm-init-command-1.png"
tags : ["npm-test", "npm-cli", "npm install command"]
title : "What is the npm install command?"
allow_iframes: true
pathname:"/how-is-npm-install-command"
cover_html: <img src="assets/images/npm-init-command-1.png" alt="npm command" width="600" height="400" loading="lazy"></p>
<pre><code>
These are all the supported fields by YML frontMatter <span class="hljs-keyword">for</span> markdown files:
</code></pre><p>title, author, publish_date, description, og:image, tags, allow_iframes, pathname, cover_html</p>
<pre><code>
This is the required field <span class="hljs-keyword">for</span> markdown files:
</code></pre><p>title
```</p>
<p>Without a title filed, the blog module produces an error <code>Uncaught TypeError: Cannot read properties of undefined (reading 'snippet')</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/undefiend-snippet-error.png" alt="error: Uncaught TypeError: Cannot read properties of undefined (reading 'snippet')" width="600" height="400" loading="lazy">
<em>Error: Uncaught TypeError: Cannot read properties of undefined (reading 'snippet')</em></p>
<h2 id="heading-how-to-deploy-your-blog-with-deno">How to Deploy Your Blog with Deno</h2>
<p>The final step is to deploy our static blog in Deno. Currently, the Deno blog module only supports Deno for deployment. But Deno deploy provides a similar interface to Netlify and Vercel. So you can easily understand the dashboard if you've worked with those tools before.</p>
<p>To deploy a new blog on Deno, you need two things. The first is an account on <a target="_blank" href="https://deno.com/deploy">Deno deploy</a>, and the second is a GitHub account. With a GitHub repository to help manage your articles, it is a straightforward process similar to <a target="_blank" href="https://vercel.com/">Vercel</a> and <a target="_blank" href="https://www.freecodecamp.org/news/p/00c3cfd3-6447-48dc-a915-804b26bf056e/netlify.com">Netlify</a>.</p>
<h3 id="heading-deployment-steps">Deployment steps:</h3>
<p>Here are the steps to deploy your blog with Deno deploy (we'll go through each one in detail below):</p>
<ol>
<li>First, login to your account on Deno deploy</li>
<li>Click to create a new project</li>
<li>Configure the GitHub repository and environment variables</li>
<li>Deploy the static blog</li>
</ol>
<h3 id="heading-login-to-your-account-on-deno-deploy">Login to your account on Deno deploy</h3>
<p>First, go to the <a target="_blank" href="https://deno.com/deploy">Deno deploy</a> website and create a new account if you don't have one already. If you do, then login to your account.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/deno-deploy-dashboard.png" alt="deno deploy website" width="600" height="400" loading="lazy">
<em>deno deploy website</em></p>
<h3 id="heading-click-to-create-a-new-project">Click to create a new project</h3>
<p>After successfully logging in, you can now access the Deno dashboard and click on the "+ <strong>new project</strong>" button.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/create-project-with-deno.png" alt="create a new project with deno deploy" width="600" height="400" loading="lazy">
<em>Create a new project with deno deploy</em></p>
<h3 id="heading-configure-the-github-repository-and-environment-variables">Configure the GitHub repository and environment variables</h3>
<p>After clicking on the <strong>new project</strong> button, you'll be redirected to the project configuration page. Your project page will look like the below. Just fill in all the details:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/fillinfoindeno.png" alt="Fill new project configuration and link github" width="600" height="400" loading="lazy">
<em>Fill out your new project configuration and link to GitHub</em></p>
<p>The first time click the GitHub button. After that, Deno deploys and asks for permission for a GitHub account. After granting all the permissions, your project page looks like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/clicktolinkbuttontodeployblogondeno.png" alt="Image" width="600" height="400" loading="lazy">
<em>After finishing the information</em></p>
<ol>
<li>After opening the project page, you fill in all the required information.</li>
<li>Then, in the second step, select the GitHub repository.</li>
<li>After selecting the GitHub repository, select a branch, then choose  <code>main.tsx</code> file.</li>
<li>Give any project name, but make sure you name is in lowercase letters – for example, my-new-website. Otherwise, you'll get a capital case error.</li>
<li>Click on the environment variable and add an environment (if you have one - otherwise, skip it).</li>
</ol>
<p>And that's it - you've done all the configuration successfully. Now click on the link button.</p>
<h3 id="heading-deployment-is-finished">Deployment is finished</h3>
<p>After deployment is finished, you'll see the website dashboard. Click on the view button to view your production-ready website.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/denowebsitedashborad.png" alt="Your website dashboard with deno looks like after successfully website deployment" width="600" height="400" loading="lazy">
<em>Your website dashboard with deno looks like this after successful website deployment.</em></p>
<p>Here's a tip to help you manage all your markdown files and speed up your written work. The VS Code code editor has a free, open-source <a target="_blank" href="https://frontmatter.codes/">FrontMatter VS Code extension</a>. It's a great tool to manage all your markdown files inside VS Code with the FrontMatter dashboard.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/Screenshot-from-2022-09-13-18-18-32.png" alt="manage markdown file with vscode extenshion" width="600" height="400" loading="lazy">
<em>Manage markdown files with VS Code extension</em></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The Deno blog module is an excellent library for creating a personal blog in five minutes and deploying it with Deno. Deno deployment is speedy. It takes less than ten seconds. </p>
<p>I think the Deno blog module is best for personal use because you do not need to customize many things. You only customize the header, footer, and various sections.</p>
<p>Thank you for reading!</p>
<h3 id="heading-references-to-help-you-setup-your-blog">References to help you setup your blog:</h3>
<ul>
<li><a target="_blank" href="https://deno.land/">https://deno.land/</a></li>
<li><a target="_blank" href="https://deno.com/deploy">https://deno.com/deploy</a></li>
<li><a target="_blank" href="https://deno.land/x/blog@0.5.0">https://deno.land/x/blog</a></li>
<li><a target="_blank" href="https://deno.land/x/dotenv">https://deno.land/x/dotenv</a></li>
<li><a target="_blank" href="https://frontmatter.codes/">https://frontmatter.codes/</a></li>
</ul>
<hr>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Intro to Deno – Guide for Beginners ]]>
                </title>
                <description>
                    <![CDATA[ What is Deno? Deno is a new JavaScript runtime. It was built by Ryan Dahl, the creator of Node.js.  Dahl had a few things that he regretted doing with Node and wanted to build a runtime that could solve those issues. Deno, like Node, is built on the ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/intro-to-deno/</link>
                <guid isPermaLink="false">66bb92e8add24ba427325111</guid>
                
                    <category>
                        <![CDATA[ Deno ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ node ]]>
                    </category>
                
                    <category>
                        <![CDATA[ TypeScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Brian Barrow ]]>
                </dc:creator>
                <pubDate>Fri, 09 Sep 2022 22:50:17 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/09/Screen-Shot-2022-09-07-at-4.09.00-PM.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <h2 id="heading-what-is-deno">What is Deno?</h2>
<p>Deno is a new JavaScript runtime. It was built by Ryan Dahl, the creator of Node.js. </p>
<p>Dahl had a few things that he regretted doing with Node and wanted to build a runtime that could solve those issues. Deno, like Node, is built on the V8 JavaScript engine but was built using Rust instead of C++.</p>
<p>One of the main goals of Deno is to bring server side JavaScript closer to browser JavaScript. </p>
<p>If you've written in both Node and browser JavaScript, then you have surely run into the differences in the APIs used in the respective spaces. Deno aims to have the same APIs on the server that you would use in the browser. We'll take a deeper look at specific examples of this later on.</p>
<h2 id="heading-key-features-of-deno">Key Features of Deno</h2>
<h3 id="heading-deno-uses-typescript">Deno Uses TypeScript</h3>
<p>One of the most eye catching features of Deno is that it treats TypeScript as a first class language out of the box. This means you can run or use TypeScript without installing any other external or third party packages. It just works. </p>
<p>TypeScript is increasingly popular in the JavaScript world, and lots of tools and companies are pushing towards using it. It is cool to see a new progressive technology like TypeScript get more attention, and getting first class status in a big project like Deno is a huge step forward.</p>
<h3 id="heading-deno-is-secure-by-default">Deno is Secure by Default</h3>
<p>Deno by default is secure. This means that unless the script is <em>specifically</em> allowed, it cannot access system files, the environment (things like environment variables), or the network. </p>
<p>In order to specifically allow for access to these features, you need to pass the respective flag in the CLI command. Here are some of the ones you'll use the most:</p>
<ul>
<li><strong>Network access</strong>: <code>--allow-net</code>, you can also specify which URLs the code is allowed to access. For example: <code>--allow-net=https://api.deepgram.com</code></li>
<li><strong>File access</strong>: <code>--allow-read</code></li>
<li><strong>Environment access</strong>: <code>--allow-env</code></li>
</ul>
<h3 id="heading-denos-browser-compatibility">Deno's Browser Compatibility</h3>
<p>Like I mentioned above, Deno strives to have the same API as the browser. The biggest of these in my opinion is the support of the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API">fetch API</a>. </p>
<p>These days, in most of the JavaScript I write, I use the <code>fetch</code> API. Being able to use the same syntax on my server side code makes it a lot easier to be productive and it makes the load of context switching much smaller.</p>
<h2 id="heading-package-manager">Package Manager</h2>
<p>Deno doesn't have a package manager registry. Node uses <code>npm</code> in order to load third party packages into your project, but Deno loads modules via URLs. </p>
<p>I was honestly confused at first by this. Having "grown up" with Node and npm it was weird to me to not have some sort of package manager or <code>package.json</code> file.</p>
<p>Instead of this centralized registry, Deno allows package developers to host their code wherever they want. If the code is hosted on GitHub, you can register your module on their <a target="_blank" href="https://deno.land/x">hosting service</a> where it is cached. That makes it easier for developers to find and use the module.</p>
<h2 id="heading-es-modules">ES Modules</h2>
<p>Deno also uses ES Modules and does not support the <code>require()</code> syntax. Again, most of the JavaScript I write these days uses modern features like this, so it has been nice to not worry about making sure I'm using the correct syntax depending on which environment I'm coding for.</p>
<h2 id="heading-standard-library">Standard Library</h2>
<p>Deno ships with a <a target="_blank" href="https://deno.land/std@0.138.0">standard library</a> that contains functionality that is audited by the Deno team. This makes it really easy to get started using Deno. </p>
<p>There is no need to look to third party packages to do fairly basic things that are needed in server side code. As a developer, it is comforting knowing that the code I use is officially supported and approved by the Deno team.</p>
<h3 id="heading-testing-module">Testing module</h3>
<p>One of the modules included in the standard library is the <a target="_blank" href="https://deno.land/std@0.109.0/testing">testing module</a>. This module makes writing tests easier in Deno and will make them more consistent across projects. </p>
<p>This might not be a plus for everyone, especially if some have strong opinions on testing libraries. I really like it though. As Deno continues to grow, consistency across projects will make maintaining code and switching projects much easier.</p>
<h2 id="heading-deno-vs-node">Deno vs Node</h2>
<p>The biggest question surrounding Deno is how it compares to Node.</p>
<p>Deno clearly offers some advantages over Node. Being secure by default is definitely an attractive feature, and developers will see the out of the box support for TypeScript as a big win.</p>
<p>On the other hand, Node has a very rich community with an established ecosystem and third party packages that make it easier to get up and running. With <a target="_blank" href="https://deno.com/blog/v1.25#experimental-npm-support">the announcement that Deno will support <em>most</em> npm packages</a> I can see people moving over to Deno sooner rather than later.</p>
<p>Deno also recently released <a target="_blank" href="https://deno.com/deploy">Deno Deploy</a> to public beta. This will allow users to rapidly deploy JavaScript code at the edge. This service might give the Deno company an edge (pun intended) over time and grow the user-base.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The experience I've had with Deno over the last several months has been a lot of fun. I've enjoyed working with it and am excited to see what the future brings for it. </p>
<p>Over the next few weeks I'll be writing several posts diving deeper into the Deno world.  </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build React Applications with Deno Using the AlephJS Library ]]>
                </title>
                <description>
                    <![CDATA[ If you're a front end developer who's just getting started with Deno, you might be wondering – can you build something as complex as a NextJS or create-react-app (CRA) application using Deno? I was recently thinking the same thing. I wanted to try De... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-react-app-using-deno-and-alephjs/</link>
                <guid isPermaLink="false">66d45d5d55db48792eed3f05</guid>
                
                    <category>
                        <![CDATA[ Deno ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Akash Joshi ]]>
                </dc:creator>
                <pubDate>Fri, 12 Mar 2021 18:08:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/03/Kapture-2021-03-11-at-11.33.15-4.gif" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you're a front end developer who's just getting started with Deno, you might be wondering – can you build something as complex as a NextJS or create-react-app (CRA) application using Deno?</p>
<p>I was recently thinking the same thing. I wanted to try Deno because of its shareability that results from being able to run an application directly from a URL. The Deno compiler supports running JavaScript and TypeScript files from a URL and it also supports imports from a URL, resulting in extreme portability.</p>
<p>I looked to see if there were any existing solutions online, but I only found <a target="_blank" href="https://dev.to/adriantwarog/react-deno-server-side-rendering-with-deno-ssr-4438">this article</a>, which built an SSR'd React application using some complex techniques. It wasn't simple, like getting started with NextJS or CRA.</p>
<p>So, through my searches online, I ended up at <a target="_blank" href="https://alephjs.org/">AlephJS</a>, which has one of the coolest landing page animations ever.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/Kapture-2021-03-11-at-11.33.15-3.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Aleph is a Zero-Config, Typescript-driven React framework, just like NextJS. The only drawback is that that Aleph is still very much in alpha.</p>
<p>So to get a true Next-like React experience inside Deno, let's get started with AlephJS. It has many of the same conventions as Next, such as:</p>
<ul>
<li><p>A <code>/pages</code> directory for creating URL routes</p>
</li>
<li><p>Direct <code>.js, .jsx, .ts, .tsx</code> support in pages</p>
</li>
<li><p>A <code>/public</code> directory for serving static assets like video, audio, or image files</p>
</li>
<li><p>A <code>/pages/api</code> folder for serving JavaScript or TypeScript files as serverless APIs.</p>
</li>
</ul>
<p>If you want to watch a video about how to do this to supplement your reading, check it out here:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/SDTedmFhnQc" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<h2 id="heading-how-to-get-started-with-alephjs">How to Get Started with AlephJS</h2>
<p>To be able to use AlephJS, you need Deno installed on your machine. You can see how to install and get started with Deno in my <a target="_blank" href="https://www.freecodecamp.org/news/build-a-url-shortener-in-deno/">previous article here</a>.</p>
<p>To get started with Aleph, you need to first install the Aleph CLI by running this command:</p>
<pre><code class="lang-bash">deno install -A -f -n aleph https://deno.land/x/aleph@v0.3.0-alpha.1/cli.ts
</code></pre>
<p>After installation, you can run <code>aleph -h</code> to check whether it got installed correctly.</p>
<p>Because of the portability of Deno, you can replace <code>aleph</code> with <code>deno run -A https://deno.land/x/aleph@v0.3.0-alpha.1/cli.ts start $app_URI</code> for any command and it will be able to run the Aleph program without having the CLI locally installed.</p>
<p>To create a starter app, run:</p>
<pre><code class="lang-bash">aleph init hello
<span class="hljs-built_in">cd</span> hello
</code></pre>
<p>And start the app in development mode using <code>aleph dev</code> to start a server at port <code>8080</code>.</p>
<p>To start the app in production mode, you have to first <code>build</code> the app and then run the built app. You can do this through these commands:</p>
<pre><code class="lang-bash">aleph build <span class="hljs-comment"># build your app</span>
aleph start <span class="hljs-comment"># runs built app</span>
</code></pre>
<p>After you initialise your Aleph app, you will find that the root component is defined at <code>pages/index.tsx</code>. It's a normal React component. You can experiment with it to see how Aleph works.</p>
<p>You can add more routes to your application by creating more <code>.jsx</code> or <code>.tsx</code> files inside the <code>pages</code> folder. You can read more on routing in Aleph <a target="_blank" href="https://alephjs.org/docs/basic-features/routing">here</a>.</p>
<h2 id="heading-how-to-import-libraries-in-deno">How to Import Libraries in Deno</h2>
<p>I've written about Deno previously on <a target="_blank" href="https://www.freecodecamp.org/news/build-a-url-shortener-in-deno/">freeCodeCamp</a> where I demoed some Deno basics, including URL imports. Since Aleph is a Deno framework, all imports happen in the "Deno way".</p>
<p>There are two kinds of libraries which you can import in a Deno application.</p>
<ol>
<li><p>Importing Deno-Native Libraries: These libraries were either built for Deno, or ported over from npm to support Deno usage.</p>
</li>
<li><p>Importing from NPM: if you've worked with JS recently you probably know about npm. If you don't, npm (the company behind node package manager) is the standard repository for all JavaScript libraries. Luckily, Deno has limited support for npm libraries. Using tools like <a target="_blank" href="http://esm.sh">esm.sh</a> or skypack.dev, users can import npm libraries into Deno.</p>
</li>
</ol>
<h3 id="heading-1-how-to-import-deno-native-libraries">1. How to Import Deno-Native Libraries</h3>
<p>You can import Deno-Native libraries in your application by importing their URLs directly. You can find a list of Deno libraries here: <a target="_blank" href="http://deno.land/x">deno.land/x</a></p>
<p>To test this out, let’s import this <a target="_blank" href="https://deno.land/std@0.88.0/datetime">standard Deno date formatting library</a>, and call a date format function in a React page. Create a file <code>date-import.tsx</code> in the <code>pages</code> folder of your app. Inside the file, write the following code:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// react is a compulsoy import in Aleph</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-comment">// import the format function from its URL</span>
<span class="hljs-keyword">import</span> { format } <span class="hljs-keyword">from</span> <span class="hljs-string">"https://deno.land/std@0.88.0/datetime/mod.ts"</span>;

<span class="hljs-comment">// capitalize the function name so it's recognized as a React component</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">DateImport</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-comment">// Here, directly calling the format function works as expected.</span>
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">section</span>&gt;</span>Hello all! Today is: {format(new Date(), "dd-MM-yyyy")}<span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span></span>;
}
</code></pre>
<p>To see the output of this file, go to <a target="_blank" href="http://localhost:8080/date-import">localhost:8080/date-import</a>, or its equivalent for your server. You should see the page displaying today's date.</p>
<h3 id="heading-2-how-to-import-libraries-from-npm">2. How to Import Libraries from NPM</h3>
<p>To import an npm library, you can also import directly from a URL – but in this case there's a slight change. Since we talked about <a target="_blank" href="http://esm.sh">esm.sh</a> and skypack.dev, let's try to use them in action. In this case, let's try to use the <a target="_blank" href="https://www.npmjs.com/package/dayjs">dayjs</a> library in our project.</p>
<blockquote>
<p>Note: Not all npm libraries work correctly in Deno because they may be relying on Node-specific functions.</p>
</blockquote>
<p>To import a library in <a target="_blank" href="http://esm.sh">esm.sh</a>, you post-pend the library's package name to the URL. In this case to import dayjs, we would be importing <a target="_blank" href="https://esm.sh/dayjs"><code>https://esm.sh/dayjs</code></a>. This also works for any CSS files you might want to import from a library.</p>
<p>Now, let's create a file in <code>pages</code> called <code>dayjs-import.tsx</code>. So, the code in our page will look like this:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// react is a compulsoy import in Aleph</span>
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-comment">// import the dayjs npm library using esm.sh</span>
<span class="hljs-keyword">import</span> dayjs <span class="hljs-keyword">from</span> <span class="hljs-string">"https://esm.sh/dayjs"</span>;

<span class="hljs-comment">// capitalize the function name so it's recognized as a React component</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">DateImport</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-comment">// call the dayjs function directly to display today's date</span>
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">section</span>&gt;</span>Hello all! Today is: {dayjs().format("DD-MM-YYYY")}<span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span></span>;
}
</code></pre>
<p>To see the output of this file, go to <a target="_blank" href="http://localhost:8080/dayjs-import">localhost:8080/dayjs-import</a>, or its equivalent for your server. You should see the page displaying the day's date.</p>
<p>There's one important thing before we go ahead, though – how do you handle <strong>React imports</strong> like importing <code>useState</code>, <code>useEffect</code>, and so on? Luckily, the devs at Aleph have already written an example for us.</p>
<p>Go into <code>./lib/useCounter.ts</code> and you'll find the code for the custom hook that's used for the counter in the home page.</p>
<p>Since I want to focus on Aleph and React themselves in this article, to check out all the different ways you can import a CSS file in Aleph, visit <a target="_blank" href="https://alephjs.org/docs/basic-features/built-in-css-support">this page from the official documentation</a>.</p>
<h2 id="heading-how-to-build-a-sample-app-with-deno-and-alephjs">How to Build a Sample App with Deno and AlephJS</h2>
<p>Now, let's get into the nitty gritty and try to build a React app in Aleph ourselves. We're going to be building "Is It Down?", a sample app I had made using an existing website-checking API. This app will allow us to check whether a website is currently up or down.</p>
<p>Here's the CodeSandbox link: <a target="_blank" href="https://codesandbox.io/s/awesome-firefly-5dofg">https://codesandbox.io/s/awesome-firefly-5dofg</a></p>
<div class="embed-wrapper">
        <iframe width="100%" height="350" src="https://codesandbox.io/embed/awesome-firefly-5dofg?fontsize=14&amp;hidenavigation=1&amp;theme=dark&amp;view=preview" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="CodeSandbox embed" allow="geolocation; microphone; camera; midi; vr; accelerometer; gyroscope; payment; ambient-light-sensor; encrypted-media; usb" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin" loading="lazy"></iframe></div>
<p> </p>
<p>Building this application will show you how to use the State hook, the Effect hook, and how to make API calls in Aleph.</p>
<p>Create a new file called <code>web-checker.tsx</code> in your <code>pages</code> folder. Let's start by just adding the UI elements first. We'll display an <code>h1</code> element with the title, an <code>h2</code> element linking to the API, and a form element to take user input. This is a non-interactive page that just displays the elements.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">fontFamily:</span> "<span class="hljs-attr">sans-serif</span>", <span class="hljs-attr">textAlign:</span> "<span class="hljs-attr">center</span>" }}&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Is it Down?<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>
        Go{" "}
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span>
          <span class="hljs-attr">href</span>=<span class="hljs-string">"https://rapidapi.com/jakash1997/api/website-data-gathering-and-update-tracking"</span>
          <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>
        &gt;</span>
          here
        <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>{" "}
        to get an API key
      <span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">form</span>
        <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{(e)</span> =&gt;</span> {
          e.preventDefault();
        }}
      &gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
          <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
        /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Submit<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Next, to capture the state of the input field, and also to capture the response of the API call we will have to make, let's introduce state.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// import useState from react</span>
<span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// define both state variables</span>
  <span class="hljs-keyword">const</span> [siteURL, setUrl] = useState(<span class="hljs-string">""</span>);
  <span class="hljs-keyword">const</span> [response, setResponse] = useState(<span class="hljs-literal">undefined</span>);
...
</code></pre>
<p>Now, we'll use this state inside our input element so it can react to it.</p>
<pre><code class="lang-jsx">...
&lt;input
  value={siteURL}
  onChange={<span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> setUrl(e.target.value)}
  type=<span class="hljs-string">"text"</span>
/&gt;
...
</code></pre>
<p>We'll also add some code to display a response when it's returned from the API response:</p>
<pre><code class="lang-jsx">...
    &lt;/form&gt;

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

    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">code</span>&gt;</span>{JSON.stringify(response, null, 2)}<span class="hljs-tag">&lt;/<span class="hljs-name">code</span>&gt;</span></span>
&lt;/div&gt;
...
</code></pre>
<p>Now, to get started with integrating the API, let's try to form the request correctly. In this case, the API is a simple <code>GET</code> call, so we only need to pass a param and an API key.</p>
<p>Firstly, go here, and generate an API key: <a target="_blank" href="https://rapidapi.com/jakash1997/api/website-data-gathering-and-update-tracking">https://rapidapi.com/jakash1997/api/website-data-gathering-and-update-tracking</a>. Find the API key like you see in the screenshot below, and keep it somewhere safe:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/Screenshot_2021-03-08_at_3.47.01_PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Next, let's create a separate function <code>submitData</code> which will generate the required request data. We will be using the <code>axios</code> library to make our <code>GET</code> call, so we will be forming its options object.</p>
<pre><code class="lang-jsx">...
const [response, setResponse] = useState(<span class="hljs-literal">undefined</span>);

<span class="hljs-keyword">const</span> submitData = <span class="hljs-function">(<span class="hljs-params">siteURL</span>) =&gt;</span> {
  setResponse(<span class="hljs-string">"Loading..."</span>);
  <span class="hljs-keyword">const</span> options = {
        <span class="hljs-comment">// passing siteURL here through object shorthand</span>
    <span class="hljs-attr">params</span>: { siteURL },

        <span class="hljs-comment">// passing the required headers here</span>
    <span class="hljs-attr">headers</span>: {
      <span class="hljs-string">"x-rapidapi-key"</span>: <span class="hljs-string">"YOUR_API_KEY"</span>,
      <span class="hljs-string">"x-rapidapi-host"</span>:
        <span class="hljs-string">"website-data-gathering-and-update-tracking.p.rapidapi.com"</span>,
    },
  };

    <span class="hljs-comment">// print options here</span>
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"options"</span>, options);
};

<span class="hljs-keyword">return</span> (
...
</code></pre>
<p>And we add this to the <code>onSubmit</code> function in our form.</p>
<pre><code class="lang-jsx">onSubmit={<span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
  e.preventDefault();
  submitData(siteURL);
}}
</code></pre>
<p>Now, whenever you press the Submit button, you will see the <code>options</code> we generated in the console. If you see the <code>options</code> object in the console, you're doing well so far!</p>
<p>Next we just have the simple step of importing the <code>axios</code> library using <a target="_blank" href="http://esm.sh"><code>http://esm.sh</code></a> and using it to make an API call.</p>
<p>Import <code>axios</code> after the <code>react</code> import like this:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">"https://esm.sh/axios"</span>;

...
</code></pre>
<p>And use it in the <code>submitData</code> function as:</p>
<pre><code class="lang-jsx">...
    axios
    .get(
      <span class="hljs-string">"https://website-data-gathering-and-update-tracking.p.rapidapi.com/sitecheck"</span>,
      options
    )
    .then(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">response</span>) </span>{
      setResponse(response.data);
      <span class="hljs-built_in">console</span>.log(response.data);
    })
    .catch(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">error</span>) </span>{
      <span class="hljs-built_in">console</span>.error(error);
    });
};
...
</code></pre>
<p>And that's it! Try submitting the form again, and this time you'll see the result both on screen and in the console.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Now you know the basics of Aleph. It's a really interesting tool which allows you to mix your existing React knowledge with the forward-looking nature and security of <a target="_blank" href="http://deno.land">deno.land</a>.</p>
<p>If you liked this tutorial, you can follow me on Twitter <a target="_blank" href="http://twitter.com/thewritingdev">@thewritingdev</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a URL Shortener in Deno ]]>
                </title>
                <description>
                    <![CDATA[ In this article, we’re going to learn the basics of Deno, like how to run a program and embrace security. Deno is the new JavaScript and TypeScript runtime written in Rust. It offers tight security, TypeScript support out-of-the-box, a single executa... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-a-url-shortener-in-deno/</link>
                <guid isPermaLink="false">66d45d5b246e57ac83a2c6f9</guid>
                
                    <category>
                        <![CDATA[ Deno ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ TypeScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Akash Joshi ]]>
                </dc:creator>
                <pubDate>Wed, 07 Oct 2020 15:40:28 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9c9848740569d1a4ca192c.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, we’re going to learn the basics of Deno, like how to run a program and embrace security.</p>
<p>Deno is the new JavaScript and TypeScript runtime written in Rust. It offers tight security, TypeScript support out-of-the-box, a single executable to run it, and a set of reviewed and audited standard modules.</p>
<p>Like <a target="_blank" href="https://npmjs.com">npm</a> in Node.js, packages in Deno are managed in a centralized package repository called <a target="_blank" href="https://deno.land/x/">X</a>. We'll be using one of these libraries, Oak, to build a REST API-based server in Deno.</p>
<p>After learning the basics by using the Express-like router package <a target="_blank" href="https://deno.land/x/oak@v6.3.0">Oak</a>, we will jump into the deep end of Deno and build a complete application.</p>
<p>Here's what we will set up in this application:</p>
<ol>
<li><p>Mapping URL shortcodes to endpoints using a JSON-based config file.</p>
</li>
<li><p>Have expiration dates attached to each URL so that these redirects are only valid for a limited period of time.</p>
</li>
</ol>
<h2 id="heading-0-prerequisites">0. Prerequisites</h2>
<ol>
<li><p>Install Deno from <a target="_blank" href="https://deno.land/#installation">this link</a>.</p>
</li>
<li><p>Make sure you know the basics of JavaScript.</p>
</li>
</ol>
<p>Although not really required to follow along with this article, you can check out the YouTube video below to get an intro to Deno in video-format.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/VQ8Jb7GLHgk" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<p>So, let’s get started. ?</p>
<h2 id="heading-1-how-to-build-the-router">1. How to Build the Router</h2>
<p>To write the server-side code for our application, we'll use the Oak module. It has an Express-like syntax for defining API routes.</p>
<p>If we look at its <a target="_blank" href="https://deno.land/x/oak">documentation here</a>, the "<a target="_blank" href="https://deno.land/x/oak#basic-usage">Basic Usage</a>" section pretty much covers all the use cases we will need in our router. So, we will expand on that code to build our application.</p>
<p>To test this code, you can create a file called <code>index.ts</code> in a folder, and copy the "Basic Usage" code into it.</p>
<p>To understand how to run TypeScript or JavaScript files in Deno, you first need to understand how Deno runs files.</p>
<p>You run a file by running the command <code>deno run file_name.ts</code> or <code>file_name.js</code>, followed by a set of flags providing certain system permissions to your application.</p>
<p>To test this, run the file we just created, containing the "Basic Usage" code, by using the command <code>deno run index.ts</code>.</p>
<p>You will see that Deno complains that you haven't given network access to your application. So, to do that, you add the <code>-allow-net</code> to the run command. The command will look like <code>deno run index.ts -allow-net</code>.</p>
<p>The router written down in the "Basic Usage” code looks like this:</p>
<pre><code class="lang-jsx">router
  .get(<span class="hljs-string">"/"</span>, <span class="hljs-function">(<span class="hljs-params">context</span>) =&gt;</span> {
    context.response.body = <span class="hljs-string">"Hello world!"</span>;
  })
  .get(<span class="hljs-string">"/book"</span>, <span class="hljs-function">(<span class="hljs-params">context</span>) =&gt;</span> {
    context.response.body = <span class="hljs-built_in">Array</span>.from(books.values());
  })
  .get(<span class="hljs-string">"/book/:id"</span>, <span class="hljs-function">(<span class="hljs-params">context</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (context.params &amp;&amp; context.params.id &amp;&amp; books.has(context.params.id)) {
      context.response.body = books.get(context.params.id);
    }
  });
</code></pre>
<p>To break down the above code, first a <code>router</code> object has been defined. Then the <code>get</code> function is called on the router, to define the various endpoints for our application. The respective logic is defined inside the callback functions.</p>
<p>For example, for the "/" endpoint, a callback function which returns "Hello World" in the response body has been defined. We can keep this endpoint unchanged to test whether our application server is running by receiving this response.</p>
<p>We don’t need the “/book” URL which has been defined, so its definition can be safely removed. At this point, your router should have the below structure:</p>
<pre><code class="lang-javascript">router
  .get(<span class="hljs-string">"/"</span>, <span class="hljs-function">(<span class="hljs-params">context</span>) =&gt;</span> {
    context.response.body = <span class="hljs-string">"Hello world!"</span>;
  })
  .get(<span class="hljs-string">"/book/:id"</span>, <span class="hljs-function">(<span class="hljs-params">context</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (context.params &amp;&amp; context.params.id &amp;&amp; books.has(context.params.id)) {
      context.response.body = books.get(context.params.id);
    }
  });
</code></pre>
<p>In the next section, we'll be focussing on starting to build the actual application.</p>
<h2 id="heading-2-how-to-build-the-url-shortener">2. How to Build the URL Shortener</h2>
<p>Now let's get started with building the actual URL shortener.</p>
<p>It should redirect to a destination (<code>dest</code>), based on a <code>shortcode</code>. The redirect should also only be valid up to an <code>expiryDate</code>, which can be provided in the Year-Month-Day format.</p>
<p>Based on these assumptions, let's create the config file, named <code>urls.json</code>. The format of the file will be:</p>
<pre><code class="lang-jsx">{
  <span class="hljs-string">"shortcode"</span>: {
    <span class="hljs-string">"dest"</span>: <span class="hljs-string">"destination_url_string"</span>,
    <span class="hljs-string">"expiryDate"</span>: <span class="hljs-string">"YYYY-MM-DD"</span>
  }
}
</code></pre>
<p>You can <a target="_blank" href="https://github.com/akash-joshi/deno-url-shortener/blob/master/urls.json">check out the JSON file here</a>.</p>
<p>To read this JSON file in your code, add the following to the top of your <code>index.ts</code>:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { Application, Router } <span class="hljs-keyword">from</span> <span class="hljs-string">"&lt;https://deno.land/x/oak/mod.ts&gt;"</span>;

<span class="hljs-keyword">const</span> urls = <span class="hljs-built_in">JSON</span>.parse(Deno.readTextFileSync(<span class="hljs-string">"./urls.json"</span>));

<span class="hljs-built_in">console</span>.log(urls);
</code></pre>
<p>Now, to run your <code>index.ts</code>, you will need another flag <code>—allow-read</code>, otherwise Deno will throw a "read permissions not provided" error. Your final command becomes <code>deno run —allow-net —allow-read index.ts</code>.</p>
<p>After running this command, you'll see the JSON file being printed in your terminal window. This means that your program is able to read the JSON file correctly.</p>
<p>If we go back to the "Basic Usage" example that we saw above, the route “/book/:id” is exactly what we need.</p>
<p>Instead of "/book/:id", we can use "/shrt/:urlid", where we will get the individual URLs based on the URL ID (<code>:urlid</code>).</p>
<p>Replace the existing code present inside the "/book/:id" route with this:</p>
<pre><code class="lang-jsx">.get(<span class="hljs-string">"/shrt/:urlid"</span>, <span class="hljs-function">(<span class="hljs-params">context</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (context.params &amp;&amp; context.params.urlid &amp;&amp; urls[context.params.urlid]) {
      context.response.redirect(urls[context.params.urlid].dest);
    } <span class="hljs-keyword">else</span> {
      context.response.body = <span class="hljs-string">"404"</span>;
    }
  });
</code></pre>
<p>The <code>if</code> condition in the route does the following:</p>
<ol>
<li><p>Checks if parameters are attached to the route</p>
</li>
<li><p>Checks if the parameter <code>urlid</code> is in the parameter list.</p>
</li>
<li><p>Checks whether the <code>urlid</code> matches with any URL in our JSON.</p>
</li>
</ol>
<p>If it matches with all these, the user is redirected to the correct URL. If it doesn't, a 404 response on the body is returned.</p>
<p>To test this, copy this route into <code>index.ts</code>. The router will now look like this:</p>
<pre><code class="lang-jsx">router
  .get(<span class="hljs-string">"/"</span>, <span class="hljs-function">(<span class="hljs-params">context</span>) =&gt;</span> {
    context.response.body = <span class="hljs-string">"Hello world!"</span>;
  })
    .get(<span class="hljs-string">"/shrt/:urlid"</span>, <span class="hljs-function">(<span class="hljs-params">context</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (context.params &amp;&amp; context.params.urlid &amp;&amp; urls[context.params.urlid]) {
          context.response.redirect(urls[context.params.urlid].dest);
        } <span class="hljs-keyword">else</span> {
          context.response.body = <span class="hljs-string">"404"</span>;
        }
      });
</code></pre>
<p>And run the file using <code>deno run —allow-net —allow-read index.ts</code>.</p>
<p>If you copied the JSON file from the example, and if you go to <code>http://localhost:8000/shrt/g</code>, you'll be redirected to Google's homepage.</p>
<p>On the other hand, if you use a random shortcode that doesn't work in our URL's config, it brings you to the 404 page.</p>
<p>However, you'll see that our shortener doesn't react live to changes in the JSON file. To test this, try adding a new redirect to <code>urls.json</code> in the same format as:</p>
<pre><code class="lang-javascript"><span class="hljs-string">"shortcode"</span>: {
    <span class="hljs-string">"dest"</span>: <span class="hljs-string">"destination_url_string"</span>,
    <span class="hljs-string">"expiryDate"</span>: <span class="hljs-string">"YYYY-MM-DD"</span>
  }
</code></pre>
<p>The reason for this is that <code>urls.json</code> is only read once at that start. So, now we will add live-reloading to our server.</p>
<h2 id="heading-3-how-to-add-live-reloading">3. How to Add Live-Reloading</h2>
<p>To make the <code>urls</code> object react live to changes in the JSON file, we simply move the read statement inside our route. This should look like the following:</p>
<pre><code class="lang-jsx">.get(<span class="hljs-string">"/shrt/:urlid"</span>, <span class="hljs-function">(<span class="hljs-params">context</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> urls = <span class="hljs-built_in">JSON</span>.parse(Deno.readTextFileSync(<span class="hljs-string">"./urls.json"</span>));

  <span class="hljs-keyword">if</span> (context.params &amp;&amp; context.params.urlid &amp;&amp; urls[context.params.urlid]) {
    context.response.redirect(urls[context.params.urlid].dest);
  } <span class="hljs-keyword">else</span> {
    context.response.body = <span class="hljs-string">"404"</span>;
  }
});
</code></pre>
<p>Note how we have moved the URLs object inside our router. Now in this case, the config file is read every time that route is called, so it can react live to any changes made in the <code>urls.json</code> file. So even if we add or remove other redirects on the fly, our code reacts to it.</p>
<h2 id="heading-4-how-to-add-an-expiration-to-the-urls">4. How to Add an Expiration to the URLs</h2>
<p>To make our URLs expire at a certain date, we will be using the popular Moment.js library, which makes it easy to work with dates.</p>
<p>Luckily, it has also been <a target="_blank" href="https://deno.land/x/moment">ported for Deno</a>. To understand how it works, check out its documentation in the previous link.</p>
<p>To use it in our code, import it directly through its URL like this:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { Application, Router } <span class="hljs-keyword">from</span> <span class="hljs-string">"&lt;https://deno.land/x/oak/mod.ts&gt;"</span>;
<span class="hljs-keyword">import</span> { moment } <span class="hljs-keyword">from</span> <span class="hljs-string">"&lt;https://deno.land/x/moment/moment.ts&gt;"</span>;

<span class="hljs-keyword">const</span> router = <span class="hljs-keyword">new</span> Router();
</code></pre>
<p>To check the date for when the URL will expire, we check the <code>expiryDate</code> key on our <code>urls</code> object. This will make the code look like this:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">if</span> (context.params &amp;&amp; context.params.urlid &amp;&amp; urls[context.params.urlid]) {
  <span class="hljs-keyword">if</span> (
    urls[context.params.urlid].expiryDate &gt; moment().format(<span class="hljs-string">"YYYY-MM-DD"</span>)
  ) {
    context.response.redirect(urls[context.params.urlid].dest);
  } <span class="hljs-keyword">else</span> {
    context.response.body = <span class="hljs-string">"Link Expired"</span>;
  }
} <span class="hljs-keyword">else</span> {
  context.response.body = <span class="hljs-string">"404"</span>;
}
</code></pre>
<p>In <code>moment().format("YYYY-MM-DD")</code>, we get the current date and time using <code>moment()</code>. We can convert it to the "YYYY-MM-DD" (Year-Month-Date) format using the function <code>.format("YYYY-MM-DD")</code>.</p>
<p>By comparing it against our <code>expiryDate</code> key, we can check whether the URL has expired or not.</p>
<p>That's it! You have built a fully functional URL shortener in Deno. You can find the final code <a target="_blank" href="https://github.com/akash-joshi/deno-url-shortener">in the GitHub repo here</a>.</p>
<p>Test it out by setting <code>expiryDate</code> as the current date and by making other changes to <code>urls.json</code> and our code.</p>
<h3 id="heading-my-thoughts-on-deno">My Thoughts on Deno</h3>
<p>To wrap the article up, I'll put my forward final thoughts on deno.land.</p>
<p>While it's refreshing to see a server-side language which takes security into consideration and supports TypeScript out-of-the-box, Deno still has a long way to go before being ready for use in production systems.</p>
<p>For example, the TypeScript compilation is still very slow, with compilation times ~20 seconds, even for simple programs like the one we just developed.</p>
<p>On the error-reporting front, it still is pretty bad with describing the errors. For example, while embedding the code to read <code>urls.json</code> in the function itself, Deno isn't able to report that the <code>-allow-read</code> flag hasn't been set. Instead, it just throws an internal server error without a proper error printed on the terminal.</p>
<h3 id="heading-what-next">What Next?</h3>
<p>You can improve your Deno or Typescript skills by building more complex applications like a <a target="_blank" href="https://css-tricks.com/build-a-chat-app-using-react-hooks-in-100-lines-of-code/">Chatting Application</a> or a <a target="_blank" href="https://auth0.com/blog/building-a-wikipedia-app-using-react-hooks-and-auth0/">Wikipedia Clone</a>.</p>
<p>You can also go through the Deno documentation at <a target="_blank" href="http://deno.land/">deno.land</a> to get more familiar with the basics.</p>
<p>Thank you for reading this far and happy programming ? !!</p>
<h3 id="heading-important-links">Important Links</h3>
<p>Deno - https://deno.land<br>Deno X (package repository) - https://deno.land/x/<br>Oak (REST framework) - <a target="_blank" href="https://deno.land/x/oak">https://deno.land/x/oak</a><br>Oak Basic Usage - <a target="_blank" href="https://deno.land/x/oak@v6.3.1#basic-usage">https://deno.land/x/oak@v6.3.1#basic-usage</a><br>Final GitHub Repo - <a target="_blank" href="https://github.com/akash-joshi/deno-url-shortener">https://github.com/akash-joshi/deno-url-shortener</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn Deno, a Node.js alternative ]]>
                </title>
                <description>
                    <![CDATA[ Deno is a Node.js  alternative created by Ryan Dahl, the same person who created Node.js. Many people, including Ryan Dahl, think that Deno is superiod to Node.js. We've posted a 6-hour video course all about Deno on the freeCodeCamp.org YouTube chan... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-deno-a-node-js-alternative/</link>
                <guid isPermaLink="false">66b2043439b555ffda8bfe9b</guid>
                
                    <category>
                        <![CDATA[ Deno ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Tue, 30 Jun 2020 17:08:13 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/09/deno.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Deno is a Node.js  alternative created by Ryan Dahl, the same person who created Node.js.</p>
<p>Many people, including Ryan Dahl, think that Deno is superiod to Node.js. We've posted a 6-hour video course all about Deno on the freeCodeCamp.org YouTube channel. Decide for yourself if it is better than Node.</p>
<p>You will learn the basics of Deno in the course. Deno can be used with JavaScript or TypeScript, but it is more common to use TypeScript. This course includes a mini crash-course on TypeScript.</p>
<p>This course was created by The Codeholic. By the end of the course, you will have used Deno to build a survey app with a REST API using MongoDB. Then you will be ready to start implementing your own applications based on Deno.</p>
<p>Here are the things covered in the course:</p>
<ul>
<li>What is Deno?</li>
<li>How to install</li>
<li>"Hello World" in Deno</li>
<li>Deno commands</li>
<li>TypeScript basics</li>
<li>Main Demo features</li>
<li>Deno standard library</li>
<li>Third party libraries</li>
<li>Working with the file system</li>
<li>Create a basic HTTP server</li>
<li>Using npm packages</li>
<li>Building a real-world project</li>
<li>Deno best practices</li>
</ul>
<p>Watch the <a target="_blank" href="https://www.youtube.com/watch?v=TQUy8ENesGY">full course on the freeCodeCamp.org YouTube channel</a> (6 hour watch).</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use MySQL With Deno and Oak ]]>
                </title>
                <description>
                    <![CDATA[ By Adeel Imran I recently wrote about how to make a Todo API in Deno + Oak (without using a database). You can find the repo under chapter_1:oak on GitHub.  This tutorial picks up where the other left off, and I'll go over how to integrate MySQL into... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-mysql-in-deno-oak/</link>
                <guid isPermaLink="false">66d45d6f2472e5ed2fa07baf</guid>
                
                    <category>
                        <![CDATA[ Deno ]]>
                    </category>
                
                    <category>
                        <![CDATA[ MySQL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Tutorial ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Sun, 07 Jun 2020 16:40:17 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9c9a78740569d1a4ca25d2.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Adeel Imran</p>
<p>I recently wrote about how to make a <strong><a target="_blank" href="https://www.freecodecamp.org/news/create-a-todo-api-in-deno-written-by-a-guy-coming-from-node/">Todo API in Deno + Oak (without using a database)</a></strong>. You can find the repo under <strong><a target="_blank" href="https://github.com/adeelibr/deno-playground/tree/master/chapter_1:oak">chapter_1:oak</a></strong> on GitHub. </p>
<p>This tutorial picks up where the other left off, and I'll go over how to integrate MySQL into a Deno and Oak project.</p>
<p>If at any time you want to see the entire source code used in this tutorial, it's available at <a target="_blank" href="https://github.com/adeelibr/deno-playground/tree/master/chapter_2:mysql"><strong>chapter_2:mysql</strong></a>. Feel free to give it a star on GitHub if you like it.</p>
<p>I'm assuming that you already completed the last tutorial mentioned above. If not, check it out <a target="_blank" href="https://www.freecodecamp.org/news/create-a-todo-api-in-deno-written-by-a-guy-coming-from-node/">here</a> and come back when you're finished.</p>
<p>Before we start, make sure that you have a MySQL client installed and running:</p>
<ul>
<li>MySQL community server [<a target="_blank" href="https://dev.mysql.com/downloads/mysql/">Download here</a>]</li>
<li>MySQL Workbench [<a target="_blank" href="https://dev.mysql.com/downloads/workbench/">Download here</a>]</li>
</ul>
<p>I wrote a small guide for Mac OS users on setting up MySQL because I struggled with it as well. Check it out <a target="_blank" href="https://github.com/adeelibr/deno-playground/blob/master/guidelines/setting-up-mysql-mac-os-catalina.md">here</a>.</p>
<p>If you are on a Windows machine you can use the same tools or you can also use <a target="_blank" href="https://www.apachefriends.org/index.html">XAMPP</a> to have a MySQL instance running in your dashboard.</p>
<p>Once you have a MySQL instance running we can begin our tutorial.</p>
<h2 id="heading-lets-begin">Let's Begin</h2>
<p>Assuming that you're coming from this article, <a target="_blank" href="https://www.freecodecamp.org/news/create-a-todo-api-in-deno-written-by-a-guy-coming-from-node/"><strong>Todo API in Deno + Oak (without using a database)</strong></a>, we will do the following:</p>
<ul>
<li>Create a MySQL database connection</li>
<li>Write a small script that resets the database every time we start our Deno server</li>
<li>Perform CRUD operations on a table</li>
<li>Add the CRUD functionality to our API controllers</li>
</ul>
<p>One last thing – here is the entire commit difference that was made in Chapter 1 to add MySQL to the project (<a target="_blank" href="https://github.com/adeelibr/deno-playground/pull/1/commits/5b63b51ebcadededcfec452fe6877a0bd0f1f83f">source code that shows the new additions made from chapter 1</a>).</p>
<p>In your project root folder – mine is called _<code>chapter_2:mysql</code>,_ though yours can be called whatever you want – create a folder called <strong>db</strong>. Inside that folder, create a file called <strong>config.ts and</strong> add the following content to it:</p>
<pre><code class="lang-db/config.ts">export const DATABASE: string = "deno";
export const TABLE = {
  TODO: "todo",
};
</code></pre>
<p>Nothing fancy here, just defining our database name along with an object for tables and then exporting it. Our project will have one database called "deno" and inside that db we will only have one table called "todo".</p>
<p>Next, inside the <strong>db</strong> folder, create another file called <strong>client.ts</strong> and add the following content:</p>
<pre><code class="lang-db/client.ts">import { Client } from "https://deno.land/x/mysql/mod.ts";
// config
import { DATABASE, TABLE } from "./config.ts";

const client = await new Client();

client.connect({
  hostname: "127.0.0.1",
  username: "root",
  password: "",
  db: "",
});

export default client;
</code></pre>
<p>A couple of things are happening here. </p>
<p>We are importing <code>Client</code> from the <code>mysql</code> library. <code>Client</code> will help us connect to our database and perform operations in the database.</p>
<pre><code class="lang-db/client.ts">client.connect({
  hostname: "127.0.0.1",
  username: "root",
  password: "",
  db: "",
});
</code></pre>
<p><code>Client</code> provides a method called <code>connect</code> which takes in object where we can provide the <code>hostname</code>, <code>username</code>, <code>password</code>, and <code>db</code>. With this information it can establish a connection to our MySQL instance.</p>
<p>Make sure that your <code>username</code> has no <code>password</code>, as it will conflict with connecting to Deno's MySQL library. If you don't know on how to do that, <a target="_blank" href="https://github.com/adeelibr/deno-playground/blob/master/guidelines/setting-up-mysql-mac-os-catalina.md#set-your-mysql-password-to-empty">read this tutorial</a> I wrote.</p>
<p>I have left the <code>database</code> field blank here because I want to select it manually later in my script.</p>
<p>Let's add a script that will initialize a database called "deno", select it, and inside that db create a table called "todo".</p>
<p>Inside <code>db/client.ts</code> file let's make some new additions:</p>
<pre><code class="lang-db/client.ts">import { Client } from "https://deno.land/x/mysql/mod.ts";
// config
import { DATABASE, TABLE } from "./config.ts";

const client = await new Client();

client.connect({
  hostname: "127.0.0.1",
  username: "root",
  password: "",
  db: "",
});

const run = async () =&gt; {
  // create database (if not created before)
  await client.execute(`CREATE DATABASE IF NOT EXISTS ${DATABASE}`);
  // select db
  await client.execute(`USE ${DATABASE}`);

  // delete table if it exists before
  await client.execute(`DROP TABLE IF EXISTS ${TABLE.TODO}`);
  // create table
  await client.execute(`
    CREATE TABLE ${TABLE.TODO} (
        id int(11) NOT NULL AUTO_INCREMENT,
        todo varchar(100) NOT NULL,
        isCompleted boolean NOT NULL default false,
        PRIMARY KEY (id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  `);
};

run();

export default client;
</code></pre>
<p>Here we are importing <code>DATABASE</code> and <code>TABLE</code> from our config file, then using those values in a new function called <code>run()</code>.</p>
<p>Let's break down this <code>run()</code> function. I have added comments in the file to help you understand the workflow:</p>
<pre><code class="lang-db/client.ts">const run = async () =&gt; {
  // create database (if not created before)
  await client.execute(`CREATE DATABASE IF NOT EXISTS ${DATABASE}`);
  // select db
  await client.execute(`USE ${DATABASE}`);

  // delete table if it exists before
  await client.execute(`DROP TABLE IF EXISTS ${TABLE.TODO}`);
  // create table
  await client.execute(`
    CREATE TABLE ${TABLE.TODO} (
        id int(11) NOT NULL AUTO_INCREMENT,
        todo varchar(100) NOT NULL,
        isCompleted boolean NOT NULL default false,
        PRIMARY KEY (id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  `);
};

run();
</code></pre>
<ul>
<li>Create a database called <code>deno</code> . If it already exists then do nothing.</li>
<li>Then select the database to use, which is called <code>deno</code></li>
<li>Delete the table inside <code>deno</code> called <code>todo</code> if it already exists. </li>
<li>Next, create a new table inside the <code>deno</code> db, call it <code>todo</code>, and define its structure: It will have a unique auto increment <code>id</code> which will be an integer, another field called <code>todo</code> which will be a string, and finally a field called <code>isCompleted</code> which is a boolean. I also define <code>id</code> as my primary key.</li>
</ul>
<p>The reason I wrote this script was because I don't want to have extra information in MySQL instance. Every time the script runs it just reinitializes everything.</p>
<p>You don't have to add this script. But if you don't, then you will have to manually create a db and the table.</p>
<p>Also, check out the Deno MySQL library's docs on <a target="_blank" href="https://deno.land/x/mysql/#create-database">db creation</a> and on <a target="_blank" href="https://deno.land/x/mysql/#create-table">table creation</a>.</p>
<p>Going back to our agenda, we just achieved two things out of the four mentioned at the top of the article:</p>
<ul>
<li>Create a MySQL database connection</li>
<li>Write a small script that resets the database every time we start our Deno server</li>
</ul>
<p>That is already 50% of the tutorial. Unfortunately, we can't see much happening right now. Let's quickly add some functionality to see it working.</p>
<h2 id="heading-performing-crud-operations-on-a-table-and-adding-the-functionality-to-our-api-controllers">Performing CRUD operations on a table and adding the functionality to our API controllers</h2>
<p>We need to update our Todo interface first. Go to the <code>interfaces/Todo.ts</code> file and add the following:</p>
<pre><code class="lang-interfaces/todo.ts">export default interface Todo {
  id?: number,
  todo?: string,
  isCompleted?: boolean,
}
</code></pre>
<p>What this <code>?</code> does is it makes the key in the object optional. I did this because later I will use different functions to pass objects with only an <code>id</code>, <code>todo</code>, <code>isCompleted</code>, or all of them at once.</p>
<p>If you want to learn more about optional properties in TypeScript, head over to their docs <a target="_blank" href="https://www.typescriptlang.org/docs/handbook/interfaces.html#optional-properties">here</a>.</p>
<p>Next, create a new folder called <strong>models</strong> and inside that folder, create a file called <strong>todo.ts</strong>. Add the following content to the file:</p>
<pre><code class="lang-models/todo.ts">import client from "../db/client.ts";
// config
import { TABLE } from "../db/config.ts";
// Interface
import Todo from "../interfaces/Todo.ts";

export default {
  /**
   * Takes in the id params &amp; checks if the todo item exists
   * in the database
   * @param id
   * @returns boolean to tell if an entry of todo exits in table
   */
  doesExistById: async ({ id }: Todo) =&gt; {},
  /**
   * Will return all the entries in the todo column
   * @returns array of todos
   */
  getAll: async () =&gt; {},
  /**
   * Takes in the id params &amp; returns the todo item found
   * against it.
   * @param id
   * @returns object of todo item
   */
  getById: async ({ id }: Todo) =&gt; {},
  /**
   * Adds a new todo item to todo table
   * @param todo
   * @param isCompleted
   */
  add: async (
    { todo, isCompleted }: Todo,
  ) =&gt; {},
  /**
   * Updates the content of a single todo item
   * @param id
   * @param todo
   * @param isCompleted
   * @returns integer (count of effect rows)
   */
  updateById: async ({ id, todo, isCompleted }: Todo) =&gt; {},
  /**
   * Deletes a todo by ID
   * @param id
   * @returns integer (count of effect rows)
   */
  deleteById: async ({ id }: Todo) =&gt; {},
};
</code></pre>
<p>Right now the functions are empty, but that is okay. We will fill them up one by one.</p>
<p>Next go to <code>controllers/todo.ts</code> file and make sure you add the following:</p>
<pre><code><span class="hljs-comment">// interfaces</span>
<span class="hljs-keyword">import</span> Todo <span class="hljs-keyword">from</span> <span class="hljs-string">"../interfaces/Todo.ts"</span>;
<span class="hljs-comment">// models</span>
<span class="hljs-keyword">import</span> TodoModel <span class="hljs-keyword">from</span> <span class="hljs-string">"../models/todo.ts"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
  <span class="hljs-comment">/**
   * <span class="hljs-doctag">@description </span>Get all todos
   * <span class="hljs-doctag">@route </span>GET /todos
   */</span>
  <span class="hljs-attr">getAllTodos</span>: <span class="hljs-keyword">async</span> ({ response }: { <span class="hljs-attr">response</span>: any }) =&gt; {},
  <span class="hljs-comment">/**
   * <span class="hljs-doctag">@description </span>Add a new todo
   * <span class="hljs-doctag">@route </span>POST /todos
   */</span>
  <span class="hljs-attr">createTodo</span>: <span class="hljs-keyword">async</span> (
    { request, response }: { <span class="hljs-attr">request</span>: any; response: any },
  ) =&gt; {},
  <span class="hljs-comment">/**
   * <span class="hljs-doctag">@description </span>Get todo by id
   * <span class="hljs-doctag">@route </span>GET todos/:id
   */</span>
  <span class="hljs-attr">getTodoById</span>: <span class="hljs-keyword">async</span> (
    { params, response }: { <span class="hljs-attr">params</span>: { <span class="hljs-attr">id</span>: string }; response: any },
  ) =&gt; {},
  <span class="hljs-comment">/**
   * <span class="hljs-doctag">@description </span>Update todo by id
   * <span class="hljs-doctag">@route </span>PUT todos/:id
   */</span>
  <span class="hljs-attr">updateTodoById</span>: <span class="hljs-keyword">async</span> (
    { params, request, response }: {
      <span class="hljs-attr">params</span>: { <span class="hljs-attr">id</span>: string };
      request: any;
      response: any;
    },
  ) =&gt; {},
  <span class="hljs-comment">/**
   * <span class="hljs-doctag">@description </span>Delete todo by id
   * <span class="hljs-doctag">@route </span>DELETE todos/:id
   */</span>
  <span class="hljs-attr">deleteTodoById</span>: <span class="hljs-keyword">async</span> (
    { params, response }: { <span class="hljs-attr">params</span>: { <span class="hljs-attr">id</span>: string }; response: any },
  ) =&gt; {},
};
</code></pre><p>Here we have empty functions as well. Let's start filling them up.</p>
<h3 id="heading-get-all-todos-api">[Get] all todos API</h3>
<p>Inside <code>models/todo.ts</code>, add a definition for a function called <code>getAll</code>:</p>
<pre><code class="lang-models/todo.ts">import client from "../db/client.ts";
// config
import { TABLE } from "../db/config.ts";
// Interface
import Todo from "../interfaces/Todo.ts";

export default {
   /**
   * Will return all the entries in the todo column
   * @returns array of todos
   */
  getAll: async () =&gt; {
    return await client.query(`SELECT * FROM ${TABLE.TODO}`);
  },
}
</code></pre>
<p>The <code>Client</code> also exposes another method besides <code>connect</code> (we used a "connect" method in <code>db/client.ts</code> file) and that is <code>query</code>. The <code>client.query</code> method lets us run MySQL queries directly from our Deno code as is.</p>
<p>Next go to <code>controllers/todo.ts</code> add definition for <code>getAllTodos</code>:</p>
<pre><code class="lang-controllers/todo.ts">// interfaces
import Todo from "../interfaces/Todo.ts";
// models
import TodoModel from "../models/todo.ts";

export default {
  /**
   * @description Get all todos
   * @route GET /todos
   */
  getAllTodos: async ({ response }: { response: any }) =&gt; {
    try {
      const data = await TodoModel.getAll();
      response.status = 200;
      response.body = {
        success: true,
        data,
      };
    } catch (error) {
      response.status = 400;
      response.body = {
        success: false,
        message: `Error: ${error}`,
      };
    }
  },
}
</code></pre>
<p>All we are doing is importing <code>TodoModel</code> and using its method called <code>getAll</code>, which we just defined now. Since it returns as a promise we have wrapped it in async/await. </p>
<p>The method <code>TodoModel.getAll()</code> will return us an array which we simply return to <code>response.body</code> with <code>status</code> set to <code>200</code>.</p>
<p>If the promise fails or there is another error, we simply go to our catch block and return a status of 400 with <code>success</code> set to false. We also set the <code>message</code> to what we get from the catch block.</p>
<p>That's it, we're done. Now let's fire up our terminal. </p>
<p>Make sure your MySQL instance is running. In your terminal type:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>Your terminal should look something like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/Screenshot-2020-06-04-at-23.29.19.png" alt="Image" width="600" height="400" loading="lazy">
<em>This is how my console looks when I start the server</em></p>
<p>My console is telling me two things here.</p>
<ol>
<li>That my Deno API server is running on port 8080</li>
<li>That my MySQL instance is running on <code>127.0.0.1</code>, which is <code>localhost</code></li>
</ol>
<p>Let's test our API out. I am using <a target="_blank" href="https://www.postman.com/">Postman</a> here, but you can use your favorite API client.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/Screenshot-2020-06-04-at-23.31.07.png" alt="Image" width="600" height="400" loading="lazy">
<em>running [GET] localhost:8080/todos =&gt; Will return all todos</em></p>
<p>Right now it only returns empty data. But once we add data to our <code>todo</code> table, it will return those todos here.</p>
<p>Awesome. One API down and four more to go.</p>
<h3 id="heading-post-add-a-todo-api">[Post] add a todo API</h3>
<p>In the <code>models/todo.ts</code> file, add the following definition for <code>add()</code> function:</p>
<pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
   <span class="hljs-comment">/**
   * Adds a new todo item to todo table
   * <span class="hljs-doctag">@param <span class="hljs-variable">todo</span></span>
   * <span class="hljs-doctag">@param <span class="hljs-variable">isCompleted</span></span>
   */</span>
  <span class="hljs-attr">add</span>: <span class="hljs-keyword">async</span> (
    { todo, isCompleted }: Todo,
  ) =&gt; {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> client.query(
      <span class="hljs-string">`INSERT INTO <span class="hljs-subst">${TABLE.TODO}</span>(todo, isCompleted) values(?, ?)`</span>,
      [
        todo,
        isCompleted,
      ],
    );
  },
}
</code></pre><p>The add function takes in object as an argument, which has two items: <code>todo</code> and <code>isCompleted</code>.</p>
<p>So <code>_add_: _async_ ({ todo, isCompleted }: Todo) =&gt; {}</code> can also be written as <code>({todo, isCompleted}: {todo:string, isCompleted:boolean})</code>. But since we already have an interface defined in our <code>interfaces/Todo.ts</code> file which is</p>
<pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> interface Todo {
  id?: number,
  todo?: string,
  isCompleted?: boolean,
}
</code></pre><p>we can simply write this as <code>_add_: _async_ ({ todo, isCompleted }: Todo) =&gt; {}</code>. This tells TypeScript that this function has two arguments, <code>todo</code>, which is a string, and <code>isCompleted</code>, which is a boolean.</p>
<p>If you want to read more on interfaces, TypeScript has an excellent document on it which you can find <a target="_blank" href="https://www.typescriptlang.org/docs/handbook/interfaces.html">here</a>.</p>
<p>Inside our function we have the following:</p>
<pre><code><span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> client.query(
  <span class="hljs-string">`INSERT INTO <span class="hljs-subst">${TABLE.TODO}</span>(todo, isCompleted) values(?, ?)`</span>,
  [
    todo,
    isCompleted,
  ],
);
</code></pre><p>This query can be broken down into two parts:</p>
<ul>
<li><code>INSERT INTO ${TABLE_._TODO}(todo, isCompleted) values(?, ?)</code>. The two question marks here denote a use of variables inside this query.</li>
<li>The other part, <code>[todo, isCompleted]</code>, is the variables that will go in the <em>first part</em> of the query and be replaced with <code>(?, ?)</code></li>
<li><code>Table.Todo</code> is just a string coming from file <code>db/config.ts</code> where the <code>Table.Todo</code> value is "<code>todo</code>"</li>
</ul>
<p>Next inside our <code>controllers/todo.ts</code> file, go to the definition of the <code>createTodo()</code> function:</p>
<pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
   <span class="hljs-comment">/**
   * <span class="hljs-doctag">@description </span>Add a new todo
   * <span class="hljs-doctag">@route </span>POST /todos
   */</span>
  <span class="hljs-attr">createTodo</span>: <span class="hljs-keyword">async</span> (
    { request, response }: { <span class="hljs-attr">request</span>: any; response: any },
  ) =&gt; {
    <span class="hljs-keyword">const</span> body = <span class="hljs-keyword">await</span> request.body();
    <span class="hljs-keyword">if</span> (!request.hasBody) {
      response.status = <span class="hljs-number">400</span>;
      response.body = {
        <span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>,
        <span class="hljs-attr">message</span>: <span class="hljs-string">"No data provided"</span>,
      };
      <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">await</span> TodoModel.add(
        { <span class="hljs-attr">todo</span>: body.value.todo, <span class="hljs-attr">isCompleted</span>: <span class="hljs-literal">false</span> },
      );
      response.body = {
        <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-attr">message</span>: <span class="hljs-string">"The record was added successfully"</span>,
      };
    } <span class="hljs-keyword">catch</span> (error) {
      response.status = <span class="hljs-number">400</span>;
      response.body = {
        <span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>,
        <span class="hljs-attr">message</span>: <span class="hljs-string">`Error: <span class="hljs-subst">${error}</span>`</span>,
      };
    }
  },
}
</code></pre><p>Let's break this down into two parts:</p>
<p><strong>Part 1</strong></p>
<pre><code><span class="hljs-keyword">const</span> body = <span class="hljs-keyword">await</span> request.body();
<span class="hljs-keyword">if</span> (!request.hasBody) {
  response.status = <span class="hljs-number">400</span>;
  response.body = {
    <span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">message</span>: <span class="hljs-string">"No data provided"</span>,
  };
  <span class="hljs-keyword">return</span>;
}
</code></pre><p>All we are doing here is checking if the user is sending data in body. If not, then we return a status <code>400</code> and in the body return <code>success: false</code> and <code>message: &lt;erromessage-string&gt;</code>.</p>
<p><strong>Part 2</strong></p>
<pre><code><span class="hljs-keyword">try</span> {
  <span class="hljs-keyword">await</span> TodoModel.add(
    { <span class="hljs-attr">todo</span>: body.value.todo, <span class="hljs-attr">isCompleted</span>: <span class="hljs-literal">false</span> },
  );
  response.body = {
    <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">message</span>: <span class="hljs-string">"The record was added successfully"</span>,
  };
} <span class="hljs-keyword">catch</span> (error) {
  response.status = <span class="hljs-number">400</span>;
  response.body = {
    <span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">message</span>: <span class="hljs-string">`Error: <span class="hljs-subst">${error}</span>`</span>,
  };
}
</code></pre><p>If there is no error, the <code>TodoModel.add()</code> function is called and simply returns a status of <code>200</code> and a confirmation message to the user.</p>
<p>Otherwise it just throws a similar error that we did in the previous API.</p>
<p>Now we're done. Fire up your terminal and make sure your MySQL instance is running. In your terminal type:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>Go to <a target="_blank" href="https://www.postman.com/">Postman</a> and run the API route for this controller:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/Screenshot-2020-06-04-at-23.55.02.png" alt="Image" width="600" height="400" loading="lazy">
<em>running [POST] localhost:8080/todos =&gt; Will add a new new todo item</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/Screenshot-2020-06-04-at-23.57.06.png" alt="Image" width="600" height="400" loading="lazy">
<em>running [POST] localhost:8080/todos =&gt; Will return all todos, notice how the new added item is being returned as well</em></p>
<p>This is great, now we have two working APIs. Only three more to go.</p>
<h3 id="heading-get-todo-by-id-api">[GET] todo by id API</h3>
<p>In your <code>models/todo.ts</code> file, add definition for these two functions, <code>doesExistById()</code> and <code>getById()</code>:</p>
<pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
   <span class="hljs-comment">/**
   * Takes in the id params &amp; checks if the todo item exists
   * in the database
   * <span class="hljs-doctag">@param <span class="hljs-variable">id</span></span>
   * <span class="hljs-doctag">@returns </span>boolean to tell if an entry of todo exits in table
   */</span>
  <span class="hljs-attr">doesExistById</span>: <span class="hljs-keyword">async</span> ({ id }: Todo) =&gt; {
    <span class="hljs-keyword">const</span> [result] = <span class="hljs-keyword">await</span> client.query(
      <span class="hljs-string">`SELECT COUNT(*) count FROM <span class="hljs-subst">${TABLE.TODO}</span> WHERE id = ? LIMIT 1`</span>,
      [id],
    );
    <span class="hljs-keyword">return</span> result.count &gt; <span class="hljs-number">0</span>;
  },
  <span class="hljs-comment">/**
   * Takes in the id params &amp; returns the todo item found
   * against it.
   * <span class="hljs-doctag">@param <span class="hljs-variable">id</span></span>
   * <span class="hljs-doctag">@returns </span>object of todo item
   */</span>
  <span class="hljs-attr">getById</span>: <span class="hljs-keyword">async</span> ({ id }: Todo) =&gt; {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> client.query(
      <span class="hljs-string">`SELECT * FROM <span class="hljs-subst">${TABLE.TODO}</span> WHERE id = ?`</span>,
      [id],
    );
  },
}
</code></pre><p>Let's talk about each function one by one:</p>
<ul>
<li><code>doesExistById</code> takes in an <code>id</code> and returns a <code>boolean</code> indicating whether a particular todo exists in the database or not.</li>
</ul>
<p>Let's break this function down:</p>
<pre><code><span class="hljs-keyword">const</span> [result] = <span class="hljs-keyword">await</span> client.query(
  <span class="hljs-string">`SELECT COUNT(*) count FROM <span class="hljs-subst">${TABLE.TODO}</span> WHERE id = ? LIMIT 1`</span>,
  [id],
);
<span class="hljs-keyword">return</span> result.count &gt; <span class="hljs-number">0</span>;
</code></pre><p>We simply check the count here in the table against a particular todo id. If the count is greater than zero, we return <code>true</code>. Otherwise, we return <code>false</code>.</p>
<ul>
<li><code>getById</code> returns the todo item against a particular id:</li>
</ul>
<pre><code><span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> client.query(
  <span class="hljs-string">`SELECT * FROM <span class="hljs-subst">${TABLE.TODO}</span> WHERE id = ?`</span>,
  [id],
);
</code></pre><p>We are simply running a MySQL query here to get a todo by id and returning the result as-is.</p>
<p>Next, go to your <code>controllers/todo.ts</code> file and add a definition for a <code>getTodoById</code> controller method:</p>
<pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
   <span class="hljs-comment">/**
   * <span class="hljs-doctag">@description </span>Get todo by id
   * <span class="hljs-doctag">@route </span>GET todos/:id
   */</span>
  <span class="hljs-attr">getTodoById</span>: <span class="hljs-keyword">async</span> (
    { params, response }: { <span class="hljs-attr">params</span>: { <span class="hljs-attr">id</span>: string }; response: any },
  ) =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> isAvailable = <span class="hljs-keyword">await</span> TodoModel.doesExistById(
        { <span class="hljs-attr">id</span>: <span class="hljs-built_in">Number</span>(params.id) },
      );

      <span class="hljs-keyword">if</span> (!isAvailable) {
        response.status = <span class="hljs-number">404</span>;
        response.body = {
          <span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>,
          <span class="hljs-attr">message</span>: <span class="hljs-string">"No todo found"</span>,
        };
        <span class="hljs-keyword">return</span>;
      }

      <span class="hljs-keyword">const</span> todo = <span class="hljs-keyword">await</span> TodoModel.getById({ <span class="hljs-attr">id</span>: <span class="hljs-built_in">Number</span>(params.id) });
      response.status = <span class="hljs-number">200</span>;
      response.body = {
        <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-attr">data</span>: todo,
      };
    } <span class="hljs-keyword">catch</span> (error) {
      response.status = <span class="hljs-number">400</span>;
      response.body = {
        <span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>,
        <span class="hljs-attr">message</span>: <span class="hljs-string">`Error: <span class="hljs-subst">${error}</span>`</span>,
      };
    }
  },
}
</code></pre><p>Let's break this down into two smaller parts:</p>
<pre><code><span class="hljs-keyword">const</span> isAvailable = <span class="hljs-keyword">await</span> TodoModel.doesExistById(
  { <span class="hljs-attr">id</span>: <span class="hljs-built_in">Number</span>(params.id) },
);

<span class="hljs-keyword">if</span> (!isAvailable) {
  response.status = <span class="hljs-number">404</span>;
  response.body = {
    <span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">message</span>: <span class="hljs-string">"No todo found"</span>,
  };
  <span class="hljs-keyword">return</span>;
}
</code></pre><p>First we check if the todo exists in the database against an id by using this method:</p>
<pre><code><span class="hljs-keyword">const</span> isAvailable = <span class="hljs-keyword">await</span> TodoModel.doesExistById(
  { <span class="hljs-attr">id</span>: <span class="hljs-built_in">Number</span>(params.id) },
);
</code></pre><p>Here we need to convert <code>params.id</code> into a <code>Number</code> because our todo interface only accepts <code>id</code> as a number. Next, we just pass <code>params.id</code> to the <code>doesExistById</code> method. This method will return as a boolean.</p>
<p>Then we simply check if the todo is not available and return a <code>404</code> method with our standard response like with the previous endpoints:</p>
<pre><code><span class="hljs-keyword">if</span> (!isAvailable) {
  response.status = <span class="hljs-number">404</span>;
  response.body = {
    <span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">message</span>: <span class="hljs-string">"No todo found"</span>,
  };
  <span class="hljs-keyword">return</span>;
}
</code></pre><p>Then we have:</p>
<pre><code><span class="hljs-keyword">try</span> {
<span class="hljs-keyword">const</span> todo: Todo = <span class="hljs-keyword">await</span> TodoModel.getById({ <span class="hljs-attr">id</span>: <span class="hljs-built_in">Number</span>(params.id) });
response.status = <span class="hljs-number">200</span>;
response.body = {
  <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">data</span>: todo,
};
} <span class="hljs-keyword">catch</span> (error) {
response.status = <span class="hljs-number">400</span>;
response.body = {
  <span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>,
  <span class="hljs-attr">message</span>: <span class="hljs-string">`Error: <span class="hljs-subst">${error}</span>`</span>,
};
</code></pre><p>This is similar to what we were doing in our previous APIs. Here we are simply getting data from the db, setting the variable <code>todo</code>, and then returning the response. If there is an error we simply return a standard error message in the catch block back to the user.</p>
<p>Now fire up your terminal and make sure your MySQL instance is running. In your terminal type:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>Go to <a target="_blank" href="https://www.postman.com/">Postman</a> and run the API route for this controller.</p>
<p>Remember that every time we restart our server we reset the db. If you don't want this behavior, you can simply comment out the <code>run</code> function in the file <code>db/client.ts</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/Screenshot-2020-06-07-at-17.09.32.png" alt="Image" width="600" height="400" loading="lazy">
<em>running [POST] localhost:8080/todos =&gt; Will add a new new todo item</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/Screenshot-2020-06-07-at-17.10.13.png" alt="Image" width="600" height="400" loading="lazy">
<em>running [POST] localhost:8080/todos =&gt; Will return all todos</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/Screenshot-2020-06-07-at-17.11.03.png" alt="Image" width="600" height="400" loading="lazy">
<em>running [GET] localhost:8080/todos/:id =&gt; will return the todo for that id if found</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/Screenshot-2020-06-07-at-17.16.06.png" alt="running [GET] localhost:8080/todos/:id => will return the todo for that id if found" width="600" height="400" loading="lazy">
<em>running [GET] localhost:8080/todos/&lt;unknown-id&gt; =&gt; returns status 404 with not found error message</em></p>
<p>So far we have done APIs for:</p>
<ul>
<li>Get all todos</li>
<li>Create a new todo</li>
<li>Get a todo by ID</li>
</ul>
<p>And here are the remaining APIs:</p>
<ul>
<li>Update a todo by ID</li>
<li>Delete a todo by ID</li>
</ul>
<h3 id="heading-put-update-todo-by-id-api">[PUT] update todo by id API</h3>
<p>Let's create a model for this API first. Go in our <code>models/todo.ts</code> file and add a definition for an <code>updateById</code> function:</p>
<pre><code>**
 * Updates the content <span class="hljs-keyword">of</span> a single todo item
 * @param id
 * @param todo
 * @param isCompleted
 * @returns integer (count <span class="hljs-keyword">of</span> effect rows)
 */
updateById: <span class="hljs-keyword">async</span> ({ id, todo, isCompleted }: Todo) =&gt; {
  <span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> client.query(
    <span class="hljs-string">`UPDATE <span class="hljs-subst">${TABLE.TODO}</span> SET todo=?, isCompleted=? WHERE id=?`</span>,
    [
      todo,
      isCompleted,
      id,
    ],
  );
  <span class="hljs-comment">// return count of rows updated</span>
  <span class="hljs-keyword">return</span> result.affectedRows;
},
</code></pre><p>The <code>updateById</code> takes in 3 params: <code>id</code>, <code>todo</code>, and <code>isCompleted</code>.</p>
<p>We simply run a MySQL query inside this function:</p>
<pre><code>onst result = <span class="hljs-keyword">await</span> client.query(
  <span class="hljs-string">`UPDATE <span class="hljs-subst">${TABLE.TODO}</span> SET todo=?, isCompleted=? WHERE id=?`</span>,
  [
    todo,
    isCompleted,
    id,
  ],
);
</code></pre><p>This updates a single todo item's <code>todo</code> and <code>isCompleted</code> by a specific <code>id</code>.</p>
<p>Next we return a count of rows updated by this query by doing:</p>
<pre><code>  <span class="hljs-comment">// return count of rows updated</span>
  <span class="hljs-keyword">return</span> result.affectedRows;
</code></pre><p>The count will either be 0 or 1, but never more than 1. This is because we have unique IDs in our database – multiple todos with the same ID cannot exist.</p>
<p>Next go to our <code>controllers/todo.ts</code> file and add a definition for a <code>updateTodoById</code> function:</p>
<pre><code>updateTodoById: <span class="hljs-keyword">async</span> (
  { params, request, response }: {
    <span class="hljs-attr">params</span>: { <span class="hljs-attr">id</span>: string };
    request: any;
    response: any;
  },
) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> isAvailable = <span class="hljs-keyword">await</span> TodoModel.doesExistById(
      { <span class="hljs-attr">id</span>: <span class="hljs-built_in">Number</span>(params.id) },
    );
    <span class="hljs-keyword">if</span> (!isAvailable) {
      response.status = <span class="hljs-number">404</span>;
      response.body = {
        <span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>,
        <span class="hljs-attr">message</span>: <span class="hljs-string">"No todo found"</span>,
      };
      <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-comment">// if todo found then update todo</span>
    <span class="hljs-keyword">const</span> body = <span class="hljs-keyword">await</span> request.body();
    <span class="hljs-keyword">const</span> updatedRows = <span class="hljs-keyword">await</span> TodoModel.updateById({
      <span class="hljs-attr">id</span>: <span class="hljs-built_in">Number</span>(params.id),
      ...body.value,
    });
    response.status = <span class="hljs-number">200</span>;
    response.body = {
      <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span>,
      <span class="hljs-attr">message</span>: <span class="hljs-string">`Successfully updated <span class="hljs-subst">${updatedRows}</span> row(s)`</span>,
    };
  } <span class="hljs-keyword">catch</span> (error) {
    response.status = <span class="hljs-number">400</span>;
    response.body = {
      <span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>,
      <span class="hljs-attr">message</span>: <span class="hljs-string">`Error: <span class="hljs-subst">${error}</span>`</span>,
    };
  }
},
</code></pre><p>This is almost the same as of our previous APIs we wrote. The part that's new here is this:</p>
<pre><code><span class="hljs-comment">// if todo found then update todo</span>
<span class="hljs-keyword">const</span> body = <span class="hljs-keyword">await</span> request.body();
<span class="hljs-keyword">const</span> updatedRows = <span class="hljs-keyword">await</span> TodoModel.updateById({
  <span class="hljs-attr">id</span>: <span class="hljs-built_in">Number</span>(params.id),
  ...body.value,
});
</code></pre><p>We simple get the body that the user sends us in JSON and pass the body to our <code>TodoModel.updateById</code> function.</p>
<p>We have to convert the <code>id</code> to a number to comply with our Todo interface.</p>
<p>The query is executed and returns the count of updated rows. From there we simply return it in our response. If there is an error it goes to the catch block where we return our standard response message.</p>
<p>Let's run this and see if it works. Make sure your MySQL instance is running and run the following from your terminal:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>Go to <a target="_blank" href="https://www.postman.com/">Postman</a> and run the API route for this controller:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/Screenshot-2020-06-07-at-17.42.02.png" alt="Image" width="600" height="400" loading="lazy">
<em>running [PUT] localhost:8080/todos/:id =&gt; will update content of that todo by given id</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/Screenshot-2020-06-07-at-17.43.13.png" alt="Image" width="600" height="400" loading="lazy">
<em>running [GET] localhost:8080/todos/ =&gt; will return all todos, see how the todo you updated is also showing there.</em></p>
<h3 id="heading-delete-todo-by-id-api">[DELETE] todo by id API</h3>
<p>In your <code>models/todo.ts</code> file create a function called <code>deleteById</code>:</p>
<pre><code><span class="hljs-comment">/**
 * Deletes a todo by ID
 * <span class="hljs-doctag">@param <span class="hljs-variable">id</span></span>
 * <span class="hljs-doctag">@returns </span>integer (count of effect rows)
 */</span>
<span class="hljs-attr">deleteById</span>: <span class="hljs-keyword">async</span> ({ id }: Todo) =&gt; {
  <span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> client.query(
    <span class="hljs-string">`DELETE FROM <span class="hljs-subst">${TABLE.TODO}</span> WHERE id = ?`</span>,
    [id],
  );
  <span class="hljs-comment">// return count of rows updated</span>
  <span class="hljs-keyword">return</span> result.affectedRows;
},
</code></pre><p>Here we simply pass an <code>id</code> as a param and then use the delete MySQL query. We then return the updated count of rows. The updated count will either be 0 or 1 because the ID of each todo is unique.</p>
<p>Next, go in your <code>controllers/todo.ts</code> file and define a <code>deleteByTodoId</code> method:</p>
<pre><code><span class="hljs-comment">/**
 * <span class="hljs-doctag">@description </span>Delete todo by id
 * <span class="hljs-doctag">@route </span>DELETE todos/:id
 */</span>
<span class="hljs-attr">deleteTodoById</span>: <span class="hljs-keyword">async</span> (
  { params, response }: { <span class="hljs-attr">params</span>: { <span class="hljs-attr">id</span>: string }; response: any },
) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> updatedRows = <span class="hljs-keyword">await</span> TodoModel.deleteById({
      <span class="hljs-attr">id</span>: <span class="hljs-built_in">Number</span>(params.id),
    });
    response.status = <span class="hljs-number">200</span>;
    response.body = {
      <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span>,
      <span class="hljs-attr">message</span>: <span class="hljs-string">`Successfully updated <span class="hljs-subst">${updatedRows}</span> row(s)`</span>,
    };
  } <span class="hljs-keyword">catch</span> (error) {
    response.status = <span class="hljs-number">400</span>;
    response.body = {
      <span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>,
      <span class="hljs-attr">message</span>: <span class="hljs-string">`Error: <span class="hljs-subst">${error}</span>`</span>,
    };
  }
},
</code></pre><p>This is pretty straightforward. We pass the <code>params.id</code> to our <code>TodoModel.deleteById</code> method and return the count of rows updated with this query.</p>
<p>If anything goes wrong an error is thrown in the catch block which returns our standard error response.</p>
<p>Let's check this out.</p>
<p>Make sure your MySQL instance is running. In your terminal type:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>Go to <a target="_blank" href="https://www.postman.com/">Postman</a> and run the API route for this controller:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/Screenshot-2020-06-07-at-18.23.04.png" alt="Image" width="600" height="400" loading="lazy">
<em>running [GET] localhost:8080/todos/ =&gt; will return all todos</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/Screenshot-2020-06-07-at-18.23.11.png" alt="Image" width="600" height="400" loading="lazy">
<em>running [DELETE] localhost:8080/todos/:id =&gt; will delete a todo by ID</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/Screenshot-2020-06-07-at-18.23.44.png" alt="Image" width="600" height="400" loading="lazy">
<em>running [GET] localhost:8080/todos/ =&gt; will return all todos, see how todo with "id" is no longer here</em></p>
<p>With this we are done with our Deno + Oak + MySQL tutorial.</p>
<p>The entire source code is available here: <a target="_blank" href="https://github.com/adeelibr/deno-playground">https://github.com/adeelibr/deno-playground</a>. If you find an issue, just let me know. Or feel free to make a pull request and I'll give you credit in the repository.</p>
<p>If you found this tutorial helpful, please share it. And as always, I am available on <a target="_blank" href="https://twitter.com/adeelibr">Twitter under @adeelibr</a>. I would love to hear your thoughts on it.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create a Todo API in Deno and Oak ]]>
                </title>
                <description>
                    <![CDATA[ By Adeel Imran I am a JavaScript/Node developer who secretly likes (actually, loves and adores) Deno. I have been a huge fan of Deno ever since it was announced and I've been wanting to play with it.  This tutorial focuses on creating a set of REST A... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/create-a-todo-api-in-deno-written-by-a-guy-coming-from-node/</link>
                <guid isPermaLink="false">66d45d5d51f567b42d9f8413</guid>
                
                    <category>
                        <![CDATA[ 2020 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Deno ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Middleware ]]>
                    </category>
                
                    <category>
                        <![CDATA[ REST API ]]>
                    </category>
                
                    <category>
                        <![CDATA[ TypeScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 29 May 2020 11:33:00 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9c9ab6740569d1a4ca273d.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Adeel Imran</p>
<p>I am a JavaScript/Node developer who secretly likes (actually, loves and adores) Deno. I have been a huge fan of Deno ever since it was announced and I've been wanting to play with it. </p>
<p>This tutorial focuses on creating a set of REST APIs for a Todo application. Keep in mind that I did not touch on the database here – I will cover that <a target="_blank" href="https://www.freecodecamp.org/news/how-to-use-mysql-in-deno-oak/">in another article</a>.</p>
<p>At any point if you feel lost or want to check a reference, here is the entire source code of this tutorial: <strong><a target="_blank" href="https://github.com/adeelibr/deno-playground/tree/master/chapter_1:oak">Chapter 1: Oak</a>.</strong></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/04/image-171.png" alt="Image" width="600" height="400" loading="lazy">
_Photo by [Unsplash](https://unsplash.com/@bernardtheclerk?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit"&gt;Bernard de Clerk / &lt;a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm<em>campaign=api-credit)</em></p>
<h3 id="heading-things-we-will-cover">Things we will cover</h3>
<ul>
<li>Create a basic server</li>
<li>Create 5 APIs (routes/controller)</li>
<li>Create a middleware to log API requests as they are made in the console</li>
<li>Create a not found (404) middleware when the user tries to access an unknown API</li>
</ul>
<h3 id="heading-what-will-we-need">What will we need</h3>
<ul>
<li>An installed version of Deno (don't worry I'll walk you through it)</li>
<li>A tiny bit of knowledge of Typescript</li>
<li>Would be awesome if you have worked with Node/Express before (don't worry if you haven't — this tutorial is very basic)</li>
</ul>
<h2 id="heading-lets-get-started">Let's get started</h2>
<p>First things first let's install Deno. I am on a Mac computer so I am using brew. Simply open your terminal and type:</p>
<pre><code>$ brew install deno
</code></pre><p>But if you are using a different operating system, just head over to <a target="_blank" href="https://deno.land/#installation"><strong>deno.land installation</strong></a><strong>.</strong> They have a lot of ways you can easily install it on your machine.</p>
<p>Once you have it installed, close the terminal, open a new one, and type:</p>
<pre><code>$ deno --version
</code></pre><p>It should output something like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-28-at-22.34.24.png" alt="Image" width="600" height="400" loading="lazy">
<em>running command "deno --version" to see which version of deno is installed</em></p>
<p>Awesome! With this we are almost done with 10% of this tutorial. </p>
<p>Let's move ahead and create the backend API for our Todo app.</p>
<h3 id="heading-setting-up-the-project">Setting up the project</h3>
<p>Before you move on, here is the entire source code of this tutorial: <strong><a target="_blank" href="https://github.com/adeelibr/deno-playground/tree/master/chapter_1:oak">Chapter 1: Oak</a>.</strong></p>
<p>Let's get started:</p>
<ul>
<li>Create a new folder and call it <strong>chapter_1:oak</strong> (but you can call it anything you want)</li>
<li>Once you create a folder simply <code>cd</code> into your new project. Create a file called <strong>server.ts</strong> and write the following code in it:</li>
</ul>
<pre><code class="lang-server.ts">import { Application } from "https://deno.land/x/oak/mod.ts";

const app = new Application();
const port: number = 8080;

console.log('running on port ', port);
await app.listen({ port });
</code></pre>
<p>Let's run this file. Open your terminal and in your project root folder type:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>I will talk about what the <code>--allow-net</code> flag does, but for now just bear with me ?.</p>
<p>You should get something like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-28-at-22.33.28.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>What we have done so far is create a server which listens on port 8080. It doesn't do much right now besides being able to run on port 8080.</p>
<p>If you have used JavaScript before, one thing you might have noticed is we are importing packages in a different way. We have to do something like:</p>
<pre><code><span class="hljs-keyword">import</span> { Application } <span class="hljs-keyword">from</span> <span class="hljs-string">"https://deno.land/x/oak/mod.ts"</span>;
</code></pre><p>When you run <code>deno run ---allow-net &lt;file_name&gt;</code> in your terminal, Deno will look at all your imports and install them locally in your machine if they are not there. </p>
<p>The first time you run this it will go to this URL <code>https://deno.land/x/oak/mod.ts</code> and install the <code>oak</code> package. Oak is basically a Deno framework for writing API's. It will put it somewhere locally in your cache.</p>
<p>In the next line we do this:</p>
<pre><code><span class="hljs-keyword">const</span> app = <span class="hljs-keyword">new</span> Application();
</code></pre><p>This creates a new instance of our application, and it will be the basis of everything as you progress further in this tutorial. You can add routes to the application instance, attach middleware like API logging, write a 404 not found, and so on.</p>
<p>Then we write:</p>
<pre><code><span class="hljs-keyword">const</span> port: number = <span class="hljs-number">8080</span>;
<span class="hljs-comment">// const port = 8080; // =&gt; can also be written like this</span>
</code></pre><p>Both are the same and do the same thing. The only difference is writing <code>const port: number = 8080</code> tells Typescript that <code>port</code> variable is of type number.</p>
<p>If you were to write <code>const port: number = "8080"</code>, this would throw an error in your terminal, as port is of type <code>number</code>. But we are trying to assign it a <code>string</code> of value "8080". </p>
<p>If you want to learn more about different types of types (pun intended) check out this very easy and basic guide on <a target="_blank" href="https://www.typescriptlang.org/docs/handbook/basic-types.html"><strong>Basic types by Typescript</strong></a>. Just give it a quick glance for 2-3 minutes and head back here.</p>
<p>And in the end we have:</p>
<pre><code><span class="hljs-built_in">console</span>.log(<span class="hljs-string">'running on port '</span>, port);
<span class="hljs-keyword">await</span> app.listen({ port });
</code></pre><p>We simply console here the port number and tell Deno to listen to the port, which is 8080.</p>
<p>It isn't doing much right now. Let's make it do something basic like show a <em>JSON</em> message in your browser when you go to http:localhost:8080<em>.</em></p>
<p>Add the following to your <strong>server.ts</strong> file:</p>
<pre><code class="lang-server.ts">import { Application, Router } from "https://deno.land/x/oak/mod.ts";

const app = new Application();
const port: number = 8080;

const router = new Router();
router.get("/", ({ response }: { response: any }) =&gt; {
  response.body = {
    message: "hello world",
  };
});
app.use(router.routes());
app.use(router.allowedMethods());

console.log('running on port ', port);
await app.listen({ port });
</code></pre>
<p>The new thing added here is that we are now also importing <code>Router</code> along with <code>Application</code> from <code>oak</code> in line 1.</p>
<p>Next what we do is:</p>
<pre><code><span class="hljs-keyword">const</span> router = <span class="hljs-keyword">new</span> Router();
router.get(<span class="hljs-string">"/"</span>, <span class="hljs-function">(<span class="hljs-params">{ response }: { response: any }</span>) =&gt;</span> {
  response.body = {
    <span class="hljs-attr">message</span>: <span class="hljs-string">"hello world"</span>,
  };
});
app.use(router.routes());
app.use(router.allowedMethods());
</code></pre><p>We create a new router instance by doing <code>const router = new Router()</code> and then we create a new route called <code>/</code> which is of type <code>get</code>.</p>
<p>Let's break this down:</p>
<pre><code>router.get(<span class="hljs-string">"/"</span>, <span class="hljs-function">(<span class="hljs-params">{ response }: { response: any }</span>) =&gt;</span> {
  response.body = {
    <span class="hljs-attr">message</span>: <span class="hljs-string">"hello world"</span>,
  };
});
</code></pre><p><code>router.get</code> takes 2 parameters. The first is route which we have set to <code>/</code> and the second is function. The function itself takes an argument which is an object. What I am doing here is <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment">destructuring</a> the object and getting only <code>response</code>.</p>
<p>Next I am type checking <code>response</code> similar to how I did <code>const port: number = 8080;</code>. All I am doing is <code>{ response }: { response: any }</code> which is telling TypeScript here that the <code>response</code> which I have destructed can be of type <code>any</code>.</p>
<p><code>any</code> helps you avoid type checking in TypeScript. You can read more about it <a target="_blank" href="https://www.typescriptlang.org/docs/handbook/basic-types.html#any">here</a>.</p>
<p>Then all I am doing is taking that <code>response</code> object and setting <code>response.body.message = "hello world";</code>.</p>
<pre><code>response.body = {
  <span class="hljs-attr">message</span>: <span class="hljs-string">"hello world"</span>,
};
</code></pre><p>Last but not least, we just add these two lines:</p>
<pre><code>app.use(router.routes());
app.use(router.allowedMethods());
</code></pre><p>This tells Deno to include all routes by our router (currently we only have one) and the next line tells Deno to allow all methods for this route(s) like <code>GET, POST, PUT, DELETE</code>.</p>
<p>And now we are done. ✅ Let's run this and see what we have:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>The <code>---allow-net</code> property tells Deno that this app gives the user the permission to access its content via the port opened up.</p>
<p>Now open your favorite browser and go to <code>http://localhost:8080</code>. You will see something like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-28-at-23.11.08.png" alt="Image" width="600" height="400" loading="lazy">
<em>Result of running localhost:8080 on your browser</em></p>
<p>Honestly the hardest part is done. Conceptually we are 60% there.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/images.jpeg" alt="Image" width="600" height="400" loading="lazy">
<em>Master Yoda approves</em></p>
<p>Awesome.</p>
<p>Just one last thing before we start with our Todo API. Let's replace:</p>
<pre><code><span class="hljs-built_in">console</span>.log(<span class="hljs-string">'running on port '</span>, port);
<span class="hljs-keyword">await</span> app.listen({ port });
</code></pre><p>with:</p>
<pre><code class="lang-server.ts">app.addEventListener("listen", ({ secure, hostname, port }) =&gt; {
  const protocol = secure ? "https://" : "http://";
  const url = `${protocol}${hostname ?? "localhost"}:${port}`;
  console.log(`Listening on: ${port}`);
});

await app.listen({ port });
</code></pre>
<p>The code we had before was not very accurate, because we were simply console logging a message and then waiting for the app to start listening on a port.</p>
<p>With the later version we wait for the app to start listening on <code>port</code> and we can listen by adding an event listener to our <code>app</code> instance with the following: <code>app_.addEventListener_("listen", ({ secure, hostname, port }) =&gt; {}</code>. </p>
<p>The first param is the event we want to listen for (which is <code>listen</code> ?) and then the second param is an object which we destruct to <code>{ secure, hostname, port }</code>. Secure is a boolean, hostname is a string, and port is a number.</p>
<p>Now when we start our app, it will only console the message once the app actually starts listening on port.</p>
<p>We can just go one step ahead and make it more colorful. Let's add a new module to the top of the file in <code>server.ts</code>:</p>
<pre><code><span class="hljs-keyword">import</span> { green, yellow } <span class="hljs-keyword">from</span> <span class="hljs-string">"https://deno.land/std@0.53.0/fmt/colors.ts"</span>;
</code></pre><p>And then inside our event listener method we can replace:</p>
<pre><code><span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Listening on: <span class="hljs-subst">${port}</span>`</span>);
</code></pre><p>with:</p>
<pre><code><span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${yellow(<span class="hljs-string">"Listening on:"</span>)}</span> <span class="hljs-subst">${green(url)}</span>`</span>);
</code></pre><p>Now when we do:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>it will show this in our console:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-28-at-23.34.29.png" alt="Image" width="600" height="400" loading="lazy">
<em>Cool, now we have a colourful console.</em></p>
<p>If you get stuck anywhere you can simply go to the source code of this tutorial <a target="_blank" href="https://github.com/adeelibr/deno-playground/tree/master/chapter_1:oak"><strong>here</strong></a>.</p>
<p>Let's create our Todo API's routes next.</p>
<ul>
<li>Create a new folder in your root folder called <code>routes</code> and inside that folder create a file called <code>todo.ts</code></li>
<li>At the same time in your root folder create a new folder called <code>controllers</code> and inside that folder create a file called <code>todo.ts</code></li>
</ul>
<p>Let's first touch the <code>controllers/todo.ts</code> file:</p>
<pre><code class="lang-controllers/todo.ts">export default {
  getAllTodos: () =&gt; {},
  createTodo: async () =&gt; {},
  getTodoById: () =&gt; {},
  updateTodoById: async () =&gt; {},
  deleteTodoById: () =&gt; {},
};
</code></pre>
<p>We are simply exporting an object here with some named functions which are empty (for now).</p>
<p>Next go inside your file <code>routes/todo.ts</code> and type this:</p>
<pre><code class="lang-routes/todo.ts">import { Router } from "https://deno.land/x/oak/mod.ts";

const router = new Router();
// controller
import todoController from "../controllers/todo.ts";

router
  .get("/todos", todoController.getAllTodos)
  .post("/todos", todoController.createTodo)
  .get("/todos/:id", todoController.getTodoById)
  .put("/todos/:id", todoController.updateTodoById)
  .delete("/todos/:id", todoController.deleteTodoById);

export default router;
</code></pre>
<p>This might look familiar to people who have worked with Node and Express. </p>
<p>All we are doing here is importing <code>Route</code> from <code>oak</code> and then setting up a new instance of Router by doing <code>const router = new Router();</code>.</p>
<p>Next we import our controllers by doing:</p>
<pre><code><span class="hljs-keyword">import</span> todoController <span class="hljs-keyword">from</span> <span class="hljs-string">"../controllers/todo.ts"</span>;
</code></pre><p>One thing to notice here in Deno is every time we import a local file in our Deno project we have to provide the file extension. This is because Deno doesn't know whether the file being imported is a <code>.js</code> or <code>.ts</code> file.</p>
<p>Moving forward we simply set all of our routes according to REST conventions:</p>
<pre><code class="lang-routes/todo.ts">router
  .get("/todos", todoController.getAllTodos)
  .post("/todos", todoController.createTodo)
  .get("/todos/:id", todoController.getTodoById)
  .put("/todos/:id", todoController.updateTodoById)
  .delete("/todos/:id", todoController.deleteTodoById);
</code></pre>
<p>The code above will translate to our API definition like this:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>TYPE</td><td>API ROUTE</td><td></td><td></td><td></td></tr>
</thead>
<tbody>
<tr>
<td>GET</td><td>/todos</td><td></td><td></td><td></td></tr>
<tr>
<td>GET</td><td>/todos/:id</td><td></td><td></td><td></td></tr>
<tr>
<td>POST</td><td>/todos</td><td></td><td></td><td></td></tr>
<tr>
<td>PUT</td><td>/todos/:id</td><td></td><td></td><td></td></tr>
<tr>
<td>DELETE</td><td>/todos/:id</td><td></td><td></td></tr>
</tbody>
</table>
</div><p>and at the end we simply export our router by doing <code>_export_ _default_ router;</code>.</p>
<p>We are done with creating our routes structure. (Now, each route doesn't do anything because our controllers are empty, we will add functionality to them in a bit.)</p>
<p>Here's the last piece of the puzzle before we start adding functionality to each route controller. We need to attach this <code>router</code> to our <code>app</code> instance.</p>
<p>So head over to <code>server.ts</code> file and do the following:</p>
<ul>
<li>Add this to the very top:</li>
</ul>
<pre><code><span class="hljs-comment">// routes</span>
<span class="hljs-keyword">import</span> todoRouter <span class="hljs-keyword">from</span> <span class="hljs-string">"./routes/todo.ts"</span>;
</code></pre><ul>
<li>Remove this piece of code:</li>
</ul>
<pre><code><span class="hljs-keyword">const</span> router = <span class="hljs-keyword">new</span> Router();
router.get(<span class="hljs-string">"/"</span>, <span class="hljs-function">(<span class="hljs-params">{ response }: { response: any }</span>) =&gt;</span> {
  response.body = {
    <span class="hljs-attr">message</span>: <span class="hljs-string">"hello world"</span>,
  };
});
app.use(router.routes());
app.use(router.allowedMethods());
</code></pre><ul>
<li>Replace it with:</li>
</ul>
<pre><code>app.use(todoRouter.routes());
app.use(todoRouter.allowedMethods());
</code></pre><p>This is it – we are done. Your <code>server.ts</code> file should look like this now:</p>
<pre><code class="lang-server.ts">import { Application } from "https://deno.land/x/oak/mod.ts";
import { green, yellow } from "https://deno.land/std@0.53.0/fmt/colors.ts";

// routes
import todoRouter from "./routes/todo.ts";

const app = new Application();
const port: number = 8080;

app.use(todoRouter.routes());
app.use(todoRouter.allowedMethods());

app.addEventListener("listen", ({ secure, hostname, port }) =&gt; {
  const protocol = secure ? "https://" : "http://";
  const url = `${protocol}${hostname ?? "localhost"}:${port}`;
  console.log(
    `${yellow("Listening on:")} ${green(url)}`,
  );
});

await app.listen({ port });
</code></pre>
<p>If you got stuck anywhere while following this, simple head over to the source code of this tutorial <strong><a target="_blank" href="https://github.com/adeelibr/deno-playground/tree/master/chapter_1:oak">here</a>.</strong></p>
<p>Awesome, now we have our routes with no functionality at the moment. So let's add that functionality in our controllers.</p>
<p>But before we do that we have to create 2 more (tiny) files.</p>
<ul>
<li>In your root folder create a new folder called <code>interfaces</code> and inside that folder create a file called <code>Todo.ts</code> (make sure Todo is capitalized, as it won't give any syntax error here if you don't – these are just conventions.)</li>
<li>Also in your root folder create a new folder called <code>stubs</code> and inside that folder create a file called <code>todos.ts</code></li>
</ul>
<p>Let's create an interface in our <code>interfaces/Todo.ts</code> file. Simply add the following code:</p>
<pre><code class="lang-interfaces/todo.ts">export default interface Todo {
  id: string,
  todo: string,
  isCompleted: boolean,
}
</code></pre>
<p>What is an interface?</p>
<p>One of the core things in TypeScript is checking the shape that value has. Similar to <code>const port: number = 8080</code> or <code>{ response }: { response : any }</code>, we can also type check an object. </p>
<p>In TypeScript, interfaces fill the role of naming these types, and are a powerful way of <strong>defining contracts within</strong> your code as well as <strong>contracts with code outside</strong> of your project. </p>
<p>Here is an another example of an interface:</p>
<pre><code class="lang-ts"><span class="hljs-comment">// We have an interface</span>
<span class="hljs-keyword">interface</span> LabeledValue {
  label: <span class="hljs-built_in">string</span>;
}

<span class="hljs-comment">// the arg passed to this function labeledObj is </span>
<span class="hljs-comment">// of type LabeledValue (interface)</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">printLabel</span>(<span class="hljs-params">labeledObj: LabeledValue</span>) </span>{
  <span class="hljs-built_in">console</span>.log(labeledObj.label);
}

<span class="hljs-keyword">let</span> myObj = {label: <span class="hljs-string">"Size 10 Object"</span>};
printLabel(myObj);
</code></pre>
<p>Hopefully this example gives you a bit more insight into interfaces. If you want more detailed information check out the docs on <a target="_blank" href="https://www.typescriptlang.org/docs/handbook/interfaces.html">interfaces here</a>.</p>
<p>Now that our interface is ready, let's mock some data (since we don't have an actual database for this tutorial).</p>
<p>Let's create a mock list of todos first in our <code>stubs/todos.ts</code> file. Simply add the following:</p>
<pre><code class="lang-stubs/todos.ts">import { v4 } from "https://deno.land/std/uuid/mod.ts";
// interface
import Todo from '../interfaces/Todo.ts';

let todos: Todo[] = [
  {
    id: v4.generate(),
    todo: 'walk dog',
    isCompleted: true,
  },
  {
    id: v4.generate(),
    todo: 'eat food',
    isCompleted: false,
  },
];

export default todos;
</code></pre>
<ul>
<li>Two things to notice here: we add a new package and use its method <code>v4</code> by doing <code>_import_ { v4 } _from_ "https://deno.land/std/uuid/mod.ts";</code>. Then every time we use <code>v4.generate()</code> it will create a new random string of <code>id</code>.  </li>
</ul>
<p>The <code>id</code> can not be a <code>number</code>, only a <code>string</code> because in our <code>Todo</code> interface we have defined <code>id</code> as a string.</p>
<ul>
<li>The other thing to focus on here is <code>let _todos_: _Todo_[]</code> = []. This basically tells Deno that our todos array is of type <code>Todo</code> (which is awesome, our compiler now <em>automagically</em> knows that each item in our array can only have <code>{**id**: _string_, **todo**: _string_ &amp; **isCompleted**: _boolean_}</code> it will not accept any other key).</li>
</ul>
<p>If you want to learn more about <code>interfaces</code> in TypeScript check out this amazing detailed documentation on interfaces <strong><a target="_blank" href="https://www.typescriptlang.org/docs/handbook/interfaces.html">here</a>.</strong></p>
<p>Awesome. If you have come this far, give yourself a pat on the back. Good job everyone.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/download-1.jpeg" alt="Image" width="600" height="400" loading="lazy">
<em>The Rock appreciates all the effort you are doing</em></p>
<h2 id="heading-lets-work-on-our-controllers">Let's work on our controllers</h2>
<p>In your file <code>controllers/todo.ts</code>:</p>
<pre><code class="lang-controllers/todos.ts">export default {
  getAllTodos: () =&gt; {},
  createTodo: async () =&gt; {},
  getTodoById: () =&gt; {},
  updateTodoById: async () =&gt; {},
  deleteTodoById: () =&gt; {},
};
</code></pre>
<p>Let's write the controller for <code>getAllTodos</code>:</p>
<pre><code class="lang-controllers/todos.ts">// stubs
import todos from "../stubs/todos.ts";

export default {
  /**
   * @description Get all todos
   * @route GET /todos
   */
  getAllTodos: ({ response }: { response: any }) =&gt; {
    response.status = 200;
    response.body = {
      success: true,
      data: todos,
    };
  },
  createTodo: async () =&gt; {},
  getTodoById: () =&gt; {},
  updateTodoById: async () =&gt; {},
  deleteTodoById: () =&gt; {},
};
</code></pre>
<p>Before I begin on this block of code, let me explain that every controller has an argument – let's call it <code>context</code>.</p>
<p>So we can deconstruct <code>_getAllTodos_: (context) =&gt; {}</code> to:</p>
<pre><code>getAllTodos: <span class="hljs-function">(<span class="hljs-params">{ request, response, params }</span>) =&gt;</span> {}
</code></pre><p>And since we are using <code>typescript</code> we have to add type checking to all of these variables:</p>
<pre><code>getAllTodos: <span class="hljs-function">(<span class="hljs-params">
  { request, response, params }: { 
    request: any, 
    response: any, 
    params: { id: string },
  },
</span>) =&gt;</span> {}
</code></pre><p>So we have added type checks to all 3 <code>{ request, response, params }</code></p>
<ul>
<li><code>request</code> is what the user sends us (information like headers and JSON data)</li>
<li><code>response</code> is what we send the user back in the API response</li>
<li><code>params</code> is what we define in our router routes, that is:</li>
</ul>
<pre><code class="lang-ts">.get(<span class="hljs-string">"/todos/:id"</span>, <span class="hljs-function">(<span class="hljs-params">{ params}: { params: { id: <span class="hljs-built_in">string</span> } }</span>) =&gt;</span> {})
</code></pre>
<p>So the <code>:id</code> in <code>/todos/:id</code> is the param. Params are a way to get information from the URL. In this example we know that we have an <code>/:id</code> . So when the user tries to access this API (that is, <code>/todos/756</code>) <strong>756</strong> is basically the <strong>:id</strong> param. Since it is in the URL we know it is of type <code>string</code>.</p>
<p>Now that we have our basic definitions defined let's get back to our todos controller:</p>
<pre><code class="lang-controllers/todos.ts">// stubs
import todos from "../stubs/todos.ts";

export default {
  /**
   * @description Get all todos
   * @route GET /todos
   */
  getAllTodos: ({ response }: { response: any }) =&gt; {
    response.status = 200;
    response.body = {
      success: true,
      data: todos,
    };
  },
  createTodo: async () =&gt; {},
  getTodoById: () =&gt; {},
  updateTodoById: async () =&gt; {},
  deleteTodoById: () =&gt; {},
};
</code></pre>
<p>For <code>getAllTodos</code> we only need <code>response</code> . If you remember, <code>response</code> is what is needed to send data back to the user.</p>
<p>For people coming from a Node and Express background, one big thing that is different here is that we don't need to <code>return</code> the response object. Deno does this for us automatically.</p>
<p>All we have to do is set <code>response.status</code> which in this case is <code>200</code>.</p>
<p>More on response statuses <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status"><strong>here</strong></a><strong>.</strong></p>
<p>The other thing we set is the <code>response.body</code> which in this case is an object:</p>
<pre><code class="lang-ts">{
  success: <span class="hljs-literal">true</span>,
  data: todos
}
</code></pre>
<p>I will go ahead and run my server:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><blockquote>
<p><strong>Revision:</strong> The <code>---allow-net</code> property tells Deno that this app gives the user permission to access its content via the port opened up.</p>
</blockquote>
<p>Once your server is running, you can access the <code>GET /todos</code> API. I am using <code>postman</code> which is a Google Chrome extension and can be downloaded <a target="_blank" href="https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop//%40">here</a>.</p>
<p>You can use whatever rest client you like. I like using <code>postman</code> because I think it is very easy.</p>
<p>In Postman, open up a new tab. Set the request to type <code>GET</code> and in the <code>URL</code> bar type <code>http://localhost:8080/todos</code>. Hit <code>Send</code> and this is what you see:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-02.01.11.png" alt="Image" width="600" height="400" loading="lazy">
<em>GET /todos API response</em></p>
<p>Cool! 1 API done, 4 more to go. ??</p>
<p>If you feel stuck anywhere just have sneak peak at the source code directly <a target="_blank" href="https://github.com/adeelibr/deno-playground/tree/master/chapter_1:oak"><strong>here</strong></a><strong>.</strong></p>
<p>Let's move on to our next controller:</p>
<pre><code class="lang-controllers/todos.ts">import { v4 } from "https://deno.land/std/uuid/mod.ts";
// interfaces
import Todo from "../interfaces/Todo.ts";
// stubs
import todos from "../stubs/todos.ts";

export default {
  getAllTodos: () =&gt; {},
  /**
   * @description Add a new todo
   * @route POST /todos
   */
  createTodo: async (
    { request, response }: { request: any; response: any },
  ) =&gt; {
    const body = await request.body();
    if (!request.hasBody) {
      response.status = 400;
      response.body = {
        success: false,
        message: "No data provided",
      };
      return;
    }

    // if everything is fine then perform
    // operation and return todos with the
    // new data added.
    let newTodo: Todo = {
      id: v4.generate(),
      todo: body.value.todo,
      isCompleted: false,
    };
    let data = [...todos, newTodo];
    response.body = {
      success: true,
      data,
    };
  },
  getTodoById: () =&gt; {},
  updateTodoById: async () =&gt; {},
  deleteTodoById: () =&gt; {},
};
</code></pre>
<p>Since we are going to be adding a new Todo to our list, I have imported 2 modules in the controller file.</p>
<ul>
<li><code>import { v4 } from</code><a target="_blank" href="https://deno.land/std/uuid/mod.ts">https://deno.land/std/uuid/mod.ts</a><code>;</code> this will be used to create a new unique one for the todo being created</li>
<li><code>import Todo from "../interfaces/Todo.ts";</code> this will be used to ensure that the new todo that is being created follows the same structure.</li>
</ul>
<p>Our <code>createTodo</code> controller is <code>async</code> meaning there are some promises used inside the controller. </p>
<p>Let's break it into smaller parts:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">const</span> body = <span class="hljs-keyword">await</span> request.body();
<span class="hljs-keyword">if</span> (!request.hasBody) {
      response.status = <span class="hljs-number">400</span>;
      response.body = {
        success: <span class="hljs-literal">false</span>,
        message: <span class="hljs-string">"No data provided"</span>,
      };
      <span class="hljs-keyword">return</span>;
}
</code></pre>
<p>First we get the content of the JSON body that the user has sent us. Then we use <code>oak's</code> built-in method called <code>request.hasBody</code> to check if the user has even sent any content. If not then we can do <code>if (!request_._hasBody) {}</code> inside this <code>if</code> block. </p>
<p>We set the status to <code>400</code> (400 means that the user did something they were not suppose to do) and the body is set to <code>{success: false, message: "no data provided }</code>. Then we simple add <code>return;</code> to ensure that no further code below is executed.</p>
<p>Next we do this:</p>
<pre><code><span class="hljs-comment">// if everything is fine then perform</span>
<span class="hljs-comment">// operation and return todos with the</span>
<span class="hljs-comment">// new data added.</span>
<span class="hljs-keyword">let</span> newTodo: Todo = {
  <span class="hljs-attr">id</span>: v4.generate(),
  <span class="hljs-attr">todo</span>: body.value.todo,
  <span class="hljs-attr">isCompleted</span>: <span class="hljs-literal">false</span>,
};
<span class="hljs-keyword">let</span> data = [...todos, newTodo];
response.body = {
  <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span>,
  data,
};
</code></pre><p>We create a new todo by doing this:</p>
<pre><code><span class="hljs-keyword">let</span> newTodo: Todo = {
  <span class="hljs-attr">id</span>: v4.generate(),
  <span class="hljs-attr">todo</span>: body.value.todo,
  <span class="hljs-attr">isCompleted</span>: <span class="hljs-literal">false</span>,
};
</code></pre><p><code>let newTodo: Todo = {}</code> ensures that <code>newTodo</code> follows the same structure as the rest of the todos. We then assign a random id by using <code>v4.generate()</code>, set todo to <code>body.value.todo</code> and <code>isCompleted</code> to  <code>false</code>.</p>
<p>The thing to notice here is all the data the user sends us we can access from <code>body.value</code> in <code>oak</code>.</p>
<p>Next we do the following:</p>
<pre><code><span class="hljs-keyword">let</span> data = [...todos, newTodo];
response.body = {
  <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span>,
  data,
};
</code></pre><p>Append the <code>newTodo</code> to our current list of todos and simply set the body to <code>{success: true &amp; data: data</code>.</p>
<p>And we are done ✅ with this controller as well.</p>
<p>Let's restart our server:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>In my postman, I open up a new tab. Set the request to <code>POST</code> type and in the <code>URL</code> bar type <code>http://localhost:8080/todos</code>. Then hit <code>Send</code> and this is what you see:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-02.24.00.png" alt="Image" width="600" height="400" loading="lazy">
<em>I send an empty request and get a 400 status error code along with an error message</em></p>
<p>Then I send some content in the body of the request payload and try again:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-02.24.15.png" alt="Image" width="600" height="400" loading="lazy">
<em>Awesome, POST /todos with body content { todo: "eat a lamma" } is success &amp; we can see content appended to our current todo list</em></p>
<p>Cool, we can see that our API is working as expected.</p>
<p>Two APIs down, three more to go. </p>
<p>We are almost there. Most of the hard work is done. ☺️ ? ? ?</p>
<p>Let's move on to our third API:</p>
<pre><code class="lang-controllers/todos.ts">import { v4 } from "https://deno.land/std/uuid/mod.ts";
// interfaces
import Todo from "../interfaces/Todo.ts";
// stubs
import todos from "../stubs/todos.ts";

export default {
  getAllTodos: () =&gt; {},
  createTodo: async () =&gt; {},
  /**
   * @description Get todo by id
   * @route GET todos/:id
   */
  getTodoById: (
    { params, response }: { params: { id: string }; response: any },
  ) =&gt; {
    const todo: Todo | undefined = todos.find((t) =&gt; {
      return t.id === params.id;
    });
    if (!todo) {
      response.status = 404;
      response.body = {
        success: false,
        message: "No todo found",
      };
      return;
    }

    // If todo is found
    response.status = 200;
    response.body = {
      success: true,
      data: todo,
    };
  },
  updateTodoById: async () =&gt; {},
  deleteTodoById: () =&gt; {},
};
</code></pre>
<p>Let's talk about our controller for <code>GET todos/:id</code>. This will get us a todo by ID.</p>
<p>Let's break this down into smaller parts and discuss it:</p>
<pre><code><span class="hljs-keyword">const</span> todo: Todo | <span class="hljs-literal">undefined</span> = todos.find(<span class="hljs-function">(<span class="hljs-params">t</span>) =&gt;</span> t.id === params.id);
<span class="hljs-keyword">if</span> (!todo) {
  response.status = <span class="hljs-number">404</span>;
  response.body = {
    <span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">message</span>: <span class="hljs-string">"No todo found"</span>,
  };
  <span class="hljs-keyword">return</span>;
}
</code></pre><p>In the first part we set a new <code>const todo</code> and set its type to either <code>Todo</code> or <code>undefined</code>. So <code>todo</code> will either be an object with the <code>Todo</code> interface shape or it will be <code>undefined</code> – it can not be anything else.</p>
<p>We then <code>_todos.find_((_t_)</code> =&gt; <em>t.id</em> === <em>params.id</em>); use <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find">Array.find()</a> to find the <code>todo</code> with the id provided in <code>params.id</code>. If it matches we get a <code>Todo</code> with shape <code>todo</code>, otherwise <code>undefined</code>.</p>
<p>If <code>todo</code> is undefined, it means that this <code>if</code> block will run:</p>
<pre><code><span class="hljs-keyword">if</span> (!todo) {
  response.status = <span class="hljs-number">404</span>;
  response.body = {
    <span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">message</span>: <span class="hljs-string">"No todo found"</span>,
  };
  <span class="hljs-keyword">return</span>;
}
</code></pre><p>Here we simply set the status to <code>404</code> which means <code>not found</code> along with our standard failure response or <code>{ status, message }</code></p>
<p>Cool, right? ?</p>
<p>Next we simply do this:</p>
<pre><code><span class="hljs-comment">// If todo is found</span>
response.status = <span class="hljs-number">200</span>;
response.body = {
  <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">data</span>: todo,
};
</code></pre><p>Set a <code>200</code> success response and in our response body we set <code>success: true &amp; data: todo</code>.</p>
<p>Let's run this in our postman.</p>
<p>Let's restart our server:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>In my postman, I open up a new tab. Set the request to <code>GET</code> type and in the <code>URL</code> bar type <code>http://localhost:8080/todos/:id</code>, then hit <code>Send</code>.</p>
<p>Since we are generating ID's randomly, first get all todos by hitting theget all todos API. Then from any todo get one of its ID to test this newly created API.<br>Every time you restart this Deno application, new ID's will be generated.</p>
<p>Let's go:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-02.40.52.png" alt="Image" width="600" height="400" loading="lazy">
<em>404 status, no record found case</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-02.41.36.png" alt="Image" width="600" height="400" loading="lazy">
<em>Provided it a known ID and it returned the todo associated with that ID along with status 200</em></p>
<p>If you need to reference the original source code of this tutorial go <a target="_blank" href="https://github.com/adeelibr/deno-playground/tree/master/chapter_1:oak"><strong>here</strong></a>.</p>
<p>Great, 3 APIs done, 2 more to go.</p>
<pre><code class="lang-controllers/todos.ts">import { v4 } from "https://deno.land/std/uuid/mod.ts";
// interfaces
import Todo from "../interfaces/Todo.ts";
// stubs
import todos from "../stubs/todos.ts";

export default {
  getAllTodos: () =&gt; {},
  createTodo: async () =&gt; {},
  getTodoById: () =&gt; {},
  /**
   * @description Update todo by id
   * @route PUT todos/:id
   */
  updateTodoById: async (
    { params, request, response }: {
      params: { id: string },
      request: any,
      response: any,
    },
  ) =&gt; {
    const todo: Todo | undefined = todos.find((t) =&gt; t.id === params.id);
    if (!todo) {
      response.status = 404;
      response.body = {
        success: false,
        message: "No todo found",
      };
      return;
    }

    // if todo found then update todo
    const body = await request.body();
    const updatedData: { todo?: string; isCompleted?: boolean } = body.value;
    let newTodos = todos.map((t) =&gt; {
      return t.id === params.id ? { ...t, ...updatedData } : t;
    });
    response.status = 200;
    response.body = {
      success: true,
      data: newTodos,
    };
  },
  deleteTodoById: () =&gt; {},
};
</code></pre>
<p>Let's talk about our controller for <code>PUT todos/:id</code>. This will update a todo by ID.</p>
<p>Let's break this down into smaller bits:</p>
<pre><code><span class="hljs-keyword">const</span> todo: Todo | <span class="hljs-literal">undefined</span> = todos.find(<span class="hljs-function">(<span class="hljs-params">t</span>) =&gt;</span> t.id === params.id);
<span class="hljs-keyword">if</span> (!todo) {
  response.status = <span class="hljs-number">404</span>;
  response.body = {
    <span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">message</span>: <span class="hljs-string">"No todo found"</span>,
  };
  <span class="hljs-keyword">return</span>;
}
</code></pre><p>This is something we did exactly the same with the previous controller as well, so I won't go into much detail here.</p>
<p>Pro tip here: You can if you want make this piece of code a generic code block and then use it in both controllers.</p>
<p>Next we do this:</p>
<pre><code><span class="hljs-comment">// if todo found then update todo</span>
<span class="hljs-keyword">const</span> body = <span class="hljs-keyword">await</span> request.body();
<span class="hljs-keyword">const</span> updatedData: { todo?: string; isCompleted?: boolean } = body.value;
<span class="hljs-keyword">let</span> newTodos = todos.map(<span class="hljs-function">(<span class="hljs-params">t</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> t.id === params.id ? { ...t, ...updatedData } : t;
});
response.status = <span class="hljs-number">200</span>;
response.body = {
  <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">data</span>: newTodos,
};
</code></pre><p>The piece of code I want to talk about here is the following:</p>
<pre><code><span class="hljs-keyword">const</span> updatedData: { todo?: string; isCompleted?: boolean } = body.value;
<span class="hljs-keyword">let</span> newTodos = todos.map(<span class="hljs-function">(<span class="hljs-params">t</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> t.id === params.id ? { ...t, ...updatedData } : t;
});
</code></pre><p>First we do <code>const updatedData = body.value</code> and then add type checking to <code>updatedData</code> like the following:</p>
<pre><code>updatedData: { todo?: string; isCompleted?: boolean }
</code></pre><p>This piece of code is telling TS that <code>updatedData</code> is an object which can <code>have/not have</code> <em>todo: string and</em> also can <code>have/not have</code> <em>isCompleted: boolean.</em></p>
<p>Then we simply map over all todos like this:</p>
<pre><code><span class="hljs-keyword">let</span> newTodos = todos.map(<span class="hljs-function">(<span class="hljs-params">t</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> t.id === params.id ? { ...t, ...updatedData } : t;
});
</code></pre><p>And where <code>params.id</code> match with <code>t.id</code> we simply append everything to that object we get from the user.</p>
<p>We are done with this API as well. </p>
<p>Let's restart our server:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>Open up a new tab in Postman. Set the request to <code>PUT</code> and in the <code>URL</code> bar type in <code>http://localhost:8080/todos/:id</code>, then hit <code>Send</code>:</p>
<p>Since we are generating ID's randomly,  first get all todos by hitting get all todos API. Then from any todo get one of its ID to test this newly created API.<br>Every time you restart this Deno application, new ID's will be generated.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-02.59.39.png" alt="Image" width="600" height="400" loading="lazy">
<em>404 status returned and no todo found error message given</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-03.00.21.png" alt="Image" width="600" height="400" loading="lazy">
<em>Provided a known ID, updated todo content in body. It returned the updated todo along with all the other todos</em></p>
<p>This is amazing – four APIs done and just one more to go.</p>
<pre><code class="lang-controllers/todos.ts">import { v4 } from "https://deno.land/std/uuid/mod.ts";
// interfaces
import Todo from "../interfaces/Todo.ts";
// stubs
import todos from "../stubs/todos.ts";

export default {
  getAllTodos: () =&gt; {},
  createTodo: async () =&gt; {},
  getTodoById: () =&gt; {},
  updateTodoById: async () =&gt; {},
  /**
   * @description Delete todo by id
   * @route DELETE todos/:id
   */
  deleteTodoById: (
    { params, response }: { params: { id: string }; response: any },
  ) =&gt; {
    const allTodos = todos.filter((t) =&gt; t.id !== params.id);

    // remove the todo w.r.t id and return
    // remaining todos
    response.status = 200;
    response.body = {
      success: true,
      data: allTodos,
    };
  },
};
</code></pre>
<p>Let's talk about our controller for <code>Delete todos/:id</code> this will delete a todo by ID.</p>
<p>We simply run a filter on all todos:</p>
<pre><code><span class="hljs-keyword">const</span> allTodos = todos.filter(<span class="hljs-function">(<span class="hljs-params">t</span>) =&gt;</span> t.id !== params.id);
</code></pre><p>Remove the <code>todo.id</code> that matches with <code>params.id</code> and return the rest.</p>
<p>Then we do this:</p>
<pre><code><span class="hljs-comment">// remove the todo w.r.t id and return</span>
<span class="hljs-comment">// remaining todos</span>
response.status = <span class="hljs-number">200</span>;
response.body = {
  <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">data</span>: allTodos,
};
</code></pre><p>Simply return all the todos left which do not have the same todo.id.</p>
<p>Let's restart our server:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>Open up a new tab in Postman. This time set the request to <code>DELETE</code> and in the <code>URL</code> bar type <code>http://localhost:8080/todos/:id</code> and hit <code>Send</code>.</p>
<p>Since we are generating ID's randomly,  first get all todos by hitting get all todos API. Then from any todo get one of its ID to test this newly created API.<br>Every time you restart this Deno application, new ID's will be generated.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-03.07.54.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>With this we are all done with all five APIs.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/75bdf06df3fd6ddd9d3311d8cb2be029.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<hr>
<p>Now we only have two things remaining:</p>
<ul>
<li>Add a not found route middleware so that when the user tries to access an unknown route it gives an error.</li>
<li>Add a logger API that consoles the response time it took to return data from one API endpoint.</li>
</ul>
<h2 id="heading-creating-a-route-middleware-for-routes-that-arent-found">Creating a route middleware for routes that aren't found</h2>
<p>In your root folder create a new folder called <code>middlewares</code>. Inside that folder create a file called <code>notFound.ts</code> and inside this file add this code:</p>
<pre><code class="lang-middlwares/notfound.ts">export default ({ response }: { response: any }) =&gt; {
  response.status = 404;
  response.body = {
    success: false,
    message: "404 - Not found.",
  };
};
</code></pre>
<p>Here we aren't doing anything new – it is very similar to our controllers structure. Just returning a status <code>404</code> (which means not found) along with a JSON object for <code>{ success, message }</code>.</p>
<p>Next go in your <code>server.ts</code> file and add the following content:</p>
<ul>
<li>Add this import somewhere at the top:</li>
</ul>
<pre><code class="lang-server.ts">// not found
import notFound from './middlewares/notFound.ts';
</code></pre>
<ul>
<li>And then just below your <code>app.use(todoRouter.allowedMethods())</code> add this line like this:</li>
</ul>
<pre><code class="lang-server.ts">app.use(todoRouter.routes());
app.use(todoRouter.allowedMethods());

// 404 page
app.use(notFound);
</code></pre>
<p>The order of execution is important here: every time we try to access an API end point it will first match/check routes from our <code>todoRouter</code>. If none are found, it will then execute <code>app_.use_(notFound);</code>. </p>
<p>Let's see if this works.</p>
<p>Restart the server:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>Open up a new tab in Postman. Set the request to <code>GET</code> and in the <code>URL</code> bar type <code>http://localhost:8080/something-unknown</code>, then hit <code>Send</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-12.28.10.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>So we now have a route middleware that we put at the end of our routes in <code>server.ts</code> as <code>app_.use_(notFound);</code>. If no route matches this middleware it will execute and return a <code>404</code> status code (which means not found). Then we simply send a response message like always which is <code>{success, message}</code>.</p>
<p><strong>Pro tip:</strong> We have decided that <code>{success, message}</code> is what we return in failed scenarios and <code>{success, data}</code> is what we return to user in success scenarios. So we can even make these to object/shapes as interfaces and add them to our project to ensure consistency and safe type checking.</p>
<p>Cool, now we are done with one of our middlewares – let's add the other middleware for logging our APIs in the console.</p>
<p><strong>Reminder:</strong> If you get stuck anywhere you can use the <a target="_blank" href="https://github.com/adeelibr/deno-playground/tree/master/chapter_1:oak">source code here</a>.</p>
<h2 id="heading-logging-apis-in-console">Logging APIs in console</h2>
<p>In your <code>middlewares</code> folder create a new file called <code>logger.ts</code> and enter the following code:</p>
<pre><code class="lang-middlewares/logger.ts">import {
  green,
  cyan,
  white,
  bgRed,
} from "https://deno.land/std@0.53.0/fmt/colors.ts";

const X_RESPONSE_TIME: string = "X-Response-Time";

export default {
  logger: async (
    { response, request }: { response: any, request: any },
    next: Function,
  ) =&gt; {
    await next();
    const responseTime = response.headers.get(X_RESPONSE_TIME);
    console.log(`${green(request.method)} ${cyan(request.url.pathname)}`);
    console.log(`${bgRed(white(String(responseTime)))}`);
  },
  responseTime: async (
    { response }: { response: any },
    next: Function,
  ) =&gt; {
    const start = Date.now();
    await next();
    const ms: number = Date.now() - start;
    response.headers.set(X_RESPONSE_TIME, `${ms}ms`)
  },
};
</code></pre>
<p>In your <code>server.ts</code> file add this code:</p>
<ul>
<li>Import this somewhere at the top:</li>
</ul>
<pre><code class="lang-server.ts">// logger
import logger from './middlewares/logger.ts';
</code></pre>
<ul>
<li>Just above your <code>todoRouter</code> code add these middlewares like this:</li>
</ul>
<pre><code><span class="hljs-comment">// order of execution is important;</span>
app.use(logger.logger);
app.use(logger.responseTime);

app.use(todoRouter.routes());
app.use(todoRouter.allowedMethods());
</code></pre><p>Now let's discuss what we just did.</p>
<p>Let's talk about the <code>logger.ts</code> file and break it down into bits:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> {
  green,
  cyan,
  white,
  bgRed,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"https://deno.land/std@0.53.0/fmt/colors.ts"</span>;
</code></pre>
<p>I am importing some console colors and console background colors that I want to use in API logging.</p>
<p>This is similar to what we did in our <code>eventListener</code> in our <code>server.ts</code> file. We will use colors in our console to log API requests.</p>
<p>Next I set <code>const X_RESPONSE_TIME: string = "X-Response-Time";</code>. This is the header we will inject in our API requests as they come into our server. I am calling this <code>X_RESPONSE_TIME</code> and its value is <code>X-Response-Time</code>. I will demonstrate its usage in a bit.</p>
<p>Next we simply export an object like this:</p>
<pre><code class="lang-middlewares/logger.ts">export default {
    logger: async ({ response, request }, next) {}
    responseTime: async ({ response }, next) {}
};
</code></pre>
<p>And then we simply use it inside our <code>server.ts</code> file like this:</p>
<pre><code class="lang-server.ts">// order of execution is important;
app.use(logger.logger);
app.use(logger.responseTime);
</code></pre>
<p>Let's now discuss what is happening in our logger middleware code and discuss it execution style using <code>next()</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-12.51.36.png" alt="Image" width="600" height="400" loading="lazy">
<em>Execution of order of logging middleware when GET /todos API is called.</em></p>
<p>The only difference here and in the controllers we had before is the use of the <code>next()</code> function. This functions helps us jump from one controller to the other as shown in the image below.</p>
<p>So in:</p>
<pre><code class="lang-middlewares/logger.ts">export default {
  logger: async (
    { response, request }: { response: any, request: any },
    next: Function,
  ) =&gt; {
    await next();
    const responseTime = response.headers.get(X_RESPONSE_TIME);
    console.log(`${green(request.method)} ${cyan(request.url.pathname)}`);
    console.log(`${bgRed(white(String(responseTime)))}`);
  },
  responseTime: async (
    { response }: { response: any },
    next: Function,
  ) =&gt; {
    const start = Date.now();
    await next();
    const ms: number = Date.now() - start;
    response.headers.set(X_RESPONSE_TIME, `${ms}ms`)
  },
};
</code></pre>
<p>Keep in mind that this is what we have in our <code>server.ts</code> file:</p>
<pre><code class="lang-server.ts">// order of execution is important;
app.use(logger.logger);
app.use(logger.responseTime);

app.use(todoRouter.routes());
app.use(todoRouter.allowedMethods());
</code></pre>
<p>The order of execution is as follows:</p>
<ul>
<li>logger.logger middleware</li>
<li>logger.responseTime middleware</li>
<li>todoRouter controller (whatever path is called by the user, for the purpose of explanation I am assuming that the user called <code>GET /todos</code> API to get all todos.)</li>
</ul>
<p>So it will first execute logger.logger middleware which is this:</p>
<pre><code class="lang-middlewares/logger.ts">logger: async (
    { response, request }: { response: any, request: any },
    next: Function,
  ) =&gt; {
    await next();
    const responseTime = response.headers.get(X_RESPONSE_TIME);
    console.log(`${green(request.method)} ${cyan(request.url.pathname)}`);
    console.log(`${bgRed(white(String(responseTime)))}`);
  },
</code></pre>
<p>It will come inside this function and immediately as it reads <code>await next()</code> it quickly jumps to the next middleware which is <code>responseTime</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-12.51.36-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Sharing the image above again for revision.</em></p>
<p>Inside <code>responseTime</code>, it only executes two lines which are (look at execution order 2 in image above):</p>
<pre><code class="lang-middlewares/logger.ts">const start = Date.now();
await next();
</code></pre>
<p>before jumping to the <code>getAllTodos</code> controller. Once it goes inside <code>getAllTodos</code> it will run the entire code inside that controller. </p>
<p>Since in that controller we are not using <code>next()</code> it will simply return the flow of logic back to <code>responseTime</code> controller. There it will run the following:</p>
<pre><code class="lang-middlewares/logger.ts">const ms: number = Date.now() - start;
response.headers.set(X_RESPONSE_TIME, `${ms}ms`)
</code></pre>
<p>Now keeping in perspective of the order of execution which is <code>2, 3, 4</code> (look at the image above).</p>
<p>This is what happens:</p>
<ul>
<li>We capture the data in <code>ms</code> by doing <code>const</code> <em><code>start</code></em> <code>=</code> <em><code>Date.now</code></em><code>();</code>. Then we immediately call <code>next()</code> which goes to <code>getAllTodos</code> controller and runs the entire code. Then it comes back in the <code>responseTime</code> controller.</li>
<li>We then subtract that <code>start</code> date with whatever the date is at that moment by doing <code>const _ms_: _number_ = _Date.now_()</code> - <em>start</em>; <code>ms</code>. Here it will return a number which is basically the difference in milliseconds that will tell us all the time it took Deno to execute our <code>getAllTodos</code> controller.</li>
</ul>
<p>Sharing the image once again for review:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-12.51.36-2.png" alt="Image" width="600" height="400" loading="lazy"></p>
<ul>
<li>Next we simply set headers in our <code>response</code> like this:</li>
</ul>
<pre><code>response.headers.set(X_RESPONSE_TIME, <span class="hljs-string">`<span class="hljs-subst">${ms}</span>ms`</span>)
</code></pre><p>Which just sets the header value <code>X-Response-Time</code> to the milliseconds it took Deno to execute our API.</p>
<ul>
<li>Then from execution order <code>4</code> we move back to execution order <code>5</code> (have a look at the image above for reference).</li>
</ul>
<p>Here we simply do:</p>
<pre><code class="lang-middlwares/logger.ts">const responseTime = response.headers.get(X_RESPONSE_TIME);
console.log(`${green(request.method)} ${cyan(request.url.pathname)}`);
console.log(`${bgRed(white(String(responseTime)))}`);
</code></pre>
<ul>
<li>We get the time we passed in the <code>X-Response-Time</code></li>
<li>Then we take that time and simply console it colourfully in the console.</li>
</ul>
<p><code>request.method</code> tells us the method used to call our API, that is  <code>GET, PUT etc</code> while <code>request.url.pathname</code> will tell the API which path the user used i.e, <code>/todos</code></p>
<p>Let's see if this works.</p>
<p>Restart the server:</p>
<pre><code>$ deno run --allow-net server.ts
</code></pre><p>Open up a new tab in Postman. Set the request to <code>GET</code>, type in <code>http://localhost:8080/todos</code>, and hit <code>Send</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-13.17.13.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Hit the API a couple of times in Postman. Then when you go back to the console, you should see something like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screenshot-2020-05-29-at-13.21.03.png" alt="Image" width="600" height="400" loading="lazy">
<em>API being logged in our console</em></p>
<p>This is it – we are done.</p>
<p>If you still feel stuck, take a look at the entire source code for this tutorial here: <a target="_blank" href="https://github.com/adeelibr/deno-playground/tree/master/chapter_1:oak">github.com/adeelibr/deno-playground/tree/master/chapter_1:oak</a></p>
<p>I hope that you found this article useful and that it was able to help you learn something today.</p>
<p>If you liked it, please do share it on social media. If you want to have a discussion about it, reach out to me on <a target="_blank" href="https://twitter.com/adeelibr">Twitter</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The Deno Handbook – A TypeScript Runtime Tutorial with Code Examples ]]>
                </title>
                <description>
                    <![CDATA[ I explore new projects every week, and it’s rare that one grabs my attention as much as Deno did. In this post I want to get you up to speed with Deno quickly. We'll compare it with Node.js, and build your first REST API with it. Table of contents W... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/the-deno-handbook/</link>
                <guid isPermaLink="false">66bb5aa3965d5c9ed5487bb4</guid>
                
                    <category>
                        <![CDATA[ Deno ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Flavio Copes ]]>
                </dc:creator>
                <pubDate>Tue, 12 May 2020 12:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-11-at-18.55.24.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>I explore new projects every week, and it’s rare that one grabs my attention as much as <a target="_blank" href="https://deno.land/">Deno</a> did.</p>
<p>In this post I want to get you up to speed with Deno quickly. We'll compare it with Node.js, and build your first REST API with it.</p>
<h2 id="heading-table-of-contents">Table of contents</h2>
<ul>
<li><a class="post-section-overview" href="#heading-what-is-deno">What is Deno?</a></li>
<li><a class="post-section-overview" href="#heading-why-deno-why-now">Why Deno? Why now?</a></li>
<li><a class="post-section-overview" href="#heading-should-you-learn-deno">Should you learn Deno?</a></li>
<li><a class="post-section-overview" href="#heading-will-it-replace-nodejs">Will it replace Node.js?</a></li>
<li><a class="post-section-overview" href="#heading-first-class-typescript-support">First-class TypeScript support</a></li>
<li><a class="post-section-overview" href="#heading-similarities-and-differences-with-nodejs">Similarities and differences with Node.js</a></li>
<li><a class="post-section-overview" href="#heading-no-package-manager">No package manager</a></li>
<li><a class="post-section-overview" href="#heading-install-deno">Install Deno</a></li>
<li><a class="post-section-overview" href="#heading-the-deno-commands">The Deno commands</a></li>
<li><a class="post-section-overview" href="#heading-your-first-deno-app">Your first Deno app</a></li>
<li><a class="post-section-overview" href="#heading-deno-code-examples">Deno code examples</a></li>
<li><a class="post-section-overview" href="#heading-your-first-deno-app-for-real">Your first Deno app (for real)</a></li>
<li><a class="post-section-overview" href="#heading-the-deno-sandbox">The Deno sandbox</a></li>
<li><a class="post-section-overview" href="#heading-formatting-code">Formatting code</a></li>
<li><a class="post-section-overview" href="#heading-the-standard-library">The standard library</a></li>
<li><a class="post-section-overview" href="#heading-another-deno-example">Another Deno example</a></li>
<li><a class="post-section-overview" href="#heading-is-there-an-expresshapikoa-for-deno">Is there an Express/Hapi/Koa/* for Deno?</a></li>
<li><a class="post-section-overview" href="#heading-example-use-oak-to-build-a-rest-api">Example: use Oak to build a REST API</a></li>
<li><a class="post-section-overview" href="#heading-find-out-more">Find out more</a></li>
<li><a class="post-section-overview" href="#heading-a-few-more-random-tidbits">A few more random tidbits</a></li>
</ul>
<p>And note: <a target="_blank" href="https://flaviocopes.com/page/deno-handbook/">You can get a PDF/ePub/Mobi version of this Deno Handbook here</a>.</p>
<h2 id="heading-what-is-deno">What is Deno?</h2>
<p>If you are familiar with Node.js, the popular server-side JavaScript ecosystem, then Deno is just like Node. Except deeply improved in many ways.</p>
<p>Let’s start from a quick list of the features I like the most about Deno:</p>
<ul>
<li>It is based on modern features of the JavaScript language</li>
<li>It has an extensive standard library</li>
<li>It has TypeScript at its core, which brings a huge advantage in many different ways, including a first-class TypeScript support (you don’t have to separately compile TypeScript, it’s automatically done by Deno)</li>
<li>It embraces <a target="_blank" href="https://flaviocopes.com/es-modules/">ES modules</a></li>
<li>It has no package manager</li>
<li>It has a first-class <code>await</code></li>
<li>It has a built-in testing facility</li>
<li>It aims to be browser-compatible as much as it can, for example by providing a built-in <code>fetch</code> and the global <code>window</code> object</li>
</ul>
<p>We’ll explore all of those features in this guide.</p>
<p>After you use Deno and learn to appreciate its features, Node.js will look like something <em>old</em>.</p>
<p>Especially because the Node.js API is callback-based, as it was written way before promises and async/await. There’s no change available for that in Node, because such a change would be monumental. So we’re stuck with callbacks or with promisifying API calls.</p>
<p>Node.js is <strong>awesome</strong> and will continue to be the de facto standard in the JavaScript world. But I think we’ll gradually see Deno get adopted more and more because of its first-class TypeScript support and modern standard library.</p>
<p>Deno can afford to have everything written with modern technologies, since there’s no backward compatibility to maintain. Of course there’s no guarantee that in a decade the same will happen to Deno and a new technology will emerge, but this is the reality at the moment.</p>
<h2 id="heading-why-deno-why-now">Why Deno? Why now?</h2>
<p>Deno was announced almost 2 years ago by the original creator of Node.js, Ryan Dahl, at JSConf EU. Watch <a target="_blank" href="https://www.youtube.com/watch?v=M3BM9TB-8yA">the YouTube video of the talk</a>, it’s very interesting and it’s a mandatory watch if you are involved in Node.js and JavaScript in general.</p>
<p>Every project manager must make decisions. Ryan regretted some early decisions in Node. Also, technology evolves, and today JavaScript is a totally different language than what it was back in 2009 when Node started. Think about the modern ES6/2016/2017 features, and so on.</p>
<p>So he started a new project to create some sort of second wave of JavaScript-powered server side apps.</p>
<p>The reason I am writing this guide now and not back then is because technologies need a lot of time to mature. And we have finally reached <strong>Deno 1.0</strong> (1.0 should be released on May 13, 2020), the first release of Deno officially declared stable.</p>
<p>That’s might seem to be just a number, but 1.0 means there will not be major breaking changes until Deno 2.0. This is a big deal when you dive into a new technology - you don’t want to learn something and then have it change too fast.</p>
<h2 id="heading-should-you-learn-deno">Should you learn Deno?</h2>
<p>That’s a big question.</p>
<p>Learning something new such as Deno is a big effort. My suggestion is that if you are starting out now with server-side JS and you don’t know Node yet, and have never written any TypeScript, I’d start with Node.</p>
<p>No one was ever fired for choosing Node.js (paraphrasing a common quote).</p>
<p>But if you love TypeScript, don’t depend on a gazillion npm packages in your projects and you want to use <code>await</code> anywhere, hey Deno might be what you’re looking for.</p>
<h2 id="heading-will-it-replace-nodejs">Will it replace Node.js?</h2>
<p>No. Node.js is a giant, well established, incredibly well-supported technology that is going to stay around for decades.</p>
<h2 id="heading-first-class-typescript-support">First-class TypeScript support</h2>
<p>Deno is written in Rust and TypeScript, two of the languages that are really growing fast today.</p>
<p>In particular, being written in TypeScript means we get a lot of the benefits of TypeScript even if we might choose to write our code in plain JavaScript.</p>
<p>And running TypeScript code with Deno does not require a compilation step - Deno does that automatically for you.</p>
<p>You are not forced to write in TypeScript, but the fact the core of Deno is written in TypeScript is huge.</p>
<p>First, an increasingly large percentage of JavaScript programmers love TypeScript.</p>
<p>Second, the tools you use can infer many information about software written in TypeScript, like Deno.</p>
<p>This means that when we code in VS Code, for example (which of course has a tight integration with TypeScript since both are developed at MicroSoft), we can get benefits like type checking as we write our code, and advanced <a target="_blank" href="https://code.visualstudio.com/docs/editor/intellisense">IntelliSense</a> features. In other words the editor can help us in a deeply useful way.</p>
<h2 id="heading-similarities-and-differences-with-nodejs">Similarities and differences with Node.js</h2>
<p>Since Deno is basically a Node.js replacement, it’s useful to compare the two directly.</p>
<p>Similarities:</p>
<ul>
<li>Both are developed upon the <a target="_blank" href="https://flaviocopes.com/v8/">V8 Chromium Engine</a></li>
<li>Both are great for developing server-side with JavaScript</li>
</ul>
<p>Differences:</p>
<ul>
<li>Node is written in C++ and JavaScript. Deno is written in Rust and TypeScript.</li>
<li>Node has an official package manager called <code>npm</code>. Deno does not, and instead lets you import any ES Module from URLs.</li>
<li>Node uses the CommonJS syntax for importing pacakges. Deno uses ES Modules, the official way.</li>
<li>Deno uses modern ECMAScript features in all its API and standard library, while Node.js uses a callbacks-based standard library and has no plans to upgrade it.</li>
<li>Deno offers a sandbox security layer through permissions. A program can only access the permissions set to the executable as flags by the user. A Node.js program can access anything the user can access.</li>
<li>Deno has for a long time envisioned the possibility of compiling a program into an executable that you can run without external dependencies, like Go, but <a target="_blank" href="https://github.com/denoland/deno/issues/986">it’s still not a thing yet</a>. That’d be a game changer.</li>
</ul>
<h2 id="heading-no-package-manager">No package manager</h2>
<p>Having no package manager and having to rely on URLs to host and import packages has pros and cons. I really like the pros: it’s very flexible, and we can create packages without publishing them on a repository like npm.</p>
<p>I think that some sort of package manager will emerge, but nothing official is out yet.</p>
<p>The Deno website provides code hosting (and thus distribution through URLs) to 3rd party packages: <a target="_blank" href="https://deno.land/x/">https://deno.land/x/</a></p>
<h2 id="heading-install-deno">Install Deno</h2>
<p>Enough talk! Let’s install Deno.</p>
<p>The easiest way is to use <a target="_blank" href="https://flaviocopes.com/homebrew/">Homebrew</a>:</p>
<pre><code class="lang-sh">brew install deno
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-09-at-12.04.45.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Once this is done, you will have access to the <code>deno</code> command. Here’s the help that you can get using <code>deno --help</code>:</p>
<pre><code>flavio@mbp~&gt; deno --help
deno <span class="hljs-number">0.42</span><span class="hljs-number">.0</span>
A secure JavaScript and TypeScript runtime

<span class="hljs-attr">Docs</span>: https:<span class="hljs-comment">//deno.land/std/manual.md</span>
Modules: https:<span class="hljs-comment">//deno.land/std/ https://deno.land/x/</span>
Bugs: https:<span class="hljs-comment">//github.com/denoland/deno/issues</span>

To start the REPL, supply no <span class="hljs-built_in">arguments</span>:
  deno

To execute a script:
  deno run https:<span class="hljs-comment">//deno.land/std/examples/welcome.ts</span>
  deno https:<span class="hljs-comment">//deno.land/std/examples/welcome.ts</span>

To evaluate code <span class="hljs-keyword">in</span> the shell:
  deno <span class="hljs-built_in">eval</span> <span class="hljs-string">"console.log(30933 + 404)"</span>

Run <span class="hljs-string">'deno help run'</span> <span class="hljs-keyword">for</span> <span class="hljs-string">'run'</span>-specific flags.

USAGE:
    deno [OPTIONS] [SUBCOMMAND]

<span class="hljs-attr">OPTIONS</span>:
    -h, --help
            Prints help information

    -L, --log-level &lt;log-level&gt;
            <span class="hljs-built_in">Set</span> log level [possible values: debug, info]

    -q, --quiet
            Suppress diagnostic output
            By <span class="hljs-keyword">default</span>, subcommands print human-readable diagnostic messages to stderr.
            If the flag is set, restrict these messages to errors.
    -V, --version
            Prints version information


<span class="hljs-attr">SUBCOMMANDS</span>:
    bundle         Bundle <span class="hljs-built_in">module</span> and dependencies into single file
    cache          Cache the dependencies
    completions    Generate shell completions
    doc            Show documentation <span class="hljs-keyword">for</span> a <span class="hljs-built_in">module</span>
    <span class="hljs-built_in">eval</span>           Eval script
    fmt            Format source files
    help           Prints <span class="hljs-built_in">this</span> message or the help <span class="hljs-keyword">of</span> the given subcommand(s)
    info           Show info about cache or info related to source file
    install        Install script <span class="hljs-keyword">as</span> an executable
    repl           Read Eval Print Loop
    run            Run a program given a filename or url to the <span class="hljs-built_in">module</span>
    test           Run tests
    types          Print runtime TypeScript declarations
    upgrade        Upgrade deno executable to newest version

ENVIRONMENT VARIABLES:
    DENO_DIR             <span class="hljs-built_in">Set</span> deno<span class="hljs-string">'s base directory (defaults to $HOME/.deno)
    DENO_INSTALL_ROOT    Set deno install'</span>s output directory
                         (defaults to $HOME/.deno/bin)
    NO_COLOR             <span class="hljs-built_in">Set</span> to disable color
    HTTP_PROXY           <span class="hljs-built_in">Proxy</span> address <span class="hljs-keyword">for</span> HTTP requests
                         (<span class="hljs-built_in">module</span> downloads, fetch)
    HTTPS_PROXY          Same but <span class="hljs-keyword">for</span> HTTPS
</code></pre><h2 id="heading-the-deno-commands">The Deno commands</h2>
<p>Note the <code>SUBCOMMANDS</code> section in the help, that lists all the commands we can run. What subcommands do we have?</p>
<ul>
<li><code>bundle</code> bundle module and dependencies of a project into single file</li>
<li><code>cache</code> cache the dependencies</li>
<li><code>completions</code> generate shell completions</li>
<li><code>doc</code> show documentation for a module</li>
<li><code>eval</code> to evaluate a piece of code, e.g. <code>deno eval "console.log(1 + 2)"</code></li>
<li><code>fmt</code> a built-in code formatter (similar to <code>gofmt</code> in Go)</li>
<li><code>help</code> prints this message or the help of the given subcommand(s)</li>
<li><code>info</code> show info about cache or info related to source file</li>
<li><code>install</code> install script as an executable</li>
<li><code>repl</code> Read-Eval-Print-Loop (the default)</li>
<li><code>run</code> run a program given a filename or url to the module</li>
<li><code>test</code> run tests</li>
<li><code>types</code> print runtime TypeScript declarations</li>
<li><code>upgrade</code> upgrade <code>deno</code> to the newest version</li>
</ul>
<p>You can run <code>deno &lt;subcommand&gt; help</code> to get specific additional documentation for the command, for example <code>deno run --help</code>.</p>
<p>As the help says, we can use this command to start a REPL (Read-Execute-Print-Loop) using <code>deno</code> without any other option.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-09-at-12.07.50.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>This is the same as running <code>deno repl</code>.</p>
<p>A more common way you’ll use this command is to execute a Deno app contained in a TypeScript file.</p>
<p>You can run both TypeScript (<code>.ts</code>) files, or JavaScript (<code>.js</code>) files.</p>
<p>If you are unfamiliar with TypeScript, don’t worry: Deno is written in TypeScript, buf you can write your “client” applications in JavaScript.</p>
<p><em>My <a target="_blank" href="https://flaviocopes.com/typescript/">TypeScript tutorial</a> will help you get up and running quickly with TypeScript if you want.</em></p>
<h2 id="heading-your-first-deno-app">Your first Deno app</h2>
<p>Let’s run a Deno app for the first time.</p>
<p>What I find pretty amazing is that you don’t even have to write a single line - you can run a command from any URL.</p>
<p>Deno downloads the program, compiles it and then runs it:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-09-at-12.22.30.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Of course running arbitrary code from the Internet is not a practice</em> I'd generally <em>recommend. In this case we are running it from the Deno official site, plus Deno has a sandbox that prevents programs to do anything you don’t want to allow. More on this later.</em></p>
<p>This program is very simple, just a <code>console.log()</code> call:</p>
<pre><code class="lang-ts"><span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Welcome to Deno ?'</span>)
</code></pre>
<p>If you open the <a target="_blank" href="https://deno.land/std/examples/welcome.ts">https://deno.land/std/examples/welcome.ts</a> URL with the browser, you’ll see this page:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-09-at-13.50.00.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Weird, right? You’d probably expect a TypeScript file, but instead we have a web page. The reason is the Web server of the Deno website knows you’re using a browser and serves you a more user friendly page.</p>
<p>Download the same UR using <code>wget</code> for example, which requests the <code>text/plain</code> version of it instead of <code>text/html</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-09-at-13.52.25.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>If you want to run the program again, it’s now cached by Deno and it does not need to download it again:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-09-at-12.22.47.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You can force a reload of the original source with the <code>--reload</code> flag:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-09-at-12.28.57.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p><code>deno run</code> has lots of different options that were not listed in the <code>deno --help</code>. Instead, you need to run <code>deno run --help</code> to reveal them:</p>
<pre><code>flavio@mbp~&gt; deno run --help
deno-run
Run a program given a filename or url to the <span class="hljs-built_in">module</span>.

By <span class="hljs-keyword">default</span> all programs are run <span class="hljs-keyword">in</span> sandbox without access to disk, network or
ability to spawn subprocesses.
  deno run https:<span class="hljs-comment">//deno.land/std/examples/welcome.ts</span>

Grant all permissions:
  deno run -A https:<span class="hljs-comment">//deno.land/std/http/file_server.ts</span>

Grant permission to read <span class="hljs-keyword">from</span> disk and listen to network:
  deno run --allow-read --allow-net https:<span class="hljs-comment">//deno.land/std/http/file_server.ts</span>

Grant permission to read whitelisted files <span class="hljs-keyword">from</span> disk:
  deno run --allow-read=<span class="hljs-regexp">/etc https:/</span><span class="hljs-regexp">/deno.land/</span>std/http/file_server.ts

<span class="hljs-attr">USAGE</span>:
    deno run [OPTIONS] &lt;SCRIPT_ARG&gt;...

OPTIONS:
    -A, --allow-all
            Allow all permissions

        --allow-env
            Allow environment access

        --allow-hrtime
            Allow high resolution time measurement

        --allow-net=&lt;allow-net&gt;
            Allow network access

        --allow-plugin
            Allow loading plugins

        --allow-read=&lt;allow-read&gt;
            Allow file system read access

        --allow-run
            Allow running subprocesses

        --allow-write=&lt;allow-write&gt;
            Allow file system write access

        --cached-only
            Require that remote dependencies are already cached

        --cert &lt;FILE&gt;
            Load certificate authority from PEM encoded file

    -c, --config &lt;FILE&gt;
            Load tsconfig.json configuration file

    -h, --help
            Prints help information

        --importmap &lt;FILE&gt;
            UNSTABLE:
            Load import map file
            Docs: https://deno.land/std/manual.md#import-maps
            Specification: https://wicg.github.io/import-maps/
            Examples: https://github.com/WICG/import-maps#the-import-map
        --inspect=&lt;HOST:PORT&gt;
            activate inspector on host:port (default: 127.0.0.1:9229)

        --inspect-brk=&lt;HOST:PORT&gt;
            activate inspector on host:port and break at start of user script

        --lock &lt;FILE&gt;
            Check the specified lock file

        --lock-write
            Write lock file. Use with --lock.

    -L, --log-level &lt;log-level&gt;
            Set log level [possible values: debug, info]

        --no-remote
            Do not resolve remote modules

    -q, --quiet
            Suppress diagnostic output
            By default, subcommands print human-readable diagnostic messages to stderr.
            If the flag is set, restrict these messages to errors.
    -r, --reload=&lt;CACHE_BLACKLIST&gt;
            Reload source code cache (recompile TypeScript)
            --reload
              Reload everything
            --reload=https://deno.land/std
              Reload only standard modules
            --reload=https://deno.land/std/fs/utils.ts,https://deno.land/std/fmt/colors.ts
              Reloads specific modules
        --seed &lt;NUMBER&gt;
            Seed Math.random()

        --unstable
            Enable unstable APIs

        --v8-flags=&lt;v8-flags&gt;
            Set V8 command line options. For help: --v8-flags=--help


ARGS:
    &lt;SCRIPT_ARG&gt;...
            script args
</code></pre><h2 id="heading-deno-code-examples">Deno code examples</h2>
<p>In addition to the one we ran above, the Deno website provides some other examples you can check out: <a target="_blank" href="https://deno.land/std/examples/">https://deno.land/std/examples/</a>.</p>
<p>At the time of writing we can find:</p>
<ul>
<li><code>cat.ts</code> prints the content a list of files provided as arguments</li>
<li><code>catj.ts</code> prints the content a list of files provided as arguments</li>
<li><code>chat/</code> an implementation of a chat</li>
<li><code>colors.ts</code> an example of</li>
<li><code>curl.ts</code> a simple implementation of <code>curl</code> that prints the content of the URL specified as argument</li>
<li><code>echo_server.ts</code> a TCP echo server</li>
<li><code>gist.ts</code> a program to post files to gist.github.com</li>
<li><code>test.ts</code> a sample test suite</li>
<li><code>welcome.ts</code> a simple console.log statement (the first program we ran above)</li>
<li><code>xeval.ts</code> allows you to run any TypeScript code for any line of standard input received. <a target="_blank" href="https://youtu.be/HjdJzNoT_qg?t=1932">Once known as <code>deno xeval</code></a> but since removed from the official command.</li>
</ul>
<h2 id="heading-your-first-deno-app-for-real">Your first Deno app (for real)</h2>
<p>Let’s write some code.</p>
<p>Your first Deno app you ran using <code>deno run https://deno.land/std/examples/welcome.ts</code> was an app that someone else wrote, so you didn’t see anything in regards to how Deno code looks like.</p>
<p>We’ll start from the default example app listed on the Deno official website:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> { serve } <span class="hljs-keyword">from</span> <span class="hljs-string">'https://deno.land/std/http/server.ts'</span>
<span class="hljs-keyword">const</span> s = serve({ port: <span class="hljs-number">8000</span> })
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'http://localhost:8000/'</span>)
<span class="hljs-keyword">for</span> <span class="hljs-keyword">await</span> (<span class="hljs-keyword">const</span> req <span class="hljs-keyword">of</span> s) {
  req.respond({ body: <span class="hljs-string">'Hello World\n'</span> })
}
</code></pre>
<p>This code imports the <code>serve</code> function from the <code>http/server</code> module. See? We don’t have to install it first, and it’s also not stored on your local machine like it happens with Node modules. This is one reason why the Deno installation was so fast.</p>
<p>Importing from <code>https://deno.land/std/http/server.ts</code> imports the latest version of the module. You can import a specific version using <code>@VERSION</code>, like this:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> { serve } <span class="hljs-keyword">from</span> <span class="hljs-string">'https://deno.land/std@v0.42.0/http/server.ts'</span>
</code></pre>
<p>The <code>serve</code> function is defined like this in this file:</p>
<pre><code class="lang-ts"><span class="hljs-comment">/**
 * Create a HTTP server
 *
 *     import { serve } from "https://deno.land/std/http/server.ts";
 *     const body = "Hello World\n";
 *     const s = serve({ port: 8000 });
 *     for await (const req of s) {
 *       req.respond({ body });
 *     }
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">serve</span>(<span class="hljs-params">addr: <span class="hljs-built_in">string</span> | HTTPOptions</span>): <span class="hljs-title">Server</span> </span>{
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> addr === <span class="hljs-string">'string'</span>) {
    <span class="hljs-keyword">const</span> [hostname, port] = addr.split(<span class="hljs-string">':'</span>)
    addr = { hostname, port: <span class="hljs-built_in">Number</span>(port) }
  }

  <span class="hljs-keyword">const</span> listener = listen(addr)
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Server(listener)
}
</code></pre>
<p>We proceed to instantiate a server calling the <code>serve()</code> function passing an object with the <code>port</code> property.</p>
<p>Then we run this loop to respond to every request coming from the server.</p>
<pre><code class="lang-ts"><span class="hljs-keyword">for</span> <span class="hljs-keyword">await</span> (<span class="hljs-keyword">const</span> req <span class="hljs-keyword">of</span> s) {
  req.respond({ body: <span class="hljs-string">'Hello World\n'</span> })
}
</code></pre>
<p>Note that we use the <code>await</code> keyword without having to wrap it into an <code>async</code> function because Deno implements <a target="_blank" href="https://flaviocopes.com/javascript-await-top-level/">top-level await</a>.</p>
<p>Let’s run this program locally. I assume you use <a target="_blank" href="https://flaviocopes.com/vscode/">VS Code</a>, but you can use any editor you like.</p>
<p>I recommend installing the Deno extension from <code>justjavac</code> (there was another one with the same name when I tried, but deprecated - might disappear in the future)</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-09-at-15.28.06.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The extension will provide several utilities and nice thing to VS Code to help you write your apps.</p>
<p>Now create an <code>app.ts</code> file in a folder and paste the above code:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-09-at-15.40.18.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Now run it using <code>deno run app.ts</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-09-at-15.39.28.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Deno downloads all the dependencies it needs, by first downloading the one we imported.</p>
<p>The <a target="_blank" href="https://deno.land/std/http/server.ts">https://deno.land/std/http/server.ts</a> file has several dependencies on its own:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> { encode } <span class="hljs-keyword">from</span> <span class="hljs-string">'../encoding/utf8.ts'</span>
<span class="hljs-keyword">import</span> { BufReader, BufWriter } <span class="hljs-keyword">from</span> <span class="hljs-string">'../io/bufio.ts'</span>
<span class="hljs-keyword">import</span> { assert } <span class="hljs-keyword">from</span> <span class="hljs-string">'../testing/asserts.ts'</span>
<span class="hljs-keyword">import</span> { deferred, Deferred, MuxAsyncIterator } <span class="hljs-keyword">from</span> <span class="hljs-string">'../async/mod.ts'</span>
<span class="hljs-keyword">import</span> {
  bodyReader,
  chunkedBodyReader,
  emptyReader,
  writeResponse,
  readRequest,
} <span class="hljs-keyword">from</span> <span class="hljs-string">'./_io.ts'</span>
<span class="hljs-keyword">import</span> Listener = Deno.Listener
<span class="hljs-keyword">import</span> Conn = Deno.Conn
<span class="hljs-keyword">import</span> Reader = Deno.Reader
</code></pre>
<p>and those are imported automatically.</p>
<p>At the end though we have a problem:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-09-at-15.42.05.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>What is happening? We have a permission denied problem.</p>
<p>Let’s talk about the sandbox.</p>
<h2 id="heading-the-deno-sandbox">The Deno sandbox</h2>
<p>I mentioned previously that Deno has a sandbox that prevents programs from doing anything you don’t want to allow.</p>
<p>What does this mean?</p>
<p>One of the things that Ryan mentions in the Deno introduction talk is that sometimes you want to run a JavaScript program outside of the Web Browser, and yet do not want allow it to access to anything it wants on your system. Or talk to the external world using a network.</p>
<p>There’s nothing stopping a Node.js app from getting your SSH keys or any other thing on your system and sending it to a server. This is why we usually only install Node packages from trusted sources. But how can we know if one of the projects we use gets hacked and in turn everyone else does?</p>
<p>Deno tries to replicate the same permission model that the browser implements. No JavaScript running in the browser can do shady things on your system unless you explicitly allow it.</p>
<p>Going back to Deno, if a program want to access the network like in the previous case, then we need to give it permission.</p>
<p>We can do so by passing a flag when we run the command, in this case <code>--allow-net</code>:</p>
<pre><code class="lang-sh">deno run --allow-net app.ts
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-09-at-15.48.41.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The app is now running an HTTP server on port 8000:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-09-at-15.49.02.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Other flags allow Deno to unlock other functionality:</p>
<ul>
<li><code>--allow-env</code> allow environment access</li>
<li><code>--allow-hrtime</code> allow high resolution time measurement</li>
<li><code>--allow-net=&lt;allow-net&gt;</code> allow network access</li>
<li><code>--allow-plugin</code> allow loading plugins</li>
<li><code>--allow-read=&lt;allow-read&gt;</code> allow file system read access</li>
<li><code>--allow-run</code> allow running subprocesses</li>
<li><code>--allow-write=&lt;allow-write&gt;</code> allow file system write access</li>
<li><code>--allow-all</code> allow all permissions (same as <code>-A</code>)</li>
</ul>
<p>Permissions for <code>net</code>, <code>read</code> and <code>write</code> can be granular. For example, you can allow reading from a specific folder using <code>--allow-read=/dev</code></p>
<h2 id="heading-formatting-code">Formatting code</h2>
<p>One of the things I really liked from Go was the <code>gofmt</code> command that came with the Go compiler. All Go code looks the same. Everyone uses <code>gofmt</code>.</p>
<p>JavaScript programmers are used to running <a target="_blank" href="https://flaviocopes.com/prettier/">Prettier</a>, and <code>deno fmt</code> actually runs that under the hood.</p>
<p>Say you have a file formatted badly like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-09-at-16.06.58.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You run <code>deno fmt app.ts</code> and it’s automatically formatted properly, also adding semicolons where missing:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-09-at-16.07.25.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-the-standard-library">The standard library</h2>
<p>The Deno standard library is extensive despite the project being very young.</p>
<p>It includes:</p>
<ul>
<li><code>archive</code> tar archive utilities</li>
<li><code>async</code> async utilties</li>
<li><code>bytes</code> helpers to manipulate bytes slices</li>
<li><code>datetime</code> date/time parsing</li>
<li><code>encoding</code> encoding/decoding for various formats</li>
<li><code>flags</code> parse command-line flags</li>
<li><code>fmt</code> formatting and printing</li>
<li><code>fs</code> file system API</li>
<li><code>hash</code> crypto lib</li>
<li><code>http</code> HTTP server</li>
<li><code>io</code> I/O lib</li>
<li><code>log</code> logging utilities</li>
<li><code>mime</code> support for multipart data</li>
<li><code>node</code> Node.js compatibility layer</li>
<li><code>path</code> path manipulation</li>
<li><code>ws</code> websockets</li>
</ul>
<h2 id="heading-another-deno-example">Another Deno example</h2>
<p>Let’s see another example of a Deno app, from the Deno examples: <a target="_blank" href="https://deno.land/std/examples/cat.ts"><code>cat</code></a>:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">const</span> filenames = Deno.args
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> filename <span class="hljs-keyword">of</span> filenames) {
  <span class="hljs-keyword">const</span> file = <span class="hljs-keyword">await</span> Deno.open(filename)
  <span class="hljs-keyword">await</span> Deno.copy(file, Deno.stdout)
  file.close()
}
</code></pre>
<p>This assigns to the <code>filenames</code> variable the content of <code>Deno.args</code>, which is a variable containing all the arguments sent to the command.</p>
<p>We iterate through them, and for each we use <code>Deno.open()</code> to open the file and we use <code>Deno.copy()</code> to print the content of the file to <code>Deno.stdout</code>. Finally we close the file.</p>
<p>If you run this using</p>
<pre><code class="lang-sh">deno run https://deno.land/std/examples/cat.ts
</code></pre>
<p>The program is downloaded and compiled, and nothing happens because we didn’t specify any argument.</p>
<p>Try now</p>
<pre><code class="lang-sh">deno run https://deno.land/std/examples/cat.ts app.ts
</code></pre>
<p>assuming you have <code>app.ts</code> from the previous project in the same folder.</p>
<p>You’ll get a permission error:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-09-at-17.06.31-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Because Deno disallows access to the filesystem by default. Grant access to the current folder using <code>--allow-read=./</code>:</p>
<pre><code>deno run --allow-read=./ https:<span class="hljs-comment">//deno.land/std/examples/cat.ts app.ts</span>
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-09-at-17.07.54-6.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-is-there-an-expresshapikoa-for-deno">Is there an Express/Hapi/Koa/* for Deno?</h2>
<p>Yes, definitely. Check out projects like</p>
<ul>
<li><a target="_blank" href="https://github.com/drashland/deno-drash">deno-drash</a></li>
<li><a target="_blank" href="https://github.com/NMathar/deno-express">deno-express</a></li>
<li><a target="_blank" href="https://github.com/oakserver/oak">oak</a></li>
<li><a target="_blank" href="https://github.com/sholladay/pogo">pogo</a></li>
<li><a target="_blank" href="https://github.com/keroxp/servest">servest</a></li>
</ul>
<h2 id="heading-example-use-oak-to-build-a-rest-api">Example: use Oak to build a REST API</h2>
<p>I want to make a simple example of how to build a REST API using Oak. Oak is interesting because it’s inspired by <a target="_blank" href="https://github.com/koajs/koa">Koa</a>, the popular Node.js middleware, and due to this it’s very familiar if you’ve used that before.</p>
<p>The API we’re going to build is very simple.</p>
<p>Our server will store, in memory, a list of dogs with name and age.</p>
<p>We want to:</p>
<ul>
<li>add new dogs</li>
<li>list dogs</li>
<li>get details about a specific dog</li>
<li>remove a dog from the list</li>
<li>update a dog's age</li>
</ul>
<p>We’ll do this in TypeScript, but nothing stops you from writing the API in JavaScript - you simply remove the types.</p>
<p>Create a <code>app.ts</code> file.</p>
<p>Let’s start by importing the <code>Application</code> and <code>Router</code> objects from Oak:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> { Application, Router } <span class="hljs-keyword">from</span> <span class="hljs-string">'https://deno.land/x/oak/mod.ts'</span>
</code></pre>
<p>then we get the environment variables PORT and HOST:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">const</span> env = Deno.env.toObject()
<span class="hljs-keyword">const</span> PORT = env.PORT || <span class="hljs-number">4000</span>
<span class="hljs-keyword">const</span> HOST = env.HOST || <span class="hljs-string">'127.0.0.1'</span>
</code></pre>
<p>By default our app will run on localhost:4000.</p>
<p>Now we create the Oak application and we start it:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">const</span> router = <span class="hljs-keyword">new</span> Router()

<span class="hljs-keyword">const</span> app = <span class="hljs-keyword">new</span> Application()

app.use(router.routes())
app.use(router.allowedMethods())

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Listening on port <span class="hljs-subst">${PORT}</span>...`</span>)

<span class="hljs-keyword">await</span> app.listen(<span class="hljs-string">`<span class="hljs-subst">${HOST}</span>:<span class="hljs-subst">${PORT}</span>`</span>)
</code></pre>
<p>Now the app should be compiling fine.</p>
<p>Run</p>
<pre><code class="lang-sh">deno run --allow-env --allow-net app.ts
</code></pre>
<p>and Deno will download the dependencies:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-10-at-16.31.11.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>and then listen on port 4000.</p>
<p>The next times you run the command, Deno will skip the installation part because those packages are already cached:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-10-at-16.32.40.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>At the top of the file, let’s define an interface for a dog, then we declare an initial <code>dogs</code> array of Dog objects:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">interface</span> Dog {
  name: <span class="hljs-built_in">string</span>
  age: <span class="hljs-built_in">number</span>
}

<span class="hljs-keyword">let</span> dogs: <span class="hljs-built_in">Array</span>&lt;Dog&gt; = [
  {
    name: <span class="hljs-string">'Roger'</span>,
    age: <span class="hljs-number">8</span>,
  },
  {
    name: <span class="hljs-string">'Syd'</span>,
    age: <span class="hljs-number">7</span>,
  },
]
</code></pre>
<p>Now let’s actually implement the API.</p>
<p>We have everything in place. After you create the router, let’s add some functions that will be invoked any time one of those endpoints is hit:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">const</span> router = <span class="hljs-keyword">new</span> Router()

router
  .get(<span class="hljs-string">'/dogs'</span>, getDogs)
  .get(<span class="hljs-string">'/dogs/:name'</span>, getDog)
  .post(<span class="hljs-string">'/dogs'</span>, addDog)
  .put(<span class="hljs-string">'/dogs/:name'</span>, updateDog)
  .delete(<span class="hljs-string">'/dogs/:name'</span>, removeDog)
</code></pre>
<p>See? We define</p>
<ul>
<li><code>GET /dogs</code></li>
<li><code>GET /dogs/:name</code></li>
<li><code>POST /dogs</code></li>
<li><code>PUT /dogs/:name</code></li>
<li><code>DELETE /dogs/:name</code></li>
</ul>
<p>Let’s implement those one-by-one.</p>
<p>Starting from <code>GET /dogs</code>, which returns the list of all the dogs:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> getDogs = <span class="hljs-function">(<span class="hljs-params">{ response }: { response: <span class="hljs-built_in">any</span> }</span>) =&gt;</span> {
  response.body = dogs
}
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-10-at-16.47.53.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Next, here’s how we can retrieve a single dog by name:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> getDog = <span class="hljs-function">(<span class="hljs-params">{
  params,
  response,
}: {
  params: {
    name: <span class="hljs-built_in">string</span>
  }
  response: <span class="hljs-built_in">any</span>
}</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> dog = dogs.filter(<span class="hljs-function">(<span class="hljs-params">dog</span>) =&gt;</span> dog.name === params.name)
  <span class="hljs-keyword">if</span> (dog.length) {
    response.status = <span class="hljs-number">200</span>
    response.body = dog[<span class="hljs-number">0</span>]
    <span class="hljs-keyword">return</span>
  }

  response.status = <span class="hljs-number">400</span>
  response.body = { msg: <span class="hljs-string">`Cannot find dog <span class="hljs-subst">${params.name}</span>`</span> }
}
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-10-at-16.48.02.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Here is how we add a new dog:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> addDog = <span class="hljs-keyword">async</span> ({
  request,
  response,
}: {
  request: <span class="hljs-built_in">any</span>
  response: <span class="hljs-built_in">any</span>
}) =&gt; {
  <span class="hljs-keyword">const</span> body = <span class="hljs-keyword">await</span> request.body()
  <span class="hljs-keyword">const</span> dog: Dog = body.value
  dogs.push(dog)

  response.body = { msg: <span class="hljs-string">'OK'</span> }
  response.status = <span class="hljs-number">200</span>
}
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-10-at-16.47.41.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Notice that I now used <code>const body = await request.body()</code> to get the content of the body, since the <code>name</code> and <code>age</code> values are passed as JSON.</p>
<p>Here’s how we update a dog’s age:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> updateDog = <span class="hljs-keyword">async</span> ({
  params,
  request,
  response,
}: {
  params: {
    name: <span class="hljs-built_in">string</span>
  }
  request: <span class="hljs-built_in">any</span>
  response: <span class="hljs-built_in">any</span>
}) =&gt; {
  <span class="hljs-keyword">const</span> temp = dogs.filter(<span class="hljs-function">(<span class="hljs-params">existingDog</span>) =&gt;</span> existingDog.name === params.name)
  <span class="hljs-keyword">const</span> body = <span class="hljs-keyword">await</span> request.body()
  <span class="hljs-keyword">const</span> { age }: { age: <span class="hljs-built_in">number</span> } = body.value

  <span class="hljs-keyword">if</span> (temp.length) {
    temp[<span class="hljs-number">0</span>].age = age
    response.status = <span class="hljs-number">200</span>
    response.body = { msg: <span class="hljs-string">'OK'</span> }
    <span class="hljs-keyword">return</span>
  }

  response.status = <span class="hljs-number">400</span>
  response.body = { msg: <span class="hljs-string">`Cannot find dog <span class="hljs-subst">${params.name}</span>`</span> }
}
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-10-at-16.48.11.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>and here is how we can remove a dog from our list:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> removeDog = <span class="hljs-function">(<span class="hljs-params">{
  params,
  response,
}: {
  params: {
    name: <span class="hljs-built_in">string</span>
  }
  response: <span class="hljs-built_in">any</span>
}</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> lengthBefore = dogs.length
  dogs = dogs.filter(<span class="hljs-function">(<span class="hljs-params">dog</span>) =&gt;</span> dog.name !== params.name)

  <span class="hljs-keyword">if</span> (dogs.length === lengthBefore) {
    response.status = <span class="hljs-number">400</span>
    response.body = { msg: <span class="hljs-string">`Cannot find dog <span class="hljs-subst">${params.name}</span>`</span> }
    <span class="hljs-keyword">return</span>
  }

  response.body = { msg: <span class="hljs-string">'OK'</span> }
  response.status = <span class="hljs-number">200</span>
}
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/05/Screen-Shot-2020-05-10-at-16.48.32.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Here’s the complete example code:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> { Application, Router } <span class="hljs-keyword">from</span> <span class="hljs-string">'https://deno.land/x/oak/mod.ts'</span>

<span class="hljs-keyword">const</span> env = Deno.env.toObject()
<span class="hljs-keyword">const</span> PORT = env.PORT || <span class="hljs-number">4000</span>
<span class="hljs-keyword">const</span> HOST = env.HOST || <span class="hljs-string">'127.0.0.1'</span>

<span class="hljs-keyword">interface</span> Dog {
  name: <span class="hljs-built_in">string</span>
  age: <span class="hljs-built_in">number</span>
}

<span class="hljs-keyword">let</span> dogs: <span class="hljs-built_in">Array</span>&lt;Dog&gt; = [
  {
    name: <span class="hljs-string">'Roger'</span>,
    age: <span class="hljs-number">8</span>,
  },
  {
    name: <span class="hljs-string">'Syd'</span>,
    age: <span class="hljs-number">7</span>,
  },
]

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> getDogs = <span class="hljs-function">(<span class="hljs-params">{ response }: { response: <span class="hljs-built_in">any</span> }</span>) =&gt;</span> {
  response.body = dogs
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> getDog = <span class="hljs-function">(<span class="hljs-params">{
  params,
  response,
}: {
  params: {
    name: <span class="hljs-built_in">string</span>
  }
  response: <span class="hljs-built_in">any</span>
}</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> dog = dogs.filter(<span class="hljs-function">(<span class="hljs-params">dog</span>) =&gt;</span> dog.name === params.name)
  <span class="hljs-keyword">if</span> (dog.length) {
    response.status = <span class="hljs-number">200</span>
    response.body = dog[<span class="hljs-number">0</span>]
    <span class="hljs-keyword">return</span>
  }

  response.status = <span class="hljs-number">400</span>
  response.body = { msg: <span class="hljs-string">`Cannot find dog <span class="hljs-subst">${params.name}</span>`</span> }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> addDog = <span class="hljs-keyword">async</span> ({
  request,
  response,
}: {
  request: <span class="hljs-built_in">any</span>
  response: <span class="hljs-built_in">any</span>
}) =&gt; {
  <span class="hljs-keyword">const</span> body = <span class="hljs-keyword">await</span> request.body()
  <span class="hljs-keyword">const</span> { name, age }: { name: <span class="hljs-built_in">string</span>; age: <span class="hljs-built_in">number</span> } = body.value
  dogs.push({
    name: name,
    age: age,
  })

  response.body = { msg: <span class="hljs-string">'OK'</span> }
  response.status = <span class="hljs-number">200</span>
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> updateDog = <span class="hljs-keyword">async</span> ({
  params,
  request,
  response,
}: {
  params: {
    name: <span class="hljs-built_in">string</span>
  }
  request: <span class="hljs-built_in">any</span>
  response: <span class="hljs-built_in">any</span>
}) =&gt; {
  <span class="hljs-keyword">const</span> temp = dogs.filter(<span class="hljs-function">(<span class="hljs-params">existingDog</span>) =&gt;</span> existingDog.name === params.name)
  <span class="hljs-keyword">const</span> body = <span class="hljs-keyword">await</span> request.body()
  <span class="hljs-keyword">const</span> { age }: { age: <span class="hljs-built_in">number</span> } = body.value

  <span class="hljs-keyword">if</span> (temp.length) {
    temp[<span class="hljs-number">0</span>].age = age
    response.status = <span class="hljs-number">200</span>
    response.body = { msg: <span class="hljs-string">'OK'</span> }
    <span class="hljs-keyword">return</span>
  }

  response.status = <span class="hljs-number">400</span>
  response.body = { msg: <span class="hljs-string">`Cannot find dog <span class="hljs-subst">${params.name}</span>`</span> }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> removeDog = <span class="hljs-function">(<span class="hljs-params">{
  params,
  response,
}: {
  params: {
    name: <span class="hljs-built_in">string</span>
  }
  response: <span class="hljs-built_in">any</span>
}</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> lengthBefore = dogs.length
  dogs = dogs.filter(<span class="hljs-function">(<span class="hljs-params">dog</span>) =&gt;</span> dog.name !== params.name)

  <span class="hljs-keyword">if</span> (dogs.length === lengthBefore) {
    response.status = <span class="hljs-number">400</span>
    response.body = { msg: <span class="hljs-string">`Cannot find dog <span class="hljs-subst">${params.name}</span>`</span> }
    <span class="hljs-keyword">return</span>
  }

  response.body = { msg: <span class="hljs-string">'OK'</span> }
  response.status = <span class="hljs-number">200</span>
}

<span class="hljs-keyword">const</span> router = <span class="hljs-keyword">new</span> Router()
router
  .get(<span class="hljs-string">'/dogs'</span>, getDogs)
  .get(<span class="hljs-string">'/dogs/:name'</span>, getDog)
  .post(<span class="hljs-string">'/dogs'</span>, addDog)
  .put(<span class="hljs-string">'/dogs/:name'</span>, updateDog)
  .delete(<span class="hljs-string">'/dogs/:name'</span>, removeDog)

<span class="hljs-keyword">const</span> app = <span class="hljs-keyword">new</span> Application()

app.use(router.routes())
app.use(router.allowedMethods())

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Listening on port <span class="hljs-subst">${PORT}</span>...`</span>)

<span class="hljs-keyword">await</span> app.listen(<span class="hljs-string">`<span class="hljs-subst">${HOST}</span>:<span class="hljs-subst">${PORT}</span>`</span>)
</code></pre>
<h2 id="heading-find-out-more">Find out more</h2>
<p>The Deno official website is <a target="_blank" href="https://deno.land/">https://deno.land</a></p>
<p>The API documentation is available at <a target="_blank" href="https://doc.deno.land/">https://doc.deno.land</a> and <a target="_blank" href="https://deno.land/typedoc/index.html">https://deno.land/typedoc/index.html</a></p>
<p>awesome-deno <a target="_blank" href="https://github.com/denolib/awesome-deno">https://github.com/denolib/awesome-deno</a></p>
<h2 id="heading-a-few-more-random-tidbits">A few more random tidbits</h2>
<ul>
<li>Deno provides a built-in <code>fetch</code> implementation that matches the one available in the browser</li>
<li>Deno has a compatibility layer with the Node.js stdlib <a target="_blank" href="https://github.com/denoland/deno/tree/master/std/node">in progress</a></li>
</ul>
<h2 id="heading-final-words">Final words</h2>
<p>I hope you enjoyed this Deno tutorial!</p>
<p>Reminder: <a target="_blank" href="https://flaviocopes.com/page/deno-handbook/">You can get a PDF/ePub/Mobi version of this Deno Handbook here</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
