Summary: A modern dev stack for modern web apps. See how I built a new web app using RavenDB, Angular, Bootstrap and TypeScript. Why these tools are an excellent choice for modern web dev.
Twin Cities Code Camp (TCCC) is the biggest developer event in Minnesota. I’ve written about it before: it’s a free event where 500 developers descend on the University of Minnesota to attend talks on software dev, learn new stuff, have fun, and become better at the software craft.
I help run the event and this April, we are hosting our 20th event. 20 events in 10 years. Yes, we’ve been putting on Code Camps for a decade! That’s practically an eternity in internet years.
For the 20th event, we thought it was time to renovate the website. Our old website had been around since about 2006 – a decade old – and the old site was showing its age:
It got the job done, but admittedly it’s not a modern site. Rather plain Jane; it didn’t reflect the awesome event that Code Camp is. We wanted something fresh and new for our 20th event.
On the dev side, everything on the old site was hard-coded – no database – meaning every time we wanted to host a new event, add speakers or talks or bios, we had to write code and add new HTML pages. We wanted something modern, where events and talks and speakers and bios are all stored in a database that drives the whole site.
Taking at stab at rewriting the TCCC websiite, I wanted to really make it a web app. That is, I want it database-driven, I want some dynamic client-side functionality; things like letting speakers upload their slides, letting attendees vote on talks, having admins login to add new talks, etc. This requires something more than a set of static web pages.
Additionally, most of the people attending Code Camp will be looking at this site on their phone or tablet. I want to build a site that looks great on mobile.
To build amazing web apps, I turn to my favorite web dev stack:
I find these tools super helpful and awesome and I’m pretty darn productive with them. I’ve used this exact stack to build all kinds of apps, both professional and personal:
And a bunch of internal apps at my current employer, 3M, use this same stack internally. I find this stack lets me get stuff done quickly without much ceremony and I want to tell you why this stack works so well for me in this post.
I’m at the point in my career that I don’t put up with friction. If there is friction in my workflow, it slows me down and I don’t get stuff done.
RavenDB is a friction remover.
My old workflow, when I was a young and naïve developer, went like this:
- Hmm, I think I need a database.
- Well, I’d guess I’d better create some tables.
- I should probably create columns with the right types for all these tables.
- Now I need to save my C# objects to the database. I guess I’ll use an object-relational mapper, like LINQ-to-SQL. Or maybe NHibernate. Or maybe Entity Framework.
- Now I’ve created mappings for my C# objects to my database. Of course, I have to massage those transitions; you can’t really do inheritance or polymorphism in SQL. Heck, my object contains a List<string>, and even something that simple doesn’t map well to SQL. (Do I make those list of strings its own table with foreign key? Or combine them into a comma-separated single column, and rehydrate them on query? Or…ugh.)
- Hmm, why is db.Events.Where(…) taking forever? Oh, yeah, I didn’t add any indexes. Crap, it’s doing a full table scan. What’s the syntax for that again?
This went on and on. It wasn’t until I tried RavenDB did I see that all this friction is not needed.
SQL databases were built for a different era in which disk space was at a premium; hence normalization and varchar and manual indexes. This comes at a cost: big joins, manual denormalization for speed. Often times on big projects, we have DBAs building giant stored procedures with all kinds of temp tables and weird optimization hacks to make shit fast.
Forget all that.
With Raven, you just store your stuff. Here’s how I store a C# object that contains a list of strings:
Notice I didn’t have to create tables. Notice I didn’t have to create foreign key relationships. Notice I didn’t have to create columns with types in tables. Notice I didn’t have to tell it how to map codeCampTalk.Tags – a list of strings – to the database.
Raven just stores it.
And when we’re ready to query, it looks like this:
db.Query<Talk>().Where(t => t.Author == "Jon Skeet");
Notice I didn’t have to do any joins; unlike SQL, Raven supports encapsulation. Whether that’s a list of strings, a single object inside another object, or a full list of objects. Honey Badger Raven don’t care.
And notice I didn’t have to create any indexes. Raven is smart about this: it creates an index for every query automatically. Then it uses machine learning – a kind of AI for your database – to optimize the ones you use the most. If I’m querying for Talks by .Author, Raven keeps that index hot for me. But if I query for Talks by .Bio infrequently, Raven will devote server resources – RAM and CPU and disk – to more important things.
It’s self optimizing. And it’s friggin’ amazing.
The end result is your app remains fast, because Raven is responding to how it’s being used and optimizing for that.
And I didn’t have to do anything make that happen. I just used it.
Zero friction. I love RavenDB.
If you’re doing .NET, there really is no reason you shouldn’t be using it. Having built about 10 apps in the last 2 years, both professional and side projects, I have not found a case where Raven is a bad fit. I’ve stopped defaulting to crappy defaults. I’ve stopped defaulting to SQL and Entity Framework. It’s not 1970 anymore. Welcome to modern, flexible, fast databases that work with you, reduce friction, work with object oriented languages and optimize for today’s read-heavy web apps.
In the bad ol’ days, we’d write front-end code like this:
Then, we discovered JQuery, which was awesome. We realized that the browser was fully programmable and JQuery made it a joy to program it. So instead of doing postbacks and having static pages, we could just update the DOM, and the user would see the new email address:
And that was good for users, because the page just instantly updated. Like apps do. No postback and full page refresh; they click the button and instantly see the results.
This was well and good. Until our code was pretty ugly. I mean, look at it. DOM manipulation isn’t fun and it’s error prone. Did I mention it was ugly?
What if we could do something like this:
No ugly DOM manipulation, we just change variables and the browser UI updates instantly.
This is data-binding, and when we discovered it in the browser, all kinds of frameworks popped up that let you do this data-binding. KnockoutJS, Ember, Backbone, and more.
This was all well and good until we realized that while data-binding is great, it kind of sucks that we still have full page reloads when moving from page to page. The whole app context is gone when the page reloads.
Enter AngularJS. Angular makes it a breeze to build web apps with:
- Client-side navigation. This means as the app moves between pages, say between the Schedule and Talks pages, your app hasn’t been blown away. You still have all the variables and state and everything still there.
- Data-binding. You put your variables in a class called a controller:
…and then in your HTML, you data-bind to those variables:
Then, any time you change the variables, the DOM – that is, the web browser UI, automatically updates. Fantastic.
Angular also add structure. You load data using service classes. Those services classes are automatically injected into your controllers. Your controllers tell the service classes to fetch data. When the data returns, you set the variable in your controller, and the UI automatically updates to show the data:
Nice clean separation of concerns. Makes building dynamic apps – apps where the data changes at runtime and the UI automatically shows the new data – a breeze.
We can instead write concise and clean, intellisense-enabled TypeScript like this:
Ahhh…lambdas, classes, properties. Beautiful. All with intellisense, refactoring, error detection. I love TypeScript.
You don’t need to drink $15 Frappamochachino Grandes to design elegant UIs.
We’ve got code at our disposal that gives us a nice set of defaults, using well-known UI concepts and components to build great interfaces on the web.
Bootstrap, with almost no effort, makes plain old HTML into something more beautiful.
A plain old HTML table:
Add a Bootstrap class to the <table> and it’s suddenly looking respectable:
A plain HTML button:
Add one of a few button classes and things start looking quite good:
Bootstrap gives you a default theme, but you can tweak the existing theme or use some pre-built themes, like those at Bootswatch. For TwinCitiesCodeCamp.com, I used the free Superhero theme and then tweaked it to my liking.
Bootstrap also gives you components, pieces of combined UI to build common UI patterns. For example, here is a Bootstrap split-button with drop-down, a common UI pattern:
Bootstrap enables these components using plain HTML with some additional CSS classes. Super easy to use.
Bootstrap also makes it easy to build responsive websites: sites that look good on small phones, medium tablets, and large desktops.
Add a few classes to your HTML, and now your web app looks great on any device. For TwinCitiesCodeCamp, we wanted to make sure the app looks great on phones and tablets, as many of our attendees will be using their mobile devices at the event.
Here’s TwinCitiesCodeCamp.com on multiple devices:
iPad and medium tablets:
And on iPhone 6 and small phones:
This is all accomplished by adding a few extra CSS classes to my HTML. The classes are Bootstrap responsive classes that adjust the layout of your elements based on available screen real-estate.
RavenDB, AngularJS, TypeScript, Bootstrap,. It’s a beautiful stack for building modern web apps.
TwinCitiesCodeCamp code is on GitHub.