Viewing category: Tutorial

Let’s build a file encrypter with Python

Today we’re going to take a bit of a detour from web development and head more towards the realm of software development, while dunking our toes into the world of intrigue that is cryptography and information security. I used a lot of buzzwords there but do not be alarmed! I intend this tutorial to be accessible to all programming levels, however having prior knowledge of Python or another object oriented programming language, and knowing your way around the command line, will make it a lot easier to follow along. Even if this sounds all over your head, I encourage you to continue reading. There is no better way to learn than to tackle a hard problem, deconstruct it, and identify the what you know and what you don’t know. If my computer science degree taught me anything, it’s that Google is my best friend. With that being said, let’s get this started!

Encryption

Let’s start by defining a key concept here: encryption. Encryption is the process of altering information or data into a form that is unrecognizable from its original state. It needs to be a reversible process (called decryption) and should make it hard for unauthorized parties to obtain the information you are encrypting. Encryption algorithms take an input, referred to as plaintext, which is the data you want to encrypt, and outputs ciphertext, which should look like a garbled up mess if everything was successful.

All algorithms use a key which is just a long string of bits (1’s and 0’s) to handle encryption and decryption. This key works similarly to a physical key in real life. Just like your house key locks and unlocks your door, an encryption key locks and unlocks data. There are many kinds of encryption algorithms out there that use different sized keys. Typically the larger the key size is, the harder the encryption is for someone to break or hack. Check out this video about encryption that does a way better job of explaining how it works, without going too in depth.

The encryption algorithm we’ll be using today is called AES. It stands for Advanced Encryption Standard and was adopted by the U. S. government in 2001 as the standard to encrypt electronic data. We’ll be encrypting with a 256-bit key derived with PBKDF2, which stands for Password-Based Key Derivation Function. There is a lot of jargon in that sentence, but simply put we will be using a commonly used encryption technique with a key we create with a password that we set.

What you’ll need

In this tutorial we will be coding in Python 3 and using the Pycryptodome library. Pycryptodome is a Python package that implements a lot of different cryptographic functions. This is awesome because we get to play around with a bunch of different encryption algorithms and tools without having to code them from scratch.

You are going to need to have Python installed on your computer and any text editor you are comfortable using. If you are on Windows 10 and need help getting set up, follow this Guide that will take you through installing the Windows Subsystem for Linux (WSL) and get you up and running with python. Just complete up through the “Run a simple Python program” section. The Windows Subsystem for Linux (WSL) is a relatively new Windows 10 feature that allows you to run Linux programs natively in a Windows version of the Bash shell. When you install it you get an awesome Ubuntu-based command line terminal where you can do all your development. I recommend doing this tutorial with WSL since it’s what I developed this program in and because I believe it’s a really good way to start easing yourself into the Linux ecosystem, which is important to learn if you want to get into web or software development.

Mac Users

macOS should come with python 2.7 out of the box. We can install python 3 using Homebrew, Mac’s package manager. If you don’t have Homebrew installed on your machine, open up your terminal and run:

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

That should get Homebrew installed. Now let’s use it to get Python 3. In the terminal run:

brew install python3

This will tell Homebrew to grab the latest version of python and you should be good to go on with the rest of the tutorial.

Once you have your development environment ready to go, type the following into your command prompt and hit enter:

pip3 install pycryptodome

This command invokes pip, the python package manager, and tells it to go search for and install pycryptodome and any dependencies so we can start coding some awesome encryption scripts. Once pip finishes installation we will be ready to start.

Now, with your text editor of choice, let’s create a new file. I named mine crypto.py.

The encryption functions

Below, I’m going to start defining some functions for our encryption, then I’ll explain what they do line-by-line.

from Crypto.Cipher import AES
from Crypto import Random
from Crypto.Protocol.KDF import PBKDF2
import os

def encrypt(text, key):
    pad = lambda s: s + b"\0" * (AES.block_size - len(s) % AES.block_size)
    text = pad(text)
    initialization = Random.new().read(16)
    cipher = AES.new(key, AES.MODE_CBC, initialization)
    return initialization + cipher.encrypt(text)

In the first four lines we are importing all the external packages we will be using throughout the program. From the Pycryptodome package we are importing the AES, PBKDF2, and Random functions. We will also be importing the os package which should already come with your Python installation.

Next we define our main encryption function. The function takes two inputs: the text or data we want to encrypt and a key used for encryption. We handle key derivation a little later. In this function we need to handle a few important things. First we need to pad the text to ensure the size of the data is a multiple of the block size of the algorithm. The block size of AES is 16 bytes so our data must be padded so that it is a multiple of 16 bytes. You can pad your data with any character. In this example we are padding with null character, “\0”.

Second we create our initialization vector (IV). An IV is a string of random bits that is used to mix in with your data during encryption to make it harder to crack. Here we create a new variable called initialization and pass 16 random bytes into it.

Now we can create our AES encryption object. Here I name the object cipher, call the Pycryptodome AES function and pass it our yet-to-be-generated key, tell it we want CBC mode and finally pass it our IV. Don’t worry about understanding CBC mode for now. We are saying we want to use Cipher Block Chaining. CBC is a bit of an advanced topic to try to explain in brevity here, but I encourage you to research on your own if interested.

Our encryption object is now constructed! Next we finish this function off by returning the IV + the ciphertext which we get by running cipher.encrypt on our padded text.

Encrypting files

OK, so we just wrote a function that encrypts strings, but now we want to encrypt files. How can we do this? We need to write a function that reads a file, saves its contents as a string and then run our encryption function on it. Then we write that encrypted string to a new file and, voila, file encryption! Lets define that function below:

def file_encrypt(file_name, key):
    with open(file_name, 'rb') as input_file:
        plaintext = input_file.read()
    encrypted_text = encrypt(plaintext, key)
    with open(file_name + ".enc", 'wb') as output_file:
        output_file.write(encrypted_text)
    os.remove(file_name)

This function also takes two parameters: a string that will be the name of the file we wish to encrypt and, again, the key that we will generate shortly. First we open the file, read its contents, and run our previously defined encryption function on it. Then we create a new file and write the encrypted ciphertext to it. We save the file with the same file name as the original but with an added .enc extension to indicate to us that it is encrypted. Now all that is left to do is to delete the original unencrypted file from our directory using the os.remove() function.

The decryption functions

We now have a mechanism to “lock” files, but what good is a lock that can not be unlocked? As I explained earlier, encryption needs to be a reversible process. Let’s build a pair of functions that will allow us to decrypt our files.

def decrypt(encrypted_text, key):
    initialization = encrypted_text[:AES.block_size]
    cipher = AES.new(key, AES.MODE_CBC, initialization)
    plaintext = cipher.decrypt(encrypted_text[AES.block_size:])
    return plaintext.rstrip(b"\0")

Here we take two parameters: our encrypted text and the key we used for encryption. It is very important we pass in the same the key we previously used to encrypt or python will throw us an error when we run the code.

The first thing we need to do is identify our IV from our encrypted text. This is easy since we saved it at the front of the string. Since we know its size, we can perform a string slice only copying the first 16 bytes of the string (the AES block size).

Now that we have our IV we can create our AES object again and use it to decrypt the message omitting the first 16 bytes. The result is the plaintext padded with the null characters(“\0”). Finally we can return the original text by stripping off the null characters.

Decrypting files

It turns out that decrypting files is just as straightforward as encrypting them. We perform the same basic steps. First we read the encrypted text, pass it to our decryption function and write the plaintext output to a new file.

def file_decrypt(file_name, key):
    with open(file_name, 'rb') as input_file:
        encrypted_text = input_file.read()
    decrypted_text = decrypt(encrypted_text, key)
    with open(file_name[:-4], 'wb') as output_file:
        output_file.write(decrypted_text)
    os.remove(file_name)

Generating keys

Finally the moment you’ve all been waiting for… key derivation! Thus far we’ve built a functioning lock but we have no key to lock it with. There are many key derivation functions we can use that offer various trade-offs between speed and security. If an algorithm generates a key too quickly, it could be easily cracked. By the same token, if you choose an algorithm that produces a very secure key, then it may be too resource-intensive to be used practically. For our purposes the PBKDF2 algorithm offers a good speed-vs-security balance. This algorithm will give us a 32 byte (256 bit) key given a user-supplied password with salt. Yes, I said salt and, no, this didn’t turn into a recipe blog post. In cryptography, salt is a random string of bytes that is used by the algorithm that makes it more difficult for your password to be cracked. It also allows multiple users to enter the same password and generate unique keys. Ideally you should generate a unique salt for every user to increase password security. For our purposes, however, we are using a “fixed” or hard-coded salt. This means we will be using the same salt for every key generated. Again, this is not safe and should not be done for serious implementations. Do not use this program to encrypt files you actually need to keep 100% safe. This tutorial is for educational purposes only.

Now let’s write our key generator!

def generate_key(password):
    salt = b'\x83\xdb\xb9\xd3\xdc"\x1e\x0ee"\x0c\xf0=5\xab_\x18\xd7\xd2\x98\x92Q.\xbd\x9cK\x96\x93-J\x08\xe0'
    return PBKDF2(password, salt, dkLen=32)

This probably didn’t need its own user defined function but I wrote it this way to make what we’re doing a little more clear. Pycryptodome does all the heavy lifting for us here. All we have to do is supply the password in the form of a string and the salt. You can generate your own salt by opening your python console and typing the following commands:

from Crypto.Random import get_random_bytes
get_random_bytes(32)

That command will generate a random byte string based on the length you specify, in this case, 32 bytes. Now all we do is feed this to Pycryptodome’s PBKDF2 function and return the output which should be a 32 byte (256 bit) key!

Finishing touches

If you have been following along this far go ahead and pat yourself on the back. We just made the inner workings of a pretty sweet encrypting tool! Now all we need to do is make a simple driver to test it all out.

Here is the completed code:

from Crypto.Cipher import AES
from Crypto import Random
from Crypto.Protocol.KDF import PBKDF2
import os

# *** Encryption Functions ***
def encrypt(text, key, key_size = 256):
    pad = lambda s: s + b"\0" * (AES.block_size - len(s) % AES.block_size)
    text = pad(text)
    initialization = Random.new().read(16)
    cipher = AES.new(key, AES.MODE_CBC, initialization)
    return initialization + cipher.encrypt(text)

def file_encrypt(file_name, key):
    with open(file_name, 'rb') as input_file:
        plaintext = input_file.read()
    encrypted_text = encrypt(plaintext, key)
    with open(file_name + ".enc", 'wb') as output_file:
        output_file.write(encrypted_text)
    os.remove(file_name)

# *** Decryption Functions ***
def decrypt(encrypted_text, key):
    initialization = encrypted_text[:AES.block_size]
    cipher = AES.new(key, AES.MODE_CBC, initialization)
    plaintext = cipher.decrypt(encrypted_text[AES.block_size:])
    return plaintext.rstrip(b"\0")

def file_decrypt(file_name, key):
    with open(file_name, 'rb') as input_file:
        encrypted_text = input_file.read()
    decrypted_text = decrypt(encrypted_text, key)
    with open(file_name[:-4], 'wb') as output_file:
        output_file.write(decrypted_text)
    os.remove(file_name)

# This function takes an alphanumeric string as a password and passes it to pycryptodome's PBKDF2 
# algorithm to generate an encryption key 
def generate_key(password):
    salt = b'\x83\xdb\xb9\xd3\xdc"\x1e\x0ee"\x0c\xf0=5\xab_\x18\xd7\xd2\x98\x92Q.\xbd\x9cK\x96\x93-J\x08\xe0'
    return PBKDF2(password, salt, dkLen=32)

secretfile = "top_secret.txt"

password = str(input("Enter a password for encryption:"))
key = generate_key(password)

option = int(input("Enter 1 to encrypt file.\nEnter 2 to decrypt file.\nSelection:"))
if option == 1:
    file_encrypt(secretfile, key)
    print("file encrypted!")

elif option == 2:
    encrypted = secretfile + ".enc"
    file_decrypt(encrypted, key)
    print("file decrypted!")

At the very end I included a simple test to see it all in action. The string secretfile contains the name of the file you want to encrypt.

To run the code from the command line make sure you are in the directory the file is located in and run the following command: python crypto.py.

If you have older versions of python installed, you may have to run python3 crypto.py to specify we want to use Python 3.

Feel free to modify the code in any way you want! Remember this code isn’t 100% safe, do not use it to secure sensitive documents or anything you do not want to possibly become corrupted!

Great job sticking with the tutorial and seeing it through to the end! I hope you learned a little bit about how encryption works and that I was able to pique your interest in cryptography and information security. It’s a really promising career path that is in high demand. I encourage you to do a little research and come up with ways to make our code more secure. Maybe look into password hashing and ways to validate that the user entered the correct password. Well that’s enough out of me. Thanks for reading and catch you next time!

Posted in: Python, Tutorial

Styling your first webpage with CSS

This article is part of a series:

If you’ve followed along, then you’ve created your very own webpage using HTML and put it on the web using Netlify. You probably noticed that it’s very plain-looking. That’s because we haven’t specified how anything should look. By default, the browser applies some basic styles—headings are big and bold, lists are indented, links are blue and underlined.

These default styles get the point across and make the site usable, but we could definitely make some improvements and use our own sense of style to add some personality. Design on the web is a big, wonderful world, with many resources to help yourself learn and improve. Here’s a great book on web design made for non-designers.

That said, for this article, we’re going to keep things simple and focus more on how to write CSS than how to create a great design. As you get better at HTML and CSS, you will be able to do more and you will need to follow design principles to keep your websites from becoming cluttered and chaotic. Fortunately, our site only has a little content.

As a reminder, here’s an example of the unstyled website we created in the last article.

If you want see what styles we’ll be adding to this page, check out the styled version of the website.

The <style> tag

CSS, or Cascading Style Sheets, is the language that we use to describe the appearance of our webpages. Any CSS styles that we add get applied to our webpage in addition to the basic styling that the web browser has already supplied.

Where do we write CSS? Well, remember that our index.html document contains a <head> section that has information about the page that is invisible to the user.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>My awesome website</title>
    </head>
    <body>
        <h1>My awesome website</h1>

        <ul class="menu">
            <li><a href="index.html">Home</a></li>
            <li><a href="journal.html">Journal</a></li>
        </ul>

        <p>My name is Blake. I enjoy making websites and writing articles. I think everybody should have a personal homepage.</p>

        <h2>Favorite board games</h2>

        <ul>
            <li>Dungeons & Dragons</li>
            <li>Risk</li>
            <li>Monopoly</li>
        </ul>

        <h2>Favorite TV shows</h2>

        <ul>
            <li>Stranger Things</li>
            <li>Cheers</li>
            <li>Game of Thrones</li>
        </ul>
    </body>
</html>

We can add a <style> tag inside the <head> tag that will contain all of our CSS code.

<head>
    <meta charset="UTF-8">
    <title>My awesome website</title>
    <style>
        ...CSS code goes here...
    </style>
</head>

Great, let’s write our first CSS rule.

<style>
    body {
        font-family: "Gill Sans", sans-serif;
    }
</style>

This rule changes the font of everything inside the <body> tag to Gill Sans, if available on the user’s device. If not, it tells the browser to use a default sans-serif font. 1

Save the file and open it up in a web browser (File > Open File…).

Anatomy of a CSS rule

Let’s look a little more closely at what we did in that example. Here’s the code again (from now on I’m omitting the <style> tag in these samples, but that is where the CSS code lives for now).

body {
    font-family: "Gill Sans", sans-serif;
}

That first bit, body, is called a selector. You might say it selects the parts of your page you wish to style.

The line inside the braces ({}) is a property and value. The property in this example is font-family, which controls what font you want to use. The value is "Gill Sans", sans-serif, which tells the browser, “I would like to use Gill Sans but if the user doesn’t have it, use any sans-serif you have.” Note that a ; goes at the end of the property/value line.

You can add multiple properties to a rule. For example, let’s make the width of our page more narrow so that users with wide screens don’t have to follow the text all the way across the screen.

body {
    max-width: 500px;
    font-family: "Gill Sans", sans-serif;
}

We just set the max-width property of the body to be 500px. That means the width of our page will never exceed 500 pixels in width. Any text that would go beyond that width will instead be wrapped around to the next line.

It doesn’t really matter what order the properties go in, but I have my own preferences I tend to follow. The important thing is that, whatever ordering scheme you decide on, you be consistent.

As you can probably imagine, there are quite a few properties that you can use. In time, you will begin to remember the common ones offhand. But if you aren’t sure what property you need or you just want to see what’s available, check out the MDN CSS Reference (it’s a long list, but remember that you only need a handful for now—there’s no need to memorize this list.

Adding more styles to the page

Let’s look at our styling progress up to now.

A screenshot of the webpage with the font changed and the body width narrowed, aligned toward the left side of the window.

So far, so good. But we should probably make the page a bit more centered so that people with wide screens don’t have to stare off to the left side so much.

We’re going to use the margin property, which controls the space around an element. Specifically, we’re using maring-left and margin-right, like this:

body {
    margin-left: auto;
    margin-right: auto;
    max-width: 500px;
    font-family: "Gill Sans", sans-serif;
}

We could have specified a pixel value here, but by using the auto keyword, we’re telling the browser that we want an even amount of margin to the left and right of the page. The result is that the page is centered in the browser window.

Screenshot showing that the webpage is centered within the window.

Okay, cool. Let’s try changing some colors.

body {
    margin-left: auto;
    margin-right: auto;
    max-width: 500px;
    font-family: "Gill Sans", sans-serif;
    background-color: antiquewhite;
    color: saddlebrown;
}

That will give us:

Screenshot of webpage showing the colors applied.

Woo hoo, colors! We’re setting the background-color property, which defines the color of empty space, the background of the page. We’re also setting color, which controls the color of text on the page.

There are different ways to reference colors in CSS. We’re using color keywords for ease of use. You can see the whole list of available color keywords, as well as other ways to represent colors, on this MDN CSS color reference.

We’re not going to win any design awards for the color choices here, but it’s my webpage and I can do what I want. 2

Styling links

By default, links are blue. But that isn’t sitting well with with the warm colors we chose. Let’s change it to something warmer.

a {
    color: firebrick;
}

We’re creating a new rule. We want to target all of the <a> elements on the page. We can do that by using a as the selector. Remember that color controls the text color. We’ll make it a reddish color.

For fun, let’s make it so that the color of the link changes when you hover the mouse over it. We’ll need a new rule for this, with a slightly different selector. We don’t want to target every link, only the one the mouse is being hovered over. CSS has a special syntax for selecting elements that are in a certain state, like being hovered over.

a:hover {
    color: crimson;
}

This selector says, if a link is in the hover state, apply this rule. In this example, we’re just changing the text color.

Meaning vs. appearance

Let’s make our navigation links sit horizontally in a row rather than stacked in a bulleted list. Remember, our list of links looks like this:

<ul>
    <li><a href="index.html">Home</a></li>
    <li><a href="journal.html">Journal</a></li>
</ul>

You might think, “Well if I don’t want a bulleted list, I’ll just change the HTML.” But in this case, we aren’t changing the meaning of the menu—it is still a list of links. It’s just that we’re changing the way it looks by tweaking the layout and removing the bullets.

So we’ll keep the HTML the way it is. But we’ll add some CSS to change the appearance.

ul {
    padding-left: 0;
    list-style: none;
}

First, we’ll target the list as a whole. We’ll set padding-left to 0 to remove the indentation (padding is similar to margin, but we’ll discuss the difference later). You can use list-style to change the bullet type, but we’re setting it to none so that the bullets are removed altogether.

Next, we’ll target the individual list items, or <li> elements.

li {
    display: inline-block;
    margin-right: 15px;
}

Setting the display property to inline-block will cause the list items to sit next to each other in a row. We’ll add a little margin-right to the list items so that they are spaced apart nicely.

But notice, there’s a problem:

Screenshot of webpage showing the menu links sitting horizontally in a row. The page has two other lists which are now also sitting horizontally without bullets.

By attempting to style our menu list, we inadvertently styled all of our lists. We don’t want that. But how do we target only the menu list? We can give it a name.

<ul class="menu">
    <li><a href="index.html">Home</a></li>
    <li><a href="journal.html">Journal</a></li>
</ul>

We can give any element the class attribute to give it one or more names (separated by spaces) that we can use in our CSS. Let’s adjust our CSS to use the new name.

.menu {
    padding-left: 0;
    list-style: none;
}

We changed the ul selector to .menu. When using class names in CSS, we start them with a dot.

We can use this same name to target our list items.

.menu li {
    display: inline-block;
    margin-right: 15px;
}

This selector is saying, “target all list items that are inside an element with the class name of menu.”

Now that both of our rules are specifically targeting the menu class name, our regular lists have reverted back to their original look.

Screenshot of the webpage showing the menu as a horizontal list without affecting the other lists on the page.

Styling the site header

Let’s do something fun with the site header. Hopefully you are starting to get the idea of how these CSS rules work—first you specify a selector, then a list of properties you want to change. This article is already getting long, so I’ll just drop in the code rather than describe each property. I encourage you to play around with the values to see how they work.

h1 {
    margin-top: 0;
    padding: 10px;
    font-size: 18px;
    font-weight: normal;
    text-transform: uppercase;
    letter-spacing: 1px;
    background-color: saddlebrown;
    color: antiquewhite;
}

This code produces the following look.

Screenshot of the webpage. The main heading now appears inside of a dark box with light, all-caps text.

One thing I want to point out—this rule demonstrates the difference between padding and margin. I gave <h1> some padding to provide some space within its box, to give the text a little padding between it and the edge of the box. On the other hand, margin controls the space around the outside of the box.

I really want the <h1> to touch the top of the viewport, but, by default, there’s a little margin all around the <body>. We’ll go back and modify our body rule to get rid of the top margin.

 body {
    margin-top: 0;
    margin-left: auto;
    margin-right: auto;
    max-width: 500px;
    font-family: "Gill Sans", sans-serif;
    background-color: antiquewhite;
    color: saddlebrown;
}

There we go. Our homepage is looking good.

Reusing CSS across different pages

We would like to apply all of the styles we wrote for the homepage to our journal page. One way to do that is to copy and paste our <style> tag and all its contents to journal.html. That would work, but what if we decide to make a change, such as choosing a different color for links? We would probably want to change the link color on both the homepage and the journal. That means editing two different files. Making changes would become more and more difficult for each additional page we add to our site.

Fortunately, there’s a better way. We’ll use an external style sheet. We’ll take all of our CSS out of index.html and put it into a separate file. Then we’ll make both the homepage and journal reference that file.

First create a separate file and name it style.css (you can name it whatever you like so long as it ends in .css). Then copy everything between the <style> and </style> tags (but not the tags themselves) and paste it into your new CSS file.

Next, edit index.html by adding a <link> tag to the <head>:

<head>
    <meta charset="UTF-8">
    <title>My awesome website</title>
    <link rel="stylesheet" href="style.css">
</head>

This bit of code links your HTML file with your CSS file. Now index.html knows that you have CSS rules that it should use in style.css.

Go ahead and make the same change to journal.html. Once you do, the journal page should be receiving all of your custom styles.

Screenshot of the Journal page. The text and color styles from the homepage have also been applied to this page.

Styling articles

Let’s spruce up our blog article by making it appear on a white card. Add this rule to style.css:

article {
    padding: 20px;
    background: #fff;
}

That’s nice. But why is there so much space above the heading? It’s because the <h2> has top margin by default. But we can remove it.

article h2 {
    margin-top: 0;
}

This rule is targeting every <h2> that appears inside an <article> and removing its top margin.

That’s looking better.

Screenshot of the Journal page. Its one article now it appears on a white card.

Let’s update our journal by adding another article. It should automatically receive the correct styles so long as we use the same HTML structure.

Blog articles usually appear with the newest ones first, so let’s add another article right above the first one.

<article>
    <h2>My second entry</h2>

    <time datetime="2020-01-12">January 12, 2020</time>

    <p>I added some CSS to my website. It’s very stylish.</p>
</article>

It received the styles but something isn’t right—the cards are touching, causing them to appear like one giant card.

Screenshot of the journal page with a second article added.

Not to worry, we can add some bottom margin to each article. Adjust the article rule like so:

article {
    margin-bottom: 20px;
    padding: 20px;
    background: #fff;
}

Which produces:

Screenshot of the Journal page. The two article cards now have vertical space between them.

Much better. One last issue. Our menu appears to have lost its horizontal styling. That’s because we need to add the menu class name to our menu list. Make the following adjustment in journal.html.

<ul class="menu">
    <li><a href="index.html">Home</a></li>
    <li><a href="journal.html">Journal</a></li>
</ul>

Looks great! You can check out the final journal page here.

Publishing your changes

Head back into your Netlify dashboard and go to the Deploys tab. At the bottom of the page you will see a box where you can drag and drop your website folder (just make sure you’ve saved all the files).

That’s it! Your website should have been updated to reflect the latest changes.

Conclusion and bonus challenge

If you have followed all the way through, you deserve a cookie and a pat on the back! You not only created your own website from scratch using HTML, you also made it look stylish by using CSS.

If you are thirsty for more, here’s a challenge for you. Adjust your menu so that the current page is in bold and not linked (hint: you could use a special class name).


  1. Most web browser’s default to Times New Roman, which is a serif font. There’s nothing wrong with Times New Roman, necessarily, but many webpage authors will change it just because it is the default font. If you want to go down the rabbit hole of the art and science of typography — which I totally recommend you do — check out Butterick’s Practical Typography
  2. That said, if you want people to actually be able to read your webpage, you want to choose background and foreground colors that contrast well. You can use this color contrast checker to make sure your text is easy to see. 

Posted in: Design, Tutorial, Web Dev

Web design in 4 minutes →

I plan to do a little of an introduction to CSS to follow up my post about making your first website. But until then this is a nice walkthrough of adding some visual styles to a webpage made with default HTML styling.

Posted in: Design, Tutorial, Web Dev

Getting Started with Voice Driven Development →

This is a little bit of an advanced read if you are just starting out. But I wanted to link to it to demonstrate that it’s possible to code even if you have extreme difficulty typing on a hardware keyboard—or even if you can’t type on a hardware keyboard at all.Talon is the software that I use to code by voice (I also use an onscreen keyboard, but that’s for another post). It’s Mac-only for now, but it’s coming to Windows and Linux very soon.

Posted in: Assistive Technology, Resources, Talon, Tutorial, Web Dev

Your first webpage with HTML and Netlify

This article is part of a series:

Ok, you have decided it would be cool if you knew how to code a webpage. Now what? This article is going to take you from nothing to having your own website on the internet. Provided you have a computer and an internet connection, the following guide will get you online with your very first webpage—for free.

Tools of the trade

To get started, you need two things:

Fortunately, essentially every computer comes with both of these! Modern web browsers are pretty awesome so it doesn’t really matter which one you choose. If you’re looking for a recommendation, I use and enjoy Firefox.

Although your computer does come with a text editor (like Notepad on Windows or TextEdit on Mac), coding webpages is easier if you get a text editor that’s made for coding. There are a lot of options in this space, which I encourage you to explore when you’re ready. But I recommend you download and install the free editor from Microsoft, Visual Studio Code (I’ll refer to it as VS Code).

The power to publish

The next thing to consider is what you want to say on your website. What do you want it to be about? We live in an amazing time when just about anyone can publish something and make it available to everyone. This is the number one reason I think everyone should have their own website.

Use whatever writing tool you’re comfortable with and literally write down some content for your website.

If you need some guidance, try this:

Of course, feel free to write less or more. You can have several sections on the page if you would like, each with its own heading. You may even decide that you need multiple pages. That’s cool, too.

A website is just files and folders

Most of the big websites that you use every day are more complicated than that. But at its simplest, a website is just a collection of files that are linked together.

So your first step needs to be to create a folder on your computer. Usually, you use your web browser to connect to websites over the internet. But you can actually just open a website from your computer if you want—and that’s what we want to do here. We’re going to work on our website on our own computer before uploading it to a server on the internet.

Create a folder somewhere on your computer. Name it, for example, my-website.

Now we are going to create a file for our homepage. Create a new file inside the folder you just created. By convention, the name of our homepage file should be index.html.

Open that file in your web browser 1. You should see a bright white page—an empty canvas. Don’t worry, we’re about to fill it in.

Writing your first HTML

If you chose Visual Studio Code, go ahead and open it. Otherwise use whatever text editor you prefer. If you’re using a different editor, your steps may differ slightly from those in this guide.

Once you start VS Code, click the “Open Folder…” link. Open the my-website folder you created earlier. You should see your file in the sidebar. Click it to open it.

The first thing we’re going to write is:

Hello world

Save it and open it in your browser. Congratulations, you made a webpage!

The browser displays this ordinary text because we haven’t told the browser anything about this text. We need to mark it up.

<h1>Hello world</h1>

Make this change and refresh your browser. The text should now be styled bold and a good bit larger. That’s because we’ve used HTML to describe this piece of text as a heading—specifically, a heading level 1.

HTML uses tags to describe content. In this case, we’ve wrapped the text, “Hello world,” with the <h1> tag. Notice that to close the tag, it’s written the same way but with a / right before the tag name.

Tagging your content

“Hello world,” was just a test. Obviously, we would like to use our own content. Copy and paste your content from your writing tool into your index.html file. Now you want to use tags to describe your content to the browser. There are over a hundred tags in HTML. But knowing just a handful of them is plenty enough to get you started.

For example, you can use the <h1> tag we used earlier for the main heading of your website.

If you wrote an intro paragraph, you can surround it with the <p> tag (“p” for “paragraph”). Don’t forget to put the / in the closing tag like so: </p>.

If you included a list of any kind, you can mark it up like this:

<ul>
    <li>My first thing</li>
    <li>Another thing</li>
    <li>The last thing</li>
</ul>

This is an example of nested tags. Each list item is marked up using the <li> tag. All three list items are wrapped by the <ul> tag, forming an unordered list, which is just HTML-speak for a bulleted list. If we wanted them to be numbered—that is, an ordered list—we could use the <ol> tag.

Here’s a very basic example:

<h1>My awesome website</h1>

<p>My name is Blake. I enjoy making websites and writing articles. I think everybody should have a personal homepage.</p>

<h2>Favorite board games</h2>

<ul>
    <li>Dungeons & Dragons</li>
    <li>Risk</li>
    <li>Monopoly</li>
</ul>

<h2>Favorite TV shows</h2>

<ul>
    <li>Stranger Things</li>
    <li>Cheers</li>
    <li>Game of Thrones</li>
</ul>

When rendered in the browser, it looks like this:

The head and the body

Our HTML document isn’t technically correct. It’s missing some useful information about the document itself. For example, take a look at the title that is displayed in the browser tab. It’s pretty ugly and useless.

An HTML document actually consists of a few parts. First, every HTML file should start with the following line of code:

<!DOCTYPE html>

This lets the browser know that this is an HTML file.

Following that, there’s the <html> tag, which contains two tags: <head> and <body>. The <head> tag is for information about the document that is invisible to the user. The <body> tag is for the page content.

Our document structure should look like this:

<!DOCTYPE html>
<html>
    <head>

    </head>

    <body>
        ...page content...
    </body>
</html>

We can change that pesky tab title by adding one to our <head> tag like this:

<head>
    <title>My awesome website</title>
</head>

And as a good practice, we should tell the browser what character set we are using in the document (which, unless you are purposely doing something else, should be utf-8). We can do it like this:

<head>
    <meta charset="utf-8">
    <title>My awesome website</title>
</head>

You’ve just met the <meta> tag, which is one of the tags in HTML that doesn’t need to be closed because it doesn’t contain content. That said, HTML tags can have attributes. The most famous one of those is probably the one that is required to make a clickable link, the href attribute on the anchor, or <a>, tag.

<a href="https://able-dev.com">This is a link to my website</a>

Have yourself a cookie, because you just coded your first webpage.

For reference, your entire index.html should look something similar to this:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>My awesome website</title>
    </head>
    <body>
        <h1>My awesome website</h1>

        <p>My name is Blake. I enjoy making websites and writing articles. I think everybody should have a personal homepage.</p>

        <h2>Favorite board games</h2>

        <ul>
            <li>Dungeons & Dragons</li>
            <li>Risk</li>
            <li>Monopoly</li>
        </ul>

        <h2>Favorite TV shows</h2>

        <ul>
            <li>Stranger Things</li>
            <li>Cheers</li>
            <li>Game of Thrones</li>
        </ul>
    </body>
</html>

Adding pages to your website

It’s totally fine for your website to consist of only one page. But chances are that you will want more. Let’s create a journal page and set up navigation between them.

First, create a new file in your my-website folder called journal.html. Instead of typing the whole page structure out, let’s copy and paste our homepage code over to this file and empty out the <body> tag. It should look something like this:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>My awesome website</title>
    </head>
    <body>

    </body>
</html>

Let’s make a heading and our first entry:

<h1>Journal</h1>

<article>
    <h2>My first entry</h2>

    <time datetime="2019-09-25">September 25, 2019</time>

    <p>I'm having a blast learning HTML and setting up my first website!</p>
</article>

We are introducing some new tags. We have several tags that we’re saying makes up an <article>. We’re also using a tag to mark up the date of the article—the <time> tag. Inside the tag it contains the nice human readable date. But it also has a datetime attribute that contains a machine readable version.

Now that we have a journal page, we need to add a way to get to it from our homepage. We’ll add a navigation list. Let’s put it right underneath the <h1> in index.html:

<ul>
    <li><a href="index.html">Home</a></li>
    <li><a href="journal.html">Journal</a></li>
</ul>

Okay cool, we’ve created a navigation list. We can just copy that in paste it right under the <h1> in journal.html. With this navigation list on both pages, visitors to your website will have a way to move back and forth.

Your website isn’t doing much good just sitting on your computer. It’s time to get that thing on the internet!

Hosting your website

Hosting your website refers to putting your HTML files on a web server. There are a lot of options here, but for ease of use and cost, we’re going to use Netlify.

Go ahead and create an account at Netlify. Once you are logged in, make sure you are on the Sites tab. Toward the bottom of the page you should see an area where you can drag and drop your site folder. Go ahead and do that.

You will see that your website gets uploaded and assigned a randomized URL. Your site is now live! If you want, you can click the Site Settings button and change the Netlify address to something memorable. For example I changed mine to https://able-dev-example.netlify.com/.

You can also follow the instructions for adding a custom domain name.

You did it!

Take a moment to appreciate what you’ve accomplished. You started with a blank slate. You wrote some content and marked it up with HTML. You made two pages and linked them together. Then you uploaded your site to a web host. Your website is now live for anyone to visit.

There’s a lot that this guide left out. For example, our website looks pretty plain. Wouldn’t it be cool if we added colors and other styles? That’s for another day (but if you’re feeling adventurous, do a web search for “CSS”). Feel free to continue to work on your site locally on your computer. When you’re ready to upload your new changes, go to your site’s dashboard page in Netlify and click on the Deploys tab. You can drag and drop your folder there to replace the existing site with your updated one.

Have fun with your new powers—and only use them for good!


  1. On Mac, you can drag the file to your browser’s icon on the dock. On most systems you can also use the File menu. 

Posted in: Tutorial, Web Dev