Bläddra i källkod

Build a Blog Posts

Steffen Cole Blake 4 år sedan
förälder
incheckning
cc0bd9c0c3

+ 104 - 0
content/post/hugo/part-1-making-of-this-blog.md

@@ -0,0 +1,104 @@
++++
+author = "Steffen Blake"
+title = "Making Of this Blog - Part 1"
+date = "2021-09-24"
+description = "Statically Served, High availability"
+tags = [
+    "blog",
+    "docker",
+    "kubernetes"
+]
+categories = [
+    "hugo"
+]
+series = ["Hugo"]
+aliases = ["making-blog-part-1"]
++++
+
+Part 1 - Statically Served, High availability <-- (You are here!)
+
+{{< timelink n="2" after="2021-09-30" desc="Building a CI/CD Markdown Blog" href="/post/hugo/part-2-building-a-blog">}}
+
+{{< timelink n="3" after="2022-01-01" desc="Serve Hugo on Kubernetes" href="/post/hugo/part-3-building-a-blog">}}
+
+## Pre-amble
+
+I wanted to take some time to write up a guide on some handy docker images I created recently in my process of building this very blog. I personally serve everything off of a Kubernetes cluster, but you could very well use this system much the same way on something like Docker Swarm or really any Docker management system.
+
+## Goals
+
+There were a couple primary goals when designing my blog architecture that had to be met.
+
+1. All blog posts are written in markdown and automatically converted to HTML
+
+2. Statically served pages for the fastest load times possible
+
+3. Host on any git repository and utilize Webhooks for automatic push and build to this website
+
+4. As small of a footprint as possible for the entire setup.
+
+After a fair bit of research I came to the conclusion that the following applications were ideally what I needed
+
+## Repository: Gogs
+
+Gitea has more features and it actually was my first pick, but unfortunately I spent well over a week trying to get it working and just couldn't get it to be consistent. I had some weird http errors with redirection loops.
+
+So instead I went with Gogs (the app it is a fork of) which has less features. However, still enough features.
+
+For those of you following along though I will preface this with the fact that `any` repository server (Github, Gitlab, Bitbucket, Gitea, Gogs, etc etc) `should` be compatible. Theoretically.
+
+The only feature that is needed from the repo is the ability to setup Webhooks for Push events with a Secret, which basically every git server nowadays supports.
+
+## Static File Host: `flashspys/docker-nginx-static` (with a twist)
+
+This is an awesome docker image that was created by [Felix Wehnert (flashspys)](https://github.com/flashspys) that I made my own fork of, `docker-nginx-static-ha` which can be found [here](https://github.com/SteffenBlake/docker-nginx-static-ha)
+
+What particularily caught my eye and has proven excellent:
+
+### The image can only be used for static file serving but is less than 4 MB (roughly 1/10 the size of the official nginx image). The running container needs ~1 MB RAM.
+
+#### So whats the difference?
+
+Primarily how the files are cached. Specifically, `docker-nginx-static` simply just serves a mounted directory `directly`. This means once it is running, any changes you make to the directory will be reflected instantly.
+
+I actually didnt want this, because when I run a build of the blog I dont want pages to be breaking if someone accesses the website mid-build.
+
+So I made a minor tweak and created `docker-nginx-static-ha` (the ha is for High availability).
+
+Now when the docker image is spun up it `copies` all of the mounted files that it will serve to its own internal directory, and then serves `that` directory instead.
+
+This small tweak now makes a big difference. Once the docker image is spun up it internally "caches" all the files over, and if you modify the original mounted directory, `no changes are reflected on the served pages`
+
+So now you can modify the original directory to your hearts content without making any impact on the website!
+
+#### Okay so how do I actually make it update?
+
+Simple, you just turn it off and back on again. When it spins back up again it will re-cache all the files
+
+### Wait so... wouldnt that take the website down...?
+
+If you only have a single docker container running, yes. But thats where the `HA` part comes in. We will dig into it farther below but what you would ideally want to have happen is use a docker management system like Swarm or Kubernetes which has `multiple` containers running in parallel, a load balancer to direct traffic across them, and then when you roll out an update you take the containers down `one at a time` so you always have some running, thus the website `smoothly` transitions over without any downtime or breaking issues.
+
+## Blog compiler: Hugo
+
+Honestly there's a few good options but I really have been enjoying Hugo. Its popular, its slick, its written in Go and thus works on my Raspberry Pi 4s, it compiles my blog wicked fast, and it has a pretty small footprint.
+
+Being able to also manage what theme I use simply by what git repo I set as a submodule is also quite choice. This made the next part below also pretty easy since I could just import the theme along with the actual blog by just using the `--recurse-submodules` flag on `git clone`
+
+## Blog CI/CD: adnanh/webhook
+
+[Link here](https://github.com/adnanh/webhook)
+
+This is another extremely lightweight and brutally simple application built by [Adnan Hajdarević](https://github.com/adnanh), once again built on go and thus compatible with basically everything.
+
+It simply lets me write a "listener" for a webhook event and then fires off a bash script on trigger. I couldn't really ask for much else. Well. Actually there is one thing I could ask for, and that is support for refering to env variables inside of the webhook triggers and whatnot. Unfortunately I had to use a custom solution with `sed` to manually (oof) replace 'variables' in my webhook json, since I wanted those to be a configurable value.
+
+## Putting them together: webhook-hugo
+
+The next step was to combine webhook + hugo together into a single docker image, since both were compiled with go and could run in alpine this was actually pretty trivial. I found two solid and working hugo and webhook docker images and effectively just put them together. Then I prebuilt the webhook json file to be mounted in and a bit more bash work and, viola!
+
+[docker-webhook-hugo](https://github.com/SteffenBlake/docker-webhook-hugo) now exists!
+
+I detailed how to use it on its github page but I will dig into how to actually consume and use these tools on the next blog post, so look forward to that!
+
+### {{< timelink n="2" after="2021-09-30" desc="Building a CI/CD Markdown Blog" href="/post/hugo/part-2-building-a-blog">}}

+ 470 - 0
content/post/hugo/part-2-building-a-blog.md

@@ -0,0 +1,470 @@
++++
+author = "Steffen Blake"
+title = "Making Of this Blog - Part 2"
+date = "2021-10-01"
+description = "Building a CI/CD Markdown Blog"
+tags = [
+    "blog",
+    "docker",
+    "kubernetes"
+]
+categories = [
+    "hugo"
+]
+series = ["Hugo"]
+aliases = ["making-blog-part-2"]
++++
+
+[Part 1 - Statically Served, High availability](/post/hugo/part-1-making-of-this-blog)
+
+Part 2 - Building a CI/CD Markdown Blog <-- (You are here!)
+
+{{< timelink n="3" after="2022-01-01" desc="Serve Hugo on Kubernetes" href="/post/hugo/part-3-building-a-blog">}}
+
+
+# Requirements
+
+To start off if you want to follow this guide, you will need the following:
+
+1. A machine with Docker installed on it. [See here for the docker install guide](https://docs.docker.com/get-docker/)
+
+2. Hugo installed as well. [See here for the hugo install guide](https://gohugo.io/getting-started/installing/)
+
+3. Git installed. [See here for the git install guide](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
+
+4. A browser
+
+Thats basically it!
+
+# Step one - Create the output folder
+
+### Windows
+
+Create a folder named `www` in your C drive, such that you now have `C:/www/` as a directory that exists
+
+### Linux
+
+```bash
+
+sudo mkdir /www
+sudo chown nobody:nogroup /www
+
+```
+
+# Step two - Create the index file
+
+### Windows
+
+1. Create a file named `index.html` in the new `www` folder
+
+2. Edit it with notepad and just enter this text in and save, `Hello World!`
+
+### Linux
+
+```bash
+
+touch /www/index.html
+echo "Hello World!" > /www/index.html
+
+```
+
+# Step three - Spin up nginx-static-ha
+
+Same command for both operating systems:
+
+```bash
+
+docker run -D -v /www:/static -p 8080:80 --name my-site-0 steffenblake/nginx-static-ha
+
+```
+
+This will spin up the docker container. You can then verify its running via:
+
+```bash
+
+docker container ls
+
+```
+
+And you should see `my-site-0` on the list.
+
+# Step four - Check its output
+
+### Browser
+
+Open up the following url: [http://localhost:8080](http://localhost:8080)
+
+You should be greeted with "Hello World!" in your browser
+
+### Headless CLI
+
+If you dont have a browser to work with you can also just do:
+
+```bash
+
+curl http://localhost:8080
+
+```
+
+Which should output "Hello World!" to your terminal
+
+# Step five: Verify the High Availability 
+
+With the docker container still actively running lets modify `index.html` and see what happens.
+
+### Windows
+
+Open `index.html` again and change its text to something else and save it
+
+### Linux
+
+```bash
+
+echo "Hello world, again!" > /www/index.html
+
+```
+
+And then to verify it stuck (Should output "Hello World, again!"):
+
+```bash
+
+cat /www/index.html
+
+```
+
+### Now test it
+
+After doing either of the above steps, now refresh your browser (or `curl` it again)... Hey! The text didnt change! Thats right, the original text for `index.html` was cached and your changes to the original files has had zero impact on the actual running site. This is good, we only want changes to happen when we trigger them on purpose
+
+# Trigger a redeploy
+
+One simple command to restart the container:
+
+```bash
+
+docker restart my-site-0
+
+```
+
+Give it a few seconds to restart, and then once again refresh your browser or `curl`, and lo and behold now "Hello world, again!" should show up. Congrats we now have the static file serving working great!
+
+# Step six - Create our git repo
+
+Choose your github server of choice (Github, Gitlab, Gitea, Gogs, whatever) and create a public repo on it. Lets call it `MyBlog` for now.
+
+Then follow [this guide here](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) to create an Access Token (assuming you are using Github) if you havent already, and make sure it has `Push` and `Pull` privileges.
+
+For our case we probably dont want this token to ever expire, so set `none` or `never` for the expiry.
+
+Save this somewhere safe.
+
+# Step seven - Bootstrap the hugo site
+
+Now we need to setup our website template, which is actually quite simple.
+
+First off make yourself a folder you want to keep your work in, on your desktop is fine for now. Lets call the folder Blogs for now.
+
+Open up your terminal inside of that folder via whatever means works in your operating system. (On windows you can `shift+right click` > `Open Powershell Window here`)
+
+And then run the following command:
+
+```bash
+
+hugo new site website
+
+```
+
+After it runs you should now have the folder `website` inside of `Blogs` on your desktop.
+
+Next up we will use git to pull down our website to a different folder. On your git server of choice (I will use Github in this case) you will want to copy the `https` clone url.
+
+With your terminal still opened up in that `Blogs` folder, run this command:
+
+```bash
+
+git clone <your url your copied from above>
+git init
+
+```
+
+This should now create a folder called `MyBlog` (Assuming thats what you named the repo) inside of `Blogs`
+
+Inside of it should probably be an empty folder with perhaps the `.git` folder, maybe the `README.md` and/or the `LICENSE` file.
+
+Next we will copy all the files and folders Hugo made from that `website` folder to the `MyBlog` folder 1:1
+
+#### Don't copy the website folder itself in, if you do it right the file `config.toml` should exist now at `<Your Desktop>/Blogs/MyBlog/config.toml`
+
+# Step eight - Pick a theme!
+
+Alright! Nearly done, now for one more step, navigate over to https://themes.gohugo.io/ and pick out a theme you like.
+
+On the themes page hit the Download button which *usually* takes you to a git server (often Github)
+
+We need to take note of two things. First off that same clone HTTPS Url again. Second the name of the theme.
+
+Lets use the hugo-PaperMod theme as an example. The two things we want can be seen here in this pic below.
+
+![Github Example](/images/part-2-building-a-blog/github-example.png)
+
+The green box is that HTTPS Url we need which I will call `<Clone Url>` and the red is the `<Repo Name>`
+
+In our case for hugo-PaperMod this is `https://github.com/adityatelange/hugo-PaperMod.git` and `hugo-PaperMod` respectively.
+
+We now need to move our terminal into the `MyBlog` folder that git made us. Assuming your terminal is still pointing at `Blogs` you simple just execute:
+
+```bash
+
+cd MyBlog
+
+```
+
+And you should now be pointing at `Blogs/MyBlog`
+
+Excellent, now we can add the theme. Execute this command:
+
+```bash
+
+git submodule add <Clone Url> themes/<Repo Name>
+
+```
+
+Or in the case of paperMod this would become
+
+```bash
+
+git submodule add https://github.com/adityatelange/hugo-PaperMod.git themes/hugo-PaperMod
+
+```
+
+Now we can verify this worked by simple checking and verifying that the folder `hugo-PaperMod` (or whatever your repo name is) exists inside of the `themes` folder
+
+So for papermod's example, the following file should now exist:
+
+`<Desktop>/Blogs/MyBlog/themes/hugo-PaperMod/config.toml`
+
+Finally we need to add this theme to our root `config.toml`, which is not the one mentioned above, but instead this one:
+
+`<Desktop>/Blogs/MyBlog/config.toml`
+
+Which is as simple as just adding this entry to the very bottom of the file:
+
+```
+
+theme = "<Repo Name>"
+
+```
+
+Or in our case
+
+```
+
+theme = "hugo-PaperMod"
+
+```
+
+# Step nine: Run the site locally to test
+
+With our terminal pointing at the `MyBlog` directory we want to now run this command:
+
+```
+
+hugo server -D -F
+
+```
+
+There are two params we are passing in here.
+
+* -D - Publish Drafts
+    * This command will still host up files tags as `draft = true`
+* -F - Publish Future
+    * This command will still host up files set to publish in the future
+
+Don't worry too much about this, but, this is the command you will want to run to be able to preview your posts on the fly when editing them locally, before you commit them.
+
+Once you run this command you should see something like this in your terminal:
+
+```
+
+Web Server is available at http://localhost:1313/ (bind address 127.0.0.1)
+
+```
+
+Open that link up in your browser and, viola! Your website exists!
+
+You can hit Ctrl+C in the terminal now to turn the site off.
+
+# Step ten: Push up the site
+
+We will first make one last little tweak to make our lives easier in the future.
+
+Create a file called `.gitignore` (note the period at the start) in the `MyBlog` folder (if one doesnt exist yet). Edit this file with a text editor and add this line of text to it:
+
+```
+
+/public
+
+```
+
+And save it.
+
+Then back in your terminal, run these commands:
+
+```
+
+git add -A
+git commit -m "Initial Commit"
+git push
+
+```
+
+The last command will prompt your for your username and password. In Github's case, this is your email for the username, and the password is that Access Token you generated back in step Six.
+
+You should now be able to go to your actual git repo on Github.com or etc and see that all your website's files are now pushed up online.
+
+# Step eleven: Port forwarding
+
+Now here's the fancy part, we can semi automate the process of building the website everytime we make changes and automatically push them into that `www` folder we made back in Step One, for consumption by our `nginx-static-ha` docker image we set up in Steps three to five
+
+First off check out your public ip by just googling "Whats my ip?", it should show up for you. This is the public IP people can go to which then sends traffic to our router.
+
+But to then get traffic to go from your router to your PC, we have to specify further. This is called port forwarding.
+
+To start you will need to expose port 9000 to the internet for triggering webhooks. All this means is when Github detects changes to your repo, it will trigger a rebuild on your computer.
+
+Follow [this guide here](https://www.hellotech.com/guide/for/how-to-port-forward). You will want to port forward port 9000 to 9000, on TCP, to the local IP of the machine you are wanting to run `nginx-static-ha` on.
+
+This will now make it so when someone types in `<Your.Public.Ip.Address>:9000` it directs traffic all the way through your router and to `<your.local.device.ip>:9000`
+
+# Step twelve: webhook-hugo
+
+Now we are going to snag the second tool I have built for this process, [docker-webhook-hugo](https://github.com/SteffenBlake/docker-webhook-hugo)
+
+All this tool does is listen on port 9000 and, when triggered, pulls the repo that triggered it, assumes it has a hugo website on it and tries to build it, then outputs the hugo website to a specified folder.
+
+Take a moment on your github to note the branch name your repo has, it might be `master` or `main`, this is `<HUGO_BRANCH>` for the below command.
+
+You also will need to come up with some kind of Secret Password (henceforth called `<HUGO_SECRET>`)
+
+You can find it here
+
+![Github Branch](/images/part-2-building-a-blog/github-branch.png)
+
+### Windows
+
+```
+
+docker run -d -v C:/www:/www -p 9000:9000 -e HUGO_BRANCH=<HUGO_BRANCH> -e HUGO_SECRET=<HUGO_SECRET> --name build-server steffenblake/webhook-hugo
+
+```
+
+### Linux
+
+```
+
+docker run -d -v /www:/www -p 9000:9000 -e HUGO_BRANCH=<HUGO_BRANCH> -e HUGO_SECRET=<HUGO_SECRET> --name build-server steffenblake/webhook-hugo
+
+```
+
+### Example
+So if my branch is `master` and I want my secret to be `PaSsWoRd123` then I would execute something like:
+
+```
+
+
+docker run -d -v C:/www:/www -p 9000:9000 -e HUGO_BRANCH=master -e HUGO_SECRET=PaSsWoRd123 --name build-server steffenblake/webhook-hugo
+
+```
+
+We can test if its working by executing the following, with `<YOUR_REPO_URL>` being the https clone url for your websites git repo.
+
+```
+
+curl -L -X POST 'localhost:9000/hooks/build' \
+-H 'Content-Type: application/json' \
+-H "X-Gitlab-Token: <HUGO_SECRET>" \
+--insecure \
+-d "{
+    \"ref\" : \"<HUGO_BRANCH>\",
+    \"repository\": {
+        \"clone_url\": \"<YOUR_REPO_URL>\"
+    }
+}"
+
+```
+
+After executing that, wait a few seconds and then check out your `www` folder. If all went well your hugo files should all be statically served there!
+
+If you encounter issues you can run the following command to inspect what may have caused a problem:
+
+```
+
+docker logs build-server
+
+```
+
+# Step thirteen, Bind it!
+
+Now that it is running and our port forwarding is functional we can do the final step. We want to trigger the build server using Github automatically whenever we make a change, instead of having to do it manually.
+
+On your Github repo, navigate as such (which will prompt you for your password)
+
+![Github Branch](/images/part-2-building-a-blog/github-webhook-menu.png)
+
+On the subsequent page, enter the values like so, where Your.Public.Ip.Address is the address you got back in eleven
+
+![Github Branch](/images/part-2-building-a-blog/github-webhook-example.png)
+
+And then hit `Add webhook`
+
+# Test it!
+
+Now lets make a small change to see if it works.
+
+On your github repo modify something simple like a value in the `config.toml` in `MyBlog`, like perhaps your repositories author, or maybe a link. Something that is easy to verify "It changed"!
+
+You can check what it theoretically should look like by running the hugo server locally again as you did in Step Nine, to preview the change before you push it up live.
+
+Once satisfied, run the same command you did in step ten to commit and push
+
+```
+
+git add -A
+git commit -m "Testing webhook"
+git push
+
+```
+
+Wait a few seconds and then try out
+
+```
+
+docker logs build-server
+
+``` 
+
+To verify if the webhook got through.
+
+Then finally to actually see the changes, run the following command again to restart your static file server
+
+```
+
+docker restart my-site-0
+
+```
+
+And once again open up [http://localhost:8080](http://localhost:8080) and, if everything worked, your hugo site should be live here.
+
+Now all you need to do to update this hosted site is:
+
+1. Modify files to your hearts content in your repo
+
+2. Commit and push your changes
+
+3. Restart your site's docker image to reload the changes
+
+
+But we can do even better. The next guide will go over how, using Kubernetes, we can automate even step 3 and *truly* make it High Availability. To prep, please check out my guides as they go up on running kubernetes on bare metal!
+
+### {{< timelink n="3" after="2022-01-01" desc="Serve Hugo on Kubernetes" href="/post/hugo/part-3-building-a-blog">}}
+

+ 1 - 3
content/post/opinions/inheritance-vs-composition.md

@@ -2,7 +2,7 @@
 author = "Steffen Blake"
 title = "Inheritance vs Composition"
 date = "2021-08-20"
-description = "Which to use?"
+description = "'Composition over Inheritance'"
 tags = [
     "ButThatsJustMyOpinionMan",
     "Coding"
@@ -14,8 +14,6 @@ series = ["Thoughts"]
 aliases = ["inheritance-vs-composition"]
 +++
 
-#### "Composition over Inheritance"
-
 This is a phrase you will eventually hear at your workplace while coding away. Perhaps during lunch break or maybe in the comments of your code review. What exactly does this mean?
 
 Well, in Object Oriented Programming, there really are two ways to relate two types to each other. ‘Is a’ vs ‘Has a’ is often the colloquial.

+ 1 - 3
content/post/opinions/why-you-dont-need-a-bootcamp.md

@@ -2,7 +2,7 @@
 author = "Steffen Blake"
 title = "Why you don't need a Bootcamp"
 date = "2021-09-18"
-description = "I keep seeing people jump to recommending code bootcamps..."
+description = "A Boy and His IDE"
 tags = [
     "ButThatsJustMyOpinionMan",
     "StoryTime",
@@ -15,8 +15,6 @@ series = ["Thoughts"]
 aliases = ["async-events-IoT"]
 +++
 
-### A Boy and His IDE
-
 It’s the middle of 2006, I am a teen boy who just got my third paycheque from my summer job and lord knows my bank account is begging me to finally put my money to use. There are a plethora of options for a young man without any bills to pay, but I already knew what I wanted.
 
 I bought my first computer that weekend. In line at the shop I excitedly await the package, pumped to get home and finally strike out my own digital space on the machine. You see, up until this point I had been grounded in the world of the woeful shared ‘Family Computer’, an entity most of us 90s kids will fondly remember, most likely nestled in the corner of ones den or living room. Generally a simple machine, designed for browsing the internet and playing solitaire.

+ 19 - 0
layouts/_default/single.html

@@ -0,0 +1,19 @@
+{{ define "main" }}
+
+<div class="row">
+    <div class="col">
+
+        <h1 class="mb-3">{{ .Title }} - {{ .Date.Format "Mon, Jan 2, 2006" }}</h1>
+
+        <h4>{{ .Params.description }}</h4>
+        {{ .Content }}
+
+    </div>
+</div>
+<div class="row align-center">
+    <div class="col">
+        <a href="{{ .Site.BaseURL }}" class="btn btn-primary btn-lg">{{ i18n "backtohome" }}</a>
+    </div>
+</div>
+
+{{ end }}

+ 8 - 0
layouts/partials/head.html

@@ -7,6 +7,14 @@
     <meta name="theme-color" content="#000084" />
     <link rel="icon" href="{{ .Site.BaseURL }}/favicon.ico">
     <link rel="canonical" href="{{ .Site.BaseURL }}">
+
+    <link rel="stylesheet" href="{{ "/css/bootstrap.min.css" | relURL }}">
+    <link rel="stylesheet" href="{{ "/css/bootstrap-theme.min.css" | relURL }}">
+    <link rel="stylesheet" href="{{ "/css/style.css" | relURL }}"> 
+    {{ range .Site.Params.customCSS -}}
+      <link rel="stylesheet" href="{{ . | relURL }}?{{ slicestr (. | relURL | md5) 0 10 }}"> 
+    {{- end }}
+
     {{/* Don't ask why it's like this. This original theme is a mess... */}}
     <!-- <noscript><style>body { visibility: visible }</style></noscript> -->
     {{ range .AlternativeOutputFormats -}}

+ 0 - 6
layouts/partials/scripts.html

@@ -1,9 +1,3 @@
-<link rel="stylesheet" href="{{ "/css/bootstrap.min.css" | relURL }}">
-<link rel="stylesheet" href="{{ "/css/bootstrap-theme.min.css" | relURL }}">
-<link rel="stylesheet" href="{{ "/css/style.css" | relURL }}"> 
-{{ range .Site.Params.customCSS -}}
-  <link rel="stylesheet" href="{{ . | relURL }}?{{ slicestr (. | relURL | md5) 0 10 }}"> 
-{{- end }}
 <script src="{{ "/js/jquery.js" | relURL }}"></script>
 <script src="{{ "/js/bootstrap.min.js" | relURL }}"></script>
 <!-- <script src="{{ "/js/bootstrap-386.js" | relURL }}"></script>

+ 7 - 0
layouts/shortcodes/timelink.html

@@ -0,0 +1,7 @@
+<p>
+    {{ if (now.After (time (.Get "after")) ) }}
+        <a href="{{ .Get "href" }}">Part {{ .Get "n" }}{{ with .Get "desc"}} - {{.}} {{ end }}</a>
+    {{ else }}
+        Part {{ .Get "n" }}{{ with .Get "desc"}} - {{.}} {{ end }} (Coming soon!)
+    {{ end }}
+</p>

+ 8 - 9
static/css/custom.css

@@ -30,9 +30,16 @@ body *, .lead, .display-3 {
   font-size: 22px;
 }
 
-pre code {
+pre {
+  padding-left: 15px;
+  background-color: #272822;
+}
+
+pre > code {
   line-height: 18px;
   font-size: 20px;
+  color: #bbb;
+  width: 100%;
 }
 
 .bootstra-enable-cursor *, body.bootstra-enable-cursor {
@@ -43,14 +50,6 @@ pre code {
   cursor:pointer!important;
 }
 
-pre > code {
-  color: #bbb;
-  width: 100%;
-}
-pre {
-  background-color: #272822;
-}
-
 .card-body > a {
   white-space: nowrap;
   overflow:hidden;

BIN
static/images/part-2-building-a-blog/github-branch.png


BIN
static/images/part-2-building-a-blog/github-example.png


BIN
static/images/part-2-building-a-blog/github-webhook-example.png


BIN
static/images/part-2-building-a-blog/github-webhook-menu.png