<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[The Underdoc]]></title><description><![CDATA[Practical insights on the modern AI stack. Building data pipelines for RAGs and Agents using football analytics as the sandbox.]]></description><link>https://ricardoheredia.substack.com</link><image><url>https://substackcdn.com/image/fetch/$s_!7Z1G!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20046b3b-539a-43f7-8114-9704dfda33e0_500x500.png</url><title>The Underdoc</title><link>https://ricardoheredia.substack.com</link></image><generator>Substack</generator><lastBuildDate>Wed, 20 May 2026 01:38:56 GMT</lastBuildDate><atom:link href="https://ricardoheredia.substack.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Ricardo Heredia]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[ricardoheredia@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[ricardoheredia@substack.com]]></itunes:email><itunes:name><![CDATA[Ricardo Heredia]]></itunes:name></itunes:owner><itunes:author><![CDATA[Ricardo Heredia]]></itunes:author><googleplay:owner><![CDATA[ricardoheredia@substack.com]]></googleplay:owner><googleplay:email><![CDATA[ricardoheredia@substack.com]]></googleplay:email><googleplay:author><![CDATA[Ricardo Heredia]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Got interviewed by Ryan Day in his Tip Sheet issue #65 and some extra thoughts]]></title><description><![CDATA[Ryan Day (author of Hands-On APIs for AI and Data Science, O&#8217;Reilly) and writer of the Tip Sheet newsletter featured me in his issue #65 last week.]]></description><link>https://ricardoheredia.substack.com/p/got-interviewed-by-ryan-day-in-his</link><guid isPermaLink="false">https://ricardoheredia.substack.com/p/got-interviewed-by-ryan-day-in-his</guid><dc:creator><![CDATA[Ricardo Heredia]]></dc:creator><pubDate>Tue, 05 May 2026 19:26:42 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!qxHj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bc49534-20f2-4ac3-8f28-71a17e26878f_1170x2051.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qxHj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bc49534-20f2-4ac3-8f28-71a17e26878f_1170x2051.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qxHj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bc49534-20f2-4ac3-8f28-71a17e26878f_1170x2051.jpeg 424w, https://substackcdn.com/image/fetch/$s_!qxHj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bc49534-20f2-4ac3-8f28-71a17e26878f_1170x2051.jpeg 848w, https://substackcdn.com/image/fetch/$s_!qxHj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bc49534-20f2-4ac3-8f28-71a17e26878f_1170x2051.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!qxHj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bc49534-20f2-4ac3-8f28-71a17e26878f_1170x2051.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qxHj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bc49534-20f2-4ac3-8f28-71a17e26878f_1170x2051.jpeg" width="1170" height="2051" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2bc49534-20f2-4ac3-8f28-71a17e26878f_1170x2051.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:2051,&quot;width&quot;:1170,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:0,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!qxHj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bc49534-20f2-4ac3-8f28-71a17e26878f_1170x2051.jpeg 424w, https://substackcdn.com/image/fetch/$s_!qxHj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bc49534-20f2-4ac3-8f28-71a17e26878f_1170x2051.jpeg 848w, https://substackcdn.com/image/fetch/$s_!qxHj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bc49534-20f2-4ac3-8f28-71a17e26878f_1170x2051.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!qxHj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2bc49534-20f2-4ac3-8f28-71a17e26878f_1170x2051.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p>Ryan Day (author of <em>Hands-On APIs for AI and Data Science, </em>O&#8217;Reilly) and writer of the Tip Sheet newsletter featured me in his <a href="https://ryan-day.kit.com/posts/tip-sheet-65-data-scientist-doctor-football-aficionado">issue #65 </a>last week.</p><p>He asked eight questions about my background, my stack, and how I learn. </p><p>There were three of them I wanted to expand a bit and share some thoughts with you.</p><div><hr></div><h3>Q4: Why are side projects valuable for people learning data science?</h3><p>In a side project you set the tone of what you want to build, why it matters, and how to measure if it worked.</p><p>You pick a problem you care enough about, you define the requirements, the scope, the technology and the dataset. It forces you to learn and think with a kind of clarity that structured learning rarely does. </p><p>I started with football analytics because I wanted to apply what I was learning to something I cared about and found fun enough and it has led me to push my knowledge forwards and collaborate with special people I wouldn&#8217;t think I&#8217;d meet if I didn&#8217;t build these kind of projects.</p><p>Fun fact is: this also helped to me work on healthcare data/AI projects on my day job. </p><h3>Q6: What methods of skill development have you benefited from most?</h3><p>I told Ryan I combine three: structured learning, project-based learning, and unstructured learning. </p><p>In this case my opinion is that the order matters.</p><p>Structured learning gives you the map and foundations to get the knowledge that you can then apply to projects. It doesn&#8217;t mean you need to learn everything there is about a topic and fall into rabbit holes, but just learning the necessary info to start building and leaving room for experimentation while you research stuff when you&#8217;re stuck.</p><p>On the other side unstructured learning like newsletters, blog posts, a well-curated social media timeline, keeps you updated to where the field is actually going. It can even give you some ideas to implement them yourself on your projects.</p><p>A dangerous trap is staying too long in one mode. </p><p>Entering tutorial hell by finishing a course and starting another course with no meaningful output (been there) creates an illusion of learning. Or jumping straight to building without a minimal foundation, spending weeks debugging something a couple hours read (or documentation) would have clarified.</p><p>The sweet spot is knowing when to shift from one to another. For example, if you&#8217;re new to something or you&#8217;re a bit confused, go with structured. </p><p>When you feel you got a good initial grasp of that knowledge, go build something even if it&#8217;s small, to make it stick. </p><p>If you feel you want to see how the field evolves, go with unstructured.</p><p>Right now I&#8217;m running all three in parallel: taking Agentic AI Engineering course at Towards AI Academy by Paul Iusztin and Louis-Fran&#231;ois Bouchard, applying it directly to a tool I&#8217;m building for myself, and constantly reading newsletters like Ryan&#8217;s to stay sharp on what people are shipping.</p><div><hr></div><h3>Q7: What would you tell people who want to keep developing their technical skills?</h3><p>To make it stick, I&#8217;ll put it inside quotes:</p><blockquote><p>Write about what you learn and share it online.</p></blockquote><p>Not for personal branding but because explaining something forces you to actually understand it.</p><p>Every post I&#8217;ve written about RAG pipelines, MCP, or football data sources has exposed gaps in my own thinking that I didn&#8217;t know were there until I tried to put them into words. This makes me want to understand things better. </p><p>Th big myth we need to debunk is the need for a big audience. You actually don&#8217;t. The &#8220;trick&#8221; is to be consistent even if you have a &#8220;small audience&#8221; or you think nobody&#8217;s going to listen. There are people out there that will definitely benefit from your point of view. </p><p>You can write a bug you fixed, the trade-off you made when deciding on your tech stack, the framework you just learn from one field and how you applied it to solve a problem in another.</p><p>Maybe ten people will read it but one of them might be building the exact same thing and needed exactly that post. Or one of them might be writing a newsletter and looking for someone to interview &#129335;&#127995;&#8205;&#9794;&#65039; </p><p>Your job is to make it exist. </p><p></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/subscribe?utm_source=email&r=&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://ricardoheredia.substack.com/subscribe?utm_source=email&r="><span>Subscribe</span></a></p><p>Here&#8217;s the link to the full interview: <strong><a href="https://ryan-day.kit.com/posts/tip-sheet-65-data-scientist-doctor-football-aficionado">Tip Sheet #65: Data Scientist, Doctor, Football Aficionado</a></strong></p><p></p><p>Till next time,</p><p>Ricardo.</p>]]></content:encoded></item><item><title><![CDATA[How a Football Framework for Measuring Performance Works For Other Industries]]></title><description><![CDATA[How you can apply this to healthcare, business or any other industry]]></description><link>https://ricardoheredia.substack.com/p/how-a-football-framework-for-measuring</link><guid isPermaLink="false">https://ricardoheredia.substack.com/p/how-a-football-framework-for-measuring</guid><dc:creator><![CDATA[Ricardo Heredia]]></dc:creator><pubDate>Mon, 09 Mar 2026 07:03:03 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/77645acd-c8eb-461a-82fb-49b0c10ffdc8_2816x1536.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I used to think starting a data project was about jumping straight to the data, looking at what&#8217;s available and drawing conclusions. </p><p>That led to dashboards and models nobody used or cared. </p><p>Then last week in the Twelve Football Context Engineering course, I realized how the concept behind the framework for measuring team and player performance they teach could be used for solving problems in other areas.</p><h4>Asking questions first, then data </h4><p>I&#8217;ve been taking this course for the past two weeks and the knowledge compounds incrementally from one week to another. The goal is to create a project around qualities, metrics, pitch visuals and time series approach that they emphasize at Twelve. </p><p>Their framework starts with a simple instruction:</p><p><strong>Start with football. Not data.</strong></p><p>The first step is asking a human question like &#8220;what you are trying to answer and for whom?&#8221;.</p><p>What insight can you bring that no-one else has brought before?</p><p>An initial question might be: <em>What makes a good midfielder? </em>or <em>What makes a team dangerous in defensive transitions?</em></p><p>Once you&#8217;ve answered that in plain football language you move to the data. The idea is to build <em>Qualities &#8594; </em>composite scores that capture a specific aspect of player or team performance.</p><p>You choose 3 to 10 metrics that capture different aspects of the concept. Assign weights based on how important each one is to the original definition. Compute scores using z-scores and compare each player against the right group.</p><p>That last part is highly important.</p><p>For example when building a <em>Passing Quality</em> score for midfielders, you can end up with five metrics: Passes (xT), Passes into the final third (xT), Passes in the final third (xT), Crosses (xT), and Creative passes weighted at 30%, 20%, 20%, 20%, and 10% respectively. The result is a single score that tells you how threatening a midfielder&#8217;s passing is.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Buqg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd6f3589-1ea2-434b-b2f6-6be3cb5d7e03_2482x1394.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Buqg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd6f3589-1ea2-434b-b2f6-6be3cb5d7e03_2482x1394.heic 424w, https://substackcdn.com/image/fetch/$s_!Buqg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd6f3589-1ea2-434b-b2f6-6be3cb5d7e03_2482x1394.heic 848w, https://substackcdn.com/image/fetch/$s_!Buqg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd6f3589-1ea2-434b-b2f6-6be3cb5d7e03_2482x1394.heic 1272w, https://substackcdn.com/image/fetch/$s_!Buqg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd6f3589-1ea2-434b-b2f6-6be3cb5d7e03_2482x1394.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Buqg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd6f3589-1ea2-434b-b2f6-6be3cb5d7e03_2482x1394.heic" width="1456" height="818" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cd6f3589-1ea2-434b-b2f6-6be3cb5d7e03_2482x1394.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:818,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:83782,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/190276623?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd6f3589-1ea2-434b-b2f6-6be3cb5d7e03_2482x1394.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Buqg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd6f3589-1ea2-434b-b2f6-6be3cb5d7e03_2482x1394.heic 424w, https://substackcdn.com/image/fetch/$s_!Buqg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd6f3589-1ea2-434b-b2f6-6be3cb5d7e03_2482x1394.heic 848w, https://substackcdn.com/image/fetch/$s_!Buqg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd6f3589-1ea2-434b-b2f6-6be3cb5d7e03_2482x1394.heic 1272w, https://substackcdn.com/image/fetch/$s_!Buqg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd6f3589-1ea2-434b-b2f6-6be3cb5d7e03_2482x1394.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Example for Kevin De Bruyne in PL 2022/2023 season</figcaption></figure></div><p>In this image you can see Belgian player Kevin De Bruyne scores near the top but the framework also tells you <em>why</em>, and which specific dimension he excels at versus where he&#8217;s merely good compared to other players. </p><p>That&#8217;s the useful part.</p><h4>Context is everything</h4><blockquote><p><em>&#8220;Metrics are meaningless without context. Choosing the correct comparison group is essential.&#8221;</em></p></blockquote><p>The comparison group (position, age, league, minutes played) is where we need to emphasize the analysis. Posing the problem and thinking clearly about it before writing the first line of code.</p><p>For example a midfielder with high progressive passes has a different meaning than an attacking midfield who sits deep in the field. </p><p>A 25 y/o player that has an elevated duel success rate has a different interpretation than a 32 y/o player in the same league. </p><p>To produce accurate insights, we need to use the same comparison pool of players.</p><h4>How you can use it in other industries </h4><p>Take diabetic patient monitoring. A case I&#8217;ve been actively working on in my day job.</p><p>The human question becomes: <em>How well is this patient managing their blood sugar?</em> </p><p>You define it in clinical terms first, consistent glucose levels, avoiding dangerous highs and lows, showing improvement over time. Then you look at what you can measure: HbA1c, time above range, time below range, trend direction, glucose variability.</p><p>You weight them by clinical importance to finally compare against patients of similar age, diabetes type, and diagnosis duration.</p><p>The output is a sentence a physician can actually use: </p><blockquote><p><em>&#8220;This patient&#8217;s glycemic control is below average for their profile, but trending in the right direction over the last six months. The main challenge is post-meal spikes, not overnight lows.&#8221;</em></p></blockquote><p>The focus is on turning data into a decision.</p><p>You could also apply this template for industries like customer churn in SaaS or credit risk in finance, by always starting with a human question.</p><h4>Key Takeaways</h4><p>The best analytical frameworks are domain-agnostic. They travel between industries.</p><p>Start with the human question by defining the concept before you open the dataset, choosing your comparison group deliberately, then let the data answer.</p><p>The framework already exists in your field and most people just never look outside their own.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share The Underdoc&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://ricardoheredia.substack.com/?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share The Underdoc</span></a></p><p>Thanks for reading one more time. </p><p>Till next time, </p><p>Ricardo. </p>]]></content:encoded></item><item><title><![CDATA[Wordalisation & Context Engineering: What Finally Made My RAG System Sound Like Football]]></title><description><![CDATA[My RAG system was technically correct but the resulting insights were useless for an analyst or a scout.]]></description><link>https://ricardoheredia.substack.com/p/wordalisation-and-context-engineering</link><guid isPermaLink="false">https://ricardoheredia.substack.com/p/wordalisation-and-context-engineering</guid><dc:creator><![CDATA[Ricardo Heredia]]></dc:creator><pubDate>Tue, 03 Mar 2026 07:02:03 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!1Mvg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd921920d-f096-4a2d-9089-40c5a993db2e_2816x1536.heic" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>My RAG system was technically correct but the resulting insights were useless for an analyst or a scout.</p><p>The numbers and metrics were being computed, the LLM was receiving them, acknowledging them, and then repeating them back to me as if reading from a spreadsheet.</p><p>&#8220;Home xG was 1.2 and they scored 3 goals. Away PPDA was 4.8, indicating a high press...&#8221;</p><p>There was no enriched analysis it was just data recitation that didn&#8217;t sound like football language.</p><p>I was using claude-haiku-4.5 which is capable of writing football language. If you ask it to analyze a match in prose it&#8217;ll produce something close to what a scout would write. The model actually knew what a high press looked like, what a low block meant, defensive compactness, progressive passing patterns, etc, but by asking it to recite metrics I just wasn&#8217;t letting it &#8220;speak&#8221; football.</p><h4>The problem was my prompt not the model</h4><p>I was passing raw floats directly to the LLM (PPDA of 4.8, expected goals of 1.2, progressive pass counts, compactness scores) and then instructing it to &#8220;state only what the metrics directly prove&#8221; with &#8220;technical terminology and neutral tone.&#8221;</p><p>David Sumpter, the brain behind Soccermatics and Twelve Football, calls the solution &#8594; <a href="https://soccermatics.medium.com/introducing-wordalisations-automated-explanations-of-data-8e6687ad2d77">Wordalisation</a>. The idea is straightforward: before you call the LLM, classify your raw metrics into qualitative English labels. The model never sees the numbers. It only sees what those numbers mean in the language of the domain.</p><p>Here&#8217;s what the change looked like in practice.</p><p>Before, the user prompt contained something like this:</p><pre><code><code>home_ppda: 4.8
home_high_press_count: 12
home_compactness: 33.4
home_field_tilt: 67.9</code></code></pre><p>After applying Wordalisation, the LLM received this instead:</p><pre><code><code>home_press_style: pressed_aggressively_allowing_few_passes
home_defensive_shape: compact_block
home_territorial_dominance: dominated_final_third
home_shot_quality: created_high_quality_chances</code></code></pre><p>Just English labels describing what the team actually did, derived from the real Eredivisie 2025-2026 distributions rather than arbitrary thresholds.</p><p>The smoke test output shifted the result for good:</p><p>Before:</p><blockquote><p>&#8220;Home xG was 1.2 and they scored 3 goals. Away PPDA was 4.8...&#8221;</p></blockquote><p>After:</p><blockquote><p>&#8220;Heracles set up to frustrate, sitting deep and inviting PEC Zwolle to come at them &#8212; a coherent enough plan in isolation, but one that demanded defensive discipline and clinical use of the rare moments they could hurt the visitors on the break. A low block without the finishing to punish opponents on the counter is simply a slow surrender.&#8221;</p></blockquote><p>The data from the pipeline was exactly the same, but thanks to this tweak the output changed completely.</p><h4>The second change: how I formatted the context</h4><p>I implemented this one from a course I&#8217;m working through called <a href="https://academy.towardsai.net/courses/agent-engineering?ref=6f2638">Agentic AI Engineering from Towards AI</a>. </p><p>The lesson was about Context Engineering, the discipline of deciding what goes into a model&#8217;s context window in order to make it follow the right instructions.</p><p>One of the practical recommendations was: <strong>prefer YAML over JSON when providing structured data as input.</strong></p><p>I&#8217;d been using Python dicts serialized as JSON. The lesson argued YAML is more token-efficient and reads more naturally alongside prose examples in a prompt.</p><p>I ran a quick comparison on my own <code>&lt;tactical_labels&gt;</code> block.</p><p>JSON version:</p><pre><code><code>{
  "home_press_style": "pressed_aggressively_allowing_few_passes",
  "home_defensive_shape": "compact_block",
  "home_territorial_dominance": "dominated_final_third"
}
</code></code></pre><p>YAML version:</p><pre><code><code>home_press_style: pressed_aggressively_allowing_few_passes
home_defensive_shape: compact_block
home_territorial_dominance: dominated_final_third
</code></code></pre><p>The YAML block is shorter (no brackets, no quotes, no commas), and it reads more like prose which matters when it&#8217;s sitting next to few-shot examples written in natural language. The model processes both from the same context window. Found out that small token savings compound across many calls, and a cleaner context means less noise for the model to work through.</p><p><strong>The other Context Engineering principle I applied was prompt structure.</strong></p><p>The lesson covered something called the &#8220;lost-in-the-middle&#8221; problem: LLMs tend to underweight information placed in the middle of long contexts, so what they remember best is what comes first and what comes last.</p><p>The practical implication: you have to put your most important instructions at the START (system prompt) and at the END (<code>&lt;instructions&gt;</code> block). Dynamic content like match labels and retrieved facts goes in the middle.</p><p>And for caching: put static content first. That way the system prompt and few-shot examples don&#8217;t change between calls. Both go at the top, before any dynamic match data. This allows the provider to cache the static prefix and skips re-processing it on every requests.</p><p>My prompt structure now looks like this:</p><pre><code><code>&lt;system_prompt&gt;     &#8592; static, cached
  [scouting style instructions]

&lt;few_shot_examples&gt; &#8592; static, cached
  [two reference match analyses]

&lt;match_context&gt;     &#8592; dynamic per call
  [YAML labels for this match]

&lt;instructions&gt;      &#8592; static, repeated at end
  [core constraints, re-anchored]
</code></code></pre><p>The model gets its instructions twice. </p><p>Once at the top before anything else and once at the bottom after seeing the data. This is how we can avoid lost-in-the-middle.</p><h4>A broader principle connecting Wordalisation and Context Engineering</h4><p>Both are fundamentally about the same thing: giving the model the right kind of information.</p><p><strong>Wordalisation</strong> says: don&#8217;t give the model numbers and ask it to interpret them. Classify the numbers into domain language first, then give the model language it can work with.</p><p><strong>Context Engineering</strong>: don&#8217;t give the model everything you have. Select what&#8217;s relevant, compress what&#8217;s not, format it so the model can use it without fighting its own architecture.</p><p>Since the LLM does not work as a calculator nor a database we need to feed it with the right data: language.</p><h4>Key Takeaways</h4><p>The RAG system has a well curated data pipeline but now, at the point where structured data meets the language model, there&#8217;s a much needed translation layer that needs to be included.</p><p>The data flows like: Numbers &#8594; Labels &#8594; LLM &#8594; football insight.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1Mvg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd921920d-f096-4a2d-9089-40c5a993db2e_2816x1536.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1Mvg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd921920d-f096-4a2d-9089-40c5a993db2e_2816x1536.heic 424w, https://substackcdn.com/image/fetch/$s_!1Mvg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd921920d-f096-4a2d-9089-40c5a993db2e_2816x1536.heic 848w, https://substackcdn.com/image/fetch/$s_!1Mvg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd921920d-f096-4a2d-9089-40c5a993db2e_2816x1536.heic 1272w, https://substackcdn.com/image/fetch/$s_!1Mvg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd921920d-f096-4a2d-9089-40c5a993db2e_2816x1536.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1Mvg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd921920d-f096-4a2d-9089-40c5a993db2e_2816x1536.heic" width="1456" height="794" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d921920d-f096-4a2d-9089-40c5a993db2e_2816x1536.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:794,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1062725,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/189698006?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd921920d-f096-4a2d-9089-40c5a993db2e_2816x1536.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1Mvg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd921920d-f096-4a2d-9089-40c5a993db2e_2816x1536.heic 424w, https://substackcdn.com/image/fetch/$s_!1Mvg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd921920d-f096-4a2d-9089-40c5a993db2e_2816x1536.heic 848w, https://substackcdn.com/image/fetch/$s_!1Mvg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd921920d-f096-4a2d-9089-40c5a993db2e_2816x1536.heic 1272w, https://substackcdn.com/image/fetch/$s_!1Mvg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd921920d-f096-4a2d-9089-40c5a993db2e_2816x1536.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>That&#8217;s exactly the principle of Wordalisation applied to Context Engineering.</p><p>Hope this gives you an idea on how to translate metrics into text, by leveraging LLM&#8217;s text generation capabilities.</p><p>Till next time, </p><p>Ricardo.</p><div><hr></div><p></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Underdoc! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Embrace Your Weirdness]]></title><description><![CDATA[You might be an outlier and you might haven't realized it yet]]></description><link>https://ricardoheredia.substack.com/p/embrace-your-weirdness</link><guid isPermaLink="false">https://ricardoheredia.substack.com/p/embrace-your-weirdness</guid><dc:creator><![CDATA[Ricardo Heredia]]></dc:creator><pubDate>Sat, 21 Feb 2026 13:38:38 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!nVLs!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee549504-5888-47ed-a9c7-cd26bc607355_1500x900.heic" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A concept I believe is really important nowadays when AI is closing the gap of what you can create and where you come from is: weirdness. The strange combination of skills that make you a valuable individual.</p><p>At some point of our lives, someone tells you to pick a lane.</p><p>The school, a teacher, family, social media. Maybe your own head at 2am wondering if you&#8217;re interested on too many things to ever be taken seriously at any of them.</p><p>&#8220;<em>Pick one thing, go deep enough and become an expert at that for the rest of your life.</em>&#8221;</p><p>Although the most interesting people I&#8217;ve come across didn&#8217;t get there by picking a lane but by refusing to.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://ricardoheredia.substack.com/subscribe?"><span>Subscribe now</span></a></p><h4>Specialists &amp; Outliers</h4><p>I&#8217;ve been recently reading Dan Koe&#8217;s <em>Purpose &amp; Profit</em> and a concept that grasped my attention was that the education system was never designed to help you reach your potential but to turn you into a useful workers in an interchangeable role.</p><p>Debatable but I can see the point behind it, if you&#8217;re only trained to do one thing you can&#8217;t adapt. Specialization isn't bad. But betting your entire identity on a single skill, in a world that's moving this fast, is the riskiest thing you can do.</p><h4>Your Weird Combination Is the Advantage</h4><p>I&#8217;ll use my own story here because it&#8217;s the most honest one I have.</p><p>I graduated from med school in Venezuela in 2019. But I felt something was off. Not wrong exactly, I knew I was supposed to be there but I wasn&#8217;t feeling fulfilled. </p><p>So I started exploring other things on the side: bartending, mobile app development, whatever I could get my hands on.</p><p>Then the pandemic hit, and I stumbled upon Python.</p><p>Something clicked. </p><p>I started applying it to football analytics and got immediately hooked. </p><p>I took MOOCs, networked with people in the industry, and eventually joined a non-profit group of analysts working with NWSL and national teams with real data from top providers like StatsBomb, Tracab, Opta.</p><p>Then I expanded into data science and machine learning applied to business. This expertise helped me land my first tech role at an AI consultancy, working on health projects and speech recognition. </p><p>Along the way, LLMs and RAGs came into the picture, and I started applying all of it to the projects I was already building.</p><p>At every step, someone raised an eyebrow.</p><p><em>Why tech? You are a doctor. Why football? You&#8217;re a doctor in tech. </em></p><p>I never had a clean answer, but I knew I was shaping the foundations of my identity. </p><p>At some point I got honest with myself about where I actually stood. I listed the gaps in my foundations: systems thinking, engineering depth, the ability to build things that work in production and not just in a notebook.</p><p>So I looked back at my background as my advantage and started building from it.</p><p>I had: </p><ul><li><p>A medical mindset </p></li><li><p>Data/AI engineering foundations </p></li><li><p>Football domain knowledge </p></li><li><p>AI tools to help me build and mix all of these. </p></li></ul><p>That led me to create my own Venn diagram intersection.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!nVLs!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee549504-5888-47ed-a9c7-cd26bc607355_1500x900.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nVLs!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee549504-5888-47ed-a9c7-cd26bc607355_1500x900.heic 424w, https://substackcdn.com/image/fetch/$s_!nVLs!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee549504-5888-47ed-a9c7-cd26bc607355_1500x900.heic 848w, https://substackcdn.com/image/fetch/$s_!nVLs!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee549504-5888-47ed-a9c7-cd26bc607355_1500x900.heic 1272w, https://substackcdn.com/image/fetch/$s_!nVLs!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee549504-5888-47ed-a9c7-cd26bc607355_1500x900.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!nVLs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee549504-5888-47ed-a9c7-cd26bc607355_1500x900.heic" width="1456" height="874" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ee549504-5888-47ed-a9c7-cd26bc607355_1500x900.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:874,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:22688,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/188697676?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee549504-5888-47ed-a9c7-cd26bc607355_1500x900.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!nVLs!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee549504-5888-47ed-a9c7-cd26bc607355_1500x900.heic 424w, https://substackcdn.com/image/fetch/$s_!nVLs!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee549504-5888-47ed-a9c7-cd26bc607355_1500x900.heic 848w, https://substackcdn.com/image/fetch/$s_!nVLs!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee549504-5888-47ed-a9c7-cd26bc607355_1500x900.heic 1272w, https://substackcdn.com/image/fetch/$s_!nVLs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee549504-5888-47ed-a9c7-cd26bc607355_1500x900.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Image by Claude</figcaption></figure></div><p>That&#8217;s Koe&#8217;s point when he says <em>you are the niche</em>. </p><p>Most people spend their careers searching for an external niche to fit into (I&#8217;ve been guilty of that too). But your specific combination of experience and context it&#8217;s already a niche. You're standing in it.</p><p>A couple of days ago on a Saturday night, I was building my football RAG system (a project that&#8217;s teaching a lot on engineering foundations), and I lost track of time. I ended working from 9pm to 3am. It felt like craft and I think that&#8217;s what happens when you stop fighting your weird path and start building from it. </p><h4>Mapping Your Own Stack</h4><p>Some self-awareness is necessary here to understand how to mix your skills, (might sound like a self help book advice but trust me, you need to sit with yourself on this). I want to give you something I didn&#8217;t have at the beginning of my journey: a starting point. </p><p>Start by asking yourself these three questions. Note them down on a notepad, Notion, or somewhere else you can easily go back to:</p><ul><li><p><strong>Is there something you know that most people in your field don&#8217;t?</strong> Something specific rather than general. What context do you bring that wasn&#8217;t in the job description?</p></li><li><p><strong>Where do your interests converge?</strong> The things you read on weekends, the problems you notice in one domain that nobody there is thinking about because they don&#8217;t have your other domain to compare it to.</p></li><li><p><strong>What can you build to work at the intersection of it?</strong> Think in projects, tools, analyses, newsletters. Something concrete that only you could have built from exactly where you&#8217;re standing.</p></li><li><p>An extra: <strong>How can you leverage the use of AI to boost your skills?</strong> </p></li></ul><p>I would start from there. </p><h4>May The Weird Ones Prevail</h4><p>We now know the system was not designed for this but AI is compressing the value of standard skills faster than most people are ready for. </p><p>What it can&#8217;t compress is taste, context, and the specific lens you&#8217;ve built from an unusual combination of experiences.</p><p>The people who do well in what&#8217;s coming won&#8217;t be the deepest specialists or the broadest generalists.</p><p>They&#8217;ll be the ones who can see across domains, connect things that shouldn&#8217;t logically connect, and build things that require a very specific, very strange set of keys to unlock.</p><p>Your weirdness is your moat. </p><div><hr></div><p>This newsletter is about building AI systems, using football analytics as the sandbox. But every now and then it's worth stepping back to talk about why we build what we build, and how we decide what's worth building next.</p><p>Till next time, </p><p>Ricardo. </p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share The Underdoc&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://ricardoheredia.substack.com/?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share The Underdoc</span></a></p><p></p><p></p><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Shipping a RAG System App to HF Spaces with Gradio]]></title><description><![CDATA[Building the GUI for the end user and next steps to scale this]]></description><link>https://ricardoheredia.substack.com/p/shipping-a-rag-system-app-to-hf-spaces</link><guid isPermaLink="false">https://ricardoheredia.substack.com/p/shipping-a-rag-system-app-to-hf-spaces</guid><dc:creator><![CDATA[Ricardo Heredia]]></dc:creator><pubDate>Tue, 10 Feb 2026 07:02:47 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Avxv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5aaee7f9-6ecd-45dd-9488-62f4f9164e45_2816x1536.heic" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This is the last article from the series: <a href="https://substack.com/@theunderdoc/p-182493528">Building a RAG System That Generates Football Post-Match Tactical Reports Automatically</a></p><p>In previous articles we&#8217;ve covered: </p><ul><li><p>Engineering the data pipeline: <a href="https://ricardoheredia.substack.com/p/rag-is-a-data-engineering-heavy-problem?r=56fjux">RAG is a Data Engineering Heavy Problem: Building a Football ETL for AI</a></p></li><li><p>Evaluating the prompt and system outputs with EDD: <a href="https://ricardoheredia.substack.com/p/from-vibes-to-metrics-how-i-evaluated">From Vibes to Metrics: How I Evaluated A Football RAG System</a></p></li></ul><p>Today I&#8217;ll be talking about the challenges of designing a user interface to interact with in an effort to make it as comfortable as possible. </p><p>This marks the end of these series on how I&#8217;ve built this MVP, which I&#8217;m scaling into an automated data platform that generates football post match reports and can run on your own computer.</p><p>You can find the entire code on the GitHub repository and the new releases: <a href="https://github.com/ricardoherediaj/football-rag-intelligence">Football RAG Intelligence</a></p><h3>What&#8217;s Gradio and Why I Chose it</h3><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6njm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc1526f7-e17c-4a82-a4dc-6e91c3750462_600x161.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6njm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc1526f7-e17c-4a82-a4dc-6e91c3750462_600x161.jpeg 424w, https://substackcdn.com/image/fetch/$s_!6njm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc1526f7-e17c-4a82-a4dc-6e91c3750462_600x161.jpeg 848w, https://substackcdn.com/image/fetch/$s_!6njm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc1526f7-e17c-4a82-a4dc-6e91c3750462_600x161.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!6njm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc1526f7-e17c-4a82-a4dc-6e91c3750462_600x161.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6njm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc1526f7-e17c-4a82-a4dc-6e91c3750462_600x161.jpeg" width="600" height="161" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cc1526f7-e17c-4a82-a4dc-6e91c3750462_600x161.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:161,&quot;width&quot;:600,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:18498,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/187177098?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce81acd5-6d1a-4477-8a50-842dd3ab8255_600x600.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!6njm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc1526f7-e17c-4a82-a4dc-6e91c3750462_600x161.jpeg 424w, https://substackcdn.com/image/fetch/$s_!6njm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc1526f7-e17c-4a82-a4dc-6e91c3750462_600x161.jpeg 848w, https://substackcdn.com/image/fetch/$s_!6njm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc1526f7-e17c-4a82-a4dc-6e91c3750462_600x161.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!6njm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc1526f7-e17c-4a82-a4dc-6e91c3750462_600x161.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><p>If you haven&#8217;t heard of it already, Gradio is an open-source Python framework that allows developers to quickly build and deploy interactive web interfaces for ML models and data pipelines. </p><p>In the context of the Football RAG platform, I used it as a lightweight presentation layer to connect the user to all the backend logic (pipelines, LLM orchestration). </p><p>At this stage of development, the goal was to keep it simple. I chose Gradio over Streamlit for these reasons:</p><ul><li><p>Avoid rerunning the script each time there&#8217;s retrieval. </p></li><li><p><strong>API capabilities</strong>: Gradio automatically generates a REST API for your interface, making it easier to treat the UI as modular rather than a monolith.</p></li><li><p><strong>LLM Integration</strong>: Gradio&#8217;s <code>ChatInterface</code> component is purpose-built for the conversational nature of RAG, allowing me to focus on prompt<strong> </strong>optimization rather than building widgets.</p></li><li><p><strong>Fast iteration</strong>: working with 108 matches, it allowed for a full database rebuild and UI refresh in seconds.</p></li></ul><p>Although in the future I could move to another frontend, this was enough to validate the idea. </p><h3>HuggingFace Spaces Deployment</h3><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GKF_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6b8f7ff-ab4a-4809-8b34-33cba36edda6_1280x720.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GKF_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6b8f7ff-ab4a-4809-8b34-33cba36edda6_1280x720.heic 424w, https://substackcdn.com/image/fetch/$s_!GKF_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6b8f7ff-ab4a-4809-8b34-33cba36edda6_1280x720.heic 848w, https://substackcdn.com/image/fetch/$s_!GKF_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6b8f7ff-ab4a-4809-8b34-33cba36edda6_1280x720.heic 1272w, https://substackcdn.com/image/fetch/$s_!GKF_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6b8f7ff-ab4a-4809-8b34-33cba36edda6_1280x720.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GKF_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6b8f7ff-ab4a-4809-8b34-33cba36edda6_1280x720.heic" width="608" height="342" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d6b8f7ff-ab4a-4809-8b34-33cba36edda6_1280x720.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:720,&quot;width&quot;:1280,&quot;resizeWidth&quot;:608,&quot;bytes&quot;:19707,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/187177098?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6b8f7ff-ab4a-4809-8b34-33cba36edda6_1280x720.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!GKF_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6b8f7ff-ab4a-4809-8b34-33cba36edda6_1280x720.heic 424w, https://substackcdn.com/image/fetch/$s_!GKF_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6b8f7ff-ab4a-4809-8b34-33cba36edda6_1280x720.heic 848w, https://substackcdn.com/image/fetch/$s_!GKF_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6b8f7ff-ab4a-4809-8b34-33cba36edda6_1280x720.heic 1272w, https://substackcdn.com/image/fetch/$s_!GKF_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6b8f7ff-ab4a-4809-8b34-33cba36edda6_1280x720.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The simplest way to host an AI/ML demo without becoming a full-time DevOps engineer was a using HuggingFace Spaces.</p><p>It&#8217;s basically a managed hosting service where you can drop your Gradio app. </p><p>Some characteristics: </p><ul><li><p><strong>GitHub-Style Deployment:</strong> You push your code to a repository, and Spaces automatically builds the container and serves the app to a public URL.</p></li><li><p><strong>Seamless Integration:</strong> Since it&#8217;s natively built for the ecosystem, it handles the Gradio environment and Python dependencies out of the box.</p></li><li><p><strong>Free Tier:</strong> It provided the perfect &#8220;sandbox&#8221; for the MVP, giving me a URL to share it publicly using generous CPU compute.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ryxo!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9163375-7bd3-453d-8863-6bdda6f3c936_2870x1634.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ryxo!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9163375-7bd3-453d-8863-6bdda6f3c936_2870x1634.heic 424w, https://substackcdn.com/image/fetch/$s_!ryxo!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9163375-7bd3-453d-8863-6bdda6f3c936_2870x1634.heic 848w, https://substackcdn.com/image/fetch/$s_!ryxo!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9163375-7bd3-453d-8863-6bdda6f3c936_2870x1634.heic 1272w, https://substackcdn.com/image/fetch/$s_!ryxo!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9163375-7bd3-453d-8863-6bdda6f3c936_2870x1634.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ryxo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9163375-7bd3-453d-8863-6bdda6f3c936_2870x1634.heic" width="692" height="394.00274725274727" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b9163375-7bd3-453d-8863-6bdda6f3c936_2870x1634.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:829,&quot;width&quot;:1456,&quot;resizeWidth&quot;:692,&quot;bytes&quot;:248575,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/187177098?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9163375-7bd3-453d-8863-6bdda6f3c936_2870x1634.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ryxo!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9163375-7bd3-453d-8863-6bdda6f3c936_2870x1634.heic 424w, https://substackcdn.com/image/fetch/$s_!ryxo!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9163375-7bd3-453d-8863-6bdda6f3c936_2870x1634.heic 848w, https://substackcdn.com/image/fetch/$s_!ryxo!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9163375-7bd3-453d-8863-6bdda6f3c936_2870x1634.heic 1272w, https://substackcdn.com/image/fetch/$s_!ryxo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9163375-7bd3-453d-8863-6bdda6f3c936_2870x1634.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h4>A Reality Check: MVP vs. Production</h4><p>Grado helped to build the UI easily, but making it "industrial-grade" meant facing a few technical issues.</p><h5>1. Deployment Binary Bug</h5><p>I hit a snag where the specific binaries for my vector store behaved differently on Mac vs. the Linux environment in Spaces. </p><p>Standardizing with <strong>uv</strong> and clean lockfiles was the way out.</p><h5>2. The $0 Intent Routing Trick:</h5><p>Saving tokens was necessary from the beginning, so I built a <strong>Smart Router</strong>:</p><ul><li><p><strong>Questions</strong> like &#8220;How did this team play?&#8221; or &#8220;Why did this team had X metric during that match?&#8221; &#8594; It goes to the LLM for tactical analysis.</p></li><li><p><strong>Visualization commands</strong> like &#8220;Show passing network plot from the match&#8221; &#8594; These bypass the LLM and trigger my Matplotlib visualizers at zero cost. </p></li></ul><h5>The "Airlock" ETL</h5><p>Talked about this in previous matches but decoupling the ingestion from the UI helped me caught data bugs like a "Home/Away swap" that was messing up team stats before they reached the user.</p><p>Here&#8217;s how the frontend looks for now in HF Spaces: </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xVFA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8d3520e-cc6e-4183-bc3f-013353e06dee_2880x1700.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xVFA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8d3520e-cc6e-4183-bc3f-013353e06dee_2880x1700.heic 424w, https://substackcdn.com/image/fetch/$s_!xVFA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8d3520e-cc6e-4183-bc3f-013353e06dee_2880x1700.heic 848w, https://substackcdn.com/image/fetch/$s_!xVFA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8d3520e-cc6e-4183-bc3f-013353e06dee_2880x1700.heic 1272w, https://substackcdn.com/image/fetch/$s_!xVFA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8d3520e-cc6e-4183-bc3f-013353e06dee_2880x1700.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xVFA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8d3520e-cc6e-4183-bc3f-013353e06dee_2880x1700.heic" width="1456" height="859" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d8d3520e-cc6e-4183-bc3f-013353e06dee_2880x1700.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:859,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:188624,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/187177098?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8d3520e-cc6e-4183-bc3f-013353e06dee_2880x1700.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!xVFA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8d3520e-cc6e-4183-bc3f-013353e06dee_2880x1700.heic 424w, https://substackcdn.com/image/fetch/$s_!xVFA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8d3520e-cc6e-4183-bc3f-013353e06dee_2880x1700.heic 848w, https://substackcdn.com/image/fetch/$s_!xVFA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8d3520e-cc6e-4183-bc3f-013353e06dee_2880x1700.heic 1272w, https://substackcdn.com/image/fetch/$s_!xVFA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8d3520e-cc6e-4183-bc3f-013353e06dee_2880x1700.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ZC4K!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43d750c0-f25d-47b8-8dfd-f1c36fdc9efb_2876x1686.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ZC4K!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43d750c0-f25d-47b8-8dfd-f1c36fdc9efb_2876x1686.heic 424w, https://substackcdn.com/image/fetch/$s_!ZC4K!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43d750c0-f25d-47b8-8dfd-f1c36fdc9efb_2876x1686.heic 848w, https://substackcdn.com/image/fetch/$s_!ZC4K!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43d750c0-f25d-47b8-8dfd-f1c36fdc9efb_2876x1686.heic 1272w, https://substackcdn.com/image/fetch/$s_!ZC4K!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43d750c0-f25d-47b8-8dfd-f1c36fdc9efb_2876x1686.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ZC4K!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43d750c0-f25d-47b8-8dfd-f1c36fdc9efb_2876x1686.heic" width="1456" height="854" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/43d750c0-f25d-47b8-8dfd-f1c36fdc9efb_2876x1686.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:854,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:241478,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/187177098?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43d750c0-f25d-47b8-8dfd-f1c36fdc9efb_2876x1686.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ZC4K!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43d750c0-f25d-47b8-8dfd-f1c36fdc9efb_2876x1686.heic 424w, https://substackcdn.com/image/fetch/$s_!ZC4K!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43d750c0-f25d-47b8-8dfd-f1c36fdc9efb_2876x1686.heic 848w, https://substackcdn.com/image/fetch/$s_!ZC4K!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43d750c0-f25d-47b8-8dfd-f1c36fdc9efb_2876x1686.heic 1272w, https://substackcdn.com/image/fetch/$s_!ZC4K!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43d750c0-f25d-47b8-8dfd-f1c36fdc9efb_2876x1686.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3>Lesson Learned</h3><p>The biggest takeaway from building this GUI and deploying the MVP is:</p><p><strong> 90% is Data Engineering, and the AI part is just the tip.</strong></p><p>You need to provide a well crafted plumbing so the system does meaningful retrieval and the user, through a comfortable UI can obtain valuable information. </p><p>Precalculating everything (compute 38 tactical metrics during ETL) helps for instant retrieval.</p><p>Validate with data contracts before moving the data forward (Pydantic)</p><p>Keeping it simple for the GUI, for quick adoption. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Avxv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5aaee7f9-6ecd-45dd-9488-62f4f9164e45_2816x1536.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Avxv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5aaee7f9-6ecd-45dd-9488-62f4f9164e45_2816x1536.heic 424w, https://substackcdn.com/image/fetch/$s_!Avxv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5aaee7f9-6ecd-45dd-9488-62f4f9164e45_2816x1536.heic 848w, https://substackcdn.com/image/fetch/$s_!Avxv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5aaee7f9-6ecd-45dd-9488-62f4f9164e45_2816x1536.heic 1272w, https://substackcdn.com/image/fetch/$s_!Avxv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5aaee7f9-6ecd-45dd-9488-62f4f9164e45_2816x1536.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Avxv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5aaee7f9-6ecd-45dd-9488-62f4f9164e45_2816x1536.heic" width="1456" height="794" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5aaee7f9-6ecd-45dd-9488-62f4f9164e45_2816x1536.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:794,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:438592,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/187177098?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5aaee7f9-6ecd-45dd-9488-62f4f9164e45_2816x1536.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Avxv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5aaee7f9-6ecd-45dd-9488-62f4f9164e45_2816x1536.heic 424w, https://substackcdn.com/image/fetch/$s_!Avxv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5aaee7f9-6ecd-45dd-9488-62f4f9164e45_2816x1536.heic 848w, https://substackcdn.com/image/fetch/$s_!Avxv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5aaee7f9-6ecd-45dd-9488-62f4f9164e45_2816x1536.heic 1272w, https://substackcdn.com/image/fetch/$s_!Avxv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5aaee7f9-6ecd-45dd-9488-62f4f9164e45_2816x1536.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Final Architecture</figcaption></figure></div><h3>What&#8217;s Next?</h3><p>Now that the demo is live and the concept is validated, I&#8217;m scaling from 108 matches to 1,000+. </p><p>I&#8217;ll be documenting that journey. In the next series we&#8217;re talking about moving to a proper infrastructure: </p><ul><li><p><strong>MinIO</strong> for object storage (S3-compatible, runs locally)</p></li><li><p>Dagster orchestrating the pipelines </p></li><li><p>dbt + DuckDB handling the analytical workloads. </p></li><li><p>Everything on-premise with Docker services </p></li><li><p>Modal free tier for serverless LLM inference on cloud GPU<strong>s.</strong></p></li></ul><p>The goal: </p><blockquote><p>An automated data platform that generates post-match tactical reports for any match, running entirely on your own machine, with cheap cloud costs for the heavy lifting.</p></blockquote><p>If you&#8217;ve been following along, you now have a blueprint for building a working RAG system with documented engineering decisions.</p><p>The next series starts soon.</p><p>If there&#8217;s a specific part of the architecture you want me to dig deeper into, please let me know in the comments.</p><div><hr></div><p><strong>Check out the code:</strong> <a href="link">Football RAG Intelligence GitHub Repository</a></p><p><strong>Try the live demo:</strong> <a href="link">HuggingFace Spaces</a></p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Underdoc! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>Thanks for reading till the end.</p><p>See you next time,</p><p>Ricardo. </p><p></p>]]></content:encoded></item><item><title><![CDATA[From Vibes to Metrics: How I Evaluated A Football RAG System]]></title><description><![CDATA[Before I started building this project, my initial workflow for creating post match reports was based in pure vibes.]]></description><link>https://ricardoheredia.substack.com/p/from-vibes-to-metrics-how-i-evaluated</link><guid isPermaLink="false">https://ricardoheredia.substack.com/p/from-vibes-to-metrics-how-i-evaluated</guid><dc:creator><![CDATA[Ricardo Heredia]]></dc:creator><pubDate>Fri, 30 Jan 2026 12:12:36 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/d42ac607-f2d5-4708-9d8f-3826bab28cd7_2816x1536.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Before I started building this project, my initial workflow for creating post match reports was based in pure vibes. </p><p>I would write a massive prompt, ask the LLM to analyze a match, read the response, and think, <em>&#8220;good enough.&#8221;</em> </p><p>This approach is not bad at the beginning, but if you want a <strong>successful </strong>system that generates trustworthy outputs, they should be evaluated from beginning to end both subjectively and <strong>objectively</strong>. </p><h3>Moving to EDD</h3><p>After reviewing different approaches, I adopted the <strong>Evaluation Driven Development (EDD)</strong>, a methodology discussed by <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Hugo Bowne-Anderson&quot;,&quot;id&quot;:63978139,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!_vkH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F941a1d5e-0a5f-45f8-8400-737c0bf9f85d_400x400.jpeg&quot;,&quot;uuid&quot;:&quot;8dc72fc6-cd6b-483e-b334-addb6f8eb64f&quot;}" data-component-name="MentionToDOM"></span> in <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Decoding AI Magazine&quot;,&quot;id&quot;:1526003,&quot;type&quot;:&quot;pub&quot;,&quot;url&quot;:&quot;https://open.substack.com/pub/decodingml&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/00bc74e0-3601-49ce-8ab9-4c7b499ce597_1280x1280.png&quot;,&quot;uuid&quot;:&quot;1b8b5fa9-23be-40b2-a76f-d81306ea5c00&quot;}" data-component-name="MentionToDOM"></span> article <a href="https://www.decodingai.com/p/escaping-poc-purgatory-evaluation">Escaping POC Purgatory: Evaluation-Driven Development for AI Systems</a>. </p><p>Where the core philosophy is: </p><blockquote><p><em><strong>You cannot optimize what you cannot measure</strong></em></p></blockquote><p>So instead of treating evaluation as a final step, you build the test harness <em>before</em> you finish building the system.</p><p>I&#8217;ll walk you through thow I used EDD to engineer my prompts in three steps:</p><ol><li><p><strong>The Metrics:</strong> Why I chose <strong>Retrieval Accuracy</strong>, <strong>Faithfulness</strong>, and <strong>Tactical Insights </strong>rules<strong>.</strong></p></li><li><p><strong>The Optimization Loop:</strong> Moving from <strong>Prompt V1.0</strong> (1800 tokens, slower, and a bit more expensive) to <strong>Prompt V3.5</strong> (360 tokens, more precise to what I wanted).</p></li><li><p><strong>The Results:</strong> Critical bugs caught at the beginning.</p></li></ol><h3>Golden Answers</h3><p>In my <a href="https://www.google.com/search?q=LINK_TO_PREVIOUS_ARTICLE">previous article</a>, I broke down how I built the <strong>Golden Dataset</strong> (<code>matches_gold.json</code>) since it&#8217;s crucial to understand <em>why</em> that dataset exists in the context of evaluation.</p><p>In standard software engineering, you write unit tests based on expected inputs and outputs, that&#8217;s the traditional software development lifecycle (SDLC). </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!y4vU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f89465-43be-4c95-b126-3e350ad77ddd_1600x638.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!y4vU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f89465-43be-4c95-b126-3e350ad77ddd_1600x638.png 424w, https://substackcdn.com/image/fetch/$s_!y4vU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f89465-43be-4c95-b126-3e350ad77ddd_1600x638.png 848w, https://substackcdn.com/image/fetch/$s_!y4vU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f89465-43be-4c95-b126-3e350ad77ddd_1600x638.png 1272w, https://substackcdn.com/image/fetch/$s_!y4vU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f89465-43be-4c95-b126-3e350ad77ddd_1600x638.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!y4vU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f89465-43be-4c95-b126-3e350ad77ddd_1600x638.png" width="611" height="243.8125" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/31f89465-43be-4c95-b126-3e350ad77ddd_1600x638.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:581,&quot;width&quot;:1456,&quot;resizeWidth&quot;:611,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!y4vU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f89465-43be-4c95-b126-3e350ad77ddd_1600x638.png 424w, https://substackcdn.com/image/fetch/$s_!y4vU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f89465-43be-4c95-b126-3e350ad77ddd_1600x638.png 848w, https://substackcdn.com/image/fetch/$s_!y4vU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f89465-43be-4c95-b126-3e350ad77ddd_1600x638.png 1272w, https://substackcdn.com/image/fetch/$s_!y4vU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31f89465-43be-4c95-b126-3e350ad77ddd_1600x638.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Traditional software development: linear, testable, predictable. <a href="https://www.decodingai.com/p/escaping-poc-purgatory-evaluation">Escaping POC Purgatory: Evaluation-Driven Development for AI Systems</a>. </figcaption></figure></div><p>When working with LLMs, defining &#8220;expected output&#8221; is harder because these models are non-deterministic, meaning you can give an LLM the same input and get two different outputs. </p><p>This leads to a more dynamic process through the entire GenAI application lifecycle. More iterations during your development and your way to production. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vDEK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bb1996b-b4a1-48a9-be8c-01fb5d521ca0_1600x763.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vDEK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bb1996b-b4a1-48a9-be8c-01fb5d521ca0_1600x763.png 424w, https://substackcdn.com/image/fetch/$s_!vDEK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bb1996b-b4a1-48a9-be8c-01fb5d521ca0_1600x763.png 848w, https://substackcdn.com/image/fetch/$s_!vDEK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bb1996b-b4a1-48a9-be8c-01fb5d521ca0_1600x763.png 1272w, https://substackcdn.com/image/fetch/$s_!vDEK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bb1996b-b4a1-48a9-be8c-01fb5d521ca0_1600x763.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!vDEK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bb1996b-b4a1-48a9-be8c-01fb5d521ca0_1600x763.png" width="624" height="297.42857142857144" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6bb1996b-b4a1-48a9-be8c-01fb5d521ca0_1600x763.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:694,&quot;width&quot;:1456,&quot;resizeWidth&quot;:624,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!vDEK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bb1996b-b4a1-48a9-be8c-01fb5d521ca0_1600x763.png 424w, https://substackcdn.com/image/fetch/$s_!vDEK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bb1996b-b4a1-48a9-be8c-01fb5d521ca0_1600x763.png 848w, https://substackcdn.com/image/fetch/$s_!vDEK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bb1996b-b4a1-48a9-be8c-01fb5d521ca0_1600x763.png 1272w, https://substackcdn.com/image/fetch/$s_!vDEK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bb1996b-b4a1-48a9-be8c-01fb5d521ca0_1600x763.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Evaluation &amp; Monitoring are part of the process since day one. <a href="https://www.decodingai.com/p/escaping-poc-purgatory-evaluation">Escaping POC Purgatory: Evaluation-Driven Development for AI Systems</a>. </figcaption></figure></div><p>In order to battle with that non-deterministic nature, I wanted to grade the system responses. See if they matched with the answers I was expecting. </p><p>That meant combining football knowledge with technology capabilities and creating a &#8220;Source of Truth&#8221; that I trusted 100% &#8594; <strong>The</strong> <strong>Golden Dataset</strong>. A ground truth that acts as the teacher&#8217;s answer key, containing the exact stats (validated by Pydantic before) for every match.</p><p>Without this, I would be just guessing and depending entirely on the LLM&#8217;s capacity.</p><p>Now that I had the answer key in hand, I needed a way to automate the grading of the system.</p><h3>The Judge: A 3-Metric Framework</h3><p>Since human evaluation doesn't go that far as LLM can, I adopted the "LLM-as-a-Judge" methodology. In the book <em>AI Engineering</em>, Chip Huyen identifies the AI judge as:</p><blockquote><p>A critical evaluation method, noting its specific utility in measuring complex metrics such as the "factual consistency between the response and the whole context&#8221;. (Huyen, 2024).</p></blockquote><p>By implementing this, we can automate the evaluation without only relying on manual review.</p><p>The evaluation harness uses the <strong>LLM-as-a-Judge</strong> pattern:</p><ol><li><p><strong>The Analyst:</strong> Claude 3 Haiku (Fast, Cheap ~$0.0001 per query) generates the report. It's optimized for speed but since speed comes with trade-offs, Haiku can occasionally miss nuances or hallucinate stats.</p></li><li><p><strong>The Judge:</strong> Claude 3.5 Sonnet (Stronger, Slower) grades the report. It catches these issues. It's slower and more expensive, but it only runs during evaluation, not intended for production. This means I can test rigorously without blowing my API budget. </p></li></ol><p>Why Anthropic's models? Honestly, I had a remaining balance there from previous experiments and wanted to blow them away. But I could have used Gemini, OpenAI, whatever. You can use any other "bigger" model for this, even a local one with Ollama.</p><h4>The 3-Metric System</h4><p>However, I needed to know why a report failed. If it was hallucination or did it ignore the charts or any other relevant part?</p><p>The evaluation framework measures three dimensions:</p><p><strong>1. Retrieval Accuracy (30%)</strong> - Did we find the right match?</p><p>Early on, I noticed reports would analyze the wrong match or mix up team stats. The system would retrieve &#8220;Ajax vs. Heracles&#8221; when I asked about &#8220;Ajax vs. Telstar.&#8221; (I&#8217;ll show you an error like this at the end).</p><p>This metric uses metadata filtering to verify the system found the exact match requested. It&#8217;s deterministic in a way so either it got the right match (100%) or it didn&#8217;t (0%). </p><p><strong>Evaluation Result: 100%</strong> &#9989;</p><p><strong>2. Faithfulness (30%)</strong> - Are the numbers accurate?</p><p>This is the guardrail preventing &#8220;hallucinations&#8221; where the model invents stats. </p><p>Early reports claiming &#8220;Ajax had 73% possession&#8221; when the actual number was 64.3%. Or &#8220;Player #14 made 28 passes&#8221; when it was 23.</p><p>The judge uses regex to extract every number from the report, then cross-checks it against <code>matches_gold.json</code>. Any number not in the source data = hallucination = failed faithfulness check.</p><p><strong>Evaluation Result: 99.4%</strong> &#9989;</p><p><strong>3. Tactical Insight (40%)</strong> - Is the analysis tactically sound?</p><p>I broke it into four measurable components:</p><ul><li><p><strong>Specificity (10%)</strong>: Does it cite concrete evidence? Counts specific references like player IDs, exact percentages, tactical metrics. </p></li><li><p><strong>Visual Grounding (10%)</strong>: Does it reference what&#8217;s actually in the visualizations? Reports should mention &#8220;The Passing Network shows Player #14 as the hub&#8221; and not just a generic commentary. This forces the system to tie text to visuals.</p></li><li><p><strong>Terminology (10%)</strong>: Does it use correct football language? The judge verifies terms against <code>tactical_rules.py</code> (e.g., &#8220;Field Tilt,&#8221; &#8220;Progressive Passes,&#8221; &#8220;PPDA,&#8221; &#8220;Verticality&#8221;) to avoid generic concepts</p></li><li><p><strong>Relevance (10%)</strong>: Does it answer the user&#8217;s actual question? If someone asks about pressing strategy, then the response shouldn&#8217;t be about passing accuracy.</p></li></ul><p>A report can be factually accurate (Faithfulness = 100%) but tactically shallow (Tactical Insight = 40%). </p><p><strong>Evaluation Result: 95.0%</strong> &#9989;</p><h4>Codifying "Vibes" into Rules</h4><p>This question was also bugging me from the start: &#8220;How do you mathematically prove a report is tactically sound?&#8221; </p><p>Since what I&#8217;m trying to do there is translating stats and tactical dashboards from post match analyses into explainable text, I couldn't let the LLM guess what the stats meant. </p><p>I had to define a way of teaching the system the coordinates used in the WhoScored and Fotmob data, how they are calculated, and displayed in the field visualizations with the mplsoccer library. </p><p>So, I built a file called <code>tactical_rules.py</code> that reverse-engineers the visualizations into text logic.</p><p>For example, I defined <strong>Verticality</strong> thresholds explicitly:</p><pre><code>def interpret_verticality(verticality: float) -&gt; str:
    if verticality &gt; 50:
        return "direct vertical passing - quick transitions"
    elif verticality &gt; 35:
        return "balanced build-up"
    else:
        return "patient possession-based build-up"</code></pre><ul><li><p><strong>Scenario:</strong> Ajax has a verticality of <strong>72%</strong>.</p></li><li><p><strong>Bad Output:</strong> &#8220;Ajax played patiently.&#8221; (Judge fails this: 72% &gt; 50%, so it <em>must</em> be direct).</p></li><li><p><strong>Good Output:</strong> &#8220;Ajax played a direct game with quick transitions.&#8221; (Judge passes this).</p></li></ul><p>If Ajax has 72% verticality and the report says "patient build-up," is a vague description. The judge verifies those numbers exist and it checks if the tactical language matches what <code>tactical_rules.py</code> says those numbers should mean.</p><p>Think of `tactical_rules.py` as the rubric, and the judge as the grader applying it.</p><p>Of course, in the future this can change depending on what rules you want to add or readapt. This was a first attempt of contributing to the evaluation harness trustworthiness.</p><h4>The Weighted Scoring Rubric</h4><p>To bring it all together, I created a weighted rubric that scores every generated report on a 10-point scale.</p><pre><code>Weighted Score = (Retrieval &#215; 0.30) + (Faithfulness &#215; 0.30) + (Specificity &#215; 0.15) + (Visual Grounding &#215; 0.15) + (Terminology &#215; 0.15) + (Relevance &#215; 0.15) + (Conciseness &#215; 0.10) </code></pre><p><strong>A report must score &#8805; 7.0/10 to be considered production-ready.</strong></p><h4>Scoring Examples: A Good Analysis But Wrong Retrieval</h4><p>Here's where evaluation gets interesting. Sometimes the system produces excellent tactical analysis but for the wrong match.</p><p><strong>What I asked:</strong> &#8220;Analyse Feyenoord vs Ajax match&#8221;</p><p><strong>What the system retrieved:</strong> Feyenoord vs FC Volendam</p><p><strong>Report Generated:</strong></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!eCy_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c0c9470-b97c-4e71-8c3b-29e9f90e4993_2880x1700.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!eCy_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c0c9470-b97c-4e71-8c3b-29e9f90e4993_2880x1700.png 424w, https://substackcdn.com/image/fetch/$s_!eCy_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c0c9470-b97c-4e71-8c3b-29e9f90e4993_2880x1700.png 848w, https://substackcdn.com/image/fetch/$s_!eCy_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c0c9470-b97c-4e71-8c3b-29e9f90e4993_2880x1700.png 1272w, https://substackcdn.com/image/fetch/$s_!eCy_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c0c9470-b97c-4e71-8c3b-29e9f90e4993_2880x1700.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!eCy_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c0c9470-b97c-4e71-8c3b-29e9f90e4993_2880x1700.png" width="725" height="427.7300824175824" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6c0c9470-b97c-4e71-8c3b-29e9f90e4993_2880x1700.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:859,&quot;width&quot;:1456,&quot;resizeWidth&quot;:725,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Text Analysis&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Text Analysis" title="Text Analysis" srcset="https://substackcdn.com/image/fetch/$s_!eCy_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c0c9470-b97c-4e71-8c3b-29e9f90e4993_2880x1700.png 424w, https://substackcdn.com/image/fetch/$s_!eCy_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c0c9470-b97c-4e71-8c3b-29e9f90e4993_2880x1700.png 848w, https://substackcdn.com/image/fetch/$s_!eCy_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c0c9470-b97c-4e71-8c3b-29e9f90e4993_2880x1700.png 1272w, https://substackcdn.com/image/fetch/$s_!eCy_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c0c9470-b97c-4e71-8c3b-29e9f90e4993_2880x1700.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Here's what the system actually returned (screenshot from the live demo).</figcaption></figure></div><p>That might be too small to read, here&#8217;s the answer: </p><p>&#8220;<strong>Match Overview</strong>: Feyenoord demonstrated superior territorial dominance with a significantly higher average team position (62.4m vs 33.9m). The home team&#8217;s lower PPDA of 9.2 indicated more aggressive pressing compared to Volendam&#8217;s 15.36, suggesting consistent offensive pressure and a controlled possession strategy.</p><p><strong>xG &amp; Shot Efficiency</strong>: Feyenoord generated substantially higher shot volume and quality, with 37 shots generating 4.82 xG versus Volendam&#8217;s 9 shots and 0.83 xG. The significant xG differential suggests consistent high-quality chance creation, with each Feyenoord shot averaging approximately 0.13 xG compared to Volendam&#8217;s 0.09 xG per shot.</p><p><strong>Pressing &amp; Progression</strong>: Progressive passing metrics (156 vs 114) reinforced Feyenoord&#8217;s offensive control. High press events (5 vs 3) further illustrated their tactical superiority in disrupting opponent&#8217;s build-up play. The defensive line positioning (13.0m vs 8.6m) confirmed Feyenoord&#8217;s ability to maintain more advanced, proactive defensive structure.</p><p><strong>Key Tactical Insight</strong>: Total pass volume (513 vs 429) combined with superior progressive passing demonstrates Feyenoord&#8217;s systematic approach to ball progression and territorial domination, directly translating into offensive efficiency and match control.&#8220;</p><p><strong>Judge Evaluation:</strong></p><ul><li><p>Retrieval: <strong>0/10</strong> (30%) - <strong>Wrong match retrieved</strong> (asked for Ajax, got Volendam)</p></li><li><p>Faithfulness: 10/10 (30%) - All numbers verified for Feyenoord vs Volendam match</p></li><li><p>Tactical Insight breakdown:</p><ul><li><p>Specificity: 10/10 (15%) - Dense with exact metrics (62.4m, 9.2 PPDA, 4.82 xG, 156 progressive passes)</p></li><li><p>Visual Grounding: 9/10 (15%) - References positional data and tactical patterns</p></li><li><p>Terminology: 10/10 (15%) - Perfect use of PPDA, progressive passes, xG/shot, defensive line</p></li><li><p>Relevance: 10/10 (15%) - Excellent explanation of tactical dominance</p></li></ul></li></ul><p>Conciseness: 10/10 (10%) - 220 words, slightly over but acceptable</p><p><strong>Weighted Final Score: 6.7/10</strong> &#10060; <strong>Failed</strong> </p><p>This is a dangerous type of failure in production systems.</p><p>The analysis is <strong>tactically excellent</strong>. If you only read the commentary, you&#8217;d think the system nailed it.</p><p>But it&#8217;s analyzing the <strong>wrong match</strong>.</p><p>This is<strong> </strong>likely a vector database issue, either the embedding similarity between &#8220;Feyenoord vs Ajax&#8221; and &#8220;Feyenoord vs FC Volendam&#8221; was high enough to return the wrong match, or the metadata filtering didn&#8217;t catch it.</p><p>This example shows why without the retrieval check, this report would score <strong>9.5/10</strong> on analysis quality alone. But it&#8217;s completely useless because it&#8217;s not what the user asked for.</p><p>A coach asking about the Ajax match would make wrong decisions based on Volendam data.</p><p><strong>The fix:</strong> Tighter metadata filtering + explicit team name verification in the retrieval step. This is why <code>matches_gold.json </code>exists, in order to verify we&#8217;re analyzing the exact match that was requested.</p><h4>What Good Evaluation Looks Like and Common Failure Modes</h4><p>When all three dimensions work correctly (right match retrieved, accurate numbers, insightful analysis) the system produces reports that score high &#8805;9.0/10:</p><ul><li><p>Retrieval: 10/10 - Correct match identified</p></li><li><p>Faithfulness: 10/10 - Every number verified against <code>matches_gold.json</code></p></li><li><p>Tactical Insight: 9-10/10 across all four checks (Specificity, Visual Grounding, Terminology, Relevance)</p></li><li><p>Conciseness: 10/10 - Under 200 words (it&#8217;s ok if slightly longer)</p></li></ul><p>The judge validates this automatically across all 108 matches in the dataset, catching failures that manual review would miss.</p><p>That away the system surfaced three failure patterns:</p><ol><li><p>Wrong retrieval: Feyenoord vs Volendam example above &#8594; fix with stricter metadata filtering.</p></li><li><p>Shallow analysis: generic commentary with no specific metrics or insights &#8594; tweaking prompt to emphasize specificity.</p></li><li><p>Hallucinated stats &#8594; catch errors early in the data engineering pipeline. </p></li></ol><h4>Takeaways from this Section</h4><ul><li><p>Turn subjective quality ("does this sound good?") into objective metrics (&#8220;does this score &#8805;7.0/10?&#8220;)</p></li><li><p>Numerical verification + tactical interpretation allows the system to move from "vibes-based development" to evaluation-driven development.</p></li><li><p>A system can sound smart while being completely wrong. This helps you catch errors in an automatic way since the beginning. </p></li></ul><h3>The Prompt Optimization Loop: From 1800 to 360 Tokens</h3><p>With the evaluation harness in place, In parallel I could measure what was actually working.</p><p>I tested prompts in Anthropic Console before touching code. </p><p>Each iteration was scored against the 10-match eval dataset.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!C6Xd!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F762cc7dd-d6c8-4eee-9828-a1c6516c67a9_2866x1500.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!C6Xd!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F762cc7dd-d6c8-4eee-9828-a1c6516c67a9_2866x1500.heic 424w, https://substackcdn.com/image/fetch/$s_!C6Xd!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F762cc7dd-d6c8-4eee-9828-a1c6516c67a9_2866x1500.heic 848w, https://substackcdn.com/image/fetch/$s_!C6Xd!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F762cc7dd-d6c8-4eee-9828-a1c6516c67a9_2866x1500.heic 1272w, https://substackcdn.com/image/fetch/$s_!C6Xd!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F762cc7dd-d6c8-4eee-9828-a1c6516c67a9_2866x1500.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!C6Xd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F762cc7dd-d6c8-4eee-9828-a1c6516c67a9_2866x1500.heic" width="724" height="378.9065934065934" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/762cc7dd-d6c8-4eee-9828-a1c6516c67a9_2866x1500.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:762,&quot;width&quot;:1456,&quot;resizeWidth&quot;:724,&quot;bytes&quot;:335689,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/186174038?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F762cc7dd-d6c8-4eee-9828-a1c6516c67a9_2866x1500.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!C6Xd!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F762cc7dd-d6c8-4eee-9828-a1c6516c67a9_2866x1500.heic 424w, https://substackcdn.com/image/fetch/$s_!C6Xd!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F762cc7dd-d6c8-4eee-9828-a1c6516c67a9_2866x1500.heic 848w, https://substackcdn.com/image/fetch/$s_!C6Xd!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F762cc7dd-d6c8-4eee-9828-a1c6516c67a9_2866x1500.heic 1272w, https://substackcdn.com/image/fetch/$s_!C6Xd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F762cc7dd-d6c8-4eee-9828-a1c6516c67a9_2866x1500.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Claude Console with the winning System Prompt from V3.5. </figcaption></figure></div><p>The evolution of iteration was like this:</p><p><strong>V1.0</strong>: 1800 tokens, 5.0/5.0 quality &#8594; Everything explicit, verbose<br><strong>V2.0</strong>: 800 tokens, 3.2/5.0 quality &#8594; Removed too much, quality tanked<br><strong>V3.0</strong>: 400 tokens, 3.8/5.0 quality &#8594; Added structured sections back<br><strong>V3.5</strong>: 360 tokens, 4.9/5.0 quality &#8594; <strong>Winner</strong></p><p>You can check how I stablished this prompt testing workflow in the repo: <a href="https://github.com/ricardoherediaj/football-rag-intelligence/tree/main/prompts">&#9917; Football RAG Intelligence</a></p><p>The V3.5 version added explicit metric interpretations directly in the prompt like: </p><ul><li><p>&#8220;Lower PPDA = more aggressive pressing&#8221;</p></li><li><p>&#8220;Higher position values = more advanced positioning&#8221;</p></li></ul><p>Also adding the required section headers (Match Overview, xG &amp; Shot Efficiency, Pressing &amp; Progression, Key Tactical Insight).</p><p>And limited constraints in the amount of text generated: &#8220;180-220 words&#8221; instead of just &#8220;be concise.&#8221;</p><p><strong>Result:</strong> 80% token reduction, dropping the cost per query from about $0.0018 to $0.0004.</p><h3>Wrapping Up</h3><p>When building GenAI systems you need to stick to a set of  best practices. I considered this ones:</p><p><strong>Evaluate first optimize later.</strong> I built the judge before iterating with prompts and before creating the vector database, cause I wanted every change measured and every response in consonance with the data I had. </p><p><strong>Prompt-first design pays off.</strong> I designed Prompt V3.5 before building the ChromaDB schema, in an attempt to reduce retrieval-generation mismatch. The ideal scenario is to align the metadata with what the prompt needs.</p><p><strong>Pre-calculate during ingestion.</strong> 38 tactical metrics were computed during ingestion, this helps to make fast rebuilds if the logic changes, a simpler RAG pipeline, fewer tokens, and stable prompts.</p><p>Building systems requires evaluation in every step of the journey. </p><p>Using Evaluation-Driven Development to cut tokens, go from vibes to data-driven analyses, and automated validation is what helps you get more a trustworthy working product.</p><p>Thanks for reading until the end, hope this helps you think of a way to evaluate your own systems. </p><p>If so, I&#8217;d love to know what other approaches are you considering when evaluating your RAG/LLM/Agentic apps.</p><div><hr></div><p>See you next time,</p><p>Ricardo. </p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The Underdoc! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Farewell FBref Advanced Stats: When One Door Closes Another Opens]]></title><description><![CDATA[A huge strike to data democratization in football analytics]]></description><link>https://ricardoheredia.substack.com/p/farewell-fbref-advanced-stats-when</link><guid isPermaLink="false">https://ricardoheredia.substack.com/p/farewell-fbref-advanced-stats-when</guid><dc:creator><![CDATA[Ricardo Heredia]]></dc:creator><pubDate>Thu, 22 Jan 2026 21:16:26 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/d3e625ce-6e0c-478b-96d0-be30dbdc7989_2816x1536.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p></p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!3dAj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f6871e6-2274-4d9d-8906-77cb86d3d36b_395x106.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3dAj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f6871e6-2274-4d9d-8906-77cb86d3d36b_395x106.heic 424w, https://substackcdn.com/image/fetch/$s_!3dAj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f6871e6-2274-4d9d-8906-77cb86d3d36b_395x106.heic 848w, https://substackcdn.com/image/fetch/$s_!3dAj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f6871e6-2274-4d9d-8906-77cb86d3d36b_395x106.heic 1272w, https://substackcdn.com/image/fetch/$s_!3dAj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f6871e6-2274-4d9d-8906-77cb86d3d36b_395x106.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!3dAj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f6871e6-2274-4d9d-8906-77cb86d3d36b_395x106.heic" width="395" height="106" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5f6871e6-2274-4d9d-8906-77cb86d3d36b_395x106.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:106,&quot;width&quot;:395,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:4044,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/185450643?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f6871e6-2274-4d9d-8906-77cb86d3d36b_395x106.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!3dAj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f6871e6-2274-4d9d-8906-77cb86d3d36b_395x106.heic 424w, https://substackcdn.com/image/fetch/$s_!3dAj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f6871e6-2274-4d9d-8906-77cb86d3d36b_395x106.heic 848w, https://substackcdn.com/image/fetch/$s_!3dAj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f6871e6-2274-4d9d-8906-77cb86d3d36b_395x106.heic 1272w, https://substackcdn.com/image/fetch/$s_!3dAj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f6871e6-2274-4d9d-8906-77cb86d3d36b_395x106.heic 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><p><strong>FBRef announced this week they removed all the Advanced Stats provided by Stats Perform by Opta. </strong></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!pFZV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35a1e90f-6fb0-40f3-8f2d-6a523613551f_1710x1314.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pFZV!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35a1e90f-6fb0-40f3-8f2d-6a523613551f_1710x1314.heic 424w, https://substackcdn.com/image/fetch/$s_!pFZV!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35a1e90f-6fb0-40f3-8f2d-6a523613551f_1710x1314.heic 848w, https://substackcdn.com/image/fetch/$s_!pFZV!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35a1e90f-6fb0-40f3-8f2d-6a523613551f_1710x1314.heic 1272w, https://substackcdn.com/image/fetch/$s_!pFZV!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35a1e90f-6fb0-40f3-8f2d-6a523613551f_1710x1314.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!pFZV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35a1e90f-6fb0-40f3-8f2d-6a523613551f_1710x1314.heic" width="617" height="474.1916208791209" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/35a1e90f-6fb0-40f3-8f2d-6a523613551f_1710x1314.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1119,&quot;width&quot;:1456,&quot;resizeWidth&quot;:617,&quot;bytes&quot;:286993,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/185450643?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35a1e90f-6fb0-40f3-8f2d-6a523613551f_1710x1314.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!pFZV!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35a1e90f-6fb0-40f3-8f2d-6a523613551f_1710x1314.heic 424w, https://substackcdn.com/image/fetch/$s_!pFZV!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35a1e90f-6fb0-40f3-8f2d-6a523613551f_1710x1314.heic 848w, https://substackcdn.com/image/fetch/$s_!pFZV!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35a1e90f-6fb0-40f3-8f2d-6a523613551f_1710x1314.heic 1272w, https://substackcdn.com/image/fetch/$s_!pFZV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35a1e90f-6fb0-40f3-8f2d-6a523613551f_1710x1314.heic 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><a href="https://www.sports-reference.com/blog/2026/01/fbref-stathead-data-update/">Article Reference</a></figcaption></figure></div><p>Something that took the football analytics community by surprise. </p><p>FBRef was maybe one of the first (if not the first) source you could think of to grab data and build high-level analysis. Whether you were a student, analyst, scout, fan, whoever, their web was a must. They these great level of detail in their data that actually made you go down rabbit holes just by looking at the granularity of their metrics.</p><p>I used to recommend it as one of the go-to places to get in contact with advanced football data stats &#8594; <a href="https://substack.com/@thenetpass14/p-168793687">How to Use FBRef for Football Scouting with Python?</a></p><p>This new situation far from being discouraging should make us all football lovers develop our <strong>creativity </strong>to make the most out of the available sources on the internet and explore other angles. For example: places like <a href="https://github.com/SkillCorner/opendata">SkillCorner Open Tracking &amp; Physical Data</a> or <a href="https://www.hudl.com/blog/elite/statsbomb">Hudl StatsBomb Event &amp; Physical Open Data</a> are well known data providers where you can obtain top valuable data to run different analyses but with a &#8220;detective mind&#8221;.</p><p>What I mean by that is trying to look at the data as a vehicle to derive close-to-real-world analyses of how technical staff at clubs or pro teams use this data, and also how other fellow colleagues use it. </p><p>You can see it on social media. The majority of professionals and data practitioners are active on X or LinkedIn. Perfect places to take a look at how this data is being used and inspire yourself of those signals to craft your own dashboards or reports how they consult other data sources, how they collect, clean, model and even how they present that data. </p><p>Having different POVs around how others manage sports data helps you upskill in the data field way faster, which is ultimately what we actually want: be more competent data professionals independently where the data comes from. </p><p>I also wouldn&#8217;t rule out the use of synthetic data for practicing purposes. With the rise of Generative AI and LLMs, this has become a popular alternative within the industry due to lack of access to closed source data. </p><p>Spending some time on crafting comprehensive prompts, using few shot examples, with metrics and well-defined ranges, can help you mimic real-world data for your own practice. </p><p>The main thing to remember from this FBRef situation is that it is essential that we adapt by focusing on sharpening skills with what&#8217;s available, or by creating our own way of accessing to data sources. </p><p>This is a great signal to start <strong>creating </strong>now. </p><p>Till next time,</p><p>Ricardo. </p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The NetPass! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[RAG is a Data Engineering Heavy Problem: Building a Football ETL for AI]]></title><description><![CDATA[How to use a Pydantic airlock and a Golden Dataset to set the information right for your RAG]]></description><link>https://ricardoheredia.substack.com/p/rag-is-a-data-engineering-heavy-problem</link><guid isPermaLink="false">https://ricardoheredia.substack.com/p/rag-is-a-data-engineering-heavy-problem</guid><dc:creator><![CDATA[Ricardo Heredia]]></dc:creator><pubDate>Mon, 12 Jan 2026 08:03:07 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!6Tya!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc246079e-6fc2-43c0-bb0e-7fad0de3e895_2816x1536.heic" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In my last post, I shared the big picture of the Football RAG system I&#8217;ve launched (<a href="https://substack.com/@thenetpass14/p-182493528">Building a RAG System That Generates Football Post-Match Tactical Reports Automatically</a>), and today, I want to talk about what is for me the most critical part of the system: the data pipeline. </p><p><strong>RAG efficiency relies on great Data Engineering.</strong> </p><p>This refers to building a solid ETL process: Extract, Transform, Load &#8212; the process that prevents bad retrieval and bad generation, helping the system produce accurate responses.</p><p>So, I&#8217;ll go over the origin of the data, the sources I used, and the decisions I made to build the pipeline.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6Tya!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc246079e-6fc2-43c0-bb0e-7fad0de3e895_2816x1536.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6Tya!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc246079e-6fc2-43c0-bb0e-7fad0de3e895_2816x1536.heic 424w, https://substackcdn.com/image/fetch/$s_!6Tya!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc246079e-6fc2-43c0-bb0e-7fad0de3e895_2816x1536.heic 848w, https://substackcdn.com/image/fetch/$s_!6Tya!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc246079e-6fc2-43c0-bb0e-7fad0de3e895_2816x1536.heic 1272w, https://substackcdn.com/image/fetch/$s_!6Tya!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc246079e-6fc2-43c0-bb0e-7fad0de3e895_2816x1536.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6Tya!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc246079e-6fc2-43c0-bb0e-7fad0de3e895_2816x1536.heic" width="1456" height="794" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c246079e-6fc2-43c0-bb0e-7fad0de3e895_2816x1536.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:794,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:963551,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/184194299?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc246079e-6fc2-43c0-bb0e-7fad0de3e895_2816x1536.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!6Tya!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc246079e-6fc2-43c0-bb0e-7fad0de3e895_2816x1536.heic 424w, https://substackcdn.com/image/fetch/$s_!6Tya!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc246079e-6fc2-43c0-bb0e-7fad0de3e895_2816x1536.heic 848w, https://substackcdn.com/image/fetch/$s_!6Tya!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc246079e-6fc2-43c0-bb0e-7fad0de3e895_2816x1536.heic 1272w, https://substackcdn.com/image/fetch/$s_!6Tya!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc246079e-6fc2-43c0-bb0e-7fad0de3e895_2816x1536.heic 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Overview of the system thanks to Nano Banana Pro.</figcaption></figure></div><h3>Where the Data Comes From</h3><p>Starting from the main goal of the system: automatically provide concise post match reports using free updated post match data from a league gathered in one place. That way, you can save time hopping from one site to another and focus on what really matters: the analysis.</p><p>To build these tactical reports, I wanted to use <strong>match event data</strong>.</p><p>I reused and improved a version of the scrapers I built for my <a href="https://ricardoheredia.substack.com/p/building-your-own-football-analytics">previous dashboard project</a>. The goal was to move from scraping one match for a plot to indexing 108 matches for a system.</p><p>The main data sources are: </p><ul><li><p><strong>WhoScored:</strong> with more than 1,300+ events per match: passes, tackles, coordinates.</p></li><li><p><strong>Fotmob:</strong> source for more specific match data like xG, numbers of shots and shot quality.</p></li></ul><p>Fotmob provides the shot as a number, whereas WhoScored only provides if the action was a shot (True) or not (False). They complement each other. </p><p>The first wall I hit in this Data Engineering process was: <strong>Entity Resolution.</strong> </p><p>Source A calls the team &#8220;R. Madrid,&#8221; Source B calls them &#8220;Real Madrid.&#8221; I needed to map them, so the RAG system wouldn&#8217;t think they are different teams.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1ncf!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff754142d-98e0-41fa-accc-243bc10a84eb_723x755.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1ncf!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff754142d-98e0-41fa-accc-243bc10a84eb_723x755.jpeg 424w, https://substackcdn.com/image/fetch/$s_!1ncf!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff754142d-98e0-41fa-accc-243bc10a84eb_723x755.jpeg 848w, https://substackcdn.com/image/fetch/$s_!1ncf!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff754142d-98e0-41fa-accc-243bc10a84eb_723x755.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!1ncf!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff754142d-98e0-41fa-accc-243bc10a84eb_723x755.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1ncf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff754142d-98e0-41fa-accc-243bc10a84eb_723x755.jpeg" width="409" height="427.10235131396956" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f754142d-98e0-41fa-accc-243bc10a84eb_723x755.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:755,&quot;width&quot;:723,&quot;resizeWidth&quot;:409,&quot;bytes&quot;:85418,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/184194299?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91b477a7-beb3-460a-87e9-7bd705cac867_890x940.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1ncf!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff754142d-98e0-41fa-accc-243bc10a84eb_723x755.jpeg 424w, https://substackcdn.com/image/fetch/$s_!1ncf!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff754142d-98e0-41fa-accc-243bc10a84eb_723x755.jpeg 848w, https://substackcdn.com/image/fetch/$s_!1ncf!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff754142d-98e0-41fa-accc-243bc10a84eb_723x755.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!1ncf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff754142d-98e0-41fa-accc-243bc10a84eb_723x755.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>This file is the glue. It&#8217;s a simple but effective way to prevent silent data corruption.</em></figcaption></figure></div><h3>Extracting the Data</h3><p>The scrapers development evolved from a one-off scraping to more matches. In this case I used just 108 matches from the first leg of the Eredivisie league. </p><p>Why the Dutch league? It&#8217;s a league I&#8217;m really curious about, they are one of the best breeding talent leagues in Europe and it is always worth it looking at their emergent talents. </p><p>The scrapers followed a simple rule: <strong>the Raw information is immutable.</strong> I save the JSON exactly as it comes from the web into a &#8220;Raw Zone&#8221; (local for now). That way if I find a bug in my tactical metrics calculation later, I don&#8217;t need to scrape the web again. I just re-run it from the raw files.</p><p>Quick summary of how it works:</p><pre><code>Scraper WhoScored --(JSON)--&gt; [ Raw Zone /whoscored/ ]
                                            |
 Scraper Fotmob   --(JSON)--&gt; [ Raw Zone /fotmob/   ]
                                            |
                              [ scrape_all_matches.py ]
                                            |
                               ( Orchestration &amp; Logs )</code></pre><ul><li><p><strong>The Workers:</strong> Specialized scrapers (one for WhoScored, another for Fotmob) designed with a single responsibility: extracting raw data.</p></li><li><p><strong>The Storage:</strong> A local directory that serves as my immutable &#8220;Raw Zone.&#8221;</p></li><li><p><strong>The Orchestrator:</strong> A central script (<code>scrape_all_matches.py</code>) that acts as the conductor, identifying missing matches and triggering the workers accordingly.</p></li></ul><pre><code>
# scripts/scrape_all_matches.py (A Simplified version of the Orchestrator)

def run_pipeline():
    # 1. Check what we already have (Incremental mode)
    existing_matches = get_local_raw_manifest()

    # 2. Run WhoScored Scraper
    print("&#128640; Starting WhoScored extraction...")
    ws_data = scrape_whoscored_season(mode="incremental", exclude=existing_matches)
    save_to_raw_zone(ws_data, source="whoscored")

    # 3. Run Fotmob Scraper
    print("&#128640; Starting Fotmob extraction...")
    fm_data = scrape_fotmob_eredivisie(mode="incremental", exclude=existing_matches)
    save_to_raw_zone(fm_data, source="fotmob")

    print("&#9989; Raw Zone updated. Ready for ETL.")</code></pre><h3>Pydantic Contracts: the &#8220;Airlock&#8221; Pattern</h3><p>To safely store data in a vector database, I needed a <strong>Contract</strong>. It is a strict, machine-checkable definition of what your data must look like before it&#8217;s allowed to move downstream.</p><p>In my case, it&#8217;s the schema for a &#8220;valid match&#8221; (required fields, types, constraints). If the scraped payload doesn&#8217;t satisfy that contract&#8212;missing <code>xG</code>, null team IDs, wrong types&#8212;the pipeline fails fast and the match never gets stored in the vector database.</p><p><strong>Pydantic</strong> is in charge to validate that match, working as an airlock. It defines exactly what a &#8220;valid match&#8221; looks like. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_93h!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8a52c02-238e-4de5-b02b-179127a692c4_2816x1536.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_93h!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8a52c02-238e-4de5-b02b-179127a692c4_2816x1536.heic 424w, https://substackcdn.com/image/fetch/$s_!_93h!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8a52c02-238e-4de5-b02b-179127a692c4_2816x1536.heic 848w, https://substackcdn.com/image/fetch/$s_!_93h!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8a52c02-238e-4de5-b02b-179127a692c4_2816x1536.heic 1272w, https://substackcdn.com/image/fetch/$s_!_93h!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8a52c02-238e-4de5-b02b-179127a692c4_2816x1536.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_93h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8a52c02-238e-4de5-b02b-179127a692c4_2816x1536.heic" width="1456" height="794" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c8a52c02-238e-4de5-b02b-179127a692c4_2816x1536.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:794,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:797828,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/184194299?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8a52c02-238e-4de5-b02b-179127a692c4_2816x1536.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!_93h!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8a52c02-238e-4de5-b02b-179127a692c4_2816x1536.heic 424w, https://substackcdn.com/image/fetch/$s_!_93h!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8a52c02-238e-4de5-b02b-179127a692c4_2816x1536.heic 848w, https://substackcdn.com/image/fetch/$s_!_93h!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8a52c02-238e-4de5-b02b-179127a692c4_2816x1536.heic 1272w, https://substackcdn.com/image/fetch/$s_!_93h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8a52c02-238e-4de5-b02b-179127a692c4_2816x1536.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>This is the guardrail, it forces the data to be &#8220;clean&#8221; before it touches the system.</em></figcaption></figure></div><h3>Pre-calculating +30 Metrics</h3><p>Dumping 1,300 raw events into the LLM didn&#8217;t seem realistic nor cost-effective. It&#8217;s  expensive in matters of tokens and slow latency, which ultimately confuses the model, making it prone to give back unreliable information.</p><p>Instead of the ETL just moving data, it acts as a <strong>Factory</strong>. </p><p>It processes raw, messy coordinates and distills them into <strong>Tactical Insights</strong> (or <strong>Actionable Metrics</strong>):</p><ul><li><p>Instead of 500 raw pass coordinates &#8594; <strong>Verticality: 0.65</strong></p></li><li><p>Instead of 20 defensive events &#8594; <strong>PPDA: 8.2</strong></p></li></ul><p><strong>The logic is simple:</strong> I don&#8217;t want the LLM to waste its &#8220;brainpower&#8221; (and tokens) trying to do math on thousands of x,y points. I want it to focus on what it does best: <strong>reasoning over tactical concepts.</strong> </p><p>By pre-calculating these metrics, I&#8217;m handing the AI a &#8220;scout&#8217;s report&#8221; instead of raw notes.</p><p>This is the <strong>transformation</strong> step of the pipeline: where raw events, shots, and mappings are stitched together into a single, validated match profile.</p><pre><code># scripts/process_raw_data.py (simplified version of the transformation logic)

def process_matches():
    # 1. Load the "Glue": Match mappings and raw data
    mappings = load_json("data/match_mapping.json")
    
    for ws_id, mapping in mappings.items():
        # 2. Resolve IDs (The fix for the Home/Away swap bug)
        home_id, away_id = resolve_team_ids(mapping)
        
        # 3. Stitch data sources (WhoScored Events + Fotmob Shots)
        ws_data = load_json(f"raw/whoscored_matches/match_{ws_id}.json")
        fotmob_match = find_match_in_bulk(mapping['fotmob_id'])
        
        # 4. The "Factory": Distill 1,300+ events into 38 tactical metrics
        events_df = pd.DataFrame(ws_data['events'])
        raw_metrics = calculate_all_metrics(events_df, fotmob_match['shots'], home_id, away_id)
        
        # 5. The "Airlock": Validate everything with Pydantic
        match_profile = MatchProfile(
            metadata=MatchMetadata(match_id=ws_id, date=mapping['match_date']),
            home_team=TeamMatchStats(**map_metrics(raw_metrics, "home")),
            away_team=TeamMatchStats(**map_metrics(raw_metrics, "away")),
            home_score=calculate_score(fotmob_match['shots'], "home"),
            away_score=calculate_score(fotmob_match['shots'], "away")
        )
        
        # 6. Save to the Golden Dataset
        save_to_gold(match_profile)</code></pre><p>In essence, it resolves team IDs, stitches two different data sources together, calculates tactical metrics, and finally passes everything through a Pydantic "airlock" to ensure the Golden Dataset is 100% reliable.</p><h4>An issue I found at the beginning </h4><p>Early in development, the system told me Zwolle dominated a game they actually lost 2-8 (https://www.sofascore.com/football/match/heracles-almelo-pec-zwolle/wjbsCjb)</p><p>The LLM was just reading the data I gave it and I thought it was hallucinating. </p><p>The ETL had a bug in the team ID mapping that swapped the Home and Away stats. </p><p>Something that made me understand that paying attention to the DE part is central.</p><h3>The Golden Dataset &amp; The Sniper Approach</h3><p>The final output of the ETL is the <code>matches_gold.json</code>. </p><p>This file became the center of the system. Everything downstream: reports, evaluations, and rebuilds started here. That&#8217;s why I treat it as the <strong>Source of Truth</strong>, and not the vector database.</p><p>Once the data is in this shape, the next step was loading it into ChromaDB. </p><p>To do that, I used a simple <strong>2-chunk architecture</strong> when indexing each match:</p><ul><li><p><strong>Summary Chunk: </strong>Contains match metadata: teams, date, score, and competition. Its job is to make sure the system finds the <em>right </em>match.</p></li><li><p><strong>Tactical Chunk: </strong>Contains the pre-calculated metrics. This is what the LLM actually reads to generate the analysis.</p></li></ul><p>I ended up calling this setup the <strong>&#8220;Sniper Approach.&#8221;</strong></p><p>I wanted to avoid relying entirely on semantic search: embed the query, retrieve the closest vectors, and hope the correct match is somewhere near the top. That works, but it always felt a bit loose for this use case.</p><p>When a user asks about <em>PSV vs Ajax</em>, I don&#8217;t want the system to &#8220;kind of&#8221; get it right. I already know the exact match I&#8217;m looking for, so I use <strong>metadata filtering</strong> to narrow it down first. Once the match is identified, only then does the LLM see the tactical data.</p><p>This way, the vector database serves exactly what I ask for and retrieval becomes deterministic.</p><p><strong>[SNIPPET F: </strong><code>scripts/rebuild_chromadb.py</code><strong> &#8211; Chunking &amp; Metadata logic]</strong></p><pre><code># scripts/rebuild_chromadb.py 

for match in matches:
    match_id = match['metadata']['match_id']
    home = match['home_team']
    away = match['away_team']
    
    # Chunk 1: Summary (for metadata filtering)
    summary_text = (
        f"{home['team_name']} vs {away['team_name']} "
        f"({match['home_score']}-{match['away_score']}). "
        f"Possession: {home['possession']}% vs {away['possession']}%. "
        f"xG: {home['xg']} vs {away['xg']}."
    )
    
    summary_meta = {
        "match_id": match_id,
        "chunk_type": "summary",
        "home_team": home['team_name'],
        "away_team": away['team_name'],
        "match_date": match['metadata']['match_date']
    }
    
    collection.add(
        documents=[summary_text],
        metadatas=[summary_meta],
        ids=[f"{match_id}_summary"]
    )
    
    # Chunk 2: Tactical Metrics (for LLM generation)
    tactical_meta = {
        "match_id": match_id,
        "chunk_type": "tactical_metrics",
        "home_ppda": home['ppda'],
        "home_verticality": home['verticality'],
        "home_xg": home['xg'],
        "away_ppda": away['ppda'],
        "away_verticality": away['verticality'],
        "away_xg": away['xg'],
        # ... (38 total metrics)
    }
    
    collection.add(
        documents=[f"Tactical metrics for {home['team_name']} vs {away['team_name']}"],
        metadatas=[tactical_meta],
        ids=[f"{match_id}_tactical_metrics"]
    )</code></pre><p><em>Two chunks per match: one for finding it (metadata filtering), one for analyzing it (LLM generation). The vector database doesn't guess; it serves exactly what I ask for. </em></p><p>I also added a <code>sanitize_metadata()</code> function to prevent ChromaDB from crashing on <code>None</code> values. It saved me from silent failures during indexing.</p><p>Link to the repo so you can check all the code: <a href="https://github.com/ricardoherediaj/football-rag-intelligence">Football RAG Intelligence</a></p><h3>Bottom Line</h3><p>At the end of the day, a football analyst needs to trust the numbers, and a developer needs to trust the pipeline.</p><p>By building a strict ETL with Pydantic and a Golden Dataset, I managed to reduce the &#8220;hallucination surface&#8221; before even writing a prompt. The idea was to make the data so clear that the AI didn&#8217;t have to guess.</p><div><hr></div><h3>What&#8217;s next?</h3><p>Now that we&#8217;ve tackled the data preparation, we need to talk to it.</p><p>In the next article, I&#8217;ll dive into the <strong>Prompt Engineering</strong> side of the project. </p><p>I&#8217;ll show you why I spent a good amount of time designing a Tailored Prompt and how that decision helped me cut token costs by 80%.</p><p>If you're interested in the intersection of Data Engineering and Generative AI, subscribe to follow this series.</p><p>See you then, </p><p>Ricardo. </p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The NetPass! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[A Thank You, Two Ideas From a Book That Changed My 2025 and Timothée Chalamet's Pursuit of Greatness]]></title><description><![CDATA[The career mindset shift that changed my 2025 that I hope can help you in 2026.]]></description><link>https://ricardoheredia.substack.com/p/a-thank-you-two-ideas-from-a-book</link><guid isPermaLink="false">https://ricardoheredia.substack.com/p/a-thank-you-two-ideas-from-a-book</guid><dc:creator><![CDATA[Ricardo Heredia]]></dc:creator><pubDate>Wed, 31 Dec 2025 17:24:19 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Jgnb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F13264168-2a9d-44b4-8ce4-0f2884980c24_1000x667.heic" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>What a year, captain&#8230;</p><p>I won't take much of your time, but before it ends, I wanted to thank you for reading this newsletter during the year. </p><p>I wrote about football, AI, RAG systems, agentic IDEs, and a bunch of technical experiments, things I hope helped you apply them to your own work.</p><p>So thank you. It really means a lot that you share this space with me.</p><p>To wrap it up, I want to share one thing that changed my thinking this year and will serve as my compass for years to come. </p><p>It's about how I want to perform my work and develop my career. </p><p>I'm sure it can help you start 2026 with a different perspective.</p><h2>The Book That Made Me Rethink About Purpose</h2><p>I recently finished reading <em>So Good They Can&#8217;t Ignore You</em> by Cal Newport, a book recommended by <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Juli&#225;n Campos&quot;,&quot;id&quot;:173193757,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b6dd3c21-1194-409d-9b45-d2d0fc8333ac_1175x1177.jpeg&quot;,&quot;uuid&quot;:&quot;810c4bd2-a8f4-41ee-b604-a7077d3cf6a9&quot;}" data-component-name="MentionToDOM"></span> on a brilliant X/Twitter thread about books every developer should read.  </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!MeyT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0277b094-27a0-4e80-8611-0e7db201a7d4_232x388.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!MeyT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0277b094-27a0-4e80-8611-0e7db201a7d4_232x388.webp 424w, https://substackcdn.com/image/fetch/$s_!MeyT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0277b094-27a0-4e80-8611-0e7db201a7d4_232x388.webp 848w, https://substackcdn.com/image/fetch/$s_!MeyT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0277b094-27a0-4e80-8611-0e7db201a7d4_232x388.webp 1272w, https://substackcdn.com/image/fetch/$s_!MeyT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0277b094-27a0-4e80-8611-0e7db201a7d4_232x388.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!MeyT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0277b094-27a0-4e80-8611-0e7db201a7d4_232x388.webp" width="262" height="438.17241379310343" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0277b094-27a0-4e80-8611-0e7db201a7d4_232x388.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:388,&quot;width&quot;:232,&quot;resizeWidth&quot;:262,&quot;bytes&quot;:17458,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/183047952?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0277b094-27a0-4e80-8611-0e7db201a7d4_232x388.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!MeyT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0277b094-27a0-4e80-8611-0e7db201a7d4_232x388.webp 424w, https://substackcdn.com/image/fetch/$s_!MeyT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0277b094-27a0-4e80-8611-0e7db201a7d4_232x388.webp 848w, https://substackcdn.com/image/fetch/$s_!MeyT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0277b094-27a0-4e80-8611-0e7db201a7d4_232x388.webp 1272w, https://substackcdn.com/image/fetch/$s_!MeyT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0277b094-27a0-4e80-8611-0e7db201a7d4_232x388.webp 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Book cover.</figcaption></figure></div><p>This was the book that really hit me this year. </p><p>Why? Cause all my life I&#8217;ve thought the popular advice &#8220;find your passion and the rest will follow&#8221; was real. Too many decisions made using this mantra. </p><p>Then, to my surprise, Newport argues the opposite in the chapters of this book. </p><p>Telling stories of people from each path and ultimately showing who developed more successful and satisfying lives. </p><p>Here&#8217;s the deal.</p><h2>Passion Mindset vs. Craft Mindset </h2><p>The central subject of the book is these two concepts.</p><p>The passion mindset is about finding work that matches a passion you supposedly already have. It&#8217;s asking &#8220;what can the world offer me?&#8221; and assuming passion comes first, then the work follows.</p><p>The craft mindset flips this. It&#8217;s about getting really good at something rare and valuable. Asking &#8220;what can I offer?&#8221; instead. </p><p>The key difference: <strong>passion comes after you develop mastery, not before.</strong></p><p>This made me rethink how I approach my own career in tech. Since I pivoted from medicine I&#8217;ve been unknowingly following this path, trying to get better at managing data, programming and ultimately building AI systems. </p><p>I was lucky enough to apply it to football (which I love) and healthcare, my background. </p><p>But the true passion came from pushing through the work and wanting to get better each day. </p><h4>How Chalamet Pursues Greatness Through Craft</h4><p>In February, at the SAG Awards ceremony, Timoth&#233;e Chalamet said something unusual: &#8220;I&#8217;m really in pursuit of greatness. I want to be one of the greats.&#8221;</p><p>I felt that quote was really honest because he was actually talking about becoming great through the work. </p><p>He mentioned being inspired by Daniel Day-Lewis, Marlon Brando, and Viola Davis, and spending 5.5 years of his life preparing for <em>A Complete Unknown </em>where he portrayed Bob Dylan.</p><p>That&#8217;s the craft mindset in action. </p><p>Greatness is something you build deliberately over years of committed work.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Jgnb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F13264168-2a9d-44b4-8ce4-0f2884980c24_1000x667.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Jgnb!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F13264168-2a9d-44b4-8ce4-0f2884980c24_1000x667.heic 424w, https://substackcdn.com/image/fetch/$s_!Jgnb!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F13264168-2a9d-44b4-8ce4-0f2884980c24_1000x667.heic 848w, https://substackcdn.com/image/fetch/$s_!Jgnb!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F13264168-2a9d-44b4-8ce4-0f2884980c24_1000x667.heic 1272w, https://substackcdn.com/image/fetch/$s_!Jgnb!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F13264168-2a9d-44b4-8ce4-0f2884980c24_1000x667.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Jgnb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F13264168-2a9d-44b4-8ce4-0f2884980c24_1000x667.heic" width="556" height="370.852" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/13264168-2a9d-44b4-8ce4-0f2884980c24_1000x667.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:667,&quot;width&quot;:1000,&quot;resizeWidth&quot;:556,&quot;bytes&quot;:82019,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/183047952?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F13264168-2a9d-44b4-8ce4-0f2884980c24_1000x667.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Jgnb!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F13264168-2a9d-44b4-8ce4-0f2884980c24_1000x667.heic 424w, https://substackcdn.com/image/fetch/$s_!Jgnb!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F13264168-2a9d-44b4-8ce4-0f2884980c24_1000x667.heic 848w, https://substackcdn.com/image/fetch/$s_!Jgnb!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F13264168-2a9d-44b4-8ce4-0f2884980c24_1000x667.heic 1272w, https://substackcdn.com/image/fetch/$s_!Jgnb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F13264168-2a9d-44b4-8ce4-0f2884980c24_1000x667.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2>Career Capital: The Currency to Buy What You Want in Your Career</h2><p>Career capital is the set of rare and valuable skills you&#8217;ve accumulated through the years. </p><p>Newport uses this economic metaphor deliberately: great jobs (those offering creativity, impact, and control) are scarce and valuable. </p><p>To get one, you need to offer something scarce and valuable in return. </p><p>Most people want autonomy, interesting projects, and meaningful work from day one (happened to me). But you need currency to buy those things. First you accumulate the capital, then you invest it to negotiate the career you actually want.</p><p>You build it by developing skills that are rare and valuable, ones others don&#8217;t have and the market needs.</p><p>This changed how I choose what to learn. </p><p>Before, I chased new technologies that sounded interesting but now I ask myself if it gives me the career capital I want to build. Or is it rare and valuable, more than a commodity. </p><p>For example: Python is valuable but not rare. Instead, using Python to create AI systems applied to a niche domain like football analytics or healthcare is a rare combination.</p><p>This lens shows if you're building capital or just chasing noise.</p><h2>What This Means for 2026</h2><p>For 2026, my plan is simple: keep accumulating capital, investing it by building projects that combine rare and valuable skills, sharing what I learn here, and iterating.</p><p>If there&#8217;s something you can take from this for your own 2026, let it be this:</p><blockquote><p>Build mastery first. The passion will come on its own.</p></blockquote><p>Have a great year.</p><p>Till next time, </p><p>Ricardo.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The NetPass! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p>]]></content:encoded></item><item><title><![CDATA[Building a RAG System That Generates Football Post-Match Tactical Reports Automatically]]></title><description><![CDATA[Transforming free event data from WhoScored and Fotmob into instant, comprehensive reports with LLMs for less than $0.50]]></description><link>https://ricardoheredia.substack.com/p/building-a-rag-system-that-generates</link><guid isPermaLink="false">https://ricardoheredia.substack.com/p/building-a-rag-system-that-generates</guid><dc:creator><![CDATA[Ricardo Heredia]]></dc:creator><pubDate>Fri, 26 Dec 2025 06:01:00 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!WMWM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F59c871ce-0be7-463e-8457-16d43dd3d553_1024x1024.heic" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!WMWM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F59c871ce-0be7-463e-8457-16d43dd3d553_1024x1024.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!WMWM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F59c871ce-0be7-463e-8457-16d43dd3d553_1024x1024.heic 424w, https://substackcdn.com/image/fetch/$s_!WMWM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F59c871ce-0be7-463e-8457-16d43dd3d553_1024x1024.heic 848w, https://substackcdn.com/image/fetch/$s_!WMWM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F59c871ce-0be7-463e-8457-16d43dd3d553_1024x1024.heic 1272w, https://substackcdn.com/image/fetch/$s_!WMWM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F59c871ce-0be7-463e-8457-16d43dd3d553_1024x1024.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!WMWM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F59c871ce-0be7-463e-8457-16d43dd3d553_1024x1024.heic" width="465" height="465" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/59c871ce-0be7-463e-8457-16d43dd3d553_1024x1024.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1024,&quot;width&quot;:1024,&quot;resizeWidth&quot;:465,&quot;bytes&quot;:88116,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/182493528?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F59c871ce-0be7-463e-8457-16d43dd3d553_1024x1024.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!WMWM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F59c871ce-0be7-463e-8457-16d43dd3d553_1024x1024.heic 424w, https://substackcdn.com/image/fetch/$s_!WMWM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F59c871ce-0be7-463e-8457-16d43dd3d553_1024x1024.heic 848w, https://substackcdn.com/image/fetch/$s_!WMWM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F59c871ce-0be7-463e-8457-16d43dd3d553_1024x1024.heic 1272w, https://substackcdn.com/image/fetch/$s_!WMWM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F59c871ce-0be7-463e-8457-16d43dd3d553_1024x1024.heic 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">A summary of the project courtesy of Nano Banana Pro</figcaption></figure></div><h2>Long time no see </h2><p>First of all, Merry Christmas &#127876;</p><p>It&#8217;s been a while since I last send a post, but life happens. So, here I am before finishing the year.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The NetPass! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>I wanted to end 2025 with the same vibe I want to start 2026: <em>building projects and sharing knowledge. </em></p><p>Lately, I&#8217;ve been working on something that mixes my interest in AI and my passion for football. I&#8217;m really excited to go over its details and how the idea came up. </p><p>When I started analyzing football data and creating post match reports, I had a problem that I think a lot of coaches, analysts, and football data practitioners can relate to.</p><p><strong>Gathering free match data from various sources to build reports is tedious.</strong></p><p>This makes it difficult to create a summarized report from any match without hopping from one web to another.</p><p>Say if you want to analyze PSV&#8217;s pressing patterns from last week&#8217;s Eredivisie match day, you need to go to WhoScored, then Fotmob for shot and xG values, Understat, BeSoccer etc, and obtaining the data manually.</p><p>That&#8217;s why I wanted to built this system:</p><p><strong>One where I could ask &#8220;What was PSV&#8217;s pressing strategy against Ajax?&#8221; in natural language and get an instant tactical report&#8212;with real stats, context, and visualizations from multiple free data sources.</strong></p><p>I want to show you how it works.</p><h2>What I Built</h2><p>This is the live demo hosted at Hugging Face Spaces: <strong><a href="https://huggingface.co/spaces/rheredia8/football-rag-intelligence">Football RAG Intelligence - Live Demo</a></strong></p><p>It&#8217;s a RAG (Retrieval-Augmented Generation) system that ingests Eredivisie match data from WhoScored and Fotmob, stores it in a vector database, and generates tactical analysis grounded in actual statistics.</p><p>You ask questions in natural language. It retrieves the match data and then generates comprehensive rundowns thanks to the LLM text-generation capability.</p><p>Reduced hallucinations and instant visualizations at low cost.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!uYkg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dcd68d6-6851-4fdf-a877-592ef79c2b7e_2876x1686.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!uYkg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dcd68d6-6851-4fdf-a877-592ef79c2b7e_2876x1686.heic 424w, https://substackcdn.com/image/fetch/$s_!uYkg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dcd68d6-6851-4fdf-a877-592ef79c2b7e_2876x1686.heic 848w, https://substackcdn.com/image/fetch/$s_!uYkg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dcd68d6-6851-4fdf-a877-592ef79c2b7e_2876x1686.heic 1272w, https://substackcdn.com/image/fetch/$s_!uYkg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dcd68d6-6851-4fdf-a877-592ef79c2b7e_2876x1686.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!uYkg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dcd68d6-6851-4fdf-a877-592ef79c2b7e_2876x1686.heic" width="1456" height="854" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5dcd68d6-6851-4fdf-a877-592ef79c2b7e_2876x1686.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:854,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:241478,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/182493528?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dcd68d6-6851-4fdf-a877-592ef79c2b7e_2876x1686.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!uYkg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dcd68d6-6851-4fdf-a877-592ef79c2b7e_2876x1686.heic 424w, https://substackcdn.com/image/fetch/$s_!uYkg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dcd68d6-6851-4fdf-a877-592ef79c2b7e_2876x1686.heic 848w, https://substackcdn.com/image/fetch/$s_!uYkg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dcd68d6-6851-4fdf-a877-592ef79c2b7e_2876x1686.heic 1272w, https://substackcdn.com/image/fetch/$s_!uYkg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dcd68d6-6851-4fdf-a877-592ef79c2b7e_2876x1686.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Here&#8217;s what it handles:</p><ul><li><p><strong>108 Eredivisie matches indexed</strong> with event-level data (~1355 events per match).</p></li><li><p><strong>Dual-mode interface:</strong> Ask a question and get tactical commentary. Request a visualization and get instant plots.</p></li><li><p><strong>Multi-provider support:</strong> Works with Anthropic&#8217;s Claude, OpenAI, and Gemini models. </p></li><li><p><strong>$0.50 total cost</strong> to test everything.</p></li></ul><p>The visualizations I used were already created using a prior code. I went through it in an earlier article, you can go check it here: <a href="https://ricardoheredia.substack.com/p/building-your-own-football-analytics?r=56fjux">Building Your Own Football Analytics Dashboards With Free Data</a></p><h2>Why This Matters</h2><p>Your match data lives in one place so you don&#8217;t have to hop around internet to get it. Ask questions in plain language, get answers backed by recent stats. Need a passing network or shot map? Type &#8220;show passing network for Feyenoord&#8221;.</p><p><strong>Who can leverage this?</strong></p><p>Coaches, scouts, and analysts at small/medium/big clubs, football fans, developers. Pretty much anyone involved in analyzing football with data.</p><h2>How It Works</h2><p>Here&#8217;s the high-level flow:</p><pre><code><code>User Query &#8594; Router (classify intent)
             &#8595;
    &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9524;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
    &#8595;                  &#8595;
LLM Analysis      Visualization
(Tailored Prompt)     (Keyword-based)
    &#8595;                  &#8595;
ChromaDB          pre-built matplotlib
retrieval         plots
    &#8595;                  &#8595;
Grounded          $0 cost
Commentary        images
</code></code></pre><p>The system does five things:</p><p><strong>1. Routes your query:</strong> Questions like &#8220;What was PSV&#8217;s pressing strategy?&#8221; go to the LLM pipeline. Commands like &#8220;Show shot map&#8221; trigger visualizations.</p><p><strong>2. Retrieves match data:</strong> ChromaDB finds the exact match using team names and metadata filtering instead of semantic search guessing.</p><p><strong>3. Generates analysis:</strong> The LLM gets the actual stats and writes tactical commentary using a carefully engineered prompt (which I&#8217;ll cover in Article 2).</p><p><strong>4. Validates output:</strong> Every statistic cited in the response is checked against the golden dataset. If it&#8217;s not there, it doesn&#8217;t make it into the output.</p><p><strong>5. Delivers instantly:</strong> Text analysis in 6-7 seconds or visualizations in under a second because they bypass the LLM entirely.</p><p>Hints on the key architectural decisions I made (I&#8217;ll dig deeper into these in future articles):</p><ul><li><p><strong>Prompt-first design:</strong> I designed the Tailored Prompt before building the ChromaDB schema. I wanted to tackle the mismatch between what the LLM expected and what the database provided.</p></li><li><p><strong>2-chunk architecture:</strong> Each match gets two documents in ChromaDB. One summary chunk (team names, score, date) for filtering. One tactical metrics chunk (38 pre-calculated features) for LLM generation.</p></li><li><p><strong>Pre-calculated metrics:</strong> All tactical metrics are computed during data ingestion. PPDA, progressive passes, field tilt, compactness, etc. The RAG pipeline doesn&#8217;t calculate anything, it just retrieves and interprets.</p></li><li><p><strong>Smart routing:</strong> Text questions go to the LLM. Visualization commands go straight to the plots generation with matplotlib. This was to reduce the cost for every viz request.</p></li><li><p><strong>Golden Dataset ETL:</strong> Raw data from WhoScored and Fotmob flows through a Pydantic validation pipeline. Only clean, validated data makes it into ChromaDB. This &#8220;airlock&#8221; pattern caught bugs before they could cause hallucinations.</p></li></ul><h2>The Results</h2><p>In initial evaluation testing on 10 diverse matches, these were the obtained results:</p><p><strong>Retrieval Accuracy: 100%</strong></p><p>Every query found the correct match data. Metadata filtering (team names, dates) acts like a &#8220;sniper&#8221; approach versus pure semantic search, which only hit 70% accuracy.</p><p><strong>Faithfulness: 99.4%</strong></p><p>Generated analysis matched source statistics. Every number cited in the commentary exists in the golden dataset. One test case had a minor discrepancy due to rounding, hence 99.4% instead of 100%.</p><p><strong>Tactical Insight: 95.0%</strong></p><p>The commentary provided actual both tactical depth and data reporting. </p><p>I evaluated the system using an LLM-as-a-Judge methodology with specific rubrics and reference answers.</p><p>The cost: <strong>~$0.0001 per query with Claude Haiku 4.5.</strong></p><p>The system still occasionally generates erroneous team names or statistics, which is why continuous evaluation is important. I'll cover my evaluation approach in Article 4.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-DhJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F000473d0-43ea-4ebf-8e4a-44e25b5dc1ce_2880x1700.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-DhJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F000473d0-43ea-4ebf-8e4a-44e25b5dc1ce_2880x1700.heic 424w, https://substackcdn.com/image/fetch/$s_!-DhJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F000473d0-43ea-4ebf-8e4a-44e25b5dc1ce_2880x1700.heic 848w, https://substackcdn.com/image/fetch/$s_!-DhJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F000473d0-43ea-4ebf-8e4a-44e25b5dc1ce_2880x1700.heic 1272w, https://substackcdn.com/image/fetch/$s_!-DhJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F000473d0-43ea-4ebf-8e4a-44e25b5dc1ce_2880x1700.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-DhJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F000473d0-43ea-4ebf-8e4a-44e25b5dc1ce_2880x1700.heic" width="1456" height="859" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/000473d0-43ea-4ebf-8e4a-44e25b5dc1ce_2880x1700.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:859,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:188624,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/182493528?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F000473d0-43ea-4ebf-8e4a-44e25b5dc1ce_2880x1700.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!-DhJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F000473d0-43ea-4ebf-8e4a-44e25b5dc1ce_2880x1700.heic 424w, https://substackcdn.com/image/fetch/$s_!-DhJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F000473d0-43ea-4ebf-8e4a-44e25b5dc1ce_2880x1700.heic 848w, https://substackcdn.com/image/fetch/$s_!-DhJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F000473d0-43ea-4ebf-8e4a-44e25b5dc1ce_2880x1700.heic 1272w, https://substackcdn.com/image/fetch/$s_!-DhJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F000473d0-43ea-4ebf-8e4a-44e25b5dc1ce_2880x1700.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2>What&#8217;s Next: The Series Roadmap</h2><p>This article gives a big picture of what I built and how it works.</p><p>In next articles I&#8217;ll go deeper into specific aspects of the journey:</p><ul><li><p><strong>Crafting a Football ETL Pipeline with free event data for RAG:</strong> What sources I used, why, how I managed all this data to make it useful for the system, and what is RAG.</p></li></ul><ul><li><p><strong>Why Prompt Engineering Came before the vector database and how it helped optimize costs: </strong>Designing the Tailored Prompt to avoid retrieval-generation mismatch. I&#8217;ll show the many prompt iterations from V1.0 (1800 tokens, slow, vague) to V3.5 (360 tokens, fast, precise).</p></li><li><p><strong>Evaluating the system with the Evaluation Driven Development approach: </strong>The LLM-as-a-Judge methodology. How I built the three-metric evaluation framework. Creating test datasets that actually matter. Debugging false failures.</p></li><li><p><strong>Deploying the App: </strong>Hosting an initial version of the app in HF Spaces, a well-known place for AI/ML developers to deploy applications.  </p></li><li><p><strong>Next steps to Production Scaling: </strong>Current MVP limitations. Production stack design following data, software, and AI engineering best practices (CID/CD, pipeline orchestration, LLM cloud hosting and inference, automated evaluations) to go from proof-of-concept to a system that obtains weekly matches and generates fully automated reports on demand hosted on premise.</p></li></ul><h2>Try It Yourself</h2><p>Demo Link: <strong><a href="https://huggingface.co/spaces/rheredia8/football-rag-intelligence">Football RAG Intelligence</a></strong></p><p>Pick a provider (Claude, GPT, or Gemini), paste your API key, and start asking questions.</p><p>Example queries to try:</p><p><strong>Text analysis:</strong></p><ul><li><p>&#8220;What was PSV&#8217;s pressing strategy against Ajax?&#8221;</p></li><li><p>&#8220;How did Heracles build up play against PEC Zwolle?&#8221;</p></li><li><p>&#8220;Explain the tactics in Feyenoord vs Ajax&#8221;</p></li></ul><p><strong>Visualizations:</strong></p><ul><li><p>&#8220;Show dashboard for Heracles vs PEC Zwolle&#8221;</p></li><li><p>&#8220;Show passing network for Feyenoord&#8221;</p></li><li><p>&#8220;Show shot map for AZ vs Utrecht&#8221;</p></li></ul><p>The code is fully open source: <strong><a href="https://github.com/ricardoherediaj/football-rag-intelligence">GitHub Repository</a></strong></p><p>Clone it. </p><p>Run it locally. </p><p>Modify it for your own league or data sources.</p><p>I included all the  documented architecture decisions to showcase the entire process and next steps. </p><h2>Bottom Line</h2><p>The goal of this project is to show that:</p><p>A RAG system and an LLM of your choice fed by your own clean data, clear architecture, and careful prompt engineering, helps you solve a real problem like automated post match analysis.</p><p>Leveraging AI to create systems or tools is one of the things that excites me the most. There's something incredible about going from idea to working system so fast. </p><p>AI helps blur that line between "I want to build this" and "I built this."</p><p>I would love to hear some thoughts on this on how useful is this to you.</p><p>Til next time, </p><p>Ricardo. </p><p></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The NetPass! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Understanding Model Context Protocol (MCP): Connecting LLMs to Real Data]]></title><description><![CDATA[How to build bridges between AI models and your data using a MinIO MCP Server as a practical example]]></description><link>https://ricardoheredia.substack.com/p/understanding-model-context-protocol</link><guid isPermaLink="false">https://ricardoheredia.substack.com/p/understanding-model-context-protocol</guid><dc:creator><![CDATA[Ricardo Heredia]]></dc:creator><pubDate>Mon, 29 Sep 2025 05:02:28 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!xvfB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7cbca14-5e64-40a4-8c15-9a1cae8259d1_800x600.heic" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Trying to get an AI model to work with your actual data instead of just hallucinating responses, can end in frustration some times.</p><p>For example, you want ChatGPT to analyze files in your S3 bucket, or to help you manage your databases, but you end up copying and pasting data manually.</p><p>Every new data source requires its own custom connector same as every AI application needs its own integration code. </p><p>There&#8217;s a solution which has risen in popularity as new way of how we work with AI and data integration: <strong>Model Context Protocol (MCP)</strong>.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The NetPass! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h2>What is an MCP and What is it Used For?</h2><p><strong>Model Context Protocol (MCP) is an open standard that allows AI models to securely connect to external data sources and tools through a unified interface.</strong></p><p>MCP acts as an USB-C port for AI applications.</p><p>Just as USB-C provides a standardized way to connect any device to any peripheral without custom cables for each combination, MCP provides a standardized way to connect any AI model to any data source without writing custom integration code.</p><p>Before MCP, if you wanted Claude to access your MinIO storage, your GitHub repositories, or your database, you&#8217;d need three separate custom integrations. With MCP, you write one MCP server for each data source, and any MCP-compatible AI client (like Claude Desktop, Cursor, or your custom application) can instantly use all of them.</p><p>The key is the <strong>standardization.</strong> Instead of AI models needing to know the specific APIs of hundreds of different services, they just need to understand one protocol: <strong>MCP</strong>.</p><h2>General Structure</h2><p>MCP follows a client-server architecture that separates concerns in the following way:</p><h3>MCP Host</h3><p>The user-facing AI application (like Claude Desktop, Cursor, or your custom AI app) that coordinates everything.</p><h3>MCP Client</h3><p>Lives inside the host application and manages secure connections to MCP servers. Each server gets its own isolated client connection.</p><h3>MCP Server</h3><p>External programs that expose specific capabilities to AI models like connecting to databases, file systems, APIs, or any other data source.</p><p>The communication happens through <strong>JSON-RPC</strong>, a lightweight protocol that enables secure, two-way communication between clients and servers.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xvfB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7cbca14-5e64-40a4-8c15-9a1cae8259d1_800x600.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xvfB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7cbca14-5e64-40a4-8c15-9a1cae8259d1_800x600.heic 424w, https://substackcdn.com/image/fetch/$s_!xvfB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7cbca14-5e64-40a4-8c15-9a1cae8259d1_800x600.heic 848w, https://substackcdn.com/image/fetch/$s_!xvfB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7cbca14-5e64-40a4-8c15-9a1cae8259d1_800x600.heic 1272w, https://substackcdn.com/image/fetch/$s_!xvfB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7cbca14-5e64-40a4-8c15-9a1cae8259d1_800x600.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xvfB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7cbca14-5e64-40a4-8c15-9a1cae8259d1_800x600.heic" width="800" height="600" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f7cbca14-5e64-40a4-8c15-9a1cae8259d1_800x600.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:600,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:29696,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/174750596?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7cbca14-5e64-40a4-8c15-9a1cae8259d1_800x600.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!xvfB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7cbca14-5e64-40a4-8c15-9a1cae8259d1_800x600.heic 424w, https://substackcdn.com/image/fetch/$s_!xvfB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7cbca14-5e64-40a4-8c15-9a1cae8259d1_800x600.heic 848w, https://substackcdn.com/image/fetch/$s_!xvfB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7cbca14-5e64-40a4-8c15-9a1cae8259d1_800x600.heic 1272w, https://substackcdn.com/image/fetch/$s_!xvfB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7cbca14-5e64-40a4-8c15-9a1cae8259d1_800x600.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>MCP image obtained from the MCP lesson of the Full Stack AI Engineering course from Towards AI Academy. </em></figcaption></figure></div><h3>Three Core Primitives</h3><p>MCP organizes functionality into three main types:</p><p><strong>Resources</strong>: Read-only data that the AI can access (like files, database records, or API responses). We can call them &#8220;things the AI can read.&#8221;</p><p><strong>Tools</strong>: Actions the AI can perform (like creating files, sending emails, or running queries). These are &#8220;functions the AI can call.&#8221;</p><p><strong>Prompts</strong>: Reusable conversation templates or workflows that provide structured interactions.</p><p>The importance of this design is that the AI model doesn&#8217;t need to know anything about MinIO&#8217;s S3 API, your database schema, or any specific service. It just knows how to ask for resources, call tools, and use prompts through the MCP interface.</p><h2>Practical Use Cases</h2><p>MCP is useful in scenarios where you need AI models to work with real, live data:</p><p><strong>Development Workflows</strong>: AI coding assistants that can read your codebase, access your Git history, and understand your project structure in real-time.</p><p><strong>Data Analysis</strong>: Models that can query your databases, analyze your files, and generate insights from your actual business data.</p><p><strong>Content Management</strong>: AI that can access your document repositories, and help you manage and organize content.</p><p><strong>Business Intelligence</strong>: Models that connect to your analytics platforms, CRM systems, and help you make data-driven decisions.</p><p><strong>Infrastructure Management</strong>: AI that can interact with your cloud storage, monitor your systems, and help with operational tasks.</p><p>The key advantage is <strong>real-time access</strong>. Instead of feeding static data to AI models, MCP enables dynamic, contextual interactions with live systems.</p><h2>Practical Example: MinIO MCP Server</h2><p>Now let&#8217;s see MCP in action with a real example: the <strong>MinIO MCP Server</strong> built in collaboration with my colleague <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Rafa&quot;,&quot;id&quot;:17515645,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/0363a2a9-0bcf-49fd-8caa-853dbb73f087_144x144.png&quot;,&quot;uuid&quot;:&quot;2838e084-2357-4544-be9b-b7952fe2bcb4&quot;}" data-component-name="MentionToDOM"></span> Ginard, a brilliant senior software engineer (<a href="https://github.com/Rafitis">Rafa's GitHub</a> and <a href="https://www.linkedin.com/in/rafa-ginard/">Rafa's LinkedIn</a>) who came up with this idea of connecting your MinIO object storage with any host and client, even a local LLM. </p><h3>What the MinIO MCP Server Does</h3><p>The server exposes MinIO object storage operations as MCP tools, allowing any MCP-compatible AI client to manage buckets and objects through natural language.</p><p><strong>Repository</strong>: <a href="https://github.com/Rafitis/minio-mcp-server">https://github.com/Rafitis/minio-mcp-server</a></p><h3>Key Features</h3><p><strong>7 MCP Tools</strong> organized by domain:</p><p><em>Bucket Operations</em>:</p><ul><li><p><code>list_buckets</code>: Get all available buckets with creation dates</p></li><li><p><code>get_bucket_info</code>: Detailed bucket metadata, policies, object count, and size</p></li><li><p><code>create_bucket</code>: Create new buckets with validation</p></li><li><p><code>delete_bucket</code>: Delete empty buckets or force delete with contents</p></li></ul><p><em>Object Operations</em>:</p><ul><li><p><code>list_objects</code>: List objects with filtering and pagination</p></li><li><p><code>get_object_info</code>: Get detailed object metadata</p></li><li><p><code>delete_object</code>: Remove objects with version support</p></li></ul><h3>Architecture Highlights</h3><p><strong>Built on FastMCP</strong>: Uses the FastMCP framework for robust MCP protocol support</p><p><strong>Async Architecture</strong>: Full async/await support for better performance</p><p><strong>Comprehensive Validation</strong>: Input validation and error handling with proper HTTP status codes</p><p><strong>Modular Design</strong>: Separated BucketTools and ObjectTools classes for clean organization</p><h3>Quick Setup</h3><p>The setup process demonstrates how streamlined MCP can be:</p><pre><code><code># Clone and install
git clone https://github.com/Rafitis/minio-mcp-server
cd minio-mcp-server
uv sync

# Configure your MinIO connection
cp .env.example .env
# Edit .env with your MinIO credentials

# Start the MCP server
uv run python src/minio_mcp/server.py
</code></code></pre><h3>Claude Desktop Integration</h3><p>To connect with Claude Desktop, you just add this configuration:</p><pre><code><code>{
  &#8220;mcpServers&#8221;: {
    &#8220;minio-mcp-server&#8221;: {
      &#8220;command&#8221;: &#8220;/path/to/uv&#8221;,
      &#8220;args&#8221;: [
        &#8220;--directory&#8221;, &#8220;/path/to/minio-mcp-server&#8221;,
        &#8220;run&#8221;, &#8220;python&#8221;, &#8220;src/minio_mcp/server.py&#8221;
      ],
      &#8220;env&#8221;: {
        &#8220;MINIO_ENDPOINT&#8221;: &#8220;localhost:9000&#8221;,
        &#8220;MINIO_ACCESS_KEY&#8221;: &#8220;minioadmin&#8221;,
        &#8220;MINIO_SECRET_KEY&#8221;: &#8220;minioadmin&#8221;,
        &#8220;MINIO_SECURE&#8221;: &#8220;false&#8221;
      }
    }
  }
}
</code></code></pre><p>After restarting Claude Desktop, you can use natural language commands like:</p><ul><li><p>&#8220;List all buckets in MinIO&#8221;</p></li><li><p>&#8220;Show me information about the &#8216;analytics-data&#8217; bucket&#8221;</p></li><li><p>&#8220;Delete &#8216;old-backup.zip&#8217; from the &#8216;archives&#8217; bucket&#8221;</p></li></ul><p><strong>The AI model automatically translates these requests into the appropriate MCP tool calls.</strong></p><h2>Connecting with Local LLMs and Optimal Prompts</h2><p>One particular aspect of MCP is its model-agnostic design. You can use the same MCP server with cloud-based models like Claude or with local models like Mistral.</p><h3>Local LLM Integration</h3><p>The <code>feature/llm-rest-api-integration</code> branch of our repository shows how to connect MCP servers with local LLMs for maximum privacy and control.</p><p><strong>Key Benefits of Local Integration</strong>:</p><ul><li><p><strong>Privacy</strong>: Your data never leaves your infrastructure</p></li><li><p><strong>Cost Control</strong>: No per-token pricing from cloud providers</p></li><li><p><strong>Customization</strong>: Fine-tune models for your specific domain</p></li><li><p><strong>Offline Capability</strong>: Works without internet connectivity</p></li></ul><h3>Setting Up with Enterprise LLMs</h3><p>Here&#8217;s how you can connect with your company&#8217;s enterprise LLM infrastructure:</p><p><strong>Enterprise LLM Setup</strong> (OpenAI-compatible API):</p><pre><code><code>import asyncio
from openai import OpenAI
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

class EnterpriseMinioMCPClient:
    def __init__(self):
        # Configure your enterprise LLM as an OpenAI-compatible client
        self.enterprise_llm = OpenAI(
            api_key=&#8221;your-enterprise-api-key&#8221;,  # Your company&#8217;s API key
            base_url=&#8221;https://llm-service.yourcompany.com/v1&#8221;  # Your company&#8217;s LLM endpoint
        )
        
    async def connect_to_minio_server(self, server_script_path: str):
        &#8220;&#8221;&#8220;Connect to MinIO MCP server&#8221;&#8220;&#8221;
        server_params = StdioServerParameters(
            command=&#8221;python&#8221;,
            args=[server_script_path],
            env=os.environ.copy()
        )
        
        # Establish connection to MCP server
        stdio_transport = await stdio_client(server_params)
        self.stdio, self.write = stdio_transport
        self.session = ClientSession(self.stdio, self.write)
        await self.session.initialize()
        
    async def process_query(self, query: str) -&gt; str:
        &#8220;&#8221;&#8220;Process user query through Enterprise LLM + MinIO tools&#8221;&#8220;&#8221;
        
        # Get available MinIO tools
        tools_response = await self.session.list_tools()
        
        # Build tool descriptions for the LLM
        tools_info = &#8220;\n&#8221;.join([
            f&#8221;- {tool.name}: {tool.description}&#8221;
            for tool in tools_response.tools
        ])
        
        # Ask enterprise LLM which tool to use
        messages = [
            {
                &#8220;role&#8221;: &#8220;system&#8221;, 
                &#8220;content&#8221;: f&#8221;You are a MinIO assistant with these tools:\n{tools_info}\n&#8221;
                          &#8220;Respond with TOOL_CALL: {{\&#8221;tool_name\&#8221;: \&#8221;name\&#8221;, \&#8221;parameters\&#8221;: {{}}}} or answer directly.&#8221;
            },
            {&#8221;role&#8221;: &#8220;user&#8221;, &#8220;content&#8221;: query}
        ]
        
        response = self.enterprise_llm.chat.completions.create(
            model=&#8221;your-company-model&#8221;,  # Your enterprise model name
            messages=messages,
            max_tokens=500
        )
        
        llm_decision = response.choices[0].message.content.strip()
        
        # Execute tool if LLM decided to use one
        if llm_decision.startswith(&#8221;TOOL_CALL:&#8221;):
            tool_call = json.loads(llm_decision.replace(&#8221;TOOL_CALL:&#8221;, &#8220;&#8221;).strip())
            tool_result = await self.session.call_tool(
                tool_call[&#8221;tool_name&#8221;], 
                tool_call[&#8221;parameters&#8221;]
            )
            
            # Format result with enterprise LLM
            format_messages = [
                {
                    &#8220;role&#8221;: &#8220;system&#8221;, 
                    &#8220;content&#8221;: &#8220;Format this MinIO tool result into a natural language response.&#8221;
                },
                {
                    &#8220;role&#8221;: &#8220;user&#8221;, 
                    &#8220;content&#8221;: f&#8221;Query: {query}\nResult: {tool_result.content}&#8221;
                }
            ]
            
            final_response = self.enterprise_llm.chat.completions.create(
                model=&#8221;your-company-model&#8221;,
                messages=format_messages,
                max_tokens=1500
            )
            
            return final_response.choices[0].message.content
        
        return llm_decision

# Usage
client = EnterpriseMinioMCPClient()
await client.connect_to_minio_server(&#8221;src/minio_mcp/server.py&#8221;)
result = await client.process_query(&#8221;Show me all buckets and find the largest files in each one&#8221;)</code></code></pre><h3>Optimal Prompting Strategies</h3><p>When working with MCP and local LLMs, these prompting techniques can help deliver a better result:</p><p><strong>Be specific about the context</strong>:</p><pre><code><code>&#8220;Using the MinIO tools, list all buckets and then show me 
the 5 largest objects in the &#8216;backups&#8217; bucket&#8221;</code></code></pre><p><strong>Structure multi-step operations</strong>:</p><pre><code><code>&#8220;First, check what buckets exist in MinIO. Then, for the 
bucket with the most objects, show me a summary of file 
types and total storage used.&#8221;</code></code></pre><p><strong>Provide clear constraints</strong>:</p><pre><code><code>&#8220;List objects in the &#8216;logs&#8217; bucket, but only show files 
from the last 7 days and limit results to 20 items&#8221;</code></code></pre><p><strong>Use domain-specific language</strong>:</p><pre><code><code>&#8220;Check the health of our data lake by listing all buckets, 
showing their sizes, and identifying any empty buckets 
that might need cleanup&#8221;</code></code></pre><p>The key: leveraging the AI&#8217;s natural language understanding while being precise about what data operations you want performed.</p><h3>Performance Considerations</h3><p>Local LLMs with MCP work best when you:</p><ul><li><p><strong>Choose function or tool-calling capable models</strong> (Mistral, Llama 3.2, Qwen)</p></li><li><p><strong>Optimize context windows</strong> for your data size</p></li><li><p><strong>Use streaming responses</strong> for real-time feedback</p></li><li><p><strong>Implement proper error handling</strong> for network timeouts</p></li></ul><h2>Relevant Resources and Documentation</h2><p>If you want to dive deeper into MCP, here are the essential resources:</p><p><strong>Official Documentation</strong>: <a href="https://spec.modelcontextprotocol.io/">Model Context Protocol Specification</a> - The complete technical specification</p><p><strong>Anthropic&#8217;s MCP Guide</strong>: <a href="https://docs.claude.com/en/docs/mcp">MCP Documentation</a> - Practical guides and tutorials</p><p><strong>MCP GitHub Organization</strong>: <a href="https://github.com/modelcontextprotocol">GitHub ModelContextProtocol</a> - SDKs, examples, and community contributions</p><p><strong>Awesome MCP Servers</strong>: A growing collection of community-built MCP servers for popular services</p><p><strong>MCP.so: </strong><a href="https://mcp.so">MCP.so</a>  - A web to &#8220;Find Awesome MCP Servers and Clients&#8221;</p><p>The ecosystem is expanding rapidly, with new MCP servers being built for everything from Slack and GitHub to specialized databases and custom APIs, even to write your own articles in Substack/Medium.</p><h2>Key Takeaways</h2><p>Model Context Protocol helps solving a big challenge in AI development: connecting models to real, live data in a standardized way, providing a universal interface that works across the entire ecosystem.</p><ul><li><p><strong>For developers</strong>, it means more time building intelligent features using AI.</p></li><li><p><strong>For organizations</strong>, this means building AI applications that can actually work with the nuances of your data infrastructure.</p></li><li><p><strong>For the AI ecosystem</strong>, this means faster innovation as everyone builds on shared standards and sharing this servers as open source. </p></li></ul><p>The goal of the MinIO MCP Server is to demonstrate how straightforward it can be to expose powerful data operations to AI models, by creating a bridge between your object store and an LLM with just a few hundred lines of code.</p><p>Whether you&#8217;re using cloud models like Claude or local models like Mistral, the same MCP server works seamlessly. </p><p>Besides improving models to make them smarter, the future of AI relies on making models seamlessly interact with the tools and data that power our workflows.</p><p>Check out the <a href="https://github.com/Rafitis/minio-mcp-server">MinIO MCP Server repository</a> and start building your own AI-data bridges today.</p><p>Til&#8217; next time, </p><p>Ricardo. </p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The NetPass! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[uv: The Tool That Helps You Manage Your Python Project Dependencies Smoothly]]></title><description><![CDATA[If you've been working with Python for a while, you've probably experienced the frustration when you're trying to set up a project and you're dealing with conflicting package versions, virtual environment headaches, or waiting forever for pip or Conda to resolve dependencies.]]></description><link>https://ricardoheredia.substack.com/p/uv-the-tool-that-helps-you-manage</link><guid isPermaLink="false">https://ricardoheredia.substack.com/p/uv-the-tool-that-helps-you-manage</guid><dc:creator><![CDATA[Ricardo Heredia]]></dc:creator><pubDate>Sun, 31 Aug 2025 17:28:37 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!fmvg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e4c9d5e-db89-4659-b2d2-44a6229481da_1350x578.heic" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you've been working with Python for a while, you've probably experienced the frustration when you're trying to set up a project and you're dealing with conflicting package versions, virtual environment headaches, or waiting forever for pip or Conda to resolve dependencies.</p><p>We've all been there.</p><p>But fortunately there's a tool that can solve all of these problems in second. </p><p><strong>uv</strong> is the Python package that's helps setting up and managing Python projects blazingly fast.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://ricardoheredia.substack.com/subscribe?"><span>Subscribe now</span></a></p><h2>What is uv?</h2><p>Is a Python package manager built in Rust that promises to be "an extremely fast Python package installer and resolver."</p><p>uv was created by the team at Astral (the same people behind Ruff), and it's designed to replace not just pip, but also pipenv, poetry, pyenv, and conda in many use cases. It's a unified tool that handles:</p><ul><li><p>Package installation and resolution</p></li><li><p>Virtual environment management</p></li><li><p>Python version management</p></li><li><p>Project scaffolding</p></li></ul><p>Think of it as the Swiss Army knife for Python development, but one that actually works smoothly instead of having unstable tools.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!fmvg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e4c9d5e-db89-4659-b2d2-44a6229481da_1350x578.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!fmvg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e4c9d5e-db89-4659-b2d2-44a6229481da_1350x578.heic 424w, https://substackcdn.com/image/fetch/$s_!fmvg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e4c9d5e-db89-4659-b2d2-44a6229481da_1350x578.heic 848w, https://substackcdn.com/image/fetch/$s_!fmvg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e4c9d5e-db89-4659-b2d2-44a6229481da_1350x578.heic 1272w, https://substackcdn.com/image/fetch/$s_!fmvg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e4c9d5e-db89-4659-b2d2-44a6229481da_1350x578.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!fmvg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e4c9d5e-db89-4659-b2d2-44a6229481da_1350x578.heic" width="1350" height="578" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9e4c9d5e-db89-4659-b2d2-44a6229481da_1350x578.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:578,&quot;width&quot;:1350,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:29036,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/172396761?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e4c9d5e-db89-4659-b2d2-44a6229481da_1350x578.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!fmvg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e4c9d5e-db89-4659-b2d2-44a6229481da_1350x578.heic 424w, https://substackcdn.com/image/fetch/$s_!fmvg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e4c9d5e-db89-4659-b2d2-44a6229481da_1350x578.heic 848w, https://substackcdn.com/image/fetch/$s_!fmvg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e4c9d5e-db89-4659-b2d2-44a6229481da_1350x578.heic 1272w, https://substackcdn.com/image/fetch/$s_!fmvg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e4c9d5e-db89-4659-b2d2-44a6229481da_1350x578.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2>Why uv Beats Everything Else</h2><h3>Speed</h3><p>Where uv really shines. While pip can take minutes to install a complex set of dependencies, uv does it in seconds. We're talking about 10-100x faster installation times.</p><p>The first time you use it, you'll think something went wrong because it finished too quickly (happened to me).</p><h3>Better Than pip</h3><p>pip is the default, but it's also slow and doesn't handle dependency resolution as elegantly as it could. </p><p>uv uses a modern resolver that's both faster and more reliable. Plus, unlike pip, uv creates isolated environments by default.</p><h3>Simpler Than Poetry</h3><p>Poetry is great for dependency management, but it has its quirks. The configuration can be complex, and it sometimes feels like overkill for simple projects. </p><blockquote><p><strong>uv gives you the power of Poetry with the simplicity of pip.</strong></p></blockquote><h3>More Reliable Than Conda</h3><p>Conda has its place, it was the first package manager I used, especially for scientific computing and data science. But for pure Python projects, Conda environments can be heavy and sometimes unpredictable, they can easily break and sometimes trying to find the root of that error and fixing it is worse than creating a new environment from scratch.</p><p> uv keeps things lightweight and consistent.</p><h2>What Makes uv Special: The Technical Bits</h2><p>When you use uv, you get three key files that make your life easier:</p><h3>1. pyproject.toml</h3><p>This is your project's configuration file. It contains all your dependencies, project metadata, and build settings in a standardized format. Unlike requirements.txt, it separates development dependencies from production ones and includes version constraints clearly.</p><p>When you run <code>uv pip install</code> in a project with a <code>pyproject.toml</code> file, <code>uv</code> will:</p><ol><li><p><strong>Read Dependencies</strong>: Automatically detect and install the dependencies listed in the <code>[project]</code> and <code>[project.optional-dependencies]</code> sections.</p></li><li><p><strong>Manage Environments</strong>: Create and sync a virtual environment with the exact dependencies specified in the <code>uv.lock</code> file (if present) or <code>pyproject.toml</code>.</p></li><li><p><strong>Lock Dependencies</strong>: Generate a <code>uv.lock</code> file that pins the versions of all direct and transitive dependencies, ensuring fully reproducible builds.</p></li></ol><p>This makes <code>uv</code> a powerful tool for managing complex projects without needing higher-level workflow managers.</p><h3>2. uv.lock</h3><p>It contains the exact versions of every package (and their dependencies) that your project uses. This means when someone else runs your project, they get the exact same package versions you used. Helps to avoid the "but it works on my machine" issues.</p><h3>3. Automatic .venv Creation</h3><p>uv automatically creates and manages virtual environments. No more remembering to activate environments or wondering which packages belong to which project.</p><p><code>uv</code> streamlines virtual environment creation and management.</p><ul><li><p><strong>Creating a virtual environment</strong>:</p></li></ul><pre><code><code># Creates a .venv directory in the current folder
uv venv</code></code></pre><p>This command automatically finds your system's Python and creates a virtual environment. To use a specific Python version, use the <code>--python</code> flag (e.g., <code>uv venv --python 3.11</code>).</p><ul><li><p><strong>Activating the virtual environment</strong>:</p></li></ul><p>Activation commands remain standard for your shell:</p><pre><code><code># For bash or zsh
source .venv/bin/activate
</code></code></pre><p>Once a virtual environment is active, <code>uv</code> commands like <code>uv pip install</code> will automatically use it.</p><h2>The Modern Data Stack Connection</h2><p>If you're working in data science or analytics (for example in football analytics), uv is particularly valuable regarding: </p><ul><li><p><strong>Reproducible analyses</strong>: The lock file ensures your analysis can be reproduced exactly</p></li><li><p><strong>Faster iteration</strong>: Quick environment setup means less time waiting, more time analyzing</p></li><li><p><strong>Clean project structure</strong>: Clear separation between development and production dependencies</p></li><li><p><strong>Better collaboration</strong>: Team members can quickly get identical environments</p></li></ul><h2>Real Example: Setting Up My Football Analytics Project</h2><p>Here&#8217;s an example on how to get started with my football analytics tutorials repository using uv.</p><h3>Step 1: Install uv</h3><pre><code><code># On macOS and Linux
curl -LsSf https://astral.sh/uv/install.sh | sh

# On Windows
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"

# Or via pip if you prefer
pip install uv
</code></code></pre><h3>Step 2: Clone and Set Up the Project</h3><pre><code><code>git clone https://github.com/ricardoheredia/football-analytics-tutorials.git
cd football-analytics-tutorials
</code></code></pre><p>Now, instead of dealing with virtual environments, requirements files, and all that complexity, you just run:</p><pre><code><code>uv sync
</code></code></pre><p>And uv will:</p><ul><li><p>Create a virtual environment automatically</p></li><li><p>Install all dependencies from the lock file</p></li><li><p>Ensure everything is isolated</p></li><li><p>Do it all in seconds</p></li></ul><h3>Step 3: Start Working</h3><pre><code><code>uv run jupyter notebook
</code></code></pre><p>This command runs Jupyter in the project's environment without you having to manually activate it.</p><h2>The Files That Make It Work</h2><p>In the repo, you'll see these key files:</p><p><strong>pyproject.toml</strong> contains our project configuration:</p><pre><code><code>[project]
name = "football-analytics-tutorials"
dependencies = [
    "pandas&gt;=2.0.0",
    "matplotlib&gt;=3.7.0",
    "seaborn&gt;=0.12.0",
    "jupyter&gt;=1.0.0",
    # ... more dependencies
]

[project.optional-dependencies]
dev = [
    "pytest&gt;=7.0.0",
    "black&gt;=23.0.0",
]
</code></code></pre><p><strong>uv.lock</strong> ensures everyone gets the exact same package versions (this file is quite long, but that's the point &#8211; it's comprehensive).</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!NE2R!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86495572-c6f7-4317-a944-7da0f9380d95_750x612.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!NE2R!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86495572-c6f7-4317-a944-7da0f9380d95_750x612.heic 424w, https://substackcdn.com/image/fetch/$s_!NE2R!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86495572-c6f7-4317-a944-7da0f9380d95_750x612.heic 848w, https://substackcdn.com/image/fetch/$s_!NE2R!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86495572-c6f7-4317-a944-7da0f9380d95_750x612.heic 1272w, https://substackcdn.com/image/fetch/$s_!NE2R!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86495572-c6f7-4317-a944-7da0f9380d95_750x612.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!NE2R!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86495572-c6f7-4317-a944-7da0f9380d95_750x612.heic" width="554" height="452.064" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/86495572-c6f7-4317-a944-7da0f9380d95_750x612.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:612,&quot;width&quot;:750,&quot;resizeWidth&quot;:554,&quot;bytes&quot;:25405,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/172396761?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86495572-c6f7-4317-a944-7da0f9380d95_750x612.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!NE2R!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86495572-c6f7-4317-a944-7da0f9380d95_750x612.heic 424w, https://substackcdn.com/image/fetch/$s_!NE2R!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86495572-c6f7-4317-a944-7da0f9380d95_750x612.heic 848w, https://substackcdn.com/image/fetch/$s_!NE2R!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86495572-c6f7-4317-a944-7da0f9380d95_750x612.heic 1272w, https://substackcdn.com/image/fetch/$s_!NE2R!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86495572-c6f7-4317-a944-7da0f9380d95_750x612.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2>Why This Matters for Your Workflow</h2><p>Using uv has changed how I approach new projects. Instead of spending minutes setting up environments and installing packages, I spend a few seconds. It helps removing the friction that often prevents us from starting new experiments or sharing our work.</p><p>Now, if I want to test a football analytics technique, I can:</p><ol><li><p>Create a new project with <code>uv init</code></p></li><li><p>Add dependencies with <code>uv add pandas matplotlib</code></p></li><li><p>Start coding immediately</p></li></ol><h2>Getting Started Today</h2><p>If you want to try this out with the example repository:</p><ol><li><p>Install uv using one of the methods above</p></li><li><p>Clone the repo: <code>git clone https://github.com/ricardoheredia/football-analytics-tutorials.git</code></p></li><li><p>Run <code>uv sync</code></p></li><li><p>Start exploring: <code>uv run jupyter notebook</code></p></li></ol><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!eZGr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa918ebd0-d32d-468c-8257-462f30b4bb07_2774x1536.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!eZGr!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa918ebd0-d32d-468c-8257-462f30b4bb07_2774x1536.heic 424w, https://substackcdn.com/image/fetch/$s_!eZGr!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa918ebd0-d32d-468c-8257-462f30b4bb07_2774x1536.heic 848w, https://substackcdn.com/image/fetch/$s_!eZGr!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa918ebd0-d32d-468c-8257-462f30b4bb07_2774x1536.heic 1272w, https://substackcdn.com/image/fetch/$s_!eZGr!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa918ebd0-d32d-468c-8257-462f30b4bb07_2774x1536.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!eZGr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa918ebd0-d32d-468c-8257-462f30b4bb07_2774x1536.heic" width="1456" height="806" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a918ebd0-d32d-468c-8257-462f30b4bb07_2774x1536.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:806,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:167133,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/172396761?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa918ebd0-d32d-468c-8257-462f30b4bb07_2774x1536.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!eZGr!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa918ebd0-d32d-468c-8257-462f30b4bb07_2774x1536.heic 424w, https://substackcdn.com/image/fetch/$s_!eZGr!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa918ebd0-d32d-468c-8257-462f30b4bb07_2774x1536.heic 848w, https://substackcdn.com/image/fetch/$s_!eZGr!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa918ebd0-d32d-468c-8257-462f30b4bb07_2774x1536.heic 1272w, https://substackcdn.com/image/fetch/$s_!eZGr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa918ebd0-d32d-468c-8257-462f30b4bb07_2774x1536.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Check the documentation from the website if you want to go deeper: <a href="https://docs.astral.sh/uv/">uv documentation</a></p><p>You'll be up and running under a minute.</p><h2>The Bottom Line</h2><p>Python package management has been a pain point for too long. </p><p>uv solves the problem and makes the whole experience smooth. Fast installation, reliable dependency resolution, and automatic environment management mean less time fighting with tools.</p><p>For football analytics, data science, machine learning, or any Python project, uv is rapidly becoming the standard. </p><p>The combination of speed, reliability, and simplicity is hard to beat.</p><div><hr></div><p>Let me know in the comments if you have already tried it before or what&#8217;s your preferred Python package manager.</p><p><strong>Check out the <a href="https://github.com/ricardoheredia/football-analytics-tutorials">tutorials repository</a> and start building your own match analysis dashboards today</strong></p><div class="captioned-button-wrap" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/p/uv-the-tool-that-helps-you-manage?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="CaptionedButtonToDOM"><div class="preamble"><p class="cta-caption">Thanks for reading The NetPass! This post is public so feel free to share it with anyone you  think might like reading about data, AI/ML, football analytics and more.</p></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/p/uv-the-tool-that-helps-you-manage?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://ricardoheredia.substack.com/p/uv-the-tool-that-helps-you-manage?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p></div><p>Till next time, </p><p>Ricardo.</p>]]></content:encoded></item><item><title><![CDATA[The Data Learning Diary: Tracking Your Weekly Learning Progress]]></title><description><![CDATA[Why checking your learning at the end of the week helps you advance in projects]]></description><link>https://ricardoheredia.substack.com/p/the-data-learning-diary-tracking</link><guid isPermaLink="false">https://ricardoheredia.substack.com/p/the-data-learning-diary-tracking</guid><dc:creator><![CDATA[Ricardo Heredia]]></dc:creator><pubDate>Sat, 23 Aug 2025 12:00:32 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!gKyD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F074a94be-7b4b-412b-8755-e16ca8be4e36_864x1152.heic" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!gKyD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F074a94be-7b4b-412b-8755-e16ca8be4e36_864x1152.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!gKyD!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F074a94be-7b4b-412b-8755-e16ca8be4e36_864x1152.heic 424w, https://substackcdn.com/image/fetch/$s_!gKyD!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F074a94be-7b4b-412b-8755-e16ca8be4e36_864x1152.heic 848w, https://substackcdn.com/image/fetch/$s_!gKyD!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F074a94be-7b4b-412b-8755-e16ca8be4e36_864x1152.heic 1272w, https://substackcdn.com/image/fetch/$s_!gKyD!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F074a94be-7b4b-412b-8755-e16ca8be4e36_864x1152.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!gKyD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F074a94be-7b4b-412b-8755-e16ca8be4e36_864x1152.heic" width="486" height="648" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/074a94be-7b4b-412b-8755-e16ca8be4e36_864x1152.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1152,&quot;width&quot;:864,&quot;resizeWidth&quot;:486,&quot;bytes&quot;:110758,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/170630595?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F074a94be-7b4b-412b-8755-e16ca8be4e36_864x1152.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!gKyD!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F074a94be-7b4b-412b-8755-e16ca8be4e36_864x1152.heic 424w, https://substackcdn.com/image/fetch/$s_!gKyD!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F074a94be-7b4b-412b-8755-e16ca8be4e36_864x1152.heic 848w, https://substackcdn.com/image/fetch/$s_!gKyD!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F074a94be-7b4b-412b-8755-e16ca8be4e36_864x1152.heic 1272w, https://substackcdn.com/image/fetch/$s_!gKyD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F074a94be-7b4b-412b-8755-e16ca8be4e36_864x1152.heic 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">A data guy taking notes backwards (?). Image By GPT-5-Mini. </figcaption></figure></div><p>When we think about writing we might believe that we have an inherent obligation of writing something ground breaking, a scientific article, an encyclopedia, etc. </p><p>But the reality is simpler. </p><p>Writing is a powerful tool that you can use pretty much for any purpose: writing short stories, listing things to remember them, or journaling, for example. </p><p>One of my favorite uses besides writing for this newsletter and sharing content online is: tracking my weekly knowledge. </p><p>A writing use case I&#8217;m sure will help you advance your learning progress, your projects, and your career in general. </p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://ricardoheredia.substack.com/subscribe?"><span>Subscribe now</span></a></p><h3>Using a Paper and Digital Notebook</h3><p>Not so long ago, when I started in this world of technology, especially in data science, in my very first day of work,  I was handed a laptop along with a small notebook and a pen. I immediately thought: &#8220;What&#8217;s the use of this? I&#8217;ll have everything inside my IDE, I don&#8217;t think I&#8217;ll forget anything.&#8221;</p><p>Boy, I was wrong. </p><p>At the same time I was advancing through projects and meetings, that notebook saved my life. It helped me: </p><ul><li><p>Organize my thoughts before presenting results in a meeting.</p></li></ul><ul><li><p>Summarize key ideas from daily standup and sprints.</p></li><li><p>Highlight key results and suggestions from my peers. </p></li><li><p>Note down next steps. </p></li><li><p>And one of my favorites: annotate new things to learn.    </p></li></ul><p>The importance of that notebook (and its content) grew more and more in my daily workflow. </p><p>Soon, I felt I needed a little &#8220;upgrade&#8221;, so I decided to expand my note taking to a digital format. </p><p>I chose Notion as my main notes storage. This helped me organized my notes in simple categories:</p><ul><li><p>Work Projects: meeting summaries, progress, next steps, deadlines, pain points.</p></li><li><p>Personal Projects</p></li><li><p>Learning (courses, new technologies, tools, etc.)</p></li><li><p>Newsletter posts ideas</p></li><li><p>Notes about books (technical and non-technical)</p></li></ul><p>This way, every note was allocated in a specific category, helping me organize the mess I was accumulating in the physical notebook. </p><p>I then realized something: I was noting down things I learned and implemented during the week, but wasn&#8217;t actually reflecting about them nor documenting them with detail. </p><p>Here, documenting the process you go through when learning something new is important. It helps you be aware of what you&#8217;re putting into practice, the failed experiments, and the final success.</p><p>That&#8217;s why I created a specific category in my notes: </p><h3>The Data Learning Diary</h3><p>I fill this diary (a basic separate page in Notion) with the things I&#8217;ve learnt through the week. </p><p> What I do in <strong>3 steps</strong>: </p><ol><li><p>I see something I want to learn &#8594; note down the topic </p></li><li><p>Go over the topic and use the Feynman technique by writing a summary in simple words to see if I understood &#8594; note down that summary (depending on the case I later ask Claude or ChatGPT to help me understand difficult concepts). </p></li><li><p>If it&#8217;s relevant to the project, apply that knowledge immediately &#8594; document every single step in the way: the <strong>goal</strong> of the project, first <strong>implementation</strong>, failed <strong>experiments</strong>, what <strong>worked</strong>, what <strong>didn't</strong>. </p></li></ol><p>I do this daily, so at the end of the week I have a list of all the things I've been going over. </p><p>This is an example of last week.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!lM8Z!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b365c87-59d4-49da-8046-769952b2d715_1178x1068.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!lM8Z!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b365c87-59d4-49da-8046-769952b2d715_1178x1068.heic 424w, https://substackcdn.com/image/fetch/$s_!lM8Z!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b365c87-59d4-49da-8046-769952b2d715_1178x1068.heic 848w, https://substackcdn.com/image/fetch/$s_!lM8Z!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b365c87-59d4-49da-8046-769952b2d715_1178x1068.heic 1272w, https://substackcdn.com/image/fetch/$s_!lM8Z!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b365c87-59d4-49da-8046-769952b2d715_1178x1068.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!lM8Z!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b365c87-59d4-49da-8046-769952b2d715_1178x1068.heic" width="536" height="485.9490662139219" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2b365c87-59d4-49da-8046-769952b2d715_1178x1068.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1068,&quot;width&quot;:1178,&quot;resizeWidth&quot;:536,&quot;bytes&quot;:60569,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/170630595?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b365c87-59d4-49da-8046-769952b2d715_1178x1068.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!lM8Z!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b365c87-59d4-49da-8046-769952b2d715_1178x1068.heic 424w, https://substackcdn.com/image/fetch/$s_!lM8Z!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b365c87-59d4-49da-8046-769952b2d715_1178x1068.heic 848w, https://substackcdn.com/image/fetch/$s_!lM8Z!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b365c87-59d4-49da-8046-769952b2d715_1178x1068.heic 1272w, https://substackcdn.com/image/fetch/$s_!lM8Z!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b365c87-59d4-49da-8046-769952b2d715_1178x1068.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Screenshot from Notion. You can add &#8216;toggle&#8217; list to write things inside each one and nest them inside. It&#8217;s useful to include subcategories.</figcaption></figure></div><p>On Friday, I did the exercise of going over each of the things I learned from Monday to Friday. Checking what I documented and rereading it to recall it. </p><p>This took me about 20-30 minutes at the end of the day, and I felt it was a powerful way of fixing that knowledge. </p><p>Giving room for your mind to process everything it went through the week, may feel overwhelming at first, but it helps your brain settle the information you&#8217;ve been learning. </p><p>Creating your own note taking methodology can make wonders in the long term. It can make a compound effect and help you advance in areas you feel stuck, understand concepts better, apply them or discard them for others that might be more suitable for your project. It&#8217;s your choice. </p><h3>Key Takeaways</h3><ul><li><p>Whether you&#8217;re advancing on your data career or you&#8217;re more experienced, writing down and organizing your notes will help you retain the daily information better. </p></li><li><p>Choose any tool you want, physical or digital, the important is to have one you feel comfortable with.</p></li><li><p>Make the effort of writing things daily, just a few comprehensive lines of what you&#8217;ve learnt that day and put aside some minutes at the end of the week to go over it. </p></li><li><p>Ask AI to help you ease the way, be it summarizing, understanding, or reframing ideas. </p></li></ul><p>You&#8217;ll see the big picture at the end of the week and adjust your methodology for a next occasion. </p><p>Hope this idea is valuable to you, and if you have any suggestions on what other note-taking methods are helpful, feel free to comment! </p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The NetPass! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>See you next time, </p><p>Ricardo. </p><p></p>]]></content:encoded></item><item><title><![CDATA[Using Agentic IDEs for Football Analytics]]></title><description><![CDATA[How you can create projects coding with AI, and a brief comparison of Cursor vs. Trae]]></description><link>https://ricardoheredia.substack.com/p/using-agentic-ides-for-football-analytics</link><guid isPermaLink="false">https://ricardoheredia.substack.com/p/using-agentic-ides-for-football-analytics</guid><dc:creator><![CDATA[Ricardo Heredia]]></dc:creator><pubDate>Tue, 12 Aug 2025 12:07:18 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!waLc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7437c5a6-d527-407b-b929-e47f01c7539b_1795x1074.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!waLc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7437c5a6-d527-407b-b929-e47f01c7539b_1795x1074.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!waLc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7437c5a6-d527-407b-b929-e47f01c7539b_1795x1074.jpeg 424w, https://substackcdn.com/image/fetch/$s_!waLc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7437c5a6-d527-407b-b929-e47f01c7539b_1795x1074.jpeg 848w, https://substackcdn.com/image/fetch/$s_!waLc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7437c5a6-d527-407b-b929-e47f01c7539b_1795x1074.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!waLc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7437c5a6-d527-407b-b929-e47f01c7539b_1795x1074.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!waLc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7437c5a6-d527-407b-b929-e47f01c7539b_1795x1074.jpeg" width="1795" height="1074" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7437c5a6-d527-407b-b929-e47f01c7539b_1795x1074.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1074,&quot;width&quot;:1795,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:225580,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/170630648?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2fe3b39-603e-4e12-95db-cb4cf3392f2a_1920x1080.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!waLc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7437c5a6-d527-407b-b929-e47f01c7539b_1795x1074.jpeg 424w, https://substackcdn.com/image/fetch/$s_!waLc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7437c5a6-d527-407b-b929-e47f01c7539b_1795x1074.jpeg 848w, https://substackcdn.com/image/fetch/$s_!waLc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7437c5a6-d527-407b-b929-e47f01c7539b_1795x1074.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!waLc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7437c5a6-d527-407b-b929-e47f01c7539b_1795x1074.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Writing code has changed in the last a couple of years. When ChatGPT appeared in the map, using a chat window and asking GPT to create something was a new way of interacting with AI. </p><p>This definitely changes the way that code and software is created. </p><p>According to the great Andrej Karpathy, who talked about this at the AI Startup School lecture in San Francisco called &#8220;<strong>Software Is Changing (Again)&#8221;<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a>, </strong>by comparing an old vs. new paradigm<strong> </strong>on creating software:<strong> </strong></p><blockquote><p><strong>&#8220;</strong><em>We now spend more time <strong>thinking, planning, and reviewing</strong> code generated by LLMs than memorizing syntax and programming from scratch</em>&#8221;.</p></blockquote><p>With time, LLMs market has risen, different AI labs have developed their own open and closed source ones. New tools have also been created to help developers improve their workflows by leveraging these models, practically embedding them inside development environments, which are known as: agentic IDEs. </p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">To receive new posts and support my work, consider becoming a free or paid subscriber.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p><h4>What are Agentic IDEs? </h4><p>They are development environments enhanced with AI that assists with code generation. They are also compared to Agentic CLIs (command line interfaces) like Claude Code and Gemini CLI, which can be used from both the terminal and as a chat window. </p><p>These tools offer capabilities like: </p><ul><li><p>A variety of LLMs from different providers to use.</p></li><li><p>Capacity to index your codebase and libraries documentation </p></li><li><p>Model Context Protocols (MCP) &#8594; open standard that connects AI models to external tools, execute actions, and read data sources, through structured interfaces with LLMs.</p></li></ul><ul><li><p>Ability to edit files autonomously, providing tab completions and code suggestions.</p></li><li><p>Help in projects from planning phase to execution phase, leveraging the use of contextual documentation to understand the nuances of the project.</p></li><li><p>Adaptation to your workflows to help amplify your development in your own domain knowledge. </p></li></ul><h4>What are their main challenges?</h4><p>For the last months I&#8217;ve been using Cursor and a couple weeks ago I started using Trae, one that looks like an affordable competitor. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!w1GN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd603d406-cabd-46b4-99f2-2eadef16c953_2546x1430.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!w1GN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd603d406-cabd-46b4-99f2-2eadef16c953_2546x1430.heic 424w, https://substackcdn.com/image/fetch/$s_!w1GN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd603d406-cabd-46b4-99f2-2eadef16c953_2546x1430.heic 848w, https://substackcdn.com/image/fetch/$s_!w1GN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd603d406-cabd-46b4-99f2-2eadef16c953_2546x1430.heic 1272w, https://substackcdn.com/image/fetch/$s_!w1GN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd603d406-cabd-46b4-99f2-2eadef16c953_2546x1430.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!w1GN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd603d406-cabd-46b4-99f2-2eadef16c953_2546x1430.heic" width="1456" height="818" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d603d406-cabd-46b4-99f2-2eadef16c953_2546x1430.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:818,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:232527,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/170630648?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd603d406-cabd-46b4-99f2-2eadef16c953_2546x1430.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!w1GN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd603d406-cabd-46b4-99f2-2eadef16c953_2546x1430.heic 424w, https://substackcdn.com/image/fetch/$s_!w1GN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd603d406-cabd-46b4-99f2-2eadef16c953_2546x1430.heic 848w, https://substackcdn.com/image/fetch/$s_!w1GN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd603d406-cabd-46b4-99f2-2eadef16c953_2546x1430.heic 1272w, https://substackcdn.com/image/fetch/$s_!w1GN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd603d406-cabd-46b4-99f2-2eadef16c953_2546x1430.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!BTUg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2950bdf6-3fe2-4a5d-96bd-6fbd3bda17b3_2220x1200.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!BTUg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2950bdf6-3fe2-4a5d-96bd-6fbd3bda17b3_2220x1200.heic 424w, https://substackcdn.com/image/fetch/$s_!BTUg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2950bdf6-3fe2-4a5d-96bd-6fbd3bda17b3_2220x1200.heic 848w, https://substackcdn.com/image/fetch/$s_!BTUg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2950bdf6-3fe2-4a5d-96bd-6fbd3bda17b3_2220x1200.heic 1272w, https://substackcdn.com/image/fetch/$s_!BTUg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2950bdf6-3fe2-4a5d-96bd-6fbd3bda17b3_2220x1200.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!BTUg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2950bdf6-3fe2-4a5d-96bd-6fbd3bda17b3_2220x1200.heic" width="1456" height="787" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2950bdf6-3fe2-4a5d-96bd-6fbd3bda17b3_2220x1200.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:787,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:130883,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/170630648?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2950bdf6-3fe2-4a5d-96bd-6fbd3bda17b3_2220x1200.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!BTUg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2950bdf6-3fe2-4a5d-96bd-6fbd3bda17b3_2220x1200.heic 424w, https://substackcdn.com/image/fetch/$s_!BTUg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2950bdf6-3fe2-4a5d-96bd-6fbd3bda17b3_2220x1200.heic 848w, https://substackcdn.com/image/fetch/$s_!BTUg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2950bdf6-3fe2-4a5d-96bd-6fbd3bda17b3_2220x1200.heic 1272w, https://substackcdn.com/image/fetch/$s_!BTUg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2950bdf6-3fe2-4a5d-96bd-6fbd3bda17b3_2220x1200.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>These tools are intuitive at first and you can get proficient at using them them pretty quickly, especially if you come from VSCode. </p><p>But like Uncle Ben says: </p><blockquote><p>&#8220;<em><strong>With great power comes great responsibility</strong></em>" &#128375;&#65039;</p></blockquote><p>Things can go sideways pretty fast if you are not on the steering wheel. </p><p>Some of the main challenges I&#8217;ve faced: </p><ul><li><p>Understanding how the different LLMs work, and which one excels at which task.</p></li><li><p>Rate limit: tracking how much of your monthly quota are you consuming. This helps you understand how to prompt better to achieve results in less iterations.</p></li><li><p>Testing different prompt formats, to see what helps to achieve better results with each model.</p></li><li><p>Knowing how to leverage the context window of each model. </p></li><li><p>Keeping the leash tight in Agent mode, trying not to let it go rogue and make extreme codebase changes without supervision.</p></li><li><p>Integrating MCPs using them as extra tools that improves my workflow. Especially the ones that are suitable for my project.</p></li></ul><p>You&#8217;'ll see how to tackle these challenges with a framework I used and how I applied it in two football-related use cases.</p><h4>How can you leverage them for Football Analytics? </h4><p>One of the things I like the most about AI is that it is here to augment our capabilities and help us create opportunities within our domain knowledge.</p><p>In this case, I followed a general framework that you can replicate for any project, it works for both Cursor and Trae. </p><ol><li><p>As soon as you open your project, create <strong>three</strong> files: </p><ol><li><p><strong>rules.mdc</strong>: this one sets the context of the rules<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a> that the agent must follow in each project when generating code. In any conversation, it will consider anything you want your project to have: role the AI must adopt, your Python version, the libraries you use, your coding style, design pattern, etc.</p></li><li><p><strong>project_context.md</strong>: you&#8217;ll entire context, this is the document where you set your project&#8217;s main idea goal, characteristics of the project, steps to achieve it, anything. It&#8217;s an opportunity to describe clearly and concisely what you&#8217;re working on. </p></li><li><p><strong>tasks.m</strong>d: granular description of your project tasks. You can use it as a log so models understand what you&#8217;ve done and your progress.</p></li></ol></li></ol><ol start="2"><li><p><strong>Version Control</strong> initiating <strong>Git</strong> from the beginning of the project: commit changes before accepting the code suggestions from the Agent, if you&#8217;re satisfied then test and proceed. </p><p></p></li><li><p><strong>Index</strong> only necessary folders, files, and libraries documentations at the beginning, this will help the Agent pay attention to your codebase structure and understand the last version of the documentation you&#8217;re using, for example the last version of Pandas or Matplotlib. </p></li></ol><p>In summary:</p><div class="pullquote"><p>Open Project &#8594; create rules.mdc + project context file + initial tasks &#8594; version control &#8594; index codebase and documentation</p></div><h4>Football Examples</h4><h5>Example 1: six&#8209;plot match dashboard</h5><p>For this I needed to do a bunch of stuff: </p><ul><li><p>Scraping match event data from different sources. </p></li><li><p>Cleaning and unifying pitch coordinates and IDs </p></li><li><p>Precalculating the metrics </p></li><li><p>Generate the plotting functions. </p></li></ul><p>You can refer the last article so see what the project is about: <a href="https://ricardoheredia.substack.com/p/building-your-own-football-analytics">Building Your Own Football Analytics Dashboards With Free Data</a></p><p>And I needed to go over each step with a structure. </p><ol><li><p>Files</p><ol><li><p><strong>rules.mdc</strong>: emphasized the generation of the code in functions and simplified code, sometimes LLMs go way over their head and make up stuff.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!3uRn!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a7def2e-2574-4bce-84ef-e7f62e49fe8e_1360x1126.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3uRn!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a7def2e-2574-4bce-84ef-e7f62e49fe8e_1360x1126.heic 424w, https://substackcdn.com/image/fetch/$s_!3uRn!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a7def2e-2574-4bce-84ef-e7f62e49fe8e_1360x1126.heic 848w, https://substackcdn.com/image/fetch/$s_!3uRn!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a7def2e-2574-4bce-84ef-e7f62e49fe8e_1360x1126.heic 1272w, https://substackcdn.com/image/fetch/$s_!3uRn!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a7def2e-2574-4bce-84ef-e7f62e49fe8e_1360x1126.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!3uRn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a7def2e-2574-4bce-84ef-e7f62e49fe8e_1360x1126.heic" width="1360" height="1126" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8a7def2e-2574-4bce-84ef-e7f62e49fe8e_1360x1126.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1126,&quot;width&quot;:1360,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:148336,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/170630648?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a7def2e-2574-4bce-84ef-e7f62e49fe8e_1360x1126.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!3uRn!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a7def2e-2574-4bce-84ef-e7f62e49fe8e_1360x1126.heic 424w, https://substackcdn.com/image/fetch/$s_!3uRn!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a7def2e-2574-4bce-84ef-e7f62e49fe8e_1360x1126.heic 848w, https://substackcdn.com/image/fetch/$s_!3uRn!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a7def2e-2574-4bce-84ef-e7f62e49fe8e_1360x1126.heic 1272w, https://substackcdn.com/image/fetch/$s_!3uRn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a7def2e-2574-4bce-84ef-e7f62e49fe8e_1360x1126.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div></li><li><p><strong>project_context.md: </strong>I went from broad to specific explanation of my project. Main goa, key components, steps to create it, plots characteristics, color and aesthetic I wanted to implement. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!dOOA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ebdeca6-cfb2-4165-9045-cf4388e98536_1586x1064.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dOOA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ebdeca6-cfb2-4165-9045-cf4388e98536_1586x1064.heic 424w, https://substackcdn.com/image/fetch/$s_!dOOA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ebdeca6-cfb2-4165-9045-cf4388e98536_1586x1064.heic 848w, https://substackcdn.com/image/fetch/$s_!dOOA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ebdeca6-cfb2-4165-9045-cf4388e98536_1586x1064.heic 1272w, https://substackcdn.com/image/fetch/$s_!dOOA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ebdeca6-cfb2-4165-9045-cf4388e98536_1586x1064.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!dOOA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ebdeca6-cfb2-4165-9045-cf4388e98536_1586x1064.heic" width="696" height="467.0274725274725" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1ebdeca6-cfb2-4165-9045-cf4388e98536_1586x1064.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:977,&quot;width&quot;:1456,&quot;resizeWidth&quot;:696,&quot;bytes&quot;:95433,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/170630648?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ebdeca6-cfb2-4165-9045-cf4388e98536_1586x1064.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!dOOA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ebdeca6-cfb2-4165-9045-cf4388e98536_1586x1064.heic 424w, https://substackcdn.com/image/fetch/$s_!dOOA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ebdeca6-cfb2-4165-9045-cf4388e98536_1586x1064.heic 848w, https://substackcdn.com/image/fetch/$s_!dOOA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ebdeca6-cfb2-4165-9045-cf4388e98536_1586x1064.heic 1272w, https://substackcdn.com/image/fetch/$s_!dOOA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ebdeca6-cfb2-4165-9045-cf4388e98536_1586x1064.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div></li><li><p><strong>project_log2025.md: </strong>this is the task document where I only set the specific task to accomplish and next steps. </p></li></ol><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GWRg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fc9bc4d-9686-415f-8a86-7f801e6f02e3_1600x324.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GWRg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fc9bc4d-9686-415f-8a86-7f801e6f02e3_1600x324.heic 424w, https://substackcdn.com/image/fetch/$s_!GWRg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fc9bc4d-9686-415f-8a86-7f801e6f02e3_1600x324.heic 848w, https://substackcdn.com/image/fetch/$s_!GWRg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fc9bc4d-9686-415f-8a86-7f801e6f02e3_1600x324.heic 1272w, https://substackcdn.com/image/fetch/$s_!GWRg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fc9bc4d-9686-415f-8a86-7f801e6f02e3_1600x324.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GWRg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fc9bc4d-9686-415f-8a86-7f801e6f02e3_1600x324.heic" width="696" height="141.0164835164835" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7fc9bc4d-9686-415f-8a86-7f801e6f02e3_1600x324.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:295,&quot;width&quot;:1456,&quot;resizeWidth&quot;:696,&quot;bytes&quot;:54641,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/170630648?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fc9bc4d-9686-415f-8a86-7f801e6f02e3_1600x324.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!GWRg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fc9bc4d-9686-415f-8a86-7f801e6f02e3_1600x324.heic 424w, https://substackcdn.com/image/fetch/$s_!GWRg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fc9bc4d-9686-415f-8a86-7f801e6f02e3_1600x324.heic 848w, https://substackcdn.com/image/fetch/$s_!GWRg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fc9bc4d-9686-415f-8a86-7f801e6f02e3_1600x324.heic 1272w, https://substackcdn.com/image/fetch/$s_!GWRg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fc9bc4d-9686-415f-8a86-7f801e6f02e3_1600x324.heic 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p></p></li><li><p><strong>Version control with Git</strong></p></li><li><p><strong>Index files and folders: </strong>in Trae, the context indexes automatically, in Cursor you need to indicating it at the beginning but then files are automatically synced.</p></li></ol><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!n1vx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4478cbe-6830-46d1-a99b-2948b179b912_1970x1020.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!n1vx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4478cbe-6830-46d1-a99b-2948b179b912_1970x1020.heic 424w, https://substackcdn.com/image/fetch/$s_!n1vx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4478cbe-6830-46d1-a99b-2948b179b912_1970x1020.heic 848w, https://substackcdn.com/image/fetch/$s_!n1vx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4478cbe-6830-46d1-a99b-2948b179b912_1970x1020.heic 1272w, https://substackcdn.com/image/fetch/$s_!n1vx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4478cbe-6830-46d1-a99b-2948b179b912_1970x1020.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!n1vx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4478cbe-6830-46d1-a99b-2948b179b912_1970x1020.heic" width="1456" height="754" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c4478cbe-6830-46d1-a99b-2948b179b912_1970x1020.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:754,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:53295,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/170630648?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4478cbe-6830-46d1-a99b-2948b179b912_1970x1020.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!n1vx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4478cbe-6830-46d1-a99b-2948b179b912_1970x1020.heic 424w, https://substackcdn.com/image/fetch/$s_!n1vx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4478cbe-6830-46d1-a99b-2948b179b912_1970x1020.heic 848w, https://substackcdn.com/image/fetch/$s_!n1vx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4478cbe-6830-46d1-a99b-2948b179b912_1970x1020.heic 1272w, https://substackcdn.com/image/fetch/$s_!n1vx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4478cbe-6830-46d1-a99b-2948b179b912_1970x1020.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p>From this point onwards,  is a back and forth iteration, tweaking the documents, and adapting the prompts to obtain satisfactory outputs from the LLMs.</p><p>Some of the <strong>challenges</strong>: the model confused coordinate systems (0&#8211;100 vs 120&#215;80), misnamed some columns, or repeated different Matplotlib functions. Had to pass the dimensions explicitly in a document to be used as context. </p><h5>Example 2: on&#8209;ball sequences with GPT&#8209;5 in Cursor (Trae didn&#8217;t have it yet)</h5><p>Sequence helps you not only analyze what happened in a match (player passed a ball in a specific direction and zone of the field) but also &#8216;<strong>how</strong>&#8217; it happened <strong>before</strong> and <strong>after</strong> that, it adds context. </p><p>I asked GPT&#8209;5 to find sequences based on my data from Salzburg vs. Real Madrid in the CWC, and gave it freedom to pick any event and any player. I did it in 3 steps: </p><ul><li><p>Asked it to adopt the role of a PhD Level Football Machine Learning Engineer and that it needed to understand my codebase and recent progress. </p></li><li><p>Indexed my event data, so it could understand the type of events and specifications of the plots colors.</p></li><li><p>I asked it to plot coordinates X and Y of any event and any player. </p></li></ul><p>It chose a pass where Dean Huijsen receives deep on the left in his own half and carries into the attacking half on the same flank. </p><p>Then plotted two examples with a dark mplsoccer theme and label the player. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Xslj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f462093-6b95-445d-b0a7-1518d93323f5_1996x726.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Xslj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f462093-6b95-445d-b0a7-1518d93323f5_1996x726.heic 424w, https://substackcdn.com/image/fetch/$s_!Xslj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f462093-6b95-445d-b0a7-1518d93323f5_1996x726.heic 848w, https://substackcdn.com/image/fetch/$s_!Xslj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f462093-6b95-445d-b0a7-1518d93323f5_1996x726.heic 1272w, https://substackcdn.com/image/fetch/$s_!Xslj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f462093-6b95-445d-b0a7-1518d93323f5_1996x726.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Xslj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f462093-6b95-445d-b0a7-1518d93323f5_1996x726.heic" width="1456" height="530" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8f462093-6b95-445d-b0a7-1518d93323f5_1996x726.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:530,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:32781,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/170630648?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f462093-6b95-445d-b0a7-1518d93323f5_1996x726.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Xslj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f462093-6b95-445d-b0a7-1518d93323f5_1996x726.heic 424w, https://substackcdn.com/image/fetch/$s_!Xslj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f462093-6b95-445d-b0a7-1518d93323f5_1996x726.heic 848w, https://substackcdn.com/image/fetch/$s_!Xslj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f462093-6b95-445d-b0a7-1518d93323f5_1996x726.heic 1272w, https://substackcdn.com/image/fetch/$s_!Xslj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f462093-6b95-445d-b0a7-1518d93323f5_1996x726.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>It filtered events, computed distance gained (about 39&#8211;43m in two cases), and drew the trajectory of the sequence. </p><p>The <strong>takeaway</strong>: when your instruction is specific and concrete, agentic IDEs translate it into working code quickly.</p><h4>How to get reliable results from the models</h4><ul><li><p>Be specific with inputs: a well-described tasks, specific code format (generate functions). </p></li><li><p>Paste snippets of your information (e.g. rows of your data frame) and state plotting specifications. </p></li><li><p>Index your context: point the Agent to the exact files or docs you want it to use.</p></li><li><p>Have it explain the logic in plain language before you run anything. </p></li></ul><h4>Quick comparison between Cursor vs Trae based on my experience</h4><h5>Cursor </h5><p>Is one of the most populars, I personally find these specs useful: </p><ul><li><p>Agent mode in Claude Sonnet 4: best model I&#8217;ve tested inside Cursor, it provides well structured code and understands the codebase when you give it the entire context. </p></li><li><p>MCP integration: most of the MCPs have integration for Cursor, for example setting Supabase was easier here than in Trae which is newer. </p></li><li><p>Haven&#8217;t tried but looks interesting: Background Agents &#8594; edit and run code in a remote environment.</p></li><li><p>Broader range of models: for small tasks the Cursor small own model helped me for writing specifications for project and I also liked using Deepseek v3.1 for coding, it was pretty solid. </p></li><li><p>Something I didn&#8217;t like: the rate limit. With pro plan ($20 a month), you were suppose to have unlimited requests but one day they changed it quietly and people started to hit rate limits all of a sudden. </p></li></ul><h5>Trae</h5><ul><li><p>Is cheaper: first month $3, next bill $10.</p></li><li><p>Has two modes: </p><ul><li><p>Builder: to execute routine and end-to-end tasks. </p></li><li><p>Builder with MCP: use MCP servers to run tasks. </p></li></ul></li><li><p>MCP: setting them is easier than in Cursor and they have a marketplace where you can grab and the ones you need. </p></li><li><p>Haven&#8217;t tried but looks interesting: Custom Agent &#8594; use MCP tools and built-in ones from Trae to use a specific Agent for specific tasks. </p></li><li><p>Needs more popularity but they are clear with the limits you have 600 a month.</p></li><li><p>Something I didn&#8217;t like: they have a SOLO builder mode which is more autonomous and you can see the development of your app during the whole process: backend and frontend, but you have to join a waitlist to get an invitation codes that hasn&#8217;t arrived yet. </p></li></ul><p>To help you evaluate them deeply you can check these two sources to help you decide: </p><p><a href="https://www.datacamp.com/tutorial/trae-ai">Trae AI: A Guide With Practical Examples</a></p><p><a href="https://www.datacamp.com/tutorial/cursor-ai-code-editor">Cursor AI: A Guide With 10 Practical Examples</a></p><h4>Final thoughts</h4><p>Agentic IDEs can help you move fast from any question you have to working code. </p><p>Start small: aim for iteration and then repeatable workflows. Keep guardrails in place: index your documents, do sanity&#8209;checks after every iteration, have the IDE generate simple tests, and ask models to state assumptions before coding. </p><p>As you polish prompts and set rules, you&#8217;ll see the improvements. </p><div class="pullquote"><p>Open Project &#8594; create rules.mdc + project context file + initial tasks &#8594; version control &#8594; index codebase and documentation</p></div><p></p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p><a href="https://www.youtube.com/watch?v=LCEmiRjPEtQ">Link to Lecture</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p><a href="https://github.com/PatrickJS/awesome-cursorrules/tree/main">Awesome Cursor Rules</a></p></div></div>]]></content:encoded></item><item><title><![CDATA[Building Your Own Football Analytics Dashboards With Free Data]]></title><description><![CDATA[A template you can use for further automations]]></description><link>https://ricardoheredia.substack.com/p/building-your-own-football-analytics</link><guid isPermaLink="false">https://ricardoheredia.substack.com/p/building-your-own-football-analytics</guid><dc:creator><![CDATA[Ricardo Heredia]]></dc:creator><pubDate>Sun, 27 Jul 2025 07:31:48 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!si8p!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238480ed-bd03-471a-b935-4f27b0b0b3e3_2370x1751.heic" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3>What&#8217;s a match dashboard? </h3><p>Is a comprehensive visual report that provides a <em>quick</em>-<em>analytical</em> overview of a football match. </p><p>If you missed a match or watched the 90+ minutes and you want to review the statistics quickly, a dashboard helps you get an overview of the tactical and performance insights in one place.</p><p>In case you're tracking a league as an analyst, as a scout to flag a player, or even as fan that wants to know how your favorite team performed this weekend, building them can make a difference in how fast you retrieve that information. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!si8p!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238480ed-bd03-471a-b935-4f27b0b0b3e3_2370x1751.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!si8p!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238480ed-bd03-471a-b935-4f27b0b0b3e3_2370x1751.heic 424w, https://substackcdn.com/image/fetch/$s_!si8p!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238480ed-bd03-471a-b935-4f27b0b0b3e3_2370x1751.heic 848w, https://substackcdn.com/image/fetch/$s_!si8p!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238480ed-bd03-471a-b935-4f27b0b0b3e3_2370x1751.heic 1272w, https://substackcdn.com/image/fetch/$s_!si8p!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238480ed-bd03-471a-b935-4f27b0b0b3e3_2370x1751.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!si8p!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238480ed-bd03-471a-b935-4f27b0b0b3e3_2370x1751.heic" width="725" height="535.782967032967" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/238480ed-bd03-471a-b935-4f27b0b0b3e3_2370x1751.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1076,&quot;width&quot;:1456,&quot;resizeWidth&quot;:725,&quot;bytes&quot;:304201,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/169314648?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238480ed-bd03-471a-b935-4f27b0b0b3e3_2370x1751.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!si8p!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238480ed-bd03-471a-b935-4f27b0b0b3e3_2370x1751.heic 424w, https://substackcdn.com/image/fetch/$s_!si8p!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238480ed-bd03-471a-b935-4f27b0b0b3e3_2370x1751.heic 848w, https://substackcdn.com/image/fetch/$s_!si8p!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238480ed-bd03-471a-b935-4f27b0b0b3e3_2370x1751.heic 1272w, https://substackcdn.com/image/fetch/$s_!si8p!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F238480ed-bd03-471a-b935-4f27b0b0b3e3_2370x1751.heic 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Match Report from Club World Cup Match between Salzburg and Real Madrid.  </figcaption></figure></div><p>I built this dashboard using: </p><ul><li><p>Python 3.10</p></li><li><p>Beautiful Soup </p></li><li><p>Pandas</p></li><li><p>NumPy</p></li><li><p>Pandas</p></li><li><p>Matplolib</p></li><li><p>Mplsoccer </p></li></ul><p>The goal was to build a template with just 6 key analytical plots:</p><ul><li><p>Passing Networks: Shows team shape, player positions, and passing combinations.</p></li><li><p>Defensive Actions: Reveals pressing intensity, defensive positioning, and team compactness.</p></li><li><p>Progressive Passes: Analyzes forward progression and attacking build-up patterns</p></li><li><p>Shot Map: Comprehensive shooting analysis with xG, shot types, and quality assessment.</p></li><li><p>xT Momentum: Tracks dangerous situation creation, goals, and match momentum shifts over time. </p></li><li><p>Match Statistics: Side-by-side comparison of key performance metrics between teams.</p></li></ul><h3>Where to get the data from? </h3><p>This is the most important part. </p><p>In this case I needed event data for only one match, using coordinates from different situations in the offensive and defensive phases like: Passes, Progressive Passes, Interceptions, Blocks, etc. </p><p>These coordinates are represented as X and Y, paired with its end_x and end_y. This helps understanding where and when a situation started, same as where it ended on the pitch.</p><p>WhoScored was my go to place to obtain the majority of them. But I was still missing the shots coordinates. Fotmob has them, though it&#8217;s a tricky place to obtain them. </p><blockquote><p><em>I suggest you to visit the GitHub repo and give the scraping logic a look: <a href="https://github.com/ricardoherediaj/football-analytics-tutorials/blob/main/notebooks/cwc_scraping_test.ipynb">https://github.com/ricardoherediaj/football-analytics tutorials/blob/main/notebooks/cwc_scraping_test.ipynb</a></em><a href="https://github.com/ricardoherediaj/football-analytics-tutorials/blob/main/notebooks/cwc_scraping_test.ipynb"> </a></p></blockquote><h2>Plotting the Dashboard</h2><p>After obtaining the data sources, I transformed the raw match events into insights. </p><p>In this case I saved the data in CSV and JSON format, you&#8217;ll see it at: <em><a href="https://github.com/ricardoherediaj/football-analytics-tutorials/tree/main/data">https://github.com/ricardoherediaj/football-analytics tutorials/blob/main/data</a></em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!50eZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44a71b7a-2c2b-4a01-bb1f-8ce1998de77d_922x776.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!50eZ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44a71b7a-2c2b-4a01-bb1f-8ce1998de77d_922x776.heic 424w, https://substackcdn.com/image/fetch/$s_!50eZ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44a71b7a-2c2b-4a01-bb1f-8ce1998de77d_922x776.heic 848w, https://substackcdn.com/image/fetch/$s_!50eZ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44a71b7a-2c2b-4a01-bb1f-8ce1998de77d_922x776.heic 1272w, https://substackcdn.com/image/fetch/$s_!50eZ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44a71b7a-2c2b-4a01-bb1f-8ce1998de77d_922x776.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!50eZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44a71b7a-2c2b-4a01-bb1f-8ce1998de77d_922x776.heic" width="498" height="419.1409978308026" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/44a71b7a-2c2b-4a01-bb1f-8ce1998de77d_922x776.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:776,&quot;width&quot;:922,&quot;resizeWidth&quot;:498,&quot;bytes&quot;:23836,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/169314648?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44a71b7a-2c2b-4a01-bb1f-8ce1998de77d_922x776.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!50eZ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44a71b7a-2c2b-4a01-bb1f-8ce1998de77d_922x776.heic 424w, https://substackcdn.com/image/fetch/$s_!50eZ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44a71b7a-2c2b-4a01-bb1f-8ce1998de77d_922x776.heic 848w, https://substackcdn.com/image/fetch/$s_!50eZ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44a71b7a-2c2b-4a01-bb1f-8ce1998de77d_922x776.heic 1272w, https://substackcdn.com/image/fetch/$s_!50eZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44a71b7a-2c2b-4a01-bb1f-8ce1998de77d_922x776.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><ul><li><p>df_events contains the main events and coordinates I used for the plotting</p></li><li><p>match_events.json and matchdict.json contain players numbers and shirts </p></li><li><p>shots_df includes the shots data from Fotmob in the match</p></li><li><p>xT_grid.csv has the values to understand the highest and lowest threat actions a team makes during a match on the pitch. </p></li></ul><p>Assisted by Claude Sonnet 4 inside the Cursor IDE, I designed this template around six plots that I found interesting for the dashboard. </p><p>I selected just six to try not to overcrowd the report. Each plot shows specific characteristics of team&#8217;s performances.</p><h3>1. Passing Networks</h3><p>Shows the team shape, players average positions, and passing combinations.</p><p>I also calculated measures for <strong>verticality</strong>, to see how direct a team's passing is. I'm also tracking the <strong>defensive line</strong>, <strong>forward line</strong>, and <strong>team median position</strong> to understand how compact or stretched a team's shape is.</p><p>When you visualize them size-by-size, Salzburg's network might show a compact, possession-based approach with short passing triangles, while Real Madrid could display a more vertical, counter-attacking structure with longer passing connections.</p><p>I converted WhoScored coordinates (0-100 scale) to StatsBomb format (0-120x0-80) for consistency across all visualizations. </p><p>The bidirectional pass combinations reveal which player partnerships are most active during the match.</p><h3>2. Defensive Actions</h3><p>This heat map shows where each team applies pressure and wins possession. </p><p>I tracked every tackle, interception, ball recovery, and blocked pass, then creating a KDE (kernel density estimation) heat map that shows the intensity of defensive actions across the pitch. </p><p>The <strong>Defensive Action Height</strong> metric tells you how high up the pitch a team typically wins the ball.</p><p>Combined with the <strong>compactness percentage</strong>, you can immediately see if a team is playing a high press or sitting deep.</p><h3>3. Progressive Passes</h3><p>Passes that significantly advance the ball toward the opponent's goal at least 30%.</p><p>The pitch is divided by zones where<strong> </strong>you can see if a team builds attacks primarily through the left flank, through the center, or via the right side.</p><p><strong>Example</strong>: If Salzburg completed 23 progressive passes with 65% coming from the left side, you can deduct they're targeting Real Madrid's right defensive lane.</p><h3>4. Shot Map</h3><p>It shows where shots were taken and incorporates <strong>Expected Goals (xG)</strong>, <strong>big chances</strong>, and different shot outcomes to give you a complete attacking picture.</p><p>Each shot is sized by its xG value and color-coded by outcome. Green circles are goals, hatched circles are saves, and larger markers indicate big chances. This shows you which team created better opportunities, regardless of the final score.</p><p><strong>For example</strong>: a team with 8 shots worth 0.3 xG total had a very different performance than a team with 4 shots worth 1.2 xG total.</p><h3>5. xT Momentum</h3><p>Expected Threat (xT) momentum tracks which team is creating more dangerous situations throughout the match, smoothed over time to show momentum shifts.</p><p>I'm calculating the xT value for every successful pass and carry, then using a weighted rolling window to show how momentum builds and shifts. When you see the line spike upward, that team is creating dangerous situations. When it dips, they're losing control.</p><p>Momentum spikes often correlate with goals, substitutions, or tactical changes. </p><h3>6. Match Statistics</h3><p>The final central plot is a comparative view of key performance metrics. </p><p>Possession percentage, field tilt (percentage of touches in the attacking third), passing accuracy, defensive actions, and PPDA (Passes Per Defensive Action - a pressing intensity metric).</p><h3>Notes on the Development Journey</h3><p>I've left my experimental attempts visible in the notebook because I wanted to show the messy development process before the final dashboard code.</p><p><strong>Experiment 1</strong>: data integration challenges, mixing WhoScored events and Fotmob shot coordinates. Since they&#8217;re different platforms they use different coordinate systems and player ID formats but still the plotting was poor.</p><p><strong>Experiment 2</strong>: used the data preprocessing from experiment 1, builds the layout and makes the visualizations work as subplots rather than standalone plots. This required making three functions to be "subplot-friendly&#8221;. </p><p><strong>Experiment 3</strong>: improved the &#8220;dual ID system&#8221; issue, since WhoScored uses different team IDs than Fotmob, so I needed to map between them correctly for the shot map while keeping everything else consistent.</p><p><strong>Experiment 6:</strong> the final version I'm satisfied with (for now). It did the preprocessing process more straightforward and plotted all six plots into a meaningful dashboard.</p><h3>Next Steps</h3><p>This template is designed to be the foundation for a larger end-to-end football analytics pipeline. The next steps would be:</p><ul><li><p><strong>Modularizing the code</strong> into separate Python scripts for easier maintenance</p></li><li><p><strong>Database integration</strong> in Supabase to store scraped data persistently</p></li><li><p><strong>Automated data collection</strong> <strong>and reports visualization</strong> using GitHub Actions or similar</p></li><li><p><strong>Individual players performance reports</strong></p></li><li><p><strong>Obtaining data for more leagues and matches </strong></p></li></ul><p>Once you have the template working for one match, you can generate these reports for any match in any league, as long as you get the underlying event data.</p><p>The goal of this is to think it a systematic approach to football analysis that combines the best of data science with tactical understanding. </p><p>Each visualization answers specific questions that matter to different stakeholders:</p><ul><li><p><strong>Coaches</strong> can see their team's tactical execution and identify areas for improvement</p></li><li><p><strong>Scouts</strong> can quickly assess player and team performance across multiple matches</p></li><li><p><strong>Analysts</strong> can spot patterns and trends that aren't visible from watching alone</p></li><li><p><strong>Developers/Fans</strong> can understand the tactical nuances of matches beyond just the final score</p></li></ul><p>I invite you to grab a cup of coffee, subscribe to my newsletter, and give it a check to the repo: https://github.com/ricardoherediaj/football-analytics-tutorials/blob/main/notebooks/match_dashboard_template.ipynb</p><p>You might learn something new, discover something to improve, or ideas to make your own football plots!</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://ricardoheredia.substack.com/subscribe?"><span>Subscribe now</span></a></p><p></p><h4>References</h4><p>Special mention to the main reference I based on: </p><p>https://github.com/adnaaan433/Post-Match-Report-2.0/tree/main</p><p></p><p></p><p></p><p></p><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[How to Use FBRef for Football Scouting with Python?]]></title><description><![CDATA[Using a Free Resource to Recruit Players]]></description><link>https://ricardoheredia.substack.com/p/how-to-use-fbref-for-football-scouting</link><guid isPermaLink="false">https://ricardoheredia.substack.com/p/how-to-use-fbref-for-football-scouting</guid><dc:creator><![CDATA[Ricardo Heredia]]></dc:creator><pubDate>Sun, 20 Jul 2025 18:52:38 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!qaLQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F220b8079-b34c-440d-b745-d645b14b67b0_1400x752.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you google: &#8220;football data&#8221; or &#8220;football statistics&#8221; you&#8217;ll probably see FBRef as one of the firsts websites that offer free statistics. </p><p>It is one of the best places to start when you don&#8217;t have access to paid providers and want to build your own players profiles for scouting, you can leverage this data and <strong>flag</strong> specific players from different leagues. </p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The NetPass! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>This gives you the opportunity to filter players and then check through video that the player you selected actually meets your criteria in the context of the team your scouting for. </p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!iydt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7886135b-f605-4d64-a147-b7ecac759704_395x106.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!iydt!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7886135b-f605-4d64-a147-b7ecac759704_395x106.png 424w, https://substackcdn.com/image/fetch/$s_!iydt!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7886135b-f605-4d64-a147-b7ecac759704_395x106.png 848w, https://substackcdn.com/image/fetch/$s_!iydt!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7886135b-f605-4d64-a147-b7ecac759704_395x106.png 1272w, https://substackcdn.com/image/fetch/$s_!iydt!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7886135b-f605-4d64-a147-b7ecac759704_395x106.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!iydt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7886135b-f605-4d64-a147-b7ecac759704_395x106.png" width="481" height="129.07848101265822" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7886135b-f605-4d64-a147-b7ecac759704_395x106.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:106,&quot;width&quot;:395,&quot;resizeWidth&quot;:481,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!iydt!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7886135b-f605-4d64-a147-b7ecac759704_395x106.png 424w, https://substackcdn.com/image/fetch/$s_!iydt!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7886135b-f605-4d64-a147-b7ecac759704_395x106.png 848w, https://substackcdn.com/image/fetch/$s_!iydt!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7886135b-f605-4d64-a147-b7ecac759704_395x106.png 1272w, https://substackcdn.com/image/fetch/$s_!iydt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7886135b-f605-4d64-a147-b7ecac759704_395x106.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><p>Metrics you can find here: </p><ul><li><p>Attacking stats: passing accuracy, possession, </p></li><li><p>Defensive stats: tackles, blocks, interceptions, clearances, errors. </p></li><li><p>Goal and Shot-creation actions.</p></li><li><p>A basic Scouting report compared with other players from similar leagues.</p></li></ul><p>This can give you an idea of the player performance from a given season. </p><p>I&#8217;ll show you how I scraped data from Championship, League One, and League Two to find a hypothetical signing for Sheffield United.</p><p>I also integrated the FBRef data with the Transfermarkt data, a process I described in my last post: </p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;43dbb74f-0c86-472d-9bf1-1ac930757bcd&quot;,&quot;caption&quot;:&quot;Web scraping has always intrigued me. In my opinion, is one of the best skills you can have in your data science/ML toolbox. It is useful for when you want to build your own custom databases for personal projects and you don&#8217;t have access to paid data providers.&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;How to Scrape Transfermarkt with Python: Data-Driven Player Recruitment using England&#8217;s Championship, League Two, and League One data.&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:313134153,&quot;name&quot;:&quot;Ricardo Heredia&quot;,&quot;bio&quot;:&quot;Writing about data &#8226; AI &#8226; football analytics &#8226; life&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6d582183-8bb5-43cc-ab1a-620ca5f196c5_1200x1500.jpeg&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-07-09T22:52:05.603Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!TnT_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2fd6ac0b-c459-4f53-8868-080fc17f1e8e_1200x670.heic&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://ricardoheredia.substack.com/p/how-to-scrape-transfermarkt-with&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:167941545,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:20,&quot;comment_count&quot;:0,&quot;publication_id&quot;:null,&quot;publication_name&quot;:&quot;The NetPass&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!O21P!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d5e48fe-5cc1-4a9f-94f1-e8eb1cc2c966_400x400.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><h3>My Approach for Scraping FBRef</h3><p>I basically did a two-step process: manual then automatic using only the <em>requests</em>, <em>pandas, </em>and<em> pyjanitor </em>packages.</p><ol><li><p>First, I manually checked the page of the Championship league for the 2024&#8211;2025 season and went tab to tab to get familiar with the metrics I actually needed (they&#8217;re a lot, and most of the time you don&#8217;t need that many). I did this for this league since it basically has the same metrics as League One and League Two.</p><p></p><p>Since I was interested on midfielders and forwards I only used data from all of the tabs except Goalkeepers.</p></li></ol><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!NXun!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F225702b5-5674-4321-bcb6-9ff0b0935cee_1400x606.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!NXun!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F225702b5-5674-4321-bcb6-9ff0b0935cee_1400x606.png 424w, https://substackcdn.com/image/fetch/$s_!NXun!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F225702b5-5674-4321-bcb6-9ff0b0935cee_1400x606.png 848w, https://substackcdn.com/image/fetch/$s_!NXun!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F225702b5-5674-4321-bcb6-9ff0b0935cee_1400x606.png 1272w, https://substackcdn.com/image/fetch/$s_!NXun!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F225702b5-5674-4321-bcb6-9ff0b0935cee_1400x606.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!NXun!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F225702b5-5674-4321-bcb6-9ff0b0935cee_1400x606.png" width="725" height="313.82142857142856" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/225702b5-5674-4321-bcb6-9ff0b0935cee_1400x606.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:606,&quot;width&quot;:1400,&quot;resizeWidth&quot;:725,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!NXun!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F225702b5-5674-4321-bcb6-9ff0b0935cee_1400x606.png 424w, https://substackcdn.com/image/fetch/$s_!NXun!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F225702b5-5674-4321-bcb6-9ff0b0935cee_1400x606.png 848w, https://substackcdn.com/image/fetch/$s_!NXun!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F225702b5-5674-4321-bcb6-9ff0b0935cee_1400x606.png 1272w, https://substackcdn.com/image/fetch/$s_!NXun!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F225702b5-5674-4321-bcb6-9ff0b0935cee_1400x606.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>2. Web scraping: to do this I need to to look at the HTML and tried to find the tabs I wanted to obtain data from. You do this by opening the FBRef URL in Chrome and righ-clicking &#8220;Inspect&#8221;, to check the HTML code.  Then, you get this beautiful Matrix-like mess.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Mb0C!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f465084-39c7-4600-aaa5-5dfc20965cfa_2000x725.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Mb0C!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f465084-39c7-4600-aaa5-5dfc20965cfa_2000x725.png 424w, https://substackcdn.com/image/fetch/$s_!Mb0C!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f465084-39c7-4600-aaa5-5dfc20965cfa_2000x725.png 848w, https://substackcdn.com/image/fetch/$s_!Mb0C!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f465084-39c7-4600-aaa5-5dfc20965cfa_2000x725.png 1272w, https://substackcdn.com/image/fetch/$s_!Mb0C!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f465084-39c7-4600-aaa5-5dfc20965cfa_2000x725.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Mb0C!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f465084-39c7-4600-aaa5-5dfc20965cfa_2000x725.png" width="725" height="262.9120879120879" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4f465084-39c7-4600-aaa5-5dfc20965cfa_2000x725.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:528,&quot;width&quot;:1456,&quot;resizeWidth&quot;:725,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!Mb0C!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f465084-39c7-4600-aaa5-5dfc20965cfa_2000x725.png 424w, https://substackcdn.com/image/fetch/$s_!Mb0C!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f465084-39c7-4600-aaa5-5dfc20965cfa_2000x725.png 848w, https://substackcdn.com/image/fetch/$s_!Mb0C!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f465084-39c7-4600-aaa5-5dfc20965cfa_2000x725.png 1272w, https://substackcdn.com/image/fetch/$s_!Mb0C!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f465084-39c7-4600-aaa5-5dfc20965cfa_2000x725.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The idea is to obtain the information from a table like this: </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qaLQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F220b8079-b34c-440d-b745-d645b14b67b0_1400x752.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qaLQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F220b8079-b34c-440d-b745-d645b14b67b0_1400x752.png 424w, https://substackcdn.com/image/fetch/$s_!qaLQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F220b8079-b34c-440d-b745-d645b14b67b0_1400x752.png 848w, https://substackcdn.com/image/fetch/$s_!qaLQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F220b8079-b34c-440d-b745-d645b14b67b0_1400x752.png 1272w, https://substackcdn.com/image/fetch/$s_!qaLQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F220b8079-b34c-440d-b745-d645b14b67b0_1400x752.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qaLQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F220b8079-b34c-440d-b745-d645b14b67b0_1400x752.png" width="1400" height="752" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/220b8079-b34c-440d-b745-d645b14b67b0_1400x752.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:752,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!qaLQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F220b8079-b34c-440d-b745-d645b14b67b0_1400x752.png 424w, https://substackcdn.com/image/fetch/$s_!qaLQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F220b8079-b34c-440d-b745-d645b14b67b0_1400x752.png 848w, https://substackcdn.com/image/fetch/$s_!qaLQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F220b8079-b34c-440d-b745-d645b14b67b0_1400x752.png 1272w, https://substackcdn.com/image/fetch/$s_!qaLQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F220b8079-b34c-440d-b745-d645b14b67b0_1400x752.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>I used this function for that: </p><pre><code><code>def get_clean_table(url, table_id):
    """
    Fetches and cleans a table from fbref.com given a URL and a table ID.

    Args:
        url (str): The URL of the webpage containing the table.
        table_id (str): The 'id' attribute of the HTML table.

    Returns:
        pd.DataFrame: The cleaned and ready-to-use DataFrame.
    """
    # Make the request and get the HTML content
    response = requests.get(url)
    html = response.text.replace('&lt;!--', '').replace('--&gt;', '')

    # Read the specific HTML table
    df = pd.read_html(html, attrs={'id': table_id})[0]

    # Clean the columns with clean_columns from pyjanitor
    # It converts the name of the columns as lower case
    df = clean_columns(df)

    # Fill missing values and reset the index
    df = df.fillna(0).reset_index(drop=True)

    return df</code></code></pre><p>I then used this other function for some data cleaning regarding mutlti-index and columns names so I could get a decent result:</p><pre><code>def clean_columns(df):
    """
    Cleans and flattens the columns of a DataFrame with multi-level indices.

    Args:
        df (pd.DataFrame): The original DataFrame with multi-level column indices.

    Returns:
        pd.DataFrame: The DataFrame with flattened and cleaned columns.
    """
    # Flatten the columns by joining the levels
    df.columns = [' '.join(col).strip() if isinstance(col, tuple) else col for col in df.columns]

    # Rename the columns if necessary
    new_columns = []
    for col in df.columns:
        if 'level_0' in col:
            new_col = col.split()[-1]
        else:
            new_col = col
        new_columns.append(new_col)
    df.columns = new_columns

    return df

def process_dataframe(df):
    """
    Applies additional processing to a DataFrame.

    Args:
        df (pd.DataFrame): The DataFrame to be processed.

    Returns:
        pd.DataFrame: The processed DataFrame.
    """
    # Check for the existence of columns before applying operations
    if 'Age' in df.columns:
        df['Age'] = df['Age'].astype(str).str[:2]
    else:
        df['Age'] = None

    if 'Pos' in df.columns:
        df['Position_2'] = df['Pos'].astype(str).str[3:]
        df['Position'] = df['Pos'].astype(str).str[:2]
    else:
        df['Position_2'] = None
        df['Position'] = None

    if 'Nation' in df.columns:
        df['Nation'] = df['Nation'].astype(str).str.split(' ').str.get(1)
    else:
        df['Nation'] = None

    # Remove columns if they exist
    df = df.drop(columns=['Rk', 'Matches'], errors='ignore')

    # Replace abbreviations with full names
    position_mapping = {'MF': 'Midfielder', 'DF': 'Defender', 'FW': 'Forward', 'GK': 'Goalkeeper'}
    df['Position'] = df['Position'].replace(position_mapping)
    df['Position_2'] = df['Position_2'].replace(position_mapping)

    return df</code></pre><p>And boring but quick manual part: selecting the URLs from each tab I wanted to gather info from and then turning them into dataframes, so I could merge the data from all tabs and visualize all the metrics.</p><pre><code># URLs and table IDs
tables_info = [
    ('https://fbref.com/en/comps/10/stats/Championship-Stats', 'stats_standard'),
    ('https://fbref.com/en/comps/10/shooting/Championship-Stats', 'stats_shooting'),
    ('https://fbref.com/en/comps/10/passing/Championship-Stats', 'stats_passing'),
    ('https://fbref.com/en/comps/10/passing_types/Championship-Stats', 'stats_passing_types'),
    ('https://fbref.com/en/comps/10/gca/Championship-Stats', 'stats_gca'),
    ('https://fbref.com/en/comps/10/defense/Championship-Stats', 'stats_defense'),
    ('https://fbref.com/en/comps/10/possession/Championship-Stats', 'stats_possession'),
    ('https://fbref.com/en/comps/10/playingtime/Championship-Stats', 'stats_playing_time'),
    ('https://fbref.com/en/comps/10/misc/Championship-Stats', 'stats_misc'),
]

# Dictionary to store the processed DataFrames
dataframes = {}

# Iterate over each URL and table ID
for url, table_id in tables_info:
    # Fetch and clean the table
    df = get_clean_table(url, table_id)
    # Apply the additional processing
    df = process_dataframe(df)
    # Store the DataFrame in the dictionary using the table ID as the key
    dataframes[table_id] = df</code></pre><p>Resultant dataframe up till this point:</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!z9XA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F400bdcbc-f431-4353-9b82-c92675bbc783_2000x599.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!z9XA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F400bdcbc-f431-4353-9b82-c92675bbc783_2000x599.png 424w, https://substackcdn.com/image/fetch/$s_!z9XA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F400bdcbc-f431-4353-9b82-c92675bbc783_2000x599.png 848w, https://substackcdn.com/image/fetch/$s_!z9XA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F400bdcbc-f431-4353-9b82-c92675bbc783_2000x599.png 1272w, https://substackcdn.com/image/fetch/$s_!z9XA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F400bdcbc-f431-4353-9b82-c92675bbc783_2000x599.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!z9XA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F400bdcbc-f431-4353-9b82-c92675bbc783_2000x599.png" width="725" height="217.10164835164835" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/400bdcbc-f431-4353-9b82-c92675bbc783_2000x599.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:436,&quot;width&quot;:1456,&quot;resizeWidth&quot;:725,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!z9XA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F400bdcbc-f431-4353-9b82-c92675bbc783_2000x599.png 424w, https://substackcdn.com/image/fetch/$s_!z9XA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F400bdcbc-f431-4353-9b82-c92675bbc783_2000x599.png 848w, https://substackcdn.com/image/fetch/$s_!z9XA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F400bdcbc-f431-4353-9b82-c92675bbc783_2000x599.png 1272w, https://substackcdn.com/image/fetch/$s_!z9XA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F400bdcbc-f431-4353-9b82-c92675bbc783_2000x599.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>To select the relevant metrics for midfielders and forwards I used a dictionary that included key-value pairs of the lists of variables I needed: </p><pre><code><code>columns_to_retain = {
    'stats_standard': ['Player', 'Nation', 'Squad', 'Age', 'Born', 'Playing Time 90s', 'Position_2', 'Position'],
    'stats_passing_types': ['Player', 'Squad', '90s', 'Pass Types TB','Pass Types Sw', 
                            'Pass Types Crs', 'Outcomes Cmp', 'Outcomes Blocks'],
    'stats_passing': ['Player', 'Squad', '90s', 'Total Cmp', 'Total Att', 
       'Total Cmp%', 'Short Cmp', 'Short Att', 
       'Short Cmp%', 'Medium Cmp', 'Medium Att',
       'Medium Cmp%', 'Long Cmp', 'Long Att', 
       'Long Cmp%', 'Ast', '1/3', 'PPA', 'PrgP'],
    'stats_playing_time': ['Player', 'Squad', 'Playing Time 90s', 'Playing Time MP','Playing Time Min'],
    'stats_shooting': ['Player', 'Squad', '90s', 'Standard Gls', 'Standard Sh', 'Standard SoT', 'Standard SoT%',
       'Standard Sh/90', 'Standard SoT/90'],
    'stats_gca': ['Player', 'Squad', '90s', 'SCA SCA','GCA GCA'],
    'stats_defense': ['Player', 'Squad', '90s', 'Tackles Tkl',
       'Tackles TklW', 'Tackles Def 3rd', 'Tackles Mid 3rd', 'Tackles Att 3rd', 'Blocks Blocks', 'Blocks Sh', 'Blocks Pass', 'Int', 'Clr', 'Err'],
    'stats_possession': ['Player', 'Squad', '90s', 'Touches Touches', 'Touches Mid 3rd', 'Touches Att 3rd', 'Touches Att Pen',
       'Take-Ons Att', 'Take-Ons Succ', 'Take-Ons Succ%', 'Carries Carries', 'Carries PrgC', 'Carries 1/3', 'Carries CPA',
       'Carries Mis', 'Carries Dis', 'Receiving Rec', 'Receiving PrgR'],
    'stats_misc': ['Player', 'Squad', '90s', 'Performance Off',
       'Performance Crs', 'Performance Int', 'Performance TklW',
       'Performance Recov', 'Aerial Duels Won', 'Aerial Duels Lost',
       'Aerial Duels Won%']
}</code></code></pre><p>Final function to obtain the merged dataframe with all the selected variables: </p><pre><code>def merge_dataframes(dataframes_dict, columns_dict):
    """
    Merges the dataframes from `dataframes_dict` by filtering the required columns from `columns_dict`.

    Args:
        dataframes_dict (dict): Dictionary of processed dataframes.
        columns_dict (dict): Dictionary with the columns to retain for each dataframe.

    Returns:
        pd.DataFrame: Merged DataFrame with the specified columns.
    """
    filtered_dfs = []
    
    # Filter the columns to retain from each dataframe, only if the columns exist
    for key, df in dataframes_dict.items():
        if key in columns_dict:
            print(f"Columns available in '{key}': {df.columns.tolist()}")  # Debug: print available columns
            columns_to_retain = [col for col in columns_dict[key] if col in df.columns]
            print(f"Columns to retain for '{key}': {columns_to_retain}")  # Debug: print columns to retain
            df_filtered = df[columns_to_retain].copy()
            df_filtered.columns = [f"{col}_{key}" if col not in ['Player', 'Squad'] else col for col in df_filtered.columns]
            filtered_dfs.append(df_filtered)
    
    # Concatenate all dataframes on 'Player' and 'Squad'
    merged_df = pd.concat(filtered_dfs, axis=1)
    
    # Remove duplicate columns for 'Player' and 'Squad'
    merged_df = merged_df.loc[:, ~merged_df.columns.duplicated()]
    
    return merged_df


merged_dataframe = merge_dataframes(dataframes, columns_to_retain)</code></pre><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!q0Mh!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d78b489-9cda-45f6-8297-655b15e15239_2000x506.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!q0Mh!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d78b489-9cda-45f6-8297-655b15e15239_2000x506.png 424w, https://substackcdn.com/image/fetch/$s_!q0Mh!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d78b489-9cda-45f6-8297-655b15e15239_2000x506.png 848w, https://substackcdn.com/image/fetch/$s_!q0Mh!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d78b489-9cda-45f6-8297-655b15e15239_2000x506.png 1272w, https://substackcdn.com/image/fetch/$s_!q0Mh!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d78b489-9cda-45f6-8297-655b15e15239_2000x506.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!q0Mh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d78b489-9cda-45f6-8297-655b15e15239_2000x506.png" width="728" height="184" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0d78b489-9cda-45f6-8297-655b15e15239_2000x506.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:368,&quot;width&quot;:1456,&quot;resizeWidth&quot;:728,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!q0Mh!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d78b489-9cda-45f6-8297-655b15e15239_2000x506.png 424w, https://substackcdn.com/image/fetch/$s_!q0Mh!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d78b489-9cda-45f6-8297-655b15e15239_2000x506.png 848w, https://substackcdn.com/image/fetch/$s_!q0Mh!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d78b489-9cda-45f6-8297-655b15e15239_2000x506.png 1272w, https://substackcdn.com/image/fetch/$s_!q0Mh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0d78b489-9cda-45f6-8297-655b15e15239_2000x506.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>The dataframe still had a lot of NaN values that needed to be cleansed, but the process to obtain data for other leagues (League One and League Two in this case) is good to go.</p><p>I need to mention that I used these references as inspiration to drive my own analysis: </p><p><a href="https://medium.com/@ricardoandreom/how-to-scrape-and-personalize-data-from-fbref-with-python-a-guide-to-unlocking-football-insights-7e623607afca">How to scrape and personalize data from FBref with Python: A guide to unlocking Football Insights</a></p><p><a href="https://www.youtube.com/watch?v=I0TB9m_hyCo">The Super Easy Way to Scrape FBREF for Free Soccer Data</a></p><p>There are also other approaches like this one from Henrik who kindly referenced mine: </p><p><a href="https://medium.com/@henrik.schjoth/scraping-fbref-creating-a-pipeline-f5c9c23ba9da">Scraping Fbref &#8212;Creating a Pipeline</a></p><p></p><p>So, if you&#8217;re into scouting/football analytics and what to try it for yourself, give it a go! </p><p>There&#8217;s more than one way to get to a solution. </p><p>I encourage you to find yours and see how it works. </p><p></p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The NetPass! Subscribe for free to receive new posts and support this space.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[How to Scrape Transfermarkt with Python: Data-Driven Player Recruitment using England’s Championship, League Two, and League One data.]]></title><description><![CDATA[Web scraping has always intrigued me.]]></description><link>https://ricardoheredia.substack.com/p/how-to-scrape-transfermarkt-with</link><guid isPermaLink="false">https://ricardoheredia.substack.com/p/how-to-scrape-transfermarkt-with</guid><dc:creator><![CDATA[Ricardo Heredia]]></dc:creator><pubDate>Wed, 09 Jul 2025 22:52:05 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!TnT_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2fd6ac0b-c459-4f53-8868-080fc17f1e8e_1200x670.heic" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!TnT_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2fd6ac0b-c459-4f53-8868-080fc17f1e8e_1200x670.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!TnT_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2fd6ac0b-c459-4f53-8868-080fc17f1e8e_1200x670.heic 424w, https://substackcdn.com/image/fetch/$s_!TnT_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2fd6ac0b-c459-4f53-8868-080fc17f1e8e_1200x670.heic 848w, https://substackcdn.com/image/fetch/$s_!TnT_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2fd6ac0b-c459-4f53-8868-080fc17f1e8e_1200x670.heic 1272w, https://substackcdn.com/image/fetch/$s_!TnT_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2fd6ac0b-c459-4f53-8868-080fc17f1e8e_1200x670.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!TnT_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2fd6ac0b-c459-4f53-8868-080fc17f1e8e_1200x670.heic" width="1200" height="670" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2fd6ac0b-c459-4f53-8868-080fc17f1e8e_1200x670.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:670,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:34329,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/167941545?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2fd6ac0b-c459-4f53-8868-080fc17f1e8e_1200x670.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!TnT_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2fd6ac0b-c459-4f53-8868-080fc17f1e8e_1200x670.heic 424w, https://substackcdn.com/image/fetch/$s_!TnT_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2fd6ac0b-c459-4f53-8868-080fc17f1e8e_1200x670.heic 848w, https://substackcdn.com/image/fetch/$s_!TnT_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2fd6ac0b-c459-4f53-8868-080fc17f1e8e_1200x670.heic 1272w, https://substackcdn.com/image/fetch/$s_!TnT_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2fd6ac0b-c459-4f53-8868-080fc17f1e8e_1200x670.heic 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Web scraping has always intrigued me. In my opinion, is one of the best skills you can have in your data science/ML toolbox. It is useful for when you want to build your own custom databases for personal projects and you don&#8217;t have access to paid data providers.</p><h1><strong>Using Web Scraping For A Project</strong></h1><p>I&#8217;ll show you how I approached a past project using web scraping. I wanted to identify two players profiles: </p><ul><li><p>A central midfielder with a mixed profile (good in both defense and attack)</p></li><li><p>A striker with good aerial game and ball retention.</p></li></ul><p>I focused on finding five players for each position that fit the profiles based on different metrics from FBRef, the team&#8217;s playing style and the economic context of the team, where Transfermarkt helps a lot with players value market. </p><p>For this, I randomly chose Sheffield United from the Championship to carry on with the analysis.</p><p>To get to know Sheffield&#8217;s playing style and what they needed I analyzed three matches and identified positions that could benefit from these signings.</p><blockquote><p><em>For more insights on how to analyze a team performance you can read this post about how I applied this framework for Como 1907 from Serie A: <a href="https://ricardoheredia.substack.com/p/the-art-of-football-data-scouting?r=56fjux">Como 1907 Team Analysis for Data Scouting</a></em></p></blockquote><p></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!reIY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7170ebc3-987f-4bb5-9272-b5c147adce2b_800x800.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!reIY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7170ebc3-987f-4bb5-9272-b5c147adce2b_800x800.heic 424w, https://substackcdn.com/image/fetch/$s_!reIY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7170ebc3-987f-4bb5-9272-b5c147adce2b_800x800.heic 848w, https://substackcdn.com/image/fetch/$s_!reIY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7170ebc3-987f-4bb5-9272-b5c147adce2b_800x800.heic 1272w, https://substackcdn.com/image/fetch/$s_!reIY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7170ebc3-987f-4bb5-9272-b5c147adce2b_800x800.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!reIY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7170ebc3-987f-4bb5-9272-b5c147adce2b_800x800.heic" width="376" height="376" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7170ebc3-987f-4bb5-9272-b5c147adce2b_800x800.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:800,&quot;width&quot;:800,&quot;resizeWidth&quot;:376,&quot;bytes&quot;:60061,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/167941545?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7170ebc3-987f-4bb5-9272-b5c147adce2b_800x800.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!reIY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7170ebc3-987f-4bb5-9272-b5c147adce2b_800x800.heic 424w, https://substackcdn.com/image/fetch/$s_!reIY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7170ebc3-987f-4bb5-9272-b5c147adce2b_800x800.heic 848w, https://substackcdn.com/image/fetch/$s_!reIY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7170ebc3-987f-4bb5-9272-b5c147adce2b_800x800.heic 1272w, https://substackcdn.com/image/fetch/$s_!reIY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7170ebc3-987f-4bb5-9272-b5c147adce2b_800x800.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><h3>How to Know Players Value Market? </h3><p>To achieve this, I needed to gather data from Transfermarkt. </p><p>For those unfamiliar with this web page, it is a place that offers a variety of data points that are helpful to identify potential players: </p><ul><li><p>Age.</p></li><li><p>Country.</p></li><li><p>Contract</p></li><li><p>Positions</p></li><li><p>Market values. </p></li></ul><p>To do this efficiently, I needed an automated way to extract player information directly from Transfermarkt, which led me to build a web scraper.</p><h1><strong>Designing the Scraper: Building Process and Core Components</strong></h1><p>In order to build the scraper, I first needed to understand what and how I was going to do it. So I wanted to see if somebody else did it first and fortunately, someone did. These two Medium articles were my go-to references to help me go through this task:</p><blockquote><p><em><a href="https://blog.devgenius.io/get-to-know-the-greatest-football-league-in-the-world-with-python-and-transfermarkt-25a7cfa6b136">https://blog.devgenius.io/get-to-know-the-greatest-football-league-in-the-world-with-python-and-transfermarkt-25a7cfa6b136</a></em></p><p><em><a href="https://medium.com/@conalhenderson/how-to-build-a-custom-web-scraper-to-extract-premier-league-player-market-data-3b8e5378cca2">https://medium.com/@conalhenderson/how-to-build-a-custom-web-scraper-to-extract-premier-league-player-market-data-3b8e5378cca2</a></em></p></blockquote><p>I specially followed Conal&#8217;s comprehensive tutorial to build my own custom web scraper, as he shows how to do it exactly but with Liverpool&#8217;s and Premier League data, so it was a matter of going through it, running the code and understanding the process that happens under the hood when scraping Transfermarkt.</p><p>It was challenging, honestly. But after a few days I managed to replicate the exact same process for my goal: obtaining England&#8217;s tier 2, 3 and 4 data. </p><p>The bright side, is that I learned a new way of web scraping and improved capabilities on Python coding, which is necessary for when you want your code to be more readable and scalable as your project grows.</p><p>I won&#8217;t get into each detail of the code though, if you&#8217;re looking to do some web scraping, I highly recommend following the tutorial to better understand step by step where everything comes from and the final output, since it requires some attention if you don&#8217;t know German (all of Transfermarkt source code is in German). </p><p>I&#8217;ll focus on the core parts I included in my pipeline.</p><p>So, to make the scraper as modular and efficient as possible, and using Python flexible capabilities, I designed it with some key components:</p><ol><li><p><strong>Abstract Parser Class</strong>: I used an Abstract Base Class (<code>Parser</code>) as a template for all specific parsers which helped obtain different types of player data. </p><p></p><p>As you&#8217;ll see in the image I focused on getting these data points from all the players: names, ages, countries, market values, and positions (plus the team and the season), because these were the ones I could get, somehow, I couldn&#8217;t manage to obtain other datapoints from the HTML source (got to look into that), but I believe these were the most helpful for my goal.</p></li></ol><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!WMW5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67e58b89-2aad-4199-b6a4-53a2a3d6964e_2000x1623.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!WMW5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67e58b89-2aad-4199-b6a4-53a2a3d6964e_2000x1623.png 424w, https://substackcdn.com/image/fetch/$s_!WMW5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67e58b89-2aad-4199-b6a4-53a2a3d6964e_2000x1623.png 848w, https://substackcdn.com/image/fetch/$s_!WMW5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67e58b89-2aad-4199-b6a4-53a2a3d6964e_2000x1623.png 1272w, https://substackcdn.com/image/fetch/$s_!WMW5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67e58b89-2aad-4199-b6a4-53a2a3d6964e_2000x1623.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!WMW5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67e58b89-2aad-4199-b6a4-53a2a3d6964e_2000x1623.png" width="1456" height="1182" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/67e58b89-2aad-4199-b6a4-53a2a3d6964e_2000x1623.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1182,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!WMW5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67e58b89-2aad-4199-b6a4-53a2a3d6964e_2000x1623.png 424w, https://substackcdn.com/image/fetch/$s_!WMW5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67e58b89-2aad-4199-b6a4-53a2a3d6964e_2000x1623.png 848w, https://substackcdn.com/image/fetch/$s_!WMW5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67e58b89-2aad-4199-b6a4-53a2a3d6964e_2000x1623.png 1272w, https://substackcdn.com/image/fetch/$s_!WMW5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67e58b89-2aad-4199-b6a4-53a2a3d6964e_2000x1623.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>By breaking the parsing into smaller, independent classes, you can maintain a cleaner code and made modifications easier in the feature without affecting other components.</p><p><strong>2. Dataclasses for Structured Data</strong>: To organize my code and ensure type safety, I used Python&#8217;s <code>dataclass</code> to create a <code>Team</code> class. This helped me encapsulate relevant information such as the team ID and name, and it was an efficient way to pass data around the scraper.</p><p><strong>3. The Scraper Class</strong>: It takes a team, a list of parsers, and then extracts data from Transfermarkt. The structure of the URL allowed for programmatic generation by passing in the team ID and name, making the whole process automated and highly scalable.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4pkl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57c61305-aaff-4a9e-be55-1939fcc188e8_2000x1579.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4pkl!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57c61305-aaff-4a9e-be55-1939fcc188e8_2000x1579.png 424w, https://substackcdn.com/image/fetch/$s_!4pkl!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57c61305-aaff-4a9e-be55-1939fcc188e8_2000x1579.png 848w, https://substackcdn.com/image/fetch/$s_!4pkl!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57c61305-aaff-4a9e-be55-1939fcc188e8_2000x1579.png 1272w, https://substackcdn.com/image/fetch/$s_!4pkl!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57c61305-aaff-4a9e-be55-1939fcc188e8_2000x1579.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4pkl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57c61305-aaff-4a9e-be55-1939fcc188e8_2000x1579.png" width="1456" height="1150" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/57c61305-aaff-4a9e-be55-1939fcc188e8_2000x1579.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1150,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!4pkl!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57c61305-aaff-4a9e-be55-1939fcc188e8_2000x1579.png 424w, https://substackcdn.com/image/fetch/$s_!4pkl!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57c61305-aaff-4a9e-be55-1939fcc188e8_2000x1579.png 848w, https://substackcdn.com/image/fetch/$s_!4pkl!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57c61305-aaff-4a9e-be55-1939fcc188e8_2000x1579.png 1272w, https://substackcdn.com/image/fetch/$s_!4pkl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57c61305-aaff-4a9e-be55-1939fcc188e8_2000x1579.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This part of the code shows the main <code>Scraper</code> class I mentioned, which fetches data for a given team and year, and allows you to scale the scraping across different teams by utilizing a uniform URL structure. </p><p>It uses BeautifulSoup to retrieve the HTML and <strong>httpx </strong>with custom headers to mimic a browser. Also, using &#8216;time.sleep(5)&#8217; is critical to use to avoid overwhelming the server, getting kicked out and blocked in the future.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!W7FN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff64ac657-444a-4571-95dd-980b8815cad9_1656x832.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!W7FN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff64ac657-444a-4571-95dd-980b8815cad9_1656x832.png 424w, https://substackcdn.com/image/fetch/$s_!W7FN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff64ac657-444a-4571-95dd-980b8815cad9_1656x832.png 848w, https://substackcdn.com/image/fetch/$s_!W7FN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff64ac657-444a-4571-95dd-980b8815cad9_1656x832.png 1272w, https://substackcdn.com/image/fetch/$s_!W7FN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff64ac657-444a-4571-95dd-980b8815cad9_1656x832.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!W7FN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff64ac657-444a-4571-95dd-980b8815cad9_1656x832.png" width="728" height="366" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f64ac657-444a-4571-95dd-980b8815cad9_1656x832.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:732,&quot;width&quot;:1456,&quot;resizeWidth&quot;:728,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!W7FN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff64ac657-444a-4571-95dd-980b8815cad9_1656x832.png 424w, https://substackcdn.com/image/fetch/$s_!W7FN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff64ac657-444a-4571-95dd-980b8815cad9_1656x832.png 848w, https://substackcdn.com/image/fetch/$s_!W7FN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff64ac657-444a-4571-95dd-980b8815cad9_1656x832.png 1272w, https://substackcdn.com/image/fetch/$s_!W7FN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff64ac657-444a-4571-95dd-980b8815cad9_1656x832.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h1><strong>The Result: Structured CSV file ready to use for scouting analysis</strong></h1><p>The final dataset included the information I meant to scrape: player names, ages, countries, positions, and market values, which I saved into CSV files for further analysis.</p><p>Additionally, I uploaded the data to Supabase in different SQL tables for each league to make it easily accessible for querying and integration with other tools afterwards.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!AM2W!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F406d4a5e-8fa0-4b8c-8e2c-45f82278a95f_1427x635.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!AM2W!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F406d4a5e-8fa0-4b8c-8e2c-45f82278a95f_1427x635.png 424w, https://substackcdn.com/image/fetch/$s_!AM2W!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F406d4a5e-8fa0-4b8c-8e2c-45f82278a95f_1427x635.png 848w, https://substackcdn.com/image/fetch/$s_!AM2W!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F406d4a5e-8fa0-4b8c-8e2c-45f82278a95f_1427x635.png 1272w, https://substackcdn.com/image/fetch/$s_!AM2W!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F406d4a5e-8fa0-4b8c-8e2c-45f82278a95f_1427x635.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!AM2W!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F406d4a5e-8fa0-4b8c-8e2c-45f82278a95f_1427x635.png" width="1427" height="635" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/406d4a5e-8fa0-4b8c-8e2c-45f82278a95f_1427x635.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:635,&quot;width&quot;:1427,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!AM2W!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F406d4a5e-8fa0-4b8c-8e2c-45f82278a95f_1427x635.png 424w, https://substackcdn.com/image/fetch/$s_!AM2W!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F406d4a5e-8fa0-4b8c-8e2c-45f82278a95f_1427x635.png 848w, https://substackcdn.com/image/fetch/$s_!AM2W!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F406d4a5e-8fa0-4b8c-8e2c-45f82278a95f_1427x635.png 1272w, https://substackcdn.com/image/fetch/$s_!AM2W!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F406d4a5e-8fa0-4b8c-8e2c-45f82278a95f_1427x635.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This allows me to have a central structured storage and to query this data quickly, be it inside Supabase or using a connection to that database and clean the data with Pandas in another development environment.</p><h1><strong>Key Takeaways</strong></h1><ul><li><p>Handling the intricacies and best practices of web scraping is tough, but necessary to execute repetitive processes effectively. </p></li><li><p>Breaking the code into modular pieces using classes and parsers, makes it easier to extend the scraper and add new features as needed.</p></li><li><p>Storing the scraped data in a database helps to maintain a centralized storage for further analyses.</p></li></ul><p>Here&#8217;s the link to project in case you want to reference the code: <a href="https://github.com/ricardoherediaj/data-driven-scouting-project">Data Driven Scouting Project</a></p><div><hr></div><p>I&#8217;d love to hear your thoughts or discuss any challenges you&#8217;ve faced when web scraping data.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/p/how-to-scrape-transfermarkt-with/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://ricardoheredia.substack.com/p/how-to-scrape-transfermarkt-with/comments"><span>Leave a comment</span></a></p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading till the end! Subscribe for free to read more about how you can apply data, ML and AI to football or your own niche.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[The Art of Football Data Scouting (II): 3 Steps to Find Potential Signings]]></title><description><![CDATA[Spotting Players with Driblab Pro]]></description><link>https://ricardoheredia.substack.com/p/the-art-of-football-data-scouting-d2a</link><guid isPermaLink="false">https://ricardoheredia.substack.com/p/the-art-of-football-data-scouting-d2a</guid><dc:creator><![CDATA[Ricardo Heredia]]></dc:creator><pubDate>Sun, 06 Jul 2025 20:40:56 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/4b9f590e-e590-46d2-a92d-58d08117aac3_944x932.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In my last article, I talked about how data can help build football squads and how I was using this approach to spot potential signings for Como 1907. I&#8217;ve made a shortlist of these players and I&#8217;ll go over their profiles and why I think they meet Como&#8217;s criteria for season 25/26.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The NetPass! Subscribe for <strong>free</strong> to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h3>Quick Recap</h3><p>To recap, there are <strong>3 steps</strong> I&#8217;ve taken to carry out this analysis: </p><ol><li><p><strong>Full Team Analysis</strong>: I&#8217;ve analyzed Como&#8217;s performance in Serie A 24/25 and how they performed in offensive and defensive phases. I also compared them with the other teams in the league. With this, I wanted to spot areas of improvements within the squad.</p></li><li><p><strong>Profile Identification </strong>: based on what the team needs, I identified specific profiles that can fulfill that necessity. </p></li><li><p><strong>Search &amp; Comparison</strong>: For that, I used <strong>Driblab&#8217;s</strong> data hub to shortlist interesting players based on specific criteria.</p></li></ol><p>I&#8217;ll develop the last 2 points and final conclusions on the players I shortlisted.</p><h3>Profile Identification</h3><ul><li><p><strong>Attacking Left Back: </strong>an attacking fullback with good physical ability, dribbling, and crossing skills to provide more width and depth on the left flank. Alberto Moreno&#8217;s contract ends in June 2025, so it&#8217;s key to anticipate his possible departure and secure a quality replacement.</p></li><li><p><strong>Attacking Right Back:</strong> an attacking fullback who can strengthen the right side and create synergy with the right winger. Ideally he can carry the ball forward and deliver crosses into the box, but also has good passing quality.</p></li><li><p><strong>Right Winger: </strong>there&#8217;s a need for more dribbling and quality crosses from the right wing to diversify the attack and create more goal-scoring chances. Ability to get in behind and provide depth. Would add competition and alternatives to Strefezza.</p></li><li><p><strong>Center Forward: </strong>there&#8217;s a need for more physical presence and effectiveness in the box to make the most of crosses and increase chances conversion. A striker who wins aerial duels and is clinical, giving the team more finishing options.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!M8lK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6db28d64-5497-4a78-b7a7-49fee0b4b4b7_868x1226.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!M8lK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6db28d64-5497-4a78-b7a7-49fee0b4b4b7_868x1226.heic 424w, https://substackcdn.com/image/fetch/$s_!M8lK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6db28d64-5497-4a78-b7a7-49fee0b4b4b7_868x1226.heic 848w, https://substackcdn.com/image/fetch/$s_!M8lK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6db28d64-5497-4a78-b7a7-49fee0b4b4b7_868x1226.heic 1272w, https://substackcdn.com/image/fetch/$s_!M8lK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6db28d64-5497-4a78-b7a7-49fee0b4b4b7_868x1226.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!M8lK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6db28d64-5497-4a78-b7a7-49fee0b4b4b7_868x1226.heic" width="310" height="437.85714285714283" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6db28d64-5497-4a78-b7a7-49fee0b4b4b7_868x1226.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1226,&quot;width&quot;:868,&quot;resizeWidth&quot;:310,&quot;bytes&quot;:26437,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/167654547?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6db28d64-5497-4a78-b7a7-49fee0b4b4b7_868x1226.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!M8lK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6db28d64-5497-4a78-b7a7-49fee0b4b4b7_868x1226.heic 424w, https://substackcdn.com/image/fetch/$s_!M8lK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6db28d64-5497-4a78-b7a7-49fee0b4b4b7_868x1226.heic 848w, https://substackcdn.com/image/fetch/$s_!M8lK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6db28d64-5497-4a78-b7a7-49fee0b4b4b7_868x1226.heic 1272w, https://substackcdn.com/image/fetch/$s_!M8lK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6db28d64-5497-4a78-b7a7-49fee0b4b4b7_868x1226.heic 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Selected profiles in a 1-4-2-3-1 line up.</figcaption></figure></div><h3>Search &amp; Comparison</h3><p>After I had identified the profiles, it was time to search for the players. </p><p>Driblab has a &#8216;<strong>Scout</strong>&#8217; tab that allows to search players worldwide, filtering by different parameters. I only had access to the top 5 leagues, but still it was an awesome setting to test this feature.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!sDBe!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fedbe981c-e3d0-46cb-9fb3-69b376cac835_2808x1628.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!sDBe!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fedbe981c-e3d0-46cb-9fb3-69b376cac835_2808x1628.jpeg 424w, https://substackcdn.com/image/fetch/$s_!sDBe!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fedbe981c-e3d0-46cb-9fb3-69b376cac835_2808x1628.jpeg 848w, https://substackcdn.com/image/fetch/$s_!sDBe!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fedbe981c-e3d0-46cb-9fb3-69b376cac835_2808x1628.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!sDBe!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fedbe981c-e3d0-46cb-9fb3-69b376cac835_2808x1628.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!sDBe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fedbe981c-e3d0-46cb-9fb3-69b376cac835_2808x1628.jpeg" width="687" height="398.3034188034188" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/edbe981c-e3d0-46cb-9fb3-69b376cac835_2808x1628.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1628,&quot;width&quot;:2808,&quot;resizeWidth&quot;:687,&quot;bytes&quot;:552489,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/167654547?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2435fa3d-b723-40d9-a69c-6f080b2d150d_2808x1628.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!sDBe!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fedbe981c-e3d0-46cb-9fb3-69b376cac835_2808x1628.jpeg 424w, https://substackcdn.com/image/fetch/$s_!sDBe!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fedbe981c-e3d0-46cb-9fb3-69b376cac835_2808x1628.jpeg 848w, https://substackcdn.com/image/fetch/$s_!sDBe!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fedbe981c-e3d0-46cb-9fb3-69b376cac835_2808x1628.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!sDBe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fedbe981c-e3d0-46cb-9fb3-69b376cac835_2808x1628.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Driblab Pro </figcaption></figure></div><p>With this, you can select players and make shortlists, build radar plots of each selected player and compare them with the ones from your squad and pretty much build your own database of selected players. </p><p>To search players, I considered: team performance, specific KPIs, and the economic context, something important for clubs, because there&#8217;s a budget sporting directions need to stick to. Aspects I looked into: </p><ul><li><p>Age of recent signings &#8594; young players with an average of 26 y/o. Veteran players (over 30) with leadership, signed as free agents or at low cost, mixing experience with youth in the squad.</p></li><li><p>Players on loan with an option to buy, or direct transfers/purchases.</p></li></ul><ul><li><p>Market value &#8594; range from &#8364; 100K - &#8364; 10M</p></li><li><p>Year End Contract &#8594; Summer 2025 (preferably)</p></li><li><p>Top 5 Leagues: &#8594; Serie A, Bundesliga, Premier League, LaLiga, Ligue 1. </p></li><li><p>Specific Positions &#8594;  i.e. Attacking Midfielder Left - AML</p></li><li><p>KPIs&#8594; Driblab scores (&gt;45), crosses, passing, minimum minutes played (450&#8217;), xG, xA, etc.</p></li></ul><h4>Shortlisted Players</h4><h5>Players Radars and Comparison With Como Players</h5><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!S2iM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8fb37e8-e593-4202-8008-9b28fe8bb9ab_1610x2090.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!S2iM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8fb37e8-e593-4202-8008-9b28fe8bb9ab_1610x2090.png 424w, https://substackcdn.com/image/fetch/$s_!S2iM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8fb37e8-e593-4202-8008-9b28fe8bb9ab_1610x2090.png 848w, https://substackcdn.com/image/fetch/$s_!S2iM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8fb37e8-e593-4202-8008-9b28fe8bb9ab_1610x2090.png 1272w, https://substackcdn.com/image/fetch/$s_!S2iM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8fb37e8-e593-4202-8008-9b28fe8bb9ab_1610x2090.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!S2iM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8fb37e8-e593-4202-8008-9b28fe8bb9ab_1610x2090.png" width="1456" height="1890" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a8fb37e8-e593-4202-8008-9b28fe8bb9ab_1610x2090.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1890,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:880839,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/167654547?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8fb37e8-e593-4202-8008-9b28fe8bb9ab_1610x2090.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!S2iM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8fb37e8-e593-4202-8008-9b28fe8bb9ab_1610x2090.png 424w, https://substackcdn.com/image/fetch/$s_!S2iM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8fb37e8-e593-4202-8008-9b28fe8bb9ab_1610x2090.png 848w, https://substackcdn.com/image/fetch/$s_!S2iM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8fb37e8-e593-4202-8008-9b28fe8bb9ab_1610x2090.png 1272w, https://substackcdn.com/image/fetch/$s_!S2iM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa8fb37e8-e593-4202-8008-9b28fe8bb9ab_1610x2090.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Javi Gal&#225;n Summary</strong></p><p>Left back with great physical ability and the capacity to advance with the ball down the wing. He provides depth on the left, with a high percentage of successful passes and dribbles. Reliable in offensive progression, though he can be impulsive defensively, bringing speed, dribbling, and solidity to the left side.</p><p></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GIyw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3eed16e0-0b35-412d-b43d-9850800c3f87_1670x2130.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GIyw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3eed16e0-0b35-412d-b43d-9850800c3f87_1670x2130.png 424w, https://substackcdn.com/image/fetch/$s_!GIyw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3eed16e0-0b35-412d-b43d-9850800c3f87_1670x2130.png 848w, https://substackcdn.com/image/fetch/$s_!GIyw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3eed16e0-0b35-412d-b43d-9850800c3f87_1670x2130.png 1272w, https://substackcdn.com/image/fetch/$s_!GIyw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3eed16e0-0b35-412d-b43d-9850800c3f87_1670x2130.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GIyw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3eed16e0-0b35-412d-b43d-9850800c3f87_1670x2130.png" width="728" height="928.5" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3eed16e0-0b35-412d-b43d-9850800c3f87_1670x2130.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1857,&quot;width&quot;:1456,&quot;resizeWidth&quot;:728,&quot;bytes&quot;:881217,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/167654547?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3eed16e0-0b35-412d-b43d-9850800c3f87_1670x2130.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!GIyw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3eed16e0-0b35-412d-b43d-9850800c3f87_1670x2130.png 424w, https://substackcdn.com/image/fetch/$s_!GIyw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3eed16e0-0b35-412d-b43d-9850800c3f87_1670x2130.png 848w, https://substackcdn.com/image/fetch/$s_!GIyw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3eed16e0-0b35-412d-b43d-9850800c3f87_1670x2130.png 1272w, https://substackcdn.com/image/fetch/$s_!GIyw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3eed16e0-0b35-412d-b43d-9850800c3f87_1670x2130.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Alvaro Tejero Summary</strong></p><p>Attacking and versatile right back. He crosses well, creates chances, and is reliable in building out from the back. While he doesn&#8217;t stand out defensively, he would add attacking depth and quality crosses to diversify play down the flanks.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!B_DR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F409969a4-ebe5-4c49-9f28-b18e579a4890_1582x2096.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!B_DR!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F409969a4-ebe5-4c49-9f28-b18e579a4890_1582x2096.png 424w, https://substackcdn.com/image/fetch/$s_!B_DR!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F409969a4-ebe5-4c49-9f28-b18e579a4890_1582x2096.png 848w, https://substackcdn.com/image/fetch/$s_!B_DR!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F409969a4-ebe5-4c49-9f28-b18e579a4890_1582x2096.png 1272w, https://substackcdn.com/image/fetch/$s_!B_DR!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F409969a4-ebe5-4c49-9f28-b18e579a4890_1582x2096.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!B_DR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F409969a4-ebe5-4c49-9f28-b18e579a4890_1582x2096.png" width="1456" height="1929" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/409969a4-ebe5-4c49-9f28-b18e579a4890_1582x2096.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1929,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:845977,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/167654547?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F409969a4-ebe5-4c49-9f28-b18e579a4890_1582x2096.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!B_DR!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F409969a4-ebe5-4c49-9f28-b18e579a4890_1582x2096.png 424w, https://substackcdn.com/image/fetch/$s_!B_DR!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F409969a4-ebe5-4c49-9f28-b18e579a4890_1582x2096.png 848w, https://substackcdn.com/image/fetch/$s_!B_DR!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F409969a4-ebe5-4c49-9f28-b18e579a4890_1582x2096.png 1272w, https://substackcdn.com/image/fetch/$s_!B_DR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F409969a4-ebe5-4c49-9f28-b18e579a4890_1582x2096.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Junya Ito Summary</strong></p><p>Fast and productive right winger, excellent at beating defenders and delivering crosses. He provides assists and scores from deep positions, also contributing defensively. Although his goal contribution is low, he offers speed and unpredictability on the wing.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_Lg_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde681204-00e5-4245-93d8-95fe77051353_1516x2080.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_Lg_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde681204-00e5-4245-93d8-95fe77051353_1516x2080.png 424w, https://substackcdn.com/image/fetch/$s_!_Lg_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde681204-00e5-4245-93d8-95fe77051353_1516x2080.png 848w, https://substackcdn.com/image/fetch/$s_!_Lg_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde681204-00e5-4245-93d8-95fe77051353_1516x2080.png 1272w, https://substackcdn.com/image/fetch/$s_!_Lg_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde681204-00e5-4245-93d8-95fe77051353_1516x2080.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_Lg_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde681204-00e5-4245-93d8-95fe77051353_1516x2080.png" width="1456" height="1998" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/de681204-00e5-4245-93d8-95fe77051353_1516x2080.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1998,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:850555,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/167654547?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde681204-00e5-4245-93d8-95fe77051353_1516x2080.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!_Lg_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde681204-00e5-4245-93d8-95fe77051353_1516x2080.png 424w, https://substackcdn.com/image/fetch/$s_!_Lg_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde681204-00e5-4245-93d8-95fe77051353_1516x2080.png 848w, https://substackcdn.com/image/fetch/$s_!_Lg_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde681204-00e5-4245-93d8-95fe77051353_1516x2080.png 1272w, https://substackcdn.com/image/fetch/$s_!_Lg_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde681204-00e5-4245-93d8-95fe77051353_1516x2080.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Mbala N&#8217;Zola Summary</strong></p><p>Center Forward with a strong presence in the box, excels in physical duels and aerial play. He stands out for his finishing, ability to shield the ball, and pressing high up the pitch. While he doesn&#8217;t contribute much in creation or dribbling, he adds finishing, power, and is a key attacking reference in the opponent&#8217;s area.</p><h3>Final Conclusions</h3><ul><li><p><strong>Diagnosis and Strategic Solution:</strong> Como 1907&#8217;s play is overly centralized, with a heavy reliance on Nico Paz and low efficiency in the opponent&#8217;s box. The proposed signings directly address these needs by strengthening the flanks and improving the team&#8217;s attacking aerial game.</p><p></p></li><li><p><strong>Expected Tactical Impact of the Signings:</strong></p><ul><li><p><strong>Javi Gal&#225;n and &#193;lvaro Tejero:</strong> would provide depth and width on both flanks, diversifying attacking options and increasing the quality of crosses into the box.</p></li><li><p><strong>Junya Ito:</strong> would complement Strefezza, adding unpredictability, speed, and the ability to dominate the right wing.</p></li><li><p><strong>Mbala N'Zola:</strong> will bring physical presence in the box, improving offensive aerial play and finishing.</p><p></p></li></ul></li><li><p><strong>Economic Viability:</strong> The selected players represent a sustainable investment (range &#8364;1.8M&#8211;&#8364;6M) with potential for increased value, aligned with the club&#8217;s recent transfer policy and with contracts that allow for medium-term planning.</p></li></ul><p>This is my personal approach on tackling a data scouting analysis. Always considering data as an asset that complements the on-site and/or video remote scouting, for a well-rounded informed process.</p><div class="captioned-button-wrap" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/p/the-art-of-football-data-scouting-d2a?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="CaptionedButtonToDOM"><div class="preamble"><p class="cta-caption">Thanks for reading The NetPass! Share this post to anyone you think would enjoy talking about football and data.</p></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/p/the-art-of-football-data-scouting-d2a?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://ricardoheredia.substack.com/p/the-art-of-football-data-scouting-d2a?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p></div>]]></content:encoded></item><item><title><![CDATA[The Art of Football Data Scouting: Building Teams With Data-Driven Decisions]]></title><description><![CDATA[How to Use Raw Statistics To Build Competitive Squads]]></description><link>https://ricardoheredia.substack.com/p/the-art-of-football-data-scouting</link><guid isPermaLink="false">https://ricardoheredia.substack.com/p/the-art-of-football-data-scouting</guid><dc:creator><![CDATA[Ricardo Heredia]]></dc:creator><pubDate>Fri, 27 Jun 2025 07:43:51 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!80QY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7af41b3-7e03-4544-8674-9a2ff560075d_3200x2255.heic" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!80QY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7af41b3-7e03-4544-8674-9a2ff560075d_3200x2255.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!80QY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7af41b3-7e03-4544-8674-9a2ff560075d_3200x2255.heic 424w, https://substackcdn.com/image/fetch/$s_!80QY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7af41b3-7e03-4544-8674-9a2ff560075d_3200x2255.heic 848w, https://substackcdn.com/image/fetch/$s_!80QY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7af41b3-7e03-4544-8674-9a2ff560075d_3200x2255.heic 1272w, https://substackcdn.com/image/fetch/$s_!80QY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7af41b3-7e03-4544-8674-9a2ff560075d_3200x2255.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!80QY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7af41b3-7e03-4544-8674-9a2ff560075d_3200x2255.heic" width="563" height="396.7293956043956" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f7af41b3-7e03-4544-8674-9a2ff560075d_3200x2255.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1026,&quot;width&quot;:1456,&quot;resizeWidth&quot;:563,&quot;bytes&quot;:366364,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/166757129?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7af41b3-7e03-4544-8674-9a2ff560075d_3200x2255.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!80QY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7af41b3-7e03-4544-8674-9a2ff560075d_3200x2255.heic 424w, https://substackcdn.com/image/fetch/$s_!80QY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7af41b3-7e03-4544-8674-9a2ff560075d_3200x2255.heic 848w, https://substackcdn.com/image/fetch/$s_!80QY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7af41b3-7e03-4544-8674-9a2ff560075d_3200x2255.heic 1272w, https://substackcdn.com/image/fetch/$s_!80QY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7af41b3-7e03-4544-8674-9a2ff560075d_3200x2255.heic 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Como 1907</figcaption></figure></div><h3>Signing Players In the Modern Way</h3><p>If you love sports, you&#8217;ve probably heard the term <strong>Moneyball</strong>. First a book, then a Brad Pitt movie, Moneyball tells the story of how the Oakland Athletics built a playoff team on a low budget. What was the secret? Data. Instead of chasing big names, they found undervalued players, signed them cheap, and sold high using math and statistics.</p><p><strong>Why does this matter for football?</strong></p><p>Because the same principles are changing the game in Europe since not so long ago. Clubs like Brentford and Midtjylland are using data to spot hidden gems and build squads that perform above their level. As Rasmus Ankersen, Brentford&#8217;s former sporting director, put it: &#8220;We look for players with potential and analyze their context&#8212;why haven&#8217;t they reached it yet? It&#8217;s like finding an undervalued stock, buying low, and selling high.&#8221;</p><p>Modern scouting is not only about watching games but using data to see what others miss and turning that insight into results.</p><h3>Starting With the Right Questions: Club Analysis</h3><p>Data is an asset. It helps you filter out noise and focus on the players who actually fit your team&#8217;s needs. That means smarter decisions, fewer wasted transfers, and a bigger impact for every euro/pound/dollar spent.</p><p>Let&#8217;s see this with an example I&#8217;ve been working on. It&#8217;s a case study with Como 1907&#8212;a club on the rise in Serie A. My goal was to: use performance metrics to break down their current squad, understand their transfer strategy, and spot which players from Europe&#8217;s top 5 leagues could improve their level.</p><p><strong>It all starts with the right questions:</strong></p><ul><li><p>What&#8217;s the team&#8217;s game model? How do they play in different phases?</p></li><li><p>Which metrics matter most for their style?</p></li><li><p>How do they stack up against the rest of the league?</p></li><li><p>What&#8217;s their transfer history and scouting philosophy?</p></li><li><p>And most importantly: Who could you sign to level up the squad?</p></li></ul><p>I&#8217;ll walk you through how I tackled each of these, using data from Driblab Pro&#8212;a professional scouting platform I access thanks to my Scouting360 course with Objetivo Analista.</p><h3><strong>Key Performance Indicators: Using Metrics That Matters</strong></h3><p>For Como 1907, I started with a general overview of them, as a presentation card, and then a general variable analysis, looking at the roster age profile and several metrics like own expected goals (xG) and against, attack zones, shot zones, own assists and against. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!snv0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2715b357-26c9-4312-9b82-8a5573ddde53_1035x1002.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!snv0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2715b357-26c9-4312-9b82-8a5573ddde53_1035x1002.heic 424w, https://substackcdn.com/image/fetch/$s_!snv0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2715b357-26c9-4312-9b82-8a5573ddde53_1035x1002.heic 848w, https://substackcdn.com/image/fetch/$s_!snv0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2715b357-26c9-4312-9b82-8a5573ddde53_1035x1002.heic 1272w, https://substackcdn.com/image/fetch/$s_!snv0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2715b357-26c9-4312-9b82-8a5573ddde53_1035x1002.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!snv0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2715b357-26c9-4312-9b82-8a5573ddde53_1035x1002.heic" width="605" height="585.7101449275362" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2715b357-26c9-4312-9b82-8a5573ddde53_1035x1002.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1002,&quot;width&quot;:1035,&quot;resizeWidth&quot;:605,&quot;bytes&quot;:65629,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/166757129?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2715b357-26c9-4312-9b82-8a5573ddde53_1035x1002.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!snv0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2715b357-26c9-4312-9b82-8a5573ddde53_1035x1002.heic 424w, https://substackcdn.com/image/fetch/$s_!snv0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2715b357-26c9-4312-9b82-8a5573ddde53_1035x1002.heic 848w, https://substackcdn.com/image/fetch/$s_!snv0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2715b357-26c9-4312-9b82-8a5573ddde53_1035x1002.heic 1272w, https://substackcdn.com/image/fetch/$s_!snv0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2715b357-26c9-4312-9b82-8a5573ddde53_1035x1002.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Como Overview and Team Roster.</figcaption></figure></div><ul><li><p>Como 1907 is a young team, with an average age of 26.</p></li><li><p>The club made significant investments in the squad over the last two transfer windows.</p></li><li><p>Under Cesc F&#225;bregas&#8217;s attacking philosophy, they finished 10th in the league.</p></li><li><p>The team&#8217;s preferred formation was 4-2-3-1.</p></li><li><p>They have potential to qualify for European competitions.</p></li><li><p>Top 3 players with most minutes played: Jean Butez, Nico Paz, and Kempf.</p></li></ul><h4>Variables Analysis</h4><p>For a quick overview to see how the team attacks, we can look at the attacking zone maps and xG per Shot maps. They attack mostly through the center, with 66.5% of possessions ending in that zone.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_ylT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88ed0f34-e21e-4352-92b8-c78e13d5aee7_1756x692.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_ylT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88ed0f34-e21e-4352-92b8-c78e13d5aee7_1756x692.heic 424w, https://substackcdn.com/image/fetch/$s_!_ylT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88ed0f34-e21e-4352-92b8-c78e13d5aee7_1756x692.heic 848w, https://substackcdn.com/image/fetch/$s_!_ylT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88ed0f34-e21e-4352-92b8-c78e13d5aee7_1756x692.heic 1272w, https://substackcdn.com/image/fetch/$s_!_ylT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88ed0f34-e21e-4352-92b8-c78e13d5aee7_1756x692.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_ylT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88ed0f34-e21e-4352-92b8-c78e13d5aee7_1756x692.heic" width="728" height="287" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/88ed0f34-e21e-4352-92b8-c78e13d5aee7_1756x692.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:574,&quot;width&quot;:1456,&quot;resizeWidth&quot;:728,&quot;bytes&quot;:44257,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/166757129?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88ed0f34-e21e-4352-92b8-c78e13d5aee7_1756x692.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!_ylT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88ed0f34-e21e-4352-92b8-c78e13d5aee7_1756x692.heic 424w, https://substackcdn.com/image/fetch/$s_!_ylT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88ed0f34-e21e-4352-92b8-c78e13d5aee7_1756x692.heic 848w, https://substackcdn.com/image/fetch/$s_!_ylT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88ed0f34-e21e-4352-92b8-c78e13d5aee7_1756x692.heic 1272w, https://substackcdn.com/image/fetch/$s_!_ylT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88ed0f34-e21e-4352-92b8-c78e13d5aee7_1756x692.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Como&#8217;s Attack Zones and xG Per Shot</figcaption></figure></div><p>Defensively, Como had a mix of performances throughout the season. In several matches, they created more and better chances than they conceded, but there were also games where they were outperformed defensively. The team was capable of both attacking with danger and having vulnerable defensive moments, with many balanced matches in between.</p><p></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!HaY6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F510f476d-7753-4a00-8d11-d4b5c427f1bc_1076x500.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!HaY6!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F510f476d-7753-4a00-8d11-d4b5c427f1bc_1076x500.heic 424w, https://substackcdn.com/image/fetch/$s_!HaY6!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F510f476d-7753-4a00-8d11-d4b5c427f1bc_1076x500.heic 848w, https://substackcdn.com/image/fetch/$s_!HaY6!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F510f476d-7753-4a00-8d11-d4b5c427f1bc_1076x500.heic 1272w, https://substackcdn.com/image/fetch/$s_!HaY6!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F510f476d-7753-4a00-8d11-d4b5c427f1bc_1076x500.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!HaY6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F510f476d-7753-4a00-8d11-d4b5c427f1bc_1076x500.heic" width="724" height="336.43122676579924" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/510f476d-7753-4a00-8d11-d4b5c427f1bc_1076x500.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:500,&quot;width&quot;:1076,&quot;resizeWidth&quot;:724,&quot;bytes&quot;:110041,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/166757129?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F510f476d-7753-4a00-8d11-d4b5c427f1bc_1076x500.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!HaY6!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F510f476d-7753-4a00-8d11-d4b5c427f1bc_1076x500.heic 424w, https://substackcdn.com/image/fetch/$s_!HaY6!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F510f476d-7753-4a00-8d11-d4b5c427f1bc_1076x500.heic 848w, https://substackcdn.com/image/fetch/$s_!HaY6!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F510f476d-7753-4a00-8d11-d4b5c427f1bc_1076x500.heic 1272w, https://substackcdn.com/image/fetch/$s_!HaY6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F510f476d-7753-4a00-8d11-d4b5c427f1bc_1076x500.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">xG vs. xG Against</figcaption></figure></div><p>To dig deeper, I broke down the analysis by phases of play in order to compare them with other opponents peers in Serie A:</p><ul><li><p><strong>Offensively</strong>, Como builds up through the center, relying on key creators like Nico Paz, and struggles with xG per shot, they make more shots, but those shots are low quality. Though they show an average position in moving the ball into dangerous areas (the final third of the pitch) compared to other teams in the league.</p></li></ul><p>How do they compare to the rest of Serie A? Como sits around the league average in most metrics, but stands out for ball progression, shots taken and touches in the opposition box. However, their aerial duels and set-piece threat are other areas for improvement.</p><ul><li><p><strong>Defensively</strong>, Como behaves like this compared to the other teams:</p><ul><li><p>Press high and recover balls in advanced areas, ranking among the best in Serie A for pressing intensity (PPDA). Though this intensity drops in the second half, leading to more goals conceded late in games.</p></li><li><p>Concede few shots overall, but the chances they allow are often high quality (higher xG per shot conceded).</p></li><li><p>Very effective at defending set pieces, conceding the lowest xG from set pieces in the league.</p></li></ul></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!i25J!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0f73bec-fe94-4e2e-a8bf-1c7c271cfd50_1732x834.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!i25J!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0f73bec-fe94-4e2e-a8bf-1c7c271cfd50_1732x834.heic 424w, https://substackcdn.com/image/fetch/$s_!i25J!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0f73bec-fe94-4e2e-a8bf-1c7c271cfd50_1732x834.heic 848w, https://substackcdn.com/image/fetch/$s_!i25J!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0f73bec-fe94-4e2e-a8bf-1c7c271cfd50_1732x834.heic 1272w, https://substackcdn.com/image/fetch/$s_!i25J!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0f73bec-fe94-4e2e-a8bf-1c7c271cfd50_1732x834.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!i25J!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0f73bec-fe94-4e2e-a8bf-1c7c271cfd50_1732x834.heic" width="728" height="350.5" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f0f73bec-fe94-4e2e-a8bf-1c7c271cfd50_1732x834.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:701,&quot;width&quot;:1456,&quot;resizeWidth&quot;:728,&quot;bytes&quot;:82720,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/166757129?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0f73bec-fe94-4e2e-a8bf-1c7c271cfd50_1732x834.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!i25J!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0f73bec-fe94-4e2e-a8bf-1c7c271cfd50_1732x834.heic 424w, https://substackcdn.com/image/fetch/$s_!i25J!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0f73bec-fe94-4e2e-a8bf-1c7c271cfd50_1732x834.heic 848w, https://substackcdn.com/image/fetch/$s_!i25J!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0f73bec-fe94-4e2e-a8bf-1c7c271cfd50_1732x834.heic 1272w, https://substackcdn.com/image/fetch/$s_!i25J!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0f73bec-fe94-4e2e-a8bf-1c7c271cfd50_1732x834.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h5>Key Takeaways </h5><p>I started broad, then zoomed in. Using general metrics to spot trends, then breaking them down by phase and comparing to the league to find where the team stands out or falls short.</p><h3>Squad Evaluation:  Finding Gaps in Their Game</h3><p>To better understand what the team needs, is important to understand how they play and identify the areas that need to be improved. Again, it was helpful to make come up with some questions and separate the analysis by game phases. </p><h4>Offensive Phase</h4><h5>Possession &amp; Build Up </h5><ul><li><p>Como builds from the back, relying on defenders and midfielders (Goldaniga, Da Cunha, Nico Paz), which centralizes play.</p></li></ul><h5>Progression and chance creation</h5><ul><li><p>Most progression happens through the center; wide players like Strefezza, Diao, and Fadera are underused for dribbling and crossing.</p></li><li><p>The team could improve by creating more danger from the flanks.</p></li></ul><h5>Danger in the box &amp; Shot Quality</h5><ul><li><p>Cutrone gets the most touches in the box, but Strefezza is more efficient with fewer touches.</p></li><li><p>Only Gabrielloni and Douvikas consistently take high-quality shots; most starters are below average for shot quality.</p></li></ul><p></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!nlIr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d8ce6a2-6d72-4444-9715-ca531e4ce230_1770x1004.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nlIr!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d8ce6a2-6d72-4444-9715-ca531e4ce230_1770x1004.heic 424w, https://substackcdn.com/image/fetch/$s_!nlIr!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d8ce6a2-6d72-4444-9715-ca531e4ce230_1770x1004.heic 848w, https://substackcdn.com/image/fetch/$s_!nlIr!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d8ce6a2-6d72-4444-9715-ca531e4ce230_1770x1004.heic 1272w, https://substackcdn.com/image/fetch/$s_!nlIr!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d8ce6a2-6d72-4444-9715-ca531e4ce230_1770x1004.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!nlIr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d8ce6a2-6d72-4444-9715-ca531e4ce230_1770x1004.heic" width="1456" height="826" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1d8ce6a2-6d72-4444-9715-ca531e4ce230_1770x1004.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:826,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:55036,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/166757129?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d8ce6a2-6d72-4444-9715-ca531e4ce230_1770x1004.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!nlIr!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d8ce6a2-6d72-4444-9715-ca531e4ce230_1770x1004.heic 424w, https://substackcdn.com/image/fetch/$s_!nlIr!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d8ce6a2-6d72-4444-9715-ca531e4ce230_1770x1004.heic 848w, https://substackcdn.com/image/fetch/$s_!nlIr!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d8ce6a2-6d72-4444-9715-ca531e4ce230_1770x1004.heic 1272w, https://substackcdn.com/image/fetch/$s_!nlIr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d8ce6a2-6d72-4444-9715-ca531e4ce230_1770x1004.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Squad offensive bar charts and scatter plots. </figcaption></figure></div><h4>Defensive Phase</h4><h5>Pressing &amp; Recoveries</h5><ul><li><p>Como presses high and recovers balls in advanced areas, led by Nico Paz, Strefezza, and Da Cunha.</p></li><li><p>They concede more goals in the second half, likely due to fatigue and a drop in pressing intensity.</p></li></ul><h5>Defensive Solidity &amp; Defense-to-Attack Transitions</h5><ul><li><p>Goalkeepers (Reina, Butez) and central defenders (Dossena, Enghardt) are strong in aerial duels. Goldaniga and Dossena excel at interceptions.</p></li><li><p>Goldaniga is key for starting attacks from the back progressing the ball to higher areas of the pitch, with support from Da Cunha.</p><p></p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!l1Qd!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec03944-2697-42f1-8410-1c1ae3f70411_1220x1000.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!l1Qd!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec03944-2697-42f1-8410-1c1ae3f70411_1220x1000.png 424w, https://substackcdn.com/image/fetch/$s_!l1Qd!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec03944-2697-42f1-8410-1c1ae3f70411_1220x1000.png 848w, https://substackcdn.com/image/fetch/$s_!l1Qd!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec03944-2697-42f1-8410-1c1ae3f70411_1220x1000.png 1272w, https://substackcdn.com/image/fetch/$s_!l1Qd!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec03944-2697-42f1-8410-1c1ae3f70411_1220x1000.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!l1Qd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec03944-2697-42f1-8410-1c1ae3f70411_1220x1000.png" width="547" height="448.3606557377049" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/aec03944-2697-42f1-8410-1c1ae3f70411_1220x1000.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1000,&quot;width&quot;:1220,&quot;resizeWidth&quot;:547,&quot;bytes&quot;:115733,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/166757129?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec03944-2697-42f1-8410-1c1ae3f70411_1220x1000.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!l1Qd!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec03944-2697-42f1-8410-1c1ae3f70411_1220x1000.png 424w, https://substackcdn.com/image/fetch/$s_!l1Qd!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec03944-2697-42f1-8410-1c1ae3f70411_1220x1000.png 848w, https://substackcdn.com/image/fetch/$s_!l1Qd!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec03944-2697-42f1-8410-1c1ae3f70411_1220x1000.png 1272w, https://substackcdn.com/image/fetch/$s_!l1Qd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec03944-2697-42f1-8410-1c1ae3f70411_1220x1000.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3>What&#8217;s Next? </h3><p>With all this analysis, we&#8217;ve seen Como&#8217;s strengths: solid build-up, intense pressing, and real danger creation. But they still need more width, better shot conversion, and more aerial power in the box. The data points us where to improve.</p><p>Next up: finding the <em>who</em>.</p><p>I&#8217;ll use this data to build a shortlist of transfer targets, matching each pick to the positions and criteria that fit Como&#8217;s game model.</p><p>Curious to see who makes the cut?</p><p><br>I&#8217;ll break it all down in the next article!</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The NetPass! Subscribe for <strong>free</strong> to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/p/the-art-of-football-data-scouting/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://ricardoheredia.substack.com/p/the-art-of-football-data-scouting/comments"><span>Leave a comment</span></a></p><p></p><p></p><p></p><p></p><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[5 Actionable Tips and Resources to Start Analyzing Football Data]]></title><description><![CDATA[Personal lessons I've learned since diving into football data projects]]></description><link>https://ricardoheredia.substack.com/p/5-actionable-tips-and-resources-to</link><guid isPermaLink="false">https://ricardoheredia.substack.com/p/5-actionable-tips-and-resources-to</guid><dc:creator><![CDATA[Ricardo Heredia]]></dc:creator><pubDate>Wed, 11 Jun 2025 20:01:12 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!zZy5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65592ba0-0910-40f5-9094-e7fcb6dc33db_2006x1070.heic" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Like many, I'm passionate about football. A few years ago, I discovered how to extract real value from match data.</p><p>Today I bring 5 tips that helped me get acquainted with how football data is used in real-world settings.</p><h4>1. Start Where the Data Is</h4><p>You don't need special credentials to start. High-quality datasets are readily available on public websites. </p><p>Some of them: </p><ul><li><p>StatsBomb: Granular event data for advanced analysis of top competitions and players (Messi&#8217;s career, Euro, Copa America, Leverkusen unbeaten Bundesliga 2023/2024). <a href="https://statsbomb.com/what-we-do/hub/free-data/">StatsBomb Free Data</a> </p></li><li><p>FBRef: Aggregated stats for team and player comparisons, trend tracking, and scouting. <a href="https://fbref.com/en/">FBRef</a></p></li><li><p>Transfermarkt: The go-to for player profiles, transfer histories, market values, and club finances. <a href="https://www.transfermarkt.en/">Transfermark</a> </p></li><li><p>WhoScored: Detailed match and player stats, including event-by-event breakdowns and player ratings. <a href="https://www.whoscored.com">WhoScored (Opta Data)</a></p></li><li><p>For Video Analysis: Ben Griffis Streaming sheet is the go to: <a href="https://docs.google.com/spreadsheets/d/18QxXLSGo_gqU0lKApfkQOkW9Z-O0sj0AfFNECAbCUOk/edit?gid=0#gid=0">Ben Griffis Free Streaming Sheet</a></p></li></ul><p>Spend time exploring these resources, ask yourself real football questions, and let the data guide your analysis.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!zZy5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65592ba0-0910-40f5-9094-e7fcb6dc33db_2006x1070.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!zZy5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65592ba0-0910-40f5-9094-e7fcb6dc33db_2006x1070.heic 424w, https://substackcdn.com/image/fetch/$s_!zZy5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65592ba0-0910-40f5-9094-e7fcb6dc33db_2006x1070.heic 848w, https://substackcdn.com/image/fetch/$s_!zZy5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65592ba0-0910-40f5-9094-e7fcb6dc33db_2006x1070.heic 1272w, https://substackcdn.com/image/fetch/$s_!zZy5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65592ba0-0910-40f5-9094-e7fcb6dc33db_2006x1070.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!zZy5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65592ba0-0910-40f5-9094-e7fcb6dc33db_2006x1070.heic" width="588" height="313.78846153846155" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/65592ba0-0910-40f5-9094-e7fcb6dc33db_2006x1070.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:777,&quot;width&quot;:1456,&quot;resizeWidth&quot;:588,&quot;bytes&quot;:51221,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/165685677?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65592ba0-0910-40f5-9094-e7fcb6dc33db_2006x1070.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!zZy5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65592ba0-0910-40f5-9094-e7fcb6dc33db_2006x1070.heic 424w, https://substackcdn.com/image/fetch/$s_!zZy5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65592ba0-0910-40f5-9094-e7fcb6dc33db_2006x1070.heic 848w, https://substackcdn.com/image/fetch/$s_!zZy5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65592ba0-0910-40f5-9094-e7fcb6dc33db_2006x1070.heic 1272w, https://substackcdn.com/image/fetch/$s_!zZy5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65592ba0-0910-40f5-9094-e7fcb6dc33db_2006x1070.heic 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Data sources I use and have used before.</figcaption></figure></div><h4>2. Free YouTube Channels</h4><p>If I had to pick three channels to binge-watch, it would be:</p><ul><li><p>Friends of Tracking: Community-driven project with free educational content, code, and data. Led by David Sumpter one of the data pioneers in the field. <a href="https://www.youtube.com/@friendsoftracking755/featured">Friends of Tracking</a></p></li><li><p>McKay Johns: sTutorials, code, and guides on using Python and data science for football analysis. <a href="https://www.youtube.com/@McKayJohns">McKay Johns Channel</a> He has football analytics courses that are well crafted and contains everything you need to know to start creating quality projects.</p></li><li><p>LanusStats: this one is in Spanish, the creator Federico R&#225;banos teaches how to use Python to grab stats, make dashboards, and understand metrics. It's great if you speak Spanish and want to learn how to analyze soccer with data and code. <a href="https://www.youtube.com/@LanusStats">LanusStats</a></p></li></ul><p></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1osg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd96901fd-f89e-4f55-894e-653454f59e84_1764x784.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1osg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd96901fd-f89e-4f55-894e-653454f59e84_1764x784.heic 424w, https://substackcdn.com/image/fetch/$s_!1osg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd96901fd-f89e-4f55-894e-653454f59e84_1764x784.heic 848w, https://substackcdn.com/image/fetch/$s_!1osg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd96901fd-f89e-4f55-894e-653454f59e84_1764x784.heic 1272w, https://substackcdn.com/image/fetch/$s_!1osg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd96901fd-f89e-4f55-894e-653454f59e84_1764x784.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1osg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd96901fd-f89e-4f55-894e-653454f59e84_1764x784.heic" width="652" height="289.77777777777777" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d96901fd-f89e-4f55-894e-653454f59e84_1764x784.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:784,&quot;width&quot;:1764,&quot;resizeWidth&quot;:652,&quot;bytes&quot;:100153,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/165685677?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b5ac94-9e84-4151-a7c3-ddd370059cf7_1920x1080.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1osg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd96901fd-f89e-4f55-894e-653454f59e84_1764x784.heic 424w, https://substackcdn.com/image/fetch/$s_!1osg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd96901fd-f89e-4f55-894e-653454f59e84_1764x784.heic 848w, https://substackcdn.com/image/fetch/$s_!1osg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd96901fd-f89e-4f55-894e-653454f59e84_1764x784.heic 1272w, https://substackcdn.com/image/fetch/$s_!1osg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd96901fd-f89e-4f55-894e-653454f59e84_1764x784.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">YouTube Channels you can watch.</figcaption></figure></div><h4>3. Improve Your Football Knowledge</h4><p>It's easy to overestimate our football knowledge. Coaches, analysts, and scouts use specific tactical concepts daily.  </p><p>For that, I recommend:</p><ul><li><p>Watch games with a tactical focus: observe team behavior in attack, defense, build-up play, and player technique. Go beyond just following the ball. You can watch free matches in these leagues: <a href="https://docs.google.com/spreadsheets/d/18QxXLSGo_gqU0lKApfkQOkW9Z-O0sj0AfFNECAbCUOk/edit">Ben Griffis Google Sheet</a>, a list of leagues that upload their matches put up together by another great analyst Ben Griffis who also shares awesome visualizations and resources ( <a href="https://x.com/BeGriffis">Ben Griffis X Account)</a></p></li><li><p>Online resources: watch YouTube channels that talk about tactics, read blogs in Medium and Substack or even books that go deep  in these concepts. </p></li><li><p>At some point and if its suitable for your pocket start with affordable video analysis courses that can help you level up your game understanding. For this I&#8217;ve taken two courses (in Spanish): </p><ul><li><p><strong>AFOPRO (Spanish)</strong>: an online academy that teaches a wide variety of courses in scouting, video analysis, physical preparation at affordable prices. <a href="https://afopro.com/">AFOPRO</a></p></li><li><p><strong>ObjetivoAnalista (Spanish)</strong>: one of the best academies on Spain created by Dani P&#233;rez, they offer three signature course: Analista360, Scouting360 and PowerBI 360. I&#8217;ve personally taken Analista360 and Scouting360. The first one help me A LOT to improve my game understanding and applying this knowledge to a collaborative opportunity I had as a remote videoanalysis for a friend&#8217;s team in the US. I&#8217;m currently finishing Scouting360 because I want to get deeper in scouting analytics. <a href="https://objetivoanalista.com/">ObjetivoAnalista</a></p></li><li><p><strong>APFA (English): </strong>an<strong> </strong>organization focused on developping analysis skills, foster a community through webinars and content, provide career progression resources like job opportunities and mentorship. <a href="https://apfa.io/">APFA</a></p></li></ul></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!CHq9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb8d09840-e02c-407e-89a6-5ee81f9947b5_1338x550.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CHq9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb8d09840-e02c-407e-89a6-5ee81f9947b5_1338x550.heic 424w, https://substackcdn.com/image/fetch/$s_!CHq9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb8d09840-e02c-407e-89a6-5ee81f9947b5_1338x550.heic 848w, https://substackcdn.com/image/fetch/$s_!CHq9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb8d09840-e02c-407e-89a6-5ee81f9947b5_1338x550.heic 1272w, https://substackcdn.com/image/fetch/$s_!CHq9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb8d09840-e02c-407e-89a6-5ee81f9947b5_1338x550.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CHq9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb8d09840-e02c-407e-89a6-5ee81f9947b5_1338x550.heic" width="603" height="247.86995515695068" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b8d09840-e02c-407e-89a6-5ee81f9947b5_1338x550.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:550,&quot;width&quot;:1338,&quot;resizeWidth&quot;:603,&quot;bytes&quot;:43308,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/165685677?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb8d09840-e02c-407e-89a6-5ee81f9947b5_1338x550.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!CHq9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb8d09840-e02c-407e-89a6-5ee81f9947b5_1338x550.heic 424w, https://substackcdn.com/image/fetch/$s_!CHq9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb8d09840-e02c-407e-89a6-5ee81f9947b5_1338x550.heic 848w, https://substackcdn.com/image/fetch/$s_!CHq9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb8d09840-e02c-407e-89a6-5ee81f9947b5_1338x550.heic 1272w, https://substackcdn.com/image/fetch/$s_!CHq9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb8d09840-e02c-407e-89a6-5ee81f9947b5_1338x550.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Analysis courses I&#8217;ve personally taken.</figcaption></figure></div><p>Technical skills matter but there&#8217;s something that&#8217;s really important to consider: knowing the game matters too.<br><br>Picture it like this: you think in data, but speak in football.</p><h4>4. Start Building Projects: From Simple to End-to-End Solutions </h4><p>Building projects is the best way to learn. You don't need to know everything upfront; start with what you know..</p><p>It doesn&#8217;t matter if your first project is simple. A simple visualization from one match or a scouting report from one player. You improve by building tiny projects until you gain confidence through creating. In time, you&#8217;ll build more complex data pipelines or modeling. </p><p>The important is to: </p><ul><li><p>Show your entire process: data collection, cleaning, modeling, and visualization. </p></li><li><p>Communicate your insights in a clean and concise way. </p></li><li><p>Translate everything into football terms. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!hTUp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca3fc6fc-097f-420f-8ffd-547f7af7ca81_1906x1306.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!hTUp!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca3fc6fc-097f-420f-8ffd-547f7af7ca81_1906x1306.heic 424w, https://substackcdn.com/image/fetch/$s_!hTUp!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca3fc6fc-097f-420f-8ffd-547f7af7ca81_1906x1306.heic 848w, https://substackcdn.com/image/fetch/$s_!hTUp!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca3fc6fc-097f-420f-8ffd-547f7af7ca81_1906x1306.heic 1272w, https://substackcdn.com/image/fetch/$s_!hTUp!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca3fc6fc-097f-420f-8ffd-547f7af7ca81_1906x1306.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!hTUp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca3fc6fc-097f-420f-8ffd-547f7af7ca81_1906x1306.heic" width="600" height="411.2637362637363" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ca3fc6fc-097f-420f-8ffd-547f7af7ca81_1906x1306.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:998,&quot;width&quot;:1456,&quot;resizeWidth&quot;:600,&quot;bytes&quot;:95581,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/165685677?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca3fc6fc-097f-420f-8ffd-547f7af7ca81_1906x1306.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!hTUp!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca3fc6fc-097f-420f-8ffd-547f7af7ca81_1906x1306.heic 424w, https://substackcdn.com/image/fetch/$s_!hTUp!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca3fc6fc-097f-420f-8ffd-547f7af7ca81_1906x1306.heic 848w, https://substackcdn.com/image/fetch/$s_!hTUp!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca3fc6fc-097f-420f-8ffd-547f7af7ca81_1906x1306.heic 1272w, https://substackcdn.com/image/fetch/$s_!hTUp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca3fc6fc-097f-420f-8ffd-547f7af7ca81_1906x1306.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Data Driven Scouting Project of mine combining different data sources in order to cluster football players from Championship, League Two and League One. <a href="https://github.com/ricardoherediaj/data-driven-scouting-project">Link to GitHub</a></figcaption></figure></div></li></ul><h4>5. Share Your Work, Build Your Network</h4><p>Sharing my work was a challenge at first. I had accounts on X and LinkedIn, but rarely posted. It's easy to feel hesitant. </p><p>I started being a little bit more constant. Since there&#8217;s value in sharing what we know. It&#8217;ll probably going to help somebody else realize they like football analytics and creating content online like I did back when I did my first Python course with DataCamp (a story for another day). </p><p>The are plenty of platforms you can use but I recommend using: </p><ul><li><p>X: Share quick insights, visualizations, and engage with the community.</p></li><li><p>LinkedIn: Showcase professional projects, network with potential employers, and share career progress. </p></li><li><p>Medium/Substack (obviously): Share in-depth articles, build a community, and connect with readers. Substack is a recent one for me but I&#8217;m digging it. </p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!CvNt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6ee8af3-333e-440c-87b4-44404ca786b0_612x566.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CvNt!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6ee8af3-333e-440c-87b4-44404ca786b0_612x566.heic 424w, https://substackcdn.com/image/fetch/$s_!CvNt!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6ee8af3-333e-440c-87b4-44404ca786b0_612x566.heic 848w, https://substackcdn.com/image/fetch/$s_!CvNt!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6ee8af3-333e-440c-87b4-44404ca786b0_612x566.heic 1272w, https://substackcdn.com/image/fetch/$s_!CvNt!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6ee8af3-333e-440c-87b4-44404ca786b0_612x566.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CvNt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6ee8af3-333e-440c-87b4-44404ca786b0_612x566.heic" width="382" height="353.2875816993464" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b6ee8af3-333e-440c-87b4-44404ca786b0_612x566.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:566,&quot;width&quot;:612,&quot;resizeWidth&quot;:382,&quot;bytes&quot;:12635,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://ricardoheredia.substack.com/i/165685677?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6ee8af3-333e-440c-87b4-44404ca786b0_612x566.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!CvNt!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6ee8af3-333e-440c-87b4-44404ca786b0_612x566.heic 424w, https://substackcdn.com/image/fetch/$s_!CvNt!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6ee8af3-333e-440c-87b4-44404ca786b0_612x566.heic 848w, https://substackcdn.com/image/fetch/$s_!CvNt!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6ee8af3-333e-440c-87b4-44404ca786b0_612x566.heic 1272w, https://substackcdn.com/image/fetch/$s_!CvNt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6ee8af3-333e-440c-87b4-44404ca786b0_612x566.heic 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This is a compact curated list with the sources I&#8217;ve tried since the beginning. Something I love I had back in the day. </p><p>Now it's your turn! Explore these resources, start building, and share your journey. I'm excited to see what you create!</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://ricardoheredia.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The NetPass! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p>]]></content:encoded></item></channel></rss>