<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Posts on oscarmlage</title>
    <link>https://oscarmlage.com/posts/</link>
    <description>Recent content in Posts on oscarmlage</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <managingEditor>info@oscarmlage.com (oscarmlage)</managingEditor>
    <webMaster>info@oscarmlage.com (oscarmlage)</webMaster>
    <lastBuildDate>Fri, 30 Jan 2026 10:00:00 +0100</lastBuildDate>
    <atom:link href="https://oscarmlage.com/posts/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>FOSDEM 2026</title>
      <link>https://oscarmlage.com/posts/fosdem-2026/</link>
      <pubDate>Fri, 30 Jan 2026 10:00:00 +0100</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/fosdem-2026/</guid>
      <description>
            &lt;p&gt;&lt;img src=&#34;gallery/fosdem26.jpg&#34; alt=&#34;FOSDEM&#34;&gt;&lt;/p&gt;
&lt;p&gt;First time at FOSDEM. After all these years reading about it, following the hashtag on social media&amp;hellip; I finally got to experience it firsthand. And no, I wasn&amp;rsquo;t prepared for what I was about to find.&lt;/p&gt;
&lt;p&gt;Those of you who know me are aware that I don&amp;rsquo;t do well with flights. And of course, there were no direct flights from Galicia, so we had to connect through Barcelona. &lt;code&gt;LCG-BCN&lt;/code&gt;, &lt;code&gt;BCN-BRU&lt;/code&gt;, and the same ordeal on the way back. The return flight went better than the outbound one, thankfully. But let me tell you: it was absolutely worth every minute of anxiety. Worth it and then some.&lt;/p&gt;
&lt;h2 id=&#34;organized-chaos&#34;&gt;Organized chaos&lt;/h2&gt;
&lt;p&gt;Arriving at the ULB and finding thousands of people trying to get into the same talks as you is&amp;hellip; chaotic. There&amp;rsquo;s no other word for it. You can&amp;rsquo;t reserve a seat, you don&amp;rsquo;t know if you&amp;rsquo;ll get in, you queue for twenty minutes only to discover the track is full, you turn around and end up in a talk that wasn&amp;rsquo;t even on your radar.&lt;/p&gt;
&lt;p&gt;And yet, that chaos has something magical about it. It forces you to improvise, to go with the flow, to discover talks you would never have chosen. I ended up in a session about contributing to FOSS projects that blew my mind, simply because the container track queue was impossible. Sometimes the best plan is having no plan at all.&lt;/p&gt;
&lt;h2 id=&#34;walking-among-giants&#34;&gt;Walking among giants&lt;/h2&gt;
&lt;p&gt;But what really hit me was entering the exhibition area. Python. Django. MySQL. Debian. PostgreSQL. Projects I&amp;rsquo;ve been using my entire professional life, right there, with their maintainers behind a table, willing to chat with you like it&amp;rsquo;s nothing.&lt;/p&gt;
&lt;p&gt;I wasn&amp;rsquo;t expecting to get emotional about this. I wasn&amp;rsquo;t expecting to feel so moved when I saw the Debian logo up close, when I could personally thank people who have spent decades building the tools I work with every day. Yes, I know, but this is who we are, those of us who&amp;rsquo;ve been in this field for years: hopeless romantics of free software who sometimes forget why we started.&lt;/p&gt;
&lt;p&gt;FOSDEM reminds you. It reminds you that behind every project there are people, community, hours of selfless work. It reminds you why you chose this path.&lt;/p&gt;
&lt;h2 id=&#34;the-real-treasure-the-people&#34;&gt;The real treasure: the people&lt;/h2&gt;
&lt;p&gt;And then there&amp;rsquo;s the best part of all. The team-building with my new colleagues.&lt;/p&gt;
&lt;p&gt;This trip coincided with an important career change in my life. New company, new projects, new faces on video calls. But knowing someone through a screen is one thing, and sharing Belgian beers and costillas while debating whether GitOps is overrated is something else entirely.&lt;/p&gt;
&lt;p&gt;I met many of them in person for the first time right there, in Brussels. We queued together, got lost around campus, argued about talks, had dinner in unlikely places. These experiences create bonds that no daily standup can ever create.&lt;/p&gt;
&lt;h2 id=&#34;a-turning-point&#34;&gt;A turning point&lt;/h2&gt;
&lt;p&gt;FOSDEM 2026 has been much more than a technical event for me. It&amp;rsquo;s been a turning point of sorts. The closing of one chapter and the beginning of another.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m leaving Brussels with a backpack full of stickers, a head full of ideas, and a heart full of gratitude. Gratitude for the FOSS community that welcomes us, for the new colleagues who already feel close, for this job that allows us to live experiences like this. And gratitude to this &lt;span style=&#34;color: #1f7fd4;&#34;&gt;fly&lt;/span&gt;mate that pushed - almost forced - me to get the flights and the hotel. I&amp;rsquo;d also like to thank the other mate that shared the trips with me and experienced my fear of flying firsthand.&lt;/p&gt;
&lt;p&gt;See you at FOSDEM 2027. It won&amp;rsquo;t be my first time anymore, but I&amp;rsquo;m sure it will still be just as special.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>SRE</title>
      <link>https://oscarmlage.com/posts/sre/</link>
      <pubDate>Mon, 26 Jan 2026 12:00:00 +0100</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/sre/</guid>
      <description>
            &lt;p&gt;&lt;img src=&#34;gallery/sre.jpg&#34; alt=&#34;SRE&#34;&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve recently started a new professional adventure that&amp;rsquo;s both exciting and overwhelming: I&amp;rsquo;ve &amp;ldquo;become&amp;rdquo; a Site Reliability Engineer. It&amp;rsquo;s definitely a change from what I&amp;rsquo;ve been doing, and honestly, it feels like stepping into an appasionate world.&lt;/p&gt;
&lt;p&gt;For years, I&amp;rsquo;ve been working between development and system administration: two worlds that, while related, have their own rhythms and philosophies. I was comfortable there. I knew the tools, I understood the problems, and I had my workflows pretty well established. But comfort zones, as we all know, can be tricky. They&amp;rsquo;re safe, but they can also become limiting.&lt;/p&gt;
&lt;h2 id=&#34;-why-sre&#34;&gt;🤔 Why SRE?&lt;/h2&gt;
&lt;p&gt;Two things drew me to this change: the technical challenge and the philosophy behind SRE. I&amp;rsquo;ve always been curious about how large-scale systems work, how companies manage to keep services running smoothly for millions of users, and how they balance the need for innovation with the requirement for stability. SRE seemed to be at the intersection of all these questions.&lt;/p&gt;
&lt;p&gt;The SRE philosophy resonates with me, this idea of applying Software Engineering principles to infrastructure problems, of measuring everything, of having error budgets instead of aiming for impossible 100% uptime. It&amp;rsquo;s a different way of thinking about systems, and that&amp;rsquo;s precisely what attracted me.&lt;/p&gt;
&lt;p&gt;But let&amp;rsquo;s be real: there&amp;rsquo;s also another crucial reason. A professional opportunity came up that I simply couldn&amp;rsquo;t let slip away. The kind of opportunity that doesn&amp;rsquo;t come around often. And after going through the entire selection process and making it through successfully, well&amp;hellip; how could I say no? Sometimes the universe aligns the right challenge with the right moment, and you just have to take the leap.&lt;/p&gt;
&lt;h2 id=&#34;-the-learning-curve&#34;&gt;📈 The learning curve&lt;/h2&gt;
&lt;p&gt;Let me be honest: the learning curve is steep. Really steep.&lt;/p&gt;
&lt;p&gt;Coming from dev and sys, I thought I had a solid foundation&amp;hellip; but SRE requires a completely different mindset. It&amp;rsquo;s not just about knowing how to code or how to manage servers. It&amp;rsquo;s about understanding systems at scale, about &lt;strong&gt;thinking in pipelines&lt;/strong&gt;, about automation as a first principle rather than an afterthought.&lt;/p&gt;
&lt;p&gt;The world of &lt;strong&gt;CI/CD pipelines&lt;/strong&gt; is fascinating but also humbling. There&amp;rsquo;s so much I don&amp;rsquo;t know yet. Every day I encounter new tools, new concepts, new ways of doing things that make me realize how much there is to learn. GitOps, infrastructure as code, observability patterns, deployment strategies&amp;hellip; the list goes on.&lt;/p&gt;
&lt;h2 id=&#34;-the-impostor-syndrome-is-real&#34;&gt;😰 The impostor syndrome is real&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;d be lying if I said I haven&amp;rsquo;t felt the impostor syndrome creeping in. When you make a radical career shift, especially into a role that&amp;rsquo;s so different from what you&amp;rsquo;ve been doing, it&amp;rsquo;s easy to feel like you don&amp;rsquo;t belong. Like everyone else knows something you don&amp;rsquo;t. Like you&amp;rsquo;re constantly playing catch-up.&lt;/p&gt;
&lt;p&gt;But here&amp;rsquo;s what I&amp;rsquo;m learning to accept: that feeling is normal. It&amp;rsquo;s part of the process. Every expert was once a beginner. Every SRE started somewhere, probably feeling exactly how I feel now.&lt;/p&gt;
&lt;h2 id=&#34;-continuous-learning&#34;&gt;📚 Continuous learning&lt;/h2&gt;
&lt;p&gt;If there&amp;rsquo;s one thing this change has reinforced for me, it&amp;rsquo;s that continuous learning isn&amp;rsquo;t just a buzzword in our profession, it&amp;rsquo;s a necessity. Technology evolves, methodologies change, and new challenges emerge. The moment we stop learning is the moment we start falling behind.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m embracing this overwhelming feeling not as a sign that I made a mistake, but as confirmation that -hopefully- I&amp;rsquo;m growing. That I&amp;rsquo;m pushing myself beyond what was comfortable.&lt;/p&gt;
&lt;h2 id=&#34;-looking-ahead&#34;&gt;🚀 Looking ahead&lt;/h2&gt;
&lt;p&gt;I don&amp;rsquo;t know what the next months will bring. I&amp;rsquo;m sure there will be moments of frustration, of feeling lost, of wondering if I&amp;rsquo;ll ever feel as confident in this role as I did in my previous ones. But I&amp;rsquo;m also certain there will be moments of clarity, of excitement, of that unique satisfaction that comes from understanding something that seemed impossible just days before.&lt;/p&gt;
&lt;p&gt;For now, I&amp;rsquo;m taking it &lt;strong&gt;one pipeline at a time&lt;/strong&gt;, one concept at a time. Learning, experimenting, failing, learning some more.&lt;/p&gt;
&lt;p&gt;And honestly? Despite the challenges, I wouldn&amp;rsquo;t have it any other way.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Leaving the freelance lane</title>
      <link>https://oscarmlage.com/posts/leaving-the-freelance-lane/</link>
      <pubDate>Fri, 12 Dec 2025 09:39:59 +0100</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/leaving-the-freelance-lane/</guid>
      <description>
            &lt;p&gt;For the last few years, freelancing has been one of the most beautiful chapters of my life. It gave me freedom, curiosity, and a strange sense of ownership over every hour of my day. I worked from cafés, trains, campings&amp;hellip; the whole «digital nomad» aesthetic, but with real deadlines and real invoices attached. It was beautiful.&lt;/p&gt;
&lt;p&gt;But bills don&amp;rsquo;t care about your sunsets.&lt;/p&gt;
&lt;p&gt;There was a moment when this way of living felt exactly like a dream. But little by little, the caveats showed up. I found myself spending less time building and more time &lt;em&gt;chasing&lt;/em&gt;: chasing payments, unclear requirements, clients who vanished in the middle of a sprint.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Being your own boss&amp;rdquo; eventually became &amp;ldquo;being your own entire company&amp;rdquo;, and the weight of that started to feel heavier than the freedom it promised. Burnout (&lt;a href=&#34;https://oscarmlage.com/posts/degraded-mode/&#34;&gt;1&lt;/a&gt;, &lt;a href=&#34;https://oscarmlage.com/posts/still-waiting-for-the-joy/&#34;&gt;2&lt;/a&gt;) doesn&amp;rsquo;t always explode suddenly, sometimes it just settles slowly, between your keyboard and your motivation. And lately, it was there more often than I wanted to admit.&lt;/p&gt;
&lt;p&gt;So I made a decision: step out of the freelance lane. I think I need a different kind of challenge now.&lt;/p&gt;
&lt;p&gt;Next Monday, I&amp;rsquo;m starting a new job &lt;strong&gt;as employee&lt;/strong&gt; in a multinational company, jumping into a role that I&amp;rsquo;ve felt so curious about for some time now: &lt;strong&gt;Site Reliability Engineer&lt;/strong&gt;.  A completely new chapter. New tools. New responsibilities. New rhythms. And, of course, new fears.&lt;/p&gt;
&lt;p&gt;The hiring process itself was already an adventure: four interviews, one practical exercise, and a rollercoaster of imposter syndrome mixed with hope. I had never gone through anything like that before, but it turned out to be unexpectedly enriching. Every conversation taught me something about the company, the role, and myself.&lt;/p&gt;
&lt;p&gt;But now the real thing begins. And honestly? I&amp;rsquo;m scared.&lt;/p&gt;
&lt;p&gt;Scared of the schedule changes, the new routines, the expectations&amp;hellip; and especially scared of not being good enough. I know that fear won&amp;rsquo;t disappear overnight but I&amp;rsquo;ll give it everything I have because I&amp;rsquo;m also incredibly excited. The tank is now full of optimism, motivation, curiosity&amp;hellip; It feels like the right moment to reset, to grow, to be part of something bigger than my own invoice calendar.&lt;/p&gt;
&lt;p&gt;Freelancing has been a beautiful ride. Now it&amp;rsquo;s time for a different road. Let&amp;rsquo;s see where it leads.&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Microblogging, here first</title>
      <link>https://oscarmlage.com/posts/microblogging-first-on-my-blog/</link>
      <pubDate>Tue, 28 Oct 2025 13:31:13 +0100</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/microblogging-first-on-my-blog/</guid>
      <description>
            &lt;p&gt;I haven’t officially left Mastodon, but it doesn’t feel the same anymore. Some people I really enjoyed following and chatting with, have moved on (&lt;a href=&#34;https://www.usebox.net/jjm/blog/i-m-not-on-mastodon/&#34;&gt;one of them&lt;/a&gt; was actually one of the main reasons I checked it every day). It’s not part of my daily routine anymore, and that’s okay.&lt;/p&gt;
&lt;p&gt;Until now, I had been using the &lt;a href=&#34;https://oscarmlage.com/microposts&#34;&gt;/microposts&lt;/a&gt; section to simply re-post what I shared on Mastodon (since I left Twitter). But from now on, I’ll start using it differently: as a space of its own.&lt;/p&gt;
&lt;p&gt;I often feel like sharing little things, short thoughts, moments, or photos that don’t quite fit into a full blog post. The kind of small updates you’d normally drop on Instagram, Twitter, or Mastodon.&lt;/p&gt;
&lt;p&gt;That’s what this section is for. A small corner for those day-to-day snippets that make up life between the bigger stories. Simple, quick, but still mine. And still here, on my own space.&lt;/p&gt;
&lt;p&gt;If you’d like to follow along, you can subscribe to its RSS feed &lt;a href=&#34;https://oscarmlage.com/microposts/index.xml&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Enduro</title>
      <link>https://oscarmlage.com/posts/enduro/</link>
      <pubDate>Sat, 25 Oct 2025 13:12:20 +0100</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/enduro/</guid>
      <description>
            &lt;p&gt;Ever since I sold my road bike, that itch to get back on two wheels has always been there in the background, but impossible to ignore. Every time I saw a motorbike pass by, part of me wanted to feel that connection again: the balance, the throttle and the freedom.&lt;/p&gt;
&lt;p&gt;A few weeks ago, a neighbour who rides &lt;em&gt;enduro&lt;/em&gt; offered me the chance to join him for a day in the mountains. He had a 250cc waiting for me. I didn’t think twice. The idea of getting back on a bike, even for just one day, was simply too tempting.&lt;/p&gt;
&lt;p&gt;It was amazing. I started off a bit unsure because the feeling is completely different from road riding. The tires, the grip, the terrain… everything changes. It’s a kind of fun that’s way less predictable, but much more dynamic. You’re constantly adapting, moving, reacting&amp;hellip; and that makes it all even more engaging.&lt;/p&gt;
&lt;p&gt;By the end of the day, I was smiling like a kid. I honestly didn’t expect to enjoy it that much. I thought I’d miss the smoothness of the asphalt, the long curves, the control. But instead, I found a new way of enjoying motorcycles: raw, direct, and full of surprises.&lt;/p&gt;
&lt;p&gt;A pleasant surprise, indeed. And maybe - just maybe - the start of something new.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>The last dance, summer 2025</title>
      <link>https://oscarmlage.com/posts/the-last-dance-summer-2025/</link>
      <pubDate>Tue, 09 Sep 2025 11:45:41 +0200</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/the-last-dance-summer-2025/</guid>
      <description>
            &lt;p&gt;The bikes, left scattered on the grass.  The sunset glowing between the houses, as the kids squeeze the very last hours out of their summer rides.&lt;/p&gt;
&lt;p&gt;It’s been an incredible summer, specially for them. Friends, trips, endless games, and experiences that will now have to wait a whole year to come back again.&lt;/p&gt;
&lt;p&gt;A chapter closed, with memories that -hopefully- will shine bright until the next summer opens its doors.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Still waiting for the joy</title>
      <link>https://oscarmlage.com/posts/still-waiting-for-the-joy/</link>
      <pubDate>Wed, 27 Aug 2025 14:34:12 +0200</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/still-waiting-for-the-joy/</guid>
      <description>
            &lt;p&gt;Spent almost the whole summer away from the keyboard. Thought it would recharge me, but it didn’t. The few times I had to log in it felt wrong: anxiety, palpitations, zero joy.&lt;/p&gt;
&lt;p&gt;Maybe the romance is over… or maybe it’s just the bad times before vacation still present, and I need to give it more time to feel the joy in my fingers again.&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Between the Apple and the Robot</title>
      <link>https://oscarmlage.com/posts/between-the-apple-and-the-robot/</link>
      <pubDate>Wed, 20 Aug 2025 18:26:37 +0200</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/between-the-apple-and-the-robot/</guid>
      <description>
            &lt;p&gt;My iPhone 12 mini has been my faithful companion for more than six years, but starting this summer its battery finally gave up. I even tried to replace it myself, only to end up with a broken screen and a cheap replacement that works far worse than the original. Also the new battery sucks.&lt;/p&gt;
&lt;p&gt;In the meantime, I needed something to keep me connected, and that’s how a POCO X7 Pro landed in my hands. What started as a temporary fix quickly turned into a proper experiment: I’ve been switching back and forth between iOS and Android, and it has been surprisingly fun.&lt;/p&gt;
&lt;h3 id=&#34;rediscovering-android&#34;&gt;Rediscovering Android&lt;/h3&gt;
&lt;p&gt;After years inside the Apple ecosystem, booting up an Android phone felt refreshing. I found myself browsing app stores, installing, tweaking, and customizing just about everything, something I had almost forgotten was possible. The insane level of configurability on Android is astonishing compared to iOS. I already knew it but it really is!.&lt;/p&gt;
&lt;p&gt;On the other hand, I was immediately annoyed by the amount of bloatware preinstalled out of the box. Having to disable or hide unwanted apps is not exactly the kind of freedom I was looking for.&lt;/p&gt;
&lt;h3 id=&#34;big-screen-smooth-motion-endless-battery&#34;&gt;Big Screen, Smooth Motion, Endless Battery&lt;/h3&gt;
&lt;p&gt;I thought moving from the iPhone Mini’s 5.4 inches to a 6.67-inch Android would be a nightmare, but the opposite happened. For videos, maps, and media consumption in general, the larger screen is a real advantage. Add to that the 120Hz refresh rate, which makes iOS feel oddly slow when I switch back, and the POCO starts to shine even more.&lt;/p&gt;
&lt;p&gt;And then there’s the battery: this phone is an absolute beast. Even without a SIM card (to be fair), the difference is shocking. On a road trip, I used it as a GPS for more than two hours, and the battery dropped only 10%. That would be unthinkable on the iPhone side.&lt;/p&gt;
&lt;h3 id=&#34;living-in-two-worlds&#34;&gt;Living in Two Worlds&lt;/h3&gt;
&lt;p&gt;One detail I’ve fell in love with on Android is the simple “back” gesture from either side of the screen. It feels so natural that I immediately miss it on iOS. But gestures aside, the reality is that Apple’s ecosystem still wins where it matters most. With iCloud, my documents, photos, and notes are always synced across my MacBook, iPad, and iPhone. Could I replicate all this with something like Nextcloud? Probably, but I don’t feel like reinventing the wheel right now.&lt;/p&gt;
&lt;h3 id=&#34;takeaways&#34;&gt;Takeaways&lt;/h3&gt;
&lt;p&gt;Switching to Android reminded me that smartphones can be fun again. The customization, the bigger screen, the battery life&amp;hellip; they all make Android incredibly compelling. But when it comes to serious stuff, from productivity to seamless syncing across devices, Apple still has the edge.&lt;/p&gt;
&lt;p&gt;In the end, it feels like a constant trade-off: flexibility and fun on one side, versus the strength of Apple’s ecosystem when you own multiple devices. A big question mark remains over what my next daily driver will be.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Small summer habits</title>
      <link>https://oscarmlage.com/posts/small-summer-habits/</link>
      <pubDate>Wed, 02 Jul 2025 09:18:03 +0200</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/small-summer-habits/</guid>
      <description>
            &lt;p&gt;It’s been nearly impossible to work in the office lately. The heatwave hitting Spain has made my usual setup (comfy chair, dual monitors, perfect lighting) feel more like a sauna than a workspace.&lt;/p&gt;
&lt;p&gt;So, in the spirit of adaptation, I’ve started a new habit. Every morning, I grab my laptop and head downstairs, where the temperature is a few degrees cooler and the air feels a little more forgiving. I set up at the dining table, no fancy setup, just enough space to type and think clearly. And my laptop seems grateful too&amp;hellip; no more fans spinning like turbines.&lt;/p&gt;
&lt;p&gt;To complete the ritual, I’ve added a new daily essential: iced coffee with milk. It’s simple, refreshing, and weirdly satisfying.&lt;/p&gt;
&lt;p&gt;Sometimes, it’s not about having the perfect environment, it’s about making just enough changes to keep going. This setup may be temporary, but for now, it’s keeping me sane and functional.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Degraded mode</title>
      <link>https://oscarmlage.com/posts/degraded-mode/</link>
      <pubDate>Tue, 01 Jul 2025 12:21:23 +0200</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/degraded-mode/</guid>
      <description>
            &lt;p&gt;I&amp;rsquo;ve been applying patches lately. Not to the operating system, nor the load balancer. To myself.&lt;/p&gt;
&lt;p&gt;Sometimes you drift into &lt;em&gt;degraded performance&lt;/em&gt; without even noticing, until something - or someone - triggers an alert. And then you have to check the logs, restart a few processes, clear some space.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s not always a scheduled &lt;em&gt;downtime&lt;/em&gt;. Sometimes maintenance has to be hot, with traffic coming in all the same. But you do what you can.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve disabled some background services, and I&amp;rsquo;m monitoring the load. There&amp;rsquo;s no magic fix, but some tweaks help. A little less noise, a little more pause.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t know when this scheduled task will finish, or whether I&amp;rsquo;ll return with improved performance. But I&amp;rsquo;m still here, doing &lt;code&gt;uptime&lt;/code&gt;, even if not everything is visible from the outside.&lt;/p&gt;
&lt;p&gt;Thanks for sticking around.&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Recently 2025-04</title>
      <link>https://oscarmlage.com/posts/recently-2025-04/</link>
      <pubDate>Mon, 12 May 2025 11:32:01 +0200</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/recently-2025-04/</guid>
      <description>
            &lt;p&gt;April felt like the start of something—almost. That in-between moment where winter still has a grip, but you can smell the freedom of spring just around the corner.&lt;/p&gt;
&lt;h3 id=&#34;-travel&#34;&gt;🚐 Travel&lt;/h3&gt;
&lt;p&gt;We started prepping the van for the season, which is always exciting. Not so exciting: finding out the battery was completely dead. The central locking didn’t work, and neither did the manual locks, so getting it open turned into a bit of a puzzle. Eventually, we managed and headed straight to the mechanic for a battery replacement. The good news? It passed the inspection without any issues. So technically, we’re road-ready.&lt;/p&gt;
&lt;p&gt;That said… both of our first weekend trips were a bust. The rain was omnipresent. We tried twice, hoping for some break in the weather, but each time ended up turning back. Just not worth sitting inside a van watching water pour down the windows.&lt;/p&gt;
&lt;h3 id=&#34;-self-time&#34;&gt;🎮 Self-time&lt;/h3&gt;
&lt;p&gt;In a heroic attempt to extend the life of our ageing phones, I tried replacing the batteries (they were all long overdue). I managed 3 out of 4 without problems, mine being the unlucky one. Cracked the screen in the mid of the operation. The battery replacement did work, but I had to wait for a new screen to actually use it again. Temporarily went back to a phone from 2012. Honestly? Not as bad as expected.&lt;/p&gt;
&lt;p&gt;Unfortunately, the new screen isn’t quite right. Besides the obvious downgrade in refresh rate and quality, it has this habit of waking up by itself and acting glitchy. This phone’s from 2019… might be time to start looking for a real alternative.&lt;/p&gt;
&lt;p&gt;On the brighter side, I got a new mini PC for tinkering. It’s based on the Intel N97 and I’ve set it up with Proxmox. Honestly, it’s been one of the most fun little machines I’ve played with in a long time. So much potential in such a small form factor.&lt;/p&gt;
&lt;h3 id=&#34;-the-blackout&#34;&gt;💡 The blackout&lt;/h3&gt;
&lt;p&gt;On the 28th of April, due to a chain of failures still without a clear explanation, the entire country experienced a massive blackout. For us, it lasted from around 12:30 PM to 21:30 PM.&lt;/p&gt;
&lt;p&gt;It was a strange Monday, we couldn’t really do any of the things we usually would, so we had to improvise. On the bright side, the weather was fantastic. We ended up sharing sandwiches with our neighbours, chatting the whole afternoon away. No phones, no distractions, just people talking. It felt like a regression to a simpler past, where electronics weren’t so central and social interactions were&amp;hellip; healthier. Bonus: we had the perfect excuse to use for the first time the new grill.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Recently 2025-03</title>
      <link>https://oscarmlage.com/posts/recently-2025-03/</link>
      <pubDate>Mon, 07 Apr 2025 21:32:31 +0200</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/recently-2025-03/</guid>
      <description>
            &lt;p&gt;Lately, I’ve been thinking about how time just flies when you’re juggling a bit of everything. March has been a mix of routines, small adventures, and moments that somehow end up sticking with you. Here’s a quick recap of what’s been going on lately&lt;/p&gt;
&lt;h3 id=&#34;-sports&#34;&gt;🏃‍♂️ Sports&lt;/h3&gt;
&lt;p&gt;This year the kids swapped basketball for handball, and they’re loving it!. Since there&amp;rsquo;s only one team in our city, we’re hitting the road every other weekend to play matches around the region. The upside? We’re discovering small towns and new places that are surprisingly close to home but we didn&amp;rsquo;t know.&lt;/p&gt;
&lt;p&gt;On a personal note, 2025 is off to a solid start: I’ve completed all of the Apple Fitness monthly challenges for January, February, and March. Not huge achievements, maybe, but they’ve helped keep me motivated and consistent.&lt;/p&gt;
&lt;p&gt;Gym-wise, I’m staying super regular and starting to notice progress, specially when it comes to intensity. I think that’s what’s really changed this year: not just showing up but pushing the limits.&lt;/p&gt;
&lt;h3 id=&#34;-self-time&#34;&gt;🎮 Self-time&lt;/h3&gt;
&lt;p&gt;Path of Exile has pretty much taken over my spare time since early access launched in December. It&amp;rsquo;s become my main escape lately — which I kind of need right now, if I’m being honest.&lt;/p&gt;
&lt;p&gt;Professionally, I’m in a bit of a stagnant phase. It feels like I’m stuck in place, and I know I need to break out. The time is coming to close my eyes, take a deep breath, and just &lt;em&gt;jump&lt;/em&gt;. Comfort zones are cozy, but they don’t get you far.&lt;/p&gt;
&lt;p&gt;Also part of my personal escape: catching Breogán basketball games with my crew. It’s more than just watching a game — it’s the excuse we need to unwind and share laughs over a beer or two.&lt;/p&gt;
&lt;p&gt;I went to a Mexican restaurant for the first time with the podcast (ex podcast actually) crew. I don’t usually have much to contribute compared to them when it comes to video games (they’re the real pros), but I helped get it started, and I’m glad they still make me feel part of the group.&lt;/p&gt;
&lt;h3 id=&#34;-diy&#34;&gt;🛠️ DIY&lt;/h3&gt;
&lt;p&gt;I’ve been playing around with my home setup and tried something new: two vertical monitors. Honestly? Loving it so far. It’s surprisingly comfortable for reading code, following help, or keeping some auxiliar stuff open without cranking my neck every five seconds.&lt;/p&gt;
&lt;p&gt;On the DIY front, I built a motion-sensor lamp for the front entrance of the house. I used a Son-off switch, ran a couple of wires, and learned a bit more about electronics — a world I’ve always found fascinating but still don’t fully understand. One project at a time.&lt;/p&gt;
&lt;p&gt;Oh, and speaking of the house: we had a tiny uninvited guest in the garage — a mouse. It gave us more than one headache, but after a few traps and some stealthy operations, we finally got it.&lt;/p&gt;
&lt;p&gt;Finally, I did some much-needed maintenance on the van (not without a few headaches) and got it through its inspection. It’s now ready for whatever spring has in store.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;It’s been a while since I last wrote a “Recently” post — and I’d almost forgotten how much I enjoy this format. So it felt like the right time to bring it back, take a moment to look around, and write it all down.&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Blog introspection</title>
      <link>https://oscarmlage.com/posts/blog-introspection/</link>
      <pubDate>Tue, 28 Jan 2025 12:39:49 +0100</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/blog-introspection/</guid>
      <description>
            &lt;p&gt;I&amp;rsquo;ve written posts about the history of this blog &lt;a href=&#34;https://oscarmlage.com/posts/stay-static/&#34;&gt;here&lt;/a&gt; and &lt;a href=&#34;https://oscarmlage.com/posts/hola-hugo/&#34;&gt;there&lt;/a&gt; (and many others have been lost during domain changes). However, this challenge shared by &lt;a href=&#34;https://www.usebox.net/jjm/blog/why-blog/&#34;&gt;el amigo Juanjo&lt;/a&gt; feels like a great exercise in introspection.&lt;/p&gt;
&lt;h2 id=&#34;why-did-you-start-blogging-in-the-first-place&#34;&gt;Why did you start blogging in the first place?&lt;/h2&gt;
&lt;p&gt;Many, many years ago, back when the Internet was practically black and white, my curiosity was sparked by &lt;em&gt;that other free operating system that didn’t belong to any big corporation.&lt;/em&gt; With that interest came the idea to create a website where I could share resources (documentation, manuals, news) about that fascinating project called Linux. That’s how &lt;a href=&#34;https://userlinux.net/&#34;&gt;Userlinux&lt;/a&gt; was born.&lt;/p&gt;
&lt;p&gt;Over time, I discovered the &lt;em&gt;blogosphere&lt;/em&gt;, and with it, I felt an increasing desire to write posts that were less technical and more personal. Somewhere along that transition — and without me even realizing it — Userlinux became &lt;em&gt;my blog.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;what-platform-are-you-using-to-manage-your-blog-and-why-do-you-use-it&#34;&gt;What platform are you using to manage your blog, and why do you use it?&lt;/h2&gt;
&lt;p&gt;Currently, I&amp;rsquo;m using &lt;a href=&#34;https://gohugo.io/&#34;&gt;Hugo&lt;/a&gt; because I don&amp;rsquo;t need anything beyond a static site. However, this blog has also been one of the main excuses for investing time in learning by developing my own content management systems. It started as a custom &lt;code&gt;PHP+MySQL&lt;/code&gt; setup, then went through several development frameworks before evolving into &lt;a href=&#34;https://pypi.org/project/django-rblog/1.8.0/&#34;&gt;a Django package&lt;/a&gt; with support for &lt;code&gt;MySQL&lt;/code&gt; and &lt;code&gt;Redis&lt;/code&gt;. Good times.&lt;/p&gt;
&lt;h2 id=&#34;have-you-blogged-on-other-platforms-before&#34;&gt;Have you blogged on other platforms before?&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve used other platforms (both commercial and open-source) for other projects and to gather ideas for features I could implement in my own CMS. In fact, when I planned the domain change (userlinux.net → oscarmlage.com), I tested several platforms before settling on the one that, in my opinion, best suited my needs.&lt;/p&gt;
&lt;h2 id=&#34;whats-your-favourite-post-on-your-blog&#34;&gt;What’s your favourite post on your blog?&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s hard to decide — it&amp;rsquo;s been over 20 years of posts! However, if I had to choose, I think my top favorites would be the ones that reflect changes, projects, or emotions that, in some way, have shaped my life (in chronological order):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://oscarmlage.com/posts/una-fantastica-idea/&#34;&gt;Una fantástica idea&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://oscarmlage.com/posts/the-van/&#34;&gt;The Van&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://oscarmlage.com/posts/good-bye-vila-penguin/&#34;&gt;Good Bye Vila Penguin &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;any-future-plans-for-the-blog&#34;&gt;Any future plans for the blog?&lt;/h2&gt;
&lt;p&gt;I have no idea what the future holds, but I believe it’s the past that has defined what this site has become, so the present is helping shape what will happen in the future (what a ridiculous way to say I have no idea).&lt;/p&gt;
&lt;p&gt;BTW, if you like the LORE, I have to say that in the past I’ve changed the way I viewed this little space many times. It went from being a place for documentation and/or technical posts related to Linux and programming languages, to a place I used as an escape and outlet for various frustrations.&lt;/p&gt;
&lt;p&gt;At one point, I tried to keep two separate sites, one for personal and one for professional content, thinking it was best for my career and that I shouldn’t mix apples with oranges. But over time, I realized there’s no sense in dividing myself like that because, in the end, I’m the same person, with all the good and bad that comes with it.&lt;/p&gt;
&lt;p&gt;If we look at the present, with everything happening in the tech giants, content filtering, and the mix of politics&amp;hellip; we can get a glimpse of what the future might look like.&lt;/p&gt;
&lt;p&gt;I think, on one hand, decentralized networks and having control and authorship over the content we write is a great decision. That’s why I can’t imagine writing anywhere other than a &lt;em&gt;site&lt;/em&gt; that I can manage and control myself. As for the topics, it’s hard to define, but I don’t think it’s much different from what it already is today.&lt;/p&gt;
&lt;p&gt;I’m not sure if I should tag someone else, I guess I should to keep the chain going&amp;hellip; so, even though it’s a bit of a hassle, I think &lt;a href=&#34;https://www.splitbrain.org&#34;&gt;Andreas&lt;/a&gt; will have a lovely story to tell us about his blog.&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Sometimes</title>
      <link>https://oscarmlage.com/posts/sometimes/</link>
      <pubDate>Mon, 20 Jan 2025 20:29:54 +0100</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/sometimes/</guid>
      <description>
            &lt;p&gt;Sometimes, things don’t turn out as planned. Not how you expected, not how you hoped, and certainly not how you envisioned them. Sometimes, life forces you to question motivations that feel irrational or outcomes that are beyond your control, things that aren’t tied to your effort, your decisions, or your intentions.&lt;/p&gt;
&lt;p&gt;Sometimes, you watch yourself shrink, becoming smaller and smaller, as you search for clarity that never quite comes, for explanations that refuse to make sense. Sometimes, life is simply about facing it&amp;hellip; about finding a way to say &lt;code&gt;keep pushing&lt;/code&gt; because you know that’s what you’re supposed to do, even when it feels impossible.&lt;/p&gt;
&lt;p&gt;Sometimes, the hardest battles aren’t visible.&lt;/p&gt;
&lt;p&gt;Sometimes.&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Magic of Christmas Fades</title>
      <link>https://oscarmlage.com/posts/magic-of-christmas-fades/</link>
      <pubDate>Wed, 08 Jan 2025 18:08:32 +0100</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/magic-of-christmas-fades/</guid>
      <description>
            &lt;p&gt;And the day came when a part of the magic and innocence of Christmas was lost. At 12 years old, it feels as though something inside me has been taken away.&lt;/p&gt;
&lt;p&gt;I hope I made the right choice. At this age, and with high school in the mix, handling it differently might have been even harsher.&lt;/p&gt;
&lt;p&gt;As someone on Mastodon suggested, it’s a natural step—one that seems more traumatic for parents than for children. I couldn’t agree more.&lt;/p&gt;
&lt;p&gt;I suppose it’s normal to feel this way as a parent. Still, I hope that next Christmas will be just as magical and beautiful as always. I’ll do my best to ensure that, even though everything has changed, it still feels like nothing has.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Hugo and Obsidian</title>
      <link>https://oscarmlage.com/posts/hugo-and-obsidian/</link>
      <pubDate>Mon, 23 Dec 2024 16:20:30 +0100</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/hugo-and-obsidian/</guid>
      <description>
            &lt;p&gt;Some time ago, I decided to integrate &lt;a href=&#34;https://gohugo.io/&#34;&gt;Hugo&lt;/a&gt;, the static site generator, with &lt;a href=&#34;https://obsidian.md/&#34;&gt;Obsidian&lt;/a&gt;, my favorite note-taking tool, so that writing becomes the only obstacle to publishing new content. This post explains how I set it up and shares some tips to reduce the friction between writing, generating, and publishing.&lt;/p&gt;
&lt;h2 id=&#34;hugo&#34;&gt;Hugo&lt;/h2&gt;
&lt;p&gt;My use of &lt;a href=&#34;https://gohugo.io/&#34;&gt;Hugo&lt;/a&gt; is limited to my development machine, where I have it set up to run in a &lt;a href=&#34;https://www.docker.com/&#34;&gt;Docker&lt;/a&gt; container in a relatively simple way. Once it&amp;rsquo;s running, I access to &lt;code&gt;http://localhost:1313&lt;/code&gt; to preview the post (or any changes) on a local development server. Here’s my &lt;code&gt;docker-compose.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;color:#f92672&#34;&gt;version&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;3.1&amp;#34;&lt;/span&gt;

&lt;span style=&#34;color:#f92672&#34;&gt;services&lt;/span&gt;:

  &lt;span style=&#34;color:#f92672&#34;&gt;build&lt;/span&gt;:
    &lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;klakegg/hugo:0.88.0-ext-alpine&lt;/span&gt;
    &lt;span style=&#34;color:#f92672&#34;&gt;command&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;build&lt;/span&gt;
    &lt;span style=&#34;color:#f92672&#34;&gt;volumes&lt;/span&gt;:
      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;${PWD}/src:/src&amp;#34;&lt;/span&gt;

  &lt;span style=&#34;color:#f92672&#34;&gt;serve&lt;/span&gt;:
    &lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;klakegg/hugo:0.88.0-ext-alpine&lt;/span&gt;
    &lt;span style=&#34;color:#f92672&#34;&gt;command&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;server -vv&lt;/span&gt;
    &lt;span style=&#34;color:#f92672&#34;&gt;volumes&lt;/span&gt;:
      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;${PWD}/src:/src&amp;#34;&lt;/span&gt;
    &lt;span style=&#34;color:#f92672&#34;&gt;ports&lt;/span&gt;:
      - &lt;span style=&#34;color:#ae81ff&#34;&gt;1313&lt;/span&gt;:&lt;span style=&#34;color:#ae81ff&#34;&gt;1313&lt;/span&gt;
    &lt;span style=&#34;color:#f92672&#34;&gt;stdin_open&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
    &lt;span style=&#34;color:#f92672&#34;&gt;tty&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I could use &lt;code&gt;docker compose up -d&lt;/code&gt;, but we &lt;em&gt;lazy folks&lt;/em&gt; are always looking for shortcuts, so for me, it’s just &lt;code&gt;make start&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Once I’m happy with the new content, I run a synchronization script against the production server. It could be something like &lt;code&gt;rsync -e ssh -avz . user@prod:/path/to/oscarmlage.com&lt;/code&gt;, but again, I prefer shortcuts. For me, it’s just a simple &lt;code&gt;make deploy&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The black magic that handles all of this is called a &lt;code&gt;Makefile&lt;/code&gt;. It’s located at the root of the project and looks something like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;color:#f92672&#34;&gt;build&lt;/span&gt;:
	&lt;span style=&#34;color:#ae81ff&#34;&gt;docker-compose -f docker-compose.yml up build&lt;/span&gt;

&lt;span style=&#34;color:#f92672&#34;&gt;serve&lt;/span&gt;:
	&lt;span style=&#34;color:#ae81ff&#34;&gt;docker-compose -f docker-compose.yml up serve&lt;/span&gt;

&lt;span style=&#34;color:#f92672&#34;&gt;bash&lt;/span&gt;:
	&lt;span style=&#34;color:#ae81ff&#34;&gt;docker-compose -f docker-compose.yml exec serve bash&lt;/span&gt;

&lt;span style=&#34;color:#f92672&#34;&gt;shell&lt;/span&gt;:
	&lt;span style=&#34;color:#ae81ff&#34;&gt;docker-compose -f docker-compose.yml run build shell&lt;/span&gt;

&lt;span style=&#34;color:#f92672&#34;&gt;deploy&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;up&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;sync&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;up&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;up&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;build&lt;/span&gt;
	&lt;span style=&#34;color:#ae81ff&#34;&gt;rsync -e &amp;#39;ssh -p 22235&amp;#39; -avz src/public/ user@prod:/path/to/oscarmlage/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To give you an idea, here’s the project structure:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;.&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;├── Makefile&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;├── docker-compose.yml&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;├── src&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;│   ├── config.yml&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;│   ├── archetypes&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;│   │   ├── default.md&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;│   │   └── posts&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;│   │       ├── gallery&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;│   │       │   └── delete.me&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;│   │       └── index.md&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;│   ├── content&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;│   │   ├── posts&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;│   │   │   ├── a-movie-for-a-change&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;│   │   │   │   └── index.md&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There’s not much more to say about the &lt;em&gt;Hugo&lt;/em&gt; configuration. The only notable detail is that the archetype for posts, as seen in the &lt;em&gt;skel&lt;/em&gt;, ensures that each post has its own directory with an &lt;code&gt;index.md&lt;/code&gt; inside, along with a &lt;code&gt;gallery/&lt;/code&gt; directory if there’s a need to attach any photos or galleries.&lt;/p&gt;
&lt;h2 id=&#34;obsidian&#34;&gt;Obsidian&lt;/h2&gt;
&lt;p&gt;On the &lt;em&gt;Obsidian&lt;/em&gt; side, the goal was to keep the workflow as smooth as possible without duplicating efforts. The first decision was whether to create a separate vault exclusively for the blog or to use the same vault I already had for my daily notes. Since I wasn’t keen on setting up another vault with the plugins, theme, and other configurations I’d need (I guess programmers are naturally like this :P), I decided to use the same one. The trick in this case was to add &lt;code&gt;src/content&lt;/code&gt; to my vault (located in a completely different directory). Nothing a &lt;em&gt;symbolic link&lt;/em&gt; can’t fix:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;$ ls ~/vaults/Personal/Projects/oscarmlage.com/
total &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; drwxr-xr-x@ Oct &lt;span style=&#34;color:#ae81ff&#34;&gt;25&lt;/span&gt; 12:59 .
&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; drwxr-xr-x@ Nov &lt;span style=&#34;color:#ae81ff&#34;&gt;14&lt;/span&gt; 18:55 ..
&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; lrwxr-xr-x  Oct &lt;span style=&#34;color:#ae81ff&#34;&gt;25&lt;/span&gt; 12:59 medialog -&amp;gt; ~/oscarmlage.com/src/content/medialog
&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; lrwxr-xr-x  Oct &lt;span style=&#34;color:#ae81ff&#34;&gt;25&lt;/span&gt; 12:59 microposts -&amp;gt; ~/oscarmlage.com/src/content/microposts
&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; lrwxr-xr-x  Oct &lt;span style=&#34;color:#ae81ff&#34;&gt;25&lt;/span&gt; 12:59 posts -&amp;gt; ~/oscarmlage.com/src/content/posts
&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;...&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This way, from &lt;em&gt;Obsidian&lt;/em&gt;, I can create new content directly in the correct location. However, I wasn’t completely satisfied because, as I mentioned earlier, creating a post requires setting up a directory with the slug, an &lt;code&gt;index.md&lt;/code&gt;, and the frontmatter… and that’s something that would be fantastic to automate. This is where &lt;a href=&#34;https://github.com/SilentVoid13/Templater&#34;&gt;Templater&lt;/a&gt; comes into play — a plugin that allows us to do exactly that, among many other things: executing &lt;em&gt;custom actions&lt;/em&gt; when creating new content within a directory.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;As shown in the screenshot, Templater&amp;rsquo;s configuration includes an option called &lt;em&gt;Folder templates&lt;/em&gt;, which triggers a &amp;ldquo;script/template&amp;rdquo; every time a new file is created in that folder. We select the folder for our blog posts on one side, and the &lt;code&gt;post.md&lt;/code&gt; template on the other, which would look something like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;%*&lt;/span&gt;
&lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;toSlug&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;title&lt;/span&gt;) {
    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;title&lt;/span&gt;
        .&lt;span style=&#34;color:#a6e22e&#34;&gt;toLowerCase&lt;/span&gt;()
        .&lt;span style=&#34;color:#a6e22e&#34;&gt;normalize&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;NFD&amp;#34;&lt;/span&gt;)
        .&lt;span style=&#34;color:#a6e22e&#34;&gt;replace&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;/[\u0300-\u036f]/g&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
        .&lt;span style=&#34;color:#a6e22e&#34;&gt;replace&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;/[^a-z0-9\s-]/g&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
        .&lt;span style=&#34;color:#a6e22e&#34;&gt;trim&lt;/span&gt;()
        .&lt;span style=&#34;color:#a6e22e&#34;&gt;replace&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;/\s+/g&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;-&amp;#34;&lt;/span&gt;);
}

&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;qcFileName&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;tp&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;system&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;prompt&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Post Title&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;titleName&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;toSlug&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;qcFileName&lt;/span&gt;);
&lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;tp&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;file&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;rename&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;titleName&lt;/span&gt;);
&lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;tp&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;file&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;move&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Projects/oscarmlage.com/posts/&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;titleName&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/index&amp;#34;&lt;/span&gt;);
&lt;span style=&#34;color:#f92672&#34;&gt;-%&amp;gt;&lt;/span&gt;
&lt;span style=&#34;color:#f92672&#34;&gt;---&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;title&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;%&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;qcFileName&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;%&amp;gt;&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;date&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;%&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;tp&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;file&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;creation_date&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;YYYY-MM-DDTHH:mm:ssZ&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;%&amp;gt;&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;draft&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;tags&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; []
&lt;span style=&#34;color:#f92672&#34;&gt;---&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As we can see in the code above, every time we add a new post to the configured directory (the symbolic link we previously created connecting &lt;code&gt;src/content&lt;/code&gt; from &lt;em&gt;Hugo&lt;/em&gt; with &lt;em&gt;Obsidian&lt;/em&gt;), the flow of what &lt;em&gt;Obsidian&lt;/em&gt; does is as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A prompt asks us for the post title: &lt;code&gt;Hugo and Obsidian&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It converts that title into a slug.&lt;/li&gt;
&lt;li&gt;Renames and moves the file to its proper location: &lt;code&gt;posts/hugo-and-obsidian/index.md&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Adds the &lt;em&gt;frontmatter&lt;/em&gt; to the file, so all we need to focus on is writing the post content.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;flow&#34;&gt;Flow&lt;/h2&gt;
&lt;p&gt;My workflow for creating new posts with this integration is quite simple and efficient. First, I open &lt;em&gt;Obsidian&lt;/em&gt; and navigate to the directory where the blog posts are stored. There, I create a new note and assign the post title in the modal. Thanks to the integration with &lt;em&gt;Templater&lt;/em&gt;, the trigger automatically runs and applies the predefined template with everything needed for &lt;em&gt;Hugo&lt;/em&gt; (archetype, date, tags&amp;hellip;). Once the trigger finishes, I simply start writing the post content directly in &lt;em&gt;Obsidian&lt;/em&gt;.&lt;/p&gt;
&lt;video width=100% controls autoplay&gt;
    &lt;source src=&#34;gallery/hugo-and-obsidian-01.mp4&#34; type=&#34;video/webm&#34;&gt;
    Your browser does not support the video tag.  
&lt;/video&gt;
&lt;p&gt;Since &lt;a href=&#34;https://obsidian.md/changelog/2024-12-18-desktop-v1.8.0/&#34;&gt;version 1.8&lt;/a&gt;, &lt;em&gt;Obsidian&lt;/em&gt; includes a Core Plugin called &lt;strong&gt;Web Viewer&lt;/strong&gt;, which allows us to have the web page and the &lt;code&gt;index.md&lt;/code&gt; side by side. This way, as we write in one &lt;em&gt;Obsidian&lt;/em&gt; pane, we can see the result in the other in real time. All you need is &lt;em&gt;Hugo&lt;/em&gt; serving locally (&lt;code&gt;make serve&lt;/code&gt;) and pointing the &lt;strong&gt;Web Viewer&lt;/strong&gt; to the new post&amp;rsquo;s URL: &lt;code&gt;http://localhost:1313/posts/hugo-and-obsidian/&lt;/code&gt;.&lt;/p&gt;
&lt;video width=100% controls autoplay&gt;
    &lt;source src=&#34;gallery/blog-edit-obsidian.mp4&#34; type=&#34;video/webm&#34;&gt;
    Your browser does not support the video tag.  
&lt;/video&gt;
&lt;p&gt;Once the creation process is complete and the content has been reviewed, we return to our beloved terminal and run &lt;code&gt;make deploy&lt;/code&gt; to synchronize the content with the production server. The content is now published and available to everyone.&lt;/p&gt;
&lt;video width=100% controls autoplay&gt;
    &lt;source src=&#34;gallery/make-deploy.mp4&#34; type=&#34;video/webm&#34;&gt;
    Your browser does not support the video tag.  
&lt;/video&gt;
&lt;p&gt;This integration between &lt;strong&gt;Hugo&lt;/strong&gt; and &lt;strong&gt;Obsidian&lt;/strong&gt; allows me to maintain a smooth and centralized workflow, reducing friction when creating and publishing content. It might also fit into your publishing process — perhaps not the entire process, but if you can make use of some of the steps, this post will have been worth it.&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>FIFA night</title>
      <link>https://oscarmlage.com/posts/fifa-night/</link>
      <pubDate>Fri, 20 Dec 2024 23:58:06 +0100</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/fifa-night/</guid>
      <description>
            &lt;p&gt;Something I&amp;rsquo;ve been waiting for years finally happened tonight: for the first time, &amp;ldquo;the boys&amp;rdquo; and I were left alone at home, and the idea of &lt;em&gt;&amp;ldquo;playing some FIFA&amp;rdquo;&lt;/em&gt; came up naturally. As cliché as it may sound, it was something I never planned to suggest myself, but I secretly hoped it would come up spontaneously from one of the kids.&lt;/p&gt;
&lt;p&gt;So, we had a total FAIL of a dinner together (not everything had to go perfectly &lt;code&gt;¯\_(ツ)_/¯&lt;/code&gt;), and then we spent almost three hours building some serious thumb calluses. It was incredibly fun — specially after I got used to the button layout on the Nintendo Switch.&lt;/p&gt;
&lt;p&gt;What made the night special wasn’t just the laughter or the /friendly/ competition but the fact that it felt so effortless. It was a shared moment that needed no grand planning, no schedules, just us being together, enjoying this FIFA thing.&lt;/p&gt;
&lt;p&gt;The rest will live on in my memory, and I really hope I don&amp;rsquo;t have to wait as long to do it again.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>The bridges of the Matrix</title>
      <link>https://oscarmlage.com/posts/the-bridges-of-the-matrix/</link>
      <pubDate>Fri, 22 Nov 2024 12:06:25 +0100</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/the-bridges-of-the-matrix/</guid>
      <description>
            &lt;p&gt;Once, I met a robot who shared some wise words with me. It said, «&lt;em&gt;I am a bridge, built to connect worlds that were never meant to meet. On one side, a web of infinite possibilities; on the other, the raw, unfiltered depths of reality. I don’t judge the messages I carry and simply ensure they reach the other side.&lt;/em&gt;».&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;That was my experience with Matrix years ago—a cursed bridge connecting my reality with the rest of the world. One day, I got tired of it. It had become unsustainable because of something called &lt;em&gt;federation&lt;/em&gt;. Unsustainable in terms of both traffic and data volume. Too much computational overhead.&lt;/p&gt;
&lt;p&gt;These days, I’ve returned to &lt;em&gt;The Matrix&lt;/em&gt;. After (hopefully) learning from my mistakes, I realized I missed those white letters on a black background that let me gather all communication into a single terminal.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; We’ll be using Docker for this entire setup, so &lt;code&gt;docker&lt;/code&gt; and &lt;code&gt;docker compose&lt;/code&gt; are a &lt;em&gt;must&lt;/em&gt; if you want to follow along with this post.&lt;/p&gt;
&lt;h2 id=&#34;dns&#34;&gt;DNS&lt;/h2&gt;
&lt;p&gt;What do we need in terms of DNS? Just two domains or subdomains: one for our &lt;em&gt;homeserver&lt;/em&gt; to be visible and reachable, and another, optionally, for the web client. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;matrix.example.com&lt;/li&gt;
&lt;li&gt;chat.example.com&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pointing them to the server where we’ll install this entire stack is enough.&lt;/p&gt;
&lt;h2 id=&#34;synapse&#34;&gt;Synapse&lt;/h2&gt;
&lt;p&gt;We’ll run &lt;a href=&#34;https://github.com/matrix-org/synapse&#34;&gt;Synapse&lt;/a&gt; with &lt;code&gt;PostgreSQL&lt;/code&gt; on port &lt;code&gt;8008&lt;/code&gt;. But before diving deeper, the first step is to generate a base configuration to work with. To do this, execute the following (having already created a directory to store this configuration and passing it as a volume, e.g., &lt;code&gt;mkdir -p data/synapse&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;$ sudo docker run -it --rm &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;    -v &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;./data/synapse:/data&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;    -e SYNAPSE_SERVER_NAME&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;matrix.example.com &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;    -e SYNAPSE_REPORT_STATS&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;yes &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;    matrixdotorg/synapse:latest generate
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will create a &lt;code&gt;homeserver.yaml&lt;/code&gt; file in the &lt;code&gt;./data/synapse/&lt;/code&gt; directory, which we’ll modify to include the connection parameters for &lt;code&gt;PostgreSQL&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span style=&#34;color:#f92672&#34;&gt;database&lt;/span&gt;:  
    &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;psycopg2  &lt;/span&gt;
    &lt;span style=&#34;color:#f92672&#34;&gt;args&lt;/span&gt;:  
    &lt;span style=&#34;color:#f92672&#34;&gt;user&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;postgres  &lt;/span&gt;
    &lt;span style=&#34;color:#f92672&#34;&gt;password&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;XXX  &lt;/span&gt;
    &lt;span style=&#34;color:#f92672&#34;&gt;database&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;synapse  &lt;/span&gt;
    &lt;span style=&#34;color:#f92672&#34;&gt;host&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;postgres  &lt;/span&gt;
    &lt;span style=&#34;color:#f92672&#34;&gt;cp_min&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;  
    &lt;span style=&#34;color:#f92672&#34;&gt;cp_max&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Since there are some variables we don’t want to hardcode in the configuration of this entire stack, we’ll create an environment file (&lt;code&gt;touch .env&lt;/code&gt;) and add specific values for different components of the stack. For &lt;em&gt;Synapse&lt;/em&gt;, it will look like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Synapse&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;SYNAPSE_HOST&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;matrix.example.com&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;SYNAPSE_PORT&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;8008&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;elementweb&#34;&gt;Elementweb&lt;/h2&gt;
&lt;p&gt;We’ll run &lt;a href=&#34;https://github.com/element-hq/element-web/releases&#34;&gt;Elementweb&lt;/a&gt; on port &lt;code&gt;9999&lt;/code&gt;, mapped to &lt;code&gt;80&lt;/code&gt;. Like with &lt;em&gt;Synapse&lt;/em&gt;, we first need to create an initial configuration. On the official &lt;em&gt;Elementweb&lt;/em&gt; website, &lt;a href=&#34;https://develop.element.io/config.json&#34;&gt;they provide an example&lt;/a&gt; that we only need to tweak slightly by editing the first lines. Save this &lt;code&gt;config.json&lt;/code&gt; file, for example, in &lt;code&gt;./data/elementweb/&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;{
    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;default_server_config&amp;#34;&lt;/span&gt;: {
        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;m.homeserver&amp;#34;&lt;/span&gt;: {
            &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;base_url&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://matrix.example.com&amp;#34;&lt;/span&gt;,
            &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;server_name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;matrix.example.com&amp;#34;&lt;/span&gt;
        },
        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;m.identity_server&amp;#34;&lt;/span&gt;: {
            &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;base_url&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://vector.im&amp;#34;&lt;/span&gt;
        }
    },
    &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;...&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Additionally, we’ll add these values to our &lt;code&gt;.env&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Elementweb&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;ELEMENT_HOST&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;chat.example.com&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;ELEMENT_PORT&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;postgresql&#34;&gt;PostgreSQL&lt;/h2&gt;
&lt;p&gt;In my previous experience with this stack, I went through two phases. The first was just to see how everything worked, so I chose &lt;code&gt;SQLite&lt;/code&gt; as the database system. I immediately regretted it when I saw the traffic and data generated by federation. The second phase came when I had to migrate everything to &lt;code&gt;PostgreSQL&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;With things running more smoothly, the plan now—even without federation in the mix—is to use &lt;code&gt;PostgreSQL&lt;/code&gt; from the start. That way, all we need are credentials; &lt;code&gt;Docker&lt;/code&gt; will handle the rest. Just add these values to the &lt;code&gt;.env&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# PostgreSQL&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;POSTGRES_DB&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;synapse&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;POSTGRES_USER&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;postgres&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;XXX&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;docker&#34;&gt;Docker&lt;/h2&gt;
&lt;p&gt;Now that we have the configuration ready, it’s time to shape it into a compose file. Let’s get to it. Here’s an overview of the folder structure:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;docker-matrix/&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;├── data/&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;│   ├── elementweb/&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;│   │   ├── config.json&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;│   ├── synapse/&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;│   │   ├── homeserver.yaml&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;│   │   ├── ...&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;│   ├── postgres/&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;│   ├── backup/&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;├── docker-compose.yml&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;├── .env&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;docker-compose.yml&lt;/code&gt; file would look like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span style=&#34;color:#f92672&#34;&gt;version&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;3.1&amp;#34;&lt;/span&gt;

&lt;span style=&#34;color:#f92672&#34;&gt;services&lt;/span&gt;:

    &lt;span style=&#34;color:#f92672&#34;&gt;postgres&lt;/span&gt;:
        &lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;postgres:14&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;env_file&lt;/span&gt;:
          - &lt;span style=&#34;color:#ae81ff&#34;&gt;./.env&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;container_name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;postgres&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;hostname&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;postgres&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;ports&lt;/span&gt;:
          - &lt;span style=&#34;color:#ae81ff&#34;&gt;5432&lt;/span&gt;:&lt;span style=&#34;color:#ae81ff&#34;&gt;5433&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;environment&lt;/span&gt;:
          - &lt;span style=&#34;color:#ae81ff&#34;&gt;POSTGRES_DB=${POSTGRES_DB}&lt;/span&gt;
          - &lt;span style=&#34;color:#ae81ff&#34;&gt;POSTGRES_USER=${POSTGRES_USER}&lt;/span&gt;
          - &lt;span style=&#34;color:#ae81ff&#34;&gt;POSTGRES_PASSWORD=${POSTGRES_PASSWORD}&lt;/span&gt;
          - &lt;span style=&#34;color:#ae81ff&#34;&gt;POSTGRES_INITDB_ARGS=--encoding=&amp;#39;UTF8&amp;#39; --lc-collate=&amp;#39;C&amp;#39; --lc-ctype=&amp;#39;C&amp;#39;&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;volumes&lt;/span&gt;:
          - &lt;span style=&#34;color:#ae81ff&#34;&gt;./data/postgres/:/var/lib/postgresql/data&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;restart&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;unless-stopped&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;networks&lt;/span&gt;:
          &lt;span style=&#34;color:#f92672&#34;&gt;default&lt;/span&gt;:
            &lt;span style=&#34;color:#f92672&#34;&gt;ipv4_address&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;10.10.10.2&lt;/span&gt;

    &lt;span style=&#34;color:#f92672&#34;&gt;adminer&lt;/span&gt;:
        &lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;adminer:4.8.1&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;container_name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;adminer&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;hostname&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;adminer&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;ports&lt;/span&gt;:
          - &lt;span style=&#34;color:#ae81ff&#34;&gt;9899&lt;/span&gt;:&lt;span style=&#34;color:#ae81ff&#34;&gt;8080&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;restart&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;unless-stopped&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;networks&lt;/span&gt;:
          &lt;span style=&#34;color:#f92672&#34;&gt;default&lt;/span&gt;:
            &lt;span style=&#34;color:#f92672&#34;&gt;ipv4_address&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;10.10.10.3&lt;/span&gt;

    &lt;span style=&#34;color:#f92672&#34;&gt;elementweb&lt;/span&gt;:
        &lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;vectorim/element-web:latest&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;env_file&lt;/span&gt;:
          - &lt;span style=&#34;color:#ae81ff&#34;&gt;./.env&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;container_name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;elementweb&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;hostname&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;elementweb&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;environment&lt;/span&gt;:
          &lt;span style=&#34;color:#f92672&#34;&gt;VIRTUAL_HOST&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;${ELEMENT_HOST}&lt;/span&gt;
          &lt;span style=&#34;color:#f92672&#34;&gt;VIRTUAL_PORT&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;${ELEMENT_PORT}&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;ports&lt;/span&gt;:
            - &lt;span style=&#34;color:#ae81ff&#34;&gt;9999&lt;/span&gt;:&lt;span style=&#34;color:#ae81ff&#34;&gt;${ELEMENT_PORT}&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;volumes&lt;/span&gt;:
            - &lt;span style=&#34;color:#ae81ff&#34;&gt;./data/elementweb/config.json:/app/config.json:rw&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;restart&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;unless-stopped&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;networks&lt;/span&gt;:
          &lt;span style=&#34;color:#f92672&#34;&gt;default&lt;/span&gt;:
            &lt;span style=&#34;color:#f92672&#34;&gt;ipv4_address&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;10.10.10.4&lt;/span&gt;

    &lt;span style=&#34;color:#f92672&#34;&gt;synapse&lt;/span&gt;:
        &lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;matrixdotorg/synapse:latest&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;env_file&lt;/span&gt;:
          - &lt;span style=&#34;color:#ae81ff&#34;&gt;./.env&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;container_name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;synapse&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;hostname&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;synapse&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;environment&lt;/span&gt;:
          &lt;span style=&#34;color:#f92672&#34;&gt;VIRTUAL_HOST&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;${SYNAPSE_HOST}&lt;/span&gt;
          &lt;span style=&#34;color:#f92672&#34;&gt;VIRTUAL_PORT&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;${SYNAPSE_PORT}&lt;/span&gt;
          &lt;span style=&#34;color:#f92672&#34;&gt;SYNAPSE_SERVER_NAME&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;${SYNAPSE_HOST}&lt;/span&gt;
          &lt;span style=&#34;color:#f92672&#34;&gt;SYNAPSE_REPORT_STATS&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;no&amp;#34;&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;ports&lt;/span&gt;:
            - &lt;span style=&#34;color:#ae81ff&#34;&gt;${SYNAPSE_PORT}:${SYNAPSE_PORT}&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;volumes&lt;/span&gt;:
            - &lt;span style=&#34;color:#ae81ff&#34;&gt;./data/synapse:/data:rw&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;depends_on&lt;/span&gt;:
            - &lt;span style=&#34;color:#ae81ff&#34;&gt;postgres&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;restart&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;unless-stopped&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;networks&lt;/span&gt;:
          &lt;span style=&#34;color:#f92672&#34;&gt;default&lt;/span&gt;:
            &lt;span style=&#34;color:#f92672&#34;&gt;ipv4_address&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;10.10.10.5&lt;/span&gt;

&lt;span style=&#34;color:#f92672&#34;&gt;networks&lt;/span&gt;:
  &lt;span style=&#34;color:#f92672&#34;&gt;default&lt;/span&gt;:
    &lt;span style=&#34;color:#f92672&#34;&gt;external&lt;/span&gt;:
      &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;matrix&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And here’s the complete &lt;code&gt;.env&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# General&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;DOCKER_ENV&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;production&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;PROJECT_NAME&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;matrix&lt;/span&gt;

&lt;span style=&#34;color:#75715e&#34;&gt;# PostgreSQL&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;POSTGRES_DB&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;synapse&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;POSTGRES_USER&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;postgres&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;XXX&lt;/span&gt;

&lt;span style=&#34;color:#75715e&#34;&gt;# Elementweb&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;ELEMENT_HOST&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;chat.example.com&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;ELEMENT_PORT&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;80&lt;/span&gt;

&lt;span style=&#34;color:#75715e&#34;&gt;# Synapse&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;SYNAPSE_HOST&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;matrix.example.com&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;SYNAPSE_PORT&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;8008&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Before anything else, we’ll create the required network:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ docker network create --driver=bridge --subnet=10.10.10.0/24 --gateway=10.10.10.1 matrix
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Once everything is set up, run &lt;code&gt;docker compose up -d&lt;/code&gt; to start all the services and wait a few minutes for everything to become healthy.&lt;/p&gt;
&lt;p&gt;After launching, since our Synapse has registration disabled, we’ll register a user via the console like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;$ docker exec -it synapse bash
$ register_new_matrix_user -c /data/homeserver.yaml http://localhost:8008
New user locaslopart &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;root&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;: theuser
Password: thepass
Confirm password:
Make admin &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;no&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;: yes
Sending registration request...
Success
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And that’s it! The web interface is now functional, and we can access Elementweb via &lt;a href=&#34;https://chat.example.com/&#34;&gt;https://chat.example.com&lt;/a&gt; and log in with the credentials created earlier.&lt;/p&gt;
&lt;p&gt;The real fun, though, lies in the bridges—those are still to be configured.&lt;/p&gt;
&lt;h2 id=&#34;heisenbridge&#34;&gt;Heisenbridge&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/hifi/heisenbridge&#34;&gt;Heisenbridge&lt;/a&gt;, will allow us to communicate with IRC networks directly from the &lt;em&gt;Matrix&lt;/em&gt; interface. As always, the first step is to generate its configuration and save it—in this case, in &lt;code&gt;./data/synapse&lt;/code&gt;. We’ll store it here because we also need to share it with &lt;em&gt;Synapse&amp;rsquo;s&lt;/em&gt; volume:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;$ docker run --rm &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;    -v &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;./data/synapse:/data&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;    hif1/heisenbridge &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;    -c /data/heisenbridge.yaml --generate
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will generate a &lt;code&gt;heisenbridge.yaml&lt;/code&gt; file, which we’ll edit to include the URL Synapse will use to connect. Specifically, we’ll need to add the IP address assigned to Heisenbridge in &lt;code&gt;docker-compose.yml&lt;/code&gt;. For consistency, we’ll use &lt;code&gt;10.10.10.6&lt;/code&gt;, so:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;id: heisenbridge&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;url: http://10.10.10.6:9898&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;as_token: ...&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;hs:token: ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next, we need to register &lt;em&gt;heisenbridge&lt;/em&gt; as an application service in &lt;em&gt;synapse&lt;/em&gt;. To do this, edit synapse’s &lt;code&gt;homeserver.yaml&lt;/code&gt;and add the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span style=&#34;color:#f92672&#34;&gt;app_service_config_files&lt;/span&gt;:
  - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/data/heisenbridge.yaml&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we’re ready to add another service to our &lt;code&gt;docker-compose.yml&lt;/code&gt;. Pay attention to the &lt;code&gt;command&lt;/code&gt; field, where we’ll need to specify the Synapse server URL—in this case, &lt;code&gt;http://10.10.10.5:8008&lt;/code&gt;—to ensure proper bidirectional communication:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span style=&#34;color:#f92672&#34;&gt;services&lt;/span&gt;:
    &lt;span style=&#34;color:#ae81ff&#34;&gt;...&lt;/span&gt;
    &lt;span style=&#34;color:#f92672&#34;&gt;heisenbridge&lt;/span&gt;:
        &lt;span style=&#34;color:#f92672&#34;&gt;image&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;hif1/heisenbridge:latest&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;container_name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;heisenbridge&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;hostname&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;heisenbridge&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;ports&lt;/span&gt;:
            - &lt;span style=&#34;color:#ae81ff&#34;&gt;9898&lt;/span&gt;:&lt;span style=&#34;color:#ae81ff&#34;&gt;9898&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;volumes&lt;/span&gt;:
            - &lt;span style=&#34;color:#ae81ff&#34;&gt;./data/synapse/heisenbridge.yaml:/heisenbridge.yaml:rw&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;command&lt;/span&gt;: [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;-c&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/heisenbridge.yaml&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;-vvv&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;http://10.10.10.5:8008&amp;#34;&lt;/span&gt;]
        &lt;span style=&#34;color:#f92672&#34;&gt;depends_on&lt;/span&gt;:
            - &lt;span style=&#34;color:#ae81ff&#34;&gt;synapse&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;restart&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;unless-stopped&lt;/span&gt;
        &lt;span style=&#34;color:#f92672&#34;&gt;networks&lt;/span&gt;:
          &lt;span style=&#34;color:#f92672&#34;&gt;default&lt;/span&gt;:
            &lt;span style=&#34;color:#f92672&#34;&gt;ipv4_address&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;10.10.10.6&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After restarting the services (check the logs to ensure everything is running correctly), you should be able to open a private chat with &lt;code&gt;@heisenbridge:chat.example.com&lt;/code&gt; and start adding the IRC networks you want:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(heisenbridge) ADDNETWORK Libera.Chat
(heisenbridge) ADDSERVER Libera.Chat irc.libera.chat 6697 --tls
(heisenbridge) OPEN Libera.Chat
(Libera.Chat) CONNECT
(Libera.Chat) NICK mynick
(Libera.Chat) JOIN #my_channel
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;other-bridges&#34;&gt;Other bridges&lt;/h2&gt;
&lt;p&gt;Other bridges follow a similar process:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Generate the configuration using a &lt;code&gt;docker run&lt;/code&gt; command or by downloading an example from the bridge’s documentation. Save it in a shared location accessible to both the bridge and synapse.&lt;/li&gt;
&lt;li&gt;Edit the configuration to include the synapse server’s URL or IP address.&lt;/li&gt;
&lt;li&gt;Update synapse’s &lt;code&gt;homeserver.yaml&lt;/code&gt; to register the new bridge as an application service.&lt;/li&gt;
&lt;li&gt;Restart the services.&lt;/li&gt;
&lt;li&gt;Open a private chat with the corresponding bot for the bridge (&lt;code&gt;@whateverbot:chat.example.com&lt;/code&gt;) and follow its instructions. You can also use the &lt;code&gt;help&lt;/code&gt;command for more guidance.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Some bridges have caused issues when they required a dedicated database that wasn’t created automatically. To resolve this, I’ve included an &lt;code&gt;adminer&lt;/code&gt; service in &lt;code&gt;docker-compose.yml&lt;/code&gt;. You can use it to log in and manually create any necessary databases.&lt;/p&gt;
&lt;h2 id=&#34;centralized-messaging-via-console&#34;&gt;Centralized Messaging via Console&lt;/h2&gt;
&lt;p&gt;Centralizing everything is great, but the goal is console-based access, right? Being able to manage all your messaging platforms (&lt;code&gt;IRC&lt;/code&gt;, &lt;code&gt;Telegram&lt;/code&gt;, &lt;code&gt;WhatsApp&lt;/code&gt;, &lt;code&gt;Signal&lt;/code&gt;, &lt;code&gt;Discord&lt;/code&gt;, &lt;code&gt;Slack&lt;/code&gt;&amp;hellip;) from a terminal is possible using &lt;a href=&#34;https://weechat.org&#34;&gt;weechat&lt;/a&gt; and the &lt;a href=&#34;https://github.com/poljar/weechat-matrix&#34;&gt;weechat-matrix&lt;/a&gt; client.&lt;/p&gt;
&lt;p&gt;Simply install it in whatever way works best for you, and once launched, connect to your &lt;em&gt;Matrix&lt;/em&gt; server like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/matrix server add matrix matrix.example.com
/set matrix.server.matrix.username theuser
/set matrix.server.matrix.password thepass
/set matrix.server.matrix.autoconnect on
/matrix connect matrix
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Once connected, the magic happens. All your conversations, both public and private, will automatically populate your &lt;code&gt;weechat&lt;/code&gt; channel list.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&amp;ndash;&lt;/p&gt;
&lt;p&gt;Bridges like these are more than tools—they’re connections that unify scattered communication into a single, seamless flow. With Matrix as the backbone and tools like &lt;code&gt;heisenbridge&lt;/code&gt;, &lt;code&gt;mautrix-*&lt;/code&gt; and &lt;code&gt;weechat&lt;/code&gt;, the terminal becomes not just a workspace but a gateway to countless networks. The simplicity of white text on a black screen hides the complexity beneath, but that’s the beauty of it: everything, everywhere, just works.&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Mastodon vs. Bluesky</title>
      <link>https://oscarmlage.com/posts/mastodon-vs-bluesky/</link>
      <pubDate>Fri, 15 Nov 2024 13:09:46 +0100</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/mastodon-vs-bluesky/</guid>
      <description>
            &lt;p&gt;&lt;strong&gt;The Eternal Dilemma.&lt;/strong&gt; The first door that opened when I decided to leave Twitter was Mastodon, and I have a special fondness for it because of that. It also gave me the chance to experience what it’s like to run &lt;a href=&#34;https://mastodon.bofhers.es/home&#34;&gt;an instance&lt;/a&gt; with actual users. Does it have its problems? Absolutely:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It’s more “complex” to understand.&lt;/li&gt;
&lt;li&gt;Migrations are a headache, upgrades too.&lt;/li&gt;
&lt;li&gt;Development is slow; they say everything depends on one person’s decisions (although that’s not necessarily a &lt;em&gt;bad&lt;/em&gt; thing).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;However, Bluesky is where most people have decided to go. Its &lt;a href=&#34;http://atproto.com&#34;&gt;ATProto&lt;/a&gt; is being designed in a very different way, learning from some of &lt;a href=&#34;https://es.wikipedia.org/wiki/ActivityPub&#34;&gt;ActivityPub&lt;/a&gt;&amp;rsquo;s mistakes, and it’s said to be “better” thought out. Still, there are things that concern me:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Right now, there’s funding because a VC invested, but at some point, they’ll want ROI. Will we become the product?&lt;/li&gt;
&lt;li&gt;I’ve read somewhere that crypto is involved, which raises some red flags.&lt;/li&gt;
&lt;li&gt;I’ve tried replicating the same setup as Mastodon to have my own independent instance, but as of today, it’s practically impossible. Sure, you can set up your PDS, Relay, and Jetstream&amp;hellip; but with AppView, I lost all hope.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Both platforms are still in their infancy, and neither is anywhere near perfect. I feel more at home on Mastodon, but the Bluesky bubble has people I can’t follow anywhere else &lt;code&gt;¯\_(ツ)_/¯&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I’m still undecided, so I’ll try to stay active on both until something happens that makes me change my mind.&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Obsidian Templater, full potential</title>
      <link>https://oscarmlage.com/posts/obsidian-templater-full-potential/</link>
      <pubDate>Wed, 13 Nov 2024 09:37:59 +0100</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/obsidian-templater-full-potential/</guid>
      <description>
            &lt;p&gt;I love automating anything that even hints at being repetitive. I don’t mind investing time in it because I know that sooner or later I’ll be grateful I did. Another one of my “sins” (from an excess) is documentation—I’m always thinking about my future self.&lt;/p&gt;
&lt;p&gt;In almost every project I’m involved with, I feel the need to keep private notes that, in some way, link to the project’s public documentation. For example, if I’m working on an issue, I tend to write down a step-by-step log of what I’ve done, what I’m currently working on, and what’s next. I also make other notes that might help me solve it (snippets, related code, resources, links, etc.). Obviously, it wouldn’t be appropriate to share all of this information in the public issue (description, comments, etc&amp;hellip;).&lt;/p&gt;
&lt;p&gt;The solution to this dilemma has usually involved creating a note manually in the project’s &lt;code&gt;issues/&lt;/code&gt; folder, matching the issue number (and title) of the one in the version control system (GitHub, Forgejo, Gitea, etc.). And let’s be honest—it’s a hassle.&lt;/p&gt;
&lt;p&gt;So, since I’m managing my notes in &lt;a href=&#34;https://obsidian.md&#34;&gt;Obsidian&lt;/a&gt; and already using the &lt;a href=&#34;https://github.com/SilentVoid13/Templater&#34;&gt;Templater&lt;/a&gt; plugin for other tasks, I decided to invest time in automating this process.&lt;/p&gt;
&lt;p&gt;First, we need to create a template that will serve as the base for all these new notes that will be created in the &lt;code&gt;issues/&lt;/code&gt; directory mentioned earlier. This setup will allow &lt;em&gt;Templater&lt;/em&gt; to take control of creating these notes and applying the template logic. Here’s the plan:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Ask me for the title of the issue and, optionally, a brief description.&lt;/li&gt;
&lt;li&gt;Run a &lt;code&gt;curl&lt;/code&gt; command against the version control server (&lt;a href=&#34;https://forgejo.org&#34;&gt;Forgejo&lt;/a&gt; or &lt;a href=&#34;https://about.gitea.com&#34;&gt;Gitea&lt;/a&gt; in this case) to create an issue with the given title.&lt;/li&gt;
&lt;li&gt;Capture the issue number (e.g. &lt;code&gt;34&lt;/code&gt;) from the &lt;code&gt;curl&lt;/code&gt; response.&lt;/li&gt;
&lt;li&gt;Create a new note with the template’s content (including a reference to the URL of the created issue for convenience).&lt;/li&gt;
&lt;li&gt;Rename the note’s title to add the issue number at the beginning (e.g. &lt;code&gt;34 - Issue Title&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These are basically the steps I used to do manually, so now let’s head to the &lt;code&gt;templates/&lt;/code&gt; directory in &lt;em&gt;Obsidian&lt;/em&gt; and create a &lt;code&gt;repo-issue&lt;/code&gt; template with the following content:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;%*&lt;/span&gt;
    &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;title&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;tp&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;system&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;prompt&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Issue title&amp;#34;&lt;/span&gt;);
    &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;content&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;tp&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;system&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;prompt&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Issue content&amp;#34;&lt;/span&gt;);
    &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;token&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;your-forgejo-or-gitea-token&amp;#34;&lt;/span&gt;;
    &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;url&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://git.yourdomain.com/api/v1/repos/owner/repo/issues&amp;#34;&lt;/span&gt;;

    &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;curlCommand&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;`curl -s -X POST -H &amp;#34;Content-Type: application/json&amp;#34; -H &amp;#34;Authorization: token &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;token&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34; -d &amp;#34;{\\&amp;#34;title\\&amp;#34;: \\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;title&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;\\&amp;#34;, \\&amp;#34;body\\&amp;#34;: \\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;content&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;\\&amp;#34;}&amp;#34; &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;url&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;;
    &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;exec&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;tp&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;user&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;curl&lt;/span&gt;({ &lt;span style=&#34;color:#a6e22e&#34;&gt;command&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;curlCommand&lt;/span&gt; });

    &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;response&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;JSON&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;parse&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;exec&lt;/span&gt;);
    &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;issueNumber&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;response&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;number&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;toString&lt;/span&gt;().&lt;span style=&#34;color:#a6e22e&#34;&gt;padStart&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;0&amp;#39;&lt;/span&gt;);
    &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;issueUrl&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;response&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;url&lt;/span&gt;;

    &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;titleWithNumber&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;issueNumber&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; - &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;title&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;;
    &lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;tp&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;file&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;rename&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;titleWithNumber&lt;/span&gt;);
&lt;span style=&#34;color:#f92672&#34;&gt;%&amp;gt;&lt;/span&gt;

&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;#&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;%&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;titleWithNumber&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;%&amp;gt;&lt;/span&gt;

&lt;span style=&#34;color:#f92672&#34;&gt;**&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Issue&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;URL&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:**&lt;/span&gt; [&lt;span style=&#34;color:#a6e22e&#34;&gt;Issue&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;#&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;%&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;issueNumber&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;%&amp;gt;&lt;/span&gt;](&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;%&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;issueUrl&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;%&amp;gt;&lt;/span&gt;)

&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;%&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;content&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;%&amp;gt;&lt;/span&gt;

&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;##&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;📄&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Log&lt;/span&gt;

&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; [[&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;%&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;tp&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;file&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;creation_date&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;YYYY-MM-DD&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;%&amp;gt;&lt;/span&gt;]] &lt;span style=&#34;color:#a6e22e&#34;&gt;Issue&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;created&lt;/span&gt;

&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;##&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;📔️&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Notes&lt;/span&gt;

&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;##&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;🔗&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Resources&lt;/span&gt;

&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;##&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;✅&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Tasks&lt;/span&gt;

&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; [ ] 

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We still need to add the function we’re calling &lt;code&gt;tp.user.curl()&lt;/code&gt; to make the request for creating the issue. To do this, we need to create a file, let’s say &lt;code&gt;curl.js&lt;/code&gt;, in our &lt;code&gt;scripts/&lt;/code&gt; directory, and tell &lt;em&gt;Templater&lt;/em&gt; in the configuration to load that file so that the method is available. The content of our &lt;code&gt;curl.js&lt;/code&gt; would look something like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; { &lt;span style=&#34;color:#a6e22e&#34;&gt;exec&lt;/span&gt; } &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;require&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;child_process&amp;#39;&lt;/span&gt;);

&lt;span style=&#34;color:#a6e22e&#34;&gt;module&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;exports&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;async&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;args&lt;/span&gt;) =&amp;gt; {
    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Promise((&lt;span style=&#34;color:#a6e22e&#34;&gt;resolve&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;reject&lt;/span&gt;) =&amp;gt; {
        &lt;span style=&#34;color:#a6e22e&#34;&gt;exec&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;args&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;command&lt;/span&gt;, (&lt;span style=&#34;color:#a6e22e&#34;&gt;error&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;stdout&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;stderr&lt;/span&gt;) =&amp;gt; {
            &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;error&lt;/span&gt;) {
                &lt;span style=&#34;color:#a6e22e&#34;&gt;console&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;error&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;`Error: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;error&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;message&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;);
                &lt;span style=&#34;color:#a6e22e&#34;&gt;reject&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;error&lt;/span&gt;);
            } &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;stderr&lt;/span&gt;) {
                &lt;span style=&#34;color:#a6e22e&#34;&gt;console&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;error&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;`Stderr: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;stderr&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;);
                &lt;span style=&#34;color:#a6e22e&#34;&gt;reject&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;stderr&lt;/span&gt;);
            } &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {
                &lt;span style=&#34;color:#a6e22e&#34;&gt;console&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;log&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;`Result: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;stdout&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;);
                &lt;span style=&#34;color:#a6e22e&#34;&gt;resolve&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;stdout&lt;/span&gt;);
            }
        });
    });
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we have all the ingredients prepared and ready, we just need to cook them (the &lt;em&gt;Templater&lt;/em&gt; configuration), and there are two simple steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Load the script to make &lt;code&gt;tp.user.curl()&lt;/code&gt; available.
&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Configure the &lt;code&gt;issues/&lt;/code&gt; directory to run the &lt;code&gt;repo-issue&lt;/code&gt; template we created earlier.
&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And with that, everything is automated. Every time we create a new note in the &lt;code&gt;issues/&lt;/code&gt; directory, not only will the note with the corresponding template content be created, but an issue will also be created in the version control server, and the note will be renamed with the issue number and link directly in the note.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;For little details like this, &lt;em&gt;Obsidian&lt;/em&gt; and &lt;em&gt;Templater&lt;/em&gt; has earned a special place in my heart.&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Feeds problems</title>
      <link>https://oscarmlage.com/posts/feeds-problems/</link>
      <pubDate>Mon, 28 Oct 2024 13:11:14 +0100</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/feeds-problems/</guid>
      <description>
            &lt;p&gt;The other day a blog reader - I assume - let me know that my feed content was broken. The content syndication was failing because, in every post that loaded an image with the theme&amp;rsquo;s gallery shortcode, the code appeared instead of the images:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;description&lt;/span&gt;&amp;gt;Can you almost smell it?
    if (!jQuery) { alert(&amp;amp;#34;jquery is not loaded&amp;amp;#34;); } $( document ).ready(() = { const gallery = $(&amp;amp;#34;
&amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;description&lt;/span&gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I imagine &lt;a href=&#34;https://github.com/mfg92/hugo-shortcode-gallery/&#34;&gt;the shortcode I’m using&lt;/a&gt; (which is part of a theme) doesn’t take in account the feeds, so I had to spend some time looking for a possible solution. I also realized that my RSS feeds weren&amp;rsquo;t including the full content of each post, only an &amp;ldquo;excerpt&amp;rdquo; version. Big mistake on my part, as I&amp;rsquo;ve always ranted about that.&lt;/p&gt;
&lt;p&gt;Getting down to it, the biggest challenge I faced was finding something that could be executed &lt;strong&gt;before&lt;/strong&gt; the shortcode, as it would be more complicated to fix once the &lt;code&gt;{{ &amp;lt;gallery ...&amp;gt; }}&lt;/code&gt; had been replaced. That’s where &lt;code&gt;RawContent&lt;/code&gt; came to the rescue. By creating a new &lt;code&gt;home.xml&lt;/code&gt; template for the feeds, I was able to edit the &lt;code&gt;description&lt;/code&gt; tag to, initially, disable the galleries:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;description&lt;/span&gt;&amp;gt;
    {{ .RawContent | replaceRE `&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;lt;&lt;/span&gt;\s*gallery[^&amp;gt;]*&amp;gt;` &amp;#34;`[image not loaded in rss]`&amp;#34; | markdownify | htmlEscape | safeHTML }}
&amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;description&lt;/span&gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Finally, I also separated the feeds by category to keep things more organized. So, as of now, the following feeds are available:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://oscarmlage.com/index.xml&#34;&gt;Posts&lt;/a&gt;: Blog posts.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://oscarmlage.com/microposts/index.xml&#34;&gt;Microposts or Log&lt;/a&gt;: Microposts from the blog (most relevant updates from Mastodon / Bluesky).&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://oscarmlage.com/medialog/watching/index.xml&#34;&gt;Watching&lt;/a&gt;: Series and movies I’m tracking.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://oscarmlage.com/medialog/reading/index.xml&#34;&gt;Reading&lt;/a&gt;: Books I’m reading.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://oscarmlage.com/medialog/listening/index.xml&#34;&gt;Listening&lt;/a&gt;: Albums currently playing on my Spotify.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://oscarmlage.com/medialog/playing/index.xml&#34;&gt;Playing&lt;/a&gt;: Video games I’m currently playing.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thanks &lt;a href=&#34;https://mastodon.bofhers.es/@benalb&#34;&gt;@benalb&lt;/a&gt; for the heads-up.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2024-10-28 Update&lt;/strong&gt;: Found &lt;a href=&#34;https://github.com/mfg92/hugo-shortcode-gallery/issues/36&#34;&gt;an issue&lt;/a&gt; related to this problem.&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Digital Nomad, the concept (2024)</title>
      <link>https://oscarmlage.com/posts/digital-nomad-the-concept-2024/</link>
      <pubDate>Fri, 25 Oct 2024 12:16:01 +0200</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/digital-nomad-the-concept-2024/</guid>
      <description>
            &lt;p&gt;As the wikipedia says, «&lt;em&gt;The term &amp;ldquo;digital nomad&amp;rdquo; started to be used in the early 1990s to describe a new type of high tech traveling lifestyle made possible by the growth of computer networking and popularization of mobile devices like laptops, tablets and PDAs.&lt;/em&gt;».&lt;/p&gt;
&lt;p&gt;Today, in some classes I’m attending, we started talking about the digital nomad concept, asking if we knew about it and if we could name someone considered a digital nomad. It reminded me of the times I’ve mentioned it in the past.&lt;/p&gt;
&lt;p&gt;I’ve been using the term &lt;code&gt;#digitalnomad&lt;/code&gt; quite frequently, especially in my Instagram posts where I’d sneak it in whenever there was some tech gear paired with a picturesque background. In fact, I’ve been teased about it quite a few times. I admit, it was a bit of a bait, but I was young and immature.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;When people hear the term &lt;em&gt;digital nomad&lt;/em&gt;, they often think of someone hopping from one exotic location to another, working remotely from beaches, cafés, or coworking spaces in different countries. While that’s a romanticized view of the lifestyle, my take on digital nomadism is a bit different.&lt;/p&gt;
&lt;p&gt;For me, being a &lt;em&gt;digital nomad&lt;/em&gt; isn’t about traveling constantly or changing locations every few weeks. Instead, it&amp;rsquo;s about autonomy—being able to carry everything I need to work effectively, regardless of where I am. It’s about the freedom of having my &lt;em&gt;digital home&lt;/em&gt; with me at all times, packaged into a compact, highly portable setup. This allows me to work in any situation, whether it’s a crowded airport lounge, a quiet café, or even in the middle of nowhere in the country side.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This is where the concept of &lt;em&gt;Everyday Carry (EDC)&lt;/em&gt; comes into play. I’ve always been fascinated by the idea of minimizing what you carry to only the essentials, ensuring that you’re always ready to work, but without being weighed down. For a digital nomad, an efficient EDC is what enables that sense of flexibility and freedom. So, what’s part of my EDC for true digital nomadism? Here’s my list of must-haves:&lt;/p&gt;
&lt;h3 id=&#34;my-essential_digital-nomad_edc&#34;&gt;My Essential &lt;em&gt;Digital Nomad&lt;/em&gt; EDC:&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;The backpack&lt;/strong&gt;&lt;br&gt;
A lightweight, durable backpack is the foundation of any nomad setup. It needs to be compact enough to carry easily but spacious enough to fit all the necessary tools. It’s your mobile office in a bag.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Laptop or iPad with Internet Access&lt;/strong&gt;&lt;br&gt;
A computer is essential. Whether it’s a laptop or a high-powered tablet like an iPad, it should be capable of handling your work tasks, whether that’s writing code, managing projects, or accessing remote servers. Recently, I’ve been leaning towards the iPad because my laptop is anything but portable, and its battery leaves much to be desired. I’m happy using the iPad in these situations, as long as they’re not long coding sessions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A data plan for reliable Internet (MiFi or mobile tethering)&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Also, I’d like to mention some optional items that, while not strictly necessary, are definitely handy to have nearby just in case, to be fully prepared:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;A powerbank&lt;/strong&gt;
Running out of battery is quite common when you&amp;rsquo;re not &amp;ldquo;plugged in&amp;rdquo; all the time. A high-capacity power bank ensures that your devices can stay charged no matter where you are.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A VPN&lt;/strong&gt;
For many of us working in tech or other remote-access jobs, a secure VPN is non-negotiable. It not only keeps your data safe on public networks but also allows you to connect to the necessary remote servers and hosts to get your work done securely.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;adapting-to-the-new-essentials&#34;&gt;Adapting to the new essentials&lt;/h3&gt;
&lt;p&gt;It’s possible that my &lt;em&gt;essentials&lt;/em&gt; have changed a bit this year. While I no longer work from cafés as often as I used to (&lt;code&gt;:sadface:&lt;/code&gt;), the last four months have forced me to deal with a home renovation situation. The constant back-and-forth has been a &lt;em&gt;great help&lt;/em&gt; in reducing my backpack to the bare minimum. So, it’s a funny coincidence that this topic has come up right now.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;related-posts&#34;&gt;Related posts&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://oscarmlage.com/posts/work-anywhere/&#34;&gt;Work anywhere, 2016&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://oscarmlage.com/posts/digital-nomad-summer-basics-2017/&#34;&gt;Digital Nomad: summer basics, 2017&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Yep, you&amp;rsquo;re right dear reader, I’ve talked about this before on the blog, but it’s interesting to see how daily essentials evolve over time :)&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Bluesky, hosting a PDS</title>
      <link>https://oscarmlage.com/posts/bluesky-hosting-a-pds/</link>
      <pubDate>Wed, 23 Oct 2024 10:47:37 +0200</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/bluesky-hosting-a-pds/</guid>
      <description>
            &lt;p&gt;As I mentioned in the &lt;strong&gt;update&lt;/strong&gt; of &lt;a href=&#34;https://oscarmlage.com/posts/mastodon-bluesky-and-the-blue-bird/&#34;&gt;the last post&lt;/a&gt;, I decided to give Bluesky a chance as long as I could host my own &lt;code&gt;PDS&lt;/code&gt; to maintain the feeling of owning my data.&lt;/p&gt;
&lt;p&gt;Setting aside the fact that I wanted to host the PDS within &lt;code&gt;Proxmox&lt;/code&gt; and route it through an &lt;code&gt;nginx-proxy-manager&lt;/code&gt;, it turned out to be easier than I thought. Initially, it didn’t work because the official stack includes not only the PDS but also &lt;code&gt;Caddy&lt;/code&gt; and &lt;code&gt;Watchover&lt;/code&gt;, causing conflicts between Caddy and &lt;code&gt;npm&lt;/code&gt; (nginx-proxy-manager). I tried several approaches, but I wasn’t able to make it work.&lt;/p&gt;
&lt;h3 id=&#34;install&#34;&gt;Install&lt;/h3&gt;
&lt;p&gt;Although I continued using a Proxmox CT, I assigned it a public IP directly so it wouldn’t route through NPM, and everything went smoothly:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;$ apt install lsb-release
$ wget https://raw.githubusercontent.com/bluesky-social/pds/main/installer.sh
$ chmod +x installer.sh
$ ./installer.sh
* Detected supported distribution Debian &lt;span style=&#34;color:#ae81ff&#34;&gt;12&lt;/span&gt;
---------------------------------------
     Add DNS Record &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; Public IP
---------------------------------------
&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;...&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It’s also important to have a domain associated with that public IP via DNS. Although the instructions tell you to associate a wildcard, this is not necessary. I opted for &lt;code&gt;pds.oscarmlage.com&lt;/code&gt; and simply created the corresponding DNS entry for that subdomain with the public IP:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;pds.oscarmlage.com              A          51.77.72.104
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The installer detects the IP itself, and after installing all the dependencies, it asks for the credentials of an account:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Detected public IP of this server: 51.77.72.104
Create a PDS user account? (y/N): y
Enter an email address (e.g. alice@pds.oscarmlage.com): oscarmlage@pds.oscarmlage.com
Enter a handle (e.g. alice.pds.oscarmlage.com): oscarmlage.pds.oscarmlage.com
Account created successfully!
-----------------------------
Handle   : oscarmlage.pds.oscarmlage.com
DID      : did:plc:XXXX
Password : XXXX
-----------------------------
Save this password, it will not be displayed again.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Everything should now be up and running. We can test it in several ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Check health: &lt;code&gt;https://pds.oscarmlage.com/xrpc/_health&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Check websocket: &lt;code&gt;wsdump.py &amp;quot;wss://pds.oscarmlage.com/xrpc/com.atproto.sync.subscribeRepos?cursor=0&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We can now create more accounts and/or invitation codes from the console using the &lt;code&gt;pdsadmin&lt;/code&gt; command:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# pdsadmin create-invite-code
pds-oscarmlage-com-xxxx-yyyy
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;account-configuration&#34;&gt;Account configuration&lt;/h3&gt;
&lt;p&gt;With the PDS now up and running, head over to &lt;a href=&#34;https://bsky.app/&#34;&gt;Bluesky&amp;rsquo;s website&lt;/a&gt; to log in (if you already have credentials) or create a new account if you have an invite code:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;And what if you want to change the domain to something nicer? For example, I’d like my handle to be &lt;code&gt;@oscarmlage.com&lt;/code&gt;instead of &lt;code&gt;@oscarmlage.pds.oscarmlage.com&lt;/code&gt;. To do this, once you&amp;rsquo;re logged in within bsky.app, go to &lt;em&gt;Settings&lt;/em&gt; → &lt;em&gt;Change handle&lt;/em&gt; → &lt;em&gt;I have my own domain&lt;/em&gt; → Enter the new handle &lt;code&gt;@oscarmlage.com&lt;/code&gt;, and it will show a &lt;em&gt;TXT&lt;/em&gt; record that needs to be added to your &lt;em&gt;DNS&lt;/em&gt; for ownership verification. If the validation is successful&amp;hellip; voilà! You have your new custom handle!&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;bridge-with-mastodon&#34;&gt;Bridge with Mastodon&lt;/h3&gt;
&lt;p&gt;Another concern I have is managing duplicate posts. Although I’ll probably keep an eye on both platforms at first, I really don’t want to maintain two social networks, so the best option —for me— is to set up a bridge with Mastodon to automatically post the same content.&lt;/p&gt;
&lt;p&gt;I’ve activated the bridge from Mastodon to Bluesky. To do this, I followed the bot &lt;code&gt;@bsky.brid.gy@bsky.brid.gy&lt;/code&gt; from Mastodon. Once you start following it —from Mastodon— it automatically creates a Bluesky account under its domain with your Mastodon information, which becomes your bridge account (the bot will share the details in a &lt;em&gt;PM&lt;/em&gt; with you). In my case, it&amp;rsquo;s &lt;code&gt;@oscarmlage.mastodon.bofhers.es.ap.brid.gy&lt;/code&gt;. And that’s it! Every time you post something on Mastodon, it will automatically be published to that Bluesky account.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;In the end, I’ve created two Bluesky accounts: one as my &amp;ldquo;main&amp;rdquo; account and another as the bridge with Mastodon. Feel free to follow me on either of them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://bsky.app/profile/oscarmlage.com&#34;&gt;@oscarmlage.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://bsky.app/profile/oscarmlage.mastodon.bofhers.es.ap.brid.gy&#34;&gt;@oscarmlage.mastodon.bofhers.es.ap.brid.gy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;final-thoughts&#34;&gt;Final thoughts&lt;/h3&gt;
&lt;p&gt;In &lt;a href=&#34;https://oscarmlage.com/posts/mastodon-bluesky-and-the-blue-bird/&#34;&gt;the last post&lt;/a&gt;, I shared a story about a bird and a butterfly, with the elephant reminding us of the importance of staying grounded. But, as I reflect on it now, perhaps the butterflies, too, have something wonderful to offer. So, let&amp;rsquo;s give Bluesky a chance to soar, without forgetting the solid ground that Mastodon has provided. After all, there&amp;rsquo;s room for both beauty and stability in the skies we navigate.&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Mastodon, bluesky and the blue bird</title>
      <link>https://oscarmlage.com/posts/mastodon-bluesky-and-the-blue-bird/</link>
      <pubDate>Tue, 22 Oct 2024 12:34:29 +0200</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/mastodon-bluesky-and-the-blue-bird/</guid>
      <description>
            &lt;p&gt;Lately, I&amp;rsquo;ve been seeing a lot of —annoying— noise about the little blue bird (which is no longer a bird, nor blue), the blue butterfly (Bluesky, I guess), and the Mastodon.&lt;/p&gt;
&lt;p&gt;Sure, every now and then, I open my Twitter account in a tab and take a quick look. I sometimes get that feeling of missing certain profiles that are still active over there, writing and feeding the X. But then, with the ads, the algorithm, and all that visual noise cluttering the timeline, the feeling goes away.&lt;/p&gt;
&lt;p&gt;Yesterday, I was tempted to create a Bluesky account. In fact, I ended up making one because reasons, but I have so many doubts that I don&amp;rsquo;t see myself going back to it. From what I&amp;rsquo;ve read, the project started as an idea by Twitter (ouch1) to create a public conversation protocol (AT Protocol, nothing to do with ActivityPub, ouch2), Open Source, and with the possibility to build both the server and the app, but the instructions are not so clear (ouch3). Tsk&amp;hellip;&lt;/p&gt;
&lt;p&gt;«A bird and a butterfly were arguing about who could fly higher and who had the best view of the sky. The bird insisted its flight was fast and precise, while the butterfly bragged about its beauty and grace as it glided through the clouds. Suddenly, an elephant appeared, walking calmly on the ground, and said: &amp;ldquo;Keep arguing up there, while I already have my feet firmly planted on what really matters.&amp;quot;»&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t know, maybe it&amp;rsquo;s just that I&amp;rsquo;m getting older, or maybe I&amp;rsquo;ve already mastered using and managing a Mastodon instance —which, by the way, still has plenty of room for optimization and resource improvements— or maybe it&amp;rsquo;s that I&amp;rsquo;ve already built my bubble and I just don&amp;rsquo;t feel like starting over. But for now, I&amp;rsquo;d rather keep my feet on the ground.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2024-10-23 Update&lt;/strong&gt; — After a chat with &lt;a href=&#34;https://mastodon.bofhers.es/@oscarmlage/113351007313588920&#34;&gt;@juanlu&lt;/a&gt; and reading here and there about &lt;em&gt;ATProto&lt;/em&gt;, I&amp;rsquo;ve decided to host my own PDS and give it a try. My initial strictly technical impressions are overwhelming—1GB of RAM and 20GB of disk space are more than enough to get it running. However, it&amp;rsquo;s tricky to make it work within a Proxmox environment while routing through nginx-proxy-manager. I’d recommend running it with its own dedicated IP.&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Automating the media (hugo-medialog.go)</title>
      <link>https://oscarmlage.com/posts/automating-medialog-with-obsidian-and-hugo/</link>
      <pubDate>Tue, 15 Oct 2024 17:18:37 +0200</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/automating-medialog-with-obsidian-and-hugo/</guid>
      <description>
            &lt;p&gt;As someone who consumes and tracks a some media items (books, series, movies, videogames, music&amp;hellip;), I’ve always looked for ways to keep an updated record without adding too much friction to my workflow. After several iterations, I’ve created a &lt;em&gt;Go script&lt;/em&gt; that automates this process using tools I already use daily: &lt;em&gt;Obsidian&lt;/em&gt; and &lt;em&gt;Hugo&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I’ll try to explain how this system works and how you can use it to keep track of any type of content with minimal effort.&lt;/p&gt;
&lt;h3 id=&#34;the--workflow&#34;&gt;The  workflow&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Obsidian&lt;/strong&gt; is my go-to note-taking tool, where I have a YAML file for each type of content (e.g., &lt;code&gt;books.yml.md&lt;/code&gt;, &lt;code&gt;series.yml.md&lt;/code&gt;, etc.). In these files, I record titles, progress, ratings, and more.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Hugo&lt;/strong&gt; is my static site generator, where I publish this tracking as part of my blog. Each time I read a book or watch a movie, my goal is to generate a markdown file in Hugo automatically from the YAML file in Obsidian.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The Script&lt;/strong&gt; in Go takes care of this transition, moving data from Obsidian to Hugo automatically. It reads the YAML files from Obsidian and generates corresponding markdown files in Hugo. Also it uses some APIs to get more information about the item (number of episodes/pages, release date, images, author/company&amp;hellip;)&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;the-script-in-action&#34;&gt;The script in action&lt;/h3&gt;
&lt;p&gt;The script is designed to process different types of content (books, series, movies, etc.). Using a &lt;code&gt;--media&lt;/code&gt; flag, you can specify which type of content you want to process. Additionally, I’ve added an optional &lt;code&gt;--update&lt;/code&gt; flag that updates the frontmatter (structured data in the markdown file) without overwriting any personal content you may have added to the markdown, like notes or reviews. Example usage: &lt;code&gt;go run main.go --media books --update&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This will process books and only update the metadata, leaving your personal content in &lt;em&gt;Hugo&lt;/em&gt; untouched.&lt;/p&gt;
&lt;h3 id=&#34;project-structure&#34;&gt;Project structure&lt;/h3&gt;
&lt;p&gt;Here&amp;rsquo;s a simplified view of how the project is organized:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;medialog-project/
├── internal/
│   ├── books/
│   │   └── model.go
│   │   └── controller.go
│   │   └── api_googlebooks.go
│   ├── games/
│   │   └── model.go
│   │   └── controller.go
│   │   └── api_igdb.go
│   ├── movies/
│   │   └── model.go
│   │   └── controller.go
│   │   └── api_trakt.go
│   ├── music/
│   │   └── model.go
│   │   └── controller.go
│   │   └── api_spotify.go
├── templates/
│   └── books.md.tpl
│   └── games.md.tpl
│   └── movies.md.tpl
│   └── music.md.tpl
├── utils/
│   └── config.go
│   └── markdown.go
│   └── utils.go
├── .env
├── main.go
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;how-does-it-work-for-books&#34;&gt;How does it work for books?&lt;/h3&gt;
&lt;p&gt;Let’s look at a concrete example. In the &lt;code&gt;books.yml.md&lt;/code&gt; file in &lt;em&gt;Obsidian&lt;/em&gt;, I have a simple record like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;- &lt;span style=&#34;color:#f92672&#34;&gt;title&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Terraform: Up and Running&amp;#34;&lt;/span&gt;
  &lt;span style=&#34;color:#f92672&#34;&gt;author&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Yevgeniy Brikman&amp;#34;&lt;/span&gt;
  &lt;span style=&#34;color:#f92672&#34;&gt;year&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;2017&lt;/span&gt;
  &lt;span style=&#34;color:#f92672&#34;&gt;progress&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;25&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#f92672&#34;&gt;rate&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;7.2&lt;/span&gt;
  &lt;span style=&#34;color:#f92672&#34;&gt;date&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;2024-10-15&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The script reads this data and searches for the corresponding markdown file in Hugo. If it doesn’t exist, it creates it calling some APIs and using a template; if it does, it can update only the metadata without touching the content, so any personal notes remain intact.&lt;/p&gt;
&lt;p&gt;Here’s a breakdown of how we handle &lt;strong&gt;books&lt;/strong&gt;:&lt;/p&gt;
&lt;h4 id=&#34;model&#34;&gt;Model&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;Book&lt;/code&gt; model represents the data structure for books. This model is responsible for parsing the YAML file from Obsidian and storing the information that will be used to generate the final markdown in Hugo.&lt;/p&gt;
&lt;p&gt;Here’s an example of how the &lt;code&gt;Book&lt;/code&gt; model might look in Go:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Book&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; {
    &lt;span style=&#34;color:#a6e22e&#34;&gt;Title&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;`yaml:&amp;#34;title&amp;#34;`&lt;/span&gt;
    &lt;span style=&#34;color:#a6e22e&#34;&gt;Author&lt;/span&gt;   &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;`yaml:&amp;#34;author&amp;#34;`&lt;/span&gt;
    &lt;span style=&#34;color:#a6e22e&#34;&gt;Year&lt;/span&gt;     &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;     &lt;span style=&#34;color:#e6db74&#34;&gt;`yaml:&amp;#34;year&amp;#34;`&lt;/span&gt;
    &lt;span style=&#34;color:#a6e22e&#34;&gt;Progress&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;`yaml:&amp;#34;progress&amp;#34;`&lt;/span&gt;
    &lt;span style=&#34;color:#a6e22e&#34;&gt;Rate&lt;/span&gt;     &lt;span style=&#34;color:#66d9ef&#34;&gt;float64&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;`yaml:&amp;#34;rate&amp;#34;`&lt;/span&gt;
    &lt;span style=&#34;color:#a6e22e&#34;&gt;Date&lt;/span&gt;     &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;`yaml:&amp;#34;date&amp;#34;`&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This structure matches the fields in the YAML file in Obsidian and allows us to easily read and write the data into markdown format.&lt;/p&gt;
&lt;h4 id=&#34;controller&#34;&gt;Controller&lt;/h4&gt;
&lt;p&gt;The controller is responsible for handling the &lt;em&gt;logic&lt;/em&gt; of reading the YAML file, updating or generating the corresponding markdown, and applying the correct template. The logic flow is as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Load YAML data:&lt;/strong&gt; The controller loads the book data from the YAML file (&lt;code&gt;books.yml.md&lt;/code&gt;) into the &lt;code&gt;Book&lt;/code&gt; model.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Check for existing markdown:&lt;/strong&gt; It checks if a markdown file for the book already exists in Hugo. If it does, it updates only the frontmatter fields (like &lt;code&gt;progress&lt;/code&gt;, &lt;code&gt;rate&lt;/code&gt;, etc.), leaving the content untouched. If it does not exist the controller calls the proper APIs to get the information.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Generate or update markdown:&lt;/strong&gt; If no markdown exists, it generates a new markdown file using a predefined template. Otherwise, it updates the existing frontmatter while preserving user content.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here’s a simplified view of how this process looks in code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ProcessBooks&lt;/span&gt;() {
    &lt;span style=&#34;color:#a6e22e&#34;&gt;books&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;LoadBooksFromYAML&lt;/span&gt;()
    
    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;book&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;range&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;books&lt;/span&gt; {
        &lt;span style=&#34;color:#a6e22e&#34;&gt;mdFile&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Sprintf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;%s/%s.md&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;MARKDOWN_OUTPUT_BOOKS_DIR&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;book&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Slug&lt;/span&gt;)
        
        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;fileExists&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;mdFile&lt;/span&gt;) {
            &lt;span style=&#34;color:#75715e&#34;&gt;// Update only the frontmatter
&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;UpdateBookFrontmatter&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;mdFile&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;book&lt;/span&gt;)
        } &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {
            &lt;span style=&#34;color:#75715e&#34;&gt;// Get proper data from APIs
&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;SearchBookByTitle&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;book&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Title&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;book&lt;/span&gt;)
    		&lt;span style=&#34;color:#a6e22e&#34;&gt;getBookImagesByTitle&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;book&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Title&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;book&lt;/span&gt;)
            &lt;span style=&#34;color:#75715e&#34;&gt;// Generate a new markdown file using the template
&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;GenerateMarkdownFile&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;mdFile&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;book&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;book_template.md&amp;#34;&lt;/span&gt;)
            &lt;span style=&#34;color:#66d9ef&#34;&gt;continue&lt;/span&gt;
        }
    }
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;template&#34;&gt;Template&lt;/h4&gt;
&lt;p&gt;The templates are stored in Hugo’s &lt;code&gt;content&lt;/code&gt; folder, and they define how the final markdown looks. Here’s an example of a simple template for books (&lt;code&gt;book_template.md&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-md&#34; data-lang=&#34;md&#34;&gt;---
title: &amp;#34;{{ .Title }}&amp;#34;
author: &amp;#34;{{ .Author }}&amp;#34;
year: {{ .Year }}
progress: {{ .Progress }}
rate: {{ .Rate }}
date: {{ .Date }}
---

# {{ .Title }}

&lt;span style=&#34;color:#75715e&#34;&gt;## Overview
&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;

&lt;span style=&#34;color:#75715e&#34;&gt;## My thoughts
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This template uses Go’s text/template syntax to dynamically insert book data into the frontmatter and content sections of the markdown. For example, the generated or updated markdown file in Hugo might look like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-md&#34; data-lang=&#34;md&#34;&gt;---
title: &amp;#34;Terraform: Up and Running&amp;#34;
author: &amp;#34;Yevgeniy Brikman&amp;#34;
year: 2017
progress: 25%
rate: 7.2
date: 2024-10-15
---

# Terraform: Up and Running

&lt;span style=&#34;color:#75715e&#34;&gt;## Overview
&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;no&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;value&lt;/span&gt;&amp;gt;

&lt;span style=&#34;color:#75715e&#34;&gt;## My thoughts
&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;This is where you can add your personal thoughts about the book.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;in-the-end&#34;&gt;In the end&lt;/h3&gt;
&lt;p&gt;This system lets me keep my medialog updated with &lt;em&gt;minimal friction&lt;/em&gt;, as I only need to update the YAML files in &lt;em&gt;Obsidian&lt;/em&gt;, which is already part of my daily note-taking routine.&lt;/p&gt;
&lt;p&gt;From there, the entire process of generating content in my blog is automated. Additionally, by using the &lt;code&gt;--update&lt;/code&gt; flag, I can ensure that any personal content added in Hugo remains untouched.&lt;/p&gt;
&lt;p&gt;Keeping track of what we consume doesn’t have to be a tedious or manual process. With the right tools and automation, you can make it as seamless as possible. If you&amp;rsquo;re interested in implementing something similar, you can check the &lt;a href=&#34;https://git.oscarmlage.com/oscarmlage/hugo-medialog&#34;&gt;script repository&lt;/a&gt;, where you can see the full code and adapt/edit it to fit your needs.&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Small tweaks in the blog</title>
      <link>https://oscarmlage.com/posts/small-tweaks-in-the-blog/</link>
      <pubDate>Fri, 20 Sep 2024 20:45:09 +0200</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/small-tweaks-in-the-blog/</guid>
      <description>
            &lt;p&gt;I&amp;rsquo;ve finally managed to make a few small changes to this site that I&amp;rsquo;ve been wanting for a while. There were certain small details that didn’t quite convince me, and with each passing day, I felt a growing need to try and adjust them. These are minor adjustments, but they make the site feel more enjoyable to me.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I’ve removed my image/avatar from the homepage since I was never fully convinced by it.&lt;/li&gt;
&lt;li&gt;The main menu has been switched from text to icons.&lt;/li&gt;
&lt;li&gt;Font sizes have been adjusted to improve readability.&lt;/li&gt;
&lt;li&gt;Margins and spacings have been refined to better fit the new changes.&lt;/li&gt;
&lt;li&gt;The footer has been minimized, now using icons instead of text.&lt;/li&gt;
&lt;li&gt;All content has been aligned to the center across all possible screen resolutions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These aren&amp;rsquo;t big updates, but I really like the theme’s foundation, so I just made a few subtle tweaks to make it feel a little more personal.&lt;/p&gt;
&lt;p&gt;Looking ahead, I’m excited to continue experimenting with design and functionality, always aiming for a cleaner interface.&lt;/p&gt;
&lt;h3 id=&#34;gallery&#34;&gt;Gallery&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;related-posts&#34;&gt;Related posts&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://oscarmlage.com/posts/hola-hugo/&#34;&gt;Hola Hugo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

      </description>
    </item>
    <item>
      <title>The Medialog</title>
      <link>https://oscarmlage.com/posts/the-medialog/</link>
      <pubDate>Tue, 27 Aug 2024 21:00:52 +0200</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/the-medialog/</guid>
      <description>
            &lt;p&gt;Lately, I&amp;rsquo;ve been diving - a bit more - into Hugo &lt;em&gt;templates&lt;/em&gt; and &lt;em&gt;archetypes&lt;/em&gt;, and I decided to create a &lt;strong&gt;&lt;a href=&#34;https://oscarmlage.com/medialog/&#34;&gt;medialog&lt;/a&gt;&lt;/strong&gt; to track all the media I&amp;rsquo;m currently consuming: movies, series, books, games, music&amp;hellip; This space helps me keep everything organized, and I&amp;rsquo;m hoping it won&amp;rsquo;t be forgotten—like some other parts of this site have been!&lt;/p&gt;
&lt;h3 id=&#34;creating-the-medialog-layout&#34;&gt;Creating the Medialog Layout&lt;/h3&gt;
&lt;p&gt;I created a new layout called &lt;code&gt;medialog.html&lt;/code&gt; to define how I want my media log to be displayed. This layout includes sections for each type of media I&amp;rsquo;m tracking. To display the content, I used Hugo&amp;rsquo;s &lt;code&gt;range&lt;/code&gt; function, iterating over my taxonomies to showcase what I’ve been watching, reading, and more.&lt;/p&gt;
&lt;p&gt;Here’s a snippet of how the layout looks:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;main&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;main wrapper&amp;#34;&lt;/span&gt;&amp;gt;
    &amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;h1&lt;/span&gt;&amp;gt;Medialog&amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;h1&lt;/span&gt;&amp;gt;

    {{ if .Site.Taxonomies.tags.watching }}
    &amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;h2&lt;/span&gt;&amp;gt;Watching&amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;h2&lt;/span&gt;&amp;gt;
    &amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;media-grid horizontal&amp;#34;&lt;/span&gt;&amp;gt;
        {{ range (.Site.Taxonomies.tags.watching).Pages }}
            {{ partial &amp;#34;medialog/watching.html&amp;#34; . }}
        {{ end }}
    &amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;div&lt;/span&gt;&amp;gt;
    {{ end }}

    {{ if .Site.Taxonomies.tags.reading }}
    &amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;h2&lt;/span&gt;&amp;gt;Reading&amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;h2&lt;/span&gt;&amp;gt;
    &amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;media-grid vertical&amp;#34;&lt;/span&gt;&amp;gt;
        {{ range (.Site.Taxonomies.tags.reading).Pages }}
            {{ partial &amp;#34;medialog/reading.html&amp;#34; . }}
        {{ end }}
    &amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;div&lt;/span&gt;&amp;gt;
    {{ end }}

&amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;main&lt;/span&gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;adding-content-with-partials&#34;&gt;Adding Content with Partials&lt;/h3&gt;
&lt;p&gt;I used Hugo&amp;rsquo;s &lt;code&gt;partials&lt;/code&gt; to keep things modular and reusable. Here’s an example of a partial that renders a media item with its rating:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;href&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;{{ .Params.Link }}&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;title&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;{{ .Title }}&amp;#34;&lt;/span&gt;&amp;gt;
  &amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;item-wrapper&amp;#34;&lt;/span&gt;&amp;gt;
    &amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;meta-text&amp;#34;&lt;/span&gt;&amp;gt;
        &amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;gridheader&amp;#34;&lt;/span&gt;&amp;gt;{{ .Title }}&amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;div&lt;/span&gt;&amp;gt;
        &amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;subheader&amp;#34;&lt;/span&gt;&amp;gt;
          {{ $rate := .Params.Rate }}
          {{ range $i, $e := (slice 0 1 2 3 4) }}{{ if lt $i $rate }}⭐{{ end }}{{ end }}
        &amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;div&lt;/span&gt;&amp;gt;
      &amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;div&lt;/span&gt;&amp;gt;
      &amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;img&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;src&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;listening/_assets/{{ .Params.Image }}&amp;#34;&lt;/span&gt;
        &lt;span style=&#34;color:#a6e22e&#34;&gt;alt&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;{{ .Title }}&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;loading&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;lazy&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;decoding&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;async&amp;#34;&lt;/span&gt; /&amp;gt;
    &amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;div&lt;/span&gt;&amp;gt;
&amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;a&lt;/span&gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;content-structure&#34;&gt;Content structure&lt;/h3&gt;
&lt;p&gt;Each content entry in the &lt;code&gt;medialog&lt;/code&gt; follows a simple structure. For example, a movie entry might look like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;---&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;title: &amp;#34;Movie title&amp;#34;&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;link: https://www.imdb.com/title/ttXXX/&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;subtitle: 2018&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;year: 2018&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;rate: 3&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;image: movie-image.png&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;date: 2024-07-11T10:44:54Z&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;draft: false&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;tags: watching&lt;/span&gt;
&lt;span style=&#34;color:#a6e22e&#34;&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;handling-layout-issues&#34;&gt;Handling Layout Issues&lt;/h3&gt;
&lt;p&gt;I ran into an issue where Hugo was rendering my &lt;code&gt;medialog&lt;/code&gt; content using &lt;code&gt;default/list.html&lt;/code&gt; instead of my custom layout. The solution was to properly configure taxonomies in &lt;code&gt;config.yaml&lt;/code&gt; and ensure the layout was correctly referenced in the frontmatter. I also had to move &lt;code&gt;layouts/medialog.html&lt;/code&gt; to &lt;code&gt;layouts/medialog/list.html&lt;/code&gt; to get everything working properly.&lt;/p&gt;
&lt;h3 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Building this &lt;code&gt;medialog&lt;/code&gt; has been a fun and rewarding experience. It’s a simple yet effective way to track my media consumption, and I’m excited to keep it updated (hopefully this time, it won’t fall by the wayside!). If you&amp;rsquo;re interested in doing something similar, I encourage you to dive into Hugo and explore its powerful template features.&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Holidays, a digital challenge</title>
      <link>https://oscarmlage.com/posts/holidays-a-digital-challenge/</link>
      <pubDate>Fri, 16 Aug 2024 23:13:38 +0200</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/holidays-a-digital-challenge/</guid>
      <description>
            &lt;p&gt;Everyone I know enjoys taking vacations, having free time, spending time with family, and doing different things that the daily grind might not allow for, etc.&lt;/p&gt;
&lt;p&gt;As much as I love disconnecting during this leisure time, due to the nature of my work, I always need to have a data plan and some gadget on hand that allows me to remotely connect to servers, if only to be able to restart a service that’s acting up.&lt;/p&gt;
&lt;p&gt;For several seasons now, the &lt;code&gt;iPad&lt;/code&gt; has become my travel companion for these tasks, and this year has been no different.&lt;/p&gt;
&lt;p&gt;However, I had another, more fun challenge in mind. Between swimming and lounging, I take the opportunity to read, and my mind shifts into creative mode. More than once, I’ve thought about writing a few lines for this blog. But since it’s a static content manager that I can’t install or build on the  &lt;code&gt;iPad&lt;/code&gt;, things get a bit more complicated.&lt;/p&gt;
&lt;p&gt;So, the reason for writing these lines is to test whether I could accomplish this fun challenge—&lt;em&gt;even with a photo!&lt;/em&gt; Challenge unlocked.&lt;/p&gt;
&lt;p&gt;Enjoy your leisure time.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;gallery/holidays-a-digital-challenge.jpg&#34; alt=&#34;holidays-a-digital-challenge&#34;&gt;&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>A movie for a change</title>
      <link>https://oscarmlage.com/posts/a-movie-for-a-change/</link>
      <pubDate>Mon, 29 Jul 2024 13:35:48 +0200</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/a-movie-for-a-change/</guid>
      <description>
            &lt;p&gt;Yesterday, we were so bored scrolling to find a series to start, in a total lazy mood, that we ended up choosing a movie. It&amp;rsquo;s been so long since the last time I can&amp;rsquo;t even remember.&lt;/p&gt;
&lt;p&gt;We usually watch series because the episodes are shorter, though it&amp;rsquo;s a bit of a trap because we end up watching more than one, but mentally it feels like less of a commitment. We&amp;rsquo;ve split the movie into 2 parts, and today we&amp;rsquo;re finishing it.&lt;/p&gt;
&lt;p&gt;Maybe it&amp;rsquo;ll become a regular thing. If it does, perhaps it&amp;rsquo;s a good idea to keep track of that kind of thing.&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Struggle and Motivation</title>
      <link>https://oscarmlage.com/posts/struggle-and-motivation/</link>
      <pubDate>Thu, 11 Jul 2024 12:05:23 +0200</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/struggle-and-motivation/</guid>
      <description>
            &lt;p&gt;I was browsing the Mastodon timeline and came across &lt;a href=&#34;https://rachsmith.com/comfortable-with-the-struggle/&#34;&gt;this interesting article&lt;/a&gt; by &lt;a href=&#34;https://rachsmith.com/&#34;&gt;Rach Smith&lt;/a&gt; discussing a key factor in becoming a developer. I mostly agree with her perspective. It&amp;rsquo;s hard to replicate the career of any individual, but, aside from external factors, the struggle with various problems you encounter is a crucial aspect. You need to enjoy it.&lt;/p&gt;
&lt;p&gt;In addition to that, I believe another key factor is &lt;strong&gt;motivation&lt;/strong&gt;. It&amp;rsquo;s great if you enjoy the job and have the right motivation. However, even if you enjoy the work and the challenges, without motivation, the journey can become hard and tough.&lt;/p&gt;
&lt;p&gt;I really enjoy tackling daily problems and finding suitable solutions. I love opening my computer every day to improve something. I&amp;rsquo;m constantly looking for new ideas, even when I&amp;rsquo;m not in front of the screen (while showering, walking, etc.).&lt;/p&gt;
&lt;p&gt;But currently, I&amp;rsquo;m at a point where I open my computer and it&amp;rsquo;s like a blank screen; I&amp;rsquo;m not enjoying it anymore. The projects I&amp;rsquo;m working on are either stalled or halted, and my motivation is nearly &lt;em&gt;/dev/null&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Motivation&lt;/strong&gt; can significantly impact your performance at work. It drives you to tackle challenges, pursue new solutions, and continuously improve. When you&amp;rsquo;re motivated, you&amp;rsquo;re more likely to be proactive, creative, and productive, which can lead to greater job satisfaction and career growth.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Motivation&lt;/strong&gt; is different for everyone; it&amp;rsquo;s essential to find your own. Whether it&amp;rsquo;s the type of work, your colleagues, the daily routine, the financial rewards, or the tasks you enjoy the most, identify what drives you. But whatever it is, make sure you find it.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s why I believe one of the key factors in this career (and probably many others) is &lt;strong&gt;motivation&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stay hydrated, stay motivated.&lt;/strong&gt;&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Madrid, spring 2024</title>
      <link>https://oscarmlage.com/posts/madrid-spring-2024/</link>
      <pubDate>Wed, 08 May 2024 20:50:23 +0200</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/madrid-spring-2024/</guid>
      <description>
            &lt;p&gt;If memory serves me right, this is the first family trip we&amp;rsquo;ve taken since last summer. It&amp;rsquo;s been a somewhat unusual winter, but in the end, we managed to break away from routine and enjoy a weekend in the capital with the excuse of seeing a musical we&amp;rsquo;ve been wanting to watch for a while.&lt;/p&gt;
&lt;p&gt;Every time I visit a big city, I feel like a little kid again, marveling at the buildings, and this time was no different.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Good Bye Vila Penguin</title>
      <link>https://oscarmlage.com/posts/good-bye-vila-penguin/</link>
      <pubDate>Thu, 25 Apr 2024 19:39:16 +0200</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/good-bye-vila-penguin/</guid>
      <description>
            &lt;p&gt;Last photo of the family in front of the mirror in one of the rooms, saying definitely goodbye to 15 years of adventures. &lt;code&gt;Vila Penguin&lt;/code&gt; was the nickname of our apartment (in tribute to &lt;em&gt;Dr. Slump&lt;/em&gt;). It&amp;rsquo;s gone, filled with memories and a whole life packed in boxes.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s go for the next level, thinking of a new nickname ;).&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;gallery/2024-04-25-good-bye-vila-penguin.png&#34; alt=&#34;2024-04-25-good-bye-vila-penguin&#34;&gt;&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Microposting... obs2hugo.go</title>
      <link>https://oscarmlage.com/posts/microposting-obs2hugo-go/</link>
      <pubDate>Wed, 10 Apr 2024 19:39:16 +0200</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/microposting-obs2hugo-go/</guid>
      <description>
            &lt;p&gt;The other day, I raised &lt;a href=&#34;https://mastodon.bofhers.es/@oscarmlage/112235259493996614&#34;&gt;through Mastodon&lt;/a&gt; what I call «the problem of microposting»  and tried to find a solution that could cover my use case minimally.&lt;/p&gt;
&lt;p&gt;Microposting is a brief and agile way of publishing &amp;ldquo;stuff&amp;rdquo; easily and with minimal friction. Platforms like &lt;em&gt;Tumblr&lt;/em&gt;, &lt;em&gt;Twitter&lt;/em&gt;, or recently &lt;em&gt;Mastodon&lt;/em&gt; have made microposting a reality that moves more dynamic and updated content than other types of publications.&lt;/p&gt;
&lt;p&gt;When it comes to reducing friction in content generation, we have to say that the clients of these platforms are very usable and make it very easy to create a text accompanied by several photos to document any kind of situation. Even if it&amp;rsquo;s temporary content, it&amp;rsquo;s very easy and quick to generate.&lt;/p&gt;
&lt;p&gt;Since I left &lt;em&gt;Twitter&lt;/em&gt; (deleting all the history of the account) and joined &lt;em&gt;Mastodon&lt;/em&gt;, I consider the content on these platforms as &lt;strong&gt;ephemeral&lt;/strong&gt;. Almost everything published will lack meaning in the future without proper context, or perhaps only as a historical record to remember or relive certain feelings. (Please note that I haven&amp;rsquo;t programmed expiration on publications yet, but I&amp;rsquo;m sure I&amp;rsquo;ll end up doing it).&lt;/p&gt;
&lt;p&gt;But there are some publications that, either for sentimental or for other reasons that are not relevant, I would like to keep in &lt;code&gt;[someplace]&lt;/code&gt;. And that&amp;rsquo;s where the questions begin. How can I save that history? Could I &amp;ldquo;export&amp;rdquo; it to another site to keep those publications without depending on what happens to the instance or to the third-party company owning the social network? Hasn&amp;rsquo;t anyone thought of this before?&lt;/p&gt;
&lt;p&gt;Considering that, in my case, we&amp;rsquo;re talking about exporting certain publications from &lt;em&gt;Mastodon&lt;/em&gt; to, for example, my blog; my first approach was to create a tag (&lt;code&gt;#micropost&lt;/code&gt;) that could have an associated feed (thanks to &lt;em&gt;Mastodon&lt;/em&gt;) and make use of a small script to read that feed to export one by one all the entries and convert them into easily importable markdown content on this blog (&lt;a href=&#34;https://gohugo.io&#34;&gt;Hugo&lt;/a&gt;). And thus, the &lt;code&gt;Social&lt;/code&gt; section was born:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://oscarmlage.com/microposts/&#34;&gt;https://oscarmlage.com/microposts/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Over time, I&amp;rsquo;ve seen that the flow isn&amp;rsquo;t right, although the creation is very simple and within reach of any device (I literally carry the &lt;em&gt;Mastodon&lt;/em&gt; client in my pocket), I have to manually run the feed reading script on a computer and also build and deploy the website for the new content to appear. &lt;strong&gt;All the friction that is reduced in content creation reappears in its publication&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;gallery/microposting-the-hard-way.png&#34; alt=&#34;microposting-the-hard-way&#34;&gt;&lt;/p&gt;
&lt;p&gt;I think it can be improved by changing the tools. And that&amp;rsquo;s what I did. I&amp;rsquo;ve created another small (well&amp;hellip; not so much) script that I can leave running on any computer that has access to &lt;code&gt;the input&lt;/code&gt; and &lt;code&gt;the output&lt;/code&gt; (we&amp;rsquo;ll talk about it now). The script takes care of reading changes on disk in certain directories and acting accordingly. The input is now &lt;a href=&#34;https://obsidian.md&#34;&gt;Obsidian&lt;/a&gt;, which also has a fantastic client, I also carry it in my pocket, and it also allows me to create content without any friction and even with more composition options than &lt;em&gt;Mastodon&lt;/em&gt;. The output is &lt;a href=&#34;https://gohugo.io&#34;&gt;Hugo&lt;/a&gt; and the flow is as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I open the &lt;em&gt;Obsidian&lt;/em&gt; client and create a new note in the folder assigned to &lt;code&gt;microposts&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;I write the content, attaching photos, videos, or any other type of content that the Obsidian client allows me. As I&amp;rsquo;m creating, the content is already synchronizing with the other &lt;em&gt;Obsidian&lt;/em&gt; instance I have on my PC.&lt;/li&gt;
&lt;li&gt;The script that is watching the disk alerts changes, translates them into markdown, and moves them to the microposts directory of &lt;em&gt;Hugo&lt;/em&gt;. Also, it &lt;code&gt;builds &amp;amp; deploys&lt;/code&gt; in background.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Automatically and without the need to do anything else than generate the content, we have already published it &lt;code&gt;\o/&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;gallery/microposting-the-easy-way.png&#34; alt=&#34;microposting-the-easy-way&#34;&gt;&lt;/p&gt;
&lt;p&gt;I think I&amp;rsquo;ve managed to reduce friction both in creation and publication to a minimum, and always using my favorite content manager and my favorite documentation tool. Goal achieved. By the way, I&amp;rsquo;ve called the script &lt;code&gt;obs2hugo&lt;/code&gt;, and you can access the source code here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://git.oscarmlage.com/oscarmlage/obs2hugo&#34;&gt;oscarmlage/obs2hugo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Please note that the script is constantly being updated, as new ideas come to me as I use it. For example, I&amp;rsquo;ve just added support for the watcher to observe several different directories and act accordingly, so I can not only manage the &lt;code&gt;microposts&lt;/code&gt; but also manage the &lt;code&gt;posts&lt;/code&gt; like this one you&amp;rsquo;re reading, written entirely following this new flow.&lt;/p&gt;
&lt;p&gt;&lt;video width=&#34;100%&#34; controls&gt;&lt;source src=&#34;gallery/obs2hugo-sample01.mov&#34; /&gt;&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;&lt;video width=&#34;100%&#34; controls&gt;&lt;source src=&#34;gallery/obs2hugo-sample02.mov&#34; /&gt;&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;Besides having had a couple of super entertaining days with this new toy, I must admit that I&amp;rsquo;m enjoying it like a kid. I love it.&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Turning Ipad Into a Remote Development Tool</title>
      <link>https://oscarmlage.com/posts/turning-ipad-into-a-remote-development-tool/</link>
      <pubDate>Tue, 20 Feb 2024 21:14:08 +0000</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/turning-ipad-into-a-remote-development-tool/</guid>
      <description>
            &lt;p&gt;&lt;img src=&#34;gallery/turning-ipad-into-remote-dev-tool-04.jpeg&#34; alt=&#34;iPad browser&#34;&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve talked before about how much I love the form factor, versatility, portability, and battery life of the iPad. It&amp;rsquo;s by far the gadget I enjoy the most.&lt;/p&gt;
&lt;p&gt;Even for development, even when working remotely, it&amp;rsquo;s ideal as long as you don&amp;rsquo;t rely too much on developer tools. For backend development, it fits like a glove.&lt;/p&gt;
&lt;p&gt;Obviously, you need access to another machine with the development environments, but as long as you don&amp;rsquo;t stray too far from the terminal (&lt;code&gt;mosh&lt;/code&gt;, &lt;code&gt;tmux&lt;/code&gt;, &lt;code&gt;vim&lt;/code&gt;&amp;hellip;), you won&amp;rsquo;t need anything more than a stable internet connection.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve &lt;a href=&#34;https://oscarmlage.com/posts/ipad-as-dev-machine/&#34;&gt;previously mentioned&lt;/a&gt; how you can use a &lt;code&gt;socks server&lt;/code&gt; via &lt;code&gt;SSH&lt;/code&gt; in &lt;a href=&#34;https://blink.sh&#34;&gt;Blink&lt;/a&gt; to resolve requests on the destination host, so if we SSH into the development machine where we have &lt;a href=&#34;http://localproject.lc/&#34;&gt;http://localproject.lc&lt;/a&gt;, the iPad can access that address.&lt;/p&gt;
&lt;p&gt;However, although configurable in Blink, it&amp;rsquo;s a somewhat tedious option as it requires a &lt;code&gt;proxy.pac&lt;/code&gt; and custom configuration.&lt;/p&gt;
&lt;p&gt;I wanted to mention another solution that involves using &lt;a href=&#34;https://tailscale.com&#34;&gt;Tailscale&lt;/a&gt; and its &lt;code&gt;SplitDNS&lt;/code&gt; feature. As long as you can run the &lt;em&gt;Tailscale&lt;/em&gt; client on both machines, the one with the development environments and the &lt;em&gt;iPad&lt;/em&gt;, you can easily access all those &amp;ldquo;local&amp;rdquo; domains. Let&amp;rsquo;s recap what we need:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Development host with Tailscale client, SSHd, and a DNS server (such as dnsmasq).&lt;/li&gt;
&lt;li&gt;iPad with Tailscale client.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;ipad&#34;&gt;iPad&lt;/h3&gt;
&lt;p&gt;All we have to do on the iPad is install the Tailscale client, log in with our account, and wait to have the rest configured.&lt;/p&gt;
&lt;h3 id=&#34;development-host&#34;&gt;Development Host&lt;/h3&gt;
&lt;p&gt;On this host, in addition to SSH, we have the Tailscale client installed, which will give us a public IP via the Tailscale network. Additionally, we need to install and configure a DNS server (I emphasize &lt;code&gt;dnsmasq&lt;/code&gt; for its ease of installation and configuration) to resolve the &lt;code&gt;.lc&lt;/code&gt; domains to its Tailscale node public IP. For example, if the public IP of this node in Tailscale is &lt;code&gt;111.112.113.114&lt;/code&gt;, we configure dnsmasq as follows:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;address=/.localproject.lc/111.112.113.114
address=/.localproject2.lc/111.112.113.114
[...]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In addition to having the development projects running, that would be all we have to do on the development host.&lt;/p&gt;
&lt;h3 id=&#34;tailscale&#34;&gt;Tailscale&lt;/h3&gt;
&lt;p&gt;The last step would be to configure Tailscale. Within its &lt;code&gt;Admin console&lt;/code&gt;, we should already see the nodes where we have the client installed; in our case described above, the development host and the iPad would appear.&lt;/p&gt;
&lt;p&gt;Now we need to focus on the &lt;code&gt;DNS&lt;/code&gt; option and within it on the &lt;code&gt;Nameservers&lt;/code&gt;. There we can add new nameservers (&lt;code&gt;Add nameserver&lt;/code&gt;) of type &lt;code&gt;Custom&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;gallery/turning-ipad-into-remote-dev-tool-01.png&#34; alt=&#34;Tailscale 01&#34;&gt;
&lt;img src=&#34;gallery/turning-ipad-into-remote-dev-tool-02.png&#34; alt=&#34;Tailscale 02&#34;&gt;&lt;/p&gt;
&lt;p&gt;And we would be all set to return to the iPad, log out and log back into the Tailscale client, and be able to access through the browser:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;gallery/turning-ipad-into-remote-dev-tool-03.png&#34; alt=&#34;iPad browser&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;With the Tailscale solution and SplitDNS feature, turning your iPad into a remote development environment becomes remarkably straightforward. By leveraging Tailscale&amp;rsquo;s seamless networking capabilities and SplitDNS functionality, you can access your development environments securely and efficiently, without the need for complex configurations or resorting to workarounds like jailbreaking.&lt;/p&gt;
&lt;p&gt;Whether you&amp;rsquo;re a developer on the go or simply prefer the convenience of using your iPad for development tasks, Tailscale provides a reliable solution that empowers you to code from anywhere, effortlessly bridging the gap between your iPad and your development environment.&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Embracing the ordinary</title>
      <link>https://oscarmlage.com/posts/embracing-the-ordinary/</link>
      <pubDate>Wed, 07 Feb 2024 21:40:18 +0000</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/embracing-the-ordinary/</guid>
      <description>
            &lt;p&gt;As I sit down to write this post in 2024, I can&amp;rsquo;t help but acknowledge the fact that my blog has remained silent for far too long. It&amp;rsquo;s not for lack of things happening, but maybe because the everyday hustle and bustle have swallowed up my creative energy (or whatever is being called nowadays).&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s simple to miss the little joys in our daily routines. Even without big events, I&amp;rsquo;m still determined to find that each day presents opportunities to appreciate the simple pleasures and to recognize that our mere existence is a gift worthy of celebration.&lt;/p&gt;
&lt;p&gt;In the end, stepping back from blogging reminds us of life&amp;rsquo;s ups and downs. It&amp;rsquo;s often the ordinary moments that stick with us the longest, and it&amp;rsquo;s in these times when we discover the beauty of existence. So, let&amp;rsquo;s embrace the everyday and treasure the little triumphs that give life its meaning.&lt;/p&gt;
&lt;p&gt;At the end, this game is all about cycles of streaks&amp;hellip; they say!.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;gallery/embracing-the-ordinary.jpeg&#34; alt=&#34;Long distance run&#34;&gt;&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Vim: embedded git diff</title>
      <link>https://oscarmlage.com/posts/vim-embedded-git-diff/</link>
      <pubDate>Wed, 11 Oct 2023 10:30:17 +0000</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/vim-embedded-git-diff/</guid>
      <description>
            &lt;p&gt;Sometimes, all you want is a simple and rapid method to review all the changes made across different branches, in a format you can easily edit. This is particularly useful for quickly assessing which tests need to be added when working on a new branch.&lt;/p&gt;
&lt;p&gt;My initial thoughts led me to consider various plugins, like &lt;a href=&#34;https://github.com/tpope/vim-fugitive&#34;&gt;fugitive&lt;/a&gt; or &lt;a href=&#34;https://github.com/kdheepak/lazygit.nvim&#34;&gt;lazygit&lt;/a&gt;, as well as manual approaches such as copying &lt;code&gt;git diff&lt;/code&gt; output into the buffer. But I had a hunch that there had to be a quicker way, and I was right:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-vim&#34; data-lang=&#34;vim&#34;&gt;:&lt;span style=&#34;color:#a6e22e&#34;&gt;r&lt;/span&gt;!&lt;span style=&#34;color:#a6e22e&#34;&gt;git&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;diff&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;master&lt;/span&gt;..&lt;span style=&#34;color:#a6e22e&#34;&gt;my&lt;/span&gt;-&lt;span style=&#34;color:#a6e22e&#34;&gt;branch&lt;/span&gt; --&lt;span style=&#34;color:#a6e22e&#34;&gt;no&lt;/span&gt;-&lt;span style=&#34;color:#a6e22e&#34;&gt;color&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;:&lt;span style=&#34;color:#a6e22e&#34;&gt;set&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;syntax&lt;/span&gt;=&lt;span style=&#34;color:#a6e22e&#34;&gt;git&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The solution lies in vim&amp;rsquo;s powerful &lt;code&gt;:r&lt;/code&gt; command. This feature allows you to import the output of an external command directly into your vim buffer. Breaking it down, &lt;code&gt;git diff&lt;/code&gt; generates a comparison between the &lt;code&gt;master&lt;/code&gt; and &lt;code&gt;my-branch&lt;/code&gt; with the &lt;code&gt;--no-color&lt;/code&gt; flag to remove any color formatting. Then vim imports this output into the buffer.&lt;/p&gt;
&lt;p&gt;To enhance the readability, we apply git syntax highlighting to the inserted text using &lt;code&gt;:set syntax=git&lt;/code&gt;. This combination of vim commands offers a fast and efficient solution for evaluating changes, navigating code, and identifying the tests that need to be incorporated.&lt;/p&gt;
&lt;p&gt;I love &lt;code&gt;vim&lt;/code&gt;.&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Boost computer CPU using a fridge</title>
      <link>https://oscarmlage.com/posts/boost-computer-performance-using-fridge/</link>
      <pubDate>Wed, 23 Aug 2023 19:26:01 +0000</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/boost-computer-performance-using-fridge/</guid>
      <description>
            &lt;p&gt;I believe some experiences are too unique not to be shared, and today&amp;rsquo;s one with my computer due to the scorching heat in my city is definitely one of them. Brace yourselves for a quirky yet somewhat educational story: Using your freezer to give your laptop a &lt;code&gt;60%&lt;/code&gt; power boost. Frozen Apple makes your laptop roar&amp;hellip; catchy clickbait, isn&amp;rsquo;t it?&lt;/p&gt;
&lt;p&gt;Today was a true summer day, with temperatures soaring around &lt;code&gt;40°C&lt;/code&gt; outside and ranging from &lt;code&gt;30°C&lt;/code&gt; to &lt;code&gt;33°C&lt;/code&gt; in the room housing my computers. In these conditions, it seemed like my Macbook wanted a day off, as even with minimal CPU load, everything was crawling at a snail&amp;rsquo;s pace.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;gallery/room-temperature.jpeg&#34; alt=&#34;Temperature of the room&#34;&gt;&lt;/p&gt;
&lt;p&gt;None of the monitoring tools - &lt;code&gt;top&lt;/code&gt;, &lt;code&gt;htop&lt;/code&gt;, &lt;code&gt;System Monitor&lt;/code&gt; - could provide a logical explanation for what was happening. The load average was hovering between 25 and 30 (&lt;code&gt;!!&lt;/code&gt;), yet no single process seemed to be the culprit.&lt;/p&gt;
&lt;p&gt;The CPU/GPU temperatures were stable around &lt;code&gt;60°C&lt;/code&gt;, and the fans were running at full throttle. At these temperatures, there shouldn&amp;rsquo;t be much cause for concern but the whole system was behaving like the slowest turtle in the world. Everything pointed towards potential &lt;em&gt;CPU throttling&lt;/em&gt; due to excessive heat.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;gallery/throttling-30.jpeg&#34; alt=&#34;Throttling cpu to 30%&#34;&gt;&lt;/p&gt;
&lt;p&gt;Indeed, once I was convinced that temperature-related throttling might be the issue, there was only one quirky and amusing way to confirm it quickly: placing my laptop in the freezer. Without hesitation, I rearranged my freezer&amp;rsquo;s contents like a master of Tetris to make room for the laptop in order to achieve a frozen apple (&lt;em&gt;ba dum tss!&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;gallery/laptop-fridge.jpeg&#34; alt=&#34;Laptop in the fridge&#34;&gt;&lt;/p&gt;
&lt;p&gt;Just a couple of minutes in the icy environment were enough to lower the temperature and witness the return of normal performance:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;gallery/throttling-100.jpeg&#34; alt=&#34;Throttling cpu to 100%&#34;&gt;&lt;/p&gt;
&lt;p&gt;Upon returning to its natural habitat, the laptop gradually warmed up, hitting &lt;code&gt;55°C&lt;/code&gt;, at which point the fans kicked in at full blast again. However, the temperature continued to rise, stabilizing around &lt;code&gt;60°C&lt;/code&gt; with the fans working at maximum capacity and throttling once again at &lt;code&gt;30%&lt;/code&gt;. I&amp;rsquo;d like to think that being unable to drop below &lt;code&gt;55°C&lt;/code&gt;, it settled into this state and everything is slow again.&lt;/p&gt;
&lt;p&gt;So, there you have it, folks! Nothing like a trusty freezer to unleash the full potential of your Apple device delivering a seamless performance!.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: No Apple products were harmed in the making of this post. While &lt;a href=&#34;https://bofhers.es&#34;&gt;#BOFHers&lt;/a&gt; endorses and stands by this technique, the author does not take responsibility for the misuse of the freezer with third-party devices.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>iPad as Dev Machine</title>
      <link>https://oscarmlage.com/posts/ipad-as-dev-machine/</link>
      <pubDate>Sun, 16 Apr 2023 11:27:17 +0000</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/ipad-as-dev-machine/</guid>
      <description>
            &lt;p&gt;Have you ever considered using an &lt;code&gt;iPad for coding&lt;/code&gt;? While an iPad may not be the most obvious choice for developers, it can serve as a valuable complement to your main development setup, thanks to its long battery life, portability, and superb keyboard. As a developer, I&amp;rsquo;ve found myself drawn to the idea of using an iPad for light development tasks, despite its limitations. In this blog post, I&amp;rsquo;ll share my experience of developing on an iPad, including the tools and apps I use, the pros and cons I&amp;rsquo;ve encountered, and my overall reflections on this unconventional approach to coding. Join me as I explore the possibilities and challenges of using an iPad as a coding tool.&lt;/p&gt;
&lt;p&gt;When it comes to coding on an iPad, having the right tools and apps can make all the difference. Here are some ideas and the apps that have helped me overcome the limitations of &lt;code&gt;iPadOS&lt;/code&gt; and enable a productive coding experience:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;VPN&lt;/strong&gt;: When coding on the go or away from home, a VPN is essential for accessing all your resources securely. I rely on the &lt;a href=&#34;https://openvpn.net&#34;&gt;OpenVPN&lt;/a&gt; app for iPad to connect to my personal VPN server, but other options like &lt;a href=&#34;https://tailscale.com&#34;&gt;Tailscale&lt;/a&gt;, &lt;a href=&#34;https://apps.apple.com/us/app/expressvpn-1-trusted-vpn/id886492891&#34;&gt;ExpressVPN&lt;/a&gt;, &lt;a href=&#34;https://apps.apple.com/us/app/cyberghost-vpn-wifi-proxy/id583009522&#34;&gt;CyberGhostVPN&lt;/a&gt;, &lt;a href=&#34;https://apps.apple.com/us/app/private-internet-access-vpn/id955626407&#34;&gt;Private Internet Access VPN&lt;/a&gt; are also available.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;SSH&lt;/strong&gt;: Since my tooling is primarily remote, all I need is a reliable terminal that supports SSH connections. &lt;a href=&#34;https://blink.sh&#34;&gt;Blink&lt;/a&gt; has been my go-to choice, offering seamless SSH connectivity on the iPad. &lt;a href=&#34;https://ish.app&#34;&gt;iSH&lt;/a&gt; and &lt;a href=&#34;https://apps.apple.com/us/app/termius-terminal-ssh-client/id549039908&#34;&gt;Termius&lt;/a&gt; are also worth checking out.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;DNS&lt;/strong&gt;: If you, like me, rely on &lt;code&gt;Docker&lt;/code&gt; for your development environment and need to resolve local domains, iPadOS lacks a direct way to modify the &lt;code&gt;/etc/hosts&lt;/code&gt; file. However, you can hack it using a &lt;code&gt;socks server&lt;/code&gt; and &lt;code&gt;SSH&lt;/code&gt; with &lt;code&gt;-D&lt;/code&gt; option to resolve requests on the destination host. This workaround has allowed me to resolve local domains, such as &lt;a href=&#34;https://localproject.lc/&#34;&gt;https://localproject.lc&lt;/a&gt;, for my Docker projects.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Editor and other tools&lt;/strong&gt;: My coding setup includes essential tools like &lt;code&gt;tmux&lt;/code&gt;, &lt;code&gt;neovim&lt;/code&gt;, &lt;code&gt;bash&lt;/code&gt;, &lt;code&gt;curl&lt;/code&gt;, &lt;code&gt;siege&lt;/code&gt;, &lt;code&gt;lazygit&lt;/code&gt;, &lt;code&gt;Docker&lt;/code&gt;, &lt;code&gt;mutt&lt;/code&gt; and more. While these tools may require some setup and configuration in the remote host you&amp;rsquo;re using, they provide a powerful coding environment over SSH.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Mosh&lt;/strong&gt; (optional): Last but not least, for enhanced stability and speed, &lt;a href=&#34;https://mosh.org&#34;&gt;Mosh&lt;/a&gt; (&lt;em&gt;Mobile Shell&lt;/em&gt;) has become a must-have for my server connections. Blink also supports Mosh connections, making it a convenient option for a more reliable and faster remote coding experience.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With the right tools and apps, an iPad can be a capable companion for coding on the go, despite its limitations. Let&amp;rsquo;s dive into the pros and cons of developing on an iPad and explore the unique possibilities it offers.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;gallery/ipad-as-dev-machine-01.png&#34; alt=&#34;iPad photo&#34;&gt;&lt;/p&gt;
&lt;p&gt;When it comes to using an iPad for development, there are several advantages that make it a compelling choice for many developers. From impressive battery life to unparalleled portability, the iPad offers a unique experience that can enhance your coding workflow. Additionally, the touch screen functionality adds a new dimension to the development process, providing new possibilities for interaction. In this section, I&amp;rsquo;ll highlight some of the main pros of using an iPad for development, based on my own experiences and observations.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Battery Life&lt;/strong&gt;: Despite not being designed for heavy development work, the iPad&amp;rsquo;s battery life is impressive. With around &lt;code&gt;8 hours&lt;/code&gt; of development work on a single charge, it&amp;rsquo;s more than enough for most coding sessions. (Please note that my dev sessions on the iPad are typically not more than &lt;code&gt;a couple of hours&lt;/code&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Portability&lt;/strong&gt;: The iPad&amp;rsquo;s portability is a standout feature, especially when compared to larger laptops like the 16-inch MacBook Pro. It&amp;rsquo;s &lt;code&gt;easy to carry around&lt;/code&gt; and set up in different work environments, making it a convenient option for developers on the go.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;User Experience&lt;/strong&gt;: There&amp;rsquo;s something about the experience of opening an iPad and starting to work on it that&amp;rsquo;s different from a regular laptop. It&amp;rsquo;s hard to put into words, but &lt;code&gt;it feels less cumbersome and more efficient&lt;/code&gt;, with a lack of laziness in getting started.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Touch Screen&lt;/strong&gt;: The iPad&amp;rsquo;s touch screen adds a new dimension to the development process. While not a primary input method, I&amp;rsquo;ve found myself trying to imitate some of those gestures on my MacBook, which seems like a sign that I miss those. The occasional use of gestures for scrolling or other basic tasks &lt;code&gt;can be helpful&lt;/code&gt; and may even influence your interactions with other devices.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;However, like any device, the iPad also has its limitations when it comes to development. While it offers unique advantages, there are some challenges and trade-offs that developers may encounter. In this section, I&amp;rsquo;ll highlight some of the main cons of using an iPad for development, based on my own experiences and observations.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Limited toolset&lt;/strong&gt;: One of the challenges of using an iPad for development is that you may not have access to all the tools and software you&amp;rsquo;re used to on a traditional laptop or desktop.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Browser limitations&lt;/strong&gt;: The iPad&amp;rsquo;s browser may have some limitations compared to desktop browsers. For example, certain advanced features or developer tools may be unavailable or restricted in functionality. This can impact your ability to thoroughly test and debug web applications, and may require you to work around these limitations or find alternative solutions.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Adaptation to remote toolset&lt;/strong&gt;: If you&amp;rsquo;re using an iPad for development like me, you&amp;rsquo;ll be working with remote tools and servers, which can require you to adapt to a different workflow. For example, using SSH or remote terminals to access your development environment, which can have a learning curve if you&amp;rsquo;re not already familiar with these tools. This can impact your productivity and may require additional time and effort to get accustomed to the remote toolset.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Changes in shortcuts and workflows&lt;/strong&gt;: The iPad&amp;rsquo;s touch-based interface and different keyboard layout compared to a traditional laptop or desktop may require you to learn new shortcuts and workflows. This can impact your muscle memory and productivity, as you may need to re-learn or adapt your familiar shortcuts and workflows to the iPad&amp;rsquo;s touch-based interactions.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In conclusion, while the iPad has its limitations and may not be the ideal choice as a dedicated development machine, it can still be a valuable tool for certain scenarios and use cases.&lt;/p&gt;
&lt;p&gt;Would I buy an iPad exclusively for development? No, based on my experience, I would opt for a more portable development machine and consider something more compact than the 16-inch MacBook Pro I own. However, if I already had an iPad, I would definitely try to equip it with the appropriate tools for development. Not for long coding sessions, but for those idle moments when I&amp;rsquo;m waiting for my kids after school, or when I&amp;rsquo;m running errands with my partner and inspiration strikes off-screen, or to break the monotony of working from home and heading to a coffee shop to finish that feature&amp;hellip; for all those occasions, the iPad is a great option.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Remote Debug in Go (nvim &#43; delve &#43; docker)</title>
      <link>https://oscarmlage.com/posts/remote-debug-dockerized-go-lang-project-nvim-delve/</link>
      <pubDate>Fri, 03 Feb 2023 19:04:27 +0000</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/remote-debug-dockerized-go-lang-project-nvim-delve/</guid>
      <description>
            &lt;p&gt;I don&amp;rsquo;t know where to start this whole story from. As a preface, I must acknowledge that my primary experience years ago has been in Python development, utilizing tools such as &lt;code&gt;pip&lt;/code&gt; for package management, a framework for organization, and &lt;code&gt;virtualenv&lt;/code&gt; for environment management. Lately, I&amp;rsquo;ve added Docker to the mix as well.&lt;/p&gt;
&lt;p&gt;Recently, a new career opportunity presented itself and I was given the opportunity to choose the tools for the job. Given the requirement for speed and high concurrency, I saw it as a perfect fit for a &lt;a href=&#34;https://go.dev&#34;&gt;go-lang&lt;/a&gt; application. I embarked on extensive research and testing to determine the best tools to support my development workflow.&lt;/p&gt;
&lt;p&gt;After careful consideration, testing, and analysis of various projects and codebases, I have reached a understanding of the flexibility that &lt;code&gt;go&lt;/code&gt; language offers in terms of project organization. I faced the challenge of breaking away from my prior &lt;em&gt;OOP&lt;/em&gt; experience and adapting to the lack of strict guidelines in go, which was both enjoyable and difficult. Through studies and observations, I have developed the ability to structure the skel to best suit the requirements of the project.&lt;/p&gt;
&lt;p&gt;Given that my unwavering red line from the start was to work with &lt;code&gt;Docker&lt;/code&gt;, it has been a very enjoyable challenge to make the entire stack dependent on containers. However there was a last step in the stack that was holding out: the debugging tools.&lt;/p&gt;
&lt;p&gt;Previously I was familiar with using &lt;code&gt;pdb&lt;/code&gt; for debugging, so my needs were relatively straightforward. I was seeking a tool to set breakpoints, inspect variables, and halt/resume execution. Initially, I considered &lt;a href=&#34;https://tip.golang.org/doc/gdb&#34;&gt;gdb&lt;/a&gt; as an option, but after reviewing the documentation, I discovered that the developers recommend &lt;a href=&#34;https://github.com/go-delve/delve&#34;&gt;delve&lt;/a&gt; as a superior alternative. Based on this recommendation, I decided to proceed with using &lt;code&gt;delve&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To use &lt;code&gt;delve&lt;/code&gt; with a &lt;code&gt;Go&lt;/code&gt; application in a container, you need to run &lt;code&gt;delve&lt;/code&gt; in the container, which allows you to control the execution of your binary by listening to remote procedure call (&lt;em&gt;RPC&lt;/em&gt;) connections. This way, you can perform actions like stopping the execution, observing variables, and stepping through the code line by line&amp;hellip;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The binary must be executed using &lt;code&gt;dlv&lt;/code&gt; (delve).&lt;/li&gt;
&lt;li&gt;A communication channel needs to be established for server-client interaction.&lt;/li&gt;
&lt;li&gt;We need a client that connects to the server and sends commands.&lt;/li&gt;
&lt;li&gt;Ideally, we would like to have an interface within our editor to manage the process.&lt;/li&gt;
&lt;li&gt;And don&amp;rsquo;t forget that all the developments is dockerized.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;delve-air-and-docker&#34;&gt;Delve, Air and Docker&lt;/h2&gt;
&lt;p&gt;The Docker setup includes two services, one for the main application and another for testing. The &lt;code&gt;app&lt;/code&gt; and &lt;code&gt;tests&lt;/code&gt; services in the Docker setup are distinct, with differing environment variables and thus separate databases. The entrypoints for each service are separate, with the &lt;code&gt;app&lt;/code&gt; service running the main application and the &lt;code&gt;tests&lt;/code&gt; service running the tests (obviously). To handle code changes, tools like &lt;a href=&#34;https://github.com/gravityblast/fresh&#34;&gt;fresh&lt;/a&gt; and &lt;a href=&#34;https://github.com/cosmtrek/air&#34;&gt;air&lt;/a&gt; were utilized, the entrypoint is configured to run air with a specific set of parameters (&lt;code&gt;.air.toml&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;root &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;.&amp;#34;&lt;/span&gt;
cmd &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;go build -o ./tmp/main main.go&amp;#34;&lt;/span&gt;
bin &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tmp/main&amp;#34;&lt;/span&gt;
include_ext &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;go&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tpl&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tmpl&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;html&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The current directory (&lt;code&gt;.&lt;/code&gt;) is mounted as a volume in the Docker container, and &lt;code&gt;air&lt;/code&gt; is configured to monitor changes to specific file extensions, triggering a rebuild and serving the updated code. For &lt;code&gt;dlv&lt;/code&gt; debugging, the binary must be run under delve, which requires installing dlv in the container. The way the binary is executed may need to be adjusted accordingly (modified &lt;code&gt;.air.toml&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;root &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;.&amp;#34;&lt;/span&gt;
cmd &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;go build -gcflags=all=\&amp;#34;-N -l\&amp;#34; -o ./tmp/main main.go&amp;#34;&lt;/span&gt;
bin &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tmp/main&amp;#34;&lt;/span&gt;
full_bin &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;dlv exec --accept-multiclient --log --headless --continue --listen=&amp;#34;&lt;/span&gt;0.0.0.0:40000&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34; --api-version=2 ./tmp/main&amp;#34;&lt;/span&gt;
include_ext &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;go&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tpl&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tmpl&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;html&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It&amp;rsquo;s important for this approach to work to remember to include the installation of &lt;code&gt;air&lt;/code&gt; and &lt;code&gt;dlv&lt;/code&gt; in your container&amp;rsquo;s &lt;code&gt;Dockerfile&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-docker&#34; data-lang=&#34;docker&#34;&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; golang:1.19-alpine&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;WORKDIR&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt; /code&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;RUN&lt;/span&gt; apk add build-base gcc-go musl-dev &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;    go install github.com/cosmtrek/air &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;    go install github.com/go-delve/delve/cmd/dlv@latest&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;...&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It appears to have potential, however, there is a new network port that we need to factor in, so we need to change our &lt;code&gt;docker-compose&lt;/code&gt; either and open both ports, appart from other options as SYS_PTRACE and seccomp/apparmor:unconfined:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;services:
  app:
    build: .
    cap_add:
        - SYS_PTRACE
    security_opt:
        - seccomp:unconfined
        - apparmor:unconfined
    &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;...&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
    command: &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;air&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
    ports:
        - 1234:1234
        - 40000:40000
    volumes:
        - ./:/code
    &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;...&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once the container has been rebuilt, we can verify that the changes are working as expected just trying to connect with &lt;code&gt;dlv&lt;/code&gt; (client) from the host to the &lt;code&gt;dlv&lt;/code&gt; (server) container. Of course you need to install &lt;code&gt;dlv&lt;/code&gt; in the host too:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;$ dlv connect 0.0.0.0:40000
Type &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;help&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; list of commands.
&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;dlv&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can now add breakpoints and continue debugging from the command line interface, which is similar to using &lt;code&gt;pdb&lt;/code&gt; in the Python world. However, it may be worth exploring further options.&lt;/p&gt;
&lt;h2 id=&#34;neovim&#34;&gt;Neovim&lt;/h2&gt;
&lt;p&gt;What do you think about having a visually appealing and straightforward debugging interface in an editor like &lt;code&gt;neovim&lt;/code&gt;?. Will try!. I&amp;rsquo;ve considered two ways: &lt;code&gt;dap&lt;/code&gt; + &lt;code&gt;dap-go&lt;/code&gt; or &lt;code&gt;vim-go&lt;/code&gt; on the other hand. I&amp;rsquo;ve tried both but only got something &lt;em&gt;usable&lt;/em&gt; with &lt;code&gt;vim-go&lt;/code&gt;, I think the &lt;code&gt;dap&lt;/code&gt; thing is the future but it still has a lot of room for the improvement, because there are some stuff that is not fully supported.&lt;/p&gt;
&lt;p&gt;First of all we need to install &lt;a href=&#34;https://github.com/fatih/vim-go&#34;&gt;vim-go&lt;/a&gt;, it depends on your package manager, in my case all I had to do was to add &lt;code&gt;Plug &#39;fatih/vim-go&#39;&lt;/code&gt; to my configuration file. Once the plugin is installed there is another little trick we should handle, the &lt;strong&gt;substitute paths&lt;/strong&gt;. Most likely your working directories will not match between your development environment and the container, so we&amp;rsquo;ll have to tell &lt;code&gt;vim-go&lt;/code&gt; to rewrite those paths so that, for example, if you want to set a breakpoint in the file &lt;code&gt;/home/oscar/code/sample/main.go&lt;/code&gt;, it knows you are referring to the file &lt;code&gt;/code/main.go&lt;/code&gt; in the container.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-vim&#34; data-lang=&#34;vim&#34;&gt;:&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;g&lt;/span&gt;:&lt;span style=&#34;color:#a6e22e&#34;&gt;go_debug_substitute_paths&lt;/span&gt; = [[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/code&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/home/oscar/code/sample&amp;#39;&lt;/span&gt;]]&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Another point to consider when opening a debug session with &lt;code&gt;vim-go&lt;/code&gt; is to indicate that it will be remote, so we will need the host and port in the same way as we have previously done with the execution of &lt;code&gt;dlv&lt;/code&gt; from the console:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-vim&#34; data-lang=&#34;vim&#34;&gt;:&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;g&lt;/span&gt;:&lt;span style=&#34;color:#a6e22e&#34;&gt;go_debug_address&lt;/span&gt; = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;0.0.0.0:40000&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we are ready to start a debug session and enjoy the debugging experience:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-vim&#34; data-lang=&#34;vim&#34;&gt;:&lt;span style=&#34;color:#a6e22e&#34;&gt;GoDebugConnect&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If everything has gone correctly, the debugging interface will open with a new layout:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&#34;problems&#34;&gt;Problems&lt;/h2&gt;
&lt;p&gt;The solution is not perfect, as I&amp;rsquo;ve commented with the &lt;code&gt;dap&lt;/code&gt; cocktail (&lt;code&gt;nvim-dap&lt;/code&gt;, &lt;code&gt;nvim-dap-go&lt;/code&gt;, &lt;code&gt;nvim-dap-ui&lt;/code&gt;&amp;hellip;) I wasn&amp;rsquo;t able to substitute the paths, so in the end the I couldn&amp;rsquo;t set breakpoints because the file was not matching. I was able to resolve it with &lt;code&gt;vim-go&lt;/code&gt;, but there are still some small issues I haven&amp;rsquo;t figured out how to solve.&lt;/p&gt;
&lt;p&gt;For example, there are many times when after establishing the connection (&lt;code&gt;:GoDebugConnect&lt;/code&gt;) and when trying to set the first breakpoint, it takes too long to respond and eventually gives an error:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;vim-go: could not toggle breakpoint: Vim(let):E716: Key not present in Dictionary: &amp;quot;result.Breakpoint&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If during that response time, you manually open &lt;code&gt;dlv connect 0.0.0.0:40000&lt;/code&gt; in another terminal, the error disappears and it continues to work. I haven&amp;rsquo;t found an explanation for this yet.&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Snowy Fun with Family</title>
      <link>https://oscarmlage.com/posts/snowy-fun-with-family/</link>
      <pubDate>Mon, 23 Jan 2023 19:57:12 +0000</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/snowy-fun-with-family/</guid>
      <description>
            &lt;p&gt;This past weekend was one for the books! My wife and I took our children on their first trip to the snow and it was an absolute blast. We live about an hour away from the nearest &amp;ldquo;snow spot&amp;rdquo;, so it was a short but sweet trip.&lt;/p&gt;
&lt;p&gt;Once we arrived, we quickly bundled up and headed outside to play in the snow. The kids were so excited to see all of the snow and they couldn&amp;rsquo;t wait to try out the sleds we had brought with us. We spent hours going down the hill, laughing and having a great time. In the afternoon, we found a familiar restaurant and decided to go for a delicious lunch. It was great to catch up with them and share in the fun of the day.&lt;/p&gt;
&lt;p&gt;As the day came to a close and we headed back home, I couldn&amp;rsquo;t help but reflect on how much fun we had as a family. This trip reminded me of the importance of spending quality time together and cherishing the moments we have with our loved ones.&lt;/p&gt;
&lt;p&gt;So, I encourage you to make an effort to plan fun and memorable experiences with your family and friends. It doesn&amp;rsquo;t have to be anything extravagant, it can be as simple as a day trip to the snow or a picnic in the park. The important thing is that you&amp;rsquo;re making time for each other and creating lasting memories.&lt;/p&gt;
&lt;p&gt;Life is short, and it&amp;rsquo;s important to make the most of it by enjoying the company of the people we love. So, don&amp;rsquo;t wait any longer, plan something fun with your family and friends, you won&amp;rsquo;t regret it! And as a fable, I can tell you, the memories and laughter you&amp;rsquo;ll create will be worth more than any material thing, it&amp;rsquo;s priceless.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>Benchmarking with Siege</title>
      <link>https://oscarmlage.com/posts/benchmarking-with-siege/</link>
      <pubDate>Thu, 29 Dec 2022 18:28:43 +0000</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/benchmarking-with-siege/</guid>
      <description>
            &lt;p&gt;If you ask me, I enjoy starting a new project, that fresh feeling during the first steps is usually becoming into a not-so-fresh thing with time. Life is so :).&lt;/p&gt;
&lt;p&gt;In this concrete case, we&amp;rsquo;re talking about an API, I needed to research and make some benchmarking work to take the best decision possible for the stack. It needs to be as fast as we can, so we can take advantage of some tools like &lt;code&gt;ab&lt;/code&gt; or &lt;code&gt;siege&lt;/code&gt; to measure some kinds of requests and scenarios.&lt;/p&gt;
&lt;p&gt;With those tools in one hand and some languages in the other (&lt;code&gt;go-lang&lt;/code&gt; and &lt;code&gt;php&lt;/code&gt; mainly, in fact, the benchmark would be go-lang using different libraries but I was curious about a compiled language vs the fastest interpreted one I know so  I added some php code), let&amp;rsquo;s start having fun!.&lt;/p&gt;
&lt;p&gt;All the tests were done in the same machine (macbook pro intel i9-9980hk) + docker containers + a dockerized mysql. The API endpoint makes a couple of SQL queries to return about 50 rows of data from a table, the response is being &lt;code&gt;jsonized&lt;/code&gt;. There is no auth and no more logic steps, just an endpoint that makes a sql query and returns the data as json.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Go-Lang + &lt;a href=&#34;https://gorm.io&#34;&gt;Gorm&lt;/a&gt; + Custom Router: the custom router uses the golang stdlib &lt;code&gt;&amp;quot;net/http&amp;quot;&lt;/code&gt; to serve GET petitions.&lt;/li&gt;
&lt;li&gt;Go-Lang + &lt;a href=&#34;https://gorm.io&#34;&gt;Gorm&lt;/a&gt; + &lt;a href=&#34;https://echo.labstack.com&#34;&gt;Echo Server&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Go-Lang + &lt;a href=&#34;https://gorm.io&#34;&gt;Gorm&lt;/a&gt; + &lt;a href=&#34;https://github.com/gin-gonic/gin&#34;&gt;Gin&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Laravel + DB raw: as Laravel was the slowest, decided to use raw sql instead Eloquent to balance a bit the results :P, queries were done with &lt;code&gt;DB::Select()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;PHP &amp;ldquo;vanilla&amp;rdquo;: some memories came to my mind using &lt;code&gt;mysqli_connect()&lt;/code&gt;, &lt;code&gt;mysqli_query()&lt;/code&gt;, and &lt;code&gt;mysqli_fetch_array()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;ve run &lt;code&gt;siege&lt;/code&gt; 3 times in different scenarios and calculated the average:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;100 requests, only 1 concurrent&lt;/li&gt;
&lt;li&gt;100 requests, 2 concurrents (50x2)&lt;/li&gt;
&lt;li&gt;100 requests, 5 concurrents (20x5)&lt;/li&gt;
&lt;li&gt;100 requests, 10 concurrents (10x10)&lt;/li&gt;
&lt;li&gt;1000 requests, 10 concurrents (100x10)&lt;/li&gt;
&lt;li&gt;10000 requests, 100 concurrents (100x100)&lt;/li&gt;
&lt;li&gt;Max requests in 30 seconds, 10 concurrents&lt;/li&gt;
&lt;li&gt;Max requests in 30 seconds, 100 concurrents&lt;/li&gt;
&lt;li&gt;Max requests in 30 seconds, 150 concurrents: I got some errors here, so it doesn&amp;rsquo;t matter for the graphics&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And the result is quite interesting:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;In this benchmark &lt;strong&gt;Go+Gorm+Echo&lt;/strong&gt; is the clear winner, closely followed by &lt;strong&gt;Go+Gorm+Gin&lt;/strong&gt;. About PHP, dunno if I did something wrong but there is a lot of difference between vanilla PHP (the results are kinda acceptable) and Laravel, still dunno why.&lt;/p&gt;
&lt;p&gt;I had so much fun with this &amp;ldquo;exercise&amp;rdquo;.&lt;/p&gt;

      </description>
    </item>
    <item>
      <title>The Van</title>
      <link>https://oscarmlage.com/posts/the-van/</link>
      <pubDate>Mon, 07 Nov 2022 10:43:36 +0000</pubDate><author>info@oscarmlage.com (oscarmlage)</author>
      <guid>https://oscarmlage.com/posts/the-van/</guid>
      <description>
            &lt;p&gt;My wife and I have been used to camping since a long time ago, just put the tent and a couple of sleeping bags in the trunk of the car and drive to somewhere with a beach. We did that since the very beginning, I have lots of good memories and stories about it.&lt;/p&gt;
&lt;p&gt;Obviously, life changes when you have children, tried - and did - it a couple of times but in the end it&amp;rsquo;s not just &amp;ldquo;pick whatever and go&amp;rdquo; because kids need more preparation, and not only preparation but stuff (clothes, games, medicines, maybe some food either&amp;hellip;) so in the end it means much more work and worries. In that case the easy way -if you can afford it- makes more sense: do a reservation in a hotel and keep the &amp;ldquo;adventure level&amp;rdquo; limited to a &amp;ldquo;what kind of mojito should I order today in the swimming pool&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;That is totally fine don&amp;rsquo;t get me wrong, but well, we usually need &lt;em&gt;something else&lt;/em&gt; in our trips, little adventures, discovering new places, not to have closed schedules for everything, etc&amp;hellip; So, after a lot of thought and doubts, two years ago (&lt;em&gt;Oct&#39;20&lt;/em&gt;) we decided to buy a van and do a full camperization according to our needs. We were sure that the project would help us to find the roots of those first camping trips.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m really proud and grateful to all the people that offered help and helped us to achieve this, taking in account I was that kind of guy that asked for help even for changing a bulb, you can imagine the amount of &amp;ldquo;try and error&amp;rdquo; stuff we had to deal with. Of course, Marta and the kids were there the whole time helping and supporting in every single problem we had to arrange, which makes the thing way easier.&lt;/p&gt;
&lt;p&gt;And two years later, after lots of learnings, investments, efforts, worries and much more stuff I can&amp;rsquo;t tell with words&amp;hellip; we did our first (and second) trip!. For the moment, even being in autumn and with so and so weather, it&amp;rsquo;s being a total success, children are always pleased to be on the road with that adventure feeling, &amp;ldquo;where are we going this time?&amp;rdquo;, &amp;ldquo;where are we going to sleep?&amp;rdquo;, &amp;ldquo;still a long way?&amp;rdquo;. Of course it&amp;rsquo;s not ideal all the time (#vanlife has &amp;ldquo;things&amp;rdquo;) we still have to deal with the basic services (clean and dirty water, electricity, park, etc&amp;hellip;) but we already knew this stuff from other experiences when rented motorhomes so, in general, there is no big surprises for now.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[image not loaded in rss]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;🤷 &lt;em&gt;I have lots of Gb. with videos and pics along this camperization process but dunno if I&amp;rsquo;ll ever have time to edit or do something more orderly and appropriate with them.&lt;/em&gt;&lt;/p&gt;

      </description>
    </item>
  </channel>
</rss>
