Day 17 of the Anvil Advent Calendar

Build a web app every day until Christmas, with nothing but Python!

All I want for Christmas is to get this song out of my head

Ever had an obscure line from a song stuck in your head and you can’t place the title? Today’s advent app lets you enter some words from a song, and get a list of songs it’s in. There’s even a link to the full lyrics (courtesy of Musixmatch).

https://name-that-carol.anvil.app

Click here to clone the app, see the source code, and modify it however you like:

We’ll explain a bit about how it works - it’s a good example of how to create a human-friendly UI on top of an existing API. We’ll talk about how we configured the styling as well.

How it works

It’s a simple user interface on top of the Musixmatch API.

We get the song list using an HTTP request. The API key is stored in an Anvil Secret (when you clone the app, this API key will not be cloned with it, of course!)

import anvil.secrets
import anvil.server
import anvil.http
from urllib.parse import quote_plus

@anvil.server.callable
def get_tracks_by_lyrics(lyrics):
  res = anvil.http.request(
    'https://api.musixmatch.com/ws/1.1/track.search?'
    f'apikey={anvil.secrets.get_secret("musixmatch_api_key")}&'
    f'q_lyrics={quote_plus(lyrics)}',
    json=True
  )
  return [x['track'] for x in res['message']['body']['track_list']]

That’s the entire server-side code for this app.

On the client side, we get the list of songs and put the data into a Data Grid. The Data Grid is initially invisible, and we set it to visible = True when the results are ready:

  def lyrics_search(self, **event_args):
    tracks = anvil.server.call('get_tracks_by_lyrics', self.text_box_lyrics.text)
    
    self.card_2.visible = True
    self.repeating_panel_1.items = sorted(tracks, key=lambda t: -int(t['track_rating']))

If you’re wondering how the Data Grid knows how to display each song: look at the Data Bindings for the components inside the Data Grid. That’s where we set up the text property of the song and artist Labels, and the url property of the lyrics Link.

Styling it

To customise the look and feel, we imported two fonts from Google Fonts. When you want to import fonts into your app from a URL, put the link tags into Native Libraries:

We used the handwriting font (Indie Flower) for the logo, and the more legible sans-serif font (Muli) for the components the user interacts with.

The logo is a Custom Component built from an Image and a Label:

Since it’s a Custom Component it appears in the Toolbox and you can just drag-and-drop it onto any Form wherever you want it.

We uploaded the treble clef image to Assets, which allows us to use /_/theme/musical-note-keyboard.svg as the source of an Image component.

Uploading an asset.

Uploading an asset.

Displaying an image from Assets in an Image component.

Displaying an image from Assets in an Image component.

To change the background colour of the entire app, we modified the body in theme.css in the Assets:

body {
  /* ... */
  background-color: #ffebd1;
}

All the other colours come from the Colour Scheme - we just applied them in the Properties Panel to the components we wanted to be red or green.

Create your own front-ends to APIs

You can follow this pattern to create your own front-ends to APIs - clone the app to get a head start:


Give the Gift of Python

Share this post: