There is a lot of code here for finding out who's playing down the road. Band pages and venues sit beside gigs and songs, with a Spring Boot backend and a Vue frontend to keep them all going. I've used the site to learn Java, Spring Boot and ECMAScript 6, so its size probably shouldn't surprise me. Still it is a free music guide and people use it. I'd like the code to be useful to somebody else too.
Maybe you could deploy it for your own local community?
I'm publishing it under the AGPL licence with documentation for both the Java and JavaScript. There are plenty of directories to poke around in.
Pick a job. Open a band page or try the search or edit a venue. Then we can follow the code behind it. Otherwise I could spend this whole article listing where I put things.
Open a band page and Vue fills the page shell with information from the API. From there choosing a venue changes the view and browser address without rebuilding the whole page, and a copied link still has to open the right record directly. The player lives outside those changing views. I'm making a music site, so being able to browse without cutting off the song seems a fairly important place to start.
A shared band link needs a preview. The tool fetching it may not run JavaScript, so an empty shell where the band should be won't do. It needs filled-in HTML. The nginx configuration recognises crawlers and can send them to Prerender, which loads the page in a headless browser and returns the resulting HTML.
Assets and requests from Prerender itself go the normal way. Otherwise it ends up asking itself to render its own rendering request, and that's a very long afternoon.
Behind the page I use three stores with different jobs:
| Store | What the site asks it for |
|---|---|
| MariaDB | The application records and their relationships |
| Redis | Prepared lists, including upcoming gigs and the hot list |
| Lucene | Indexed text for searching |
Yes, three stores. I've got venue records to save, gig lists to prepare and band names to search through, and I've given each a home (apparently a database wasn't enough for my local music guide).
The upcoming list in Redis turns repeating-event rules into dates somebody can actually attend. The hot list orders media using counts and age from the source platforms. Keeping those lists ready saves working them out while somebody waits for the homepage. The gig scanner supplies event records after approval.
Finding the name you nearly remember
You might be searching for a band's name because you don't quite remember it. Requiring the exact spelling is a lot to ask.
The search handles artists, media and venues. An analyser turns text into tokens, pieces it can compare, and it does this for both stored text and the visitor's query. Clever filtering on the index alone would leave the visitor typing something the stored words no longer resemble. The chain strips HTML, maps accented characters, splits the text into words and lowercases them, so JERSEY can meet Jersey before the more specialised filters get their chance to deal with misspellings.
An English stemmer reduces related word forms, a synonym file supplies local substitutions and further accent folding simplifies letters. Then Double Metaphone adds codes for how words sound, giving a misspelt name another chance to meet the right band.
I could spend ages trying more filters. More spellings to try, cleverer matches, another filter.... Before adding anything, let's see what this lot produces.
The stop-word filter removes common words. It runs after the sound-alike stage and has to recognise whatever tokens it gets by then.
Stemming the electric penguins gives the tokens the, electr and penguin. The sound-alike stage adds 0, ALKT and PNKN, keeping the word tokens alongside them.
All six tokens survive the stop-word stage. The list has entries such as the= and the token is the. They don't match. The word stays in despite being on the list under another spelling.
That list needs a look.
I still have to supply the local vocabulary. A sound-alike filter doesn't know where a parish is.
A synonym replaces whatever the earlier filters have left of the word I typed. I want jsy to become jersey. With the full chain it doesn't. The stemmer changes it to jsi before the synonym stage can read it. That's the wrong word. I've got the shortcut in the file, but it never sees the text I wrote it for, so there's another thing to sort out in the filter order.
Editing without another handmade form
Each new record type brings fields to display, edit and validate in the admin. Another handmade form means describing much of the same information twice. The Java model already has the field's type, name and annotations about how the admin should treat it. A schema reader collects those details into a description for the frontend.
Vue then chooses a field component for each entry. A text field and a relationship to another record need different controls, but they can belong to the same generated form.
Here is a simplified example of the conversation:
Model field Schema information Form control
venue.name editable text text input
event.location linked venue venue picker
record.id locked identifier read-only value
The venue picker still needs designing. Once it knows how to select a venue, the next form can use it too. Writing another handmade form would send me back through decisions I've already made, which is a fairly dull way to spend time on a music site.
I'm pleased with how much this saves me writing. What does a locked field actually lock, though? It tells the browser to show a read-only control. Somebody sending an HTTP request can skip that control entirely. The server still has to enforce permission rules, however convincingly grey the box looks.
Anyway, let's get a copy running.
The live server and public repository of Sound.je “may not be completely in sync”. I've published the source as a mirror of the working copy, so the open-source version might lag with development.
Getting it running also means setting up Java, MariaDB, Redis and Lucene. That's quite a shopping list before you've seen a band page.
The Vagrant box should make that first encounter less of a scavenger hunt by creating a virtual machine for the site, with Puppet describing the packages and setup work inside it.
The local copy comes with entirely fictional bands playing at entirely fictional pubs. Pick one and follow it through the site.
Let me know if you try this yourself, I will be most interested in hearing from you.