A few months ago I started working on gathering: A website for announcing group events which powered gathering.purescript.org.

This blog post is an experience report on building this project.

Motivation

There were two main reasons why I started working on gathering:

The first reason was that I saw a need for this kind of website for the PureScript community.

The PureScript community holds online gatherings every two weeks. Sometimes there are hacking sessions where people hack on different things, and sometimes there are presentations on different projects, concepts or features. The problem, at least for me, was that it wasn't easy keeping track which event is taking place, when is it, and if people know about it or are going to show up at all.

I was hoping that by building gathering I could help with that.

The second reason was that I wanted to to learn more about web development. This is not the field I work in at my day job and I wanted to learn more about it, so this was a good excuse for me.

Constraints

I had a few constraints coming to the project:

The first was time. Even though this is something I wanted to work on, I have a long list of other things I have to do and learn as well. And by working full-time I could only dedicate around an hour or two each day for working on gathering (though on the weekends I could dedicate a bit more).

I Also wanted this website to be done quickly so it could be used for PureScript online gatherings. So basically I just wanted to make something that works quickly and that will require as little effort as possible.

In total building gathering took about a month.

The second constraint was my knowledge on the subject of web development. I have built a few simple websites here and there but this was going to be bigger and more thorough than other stuff I've built. So I needed to take this into account while designing the project.

Choices

Due to that I had to make a few choices:

The main tech used is going to be the Haskell programming language, The Spock web framework, and just a tiny bit of JavaScript.

I'm going to write a high-level design that will describe which features to implement in order to get a minimum viable product, and will try to divide those into small chunks that I can complete in an hour or two and also see the result after finishing.

Why Haskell?

Haskell is the language I know best. It would be easier for me to work with Haskell than any other language to get this project done quickly.

Why Spock?

Spock seemed like a simple, no-magic, modern library I could use that is still featureful enough so it would provide me with what I need to accomplish my goal. It also looks a bit similar to scotty which I used a bit in the past.

Why no JavaScript?

Building static websites is easier for me than building SPAs and would require less learning.

Workflow

I found that planning beforehand what I'm going to build have made programming a lot easier. Of course some ideas changed in the process and new ideas were added, but the design doc did show the way to go and was very helpful.

However, at the beginning I didn't actually start by dividing the work to small chunks after designing what I'd like to build. I just started by creating a few data types that represents the data of the website, and then wrote a bunch of SQL statements to communicate with the database.

But it wasn't really fun. I've written a lot of lines of code but I didn't actually see any value from them. It was a bit of a motivational blow. So I decided to change strategy and create a list of small tasks I could finish in a session of about an hour or two that would show some progress.

Instead of trying to compile the list all at once, I edited it as I continued with the project. Sometimes refactoring tasks were added when needed as well.

This was probably the most important thing I did for this project. It made it easier to understand what I'm going to do tomorrow so I could think about it during the day and just get to work in the evening. It also made it more fun. I completed a task and i could see the fruits of my labor quickly and I could see how it advanced the project. And even though I couldn't always finish tasks in a short session, I usually could.

What went well

Let's talk a bit about what went well:

Package availability

In the Haskell ecosystem there were packages available for the stuff I wanted to do. Some examples include:

  • optparse-applicative: This is a pretty cool library that is used to build a cli arguments parser. I like it a lot!
  • configurator: This library can be used to parse configuration files. It was very simple to use.
  • smtp-mail: This library uses sendmail to send emails. sendmail was a bit tricky, but smtp-mail wasn't.
  • digestive-functors: This library makes it *really* simple to create and validate forms.

The Spock framework features

The Spock framework also had a few very nice features that made it easier for me to create this project:

Spock's typesafe routing and authentication

Spock makes it easy (and typesafe) to separate which pages are available to which users (guests vs. authenticated users for example). And lets me not worry about the data I get from parsing the url. You can see the code for the router here.

Forms and Validation

As I mentioned, digestive-functors let's us define forms and their validation in a high-level way which made it really easy to create new forms. You can see some example of forms here.

CSRF protection

Spock comes with csrf protection built-in that you can turn on, and it's fairly simple to embed csrf protection in your forms.

Another few things that worked well:

Quick to prototype

I talked about this a bit when I talked about the workflow I had and the time constriants. It was pretty important that I'll be able to complete tasks in a short time and see the benefits even if I had to hack my way some of the time. I felt it worked pretty well.

Easy refactoring

In order to keep the project maintainable and approachable, and to avoid writing the same code over and over again or copy/paste, When I found something could be written more easily or in a simpler matter, I usually just rewrote or changed it. This was also important because I wanted other people to be able to use gathering as an example when learning how to use Spock. This was always easy to do.

The end result was approachable for others (I think)

A few people contributed to the project so I'm guessing it was approachable enough?

What was harder

Nothing is all roses, and this project had a few bumps as well. A few of those are:

There is a lack of tutorials for Spock and no definitive guide on how to work with it. Instead I read the blog posts, examples, and API docs. Some of those were enough to get the idea of how to build what I wanted to build, And when that didn't work I asked on IRC or opened an issue and got feedback and explainations from Spock's creator. This worked for me, but might not work for everyone.

Another problem with this is that I also don't know if I completed my tasks well or just hacked around a big mess. A good tutorial would probably show the right approach and would make it easier to measure the quality of my work against what is shown in the tutorial.

I should probably note that this is probably easier if you are working with Yesod as it has both a book and a cookbook.

Another point is that I did have some trouble understanding some machinery I used, like hvect. Fortunately it did not stop me from actually using it.

Conclusion

I enjoyed working on this project and I feel I achieved my goals with it. gathering has been used by the PureScript community for a few months and I feel it is now fairly easy to get updates on new online community gatherings.

If you have any feedback or questions on the project or my post, feel free to contact me!