Introduction: The Role of the Backend in a Music Player

Welcome to the first lesson of the course! In this lesson, you will learn how to set up the backend for a music player application and load music track data. The backend is the part of the app that manages and serves data, such as the list of available songs. It acts as the "brain" behind the scenes, making sure the right information is sent to the user when needed.

By the end of this lesson, you will know how to:

  • Store music track data in a file
  • Load that data into your application
  • Set up a simple API endpoint to share this data with other parts of your app

This course is the first step in building your smart music player, but here we’re focused on the essentials — the backend infrastructure that makes everything else possible. You won’t see any smart recommendations just yet. Instead, you'll learn how to:

  • Structure and serve music metadata
  • Track what users listen to
  • Build a clean and functional API layer

Think of this course as laying the foundation — the “plumbing” of your system. Once the backend is solid, future courses in this path will introduce smart enhancements, such as track embeddings, similarity search, and predictive preference models.

This foundation is important because every music player needs a way to organize and deliver track information. Let’s get started!

Setting Up Your Environment (For Local Development)

If you're following along on your own machine, you'll need to set up a few things to run this project locally. The examples in this course use the following Python libraries:

  • Flask: for building the web server and API routes
  • pandas: for loading and manipulating the music track data
  • os: part of the Python standard library for file path management

To set up your environment, run the following commands in your terminal:

pip install --quiet --upgrade pip
pip install --quiet flask
pip install --quiet pandas
pip install --quiet requests

These commands ensure you have the necessary tools without displaying extra output.

Note: In the CodeSignal environment, there's no need to install anything — all required libraries are already pre-installed and ready to go.

With your environment set up, you’re ready to dive into the backend structure!

Quick Recap: Project Structure and Initial Setup

Before we dive in, let’s quickly look at the main files and folders you will use in this lesson. This will help you understand where everything fits.

Here is a simple example of the project structure and basic setup:

# app.py
from flask import Flask

app = Flask(__name__)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5001, debug=True)
  • app.py: This is the main file where your Flask app is created.
  • static/tracks.json: This file will store your music track data.
  • src/database.py: This file will handle loading and managing the track data.

You do not need to set up these files from scratch on CodeSignal, but it is good to know where things are located for when you work on your own device.

Storing Track Data in JSON

Music track data is stored in a file called tracks.json using the JSON format. JSON (JavaScript Object Notation) is a simple way to store data that looks like a list of dictionaries. Each dictionary represents a track with details like title, artist, genre, and more.

Here is an example of what tracks.json looks like:

[
  {
    "id": "track001",
    "title": "Sunrise Melody",
    "artist": "Synth Weaver",
    "album": "Digital Dreams",
    "genre": "Electronic",
    "mood": "Uplifting",
    "tempo": 120,
    "energy": 0.8
  },
  {
    "id": "track002",
    "title": "Midnight Cruise",
    "artist": "Groove Rider",
    "album": "City Lights",
    "genre": "Funk",
    "mood": "Chill",
    "tempo": 90,
    "energy": 0.6
  }
]

Why use JSON?

  • It is easy to read and write for both humans and computers.
  • It works well with many programming languages, including Python.
  • It is a common choice for storing and sharing data in web applications.
Loading Track Data with Pandas

To use the track data in your app, you need to load it from the JSON file. In this project, we use the Pandas library to read the data into a DataFrame, which is like a table in memory.

Here is the code from src/database.py that loads the data:

import pandas as pd
import os

# File paths relative to the project root
TRACKS_FILE_PATH = os.path.join(os.path.dirname(__file__), '..', 'static', 'tracks.json')

# Cache tracks data in memory after first load
_tracks_cache = None

def load_tracks_data():
    """
    Loads track data from JSON file into a Pandas DataFrame.
    Uses caching to avoid repeated file reads.
    """
    global _tracks_cache
    
    if _tracks_cache is not None:
        return _tracks_cache
    
    if not os.path.exists(TRACKS_FILE_PATH):
        print(f"Tracks file not found at {TRACKS_FILE_PATH}")
        _tracks_cache = pd.DataFrame()
        return _tracks_cache
    
    try:
        _tracks_cache = pd.read_json(TRACKS_FILE_PATH)
        # Ensure ID column is string type for consistent lookups
        if 'id' in _tracks_cache.columns:
            _tracks_cache['id'] = _tracks_cache['id'].astype(str)
        print(f"Loaded {len(_tracks_cache)} tracks from database")
        return _tracks_cache
    except Exception as e:
        print(f"Error loading tracks: {e}")
        _tracks_cache = pd.DataFrame()
        return _tracks_cache

def get_all_tracks():
    """Returns all tracks as a DataFrame."""
    return load_tracks_data()

Explanation:

  • The load_tracks_data function reads the tracks.json file and loads it into a Pandas DataFrame.
  • It uses a cache (_tracks_cache) so the file is only read once, which makes the app faster.
  • If the file is missing or there is an error, it returns an empty DataFrame.
  • The get_all_tracks function simply calls load_tracks_data and returns the DataFrame.

Note: The usage of (_tracks_cache) is done via technique called in-memory caching. It prevents repeated disk I/O by storing the parsed data in a variable for reuse. Since the track data doesn’t change often in this project, caching improves performance without much downside. If you update the tracks.json file, restarting the app will refresh the cache.

Example Output: If you call get_all_tracks(), you will get a DataFrame like this:

idtitleartistalbumgenremoodtempoenergy
track001Sunrise MelodySynth WeaverDigital DreamsElectronicUplifting1200.8
track002Midnight CruiseGroove RiderCity LightsFunkChill900.6
Serving Track Data with a Flask API Endpoint

Now that you have the track data loaded, you need a way to share it with other parts of your app, such as the frontend. This is done by creating an API endpoint using Flask.

Here is the code from app.py that creates the endpoint:

from flask import Flask, jsonify
from src.database import get_all_tracks

app = Flask(__name__)

@app.route('/api/tracks', methods=['GET'])
def get_tracks_endpoint():
    """
    API endpoint to retrieve all tracks.
    Returns tracks as JSON list or error message.
    """
    tracks_df = get_all_tracks()
    
    if tracks_df.empty:
        return jsonify({"error": "No tracks available"}), 404
    
    # Convert DataFrame to list of dictionaries for JSON response
    tracks_list = tracks_df.to_dict(orient='records')
    return jsonify(tracks_list)

if __name__ == '__main__':
    # Run development server
    app.run(host='0.0.0.0', port=5001, debug=True)

Explanation:

  • The @app.route('/api/tracks', methods=['GET']) line creates a new API endpoint at /api/tracks.
  • When someone visits this endpoint, the get_tracks_endpoint function is called.
  • It loads all tracks using get_all_tracks().
  • If there are no tracks, it returns an error message.
  • Otherwise, it converts the DataFrame to a list of dictionaries and returns it as JSON. This conversion is done using DataFrame.to_dict(orient='records'), which turns each row into a dictionary and returns a list of them. This format is ideal for JSON responses, as each track becomes a distinct object in the array. It's also easy to loop through on the frontend.

Example Output: When you visit http://localhost:5001/api/tracks, you will get a response like:

[
  {
    "id": "track001",
    "title": "Sunrise Melody",
    "artist": "Synth Weaver",
    "album": "Digital Dreams",
    "genre": "Electronic",
    "mood": "Uplifting",
    "tempo": 120,
    "energy": 0.8
  },
  {
    "id": "track002",
    "title": "Midnight Cruise",
    "artist": "Groove Rider",
    "album": "City Lights",
    "genre": "Funk",
    "mood": "Chill",
    "tempo": 90,
    "energy": 0.6
  }
]
Getting All Available Genres

In addition to track data, it’s often useful for a frontend to know what genres are available. This allows the user interface to offer genre filters or suggestions. To support this, we’ve added a new function and API route:

In src/database.py, we have the get_all_genres() function:

def get_all_genres():
    """Returns a sorted list of unique genres from the tracks."""
    tracks_df = load_tracks_data()
    if tracks_df.empty or 'genre' not in tracks_df.columns:
        return []
    genres = tracks_df['genre'].dropna().unique().tolist()
    return sorted(genres)
  • We use dropna() to ignore missing genres.
  • unique() finds all distinct genres.
  • We sort the result to make it easier to use in dropdowns or lists.

In app.py, we expose this with a new route:

@app.route('/api/genres', methods=['GET'])
def get_genres_endpoint():
    """API endpoint to retrieve all unique genres."""
    genres = get_all_genres()
    return jsonify(genres)

When you visit http://localhost:5001/api/genres, the server returns a JSON array of all genres:

["Electronic", "Funk", "Pop", "Ambient"]
Summary And What’s Next

In this lesson, you learned how to:

  • Store music track data in a JSON file
  • Load that data into your app using Pandas
  • Set up a Flask API endpoint to serve the track data as JSON

These are the basic building blocks for any music player backend. In the practice exercises that follow, you will get hands-on experience working with these files and functions. This will prepare you for more advanced features in future lessons, such as tracking user sessions and making music recommendations. Good luck, and have fun practicing!

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal