<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Cátia Barros — Blog</title>
    <link>https://catia.pt/blog</link>
    <description>The world through Gen Z eyes: notes on journalism, technology and what I learn along the way.</description>
    <language>en-GB</language>
    <atom:link href="https://catia.pt/rss.en.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>My engineer friends were right</title>
      <link>https://catia.pt/blog/amigos-engenheiros-tinham-razao</link>
      <guid isPermaLink="true">https://catia.pt/blog/amigos-engenheiros-tinham-razao</guid>
      <pubDate>Tue, 07 Jul 2026 00:00:00 GMT</pubDate>
      <description>On winging it, repurposing mechanics, and the criticism my engineer friends always had for me: you have to know how to reuse.</description>
      <content:encoded><![CDATA[<p>During secondary school I studied sciences, a choice nudged along by a teacher who saw a future engineer in me. They weren&#39;t the years I felt most comfortable in (it didn&#39;t help being the only girl in the class, with the sense that everything cost me more just because of that, but that&#39;s a story for another day).</p>
<p>I keep good memories from that time and, above all, a group of friends who still show up at any hour. Unlike me, they all went into some kind of engineering and work in tech today. I went into journalism, but I never stopped wanting to bring their world together with mine.</p>
<p>I&#39;m a pandemic graduate. I finished my degree in June 2020, over Zoom, and it was around then that I decided to learn web development, largely because I wasn&#39;t even sure journalism was really for me. I bought a twelve-euro course on Udemy and learned to live by the fine art of <em>desenrascanço</em>, that very Portuguese skill of making do: hours on Stack Overflow (I&#39;ll admit I even miss it) and endless messages to my friends asking how on earth you did this or that.</p>
<p>They never quite got why I gave myself so much trouble. They found it odd, but they soon came round to the fact that I&#39;d got it into my head to go this way and there was no turning back.</p>
<p>And they&#39;ve always been tireless. They don&#39;t mind when I go on about gamification for hours or throw them questions that make no sense, and they still haven&#39;t given up on explaining object-oriented programming to me. They tell me I understand more than I think, but there&#39;s one criticism that never fails: I don&#39;t think like an engineer.</p>
<p>And it&#39;s true. An engineer sets out to make their own life easier: if a mechanic works, they make it reusable. I worked the other way round, every project started from scratch and thrown out at the end. When we get together for a coffee back in our hometown, the conversation always lands on &quot;so, how&#39;s work?&quot;, and a while ago one of them started letting slip a &quot;you&#39;re starting to think like an engineer&quot;.</p>
<p>And I think they&#39;re right, not just about me. We hear so much about productivity, about how AI is going to save us, but before any of that there&#39;s a much simpler move within reach of any journalist: to think a little like an engineer. To ask what you can put together now so you&#39;re not repeating the same work tomorrow. In journalism this matters even more, because we live plunged in the tide of the news cycle and the world interrupts us at every turn.</p>
<p>These past days have been swept up by that tide. Portugal&#39;s statistics office (INE) put an end to the statistical void around <a href="https://expresso.pt/migracoes/2026-06-22-fim-do-vazio-estatistico-quem-sao-onde-vivem-e-de-onde-vem-os-imigrantes-em-portugal-7fe2b024" target="_blank" rel="noopener noreferrer">who the country's immigrants are and where they come from</a>, Venezuela <a href="https://expresso.pt/venezuela/2026-06-25-dois-sismos-em-39-segundos-onde-com-que-forca-e-ha-quanto-tempo-nao-tremia-assim-a-venezuela-2e498f2b" target="_blank" rel="noopener noreferrer">shook twice in 39 seconds</a>, there were <a href="https://multimedia.expresso.pt/incendios2025/" target="_blank" rel="noopener noreferrer">wildfires</a> and the <a href="https://expresso.pt/sociedade/saude/2026-07-05-novas-regras-de-acesso-ao-sns-o-que-muda-e-quem-arrisca-perder-o-medico-de-familia--bdf4b551" target="_blank" rel="noopener noreferrer">rules for accessing the national health service changed</a>. I wrote about all of it over the last fortnight. And in the middle of the rush, I still managed to launch two newsgames a week apart. One is a <a href="https://multimedia.expresso.pt/mundial2026quiz" target="_blank" rel="noopener noreferrer">quiz on the history of the football World Cups</a>, with a look inspired by Panini stickers and sticker albums. The other tells the <a href="https://multimedia.expresso.pt/independenciaeua/" target="_blank" rel="noopener noreferrer">250 years of US independence</a> through a timeline of presidents and milestones, and came out on the 4th of July.</p>
<p><img src="https://catia.pt/posts/quiz-mundiais-tribuna.png" alt="Opening screen of the World Cup quiz: a grid of blue cards showing players from various national teams, styled like a sticker album.">
<em>The World Cup quiz, on Tribuna Expresso, with a look inspired by Panini stickers.</em></p>
<p><img src="https://catia.pt/posts/jogo-250-anos-eua.png" alt="Opening screen of the 250-years-of-the-US game: a row of presidential portraits over a timeline running from 1776 to 2026.">
<em>250 years of US independence, from the presidents to the most defining moments.</em></p>
<p>Both come from the same idea, gamifying timelines, something the New York Times does beautifully in its <a href="https://www.nytimes.com/spotlight/flashback" target="_blank" rel="noopener noreferrer">quiz</a>. The mechanic is identical: you get one card at a time, with a clue, and you have to slot it into the right place on the timeline. The logic for dragging, checking and scoring is written once only; from one game to the other, all I swap is the data file, which I put together with colleagues who know far more about World Cups and the United States than I do.</p>
<p>It&#39;s the part I like most. An old-fashioned timeline is a list of dates your eyes just slide past. Turned into a game, it puts the reader at the centre of the story: instead of receiving it ready-made, they arrange each event themselves and build the chronology at their own pace. And for anyone who just wants the facts, there&#39;s always the option to skip ahead and read it straight through.</p>
<p>The interfaces couldn&#39;t be more different, but it&#39;s the same machinery telling 250 years of American history or decades of World Cups. A few years ago I&#39;d have built both from start to finish, one by one. This time I built an engine, and for the next playable timeline I won&#39;t be starting from scratch. Maybe that&#39;s all they were trying to tell me, sitting there at the café table.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Five years of data inside a tooltip</title>
      <link>https://catia.pt/blog/tooltip-datawrapper-grafico-mapa</link>
      <guid isPermaLink="true">https://catia.pt/blog/tooltip-datawrapper-grafico-mapa</guid>
      <pubDate>Wed, 24 Jun 2026 00:00:00 GMT</pubDate>
      <description>How I used HTML to fit the foreign population's evolution since 2021 inside a Datawrapper map's tooltips.</description>
      <content:encoded><![CDATA[<p>For anyone doing data, visual or infographic journalism, the tools we already have make life much easier. With a clean Excel file or a CSV, you can put a map or a chart online in maybe under five minutes.</p>
<p>The flip side is that personalising takes work. With public data, it is natural that several newsrooms end up with similar maps: they start from the same file, and the tools, by default, lead to similar results. There is nothing wrong with that. But in this case I felt like going a little further.</p>
<p>This Monday, Statistics Portugal (INE) resumed publishing its population estimates. It had suspended the releases on immigration and foreign resident population in order to validate the <a href="https://expresso.pt/sociedade/2025-10-16-aima-reve-em-baixa-numero-de-estrangeiros-a-viver-em-portugal-sao-1.543.697-50d4eb45" target="_blank" rel="noopener noreferrer">AIMA data</a>, which led to what at Expresso we called the <a href="https://expresso.pt/sociedade/2025-12-18-estado-nao-sabe-quantos-sao-e-onde-vivem-os-imigrantes-ine-suspende-estatisticas-e-admite-reavaliar-numeros-b0f222c3" target="_blank" rel="noopener noreferrer">‘statistical void’</a>: in December 2025, the State did not know for certain how many immigrants there were nor where they lived.</p>
<p>INE&#39;s revision was not only about 2025. The institute also revised the 2021 to 2024 figures and, for the foreign population, published 2024 for the first time. The corrections were large, and came almost entirely from the foreign population, which had been undercounted. To give an idea: the total number of residents in 2024 rose from 10.7 to 11.4 million, and the number of foreigners in 2023 went from around 1.05 to 1.35 million. In 2025, the resident population reached 11,424,031, the highest figure on record, more than 800,000 people up on 2021, almost all of it through immigration.</p>
<p>INE&#39;s numbers are also different in nature from AIMA&#39;s. They are an estimate of residents, cross-referencing tax, social security and school records to work out where people actually live, rather than a count of residence permits.</p>
<p>With so many new numbers, and with what data journalism allows, letting readers see the data wherever they want, I knew it was worth doing the portrait: who they are, where they live and where they come from.</p>
<p>But there was a problem. The data ran from 2021 to 2025, and a choropleth shows a single number, the 2025 one. I felt that years and years of information were going to be left behind, hidden under one flat colour.</p>
<p>And the web has a rare advantage: it lets you tinker underneath what is on show. So that is what I did, a version of the map where hovering over a municipality reveals the evolution since 2021.</p>
<p><img src="https://images.impresa.pt/expresso/2026-06-22-pop_estrangeira_retrato-ff8a0742-1/original" alt="Map of the foreign population by municipality, with the tooltip for Odemira open, showing the evolution since 2021"></p>
<p>Datawrapper is clear about this in its documentation: it explains how to <a href="https://www.datawrapper.de/academy/i-want-to-change-how-my-data-appears-in-tooltips" target="_blank" rel="noopener noreferrer">change the way data appears in tooltips</a> and even how to <a href="https://www.datawrapper.de/academy/how-to-embed-charts-into-tooltips" target="_blank" rel="noopener noreferrer">embed charts inside them</a>. That was exactly what I wanted. With HTML, I managed to fit the five years into a tooltip: on one side, the absolute numbers for 2021 and 2025; on the other, a small bar chart with the share of foreigners in the total resident population, year by year.</p>
<p>I set myself two rules. The chart&#39;s scale had to be the same across every municipality, so the bars would be comparable from one tooltip to the next. And the colour of each bar had to match the map&#39;s legend, instead of a single colour, so that each year&#39;s bar said the same thing as the shaded municipality.</p>
<p>The percentages, the height of each bar and the colour of each year were worked out beforehand and added to the file as columns. In the tooltip, it is just a matter of slotting them into place, through placeholders:</p>
<pre><code class="hljs language-html">{{ UPPER(nome) }} <span class="hljs-tag">&lt;<span class="hljs-name">hr</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">&quot;font-family:inherit;width:max-content;max-width:340px;padding:0px 0px&quot;</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">&quot;font-size:11px;color:#888;margin:2px 0 2px&quot;</span>&gt;</span>População estrangeira<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">&quot;display:flex;gap:4px;align-items:flex-start&quot;</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">&quot;flex:0 0 auto&quot;</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">&quot;font-size:11px;color:#888;line-height:1.1&quot;</span>&gt;</span>em 2021<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">&quot;font-size:13px;color:#888;margin-bottom:8px&quot;</span>&gt;</span>{{ FORMAT(valor_2021, &quot;0,0&quot;) }}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">&quot;font-size:11px;color:#015782;line-height:1.1&quot;</span>&gt;</span>em 2025<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">&quot;font-size:22px;font-weight:bold;color:#015782;line-height:1.1&quot;</span>&gt;</span>{{ FORMAT(valor_2025, &quot;0,0&quot;) }}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
   <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">&quot;flex:0 0 auto;border-left:1px solid #e5e5e5;padding-left:6px&quot;</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">&quot;font-size:10px;color:#888;margin-bottom:6px;white-space:nowrap&quot;</span>&gt;</span>% do total de residentes<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">&quot;display:flex;align-items:flex-end;gap:6px&quot;</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">&quot;display:flex;flex-direction:column;align-items:center;width:18px&quot;</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">style</span>=<span class="hljs-string">&quot;font-size:9px;color:#888;line-height:1;margin-bottom:2px&quot;</span>&gt;</span>{{ FORMAT(percentagem_2021, &quot;0%&quot;) }}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">&quot;width:12px;height:64px;background:#eef1f3;display:flex;align-items:flex-end&quot;</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">&quot;width:100%;height:{{ altura_2021 }}px;background:{{ cor_2021 }}&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">style</span>=<span class="hljs-string">&quot;font-size:9px;color:#888;margin-top:3px&quot;</span>&gt;</span>&#x27;21<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-comment">&lt;!-- &#x27;22, &#x27;23, &#x27;24 follow the same pattern --&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">&quot;display:flex;flex-direction:column;align-items:center;width:18px&quot;</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">style</span>=<span class="hljs-string">&quot;font-size:9px;font-weight:bold;color:#015782;line-height:1;margin-bottom:2px&quot;</span>&gt;</span>{{ FORMAT(percentagem_2025, &quot;0%&quot;) }}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">&quot;width:12px;height:64px;background:#eef1f3;display:flex;align-items:flex-end&quot;</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">&quot;width:100%;height:{{ altura_2025 }}px;background:{{ cor_2025 }}&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">style</span>=<span class="hljs-string">&quot;font-size:9px;color:#015782;font-weight:bold;margin-top:3px&quot;</span>&gt;</span>&#x27;25<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></code></pre><p>The bar is the trick: a grey track of fixed height, 64px, with a second element inside it whose height and colour come from the file. Pinned to the bottom, it grows upwards, the way a bar should.</p>
<p>In Odemira, the municipality with the highest share of foreign population in the country, the tooltip shows 14,794 foreigners in 2021 and 22,930 in 2025, with the percentage series at 41%, 48%, 52%, 53% and 52%. Note that 2024 (53%) is above 2025 (52%). It is not a clean rise all the way to the end, and that was exactly what I wanted to show: the trajectory, not an arrow pointing up.</p>
<p>In the end, underneath, it is still the same choropleth. What changes is what the reader finds when they get closer: five years of history where, by default, only one number would appear. That is what I wanted to add.</p>
<p>You can read the article and explore the data <a href="https://expresso.pt/migracoes/2026-06-22-fim-do-vazio-estatistico-quem-sao-onde-vivem-e-de-onde-vem-os-imigrantes-em-portugal-7fe2b024" target="_blank" rel="noopener noreferrer">here</a>.</p>
]]></content:encoded>
    </item>
  </channel>
</rss>