{
    "version": "https://jsonfeed.org/version/1",
    "title": "vixalien.io",
    "home_page_url": "http://vixalien.com/",
    "feed_url": "https://vixalien.com/feed/feed.json",
    "description": "Feed for my personal website!",
    "icon": "http://vixalien.com/favicon/maskable.png",
    "author": {
        "name": "Angelo Verlain",
        "url": "https://vixalien.com"
    },
    "items": [
        {
            "id": "setup-git",
            "content_html": "<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"utf-8\" /><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\" /><meta name=\"theme-color\" content=\"#030f1b\" /><link rel=\"stylesheet\" href=\"/css/app.css\" /><link rel=\"shortcut icon\" href=\"/favicon.ico\" /><link rel=\"manifest\" href=\"/manifest.json\" /><link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"/favicon/android-chrome-192x192.png\" /><link rel=\"alternate\" type=\"application/rss+xml\" title=\"RSS\" href=\"https://vixalien.ga/feed/feed.rss\" /><link rel=\"alternate\" type=\"application/atom+xml\" title=\"Atom\" href=\"https://vixalien.ga/feed/feed.atom\" /><link rel=\"alternate\" type=\"application/json\" title=\"JSON\" href=\"https://vixalien.ga/feed/feed.json\" /><title>Setup Git - vixalien</title><link rel=\"canonical\" href=\"https://www.vixalien.com/post/setup-git\" /><meta name=\"description\" content=\"How I set up Git on my systems with using opinionated defaults.\" /><link rel=\"stylesheet\" href=\"/css/highlight.css\" /><link rel=\"stylesheet\" href=\"/css/image-container.css\" /></head><body><script src=\"/js/config.js\"></script><div class=\"root\"><div class=\"image-container\"><div style=\"padding-bottom:0\" class=\"inner-container container\"><div class=\"top\"><header><nav><a href=\"/\">← vixalien's blog</a></nav></header></div><picture><source srcset=\"/.build/images/600/posts/setup-git/banner.webp\" media=\"(max-width: 600px)\" /><source srcset=\"/.build/images/1200/posts/setup-git/banner.webp\" media=\"(min-width: 600px) and (max-width: 1200px)\" /><source srcset=\"/.build/images/3000/posts/setup-git/banner.webp\" media=\"(min-width: 1200px)\" /><img src=\"/.build/images/1200/posts/setup-git/banner.webp\" /></picture><div class=\"bottom\"><div class=\"intro\"><small>Thu Mar 31 2022</small><br /><h1>Setup Git</h1></div><p>How I set up Git on my systems with using opinionated defaults.</p><div class=\"stack\"><p><a href=\"#main\" class=\"read-link\">↓ Read</a></p><hr /></div></div></div></div><main style=\"\" id=\"main\" class=\" container\"><br /><article><h1 id=\"how-to-setup-git\">How to setup Git</h1>\n<p>This is my default setup</p>\n<h3 id=\"1-install-git\">1. Install Git</h3>\n<p>Git has a high chance of being already installed on some systems. First run <code>git version</code> to see if it is installed and up-to-date.</p>\n<pre class=\"block-code\"><code class=\"language-sh\">brew install git <span class=\"hljs-comment\"># on macos</span>\n\nyay -S git <span class=\"hljs-comment\"># arch (or use pacman)</span>\nsudo apt install git <span class=\"hljs-comment\"># ubuntu</span>\nsudo dnf install git <span class=\"hljs-comment\"># fedora</span>\n\n<span class=\"hljs-comment\"># this guide is not really meant for windows but everything should work, go to https://git-scm.com/download/win to download git for windows</span>\n</code></pre>\n<h3 id=\"2-update-git-settings\">2. Update Git settings</h3>\n<p>Create a file called <code>.gitconfig</code> in your home directory. On Windows, it is <code>C:\\Users\\username\\.gitconfig</code>.</p>\n<pre class=\"block-code\"><code class=\"language-yaml\"><span class=\"hljs-comment\"># ~/.gitconfig</span>\n<span class=\"hljs-comment\"># Tell Git who you are</span>\n[<span class=\"hljs-string\">user</span>]\n    <span class=\"hljs-string\">email</span> <span class=\"hljs-string\">=</span> <span class=\"hljs-string\">good@email.dne</span>\n    <span class=\"hljs-string\">name</span> <span class=\"hljs-string\">=</span> <span class=\"hljs-string\">Beatiful</span> <span class=\"hljs-string\">Name</span>\n<span class=\"hljs-comment\"># It is a good idea to tell Git to remember your credentials so that you don&#x27;t have to log in everytime especially if you use Personal Access Tokens as seen below.</span>\n<span class=\"hljs-comment\"># <span class=\"hljs-doctag\">Note:</span> If you don&#x27;t want Git to remember your credentials forever, use `cache` instead of `store` or run `git help -a | grep credential-` to view all available helpers.</span>\n[<span class=\"hljs-string\">credential</span>]\n    <span class=\"hljs-string\">helper</span> <span class=\"hljs-string\">=</span> <span class=\"hljs-string\">store</span>\n<span class=\"hljs-comment\"># Allow you to view pretty outputs when you fo `git log`. To enable these aliases, add the following lines to your `~/.gitconfig` file (create one if it doesn&#x27;t exist)</span>\n<span class=\"hljs-comment\"># some are stolen from https://stackoverflow.com/questions/1057564/pretty-git-branch-graphs</span>\n[<span class=\"hljs-string\">alias</span>]\n    <span class=\"hljs-string\">lg1</span> <span class=\"hljs-string\">=</span> <span class=\"hljs-string\">log</span> <span class=\"hljs-string\">--graph</span> <span class=\"hljs-string\">--abbrev-commit</span> <span class=\"hljs-string\">--decorate</span> <span class=\"hljs-string\">--format=format:&#x27;%C(bold</span> <span class=\"hljs-string\">blue)%h%C(reset)</span> <span class=\"hljs-bullet\">-</span> <span class=\"hljs-string\">%C(bold</span> <span class=\"hljs-string\">green)(%ar)%C(reset)</span> <span class=\"hljs-string\">%C(white)%s%C(reset)</span> <span class=\"hljs-string\">%C(dim</span> <span class=\"hljs-string\">white)-</span> <span class=\"hljs-string\">%an%C(reset)%C(bold</span> <span class=\"hljs-string\">yellow)%d%C(reset)&#x27;</span> <span class=\"hljs-string\">--all</span>\n    <span class=\"hljs-string\">lg2</span> <span class=\"hljs-string\">=</span> <span class=\"hljs-string\">log</span> <span class=\"hljs-string\">--graph</span> <span class=\"hljs-string\">--abbrev-commit</span> <span class=\"hljs-string\">--decorate</span> <span class=\"hljs-string\">--format=format:&#x27;%C(bold</span> <span class=\"hljs-string\">blue)%h%C(reset)</span> <span class=\"hljs-bullet\">-</span> <span class=\"hljs-string\">%C(bold</span> <span class=\"hljs-string\">cyan)%aD%C(reset)</span> <span class=\"hljs-string\">%C(bold</span> <span class=\"hljs-string\">green)(%ar)%C(reset)%C(bold</span> <span class=\"hljs-string\">yellow)%d%C(reset)%n&#x27;&#x27;</span>          <span class=\"hljs-string\">%C(white)%s%C(reset)</span> <span class=\"hljs-string\">%C(dim</span> <span class=\"hljs-string\">white)-</span> <span class=\"hljs-string\">%an%C(reset)&#x27;</span> <span class=\"hljs-string\">--all</span>\n    <span class=\"hljs-string\">lg</span> <span class=\"hljs-string\">=</span> <span class=\"hljs-string\">!&quot;git</span> <span class=\"hljs-string\">lg1&quot;</span>\n    <span class=\"hljs-string\">adog</span> <span class=\"hljs-string\">=</span> <span class=\"hljs-string\">log</span> <span class=\"hljs-string\">--all</span> <span class=\"hljs-string\">--decorate</span> <span class=\"hljs-string\">--oneline</span> <span class=\"hljs-string\">--graph</span>\n    <span class=\"hljs-comment\"># silly amend the last commit using the same message, useful when you forgot to add something before committing.</span>\n    <span class=\"hljs-string\">silly</span> <span class=\"hljs-string\">=</span> <span class=\"hljs-string\">commit</span> <span class=\"hljs-string\">--amend</span> <span class=\"hljs-string\">-a</span> <span class=\"hljs-string\">--no-edit</span>\n[<span class=\"hljs-string\">filter</span> <span class=\"hljs-string\">&quot;lfs&quot;</span>]\n    <span class=\"hljs-string\">required</span> <span class=\"hljs-string\">=</span> <span class=\"hljs-literal\">true</span>\n    <span class=\"hljs-string\">clean</span> <span class=\"hljs-string\">=</span> <span class=\"hljs-string\">git-lfs</span> <span class=\"hljs-string\">clean</span> <span class=\"hljs-string\">--</span> <span class=\"hljs-string\">%f</span>\n    <span class=\"hljs-string\">smudge</span> <span class=\"hljs-string\">=</span> <span class=\"hljs-string\">git-lfs</span> <span class=\"hljs-string\">smudge</span> <span class=\"hljs-string\">--</span> <span class=\"hljs-string\">%f</span>\n    <span class=\"hljs-string\">process</span> <span class=\"hljs-string\">=</span> <span class=\"hljs-string\">git-lfs</span> <span class=\"hljs-string\">filter-process</span>\n<span class=\"hljs-comment\"># Set the default branch to main</span>\n[<span class=\"hljs-string\">init</span>]\n    <span class=\"hljs-string\">defaultBranch</span> <span class=\"hljs-string\">=</span> <span class=\"hljs-string\">main</span>\n[<span class=\"hljs-string\">color</span>]\n    <span class=\"hljs-string\">ui</span> <span class=\"hljs-string\">=</span> <span class=\"hljs-literal\">true</span>\n<span class=\"hljs-comment\"># Set editor to VS Code</span>\n[<span class=\"hljs-string\">core</span>]\n      <span class=\"hljs-string\">editor</span> <span class=\"hljs-string\">=</span> <span class=\"hljs-string\">code</span>\n</code></pre>\n<h2 id=\"github\">Github</h2>\n<p>Git and Github are a pair. This is how I set them up.</p>\n<h3 id=\"1-logging-in\">1. Logging in</h3>\n<p>You will need to login to Github from Git to access private repositories or push to repos. To my knowledge, you can either use SSH (Secure Shell) or Personal Access Tokens to login to Github from Git. You can choose whatever you like but I personally like to use SSH.</p>\n<h4 id=\"1-using-ssh\">1. Using SSH</h4>\n<p>SSH is a protocol for logging into a remote machine and for executing commands on a remote machine. You can use the protocol to sign in into Github.</p>\n<h5 id=\"1-check-if-ssh-files-are-present\">1. Check if SSH files are present</h5>\n<p>FIrst check if you have the files <code>~/.ssh/id_rsa</code> and <code>~/.ssh/id_rsa.pub</code>.</p>\n<pre class=\"block-code\"><code class=\"language-sh\"><span class=\"hljs-built_in\">ls</span> ~/.ssh/id_rsa{,.pub}\n</code></pre>\n<p>If the 2 files are present, skip to step 3.</p>\n<h5 id=\"2-generate-the-ssh-keys\">2. Generate the SSH keys</h5>\n<pre class=\"block-code\"><code>ssh-keygen -t rsa -C &quot;good@email.dne&quot;\n</code></pre>\n<h5 id=\"3-copy-the-contents-of-the-id_rsapub\">3. Copy the contents of the <code>id_rsa.pub</code></h5>\n<pre class=\"block-code\"><code class=\"language-sh\">pbcopy &lt; ~/.ssh/id_rsa.pub <span class=\"hljs-comment\"># on macOS</span>\n\n<span class=\"hljs-built_in\">cat</span> ~/.ssh/id_rsa.pub <span class=\"hljs-comment\"># on *nix, copy by hand-erm-mouse</span>\n</code></pre>\n<h5 id=\"4-add-your-ssh-to-github\">4. Add your SSH to Github</h5>\n<p>You will now need to add your SSH key to Github.</p>\n<ol>\n<li>Go to your Github&#39;s <a href=\"https://github.com/settings/profile\">Account Settings</a></li>\n<li>On the sidebar, Click on &quot;<a href=\"https://github.com/settings/keys\">SSH and GPG keys</a>&quot;.</li>\n<li>Scroll and click on &quot;New SSH Key&quot;.</li>\n<li>Add a descriptive label and paste the text you had copied from the previous command and save.</li>\n</ol>\n<h5 id=\"5-test-ssh\">5. Test SSH</h5>\n<p>To test SSH, run the following command:</p>\n<pre class=\"block-code\"><code class=\"language-sh\">ssh -T git@github.com\n</code></pre>\n<p>If you see something like the following, it worked:</p>\n<pre class=\"block-code\"><code>Hi username! You&#39;ve successfully authenticated, but Github does\nnot provide shell access.\n</code></pre>\n<p>Also, don&#39;t mind it if you see a message that says the authenticity of &#39;github.com&#39; can&#39;t be established. It&#39;s normal.</p>\n<p>Now clone a repo using SSH by running your clone commands in the form:</p>\n<pre class=\"block-code\"><code class=\"language-sh\">git <span class=\"hljs-built_in\">clone</span> git@github.com:user/repo.git\n</code></pre>\n<h4 id=\"2-using-personal-access-tokens\">2. Using Personal Access Tokens</h4>\n<p>You need to push a repo to Github to initiate the authentication flow using Personal Access Tokens. Clone one of your repos and try to push it to Github using <code>git push</code>. If you do, it will ask for your username and password. Do not enter your real password, instead, create a new Personal Access Token that will serve as your password.</p>\n<ol>\n<li>Go to <a href=\"https://github.com\">Github</a></li>\n<li>Go to <a href=\"https://github.com/settings/profile\">Settings</a> by clicking your account icon in the top right corner.</li>\n<li>On the sidebar on the left, scroll down and click on <a href=\"https://github.com/settings/apps\">&quot;Developer Settings&quot;</a></li>\n<li>On the new sidebar that appears, click on <a href=\"https://github.com/settings/tokens\">Personal access tokens</a></li>\n<li>&quot;Generate new token&quot;</li>\n</ol>\n<p>Choose a name for your token. I recommend the format: <code>COMPUTER_NAME OS VERSION &quot;GIT&quot;</code>. For example: <code>HP Laptop Ubuntu 21.04 Git</code>. It may help you remember which tokens are used for what.</p>\n<p>I recommed you check the <code>workflow</code> scope ONLY. This will automatically select <code>repo</code> too and this will allow you to do basically almost anything you want on Git (including pushing &amp; running Workflows/Automations). If you don&#39;t know what workflows are, only select <code>repo</code>. If you feel compelled as those are not enough, create it with those scopes anyways as you can create other tokens anyways anytime.</p>\n<p>It is equally important to note that Personal Access Tokens are used only once and cannot be viewed ever again although you can delete them.</p>\n<h3 id=\"2-adding-a-gpg-key-to-your-account\">2. Adding a GPG Key to your account.</h3>\n<p>You can show a <code>Verified</code> Badge or a blue tick next to your commits by setting up a GPG Key and using it to sign your commits. Commits made through the Github web interface are automatically signed.</p>\n<h4 id=\"1-install-gpg\">1. Install gpg</h4>\n<pre class=\"block-code\"><code class=\"language-sh\">brew install gpg <span class=\"hljs-comment\"># on macos</span>\n<span class=\"hljs-comment\"># it&#x27;s usually preinstalled on linux</span>\n<span class=\"hljs-comment\"># on windows go to https://www.gnupg.org/download/</span>\n</code></pre>\n<h4 id=\"2-generate-a-new-gpg-key\">2. Generate a new GPG Key</h4>\n<pre class=\"block-code\"><code class=\"language-sh\">gpg --full-generate-key\n</code></pre>\n<p>GPG will ask you for many details. You must follow the prompts and enter the data provided. However it is extremely important that you enter the same email as you use on Github otherwise your commits won&#39;t be verified.</p>\n<p>GPG will ask some questions and this is how I choose to answer them. The <code>circled</code> texts are my answers.</p>\n<pre class=\"not-code\">\ngpg (GnuPG) 2.2.20; Copyright (C) 2020 Free Software Foundation, Inc.\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.\n\nPlease select what kind of key you want:\n   (1) RSA and RSA (default)\n   (2) DSA and Elgamal\n   (3) DSA (sign only)\n   (4) RSA (sign only)\n  (14) Existing key from card\nYour selection? <code>1</code>\nRSA keys may be between 1024 and 4096 bits long.\nWhat keysize do you want? (3072) <code>4096</code>\nRequested keysize is 4096 bits\nPlease specify how long the key should be valid.\n         0 = key does not expire\n      &lt;n&gt;  = key expires in n days\n      &lt;n&gt;w = key expires in n weeks\n      &lt;n&gt;m = key expires in n months\n      &lt;n&gt;y = key expires in n years\nKey is valid for? (0) <code>3m</code>\nKey expires at Thu 30 Jun 2022 00:20:24 CAT\nIs this correct? (y/N) y\n\nGnuPG needs to construct a user ID to identify your key.\n\nReal name: <code>Beautiful Email</code>\nEmail address: <code>good@email.dne</code>\nComment: <code>The comment you provided</code>\nYou selected this USER-ID:\n    <i>\"Beautiful name (The comment you provided) &lt;good@email.dne&gt;</i>\n\nChange (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? <code>o</code>\nWe need to generate a lot of random bytes. It is a good idea to perform\nsome other action (type on the keyboard, move the mouse, utilize the\ndisks) during the prime generation; this gives the random number\ngenerator a better chance to gain enough entropy.\nWe need to generate a lot of random bytes. It is a good idea to perform\nsome other action (type on the keyboard, move the mouse, utilize the\ndisks) during the prime generation; this gives the random number\ngenerator a better chance to gain enough entropy.\ngpg: key <i><b><code>YOUR KEY WILL BE HERE</code></b></i> marked as ultimately trusted\ndgpg: revocation certificate stored as '/home/<i>USERNAME</i><wbr>/.gnupg/openpgp-revocs.d/RANDOM40CHARACTERSIDKWHYUREADINGTHISLMAO.rev'\npublic and secret key created and signed.\n\npub   rsa4096 2022-03-31 [SC] [expires: 2022-06-29]\n      RANDOM40CHARACTERSIDKWHYUREADINGTHISLMAO\nuid                      <i>\"Beautiful name (The comment you provided) &lt;good@email.dne&gt;</i>\nsub   rsa4096 2022-03-31 [E] [expires: 2022-06-29]\n</pre>\n\n<p>At this point you will be demanded to enter a password twice. Please remember it or save it somewhere (in a password manager, does paper still exist in the future?)</p>\n<h4 id=\"3-verify-the-gpg-key\">3. Verify the GPG key</h4>\n<pre class=\"block-code\"><code class=\"language-sh\">gpg --list-secret-keys --keyid-format LONG\n</code></pre>\n<p>It should return text in the following format. Take note of the <code>[KEY_ID]</code>.</p>\n<pre class=\"not-code\">\nsec   rsa4096/<code>[KEY_ID]</code> 2022-03-31 [SC] [expires: 2022-06-29]\n      A13CD138DCCB7314834CD603049EF1938BFB0ACD\nuid                 [ultimate] <i>\"Beautiful name (The comment you provided) &lt;good@email.dne&gt;</i>\nssb   rsa4096/795E8F10B7A9C97D 2022-03-31 [E] [expires: 2022-06-29]\n</pre>\n\n<h4 id=\"4-export-the-key-and-add-it-to-github\">4. Export the key and add it to Github</h4>\n<p>Run the following command using the <code>[KEY_ID]</code> from the previous command to export your newly-created GPG key.</p>\n<pre class=\"block-code\"><code class=\"language-sh\">gpg --armor --<span class=\"hljs-built_in\">export</span> [KEY_ID]\n</code></pre>\n<p>This will generate a large block of text. In the following format.</p>\n<pre class=\"block-code\"><code>-----BEGIN PGP PUBLIC KEY BLOCK-----\n[SCRAMBLE]\n-----END PGP PUBLIC KEY BLOCK-----\n</code></pre>\n<p>Copy the whole text including the comments.</p>\n<p>To add the key to Github.</p>\n<ol>\n<li>Open <a href=\"https://github.com\">Github</a></li>\n<li>Go your <a href=\"https://github.com/settings/profile\">settings</a></li>\n<li>On the sidebar, Click on &quot;<a href=\"https://github.com/settings/keys\">SSH and GPG keys</a>&quot;.</li>\n<li>Scroll and click on &quot;New GPG Key&quot; in the &quot;GPG&quot; keys section. (Below the SSH section).</li>\n<li>Paste the text you had copied from the previous command and save.</li>\n</ol>\n<h4 id=\"5-configure-git-to-always-sign-commits\">5. Configure Git to always sign commits</h4>\n<p>Now that you have GPG set up with Git, run the following commands to tell git to always sign your commits with your GPG key.</p>\n<pre class=\"block-code\"><code class=\"language-sh\">git config --global user.signingkey [KEY_ID]\ngit config --global commit.gpgsign <span class=\"hljs-literal\">true</span>\n</code></pre>\n<p>If you do not enable <code>commit.gpgsign</code> you can always sign each commit individually by running <code>git commit -S</code>.</p>\n<p>Now try and commit to one of your projects. And it should show a verified commit.</p>\n<h4 id=\"troubleshooting\">Troubleshooting</h4>\n<p>If you run into issues while on the last part and the response says the commit can&#39;t be verified, try running the following command.</p>\n<pre class=\"block-code\"><code class=\"language-sh\"><span class=\"hljs-built_in\">echo</span> <span class=\"hljs-string\">&quot;test&quot;</span> | gpg --clearsign\n</code></pre>\n<p>If it fails, set the GPG_TTY variable.</p>\n<pre class=\"block-code\"><code class=\"language-sh\"><span class=\"hljs-built_in\">export</span> GPG_TTY=$(<span class=\"hljs-built_in\">tty</span>)\n</code></pre>\n<p>Then try re-running the command and it should be successful.</p>\n<p>It is also a good idea to kill the GPG client so that it asks for the password the first time.</p>\n<pre class=\"block-code\"><code class=\"language-sh\">gpgconf --<span class=\"hljs-built_in\">kill</span> all\ngpg-agent --daemon\n</code></pre>\n<h3 id=\"sources\">Sources</h3>\n<ul>\n<li><a href=\"https://daily-dev-tips.com/posts/how-to-verify-your-commits-on-github/\">Verifying GPG keys on Daily Dev Tips</a>.</li>\n<li><a href=\"https://kbroman.org/github_tutorial/pages/first_time.html\">Your First time on Git by Karl Broman</a></li>\n</ul>\n</article><footer class=\"footer\"><hr /><a href=\"#top\" class=\"top\">↑ Scroll to Top</a></footer></main></div><script src=\"/js/bundle.js\" defer=\"defer\"></script></body></html>",
            "url": "https://vixalien.com/post/setup-git",
            "title": "Setup Git",
            "summary": "How I set up Git on my systems with using opinionated defaults.",
            "date_modified": "2022-03-31T23:47:12.886Z",
            "author": {
                "name": "Angelo Verlain",
                "url": "https://vixalien.com"
            }
        },
        {
            "id": "explosiv-blog",
            "content_html": "<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"utf-8\" /><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\" /><meta name=\"theme-color\" content=\"#030f1b\" /><link rel=\"stylesheet\" href=\"/css/app.css\" /><link rel=\"shortcut icon\" href=\"/favicon.ico\" /><link rel=\"manifest\" href=\"/manifest.json\" /><link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"/favicon/android-chrome-192x192.png\" /><link rel=\"alternate\" type=\"application/rss+xml\" title=\"RSS\" href=\"https://vixalien.ga/feed/feed.rss\" /><link rel=\"alternate\" type=\"application/atom+xml\" title=\"Atom\" href=\"https://vixalien.ga/feed/feed.atom\" /><link rel=\"alternate\" type=\"application/json\" title=\"JSON\" href=\"https://vixalien.ga/feed/feed.json\" /><title>Building a blog with Explosiv - vixalien</title><link rel=\"canonical\" href=\"https://www.vixalien.com/post/explosiv-blog\" /><meta name=\"description\" content=\"Building a static lightweight and fast blog with Explosiv.\" /><link rel=\"stylesheet\" href=\"/css/highlight.css\" /></head><body><script src=\"/js/config.js\"></script><div class=\"root\"><main style=\"\" id=\"main\" class=\" container\"><header><nav><a href=\"/\">← vixalien's blog</a></nav></header><div class=\"intro\"><small>Sun Dec 19 2021</small><br /><h1>Building a blog with Explosiv</h1></div><p>Building a static lightweight and fast blog with Explosiv.</p><hr /><br /><article><p>Earlier this year, I created <a href=\"https://github.com/vixalien/explosiv\">Explosiv ↗</a>, a lightweight &amp; fast static site generator that allows pages to be built with JSX. This is a tutorial on how to build a functional blog with Explosiv.</p>\n<h1 id=\"terminology\">Terminology</h1>\n<p>We&#39;ll first talk about how the blog will be built. You can directly <a href=\"#code\">jump to the programming part</a> or directly view <a href=\"https://github.com/vixalien/explosiv-blog\">the source code of the final blog on Github</a>.</p>\n<h2 id=\"whats-in-this-blog\">What&#39;s in <em>this blog</em>?</h2>\n<p>The blog will be a simple one with room for improvement (I invite you to be creative.) It will simply render a homepage, an about page and a group of posts. That&#39;s it. We&#39;ll not be using any heavy styling or custom components library. Of course we&#39;ll use <strong>Explosiv</strong> to build the blog and we&#39;ll write the blog posts themselves in <strong>Markdown</strong>.</p>\n<h2 id=\"explosiv\">Explosiv?</h2>\n<p><a href=\"https://github.com/vixalien/explosiv\">Explosiv ↗</a> is a NodeJS framework that uses JSX to render pages. It transforms <code>.jsx</code> files into <code>.html</code> files. That is: you write code that uses components, run js etc and Explosiv convert them into native HTML ready to be displayed to your favorite web browser.</p>\n<h2 id=\"jsx\">JSX?</h2>\n<p><a href=\"https://reactjs.org/docs/introducting-jsx.html\">JSX ↗</a> stands for <strong>XHTML in JSX</strong> and it allows you to write HTML inside JS files simplifying data binding. JSX was created by the React team and is famously used within React so if you come from React, Explosiv will be easy for you to understand because it uses that same loved JSX syntax. Here is an example of JSX syntax.</p>\n<pre class=\"block-code\"><code class=\"language-jsx\"><span class=\"hljs-comment\">// JSX syntax is coool!</span>\n<span class=\"hljs-keyword\">let</span> <span class=\"hljs-title function_\">Site</span> = (<span class=\"hljs-params\">data</span>) =&gt; {\n    <span class=\"hljs-keyword\">return</span> <span class=\"language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div</span>&gt;</span>Hello {data.name}!<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">div</span>&gt;</span></span>\n}\n</code></pre>\n<details><summary>Why not use React instead? or NextJS? or Gatsby? - Rant</summary>\n\n<p>&nbsp;</p>\n<h2 id=\"why-not-use-react-instead-or-nextjs-or-gatsby\">Why not use React instead? or NextJS? or Gatsby?</h2>\n<p>React is only a library. React is in the core of NextJS or Gatsby and they all use it to create their own opinionated way of rendering React pages into HTML pages.</p>\n<p><a href=\"https://nextjs.org\">NextJS ↗</a> is a framework created by Vercel and it provides many features to build very complex web apps: API Routes, Internationalisation, Analytics, Typescript, Image Optimization. It&#39;s many features means you can use it to create any type of website, from TikTok to Twitch to <a href=\"https://nextjs.org/showcase\">others ↗</a>. However this means that it&#39;s also pretty bloated for simple websites like blogs where you end up not using much of the features. And the site ends up containing many and many JS files you&#39;ll not use and takes some time to load.</p>\n<p><div class=\"block-image\">\n\t\t\t\t<img src=\"/images/posts/explosiv-blog/nextjs-waterfall.png\" alt=\"NextJS waterfall\" loading=\"lazy\">\n\t\t\t\t<div class=\"text\" aria-hidden=\"true\"><small>NextJS waterfall - <a href=\"/images/posts/explosiv-blog/nextjs-waterfall.png\" target=\"_blank\">View Image ↗</a></small></div>\n\t\t\t</div></p>\n<p>As you can see in the above screenshot from <a href=\"https://www.joshwcomeau.com/blog/how-i-built-my-blog\">https://www.joshwcomeau.com/blog/how-i-built-my-blog</a>. NextJS served more than 120 requests weighing 6 MBs in 13 seconds. Hmm??</p>\n<p><a href=\"https://www.gatsbyjs.com/\">Gatsby ↗</a> touts itself as a fast static site generator that also uses React. <a href=\"https://news.ycombinator.com/item?id=24670252\">It is NOT fast ↗</a>. It takes about 30 seconds to make a production build. Imagine what would happen if you customize your site. Plus there are also some features that I think are overkill like GraphQL integrations. I mean I get it, but I would like to install GraphQL as a plugin, not baked into my static site that won&#39;t use it</p>\n<hr></details><br><br>\n\n\n<h2 id=\"markdown\">Markdown?</h2>\n<p><a href=\"https://www.markdownguide.org/getting-started/\">Markdown</a> is a lightweight language that will convert plain text to formatted text. It&#39;s the language we&#39;ll use to write our own blog posts. It is used by bloggers, software developers and documentation writers. All those <code>README.md</code> files on GitHub are Markdown!. You can view the simple syntax of Markdown here:</p>\n<pre class=\"block-code\"><code class=\"language-md\"><span class=\"hljs-section\"># This is a heading</span>\n\nThis is a paragraph wil <span class=\"hljs-emphasis\">_emphasized_</span> and <span class=\"hljs-strong\">**strongly emphasized**</span> text. And this is [<span class=\"hljs-string\">a link to Google</span>](<span class=\"hljs-link\">https://google.com</span>)\n\n<span class=\"hljs-bullet\">1.</span> This is an ordered list\n<span class=\"hljs-bullet\">2.</span> Another list item\n<span class=\"hljs-bullet\">3.</span> - A nested unordered list\n<span class=\"hljs-bullet\">   -</span> Another list item.\n</code></pre>\n<p>This blog post you are reading is written in markdown too! You can <a href=\"https://github.com/vixalien/dotio2/blob/main/blog/explosiv-blog.md\">view the source code here ↗</a>.</p>\n<h1 id=\"code\">Code</h1>\n<p>Explosiv is a NodeJS framework. That means you&#39;ll need to have NodeJS installed first. NodeJS comes with a package manager called <code>npm</code> and we&#39;ll use it to install Explosiv.</p>\n<h2 id=\"1-install-explosiv\">1. Install Explosiv</h2>\n<p>The first step is creating a folder for your blog. I used <code>explosiv-blog</code> for mine. Open the folder in your favorite shell (or command prompt or command line interface). You&#39;ll first need to initialize the folder as a NodeJS project.</p>\n<pre class=\"block-code\"><code class=\"language-bash\">npm init -y\n</code></pre>\n<p>NPM will generate a <code>package.json</code> that will be used to identify your app and manage your dependencies. The next step is to install Explosiv.</p>\n<pre class=\"block-code\"><code class=\"language-bash\">npm install explosiv\n</code></pre>\n<p>You&#39;re now ready to start building with Explosiv.</p>\n<h2 id=\"2-create-homepage-and-about-page\">2. Create homepage and about page.</h2>\n<p>Now go ahead and create a folder called <code>pages</code> at the root of your project. This folder will hold all Explosiv pages.</p>\n<h3 id=\"homepage\">Homepage</h3>\n<p>Create a file called <code>index.js</code> for our homepage. <code>index</code> is a special name as it denotes that this file will be the first one that the user sees when they visit our site for the first time. Add some simple JSX to our index page to show a warm welcome message to visitors of the blog.</p>\n<pre class=\"block-code\"><code class=\"language-jsx\"><span class=\"hljs-comment\">// index.js</span>\n<span class=\"hljs-keyword\">let</span> <span class=\"hljs-title function_\">Homepage</span> = (<span class=\"hljs-params\"></span>) =&gt; {\n    <span class=\"hljs-keyword\">return</span> <span class=\"language-xml\"><span class=\"hljs-tag\">&lt;&gt;</span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Head</span>&gt;</span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">title</span>&gt;</span>my blog<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">title</span>&gt;</span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">meta</span> <span class=\"hljs-attr\">name</span>=<span class=\"hljs-string\">&quot;description&quot;</span> <span class=\"hljs-attr\">content</span>=<span class=\"hljs-string\">&quot;This is my own blog&quot;</span>/&gt;</span>\n        <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">Head</span>&gt;</span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">main</span>&gt;</span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1</span>&gt;</span>Welcome to my blog<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">h1</span>&gt;</span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p</span>&gt;</span>This is my cool new blog built with Explosiv. <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a</span> <span class=\"hljs-attr\">href</span>=<span class=\"hljs-string\">&quot;/about&quot;</span>&gt;</span>About Me<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">a</span>&gt;</span><span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">p</span>&gt;</span>\n        <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">main</span>&gt;</span>\n    <span class=\"hljs-tag\">&lt;/&gt;</span></span>\n};\n\n<span class=\"hljs-keyword\">export</span> <span class=\"hljs-keyword\">default</span> <span class=\"hljs-title class_\">Homepage</span>;\n</code></pre>\n<p>We can now see how our site will look in the browser. Switch to your shell and run the following command.</p>\n<h3 id=\"explosiv-development-mode\">Explosiv Development mode</h3>\n<pre class=\"block-code\"><code class=\"language-bash\">npx explosiv dev\n</code></pre>\n<p>This will start Explosiv in Development Mode, build the app then serve it locally at <a href=\"http://localhost:3000\">http://localhost:3000</a>. Visit the URL to view the homepage.</p>\n<p><div class=\"block-image\">\n\t\t\t\t<img src=\"/images/posts/explosiv-blog/blog-homepage.png\" alt=\"Blog homepage\" loading=\"lazy\">\n\t\t\t\t<div class=\"text\" aria-hidden=\"true\"><small>Blog homepage - <a href=\"/images/posts/explosiv-blog/blog-homepage.png\" target=\"_blank\">View Image ↗</a></small></div>\n\t\t\t</div></p>\n<h3 id=\"about-page\">About Page</h3>\n<p>Create a file called <code>about.js</code>. This will be our about page and it will be accessible at <code>/about</code> on our website.  Add some JSX for the about page as well.</p>\n<pre class=\"block-code\"><code class=\"language-jsx\"><span class=\"hljs-comment\">// about.js</span>\n<span class=\"hljs-keyword\">let</span> <span class=\"hljs-title function_\">About</span> = (<span class=\"hljs-params\"></span>) =&gt; {\n    <span class=\"hljs-keyword\">return</span> <span class=\"language-xml\"><span class=\"hljs-tag\">&lt;&gt;</span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Head</span>&gt;</span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">title</span>&gt;</span>about my blog<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">title</span>&gt;</span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">meta</span> <span class=\"hljs-attr\">name</span>=<span class=\"hljs-string\">&quot;description&quot;</span> <span class=\"hljs-attr\">content</span>=<span class=\"hljs-string\">&quot;About my blog&quot;</span>/&gt;</span>\n        <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">Head</span>&gt;</span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">main</span>&gt;</span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1</span>&gt;</span>About my blog<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">h1</span>&gt;</span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p</span>&gt;</span>Hey there! Welcome to my new blog built with Explosiv. Here you can find all my blog posts. <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a</span> <span class=\"hljs-attr\">href</span>=<span class=\"hljs-string\">&quot;/&quot;</span>&gt;</span>Go back to homepage<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">a</span>&gt;</span><span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">p</span>&gt;</span>\n        <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">main</span>&gt;</span>\n    <span class=\"hljs-tag\">&lt;/&gt;</span></span>\n};\n\n<span class=\"hljs-keyword\">export</span> <span class=\"hljs-keyword\">default</span> <span class=\"hljs-title class_\">About</span>;\n</code></pre>\n<p>Now go to <a href=\"http://localhost:3000/about\">http://localhost:3000/about</a> to view the about page. Note that Explosiv automatically rebuilt the app because we started explosiv in development mode.</p>\n<blockquote>\n<p><strong>ProTip:</strong> Creating a page at <code>pages/about.js</code> is equivalent to creating one at <code>pages/about/index.js</code>.</p>\n</blockquote>\n<h2 id=\"3-styling\">3. Styling</h2>\n<p>Now the page looks a little bit ugly doesn&#39;t it? We can add CSS styles to make our site look nicer. We&#39;ll create a folder called <code>public/</code> and create a stylesheet at <code>public/app.css</code>. Files in the <code>public/</code> folder will be publicly accessible so you can visit <a href=\"http://localhost:3000/app.css\">http://localhost:3000/app.css</a> to view the stylesheet.</p>\n<pre class=\"block-code\"><code class=\"language-css\"><span class=\"hljs-comment\">/* public/app.css */</span>\n<span class=\"hljs-selector-tag\">body</span> {\n  <span class=\"hljs-attribute\">max-width</span>: <span class=\"hljs-number\">600px</span>;\n  <span class=\"hljs-attribute\">padding</span>: <span class=\"hljs-number\">0</span> <span class=\"hljs-number\">20px</span>;\n  <span class=\"hljs-attribute\">margin</span>: <span class=\"hljs-number\">0</span> auto;\n  <span class=\"hljs-attribute\">font-family</span>: system-ui, -apple-system, <span class=\"hljs-string\">&quot;Segoe UI&quot;</span>, <span class=\"hljs-string\">&quot;Roboto&quot;</span>, <span class=\"hljs-string\">&quot;Ubuntu&quot;</span>, <span class=\"hljs-string\">&quot;Cantarell&quot;</span>, <span class=\"hljs-string\">&quot;Noto Sans&quot;</span>, sans-serif, <span class=\"hljs-string\">&quot;Apple Color Emoji&quot;</span>, <span class=\"hljs-string\">&quot;Segoe UI Emoji&quot;</span>, <span class=\"hljs-string\">&quot;Segoe UI Symbol&quot;</span>, <span class=\"hljs-string\">&quot;Noto Color Emoji&quot;</span>\n}\n</code></pre>\n<p>Now to allow Explosiv to include the above CSS, create a document file at <code>pages/_document.js</code> to customize the overall behavior of the blog.</p>\n<pre class=\"block-code\"><code class=\"language-jsx\"><span class=\"hljs-comment\">// pages/_document.js</span>\n<span class=\"hljs-keyword\">let</span> <span class=\"hljs-title function_\">Document</span> = (<span class=\"hljs-params\"></span>) =&gt; {\n    <span class=\"hljs-keyword\">return</span> (<span class=\"language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">html</span> <span class=\"hljs-attr\">lang</span>=<span class=\"hljs-string\">&quot;en&quot;</span>&gt;</span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">head</span>&gt;</span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">meta</span> <span class=\"hljs-attr\">charset</span>=<span class=\"hljs-string\">&quot;utf-8&quot;</span>/&gt;</span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">meta</span> <span class=\"hljs-attr\">name</span>=<span class=\"hljs-string\">&quot;viewport&quot;</span> <span class=\"hljs-attr\">content</span>=<span class=\"hljs-string\">&quot;width=device-width,initial-scale=1&quot;</span>/&gt;</span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">link</span> <span class=\"hljs-attr\">rel</span>=<span class=\"hljs-string\">&quot;stylesheet&quot;</span> <span class=\"hljs-attr\">href</span>=<span class=\"hljs-string\">&quot;/app.css&quot;</span>/&gt;</span>\n        <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">head</span>&gt;</span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">body</span>&gt;</span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div</span> <span class=\"hljs-attr\">class</span>=<span class=\"hljs-string\">&quot;root&quot;</span>&gt;</span><span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">div</span>&gt;</span>\n        <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">body</span>&gt;</span>\n    <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">html</span>&gt;</span></span>)\n}\n\n<span class=\"hljs-keyword\">export</span> <span class=\"hljs-keyword\">default</span> <span class=\"hljs-title class_\">Document</span>;\n</code></pre>\n<p>The <code>_document.js</code> file is a special one because it provides a wrapper to the whole site, hence it can be used to customize the site. Let&#39;s explain the components of this <code>_document.js</code>:</p>\n<ul>\n<li><code>&lt;html lang=&quot;en&quot;&gt;</code> specify the language of our site.</li>\n<li><code>&lt;meta charset=&quot;utf-8&quot;/&gt;</code> to specify the character set of our site to prevent incorrect renderings of our site&#39;s text.</li>\n<li><code>&lt;meta name=&quot;viewport&quot;&gt;</code> to correctly scale the site for mobile users.</li>\n<li><code>&lt;link rel=&quot;stylesheet&quot;&gt;</code> to allow web browsers to fetch our stylesheet.</li>\n<li><code>&lt;div class=&quot;root&quot;&gt;&lt;/div&gt;</code> where the main page&#39;s content will be rendered.</li>\n</ul>\n<p>You can now refresh <a href=\"http://localhost:3000\">http://localhost:3000</a> in your browser to see the updated page.</p>\n<p><div class=\"block-image\">\n\t\t\t\t<img src=\"/images/posts/explosiv-blog/styled-blog-homepage.png\" alt=\"Looks better already\" loading=\"lazy\">\n\t\t\t\t<div class=\"text\" aria-hidden=\"true\"><small>Looks better already - <a href=\"/images/posts/explosiv-blog/styled-blog-homepage.png\" target=\"_blank\">View Image ↗</a></small></div>\n\t\t\t</div></p>\n<p>Now you know how to add custom styles, the limit is the sky. You can start to style your app this way. You can even use PostCSS or Stylus to build stylesheets faster.</p>\n<h2 id=\"4-blog-posts\">4. Blog Posts</h2>\n<h3 id=\"writing-the-first-blog-post\">Writing the first blog post</h3>\n<p>Off to writing the real posts now. Create a blog post at <code>blog/first-post.md</code>:</p>\n<pre class=\"block-code\"><code class=\"language-markdown\">---\ntitle: My First Blog Post\ndescription: &quot;The first blog post to be created on this site.&quot;\n<span class=\"hljs-section\">created: 1639915508100\n---</span>\n\nHello people, a warm welcome to you. This is the first blog post on this site.\n</code></pre>\n<blockquote>\n<p><strong>Note:</strong> Notice the block at the beginning of the file that starts and ends with <code>---</code>. This is called Front Matter and is used to describe the blog posts like who wrote it, the title, when was it written etc. Also, be sure to update the <code>created</code> field to show the real time you created it. <a href=\"https://vixalien.com/date\">View time in terms of milliseconds after the UNIX epoch</a>.</p>\n</blockquote>\n<h3 id=\"showing-the-blog-posts-on-the-homepage\">Showing the blog posts on the homepage</h3>\n<p>Now comes the part that requires us to be a little bit ingenious. We are going to show all the blog posts on the homepage and provide links to them.</p>\n<p>First of all, we&#39;ll be installing 2 other dependencies to allow us deal with Markdown files.</p>\n<pre class=\"block-code\"><code class=\"language-bash\">npm install front-matter marked\n</code></pre>\n<ul>\n<li><code>front- matter</code>: Allows use to parse page&#39;s front matter.</li>\n<li><code>marked</code>: Allows use to parse Markdown files into HTML.</li>\n</ul>\n<p> We are going to write a script at <code>src/posts.js</code> that loads all blog posts then give us info about them.</p>\n<pre class=\"block-code\"><code class=\"language-js\"><span class=\"hljs-comment\">// src/posts.js</span>\n\n<span class=\"hljs-comment\">// Import dependencies</span>\n<span class=\"hljs-keyword\">let</span> path = <span class=\"hljs-built_in\">require</span>(<span class=\"hljs-string\">&quot;path&quot;</span>);\n<span class=\"hljs-keyword\">let</span> fs = <span class=\"hljs-built_in\">require</span>(<span class=\"hljs-string\">&quot;fs&quot;</span>);\n<span class=\"hljs-keyword\">let</span> fm = <span class=\"hljs-built_in\">require</span>(<span class=\"hljs-string\">&quot;front-matter&quot;</span>);\n\n<span class=\"hljs-comment\">// This function resolves where files or folders are relative to the `cwd` or current working directory.</span>\n<span class=\"hljs-keyword\">let</span> <span class=\"hljs-title function_\">resolve</span> = (<span class=\"hljs-params\">...link</span>) =&gt; path.<span class=\"hljs-title function_\">resolve</span>(process.<span class=\"hljs-title function_\">cwd</span>(), ...link);\n\n<span class=\"hljs-comment\">// Where all our blog posts are stored</span>\n<span class=\"hljs-keyword\">let</span> blogsPath = <span class=\"hljs-title function_\">resolve</span>(<span class=\"hljs-string\">&quot;blog&quot;</span>);\n\n<span class=\"hljs-keyword\">let</span> blogs = fs\n    <span class=\"hljs-comment\">// Get all blog posts in the `blogsPath` folder.</span>\n    .<span class=\"hljs-title function_\">readdirSync</span>(blogsPath)\n    .<span class=\"hljs-title function_\">map</span>(<span class=\"hljs-function\">(<span class=\"hljs-params\">blog</span>) =&gt;</span> {\n         <span class=\"hljs-comment\">// Get the slug. i.e `first-post` from `first-post.md`</span>\n        <span class=\"hljs-keyword\">let</span> slug = blog.<span class=\"hljs-title function_\">replace</span>(<span class=\"hljs-regexp\">/\\.md$/</span>, <span class=\"hljs-string\">&quot;&quot;</span>);\n        <span class=\"hljs-comment\">// And return an array of posts and their front matter</span>\n        <span class=\"hljs-comment\">// Example: [ &quot;first-post&quot;, { title: &quot;My First Blog Post&quot;, created: 1639915508100, description: &quot;...&quot; } ]</span>\n        <span class=\"hljs-keyword\">return</span> [\n            slug,\n            { slug, ...<span class=\"hljs-title function_\">fm</span>(fs.<span class=\"hljs-title function_\">readFileSync</span>(<span class=\"hljs-title function_\">resolve</span>(blogsPath, blog), <span class=\"hljs-string\">&quot;utf8&quot;</span>)).<span class=\"hljs-property\">attributes</span> },\n        ]\n    })\n    <span class=\"hljs-comment\">// Sort the blog posts by date created</span>\n    .<span class=\"hljs-title function_\">sort</span>(<span class=\"hljs-function\">(<span class=\"hljs-params\">[_, a], [$, b]</span>) =&gt;</span> b.<span class=\"hljs-property\">created</span> - a.<span class=\"hljs-property\">created</span>);\n\n<span class=\"hljs-comment\">// Export the posts as an object</span>\n<span class=\"hljs-variable language_\">module</span>.<span class=\"hljs-property\">exports</span> = <span class=\"hljs-title class_\">Object</span>.<span class=\"hljs-title function_\">fromEntries</span>(blogs);\n</code></pre>\n<p>We are then going to display all blog posts on the homepage. To do this, we&#39;ll create a component at <code>components/posts.js</code> that uses the post data to display a list of info about posts.</p>\n<pre class=\"block-code\"><code class=\"language-jsx\"><span class=\"hljs-comment\">// components/posts.js</span>\n<span class=\"hljs-comment\">// Load the posts as an object.</span>\n<span class=\"hljs-keyword\">import</span> postsJSON <span class=\"hljs-keyword\">from</span> <span class=\"hljs-string\">&quot;../src/posts&quot;</span>;\n\n<span class=\"hljs-keyword\">let</span> <span class=\"hljs-title function_\">PostsCard</span> = (<span class=\"hljs-params\">{ ...props }</span>) =&gt; {\n    <span class=\"hljs-comment\">// Convert the posts object into an array.</span>\n    <span class=\"hljs-keyword\">let</span> posts = <span class=\"hljs-title class_\">Object</span>.<span class=\"hljs-title function_\">entries</span>(postsJSON)\n\n    <span class=\"hljs-keyword\">return</span> (\n        <span class=\"language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p</span>&gt;</span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h2</span>&gt;</span>Posts<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">h2</span>&gt;</span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div</span> <span class=\"hljs-attr\">className</span>=<span class=\"hljs-string\">&quot;posts&quot;</span>&gt;</span>\n                 {/* Display the posts one by one */}\n                 {/* Display each post&#x27;s title, date of creation and description with a link to read the post */}\n                {posts.map(([slug, { title, description, created }]) =&gt; (\n                    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p</span>&gt;</span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a</span> <span class=\"hljs-attr\">href</span>=<span class=\"hljs-string\">{</span>&quot;/<span class=\"hljs-attr\">post</span>/&quot; + <span class=\"hljs-attr\">slug</span>}&gt;</span>{title} <span class=\"hljs-symbol\">&amp;rarr;</span><span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">a</span>&gt;</span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">br</span>/&gt;</span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">small</span>&gt;</span>{new Date(created).toDateString()}<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">small</span>&gt;</span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">br</span>/&gt;</span>\n                        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span</span>&gt;</span>{description}<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">span</span>&gt;</span>\n                    <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">p</span>&gt;</span>\n                ))}\n            <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">div</span>&gt;</span>\n        <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">p</span>&gt;</span></span>\n    );\n};\n\n<span class=\"hljs-keyword\">export</span> <span class=\"hljs-keyword\">default</span> <span class=\"hljs-title class_\">PostsCard</span>;\n</code></pre>\n<p>We&#39;ll then modify <code>pages/index.js</code> to show blog posts using the newly created component on the homepage.</p>\n<pre class=\"block-code\"><code class=\"language-jsx\"><span class=\"hljs-comment\">// index.js</span>\n<span class=\"hljs-keyword\">import</span> <span class=\"hljs-title class_\">PostsCard</span> <span class=\"hljs-keyword\">from</span> <span class=\"hljs-string\">&quot;../components/posts.js&quot;</span>;\n\n<span class=\"hljs-keyword\">let</span> <span class=\"hljs-title function_\">Homepage</span> = (<span class=\"hljs-params\"></span>) =&gt; {\n    <span class=\"hljs-keyword\">return</span> <span class=\"language-xml\"><span class=\"hljs-tag\">&lt;&gt;</span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Head</span>&gt;</span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">title</span>&gt;</span>my blog<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">title</span>&gt;</span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">meta</span> <span class=\"hljs-attr\">name</span>=<span class=\"hljs-string\">&quot;description&quot;</span> <span class=\"hljs-attr\">content</span>=<span class=\"hljs-string\">&quot;This is my own blog&quot;</span>/&gt;</span>\n        <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">Head</span>&gt;</span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">main</span>&gt;</span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1</span>&gt;</span>Welcome to my blog<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">h1</span>&gt;</span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p</span>&gt;</span>This is my cool new blog built with Explosiv. <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a</span> <span class=\"hljs-attr\">href</span>=<span class=\"hljs-string\">&quot;/about&quot;</span>&gt;</span>About Me<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">a</span>&gt;</span><span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">p</span>&gt;</span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">PostsCard</span>/&gt;</span>\n        <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">main</span>&gt;</span>\n    <span class=\"hljs-tag\">&lt;/&gt;</span></span>\n};\n\n<span class=\"hljs-keyword\">export</span> <span class=\"hljs-keyword\">default</span> <span class=\"hljs-title class_\">Homepage</span>;\n</code></pre>\n<p>At this point you can visit <a href=\"http://localhost:3000\">http://localhost:3000</a> to view the site in a web browser. Notice the list of posts</p>\n<p><div class=\"block-image\">\n\t\t\t\t<img src=\"/images/posts/explosiv-blog/blog-homepage-with-posts.png\" alt=\"Blog Homepage with Posts\" loading=\"lazy\">\n\t\t\t\t<div class=\"text\" aria-hidden=\"true\"><small>Blog Homepage with Posts - <a href=\"/images/posts/explosiv-blog/blog-homepage-with-posts.png\" target=\"_blank\">View Image ↗</a></small></div>\n\t\t\t</div></p>\n<h3 id=\"showing-the-blog-posts-on-their-urls\">Showing the blog posts on their URLs</h3>\n<p>Yay!! Our blog can now show posts. But if you click on the link to read the blog post, you&#39;ll reach a 404 page. We are going to create a page that will render each blog post to allow readers to read it.</p>\n<h4 id=\"meet-dynamic-pages\">Meet dynamic pages</h4>\n<p>We would need to write each blog&#39;s page like <code>/pages/post/first-blog.js</code> and <code>/pages/post/second-blog.js</code> etc. However, there is a feature called <strong>Dynamic Pages</strong> that simplify the development of related pages. We will be creating one single dynamic page at <code>/pages/post/[slug].js</code> that will render each post according to the <code>[slug]</code> provided. For example, visiting <code>/post/first-blog</code> will render <code>/pages/post/[slug].js</code> with a <code>slug</code> that is equal to <code>first-blog</code>.</p>\n<blockquote>\n<p><strong>Note:</strong> You can change <code>[slug]</code> to any other name you like. For example <code>[id]</code> or <code>[post]</code>. However, it is important to enclose the slug in brackets (<code>[]</code>).</p>\n</blockquote>\n<pre class=\"block-code\"><code class=\"language-jsx\"><span class=\"hljs-comment\">// pages/post/[slug].js</span>\n\n<span class=\"hljs-comment\">// Import dependencies, will be used later</span>\n<span class=\"hljs-keyword\">import</span> { promises <span class=\"hljs-keyword\">as</span> fs } <span class=\"hljs-keyword\">from</span> <span class=\"hljs-string\">&#x27;fs&#x27;</span>\n<span class=\"hljs-keyword\">import</span> path <span class=\"hljs-keyword\">from</span> <span class=\"hljs-string\">&#x27;path&#x27;</span>\n<span class=\"hljs-keyword\">import</span> matter <span class=\"hljs-keyword\">from</span> <span class=\"hljs-string\">&#x27;front-matter&#x27;</span>\n<span class=\"hljs-keyword\">import</span> { marked } <span class=\"hljs-keyword\">from</span> <span class=\"hljs-string\">&#x27;marked&#x27;</span>\n\n<span class=\"hljs-comment\">// The Post component will be used to render each post</span>\n<span class=\"hljs-keyword\">const</span> <span class=\"hljs-title function_\">Post</span> = (<span class=\"hljs-params\">{ post }</span>) =&gt; (\n    <span class=\"language-xml\"><span class=\"hljs-tag\">&lt;&gt;</span>\n        {/* Add a HEAD that shows the title of the page and expose the description of the post */}\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Head</span>&gt;</span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">title</span>&gt;</span>{post.attributes.title} - vixalien<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">title</span>&gt;</span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">meta</span> <span class=\"hljs-attr\">name</span>=<span class=\"hljs-string\">&quot;description&quot;</span> <span class=\"hljs-attr\">content</span>=<span class=\"hljs-string\">{post.attributes.description}</span> /&gt;</span>\n        <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">Head</span>&gt;</span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">main</span>&gt;</span>\n            {/* Show a link to the homepage */}\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div</span> <span class=\"hljs-attr\">style</span>=<span class=\"hljs-string\">{{marginTop:</span>&quot;<span class=\"hljs-attr\">20px</span>&quot;}}&gt;</span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a</span> <span class=\"hljs-attr\">href</span>=<span class=\"hljs-string\">&quot;/&quot;</span>&gt;</span>Homepage<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">a</span>&gt;</span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">br</span>/&gt;</span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">br</span>/&gt;</span><span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">div</span>&gt;</span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">small</span>&gt;</span>{new Date(post.attributes.created).toDateString()}<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">small</span>&gt;</span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1</span>&gt;</span>{post.attributes.title}<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">h1</span>&gt;</span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p</span>&gt;</span>{post.attributes.description}<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">p</span>&gt;</span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div</span>&gt;</span>===<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">div</span>&gt;</span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">br</span>/&gt;</span>\n            {/* Render the post&#x27;s content as HTML in an `article` tag */}\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">article</span> <span class=\"hljs-attr\">html</span>=<span class=\"hljs-string\">{post.content}/</span>&gt;</span>\n        <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">main</span>&gt;</span>\n    <span class=\"hljs-tag\">&lt;/&gt;</span></span>\n)\n\n<span class=\"hljs-keyword\">export</span> <span class=\"hljs-keyword\">default</span> <span class=\"hljs-title class_\">Post</span>;\n</code></pre>\n<h4 id=\"getpaths-and-getprops\"><code>getPaths</code> and <code>getProps</code></h4>\n<p>However, the above content is not enough for a dynamic page to work. For it to work correctly, we need to export 2 other functions beside the default export which is the main page JSX.</p>\n<p>The first needed export is <code>getPaths</code> and it is used to determine the number of all acceptable paths (or slugs). For example, it can be used to allow <code>/post/first-blog</code> to be rendered and <code>/post/unknown-post</code> to return a 404 page (Not Found). In our case, it&#39;s pretty straightforward to know the range of acceptable slugs. We just read the <code>blog</code> folder and see which blog posts are there:</p>\n<pre class=\"block-code\"><code class=\"language-jsx\"><span class=\"hljs-comment\">// Append to the end of `pages/post/[slug].js`</span>\n<span class=\"hljs-keyword\">export</span> <span class=\"hljs-keyword\">const</span> getPaths = <span class=\"hljs-keyword\">async</span> () =&gt; {\n    <span class=\"hljs-comment\">// Read all files in the `blog` folder.</span>\n    <span class=\"hljs-keyword\">const</span> files = <span class=\"hljs-keyword\">await</span> fs.<span class=\"hljs-title function_\">readdir</span>(path.<span class=\"hljs-title function_\">resolve</span>(<span class=\"hljs-string\">&#x27;blog&#x27;</span>))\n    <span class=\"hljs-comment\">// Remove the training extensions like `.md` (remove the 3 last characters of filename)</span>\n    <span class=\"hljs-keyword\">return</span> files.<span class=\"hljs-title function_\">map</span>(<span class=\"hljs-function\">(<span class=\"hljs-params\">filename</span>) =&gt;</span> filename.<span class=\"hljs-title function_\">slice</span>(<span class=\"hljs-number\">0</span>, filename.<span class=\"hljs-property\">length</span> - <span class=\"hljs-number\">3</span>))\n}\n</code></pre>\n<p>Now that we know what posts are there, we&#39;ll use <code>getProps</code> to read info about the post themselves given the slug. The <code>getProps</code> function is provided with a <code>slug</code> and use it to get information that will be passed to default export of the function (as props.)</p>\n<pre class=\"block-code\"><code class=\"language-jsx\"><span class=\"hljs-comment\">// Append to the end of `pages/post/[slug].js`</span>\n<span class=\"hljs-keyword\">export</span> <span class=\"hljs-keyword\">const</span> getProps = <span class=\"hljs-keyword\">async</span> (slug) =&gt; {\n    <span class=\"hljs-comment\">// Read the file named `slug`+.md in the `blog` directory with the utf-8 format.</span>\n    <span class=\"hljs-keyword\">let</span> post = <span class=\"hljs-keyword\">await</span> fs.<span class=\"hljs-title function_\">readFile</span>(path.<span class=\"hljs-title function_\">join</span>(<span class=\"hljs-string\">&#x27;blog&#x27;</span>, <span class=\"hljs-string\">`<span class=\"hljs-subst\">${slug}</span>.md`</span>), <span class=\"hljs-string\">&#x27;utf-8&#x27;</span>)\n    <span class=\"hljs-comment\">// uses the `front-matter` package to get the post&#x27;s attributes.</span>\n    post = <span class=\"hljs-title function_\">matter</span>(post)\n\n    <span class=\"hljs-comment\">// parse the post&#x27;s body to get the raw HTML content.</span>\n    post.<span class=\"hljs-property\">content</span> = <span class=\"hljs-title function_\">marked</span>(post.<span class=\"hljs-property\">body</span>)\n    <span class=\"hljs-comment\">// Return an object that will be passed onto the default page export.</span>\n    <span class=\"hljs-keyword\">return</span> { post }\n}\n</code></pre>\n<p>Now visit <a href=\"http://localhost:3000/post/first-blog\">http://localhost:3000/post/first-blog</a> to read <code>first-blog</code>.</p>\n<p><div class=\"block-image\">\n\t\t\t\t<img src=\"/images/posts/explosiv-blog/blog-post.png\" alt=\"First Blog\" loading=\"lazy\">\n\t\t\t\t<div class=\"text\" aria-hidden=\"true\"><small>First Blog - <a href=\"/images/posts/explosiv-blog/blog-post.png\" target=\"_blank\">View Image ↗</a></small></div>\n\t\t\t</div></p>\n<h2 id=\"final-steps\">Final Steps</h2>\n<p>Now that you are done, here are a list of things you should do next.</p>\n<ul>\n<li>Visit <a href=\"https://github.com/vixalien/explosiv\">Explosiv</a> on Github for docs, stars etc.</li>\n<li>Host your site on <a href=\"https://vercel.com\">Vercel</a></li>\n<li>Provide feedback in Github Issues</li>\n<li>View the <a href=\"https://github.com/vixalien/dotio2\">source of this site</a>, which is written with Explosiv as well.</li>\n</ul>\n</article><footer class=\"footer\"><hr /><a href=\"#top\" class=\"top\">↑ Scroll to Top</a></footer></main></div><script src=\"/js/bundle.js\" defer=\"defer\"></script></body></html>",
            "url": "https://vixalien.com/post/explosiv-blog",
            "title": "Building a blog with Explosiv",
            "summary": "Building a static lightweight and fast blog with Explosiv.",
            "date_modified": "2021-12-19T12:05:08.100Z",
            "author": {
                "name": "Angelo Verlain",
                "url": "https://vixalien.com"
            }
        },
        {
            "id": "rabbet",
            "content_html": "<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"utf-8\" /><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\" /><meta name=\"theme-color\" content=\"#030f1b\" /><link rel=\"stylesheet\" href=\"/css/app.css\" /><link rel=\"shortcut icon\" href=\"/favicon.ico\" /><link rel=\"manifest\" href=\"/manifest.json\" /><link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"/favicon/android-chrome-192x192.png\" /><link rel=\"alternate\" type=\"application/rss+xml\" title=\"RSS\" href=\"https://vixalien.ga/feed/feed.rss\" /><link rel=\"alternate\" type=\"application/atom+xml\" title=\"Atom\" href=\"https://vixalien.ga/feed/feed.atom\" /><link rel=\"alternate\" type=\"application/json\" title=\"JSON\" href=\"https://vixalien.ga/feed/feed.json\" /><title>How Rabbet Works - vixalien</title><link rel=\"canonical\" href=\"https://www.vixalien.com/post/rabbet\" /><meta name=\"description\" content=\"A lightweight site that allow you to build pages from  links.\" /><link rel=\"stylesheet\" href=\"/css/highlight.css\" /></head><body><script src=\"/js/config.js\"></script><div class=\"root\"><main style=\"\" id=\"main\" class=\" container\"><header><nav><a href=\"/\">← vixalien's blog</a></nav></header><div class=\"intro\"><small>Fri Dec 17 2021</small><br /><h1>How Rabbet Works</h1></div><p>A lightweight site that allow you to build pages from  links.</p><hr /><br /><article><p><strong>Rabbet</strong> is a very small and minimal app that allows users to create pages on the Internet with a set of URLs.</p>\n<p>I will try my best to share how Rabbet works in this short write-up. You can try to browse the source to follow along the explanations.</p>\n<p>Useful links:</p>\n<ul>\n<li><a href=\"https://dash.rabbet.me/account\">Rabbet dashboard ↗</a></li>\n<li><a href=\"https://github.com/vixalien/rabbet3\">Github ↗</a></li>\n<li><a href=\"https://vixalien.rabbet.me/test\">Test Page ↗</a></li>\n</ul>\n<h1 id=\"rabbet-is-a-monorepo\">Rabbet is a monorepo</h1>\n<p>Rabbet is built as a monorepo. That is, it is one repository (folder) but it contain other packages inside of it. The monorepo doesn&#39;t use any repo manager like Lerna or Yarn workspaces as the packages are not tightly coupled. The different packages are for different uses:</p>\n<ul>\n<li><strong>render:</strong> a simple library that consume pages as JSON and return rendered HTML ready to be used in <code>pages</code> or <code>dash</code> to preview pages.</li>\n<li><strong>db:</strong> a library that allows other packages to access the database where the users and pages are stored.</li>\n<li><strong>pages:</strong> the express app that serves the rabbet pages at [username].rabbet.me/[page-slug].</li>\n<li><strong>dash:</strong> a NextJS app that renders the <a href=\"https://dash.rabbet.me/account\">Rabbet dashboard ↗</a> that serves as a front end that allows users to sign in and create pages.</li>\n</ul>\n<h2 id=\"render\">Render</h2>\n<p><code>render</code> was one of the hardest packages to create. The hardest part is that it has different templates so that a user can choose a template they choose. </p>\n<h3 id=\"templates\">Templates</h3>\n<p>TODO: Allow user to select template in Dashboard UI</p>\n<p>Templates reside in the <code>/templates</code> directory. The default template is called <strong>Lnks.</strong> Templates favorably use <strong>React</strong> and <strong>Stylus</strong> to render HTML and CSS respectively. Because the <code>render</code> package is meant to be run in the browser, Templates can&#39;t access the filesystem. So the template is split into 2 files:</p>\n<h4 id=\"metadatajs\"><code>metadata.js</code></h4>\n<p>This file is run at build time and is used to get all files necessary using <code>require</code> statements. For example, <strong>Lnks</strong> use <code>metadata.js</code> to load it&#39;s JSX file (the one that will be used to render the page into HTML.) And the CSS file that will be used to style the rendered page.</p>\n<pre class=\"block-code\"><code class=\"language-js\"><span class=\"hljs-keyword\">const</span> jsFn = <span class=\"hljs-built_in\">require</span>(<span class=\"hljs-string\">&quot;./page.jsx&quot;</span>).<span class=\"hljs-property\">default</span>;\n<span class=\"hljs-keyword\">const</span> cssString = <span class=\"hljs-built_in\">require</span>(<span class=\"hljs-string\">&#x27;./style.css&#x27;</span>);\n\n<span class=\"hljs-variable language_\">module</span>.<span class=\"hljs-property\">exports</span> = <span class=\"hljs-keyword\">async</span> () =&gt; {\n    <span class=\"hljs-keyword\">return</span> { cssString, jsFn };\n}\n</code></pre>\n<h4 id=\"pagejs\"><code>page.js</code></h4>\n<p>This file is used to provide info about the template itself. It exports a JSON object with the following properties and a render function.</p>\n<pre class=\"block-code\"><code class=\"language-js\">{\n    <span class=\"hljs-string\">&quot;label&quot;</span>: <span class=\"hljs-string\">&quot;lnks&quot;</span>,\n    <span class=\"hljs-string\">&quot;settings&quot;</span>: [\n        {\n            <span class=\"hljs-string\">&quot;key&quot;</span>: <span class=\"hljs-string\">&quot;show_rabbet&quot;</span>,\n            <span class=\"hljs-string\">&quot;label&quot;</span>: <span class=\"hljs-string\">&quot;Show Powered by Rabbet&quot;</span>,\n            <span class=\"hljs-string\">&quot;description&quot;</span>: <span class=\"hljs-string\">&quot;Show the text &#x27;Powered by Rabbet&#x27; at the end of the page.&quot;</span>,\n            <span class=\"hljs-string\">&quot;type&quot;</span>: <span class=\"hljs-string\">&quot;boolean&quot;</span>, <span class=\"hljs-comment\">// can be boolean, number, string</span>\n            <span class=\"hljs-string\">&quot;default&quot;</span>: <span class=\"hljs-literal\">true</span>,\n        }\n    ],\n    render,\n};\n</code></pre>\n<p>The settings property affect Settings related to the template itself.</p>\n<p>The render function is a function that is fed the Page JSON and a meta attribute (which is the data returned from <code>metadata.json</code>.) The <code>render</code> function returns an object with properties that will be converted into HTML.</p>\n<pre class=\"block-code\"><code class=\"language-js\"><span class=\"hljs-keyword\">let</span> <span class=\"hljs-title function_\">render</span> = (<span class=\"hljs-params\">page, meta</span>) =&gt; {\n  <span class=\"hljs-keyword\">return</span> {\n    <span class=\"hljs-attr\">title</span>: <span class=\"hljs-string\">&quot;Sample page&quot;</span>,\n    <span class=\"hljs-attr\">about</span>: <span class=\"hljs-string\">&quot;A sample page&quot;</span>,\n    <span class=\"hljs-attr\">scripts</span>: [\n      { <span class=\"hljs-attr\">src</span>: <span class=\"hljs-string\">&quot;https://uri&quot;</span>, <span class=\"hljs-attr\">type</span>: <span class=\"hljs-string\">&quot;module&quot;</span> },\n      { <span class=\"hljs-attr\">html</span>: <span class=\"hljs-string\">&quot;console.log(\\&quot;Hello\\&quot;)&quot;</span> },\n      <span class=\"hljs-string\">&quot;https://uri&quot;</span>,\n      <span class=\"hljs-string\">&quot;console.log(\\&quot;Hello\\&quot;)&quot;</span>\n    ],\n    <span class=\"hljs-attr\">links</span>: [\n      { <span class=\"hljs-attr\">href</span>: <span class=\"hljs-string\">&quot;https://uri&quot;</span>, <span class=\"hljs-attr\">rel</span>: <span class=\"hljs-string\">&quot;stylesheet&quot;</span> },\n      <span class=\"hljs-string\">&quot;https://uri&quot;</span>\n    ],\n    <span class=\"hljs-attr\">styles</span>: [\n      { <span class=\"hljs-attr\">html</span>: <span class=\"hljs-string\">&#x27;body { color: &quot;red&quot; }&#x27;</span> },\n      <span class=\"hljs-string\">&#x27;body { color: &quot;red&quot; } &#x27;</span>\n    ],\n    <span class=\"hljs-attr\">html</span>: <span class=\"hljs-string\">&quot;HTML&quot;</span>\n  }\n}\n</code></pre>\n<p>The <code>html</code> attribute is what will be in the body of the rendered page. The reason for <code>styles</code>, <code>links</code> and <code>scripts</code> is that the template may or may not need some scripts. For example, <strong>Lnks</strong> only use Lite Youtube scripts and external CSSs when the page&#39;s hero is a YouTube Embed.</p>\n<h2 id=\"db\">DB</h2>\n<blockquote>\n<p><strong>Note:</strong> All DB functions are expected to be promises.</p>\n</blockquote>\n<p>This is the most trivial package of all. It provides an <code>/init</code> script that is called before any database operation (may be called multiple times.)  It&#39;s main export is a file that provide a set of trivial operations such as:</p>\n<h3 id=\"db-operations\">DB operations.</h3>\n<ul>\n<li><strong>get(COLLECTION, id):</strong> Get an item with given <code>id</code> from <code>collection</code>.</li>\n<li><strong>set(COLLECTION, id, data, merge = false):</strong> Update <code>data</code> for an item with given <code>id</code> from <code>collection</code> and whether to <code>merge</code> the new data with already exisiting data.</li>\n<li><strong>add(COLLECTION, data):</strong> Add an item with given <code>data</code> to <code>collection</code>. The <code>id</code> is inferred automatically.</li>\n<li><strong>query(COLLECTION, ...queries):</strong> Perform a set of <code>queries</code> on given <code>collection</code>.</li>\n<li><strong>deleteAll(COLLECTION, ...queries):</strong> Delete all records that match a set of <code>queries</code> on given <code>collection</code>.</li>\n</ul>\n<p>A query is built with the exported <code>where</code> property. For example, to get all users who have the given username use:</p>\n<pre class=\"block-code\"><code class=\"language-js\"><span class=\"hljs-keyword\">import</span> db <span class=\"hljs-keyword\">from</span> <span class=\"hljs-string\">&quot;@rabbet/db&quot;</span>;\n\ndb.<span class=\"hljs-title function_\">get</span>(<span class=\"hljs-string\">&quot;users&quot;</span>, db.<span class=\"hljs-title function_\">where</span>(<span class=\"hljs-string\">&quot;username&quot;</span>, <span class=\"hljs-string\">&quot;==&quot;</span>, <span class=\"hljs-string\">&quot;exampleusername&quot;</span>));\n</code></pre>\n<h3 id=\"account-operations\">Account operations</h3>\n<blockquote>\n<p>In the future, all account operations will be moved to <code>/account</code> instead of the current default export.</p>\n</blockquote>\n<ul>\n<li><strong>getCurrentUser():</strong> Get the logged in user or null.</li>\n<li><strong>getRealUser({ uid }):</strong> Get the real user&#39;s info (from the database) based on the <code>uid</code> returned from login.</li>\n<li><strong>onCurrentUserChange(callback):</strong> Calls the given <code>callback</code> when the current user changes (logged out, logged in, loaded, logged out remotely)</li>\n</ul>\n<blockquote>\n<p><strong>Note:</strong> Firebase take a while to initialize so when yu call <code>getCurrentUser</code> for the first time it will always return null. Rabbet doesn&#39;t use <code>getCurrentUser</code> but instead listen to the <code>onCurrentUserChange</code> to get a real result when the user has changed.</p>\n</blockquote>\n<p>Example:</p>\n<pre class=\"block-code\"><code class=\"language-js\"><span class=\"hljs-keyword\">import</span> db <span class=\"hljs-keyword\">from</span> <span class=\"hljs-string\">&quot;@rabbet/db&quot;</span>;\n\n<span class=\"hljs-keyword\">let</span> user = <span class=\"hljs-keyword\">await</span> <span class=\"hljs-title function_\">dbgetCurrentUser</span>();\n</code></pre>\n<h3 id=\"optimized-account-operations\">Optimized Account operations</h3>\n<p>Optimized account operations are located at <code>/account</code>.</p>\n<ul>\n<li><strong>login {}:</strong> Currently an object with <code>{ withGoogle }</code> that launchs a login dialog.</li>\n<li><strong>logout():</strong> Logout from the current device.</li>\n</ul>\n<p>Example:</p>\n<pre class=\"block-code\"><code class=\"language-js\"><span class=\"hljs-keyword\">import</span> account <span class=\"hljs-keyword\">from</span> <span class=\"hljs-string\">&quot;@rabbet/db/account&quot;</span>;\n\nloginWithGoogleButton.<span class=\"hljs-title function_\">addEventListener</span>(<span class=\"hljs-string\">&quot;click&quot;</span>, account.<span class=\"hljs-property\">login</span>.<span class=\"hljs-property\">withGoogle</span>);\nlogoutButton.<span class=\"hljs-title function_\">addEventListener</span>(<span class=\"hljs-string\">&quot;click&quot;</span>, logout);\n</code></pre>\n<h2 id=\"pages\">Pages</h2>\n<p><code>pages</code> is a small Express app that resides at <code>https://rabbet.me</code>. It renders a page from the given url. You can always visit a <a href=\"https://vixalien.rabbet.me/test\">test rabbet page ↗</a>.</p>\n<p>Assuming the root URL is <code>rabbet.me</code>, the pages app routes using the following rules:</p>\n<ul>\n<li><strong>[username].rabbet.me/[slug]:</strong> Return the page with given <code>slug</code> created by user with given <code>username</code>.</li>\n<li><strong>rabbet.me/:</strong> Redirects to Rabbet dashboard.</li>\n<li>A 404 page with a link to the Rabbet dashboard when a resource isn&#39;t found.</li>\n</ul>\n<blockquote>\n<p><strong>Note:</strong> Pages doesn&#39;t currently use the <code>db</code> package but use a custom implementation that access the firebase API using URLs instead of a native driver (library) because it was thought to be faster. TODO: fix this.</p>\n</blockquote>\n<h2 id=\"dash\">Dash</h2>\n<p>This is the dashboard that appears to all visitors of the service. It allows users to log in and create accounts, create, modify and delete pages. It is a NextJS app.</p>\n<p>The package has the following directory structure:</p>\n<div style=\"white-space: break-spaces; font-family: monospace;\">\n\n<p>  <strong>dash</strong>\n  ├─ <strong>components</strong>: Components used throughout the app.\n  ├─ <strong>lib</strong>: Useful libraries and tools.\n  │  ├─ <strong>constants</strong>: Holds app constants.\n  ├─ <strong>pages</strong>: Contains JSX files for the project.\n  │  ├─ <strong>account</strong>: Pages related to user accounts&#39;\n  │  ├─ <strong>pages</strong>: Pages related to linkpages created by users\n  │  ├─ <strong>home</strong>: Homepage: the site which the users see when not logged in.\n  ├─ <strong>public</strong>: Static files\n  ├─ <strong>partials</strong>: Reused high-level components\n  ├─ <strong>schemas</strong>: Validation schemas for different objects\n  ├─ <strong>stores</strong>: Zustand stores for different objects like user, pages etc.\n  ├─ <strong>stylus</strong>: Stylus for the site that will be transcribed into CSS</p>\n</div>\n\n<hr>\n<br/>\n\n<p>If you&#39;ve read this much, you might as well create a PR for a template. Inspirations: <a href=\"https://skepta.orcd.co/all-in\">Orcd ↗</a> <a href=\"https://ada.lnk.to/Intro\">Linkfire ↗</a> <a href=\"https://dev.page/vixalien\">Dev.page ↗</a></p>\n</article><footer class=\"footer\"><hr /><a href=\"#top\" class=\"top\">↑ Scroll to Top</a></footer></main></div><script src=\"/js/bundle.js\" defer=\"defer\"></script></body></html>",
            "url": "https://vixalien.com/post/rabbet",
            "title": "How Rabbet Works",
            "summary": "A lightweight site that allow you to build pages from  links.",
            "date_modified": "2021-12-17T18:57:10.259Z",
            "author": {
                "name": "Angelo Verlain",
                "url": "https://vixalien.com"
            }
        },
        {
            "id": "git",
            "content_html": "<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"utf-8\" /><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\" /><meta name=\"theme-color\" content=\"#030f1b\" /><link rel=\"stylesheet\" href=\"/css/app.css\" /><link rel=\"shortcut icon\" href=\"/favicon.ico\" /><link rel=\"manifest\" href=\"/manifest.json\" /><link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"/favicon/android-chrome-192x192.png\" /><link rel=\"alternate\" type=\"application/rss+xml\" title=\"RSS\" href=\"https://vixalien.ga/feed/feed.rss\" /><link rel=\"alternate\" type=\"application/atom+xml\" title=\"Atom\" href=\"https://vixalien.ga/feed/feed.atom\" /><link rel=\"alternate\" type=\"application/json\" title=\"JSON\" href=\"https://vixalien.ga/feed/feed.json\" /><title>Learn Git! - vixalien</title><link rel=\"canonical\" href=\"https://www.vixalien.com/post/git\" /><meta name=\"description\" content=\"Learn to use Git, a popular Distributed Control System to effectively collaborate and manage your software projects.\" /><link rel=\"stylesheet\" href=\"/css/highlight.css\" /></head><body><script src=\"/js/config.js\"></script><div class=\"root\"><main style=\"\" id=\"main\" class=\" container\"><header><nav><a href=\"/\">← vixalien's blog</a></nav></header><div class=\"intro\"><small>Sun Aug 01 2021</small><br /><h1>Learn Git!</h1></div><p>Learn to use Git, a popular Distributed Control System to effectively collaborate and manage your software projects.</p><hr /><br /><article><p>So now you understand a certain programming language and coffee is your new best friend. But everywhere there is code, you see <strong>Git</strong>. They say a true developer must know Git and here you are, knowing nothing about Git, but longing to getting started.</p>\n<p>I have to admit, Git is as complex as it is popular. However, you don&#39;t need to know all the 160+ commands of Git to do daily operations. Here is a short but comprehensive tutorial that will teach you the most used features of this world-famous version control system.</p>\n<h2 id=\"what-is-a-version-control-system\">What is a Version Control System?</h2>\n<p>A Version Control System (VCS) is a system that track and manages changes to files. A project with a VCS is usually called a <strong>repository</strong> or <strong>repo</strong> for short.</p>\n<p>A VCS allows you to have multiple versions of a project. To visualize the need for a VCS, imagine you are working on a new feature in a project, and a bug that needs to be fixed immediately is reported. With a VCS, you can easily create a new version of your repository, fix the bug, then return to the previous version when you are done fixing the bug. You can also see the different changes you&#39;ve made in your repository over time and can easily rollback when a change is undesired or introduced a bug. If you also modify your files or lose them, you can restore your repository to the last saved snapshot.</p>\n<h2 id=\"what-is-git\">What is Git?</h2>\n<p><strong>Git</strong> is a version control system that manages a collection of files in a certain directory. Git is a <em>Distributed Version Control System.</em> This means Git does not rely on a central server to store all the versions of a project&#39;s files. Instead, every person &quot;clones&quot; a copy of a repository and get all the history and branches (more on that later) of the project. Although the original source code of a repository may be stored on a third-party hosting service like Github, any person can have their own copy of the project.</p>\n<p>Git was created by Linus Torvalds in 2005 for development of the Linux kernel, with other kernel developers contributing to its initial development.</p>\n<h2 id=\"installation\">Installation</h2>\n<blockquote>\n<p><strong>Note: You&#39;ll need to be able to work with the command line fluently before learning Git.</strong> Even though there are Git GUIs, Git itself is a command line application. If you don&#39;t understand the arts of the command line yet, you can check <a href=\"https://www.taniarascia.com/how-to-use-the-command-line-for-apple-macos-and-linux/\">Tania&#39;s command line tutorial</a>.</p>\n</blockquote>\n<p>You can download Git for macOS, Windows, Linux or build it from source from the <a href=\"https://git-scm.com/book/en/v2/Getting-Started-Installing-Git\">Official Git website</a>.</p>\n<p>When you are finished installing, you can check if git is installed by running the following code in your Terminal (or Command Prompt for windows).</p>\n<pre class=\"block-code\"><code class=\"language-sh\">git --version\n</code></pre>\n<p>If you see a result like the following, you are good to go.</p>\n<pre class=\"block-code\"><code>git version 2.30.2.windows.1\n</code></pre>\n<h2 id=\"configuring-git\">Configuring Git</h2>\n<p>After you install Git, you will have to set some configurations. These include your name and email and are used to mark changes that you introduce in a repository. That way, people can see changes you made and contact you easi;y.</p>\n<pre class=\"block-code\"><code class=\"language-sh\">git config --global user.name <span class=\"hljs-string\">&quot;Firstname Lastname&quot;</span>\ngit config --global user.email username@email.com\n</code></pre>\n<p>The above commands tell Git your names and email. Remember to change <code>Firstname Lastname</code> and <code>username@email.com</code> to your own names and email respectively.</p>\n<p>You can type the following command to check the saved config:</p>\n<pre class=\"block-code\"><code class=\"language-sh\">git config --list\n</code></pre>\n<p>And you may get results similar to this:</p>\n<pre class=\"block-code\"><code>color.ui=auto\ncore.editor=&#39;C:\\Program Files\\Sublime Text 3\\subl.exe&#39; -w\ncore.symlinks=true\ncore.eol=lf\nuser.email=username@email.com\nuser.name=Firstname Lastname\n</code></pre>\n<h2 id=\"git-workflow\">Git workflow</h2>\n<p>Any git repository consists of 3 &quot;trees&quot; maintained by Git:</p>\n<ul>\n<li><strong>Working Directory:</strong> This is your folder with the actual files, the one you can see in File Explorer.</li>\n<li><strong>Index:</strong> This is a staging area where Git put files that you are going to commit soon. (i.e. changes that are going to be marked as a new version.) This is because there are certain files that you may want to mark as finished and won&#39;t change, while there are others you are still working on and don&#39;t want to be released in this version.</li>\n<li><strong>HEAD:</strong> This is a reference that points to the last commit you&#39;ve made.</li>\n</ul>\n<p>So you <em>add</em> files from the Working directory to the Index. As you work further, you can add more files to the Index or even remove (<em>restore</em>) files from the Index. When you are ready, you <strong>commit</strong> your changes. This will next generate a commit and a new HEAD that points to your last commit.</p>\n<h2 id=\"working-with-repositories\">Working with repositories</h2>\n<p>In this tutorial, we will need a new blank directory to learn Git and follow along. You can create a new folder anywhere to start experimenting with Git. I created mine at <code>D:\\project</code>.</p>\n<h3 id=\"initializing-a-git-repository\">Initializing a Git repository</h3>\n<p>By Initializing a Git repository, you convert an unversioned project to Git or as in our case, create a new empty repository. (Yep, you can now call your project a repository!) You will need to run the rest of the commands in the root of the project. You can type <code>cd</code> to see where you are now and check if it is indeed where you are planning to create a new repository.</p>\n<pre class=\"block-code\"><code class=\"language-sh\">git init\n</code></pre>\n<p>After initializing your git repository, you should see a message like: &quot;Initialized empty Git repository in C:/project/.git/&quot; to confirm that a new repo has been created successfully. Note that Git create a hidden folder called <code>.git</code> to store version and history data.</p>\n<h3 id=\"tracking-files\">Tracking files</h3>\n<p>You will now need to create two files at the root of your project folder: <code>index.html</code> and <code>style.css</code>. You can use your favorite text editor (I ❤ <a href=\"https://www.sublimetext.com/\">Sublime Text</a>) to save them to the root of your repository.</p>\n<h4 id=\"checking-the-status-of-a-repository\">Checking the status of a repository</h4>\n<p>You can check the status of your local repository by using the <code>git status</code> command. You will use this command a lot while working with Git repositories.</p>\n<pre class=\"block-code\"><code class=\"language-sh\">git status\n</code></pre>\n<p>Output:</p>\n<pre class=\"block-code\"><code>On branch main\n\nNo commits yet\n\nUntracked files:\n  (use &quot;git add &lt;file&gt;...&quot; to include in what will be committed)\n        index.html\n        style.css\n\nnothing added to commit but untracked files present (use &quot;git add&quot; to track)\n</code></pre>\n<blockquote>\n<p><strong>Note:</strong> On some older versions of Git, the <code>main</code> branch may be called <code>master</code> by default, this is normal. To change the name of the master branch to main, run: <code>git checkout master</code> then <code>git branch -M main</code></p>\n</blockquote>\n<h4 id=\"staging-files\">Staging files</h4>\n<p>The output above tells us that Git knows there are new files in the Working Directory but they are not tracked (They are not part of our Git repo; Git is not tracking changes to them, yet). We have to <strong>stage</strong> the files using the git <code>add</code> command.</p>\n<pre class=\"block-code\"><code class=\"language-sh\">git add .\n</code></pre>\n<p>Adding/Staging the files put them to Git&#39;s Index.</p>\n<blockquote>\n<p>The <code>.</code> (or <code>*</code>) tells git to add EVERYTHING to the repo.</p>\n<p>You can also add a single file to the index at a time by using the <code>git add &lt;filename&gt;</code> syntax. <code>git add index.html</code> would add index.html only.</p>\n<p>You could also add a range of files using the <code>*</code> (wildcard character). <code>git add hello/*</code> would add all files in the hello  folder.</p>\n</blockquote>\n<h4 id=\"committing-changes\">Committing changes</h4>\n<p>Let&#39;s check the status again with <code>git status</code>.</p>\n<pre class=\"block-code\"><code>On branch main\n\nNo commits yet\n\nChanges to be committed:\n  (use &quot;git rm --cached &lt;file&gt;...&quot; to unstage)\n        new file:   index.html\n        new file:   style.css\n</code></pre>\n<p>We are now ready to commit the files (i.e. mark the changes we made a version).</p>\n<pre class=\"block-code\"><code class=\"language-sh\">git commit -m <span class=\"hljs-string\">&quot;Initial Commit&quot;</span>\n</code></pre>\n<p>Output:</p>\n<pre class=\"block-code\"><code>[main (root-commit) 154dcd7] Initial Commit\n 2 files changed, 2 insertions(+)\n create mode 100644 index.html\n create mode 100644 style.css\n</code></pre>\n<p>While committing, the option <code>-m</code> can be used to provide a commit message, in this case &quot;Initial Commit&quot;. You are encouraged to always provide a descriptive commit message that show a gist of the changes you&#39;ve made.</p>\n<blockquote>\n<p>If you don&#39;t provide a commit message, Git will use the default editor, set in the installation process on Windows or otherwise Vim, which could be weird for users who don&#39;t know to use Vim because it shows a strange screen where you can no longer enter any commands. To quit Vim, press <kbd>ESC</kbd> and type <code>:q!</code> followed by <kbd>ENTER</kbd>. You can <a href=\"https://docs.github.com/en/get-started/getting-started-with-git/associating-text-editors-with-git\">learn how to configure Git to use your favorite text editor</a>. </p>\n</blockquote>\n<h3 id=\"branches\">Branches</h3>\n<p>Branches are used to develop features isolated from each other. The <code>main</code> branch (or <code>master</code>, depending on the version of Git) is the &quot;default&quot; branch when you create a repository. Use other branches for development and merge them back to the main branch upon completion.</p>\n<h4 id=\"creating-a-new-branch\">Creating a new branch</h4>\n<p>In this project, we will be creating a new branch to add javascript.\nYou use the <code>git chekout -b &lt;branch-name&gt;</code> syntax to add a new branch.</p>\n<pre class=\"block-code\"><code class=\"language-sh\">git checkout -b javascript\n</code></pre>\n<pre class=\"block-code\"><code>Switched to a new branch &#39;javascript&#39;\n</code></pre>\n<h4 id=\"listing-all-branches\">Listing all branches</h4>\n<p>You can use the <code>git branch</code> command to list all branches in the current repository.</p>\n<pre class=\"block-code\"><code class=\"language-sh\">git branch\n</code></pre>\n<pre class=\"block-code\"><code>* javascript\n  main\n</code></pre>\n<p>The current branch is highlighted in green and an <code>asterisk</code> is shown before it&#39;s name.</p>\n<p>We can starting working on code in our new branch. Create a file called <code>script.js</code>. We can the use <code>git status</code> to view the state of our repo.</p>\n<pre class=\"block-code\"><code class=\"language-sh\">git status\n</code></pre>\n<pre class=\"block-code\"><code>On branch javascript\nUntracked files:\n  (use &quot;git add &lt;file&gt;...&quot; to include in what will be committed)\n        script.js\n\nnothing added to commit but untracked files present (use &quot;git add&quot; to track)\n</code></pre>\n<p>Notice that the output shows that we&#39;re on branch <code>javascript</code> and that <code>script.js</code> is untracked. We will need to add it to the \nIndex.</p>\n<pre class=\"block-code\"><code class=\"language-sh\">git add .\n</code></pre>\n<p>Then commit.</p>\n<pre class=\"block-code\"><code class=\"language-sh\">git commit -m <span class=\"hljs-string\">&quot;Add script&quot;</span>\n</code></pre>\n<pre class=\"block-code\"><code>[javascript 355fad9] Add script\n 1 file changed, 1 insertion(+)\n create mode 100644 script.js\n</code></pre>\n<h3 id=\"reviewing-and-merging\">Reviewing and Merging</h3>\n<p>When you are done implementing a feature in a branch, the only thing left is to <strong>merge</strong> it to the main branch. Merging is Git&#39;s way of taking a forked history (an independent line of that divergd from the current branch) and incorporating it the current branch. Merging allows you to &quot;combine&quot; different versions of code that diverged from a shared branch. We are going to merge code from the <code>javascript</code> branch back into the <code>main</code> branch.</p>\n<p>We&#39;ll need to go back to the main branch first.</p>\n<pre class=\"block-code\"><code class=\"language-sh\">git checkout main\n</code></pre>\n<h4 id=\"git-diff\">git diff</h4>\n<p>It is good practise to first review changes before merging or committing. You can use the <code>git diff</code> command (short for difference) to show changes between different revisions or paths. (You can use it to compare branches, commits and whatnots).</p>\n<p>If you provide only one argument, Git shows the changes in your working tree relative to the named reference. You can use HEAD to compare it to the latest commit, or a branch name to compare it to the tip of a different branch, which is what we&#39;ll do here.</p>\n<pre class=\"block-code\"><code class=\"language-sh\">git diff javascript\n</code></pre>\n<pre class=\"block-code\"><code>diff --git a/script.js b/script.js\nnew file mode 100644\nindex 0000000..d7ac302\n--- /dev/null\n+++ b/script.js\n@@ -0,0 +1 @@\n</code></pre>\n<h4 id=\"git-merge\">git merge</h4>\n<p>After now reviewing the changes we are about to merge, it&#39;s time we merge the actual changes back into the main branch.</p>\n<pre class=\"block-code\"><code class=\"language-sh\">git merge javascript\n</code></pre>\n<pre class=\"block-code\"><code>Updating 154dcd7..355fad9\nFast-forward\n script.js | 1 +\n 1 file changed, 1 insertion(+)\n create mode 100644 script.js\n</code></pre>\n<p>After the branch is merged successfully, we can now delete the <code>javascript</code> branch because it is no longer needed.</p>\n<pre class=\"block-code\"><code class=\"language-sh\">git branch -d javascript\n</code></pre>\n<blockquote>\n<p>Git tries to auto-merge changes. Unfortunately, this is not always possible and results in conflicts. You are responsible to merge those conflicts manually by editing the files shown by git. After changing, you need to mark them as merged with <code>git add &lt;filename&gt;</code> before merging changes.</p>\n</blockquote>\n<h3 id=\"logging\">Logging</h3>\n<p>You can type <code>git log</code> see the repository&#39;s history and confirm that the branch has been merged.</p>\n<pre class=\"block-code\"><code>commit 355fad97c2d442bb4a307385bfd6bac2198e825d (HEAD -&gt; main)\nAuthor: Firstname Lastname &lt;username@email.com&gt;\nDate:   Sun Aug 1 15:35:31 2021 +0200\n\n    Add script\n\ncommit 154dcd7ce38589eb903346f6996e810401fa4910\nAuthor: Firstname Lastname &lt;username@email.com&gt;\nDate:   Sun Aug 1 15:07:37 2021 +0200\n\n    Initial Commit\n</code></pre>\n<p>Because git feeds git log results to a pager, you may need to press <code>q</code> when the log is too long.</p>\n<p>You can add a lot of parameters to make the log look like what you want. Here are a few examples:</p>\n<ul>\n<li>To see only the commits of a certain author:\n<code>git log --author=alice</code></li>\n<li>To see a very compressed log where each commit is one line:\n<code>git log --pretty=oneline</code></li>\n<li>Or maybe you want to see an ASCII art tree of all the branches, decorated with the names of tags and branches:\n<code>git log --graph --oneline --decorate --all</code></li>\n<li>See only which files have changed:\n<code>git log --name-status</code></li>\n</ul>\n<p>These are just a few of the possible parameters you can use. For more, see <code>git log --help</code></p>\n<h3 id=\"tags\">Tags</h3>\n<p>When you are done and ready to mark a version of your code, you can add a git tag.</p>\n<pre class=\"block-code\"><code class=\"language-sh\">git tag v1.0.0\n</code></pre>\n<h3 id=\"the-end\">The End</h3>\n<p>You are now mostly ready to contribute to projects while using Git to track your projects. Although you must note that this is only a basic tutorial of Git and you still have more to learn namely working with remotes. Git is a very complex software and has more than 160 commands but it&#39;s amazing how you don&#39;t have to know even a half to contribute to open source projects and track your project&#39;s progress. You&#39;ll know more git commands naturally as you become more experienced with Git and when the need for them comes.</p>\n<h3 id=\"resources\">Resources</h3>\n<ul>\n<li><a href=\"https://git-scm.com/\">Official Git website</a></li>\n<li><a href=\"https://git-scm.com/downloads\">Git Downloads from the official site</a></li>\n<li><a href=\"https://rogerdudler.github.io/git-guide/img/trees.png\">No nonsense git cheatsheet</a></li>\n<li><a href=\"https://www.atlassian.com/git\">Extensive Git guide by Atlassian</a></li>\n</ul>\n</article><footer class=\"footer\"><hr /><a href=\"#top\" class=\"top\">↑ Scroll to Top</a></footer></main></div><script src=\"/js/bundle.js\" defer=\"defer\"></script></body></html>",
            "url": "https://vixalien.com/post/git",
            "title": "Learn Git!",
            "summary": "Learn to use Git, a popular Distributed Control System to effectively collaborate and manage your software projects.",
            "date_modified": "2021-08-01T11:42:49.271Z",
            "author": {
                "name": "Angelo Verlain",
                "url": "https://vixalien.com"
            }
        },
        {
            "id": "let-it-snow",
            "content_html": "<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"utf-8\" /><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\" /><meta name=\"theme-color\" content=\"#030f1b\" /><link rel=\"stylesheet\" href=\"/css/app.css\" /><link rel=\"shortcut icon\" href=\"/favicon.ico\" /><link rel=\"manifest\" href=\"/manifest.json\" /><link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"/favicon/android-chrome-192x192.png\" /><link rel=\"alternate\" type=\"application/rss+xml\" title=\"RSS\" href=\"https://vixalien.ga/feed/feed.rss\" /><link rel=\"alternate\" type=\"application/atom+xml\" title=\"Atom\" href=\"https://vixalien.ga/feed/feed.atom\" /><link rel=\"alternate\" type=\"application/json\" title=\"JSON\" href=\"https://vixalien.ga/feed/feed.json\" /><title>Let it snow! - vixalien</title><link rel=\"canonical\" href=\"https://www.vixalien.com/post/let-it-snow\" /><meta name=\"description\" content=\"Building an optimized snowing weather with the Web Animations API and Promises.\" /><link rel=\"stylesheet\" href=\"/css/highlight.css\" /></head><body><script src=\"/js/config.js\"></script><div class=\"root\"><main style=\"\" id=\"main\" class=\" container\"><header><nav><a href=\"/\">← vixalien's blog</a></nav></header><div class=\"intro\"><small>Sun Jan 31 2021</small><br /><h1>Let it snow!</h1></div><p>Building an optimized snowing weather with the Web Animations API and Promises.</p><hr /><br /><article><blockquote>\n<p>Easter egg: Run this page with <code>#snow</code> at the end</p>\n</blockquote>\n<p>🌨⛄ Do you like snow? Does it snow in your region? Are we in December yet?</p>\n<p>We are going to create virtual snow using the chilly <em><a href=\"https://developer.mozilla.org/en-US/docs.Web/API/Web_Animations_API\">Web Animations API</a></em>.</p>\n<h2 id=\"a-snowflake\">A snowflake!</h2>\n<p>First and foremost, let&#39;s create a snowflake! Our snowflake will be loaded as an <code>.svg</code> file provided by the beautiful <a href=\"https://ionicons.com\">Ionicons</a>.</p>\n<h3 id=\"loading-the-snowflake\">Loading the snowflake</h3>\n<p>You can store it as a local file then load it as SVG, or use it from Ionicon&#39;s library, but we will be storing it as a string.</p>\n<pre class=\"block-code\"><code class=\"language-js\"><span class=\"hljs-keyword\">let</span> svg_str = <span class=\"hljs-string\">`&lt;!-- snowflake svg text here --&gt;`</span>;\n</code></pre>\n<h3 id=\"parsing-the-string-into-a-dom-element\">Parsing the string into a DOM element</h3>\n<p>Then we&#39;ll use <code>DOMParser</code> to parse the string into an actual DOM element.</p>\n<pre class=\"block-code\"><code class=\"language-js\"><span class=\"hljs-keyword\">let</span> snow = <span class=\"hljs-keyword\">new</span> <span class=\"hljs-title class_\">DOMParser</span>().<span class=\"hljs-title function_\">parseFromString</span>(svg_str, <span class=\"hljs-string\">&quot;text/xml&quot;</span>).<span class=\"hljs-property\">children</span>[<span class=\"hljs-number\">0</span>];\n</code></pre>\n<blockquote>\n<p><strong>Note:</strong> Because <code>parseFromString</code> returns a <code>#document</code>, we used <code>.children[0]</code> to get the <code>&lt;svg&gt;</code> element instead. (<code>&lt;svg&gt;</code> is equivalent to <code>&lt;html&gt;</code>.)</p>\n</blockquote>\n<h3 id=\"setting-the-snowflake-to-float\">Setting the snowflake to float</h3>\n<p>Our snowflake is fixed (it doesn&#39;t scroll like other elements) and initially, it is placed just above the screen.</p>\n<pre class=\"block-code\"><code class=\"language-js\">snow.<span class=\"hljs-property\">style</span>.<span class=\"hljs-property\">position</span> = <span class=\"hljs-string\">&quot;fixed&quot;</span>;\nsnow.<span class=\"hljs-property\">style</span>.<span class=\"hljs-property\">top</span> = <span class=\"hljs-string\">&quot;-24px&quot;</span>;\n</code></pre>\n<h2 id=\"creating-a-new-snowflake\">Creating a new snowflake</h2>\n<p>Because our page will have many snowflakes, we&#39;ll clone the snowflake we just created.</p>\n<pre class=\"block-code\"><code class=\"language-js\"><span class=\"hljs-keyword\">let</span> <span class=\"hljs-title function_\">newSnow</span> = (<span class=\"hljs-params\"></span>) =&gt; {\n    <span class=\"hljs-keyword\">let</span> clonedSnow = snow.<span class=\"hljs-title function_\">cloneNode</span>(<span class=\"hljs-literal\">true</span>);\n    <span class=\"hljs-comment\">// we pass true to clone the node deeply (that is, with all it&#x27;s children).</span>\n};\n</code></pre>\n<blockquote>\n<p><strong>Note:</strong> from now on, our code will be in the <code>newSnow</code> function.</p>\n</blockquote>\n<p>Next, we&#39;ll generate a random left position for that snowflake</p>\n<pre class=\"block-code\"><code class=\"language-js\"><span class=\"hljs-keyword\">let</span> left = <span class=\"hljs-title class_\">Math</span>.<span class=\"hljs-title function_\">floor</span>(<span class=\"hljs-variable language_\">document</span>.<span class=\"hljs-property\">body</span>.<span class=\"hljs-property\">offsetWidth</span> * <span class=\"hljs-title class_\">Math</span>.<span class=\"hljs-title function_\">random</span>());\n<span class=\"hljs-comment\">// we use Math.floor to ensure left is an integer</span>\nclonedSnow.<span class=\"hljs-property\">style</span>.<span class=\"hljs-property\">left</span> = left + <span class=\"hljs-string\">&quot;px&quot;</span>;\n</code></pre>\n<p>Then we&#39;ll just add it to the DOM</p>\n<pre class=\"block-code\"><code class=\"language-js\"><span class=\"hljs-variable language_\">document</span>.<span class=\"hljs-property\">body</span>.<span class=\"hljs-title function_\">append</span>(clonedSnow);\n</code></pre>\n<h3 id=\"animating-the-snowflake\">Animating the snowflake</h3>\n<p>Here we&#39;ll just use <em><a href=\"https://developer.mozilla.org/en-US/docs.Web/API/Web_Animations_API\">Web Animations API</a></em> to animate an element. To use the API, we run <code>element.animate(keyframes, options)</code>. You can read more in the <a href=\"https://developer.mozilla.org/en-US/docs.Web/API/Web_Animations_API\">MDN Page</a>.</p>\n<p>To make real snow effect, we will also generate a random speed (think the animation&#39;s duration)</p>\n<pre class=\"block-code\"><code class=\"language-js\"><span class=\"hljs-keyword\">let</span> time = <span class=\"hljs-title class_\">Math</span>.<span class=\"hljs-title function_\">max</span>(<span class=\"hljs-number\">10</span> * <span class=\"hljs-title class_\">Math</span>.<span class=\"hljs-title function_\">random</span>(), <span class=\"hljs-number\">5</span>) * <span class=\"hljs-number\">1000</span>;\n<span class=\"hljs-comment\">// Math.max choose the largest argument it was given. By using it here, we restrict time to be larger than 5.</span>\n</code></pre>\n<p>We will animate the snow to change it&#39;s <code>top</code> CSS property gradually. At the end, the element will be placed just below the viewport, where you can&#39;t see it.</p>\n<pre class=\"block-code\"><code class=\"language-js\"><span class=\"hljs-keyword\">let</span> anim = clonedSnow.<span class=\"hljs-title function_\">animate</span>(\n    {\n        <span class=\"hljs-attr\">top</span>: <span class=\"hljs-variable language_\">window</span>.<span class=\"hljs-property\">innerHeight</span> + <span class=\"hljs-number\">24</span> + <span class=\"hljs-string\">&quot;px&quot;</span>,\n    },\n    { <span class=\"hljs-attr\">duration</span>: time, <span class=\"hljs-attr\">fill</span>: <span class=\"hljs-string\">&quot;forwards&quot;</span> }\n);\n</code></pre>\n<p>One last thing, we&#39;ll do Garbage Collection. When the animation ends, delete that snowflake as it is no longer useful.</p>\n<pre class=\"block-code\"><code class=\"language-js\"><span class=\"hljs-comment\">// garbage collection</span>\nanim.<span class=\"hljs-property\">onfinish</span> = <span class=\"hljs-function\"><span class=\"hljs-params\">el</span> =&gt;</span> el.<span class=\"hljs-property\">target</span>.<span class=\"hljs-property\">effect</span>.<span class=\"hljs-property\">target</span>.<span class=\"hljs-title function_\">remove</span>()\n</code></pre>\n<p>Now go ahead, in your console, run <code>newSnow()</code>. You&#39;ll see a snowflake falling slowly.</p>\n<h2 id=\"snowing\">Snowing!!!</h2>\n<p>So far, we can only create snowflakes on demand by running <code>newSnow()</code> everytime we need it. What about we create a loop that create as many snowflakes as possible?</p>\n<h3 id=\"the-problem-with-native-js-loops\">The problem with native JS loops</h3>\n<p>If you use <code>for</code> loops or <code>while</code> or whatever, it won&#39;t work. Why? It will create many snowflakes at a time. Your browser will be filled with snowflakes and unless you are on a supercomputer, your browser will crash, badly. This creates a need for a custom loop!</p>\n<h3 id=\"looping-asynchronously\">Looping asynchronously</h3>\n<h4 id=\"async-iterate\">Async Iterate</h4>\n<p>Here&#39;s an implementation of an async loop.</p>\n<pre class=\"block-code\"><code class=\"language-js\"><span class=\"hljs-keyword\">let</span> asyncIterate = <span class=\"hljs-keyword\">async</span> (start, iterations, fn) =&gt; {\n    <span class=\"hljs-comment\">// initialize the iterator</span>\n    <span class=\"hljs-keyword\">let</span> i = start;\n    <span class=\"hljs-keyword\">let</span> <span class=\"hljs-title function_\">call</span> = res =&gt; <span class=\"hljs-title function_\">fn</span>(res)\n        <span class=\"hljs-comment\">// waits for the function to resolves before calling the next iteration</span>\n        .<span class=\"hljs-title function_\">then</span>(<span class=\"hljs-keyword\">async</span> result =&gt; {\n            <span class=\"hljs-keyword\">if</span> (i &gt;= iterations) <span class=\"hljs-keyword\">return</span> result;\n            i++\n            <span class=\"hljs-keyword\">return</span> <span class=\"hljs-keyword\">await</span> <span class=\"hljs-title function_\">call</span>(i)\n        });\n    <span class=\"hljs-keyword\">return</span> <span class=\"hljs-keyword\">await</span> <span class=\"hljs-title function_\">call</span>(i);\n}\n</code></pre>\n<p>It accepts 3 parameters. <code>start</code> is what the iterator is initialized as. <code>iterations</code> is pretty self-explanatory. it is the number of times the function will run. then <code>fn</code> is the function to execute.</p>\n<p>It is important to remember that this is an async loop. That means, it will run the function, <em>then waits that it resolves</em>. then execute the next iteration.</p>\n<h4 id=\"wait\">wait</h4>\n<p>Next is the <code>wait</code> function. This is a wrapper around <code>setTimeout</code>. It waits some time (in milliseconds), then execute a function. (It is available on the npm registry as <a href=\"https://npmjs.com/package/async-wait-then\">async-wait-then</a>).</p>\n<pre class=\"block-code\"><code class=\"language-js\">wait = <span class=\"hljs-function\"><span class=\"hljs-params\">time</span> =&gt;</span> <span class=\"hljs-keyword\">new</span> <span class=\"hljs-title class_\">Promise</span>(<span class=\"hljs-function\"><span class=\"hljs-params\">res</span> =&gt;</span> <span class=\"hljs-built_in\">setTimeout</span>(res, time))\n</code></pre>\n<p>Here is a simple example using <code>wait</code>.</p>\n<pre class=\"block-code\"><code class=\"language-js\"><span class=\"hljs-title function_\">wait</span>(<span class=\"hljs-number\">1000</span>)\n    .<span class=\"hljs-title function_\">then</span>(<span class=\"hljs-function\">() =&gt;</span> <span class=\"hljs-variable language_\">console</span>.<span class=\"hljs-title function_\">log</span>(<span class=\"hljs-string\">&#x27;This will be logged after one second!&#x27;</span>));\n</code></pre>\n<h4 id=\"using-wait-and-asynciterate-to-snow\">Using <code>wait</code> and <code>asyncIterate</code> to snow</h4>\n<p>By combining <code>wait</code> and <code>asyncIterate</code>, we get a powerful function set that uses the Promises API.</p>\n<p>So, to create realistic snow (and prevent browser crashes) we&#39;ll have to wait before we create a snow element</p>\n<pre class=\"block-code\"><code class=\"language-js\"><span class=\"hljs-title function_\">asyncIterate</span>(<span class=\"hljs-number\">0</span>, <span class=\"hljs-number\">10</span>, <span class=\"hljs-keyword\">async</span> () =&gt; {\n    <span class=\"hljs-keyword\">await</span> <span class=\"hljs-title function_\">wait</span>(<span class=\"hljs-number\">1000</span>)\n    <span class=\"hljs-title function_\">newSnow</span>()\n})\n</code></pre>\n<p>This will make it rain 10 snowflakes, but with an interval of 1 seconds between each snowflake</p>\n<p>To make it look more realistic (and add some suspense), we will wait for a random amount of time instead of the static 1 second.</p>\n<pre class=\"block-code\"><code class=\"language-js\"><span class=\"hljs-title function_\">asyncIterate</span>(<span class=\"hljs-number\">0</span>, <span class=\"hljs-number\">10</span>, <span class=\"hljs-keyword\">async</span> () =&gt; {\n    <span class=\"hljs-keyword\">await</span> <span class=\"hljs-title function_\">wait</span>(<span class=\"hljs-title class_\">Math</span>.<span class=\"hljs-title function_\">max</span>(<span class=\"hljs-number\">3</span> * <span class=\"hljs-title class_\">Math</span>.<span class=\"hljs-title function_\">random</span>(), <span class=\"hljs-number\">1</span>) * <span class=\"hljs-number\">300</span>)\n    <span class=\"hljs-title function_\">newSnow</span>()\n})\n</code></pre>\n<p>But then, this will only create 10 snowflakes. Let&#39;s make it rain forever.</p>\n<pre class=\"block-code\"><code class=\"language-js\"><span class=\"hljs-title function_\">asyncIterate</span>(<span class=\"hljs-number\">0</span>, <span class=\"hljs-title class_\">Infinity</span>, <span class=\"hljs-keyword\">async</span> () =&gt; {\n    <span class=\"hljs-keyword\">await</span> <span class=\"hljs-title function_\">wait</span>(<span class=\"hljs-title class_\">Math</span>.<span class=\"hljs-title function_\">max</span>(<span class=\"hljs-number\">3</span> * <span class=\"hljs-title class_\">Math</span>.<span class=\"hljs-title function_\">random</span>(), <span class=\"hljs-number\">1</span>) * <span class=\"hljs-number\">300</span>)\n    <span class=\"hljs-title function_\">newSnow</span>()\n})\n</code></pre>\n<p>The full code, complete with some optimizations is posted as <a href=\"https://gist.github.com/vixalien/4a9fb790036d01399186e7c3050c2560\">Github Gist</a></p>\n</article><footer class=\"footer\"><hr /><a href=\"#top\" class=\"top\">↑ Scroll to Top</a></footer></main></div><script src=\"/js/bundle.js\" defer=\"defer\"></script></body></html>",
            "url": "https://vixalien.com/post/let-it-snow",
            "title": "Let it snow!",
            "summary": "Building an optimized snowing weather with the Web Animations API and Promises.",
            "date_modified": "2021-01-31T15:49:22.776Z",
            "author": {
                "name": "Angelo Verlain",
                "url": "https://vixalien.com"
            }
        },
        {
            "id": "explosiv",
            "content_html": "<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"utf-8\" /><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\" /><meta name=\"theme-color\" content=\"#030f1b\" /><link rel=\"stylesheet\" href=\"/css/app.css\" /><link rel=\"shortcut icon\" href=\"/favicon.ico\" /><link rel=\"manifest\" href=\"/manifest.json\" /><link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"/favicon/android-chrome-192x192.png\" /><link rel=\"alternate\" type=\"application/rss+xml\" title=\"RSS\" href=\"https://vixalien.ga/feed/feed.rss\" /><link rel=\"alternate\" type=\"application/atom+xml\" title=\"Atom\" href=\"https://vixalien.ga/feed/feed.atom\" /><link rel=\"alternate\" type=\"application/json\" title=\"JSON\" href=\"https://vixalien.ga/feed/feed.json\" /><title>How Explosiv Works - vixalien</title><link rel=\"canonical\" href=\"https://www.vixalien.com/post/explosiv\" /><meta name=\"description\" content=\"The most lightweight, yet fully featured static-site generator you'll see.\" /><link rel=\"stylesheet\" href=\"/css/highlight.css\" /></head><body><script src=\"/js/config.js\"></script><div class=\"root\"><main style=\"\" id=\"main\" class=\" container\"><header><nav><a href=\"/\">← vixalien's blog</a></nav></header><div class=\"intro\"><small>Thu Jan 28 2021</small><br /><h1>How Explosiv Works</h1></div><p>The most lightweight, yet fully featured static-site generator you'll see.</p><hr /><br /><article><p>Explosiv <a href=\"https://npmjs.com/package/explosiv\">npm ↗</a> <a href=\"https://github.com/vixalien/explosiv\">Github ↗</a> is a static site generator for JSX content.</p>\n<blockquote>\n<p>This article is about how Explosiv works, if you want to want to learn how to use Explosiv go to <a href=\"https://github.com/vixalien/explosiv\">Explosiv&#39;s Github Page</a> instead.</p>\n</blockquote>\n<h2 id=\"why-explosiv-was-made\">Why Explosiv was made.</h2>\n<p>While I was creating this blog, I thought.</p>\n<p>About all the front-end options I had. Because, I was not going to write static HTML for a fully featured site! While I had already met <a href=\"https://google.com?q=stylus+css\">stylus</a> for all my CSS needs, I was still looking for an option to write my markup seamlessly.</p>\n<h2 id=\"react\">React</h2>\n<p>TBH, I love <a href=\"https://reactjs.org\">React</a>. It&#39;s syntax, it&#39;s community, it&#39;s everything really. Yet, React also put so much overhead on your site, like Build times, Babel, Webpack, hydrating or rendering etc. After some digging, I found out the foundation behind React was <a href=\"https://reactjs.org/docs/introducting-jsx.html\">JSX</a>, dubbed as XHTML within Javascript.</p>\n<pre class=\"block-code\"><code class=\"language-js\"><span class=\"hljs-comment\">// JSX syntax is coool!</span>\n<span class=\"hljs-keyword\">let</span> <span class=\"hljs-title function_\">Site</span> = (<span class=\"hljs-params\">data</span>) =&gt; {\n    <span class=\"hljs-keyword\">return</span> <span class=\"language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div</span>&gt;</span>Hello {data.name}!<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">div</span>&gt;</span></span>\n}\n</code></pre>\n<p>Well because JSX is tightly coupled with React, I kinda thought it would not work on it&#39;s own, but yet <a href=\"https://www.github.com/kartiknair\">kartiknair</a> made <a href=\"https://www.github.com/kartiknair\">Dhow</a>, which proved me otherwise.</p>\n<h2 id=\"dhow\">Dhow</h2>\n<p><a href=\"https://www.github.com/kartiknair\">Dhow</a>, is a static site generator, that uses JSX to render static HTML at build time, ready to be served as is. It is quick, <em>very fast</em> and still uses JSX, so migrating my app from React was <em>a breeeeze</em>.  Until I encountered the severe limitations of Dhow.</p>\n<p>Dhow was very young. That means It just implemented JSX, nothing else. Many features were lacking. While creating this site, I cloned Dhow. I found myself adding many features as I wanted. I saw it was incredible. I decided to push it to My Github as <a href=\"https://www.github.com/vixalien/explosiv\">Explosiv</a></p>\n<h2 id=\"explosiv\">Explosiv</h2>\n<p><a href=\"https://www.github.com/vixalien/explosiv\">Explosiv</a>, being a clone of <a href=\"https://www.github.com/kartiknair\">Dhow</a>, inherits all it&#39;s current features. Here is a simple example.</p>\n<p>First, add <code>explosiv</code> to your site&#39;s dependencies.</p>\n<pre class=\"block-code\"><code class=\"language-bash\">npm i explosiv\n</code></pre>\n<p>And install explosiv globally, so that you can use the CLI wherever you are...</p>\n<pre class=\"block-code\"><code class=\"language-bash\">npm i explosiv -g\n</code></pre>\n<p>Or, to keep up with modern standards, although I personally like the first syntax more, use <code>npx</code> to always use the latest version of explosiv</p>\n<pre class=\"block-code\"><code class=\"language-bash\">npx explosiv\n</code></pre>\n<p>To make an Explosiv site, just create a folder and generate a <code>pages/</code> directory. Add a simple <code>index.js</code> file to get started.</p>\n<pre class=\"block-code\"><code class=\"language-js\"><span class=\"hljs-comment\">// pages/index.js</span>\n<span class=\"hljs-keyword\">import</span> <span class=\"hljs-title class_\">Explosiv</span> <span class=\"hljs-keyword\">from</span> <span class=\"hljs-string\">&#x27;explosiv&#x27;</span>\n\n<span class=\"hljs-keyword\">export</span> <span class=\"hljs-keyword\">default</span> () =&gt; (\n    <span class=\"language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">main</span>&gt;</span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1</span>&gt;</span>Hello there!<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">h1</span>&gt;</span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p</span>&gt;</span>\n            This is a super simple example of generating static files using Explosiv.\n            You can learn more at{&#x27; &#x27;}\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a</span> <span class=\"hljs-attr\">href</span>=<span class=\"hljs-string\">&quot;https://github.com/vixalien/explosiv&quot;</span>&gt;</span>here<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">a</span>&gt;</span>\n        <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">p</span>&gt;</span>\n    <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">main</span>&gt;</span></span>\n)\n</code></pre>\n<p>To build, and serve, the site use:</p>\n<pre class=\"block-code\"><code class=\"language-bash\">explosiv build\nexplosiv serve\n</code></pre>\n<p>Et voìla! A static site was generated in your <code>/out</code> directory. Magic right!</p>\n<h3 id=\"how-it-works\">How it works</h3>\n<p>You can learn how JSX works by <a href=\"https://reactjs.org/docs/introducting-jsx.html\">this article</a> from the React team.</p>\n<p>You can read a very nice article by kartiknair, the creator of Dhow <a href=\"https://kartikn.me/writing/jsx-without-react\">about converting JSX into HTML</a> <strong>without React</strong>.</p>\n<p>TL;DR: We use a <em>pragma</em> function that generate real DOM elements using a minimal DOM implementation, <a href=\"https://npmjs.com/package/min-document\">min-document</a>.</p>\n<pre class=\"block-code\"><code class=\"language-js\"><span class=\"hljs-comment\">// A general overview of how it works.</span>\n<span class=\"hljs-comment\">// !! Not real code</span>\n<span class=\"hljs-keyword\">const</span> <span class=\"hljs-variable language_\">document</span> = <span class=\"hljs-built_in\">require</span>(<span class=\"hljs-string\">&#x27;min-document&#x27;</span>);\n\n<span class=\"hljs-keyword\">const</span> <span class=\"hljs-title function_\">createElement</span> = (<span class=\"hljs-params\">tag, props, ...children</span>) =&gt; {\n    <span class=\"hljs-keyword\">const</span> element = <span class=\"hljs-variable language_\">document</span>.<span class=\"hljs-title function_\">createElement</span>(tag)\n\n    children.<span class=\"hljs-title function_\">forEach</span>(<span class=\"hljs-function\">(<span class=\"hljs-params\">child</span>) =&gt;</span> {\n        element.<span class=\"hljs-title function_\">appendChild</span>(child)\n    })\n\n    <span class=\"hljs-keyword\">return</span> element\n}\n</code></pre>\n<p>We transpile Javascript using <a href=\"https://esbuild.github.io\">ESBuild</a>, a verrry fast, yet fully featured transpiler. We transpile the code in the pages directory  from JSX into pure, native Javascript, while replacing all instances of JSX with our <em>pragma</em> function.</p>\n<p>The transpiled file will look like this</p>\n<pre class=\"block-code\"><code class=\"language-js\"><span class=\"hljs-comment\">// transpiled/index.js</span>\n<span class=\"hljs-keyword\">let</span> { createElement } = <span class=\"hljs-built_in\">require</span>(<span class=\"hljs-string\">&#x27;explosiv&#x27;</span>)\n\n<span class=\"hljs-keyword\">export</span> <span class=\"hljs-keyword\">default</span> () =&gt; (\n    <span class=\"hljs-title function_\">createElement</span>(<span class=\"hljs-string\">&#x27;main&#x27;</span>, <span class=\"hljs-literal\">null</span>, \n        <span class=\"hljs-title function_\">createElement</span>(<span class=\"hljs-string\">&#x27;h1&#x27;</span>, <span class=\"hljs-literal\">null</span>, <span class=\"hljs-string\">&#x27;Hello there!&#x27;</span>),\n        <span class=\"hljs-title function_\">createElement</span>(<span class=\"hljs-string\">&#x27;p&#x27;</span>, <span class=\"hljs-literal\">null</span>, \n            <span class=\"hljs-string\">&#x27;This is a super simple example of generating static files using Explosiv.&#x27;</span>,\n            <span class=\"hljs-string\">&#x27;You can learn more&#x27;</span>, <span class=\"hljs-string\">&#x27; &#x27;</span>,\n            <span class=\"hljs-title function_\">createElement</span>(<span class=\"hljs-string\">&#x27;a&#x27;</span>, {\n                <span class=\"hljs-attr\">href</span>: <span class=\"hljs-string\">&quot;https://github.com/vixalien/explosiv&quot;</span>\n            }, <span class=\"hljs-string\">&#x27;here&#x27;</span>\n        ),\n    )\n)\n</code></pre>\n<p>At the end we render our DOM into static HTML by using <code>document.toString()</code> and piping the output into the relevant output directory.</p>\n<h3 id=\"impovements-over-dhow\">Impovements over Dhow</h3>\n<p>Explosiv, is a personal project. It is not a competitor, or even an alternative to Dhow, yet all current improvements are listed for anyone interested. Many of these can also be implemented in Dhow if worth it.</p>\n<ul>\n<li>Provide an <code>explosiv serve</code> command that serve a static directory on a specified port (defaults to  3000).</li>\n<li><code>Head</code> elements are added on top of <code>document.head</code> instead of the bottom (allowing overriding existing tags)</li>\n<li>Rewritten for <code>build</code> code to be independent and ease debugging</li>\n<li>Does not use <code>polka</code> but the more minimal <code>connect</code>.</li>\n<li>Use middleware deemed as useful like <code>morgan</code> which log all requests and <code>compression</code> which compress resources on HTTP.</li>\n<li>Fixed bugs on edge cases like rendering <code>&lt;&gt;</code> (aka Fragment tags) as root elements and rendering empty children.</li>\n<li>Added support for <code>className</code> HTML attribute.</li>\n<li>Fixed bug where self-closing (like <code>&lt;img src=&quot;/path/to.img&quot;&gt;</code>) elements doesn&#39;t render correctly.</li>\n<li>Use tabs instead of 4 spaces lol!</li>\n<li>And other many but subtle changes.</li>\n</ul>\n</article><footer class=\"footer\"><hr /><a href=\"#top\" class=\"top\">↑ Scroll to Top</a></footer></main></div><script src=\"/js/bundle.js\" defer=\"defer\"></script></body></html>",
            "url": "https://vixalien.com/post/explosiv",
            "title": "How Explosiv Works",
            "summary": "The most lightweight, yet fully featured static-site generator you'll see.",
            "date_modified": "2021-01-28T17:23:43.290Z",
            "author": {
                "name": "Angelo Verlain",
                "url": "https://vixalien.com"
            }
        }
    ]
}