How To · · 10 min read

Building a first side project

Discover how to build a fun, first dashboard with Evidence.dev. This guide helps you set up data connections and create dynamic content—perfect for developers looking for a side project.

Building a first side project
Photo by Isaac Smith / Unsplash

Creating a compelling and insightful dashboard is essential for presenting data in a way that is both informative and engaging. In this blog post, we'll walk through the process of building a one-pager statistics page for FC24 players using Evidence.dev. This dashboard will provide high-level statistics, highlight top players, and showcase data on countries and clubs.

Prerequisites

Before diving into the code, ensure you have the following:

  1. Evidence.dev: An open-source data analytics framework. Get more info on how to get started on the website of the official documentation.
  2. FC24 Players Data: A CSV file containing player statistics.

The application repository

For people who really don't want to read the full article but just want to get started. Visit the repo below.

Repository: https://github.com/hoipippeloi/fc24.fact.ist

Get started...

  • Clone it
  • Open your command line in the folder you just created and...
  • Run -> npm install
  • Run -> npm run sources
  • Run -> npm run dev
  • Or if you want to know more ->
🔗
What you will be building -> https://fc24.fact.ist/

Connecting to the data

First, we need to connect to our data. This is done using the settings option after opening up evidence. Go to settings by clicking on the three dots on the top right. We then create a csv connection which creates a folder with two YAML files in it. In that folder we can store the csv files we want to be part of our app.

Read more about using csv files in the docs.

Setting up the data

Second, we need to load our data from the CSV file into Evidence.dev. This is done using the select statement, which reads data from our CSV file into a variable named recs. See how the csv.-prefix tells evidence to use the csv folder for getting the data.

select * from csv.fc24_players
Evidence.dev uses DuckDB in the browser under the hood. This means that every time you use 'npm run sources' the configured data connections and sets are imported into duckdb which then gets used by evidence and its capabilities.

Initializing the dashboard

The dashboard starts with a title and brief description, providing context about the FC24 statistics app. The recs variable is used to reference our data throughout the dashboard.

<h1>FC24 Statistics</h1>
<p>This app hosts analyses and insights to understand the 
<a class="link" 
  href="https://www.ea.com/nl-nl/games/ea-sports-fc/fc-24" 
  target="_blank">FC24
</a> 
players and teams data better.</p>
<hr class="uk-margin uk-divider-icon" />

High-level statistics

We calculate several high-level statistics such as total players, countries, clubs, and average metrics (e.g., age, height, weight, rating, wage, potential, value). This is achieved using SQL aggregate functions.

select 
    count(*) as total_players,
    count(distinct nationality_name) as total_countries,
    count(distinct club_name) as total_clubs,
    avg(age) as average_age,
    avg(height_cm) as average_height,
    avg(weight_kg) as average_weight,
    avg(overall) as average_rating,
    avg(wage_eur) as average_wage,
    avg(potential) as average_potential,
    avg(value_eur) as average_value
from ${recs} recs

These statistics are then displayed using the BigValue component, which provides a clean and visually appealing way to present key metrics.

<Grid cols=5>
    <div>
        <BigValue title="Total Players" data={totals} 
        value=total_players fmt='#,##0' />
    </div>
    <!-- Look into the code of the page to see the full script -->
</Grid>
<hr class="uk-margin uk-divider-icon" />

Click here for a full view of the page.

Top players based on rating

Next, we identify the top 12 players based on their overall rating. We use SQL to group and order the players by their rating.

select
    player_id as pid,
    'https://cdn.fifacm.com/content/media/imgs/fc24/players/p'
    || player_id::INTEGER::VARCHAR ||'.png' as img,
    long_name,
    short_name,
    club_name,
    club_position,
    nationality_name,
    player_traits,
    avg(overall) as overall_rating,
    avg(potential) as potential_rating
from ${recs} recs
group by 1,2,3,4,5,6,7,8
order by 9 desc
limit 12

We then display these top players in a grid format, including their image, name, club, and nationality.

<h3>Top 12 Players based on Rating</h3>
<Grid cols=3>
    {#each player_potential as pp}
    <div>
        <div class="uk-card uk-card-default uk-card-body">
            <img class="uk-preserve-width uk-border-circle uk-align-right" 
            style="border:1px solid #ccc;" src="{pp.img}" width="80" alt="">
            <span class="uk-preserve-width uk-border-circle uk-position-small 
            uk-position-top-right uk-text-center" 
            style="width:30px;height:30px;border:1px solid #ccc;padding:5px;">
            {pp.overall_rating}</span>
            <h3 class="uk-card-title">{pp.short_name}</h3>
            <p><a class="link" href="/{pp.club_name}/">{pp.club_name}</a> 
            / {pp.nationality_name}</p>
        </div>
    </div>
    {/each}
</Grid>
<hr class="uk-margin uk-divider-icon">

What does this code do?

The provided code snippet is designed to display a section titled "Top 12 Players based on Rating" on a webpage. Here's a high-level summary of how it works:

  1. Section Header:
    • <h3>Top 12 Players based on Rating</h3>: This line sets the title for the section, informing users that the following content will display the top 12 players based on their rating.
  2. Grid Layout:
    • <Grid cols=3>: Initializes a grid layout with three columns, ensuring that the player cards will be arranged in a three-column format for better visual organization.
  3. Dynamic Content Generation:
    • {#each player_potential as pp}: Begins a loop to iterate over the player_potential array. For each player object in this array, a block of HTML will be generated dynamically.
  4. Player Card Structure:
    • <div><div class="uk-card uk-card-default uk-card-body">: Creates a card for each player. The card is styled using UIkit classes to have a default appearance and a body section.
  5. Player Image:
    • <img class="uk-preserve-width uk-border-circle uk-align-right" style="border:1px solid #ccc;" src="{pp.img}" width="80" alt="">: Displays the player's image, styled to be circular, aligned to the right, and bordered. The image source URL is dynamically set from the player data.
  6. Player Rating Badge:
    • <span class="uk-preserve-width uk-border-circle uk-position-small uk-position-top-right uk-text-center" style="width:30px;height:30px;border:1px solid #ccc;padding:5px;">{pp.overall_rating}</span>: Displays the player's overall rating inside a styled badge, positioned in the top-right corner of the card.
  7. Player Name and Club Information:
    • <h3 class="uk-card-title">{pp.short_name}</h3>: Displays the player's short name as the card title.
    • <p><a class="link" href="/{pp.club_name}/">{pp.club_name}</a> / {pp.nationality_name}</p>: Displays the player's club name as a clickable link and their nationality. The link dynamically routes to a URL based on the club name.
  8. Closing Tags:
    • {/each}: Closes the loop that iterates over the player data.
    • </Grid>: Closes the grid layout.
  9. Section Divider:
    • <hr class="uk-margin uk-divider-icon">: Adds a horizontal rule (divider) to visually separate this section from others on the webpage.

The code dynamically generates and displays a grid of player cards, each containing an image, rating, name, club, and nationality of the top 12 players based on their rating. The grid layout and card styling are handled using UIkit classes, ensuring a consistent and visually appealing presentation. The dynamic content generation is facilitated by looping through the player_potential array, making the code flexible and easily updatable with new data.

Top 20 countries

We analyze the top 20 countries based on the number of players. This involves grouping by nationality and calculating various metrics.

select
    nationality_id,
    nationality_name, 
    count(*) as total,
    count(distinct club_name) as total_clubs,
    avg(age) as average_age,
    avg(height_cm) as average_height,
    avg(weight_kg) as average_weight,
    avg(overall) as average_rating,
    avg(wage_eur) as average_wage,
    avg(potential) as average_potential,
    avg(value_eur) as average_value
from ${recs} recs
group by 1,2
order by 3 desc
limit 20

We visualize the data using bar charts to compare the number of players and clubs for each country.

<h3>Top 20 Countries</h3>
<Grid cols=2>
    <div>
        <BarChart 
          title='Number of Players' 
          data={by_country} 
          x=nationality_name 
          y=total 
          swapXY=true 
          colorPalette={['#06871A']} 
          renderer=svg 
        />
    </div>
    <div>
        <BarChart 
          title='Number of Clubs' 
          data={by_country} 
          x=nationality_name 
          y=total_clubs 
          swapXY=true 
          colorPalette={['#06871A']} 
          renderer=svg 
        />
    </div>
</Grid>
<hr class="uk-margin uk-divider-icon" />

Top 20 clubs - skills

Finally, we analyze the top 20 clubs based on various skills such as pace, shooting, passing, dribbling, defending, and physic. We rank the clubs and calculate normalized scores for each skill.

WITH RankedClubs AS (
    SELECT
        club.club_name,
        club.club_team_id,
        AVG(club.overall)::INTEGER AS overall,
        AVG(club.pace)::INTEGER as pace,
        AVG(club.shooting)::INTEGER as shooting,
        AVG(club.passing)::INTEGER as passing,
        AVG(club.dribbling)::INTEGER as dribbling,
        AVG(club.defending)::INTEGER as defending,
        AVG(club.physic)::INTEGER as physic,
        AVG(club.mentality_composure)::INTEGER as composure
    FROM ${recs} club
    GROUP BY club.club_name, club.club_team_id
    ORDER BY overall DESC
    LIMIT 20
)
SELECT
    'score' as ph,
    club_name,
    club_team_id,
    overall,
    1 - ((MAX(overall) OVER () - overall) 
    / (MAX(overall) OVER () - MIN(overall) OVER ())) + 0.1 as rank_overall,
    pace,
    1 - ((MAX(pace) OVER () - pace) 
    / (MAX(pace) OVER () - MIN(pace) OVER ())) + 0.1 as rank_pace,
    shooting,
    1 - ((MAX(shooting) OVER () - shooting) 
    / (MAX(shooting) OVER () - MIN(shooting) OVER ())) + 0.1 as rank_shooting,
    passing,
    1 - ((MAX(passing) OVER () - passing) 
    / (MAX(passing) OVER () - MIN(passing) OVER ())) + 0.1 as rank_passing,
    dribbling,
    1 - ((MAX(dribbling) OVER () - dribbling) 
    / (MAX(dribbling) OVER () - MIN(dribbling) OVER ())) + 0.1 as rank_dribbling,
    defending,
    1 - ((MAX(defending) OVER () - defending) 
    / (MAX(defending) OVER () - MIN(defending) OVER ())) + 0.1 as rank_defending,
    physic,
    1 - ((MAX(physic) OVER () - physic) 
    / (MAX(physic) OVER () - MIN(physic) OVER ())) + 0.1 as rank_physic,
    composure,
    1 - ((MAX(composure) OVER () - composure) 
    / (MAX(composure) OVER () - MIN(composure) OVER ())) + 0.1 as rank_composure

FROM RankedClubs
ORDER BY overall DESC

We display the data in a table, using background colors to indicate the relative strength of each skill.

<h3>Top 20 Clubs - Skills</h3>
<table class="uk-table uk-table-small uk-table-divider">
    <thead>
        <tr>
            <th style="width:2%;text-align:center;"></th>
            <th>Club</th>
            <th style="width:8%;text-align:center;">Overall</th>
            <th style="width:8%;text-align:center;">Pace</th>
            <th style="width:8%;text-align:center;">Shooting</th>
            <th style="width:8%;text-align:center;">Passing</th>
            <th style="width:8%;text-align:center;">Dribbling</th>
            <th style="width:8%;text-align:center;">Defending</th>
        </tr>
    </thead>
    <tbody>
    {#each by_club as hm}
        <tr>
            <td style="text-align:center;">
              <img class="uk-preserve-width uk-border-circle"
               src="https://fifastatic.fifaindex.com/FIFA24/teams/light/
              {hm.club_team_id}.png" width="24" height="24" alt="">
            </td>
            <td>{hm.club_name}</td>
            <td style="text-align:center;
              background-color:rgba(0,163,20,{hm.rank_overall});">
              {hm.overall}
            </td>
            <td style="text-align:center;
              background-color:rgba(0,163,20,{hm.rank_pace});">
              {hm.pace}
            </td>
            <td style="text-align:center;
              background-color:rgba(0,163,20,{hm.rank_shooting});">
              {hm.shooting}
            </td>
            <td style="text-align:center;
              background-color:rgba(0,163,20,{hm.rank_passing});">
              {hm.passing}
            </td>
            <td style="text-align:center;
              background-color:rgba(0,163,20,{hm.rank_dribbling});">
              {hm.dribbling}
            </td>
            <td style="text-align:center;
              background-color:rgba(0,163,20,{hm.rank_defending});">
              {hm.defending}
            </td>
        </tr>
    {/each}
    </tbody>
</table>

Conclusion

Using Evidence.dev, we've built a helpful dashboard that shows FC24 player stats. It includes key metrics, top player highlights, and detailed looks at countries and clubs. Whether you're into data or just love football, this dashboard can help you explore and understand FC24 data better.


What do I have now?

Click the button below to see what you built...

Show me

Stay tuned for next updates and articles. You can also subscribe to get more content on data and information design in your inbox.

FAQs

1. What is the purpose of this project?

This project aims to create a compelling and insightful dashboard for FC24 players using Evidence.dev. The dashboard provides high-level statistics, highlights top players, and showcases data on countries and clubs, making it perfect for developers looking for a fun and engaging side project.

2. What are the prerequisites for starting this project?

Before starting, ensure you have the following:

  • Evidence.dev installed (an open-source data analytics framework)
  • A CSV file containing FC24 player statistics
  • Access to the application repository, which you can find here.

3. How do I connect my data to Evidence.dev?

To connect your data, open Evidence and navigate to the settings by clicking on the three dots in the top right corner. Create a CSV connection, which will generate a folder with two YAML files. Store your CSV files in this folder to include them in your app.

4. How can I load my data into Evidence.dev?

You can load your data using the select statement in Evidence.dev. For example:

select * from csv.fc24_players

This command reads data from your CSV file into a variable named recs.

5. How do I display high-level statistics in the dashboard?

Use SQL aggregate functions to calculate high-level statistics such as total players, countries, clubs, and average metrics (e.g., age, height, weight, rating, wage, potential, value). Display these metrics using the BigValue component for a clean and visually appealing presentation.

6. How can I highlight top players based on their rating?

To highlight the top 12 players based on their overall rating, use SQL to group and order the players by their rating. Then, display these top players in a grid format, including their image, name, club, and nationality.

7. How do I analyze the top 20 countries based on the number of players?

Group the players by nationality using SQL and calculate various metrics. Visualize the data using bar charts to compare the number of players and clubs for each country.

8. How can I analyze the top 20 clubs based on various skills?

Rank the clubs and calculate normalized scores for various skills such as pace, shooting, passing, dribbling, defending, and physic. Display the data in a table, using background colors to indicate the relative strength of each skill.

9. Where can I see the final dashboard?

You can view the final dashboard by clicking here. This will show you the completed project with all the data visualizations and insights.

10. What resources can help me learn more about using Evidence.dev?

To learn more about Evidence.dev, you can explore the official documentation, familiarize yourself with SQL and markdown syntax, and join the Evidence community on Slack or GitHub for support and insights.

Read next