BRYAN TRAVIS HOOPER
February 5, 2023

Hosting a Static Site on AWS

Recently, I decided to move this blog, which is a very poorly maintained blog, I admit, to AWS. I wanted to do this more or less as a learning excersize and also because I figured AWS would be an inexpensive option.

I have been a happy customer of serices like Linode, Heroku and Digital Ocean for years. These companies provide a great solutino for web apps and web sites, and they have been improving and expanding their offerings lately. Generally speaking you can reserve a virtual instance with your flavor of linux and attach some storage and a database and get a basic project up and running. For projects like that - with a modern, but basic stack - these tools are perfect. I love how easy it is to fire up a Linode node and get to work.

But, for a simple static site, they seem like a bit of overkill. If you are just serving HTML, CSS and JS, Amazon Web Services seems like a better option. AWS has tons of different services, so if your project expands to include more needs, AWS allows you to take advantage of the vast resources AWS has to offer. Decide later you want to add DB functionality? What to add some basic API endpoints? What to run some maintenence workers? AWS has you covered. If you are sure you only want a static site, perhaps GitHub Pages is a better option since it is totally free. But AWS also allows you to integrate with your GitHub repo and update your static site with a simple push command.

But...and this is a big but...AWS doens't go out of it's way to make life easy. If anything, AWS is overwhelming with options. For any given problem there are multiple different paths to a solution. And AWS can be confusing becuase of it's sheer scale. There are loads of tutorials out there on setting up a static stie on AWS. And yet, AWS can still mess with your head.

Is it worth it?

I think so. I reduced my hosting costs from around $10/month to less than $1/month. The initial configuration and set up was a bit of work, but once things were all wired up, I could push up to my GitHub repo and AWS does the rest. It works. And it saves me a lot of money.

DHH and the 37 Signals team have been moving away from AWS, and DHH has recently talked about the reasons why. I think he makes some good points, and organizations in similar situations would do well to ponder the lessons they've learned. At the same time, no one should shy away from AWS. It remains an amazing service with a low cost to entry. The biggest barrier to AWS is the learning curve.

January 18, 2022

What a Former Clergyperson Brings to Your Team

Since I began looking for a new full-time job, I have noticed two major challenges I face as a candidate. One is simply my age. As a "second-career" person, it is sometimes difficult to be considered for junior positions. I have some thoughts on that, but I'll save them for another post. The second major challenge, which I will focus on here, is overcoming a number of assumptions around my "first career."

Religion is a hot button topic in almost any context. But, as mainline denominations continue to decline and traditional expressions of religion become more marginal, I have noticed that many people know very little about religious people or regard them with suspicion. I think this is understandable. Perhaps another blog post could be "10 Myths About Me as a Former Religious Leader." I would like to suggest, however, that clergy develop a number of key skills that are of great value to any development team. I suspect that many people are unaware of what the role of 'pastor' actually entails. So, here are a few things to consider.

  • Clergy are self-starters. Generally speaking, clergy have to supervise themselves. I always had to set my own agenda, organize my meetings, reach out to people for engagement, and then follow up to ensure things got done. I even had to train committees on how best to evaluate me and review my performance. In most of the churches I served, I had to initiate or facilitate almost everything that happened in the church life.
  • Clergy know how to overcome adversity. I have lived in parsonages (housing for clergy) that lacked electricity. I have called 911 to protect my home and church building multiple times. I have escorted troubled, disturbed, potentially violent people out of the church. I have worked with highly restrictive budgets in order to get something done. I have managed small, overworked, underpaid staff. Difficult circumstances are the norm for clergy.
  • Clergy are problem solvers. Running a church is like putting a 500-piece puzzle together with 250 pieces. You have to figure stuff out. I served a church that lost its boiler in the middle of a freezing cold winter. We had a very small budget. You have to figure it out. I served a church that needed a new way to connect with the neighborhood and the wider community. You just have to figure something out. Solutions have to be found. And you are the person to find them. The fact is that the "buck stops" with the pastor in most churches.
  • Clergy are good communicators. Sure we have to preach and speak often in public settings. But we also have to organize people into leadership teams and committees. We draft newsletters and blog posts. We plan and lead educational programming for all ages. Most of all, perhaps, we have to motivate people to be engaged and to live their lives faithfully.
  • Clergy know how to deal with people. Churches are people. And that means there are all kinds of people. Some are easy to work with. Some are not. Clergy work with them all. Navigating personalities, investing in difficult relationships, reaching out to people in need, listening, counseling, advising - all of this and more is part of the daily life for clergy.
  • Clergy are life-long learners. Most clergy I know are in therapy with a professional counselor - not because of any particular diagnosis - but because they want to invest in a deeper understanding of themselves. Most clergy I know have a huge bookshelf full of books and attend conferences and are part of support groups. Clergy are committed to learning more and more about themselves and their craft.
  • Clergy have high emotional intelligence. Clergy know how to listen closely to people and really integrate their ideas. Clergy also know how to address the concerns of others to meaningfully impact them. Clergy are trained to be responsive to the needs of the people they serve, and to always be authentic in their encounters with others. Clergy bring their "whole selves" to their work.

I understand why hiring managers are a little reluctant to consider former clergy people for their positions. But if they could take a more objective look at former clergy from mainstream churches, they might see a wealth of opportunity in their hiring practices.

May 23, 2021

I Hit the Road

With COVID restrictions loosening up, for better or worse, and with my vaccination well established, I decided it was time to venture out of the quiet spaces of Vermont where I have been for over a year now. So I set up some lunches with family and friends and headed down to Connecticut. Not a huge trip - but a good chance to test my traveling abilities before some longer road trips this summer.

As I left Vermont, I realized that it has been a long time since:

  • I saw a billboard sign. I haven't seen a billboard sign in over a year.
  • I saw a Tesla charging station....in Meriden, CT! The electric revolution is coming.
  • I drove in traffic. I was even cut off!
  • I talked to strangers. This seemed to be a universal issue, as everyone I encountered seemed quite chatty.

It was great to see friends and spend time with people I haven't been able to spend time with. It was nice to see a different part of the earth. And it was nice to drive old familiar streets in Hartford.

May 10, 2021

Overstatement is Now Built with Zola

Every year or so I revisit this blog and think of a new way to do it. Mainly I view this as a learning exercise, so I try to find something new and interesting that I would like to try.

Recently I have been interested in static site generators. The previous version of Overstatement was build with Jekyll, a Ruby-based static site generator that is very popular. Since I know a little Ruby, it made sense to me to use Jekyll. Jekyll is robust, with a large community behind it. If you need help, it's easy to find. If you are looking to implement a feature, someone else has probably already implemented it.

There are two downsides to Jekyll in my view. One is that it is slow. Compared to other options, Jekyll generated even my little web site noticeably slower. Since you only generate the site when you have to update it, this isn't a really big deal for me, but for more active sites this could be a deal breaker.

The second downside, and this is an issue with a lot of software these days, is Jekyll's dependencies. A static site is by nature a secure site, generally speaking. But Jekyll has had a few security concerns with some of its dependencies in the past. Of course, things were patched and updated. But if I have a choice between a lot of dependencies or not many dependencies, I say the fewer the better.

So for this new version of Overstatement, I went with Zola. Zola is a fairly new option, and instead of Ruby it is built with Rust. I was interested in Rust because it is a lower level programming language, which means it is fast. Rust generates my current site in 85 milliseconds. That's almost instantaneous. Rust is also open source and is being developed in a transparent manner. I think it is one of the more interesting programming language projects going on right now, for what little I know.

Oh, and Zola has no dependencies at all. Zero. It's just Zola. That keeps it fast and simple.

Zola's biggest downside is that because it is newer, and a little niche, it has a smaller community. It was harder to find help online, and the documentation, while good, is incomplete. I figured everything out for the most part, but it would have been helpful for me to know a little Rust. Another thing to learn!

Zola is also pretty simple. It does not have the robust feature set that Jekyll has. My site is simple, so Zola being simple is perfect. But I imagine a more complex site would be challenging to implement in Zola. I hope Zola continues to grow and gain more support and features, while remaining fast and reliable.

One feature I really liked was "shortcodes", a concept the Zola team stole from WordPress. These little micro-templates make it super easy to reuse code and pass parameters around as needed. I used shortcodes for my vimeo embeds and to generate a gallery. I also like the way Zola encourages you to store assets and blog content together. At first this was counter-intuitive to me, but it made more sense as I used it. Images and documents are stored in a folder with blog content making it super easy to include them in the blog post and also keeping everything logically together.

One other change I made with this version of Overstatement is I converted all the CSS to Tailwind. I have used Tailwind on a few projects now and I'm starting to really like it. It's biggest advantage to me is how easy it is to change and update. You can design almost anything with it, and you can customize things as you need to. So, it feels like it can be the super-framework for a good long time. I can completely change the look of Overstatement without changing my framework at all.

All in all this was a fun project. I love learning new things. I look forward to seeing how/if Zola evolves. Hopefully, this version of Overstatement can serve the Overstatement community for a few years. Or until I want to learn something else.

April 7, 2021

Coming to Terms with React Router

When I first learned about modern approaches to routing user requests to the appropriate resources I was learning Ruby on Rails and working under a RESTful paradigm. Next, I learned a bit about NodeJS and Express, which seemed to me to work in a very similar fashion. When I started learning React Router it seemed very different from those two, and I finally concluded that that's because it is!

First of all, let me explain what I think the purpose of a router is in a web application. A router is the collection of tools that interprets a request from a user, usually by parsing a URL, and directs the server to the controller or method that is designated to respond to that request. Usually, this results in a server response to the user that provides the requested resource. In a RESTful app, this would look something like this:

  • User requests http://xyzcompany.com/products in their browser.
  • Router has a GET route for /products that instructs the server to execute the #index method in the Products controller.
  • The Products controller retrieves all the products from the database, formats the data in the desired format (usually HTML or JSON) and returns the formatted data to the user. (More formally, the controller sends the data over to a view which handles the rendering, but nevertheless.)

But with React Router, there is no back end server at all, so everything is handled in the user's browser. Since it always seemed to me that the key feature of a router was the routing part, I found this a bit confusing. I found it useful for myself to think of React Router as more of a filter for components, that does its filtering based on the URL. React Router does more than this, but in terms of how it simulates a traditional Router, this is a key point. New components are shown based on a pattern matching algorithm that matches URLs and updates the browser's history to simulate page refreshes and different resources loading.

An artificial example will illustrate this point.

See the Pen React Router Example by Bryan Hooper (@bthooper) on CodePen.

If you examine this code, you will notice a list of links working more or less as a navigation menu. The links are created using React Router's <Link> component, which creates the <a> tag for the link. Each link points to a simple URL. Then, down in the App component, the <Route> components, also from React Router, direct traffic to render content depending on which route you are requesting. It seems simple enough, but React Router does some funny things with matching the URL and the paths. First of all, if you head over to codepen where you can play with this code, you will notice that every route you choose always renders the "/" route - namely the word "Home".

You might conclude that React Router is just matching whatever meets the minimum requirement to match the route. If it starts with "/", as all routes do, than the Home route will always match. You can see this behavior again when you click on More About. Here, the URL is "/about/more" and that matches "/" and "/about" as well as "/about/more."

But when you click on More Yet, things get a little fuzzy. The URL is "/about/moreyet" but only "/", "/about" and "about/moreyet" are matched. What wasn't "/about/more" matched? My guess is that React Router doesn't look at the URL as a string, but rather as a collection of strings separated by "/". So each string is comparaed aginst the other string within that segment enclosed by "/"s. The other somewhat unexpected behavior is demonstrated when you click on Blog. Two routes are pointing to "/blog" and so, when you click on that link you get both routes back! I guess it isn't that surprising, but one can see how it might produce unexpected results.

React Router provides a Switch component that can address some of these issues. Switch works by finding the first match and then only rendering the first match. However, it too can produce some surprising results if you aren't careful. Simply adding the Switch component around our routes will resutl in ONLY the home route displaying, since it is always matched. The "exact" keyword can be used to only match a URL exactly to overcome this problem.

In my mind it was helpful to think of React Router less as a routing tool that loads assets when requested by a user and more as a conditional rendering tool, that renders components based on matching the URL. Instead of a "router" I thought of it more as a conditional render tool. Routes are more like conditions or "if/then" checks that decided when to disply a component based on a given URL. Once I started thinking of React Router this way, it's behavior made much more sense to me and I was able to build more reliable React Router routes.

React Router is a powerful piece of software that does more than just "direct traffic." It also manipulates the browser history to maintain the appearance of a true router and preserve your URLs just like a real URL even though it is all rendered in the browser. I have only started scratching the surface of React Router, and I am eager to engage with it some more.