Building a Moderately Functional Web App
This weekend, I built a moderately functional web app. I’ve done this before, of course — I used to work in web development back in The Before Times — but this is only the second app I’ve built in 5-6 years, and it included some new things I haven’t done before! So, in no particular order, here are some things I learned. (Many of these things may have been true for a decade or more; that doesn’t mean that I didn’t just learn them!)
- If you intend to do anything with media queries, it seems that the common knowledge is that you *must* include a specific viewport meta tag:
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
. Without this, things work fine on desktop browsers, but fail on mobile browsers. This does not make sense to me, but there it is. (Thankfully, they at least also fail in Chrome’s mobile device inspector mode, so it’s actually possible to debug.) - mod_wsgi has a python-home directive that allows you to specify the virtualenv that you would like to use to run your particular application. This is useful if you are using virtualenv to package up your dependencies; it means that you don’t have to mess about with weird path includes in order to get your virtualenv working in your Apache webserver.
- localStorage seems to work by default across major browsers at this point. This means that I was able to store information locally without any magical … anything. For minimizing server-side storage entirely, this seems cool and good to know. localStorage is available in the default Javascript scope, and has two functions:
getItem('key')
andsetItem('key', 'value')
. - If you have a div with contenteditable set, by default it appears to have a height in Safari and Chrome, but not in Firefox; so make sure you set a min-height on the element in Firefox.
- CSS flexbox support has been available in every major browser for years. This means that you can actually horizontally and vertically position elements without using tables. This is amazing to me. (In fact, out of desparation, I briefly attempted to use a <table>, only to find it screwed up my layout more — and that CSS flexbox was *easier* than using a table for what I wanted.) This is pretty amazing to me.
- If you are using a contenteditable field, then the following will ensure that when you paste into the field, it is pasted using plain text. (This is necessary in Safari; not in Chrome, not sure about other browsers.) I haven’t thoroughly tested how cross-platform this snippet is.
document.getElementById('input').addEventListener("paste", function(e) {
// cancel paste
e.preventDefault();// get text representation of clipboard
var text = (event.originalEvent || event).clipboardData.getData('text/plain');// insert text manually
document.execCommand("insertHTML", false, text);
}); - pusher.com is a quick way to get support for a moderate size of websocket connections (100 active connections; 200,000 daily messages) supported by a wide variety of push + receive client libraries, with almost no work. It honestly feels a little bit like magic; as someone who had been putting things off specifically because of the pain that is *either* polling or running a websocket service, this was really quite nice to see. Also supports posting out received messages via webhooks for clients that might want that instead of websockets. I expect that if I ever reach that level of scale, I’ll probably just set up my own websocket server rather than pay the $50/month for the next tier, but for a getting started, this was really useful. I started with this guide on building a chat app in Javascript and found that it was easy to get started with and to modify, since it only has around 30-50 lines of code.
- I probably need to bite the bullet and start moving towards Python3, even though I don’t really care about it. This is annoying as my gap of 3-5 years since I built new apps has left my server environments atrophied and weak.
- People really prefer a “dark” theme to a light theme in the social spaces that I run in. (I’m surprised that Facebook doesn’t have a dark mode yet.)
- Modern browsers continue to change constraints — on things like autoplaying videos, third-party cookie restrictions — in ways that are likely good for privacy and user experience, but break older apps without much way to fix it and with user control over those changes minimized. Old apps that worked fine are now non-functional because of these restrictions.
- If you try to copy a virtualenv from a different machine, you get *weird* behaviors. Also, if you’re creating a virtualenv, the first thing you want to do is probably upgrade pip. (Turns out that when the pip you’re using doesn’t support modern dependency descriptors, you also get really weird failure modes!)
- I really miss the handiness of Google’s auto-formatting facilities when writing code. Everything I’ve written this weekend is indented poorly, and it’s frustrating.
Anyway, starting around midnight on Sunday until early Monday morning, I built myself an app; it includes synchronized viewing of YouTube playlists, plus a completely built-from-scratch chat app that is moderately functional and improves in a lot of ways over YouTube chat for the use case I have. I built media queries that let the UI actually work on a mobile device, and it actually looks halfway decent. I didn’t have to use much in the way of browser-specific hacks (modulo comment on min-height in Firefox).
That’s a pretty cool experience.