<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>GitHub Actions on Christian Martínez De La Rosa</title><link>https://christt105.github.io/ca/tags/github-actions/</link><description>Recent content in GitHub Actions on Christian Martínez De La Rosa</description><generator>Hugo -- gohugo.io</generator><language>ca</language><lastBuildDate>Fri, 21 Aug 2026 00:00:00 +0200</lastBuildDate><atom:link href="https://christt105.github.io/ca/tags/github-actions/index.xml" rel="self" type="application/rss+xml"/><item><title>Com un GIF per al meu perfil de GitHub va acabar sent el Parallax Scene Editor</title><link>https://christt105.github.io/ca/blog/github-profile-readme/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0200</pubDate><guid>https://christt105.github.io/ca/blog/github-profile-readme/</guid><enclosure url="https://christt105.github.io/blog/github-profile-readme/github-profile-screenshot.png" length="343324" type="image/png"/><description>&lt;p&gt;Benvinguts a un nou post!&lt;/p&gt;&#10;&lt;p&gt;Aquest cop va d&amp;rsquo;una cosa petita: el README del meu perfil de GitHub. Volia que fos simple, un GIF que digués alguna cosa de mi, una mica friqui però sense passar-se, una descripció curta i poca cosa més. Al final se&amp;rsquo;m va escapar de les mans força més del que tocava.&lt;/p&gt;&#10;&lt;h2 id="la-idea"&gt;La idea&#10;&lt;/h2&gt;&lt;p&gt;El punt de partida va ser la intro de Pokémon Maragda: el personatge surt en bicicleta mentre uns quants Pokémon corren al seu costat, just abans dels crèdits. Aquesta escena sempre m&amp;rsquo;ha agradat, així que volia alguna cosa amb el mateix esperit, personalitzada, però que es reconegués la mateixa idea. Senzill, en teoria.&lt;/p&gt;&#10;&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="386" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://christt105.github.io/blog/github-profile-readme/PokemonEmeraldIntro.jpg" width="686"&gt;&lt;/p&gt;&#10;&lt;h2 id="primer-intent-aseprite"&gt;Primer intent: Aseprite&#10;&lt;/h2&gt;&lt;p&gt;Em vaig descarregar &lt;a class="link" href="https://www.aseprite.org/" target="_blank" rel="noopener"&#10; &gt;Aseprite&lt;/a&gt; perquè feia temps que volia una excusa per aprendre&amp;rsquo;l. Mentre m&amp;rsquo;hi familiaritzava, vaig demanar a Claude que anés extraient els sprites de &lt;a class="link" href="https://github.com/pret/pokeemerald" target="_blank" rel="noopener"&#10; &gt;pokeemerald&lt;/a&gt;, el projecte de descompilació. No hi tenia gaire fe, però ho va fer força bé: va treure els sprites força ordenats, per parts, i després els va ajuntar en diversos spritesheets, i el mateix amb els fons de les diferents escenes, urbà, mar i bosc.&lt;/p&gt;&#10;&lt;p&gt;Li vaig preguntar si era capaç de recrear l&amp;rsquo;escena original a Aseprite, i també ho va aconseguir. Aquí em vaig trobar amb el problema de debò: Aseprite funciona per frames. No hi ha manera, que jo sàpiga, de moure&amp;rsquo;t lliurement entre keyframes arbitraris i que interpoli; cada frame el dibuixes o el col·loques a mà. Perfecte per fer sprites, no tant per coreografiar una càmera i actors al llarg de centenars de frames.&lt;/p&gt;&#10;&lt;h2 id="plot-twist"&gt;Plot twist&#10;&lt;/h2&gt;&lt;p&gt;Així que li vaig demanar que muntés la mateixa escena directament a partir d&amp;rsquo;un JSON amb les dades i posicions dels actors, tretes directament del joc. Imitava a la perfecció l&amp;rsquo;escena original. I aquí és quan va aparèixer la idea que de debò volia: i si un projectet d&amp;rsquo;una tarda el convertia en un d&amp;rsquo;una setmana?&lt;/p&gt;&#10;&lt;p&gt;Així va néixer el &lt;a class="link" href="https://github.com/christt105/parallax-scene-editor" target="_blank" rel="noopener"&#10; &gt;Parallax Scene Editor&lt;/a&gt;. Li vaig demanar una pàgina web que treballés amb sprites i un JSON que descrivís l&amp;rsquo;escena, i vam anar iterant a partir d&amp;rsquo;aquí. Dues restriccions des del principi: tot local, i havia d&amp;rsquo;escriure directament al disc, no quedar-se en un estat intern de l&amp;rsquo;aplicació que exportes a mà al final.&lt;/p&gt;&#10;&lt;h2 id="leditor"&gt;L&amp;rsquo;editor&#10;&lt;/h2&gt;&lt;h3 id="parallax"&gt;Parallax&#10;&lt;/h3&gt;&lt;p&gt;Abans de continuar, un incís per a qui no li soni el terme. El parallax és el truc de tota la vida per donar sensació de profunditat en 2D. En lloc d&amp;rsquo;un únic fons, s&amp;rsquo;apilen diverses capes (cel, muntanyes, arbres, terra&amp;hellip;) i cadascuna es mou a la seva pròpia velocitat, les llunyanes més a poc a poc, les properes més ràpid. L&amp;rsquo;ull interpreta aquesta diferència de velocitat com a distància, encara que a sota només hi hagi sprites plans. És la mateixa tècnica dels jocs de 16 bits, i la que fa servir Pokémon Maragda a la seva intro.&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="Exemple de parallax scrolling amb diverses capes movent-se a diferent velocitat" class="gallery-image" data-flex-basis="411px" data-flex-grow="171" height="448" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://images.squarespace-cdn.com/content/551a19f8e4b0e8322a93850a/1573861732601-PTWHSU2HW5BZ9C2IASCM/Intro_Parallax.gif?content-type=image%2Fgif" width="768"&gt;&#10;&lt;em&gt;Exemple de &lt;a class="link" href="https://www.slynyrd.com/blog/2019/11/12/pixelblog-23-parallax-scrolling" target="_blank" rel="noopener"&#10; &gt;slynyrd.com&lt;/a&gt;, que té un post sencer molt recomanable sobre com dibuixar parallax scrolling en pixel art.&lt;/em&gt;&lt;/p&gt;&#10;&lt;h3 id="fent-servir-leditor"&gt;Fent servir l&amp;rsquo;editor&#10;&lt;/h3&gt;&lt;p&gt;Com sempre us deixo el repositori de l&amp;rsquo;editor amb el codi font per a qui vulgui trastejar.&lt;/p&gt;&#10;&lt;a class="github-repo-card" href="https://github.com/christt105/parallax-scene-editor" target="_blank" rel="noopener"&gt;&#10; &lt;img src="https://avatars.githubusercontent.com/u/36189169?v=4" alt="christt105 avatar" class="repo-avatar"&gt;&#10; &lt;h3&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-github" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"&gt;&#10; &lt;path stroke="none" d="M0 0h24v24H0z" fill="none"/&gt;&#10; &lt;path d="M9 19c-4.3 1.4 -4.3 -2.5 -6 -3m12 5v-3.5c0 -1 .1 -1.4 -.5 -2c2.8 -.3 5.5 -1.4 5.5 -6a4.6 4.6 0 0 0 -1.3 -3.2a4.2 4.2 0 0 0 -.1 -3.2s-1.1 -.3 -3.5 1.3a12.3 12.3 0 0 0 -6.2 0c-2.4 -1.6 -3.5 -1.3 -3.5 -1.3a4.2 4.2 0 0 0 -.1 3.2a4.6 4.6 0 0 0 -1.3 3.2c0 4.6 2.7 5.7 5.5 6c-.6 .6 -.6 1.2 -.5 2v3.5" /&gt;&#10;&lt;/svg&gt;&#10;&#10;&#10; christt105/parallax-scene-editor&lt;/h3&gt;&#10; &lt;p&gt;Browser-based editor for seamlessly looping pixel art parallax scenes. Serverless, zero uploads.&lt;/p&gt;&#10; &lt;div class="repo-stats"&gt;&#10; &lt;span&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor" class="icon icon-tabler icons-tabler-filled icon-tabler-star"&gt;&lt;path stroke="none" d="M0 0h24v24H0z" fill="none"/&gt;&lt;path d="M8.243 7.34l-6.38 .925l-.113 .023a1 1 0 0 0 -.44 1.684l4.622 4.499l-1.09 6.355l-.013 .11a1 1 0 0 0 1.464 .944l5.706 -3l5.693 3l.1 .046a1 1 0 0 0 1.352 -1.1l-1.091 -6.355l4.624 -4.5l.078 -.085a1 1 0 0 0 -.633 -1.62l-6.38 -.926l-2.852 -5.78a1 1 0 0 0 -1.794 0l-2.853 5.78z" /&gt;&lt;/svg&gt; 1&lt;/span&gt;&#10; &lt;span&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-git-fork"&gt;&lt;path stroke="none" d="M0 0h24v24H0z" fill="none"/&gt;&lt;path d="M10 18a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" /&gt;&lt;path d="M5 6a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" /&gt;&lt;path d="M15 6a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" /&gt;&lt;path d="M7 8v2a2 2 0 0 0 2 2h6a2 2 0 0 0 2 -2v-2" /&gt;&lt;path d="M12 12l0 4" /&gt;&lt;/svg&gt; 0&lt;/span&gt;&#10; &lt;span&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-calendar-event"&gt;&lt;path stroke="none" d="M0 0h24v24H0z" fill="none"/&gt;&lt;path d="M4 7a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2l0 -12" /&gt;&lt;path d="M16 3l0 4" /&gt;&lt;path d="M8 3l0 4" /&gt;&lt;path d="M4 11l16 0" /&gt;&lt;path d="M8 15h2v2h-2l0 -2" /&gt;&lt;/svg&gt; 2026-08-29&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;p&gt;Anem a veure com funciona aquesta petita eina.&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="L’editor obert sobre l’escena de demostració, amb les capes, els actors i la línia de temps visibles" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="1080" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://christt105.github.io/blog/github-profile-readme/parallax-editor-loop.gif" srcset="https://christt105.github.io/blog/github-profile-readme/parallax-editor-loop_hu_7eb43a54268906fc.gif 800w, https://christt105.github.io/blog/github-profile-readme/parallax-editor-loop_hu_c20eaedc1aaff01c.gif 1600w, https://christt105.github.io/blog/github-profile-readme/parallax-editor-loop.gif 1920w" width="1920"&gt;&lt;/p&gt;&#10;&lt;p&gt;Una escena de parallax aquí és un únic fitxer JSON: càmera, capes, actors, keyframes. L&amp;rsquo;edites mentre es reprodueix en bucle, i t&amp;rsquo;avisa en vermell en el moment en què alguna cosa no tancarà bé. Algunes de les coses que va acabar fent:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Llegeix i escriu directament al teu disc.&lt;/strong&gt; Obres una carpeta amb la File System Access API (només Chromium) i a partir d&amp;rsquo;aquí cada canvi s&amp;rsquo;escriu de nou al mateix fitxer uns quants centenars de mil·lisegons després que deixis de tocar res. Un missatge al costat de Save diu en tot moment on està escrivint.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Els sprites es recarreguen sols.&lt;/strong&gt; Repintes alguna cosa a Aseprite, guardes, i un parell de segons després ja és al canvas, sense que hagis de fer res.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Actors amb keyframes i easing&lt;/strong&gt;, més moviment &lt;code&gt;sine&lt;/code&gt;/&lt;code&gt;cosine&lt;/code&gt;/&lt;code&gt;wobble&lt;/code&gt; a sobre per als detalls petits, un rebot a la bici, un ocell que es mou una mica mentre vola, sense haver-ho de dibuixar a mà.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Fa l&amp;rsquo;aritmètica de tancament de bucle per tu.&lt;/strong&gt; Si la velocitat d&amp;rsquo;una capa no encaixa al tile, o el nombre de cels d&amp;rsquo;un actor no divideix el bucle, l&amp;rsquo;editor no es limita a avisar-te: t&amp;rsquo;ofereix la solució exacta, les dues velocitats més properes que sí que tanquen, o una nova durada de bucle, amb un botó per a cadascuna.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Onion skin, línia de temps arrossegable, historial de desfer&lt;/strong&gt;, les coses de sempre que voldries i trobaries a faltar si no hi fossin.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Exporta a GIF, WebM o una seqüència de PNG.&lt;/strong&gt; El codificador de GIF està escrit des de zero. Si tota l&amp;rsquo;animació cap en 256 colors, que és el cas de gairebé tot el pixel art, la paleta és exacta.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Així es veu ja treballant sobre el projecte de veritat, amb el ciclista, Mudkip i un Tropius volant, i el panell de la dreta avisant en vermell que el cicle de Tropius no tanca el bucle:&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="L’editor amb el projecte de Pokémon Maragda carregat, mostrant el ciclista, Mudkip, un Tropius volant i l’avís de tancament de bucle" class="gallery-image" data-flex-basis="458px" data-flex-grow="190" height="1320" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://christt105.github.io/blog/github-profile-readme/editor-pokemon-project.png" srcset="https://christt105.github.io/blog/github-profile-readme/editor-pokemon-project_hu_10e6b17cdc9ee60.png 800w, https://christt105.github.io/blog/github-profile-readme/editor-pokemon-project_hu_7dc6a8891bcae378.png 1600w, https://christt105.github.io/blog/github-profile-readme/editor-pokemon-project_hu_5c27df083c3491d.png 2400w, https://christt105.github.io/blog/github-profile-readme/editor-pokemon-project.png 2520w" width="2520"&gt;&lt;/p&gt;&#10;&lt;p&gt;És completament open source, sense dependències ni pas de compilació, així que GitHub Pages el serveix tal qual. Hi ha una versió en viu a &lt;a class="link" href="https://christt105.github.io/parallax-scene-editor/" target="_blank" rel="noopener"&#10; &gt;christt105.github.io/parallax-scene-editor&lt;/a&gt; per si li voleu fer un cop d&amp;rsquo;ull.&lt;/p&gt;&#10;&lt;h2 id="fent-el-gif-de-debò"&gt;Fent el GIF de debò&#10;&lt;/h2&gt;&lt;p&gt;Amb l&amp;rsquo;editor en un estat prou madur, vaig tornar al GIF en si. Vaig conservar el personatge en bicicleta, el vaig posicionar a l&amp;rsquo;escena, i em vaig posar a buscar un Pokémon corrent per posar al seu costat. Vaig trobar un spritesheet de Mudkip de Pokémon Mundo Misteriós que, sorprenentment, encaixava gairebé de fàbrica en la mida i la perspectiva que necessitava. Casualitat que és el meu Pokémon preferit.&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="Un peluix de Mudkip del Pokémon Center del Japó que em va regalar un amic que em coneix molt bé" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1500" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://christt105.github.io/blog/github-profile-readme/IMG_20260820_224501.jpg" srcset="https://christt105.github.io/blog/github-profile-readme/IMG_20260820_224501_hu_24bc84126df976ae.jpg 800w, https://christt105.github.io/blog/github-profile-readme/IMG_20260820_224501_hu_fa34aa666f9a4752.jpg 1600w, https://christt105.github.io/blog/github-profile-readme/IMG_20260820_224501.jpg 2000w" width="2000"&gt;&lt;/p&gt;&#10;&lt;p&gt;L&amp;rsquo;únic problema va ser el color. L&amp;rsquo;estil artístic de Mundo Misteriós és prou diferent al de Maragda perquè Mudkip desentonés al costat de tota la resta. Vaig demanar a Claude que analitzés els altres sprites de Pokémon que ja hi havia a l&amp;rsquo;escena i ajustés la paleta de Mudkip per igualar-la, i el resultat no està malament, sobretot al voltant de la vora.&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="El spritesheet de Mudkip tal com surt de Pokémon Mundo Misteriós, sense retocar" class="gallery-image" data-flex-basis="720px" data-flex-grow="300" height="132" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://christt105.github.io/blog/github-profile-readme/mudkip-original.png" width="396"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="El spritesheet de Mudkip ja recolorit i ajustat, tal com es fa servir al projecte" class="gallery-image" data-flex-basis="720px" data-flex-grow="300" height="132" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://christt105.github.io/blog/github-profile-readme/mudkip-project.png" width="396"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="El spritesheet de Torchic fet servir al Pokémon Maragda" class="gallery-image" data-flex-basis="720px" data-flex-grow="300" height="144" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://christt105.github.io/blog/github-profile-readme/torchic-project.png" width="432"&gt;&lt;/p&gt;&#10;&lt;p&gt;També vaig provar unes animacions personalitzades de Pokémon que vaig trobar per internet, però l&amp;rsquo;estil i la perspectiva estaven massa lluny com per encaixar, així que les vaig descartar i em vaig quedar amb el protagonista i un Mudkip corrent sobre un fons de bosc. Hauria estat bé muntar un equip complet de sis que hagués jugat en algun moment, però portar els sprites a aquest nivell de consistència és més del que vull assumir ara mateix. Vaig aplicar un lleuger zoom out i ho vaig deixar aquí, senzill, però net.&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="El resultat final: el ciclista i un Mudkip corrent en bucle sobre un fons de bosc" class="gallery-image" data-flex-basis="640px" data-flex-grow="266" height="480" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://christt105.github.io/blog/github-profile-readme/bike-ride.gif" srcset="https://christt105.github.io/blog/github-profile-readme/bike-ride_hu_cbb9caeee52a9e85.gif 800w, https://christt105.github.io/blog/github-profile-readme/bike-ride.gif 1280w" width="1280"&gt;&lt;/p&gt;&#10;&lt;h2 id="automatitzant-lactualització"&gt;Automatitzant l&amp;rsquo;actualització&#10;&lt;/h2&gt;&lt;p&gt;L&amp;rsquo;editor exporta a GIF i WebM, així que el pla era: el repo del projecte de Pokémon exporta el GIF, i el README del perfil el referencia. Volia que això fos el més automàtic possible, així que vaig afegir una &lt;a class="link" href="https://github.com/christt105/PokemonEmeraldIntroVideo/blob/main/.github/workflows/export.yml" target="_blank" rel="noopener"&#10; &gt;GitHub Action&lt;/a&gt; al repo de &lt;a class="link" href="https://github.com/christt105/PokemonEmeraldIntroVideo" target="_blank" rel="noopener"&#10; &gt;PokemonEmeraldIntroVideo&lt;/a&gt; que s&amp;rsquo;executa a cada push: fa checkout d&amp;rsquo;una build de l&amp;rsquo;editor, la condueix en mode headless amb Playwright, i fa commit del GIF i el WebM resultants directament a &lt;code&gt;out/&lt;/code&gt;.&lt;/p&gt;&#10;&lt;a class="github-repo-card" href="https://github.com/christt105/PokemonEmeraldIntroVideo" target="_blank" rel="noopener"&gt;&#10; &lt;img src="https://avatars.githubusercontent.com/u/36189169?v=4" alt="christt105 avatar" class="repo-avatar"&gt;&#10; &lt;h3&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-github" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"&gt;&#10; &lt;path stroke="none" d="M0 0h24v24H0z" fill="none"/&gt;&#10; &lt;path d="M9 19c-4.3 1.4 -4.3 -2.5 -6 -3m12 5v-3.5c0 -1 .1 -1.4 -.5 -2c2.8 -.3 5.5 -1.4 5.5 -6a4.6 4.6 0 0 0 -1.3 -3.2a4.2 4.2 0 0 0 -.1 -3.2s-1.1 -.3 -3.5 1.3a12.3 12.3 0 0 0 -6.2 0c-2.4 -1.6 -3.5 -1.3 -3.5 -1.3a4.2 4.2 0 0 0 -.1 3.2a4.6 4.6 0 0 0 -1.3 3.2c0 4.6 2.7 5.7 5.5 6c-.6 .6 -.6 1.2 -.5 2v3.5" /&gt;&#10;&lt;/svg&gt;&#10;&#10;&#10; christt105/PokemonEmeraldIntroVideo&lt;/h3&gt;&#10; &lt;p&gt;&lt;/p&gt;&#10; &lt;div class="repo-stats"&gt;&#10; &lt;span&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor" class="icon icon-tabler icons-tabler-filled icon-tabler-star"&gt;&lt;path stroke="none" d="M0 0h24v24H0z" fill="none"/&gt;&lt;path d="M8.243 7.34l-6.38 .925l-.113 .023a1 1 0 0 0 -.44 1.684l4.622 4.499l-1.09 6.355l-.013 .11a1 1 0 0 0 1.464 .944l5.706 -3l5.693 3l.1 .046a1 1 0 0 0 1.352 -1.1l-1.091 -6.355l4.624 -4.5l.078 -.085a1 1 0 0 0 -.633 -1.62l-6.38 -.926l-2.852 -5.78a1 1 0 0 0 -1.794 0l-2.853 5.78z" /&gt;&lt;/svg&gt; 0&lt;/span&gt;&#10; &lt;span&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-git-fork"&gt;&lt;path stroke="none" d="M0 0h24v24H0z" fill="none"/&gt;&lt;path d="M10 18a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" /&gt;&lt;path d="M5 6a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" /&gt;&lt;path d="M15 6a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" /&gt;&lt;path d="M7 8v2a2 2 0 0 0 2 2h6a2 2 0 0 0 2 -2v-2" /&gt;&lt;path d="M12 12l0 4" /&gt;&lt;/svg&gt; 0&lt;/span&gt;&#10; &lt;span&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-calendar-event"&gt;&lt;path stroke="none" d="M0 0h24v24H0z" fill="none"/&gt;&lt;path d="M4 7a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2l0 -12" /&gt;&lt;path d="M16 3l0 4" /&gt;&lt;path d="M8 3l0 4" /&gt;&lt;path d="M4 11l16 0" /&gt;&lt;path d="M8 15h2v2h-2l0 -2" /&gt;&lt;/svg&gt; 2026-08-16&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;p&gt;El README del perfil simplement apunta a la URL raw d&amp;rsquo;aquest fitxer. Així que en el moment en què toco una velocitat o moc un keyframe a l&amp;rsquo;escena i faig push, l&amp;rsquo;animació es regenera sola i el README s&amp;rsquo;actualitza amb ella, sense el pas d&amp;rsquo;exportar-commitejar-pushejar per la meva banda.&lt;/p&gt;&#10;&lt;h2 id="el-resultat"&gt;El resultat&#10;&lt;/h2&gt;&lt;p&gt;Una descripció de mi mateix, curta a propòsit, i una petita llista de l&amp;rsquo;stack que faig servir al dia a dia. Aquest gif és just a dalt de tot, com a capçalera, que és en realitat tota la idea: alguna cosa que digui una mica de mi abans que ho faci una sola paraula.&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="El perfil de GitHub en mode fosc, amb el gif del ciclista en bucle a la capçalera del README" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="1080" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://christt105.github.io/blog/github-profile-readme/github-profile-loop.gif" srcset="https://christt105.github.io/blog/github-profile-readme/github-profile-loop_hu_7437adac256ce14.gif 800w, https://christt105.github.io/blog/github-profile-readme/github-profile-loop_hu_2d62f19a29bb6d12.gif 1600w, https://christt105.github.io/blog/github-profile-readme/github-profile-loop.gif 1920w" width="1920"&gt;&lt;/p&gt;&#10;&lt;p&gt;Tot això es va allargar força més del previst, i em fa gràcia haver acabat fent un editor de parallax complet només per aconseguir un GIF animat en una pàgina de perfil. No vaig arribar a mirar si ja existia alguna cosa semblant, però aquí està el meu, de codi obert, perquè qui vulgui retòrcer-lo cap a una altra cosa ho pugui fer. Ja tinc una altra idea per al README, una mica més ambiciosa, però aquesta és per a un altre post (si la vida m&amp;rsquo;ho permet).&lt;/p&gt;&#10;&lt;p&gt;Espero que us hagi agradat, i podeu provar l&amp;rsquo;editor si teniu al cap alguna escena de parallax pròpia.&lt;/p&gt;&#10;&lt;p&gt;Fins la propera!&lt;/p&gt;&#10;</description></item></channel></rss>