Home and Learn: Vibe Coding Course


Build a Premier League Transfer Data App with Codex

By Home and Learn · Last updated 31 July 2026

In this CSV JavaScript tutorial, you'll build a data-driven web app with Codex. The project explores player transfers in the UK Premier League from 2010/2011 through 2022/2023.

The Codex data app uses HTML to structure the page, CSS to control its appearance, JavaScript to load, filter, summarise and display the records, and a CSV file to store the transfer data. This keeps the project suitable for an ordinary static website while showing how the four technologies work together.

If you're new to the course, read the introduction to vibe coding and set up Codex in the getting-started tutorial before beginning this project.

So that you can see the end goal before you start building, open the completed app here:

Data Driven App - Premier League Transfers (opens in new tab)

Where Data Comes From

A browser app can use data in a few different ways. The simplest method is to place the data directly inside the JavaScript file. This is easy for small examples, but it becomes messy as the data grows. Another common method is to store the data in a separate file, such as a CSV file, and use JavaScript to load it when the page opens. This keeps the data separate from the code, which makes the project easier to understand.

A browser app can also get data from a server. For example, the browser might send a request to an API, and the API sends back the data. This is how many real websites work. The data might be stored in a database, such as SQLite, MySQL, PostgreSQL, or DuckDB. The browser does not usually talk directly to the database. Instead, it talks to a backend program, and the backend program gets the data safely from the database.

For a beginner project, using a separate data file is often the best place to start. It means you can see the data clearly, open it in spreadsheet software, and understand how the web page is using it. In this tutorial, the app will load the transfer data from a CSV file. The JavaScript reads the file, turns each row into an object, and then uses those objects to populate dropdowns, summary boxes, and a table.

A CSV file is a plain text file that stores data in rows and columns. CSV stands for “comma-separated values”. Each line is a row, and each value is separated by a comma. CSV files are useful because they are simple, small, and easy for code to read. They can also be opened in Excel, Google Sheets, or a text editor. This makes them a good choice for web apps and tutorials.

The disadvantage of CSV is that it only stores raw data. It does not store formatting, formulas, colours, charts, or multiple worksheets. It can also have problems if the data contains commas, line breaks, or inconsistent values. For example, football transfer data might include blank fees, loan notes, or slightly different club names. The CSV file can store these values, but it does not explain or clean them for us.

A spreadsheet file, such as an Excel .xlsx file, is more powerful for people to look at and work with manually. It can contain formatted tables, filters, formulas, charts, colours, and multiple sheets. This makes it easier to explore the data before building the app. A spreadsheet is often better for planning and checking the data, especially if you want to sort columns, filter rows, or quickly calculate totals.

The disadvantage of a spreadsheet file is that it is more complicated for a browser app to read directly. A CSV file can be loaded with basic JavaScript, but an Excel file usually needs an extra library or a backend tool to process it. Spreadsheet files are also larger and more complex than CSV files. For a beginner web app, it is usually easier to use the spreadsheet for exploring the data, then export or save the data as CSV for the app itself.

A useful way to think about it is this: the spreadsheet is good for humans, and the CSV is good for code. You can open the spreadsheet to understand the data, check the column headings, and spot any problems. Then the web app can load the CSV version because it is simpler and easier to process in JavaScript.

But, in case you are interested in the source, the transfer data is taken from this GitHub page:

https://github.com/JaseZiv/worldfootballR

We created both a CSV file and an Excel spreadsheet. You can download both here:

Download the Data (1.7 MB zip file)

The Excel file holds nearly 11 thousand rows, so there is plenty of data for us to work with. Save the ZIP file to your own computer. Then unzip the file. Make a note of where on your computer you save the file to.

Planning Your App

To better plan what data you want to concentrate on with your app, you can ask Codex to display the column headers from the spreadsheet and give an explanation of what data is in each column. Something like this prompt:

Obviously, delete PATH_TO_YOUR_UNZIPPED_FILES_HERE and enter your own filepath. You'll get some feedback like this:

Column What it appears to contain
season_label A readable football season label, such as 2010/2011. This is useful for dropdown filters.
season The starting year of the season, such as 2010 for 2010/2011.
window The transfer window: usually Summer or Winter.
direction Whether the transfer is an incoming or outgoing move for the Premier League club. Values are in and out.
pl_club The Premier League club the transfer row is about, such as Chelsea FC or Sunderland AFC.
player_name The name of the player involved in the transfer.
position The player’s position, such as Centre-Forward, Goalkeeper, or Central Midfield.
age The player’s age at the time of the transfer. This is stored as text in the CSV but can be treated as a number for age-group filters.
nationality The player’s nationality.
from_club The club the player moved from. For outgoing transfers, this is usually the Premier League club.
to_club The club the player moved to. For incoming transfers, this is usually the Premier League club.
counterparty_club The other club involved in the transfer, from the perspective of the Premier League club.
counterparty_league The league of the other club, where known, such as Championship, Premier League, or Bundesliga.
counterparty_country The country of the other club, where known.
fee_eur The listed transfer fee in euros. Many rows are blank because loans, free transfers, returns, or unknown fees may not have a fee value.
is_loan Whether the move appears to be a loan-related transfer. Values are True or False.
transfer_notes Extra information about the move, such as loan transfer, End of loan May 31, 2011, or other notes. This is useful for understanding loan returns and duplicate-looking rows.
in_squad Squad involvement after the move, where available. Appears to be a numeric count.
appearances Number of appearances, where available.
goals Number of goals, where available.
minutes_played Minutes played, where available.
player_url The player’s Transfermarkt profile URL.
source_league The source league for the filtered dataset. In this file, it is always Premier League.
source_country The source country for the filtered dataset. In this file, it is always England.
source_url The GitHub/raw data source used to create the CSV.

Some of the columns above are better for filtering, such as pl_club, season_label, age, and direction. Other columns are better for display, such as player_name, from_club, to_club, fee_eur, and transfer_notes. Some columns, especially loan notes, fees, and player ages, may need cleaning before being used for serious analysis.

You can tell Codex to pull and filter the data that you are interested in. For us, we wanted dropdown lists at the top of our app, nice and simple so that a user could just dive in. We wanted three dropdown lists at the top for Club, Season, and Player Age.

Designing and Vibe Coding the App

Don't forget, as you saw in a previous lesson, you can put Codex into planning mode and ask it for some ideas on how your app should work.

You can also ask Codex to display, say, four designs for your app. It will then give you back images of what it thinks are good designs, enabling you to select the best one. We did this for our Match Three game.

As we already knew what we wanted, here is our prompt:

Codex then came back to us with a web page we could view. Viewing the web page allowed us to make tweaks and corrections. Such as:

During the testing, we also noticed some issues:

Codex then came back and corrected the issues we listed.

After more back-and-forth prompts, we finally had a version we were happy with. Which is the version you played around with at the top of this lesson. Tinker with your own app. Get Codex to tweak it until you’re satisfied with the result.

Conclusion

We'll leave it there, though, for this simple data-driven web app. But one thing you may notice is errors in the data (player appearing multiple times, inconsistent club naming, age oddities, etc). This is exactly the kind of thing you will meet with real datasets. So some points to bear in mind:

  • Web apps like these are only as reliable as the source data.
  • Filtering and summaries can reveal data quality issues.
  • Cleaning data is a separate phase from building the interface.

Just to wrap. In this lesson, you learned the basics of what is needed for a data-driven app that you can interact with. You learned to solve performance issues and discovered that real data sources can be quite messy.

In the next lesson, we'll get away from the browser. We'll create a business PowerPoint presentation as well as a smart PDF summary to go with it.

 

Vibe Coding Home


Email us: enquiry at homeandlearn.co.uk