<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>ThangQT&apos;s Writing</title><description>My various thoughts on life, tech, and everything in between</description><link>https://thangqt.com/</link><language>en-us</language><item><title>Year 2025</title><link>https://thangqt.com/writing/year-2025/</link><guid isPermaLink="true">https://thangqt.com/writing/year-2025/</guid><description>A soft look back at the year that passed, and a small promise for the year ahead.</description><pubDate>Tue, 17 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;It’s 00:49 AM. I just got back from a New Year gathering with my friends.&lt;/p&gt;
&lt;p&gt;Normally, I’d take time after midnight to be by myself and sit with the atmosphere for a bit. But tonight felt different. Being with my friends felt warm and real, and for once I didn’t feel like I was missing that quiet moment alone.&lt;/p&gt;
&lt;p&gt;Another year has passed. A new chapter is opening. Before I move forward, I want to look back at the things I missed and the things I loved.&lt;/p&gt;
&lt;p&gt;I’ll start with the hard stuff.&lt;/p&gt;
&lt;p&gt;The most disappointing thing this year was failing two people who mattered to me, who trusted me. They were going through critical moments in their lives, and I was careless. I regret it, and I’m truly sorry for it.&lt;/p&gt;
&lt;p&gt;I also crossed one of my moral lines. I’m not proud of it. The only good part is I didn’t fully act on it, and I’ve been actively working on that part of myself. Still, it’s something I need to take seriously.&lt;/p&gt;
&lt;p&gt;Lastly, I told myself I’d put in more work for the courses I’m not interested in. Just be disciplined, do what needs to be done. But I haven’t really done it. It’s not surprising, but it still feels like a letdown.&lt;/p&gt;
&lt;p&gt;That’s enough of the hard stuff.&lt;/p&gt;
&lt;p&gt;On the positive side, I’ve been enjoying other people’s company more. That’s honestly a really good change for me.&lt;/p&gt;
&lt;p&gt;Even while going through some difficulties, I stayed mostly financially independent and could afford the gear and subscriptions I like. But I also spent about half of my savings, which isn’t great. That’s something I need to be more mindful of this year.&lt;/p&gt;
&lt;p&gt;I managed to do four personal projects. Most reached MVP, and one was publicly released. They still need finishing touches. I told myself I’d polish them during the holiday, but other things came up, and partly I lost interest. So I’m putting them aside for now, without forcing it.&lt;/p&gt;
&lt;p&gt;I also focused more on myself. I changed up my clothing style a bit. And even better, I started working out recently. I never imagined I’d actually enjoy it, but here I am. It’s peaceful alone time, and it feels healthy.&lt;/p&gt;
&lt;p&gt;Though honestly, I spent too much money on it. Part of that savings I mentioned. There were cheaper options, but the more expensive one gives me a better, more comfortable environment. It makes it easier to show up consistently. Hopefully it works itself out.&lt;/p&gt;
&lt;p&gt;The biggest thing is I got an internship offer, and I’m onboarding right after the holiday. To be honest, I wasn’t planning to apply this early. I thought I’d wait until summer. But my friends kept asking about it, and I got hit with FOMO. So I started looking right before the holiday and got one after a few tries.&lt;/p&gt;
&lt;p&gt;I’ve also been trying to get my sleep schedule back to normal after staying up late for too long. I’ve made real progress recently, which feels good since I’ll need to wake up early for the internship and school.&lt;/p&gt;
&lt;p&gt;On top of that, my parents got me a motorbike to commute to work. A huge gift. I’m really grateful.&lt;/p&gt;
&lt;p&gt;So my direction for this new year is simple. Try my best in this internship and prepare myself for the job market.&lt;/p&gt;
&lt;p&gt;More specifically, I’m planning to take IELTS before summer. I’m confident in reading and listening, but speaking, and maybe writing, aren’t quite there yet. After the holiday, I’ll take a mock test to make an informed decision and see if I can allocate the time for it.&lt;/p&gt;
&lt;p&gt;I also want more agency this year. I want to cut down on unhelpful ways I relax, like mobile gaming, read more books, and reduce the unhealthy content I consume on social media.&lt;/p&gt;
&lt;p&gt;Honestly, I don’t know exactly how it’ll all play out. But this feels like a transition year for me. Something is waiting, and I have a good feeling about it.&lt;/p&gt;
&lt;p&gt;Chúc mừng năm mới!&lt;/p&gt;</content:encoded><category>personal</category></item><item><title>My thoughts on NixOS and Void Linux</title><link>https://thangqt.com/writing/thoughts-on-nixos-and-void/</link><guid isPermaLink="true">https://thangqt.com/writing/thoughts-on-nixos-and-void/</guid><description>Why I keep bouncing between Void and NixOS</description><pubDate>Fri, 23 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I keep bouncing between Void and NixOS. It’s been years of hopping, but lately it’s mostly those two.&lt;/p&gt;
&lt;p&gt;Back when I was on Arch, I found Void as a lightweight alternative. I didn’t really care about the systemd debate, I was just tired of my system breaking from dependency conflicts. You know the drill: on Ubuntu-based distros you add third-party repos, on Arch you use the AUR, and eventually something breaks.&lt;/p&gt;
&lt;p&gt;Void has honestly been one of the most stable experiences I’ve had with a “normal” distro. People say its package repo is modest, but I never felt like I was missing much.&lt;/p&gt;
&lt;p&gt;Then came NixOS. The immutable distro everyone was talking about. The “high learning curve” warnings didn’t turn me off. After trying it, yeah, it’s different. But even without really learning Nix syntax properly, I was able to set up my workspace.&lt;/p&gt;
&lt;p&gt;Here’s my honest take: 90% of the time, NixOS offers convenience and time savings far beyond any distro I’ve used. With &lt;code&gt;services.*&lt;/code&gt;, I can deploy almost any service with just a few lines of config. &lt;code&gt;nix-shell&lt;/code&gt; is great for temporary experiments. And if I ever break my system, I just boot into the previous generation. How nice is that!&lt;/p&gt;
&lt;p&gt;But the remaining 10%? When you want to do something that’s not officially supported or not “the Nix way”, it becomes way harder than on normal distros. That’s why I switched back to Void the last time. I was struggling to set up my web dev environment for learning, and I just needed things to work.&lt;/p&gt;
&lt;p&gt;Overall, I still prefer NixOS so much that I’ve switched back to it. I initially didn’t think much about making the switch, but then I found a cheap object storage offer and set up backups - having that safety net made the decision easier. You can read about my backup setup &lt;a href=&quot;/writing/restic-backup&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Edit:&lt;/strong&gt; I just remembered that one of the big friction points I had with NixOS last time was running Prisma. Now that I’m back, I tried setting it up again following the official guide, but still had no luck. Luckily, I found &lt;a href=&quot;https://github.com/VanCoding/nix-prisma-utils&quot;&gt;nix-prisma-utils&lt;/a&gt; and it worked like a charm.&lt;/p&gt;</content:encoded><category>linux</category><category>personal</category></item><item><title>Setting up backup with restic</title><link>https://thangqt.com/writing/restic-backup/</link><guid isPermaLink="true">https://thangqt.com/writing/restic-backup/</guid><description>Finally setting up proper backups with restic on Void and NixOS</description><pubDate>Fri, 23 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I recently came across a cheap object storage offer. It got me thinking about backups, one of those things I always tell myself I’ll set up “eventually.” Well, this is eventually.&lt;/p&gt;
&lt;p&gt;It also got me thinking about switching back to NixOS (why? I wrote about that &lt;a href=&quot;/writing/thoughts-on-nixos-and-void&quot;&gt;here&lt;/a&gt;), something I’ve been considering for a while now. This felt like the perfect opportunity - set up proper backups first, then make the switch with a safety net.&lt;/p&gt;
&lt;p&gt;Then I realized I still had a Windows partition sitting unused on another disk. It only existed because my professor required a monitored exam browser for exams, and after that I had a brief gamepad phase where I played RDR for a few days. Haven’t touched it since.&lt;/p&gt;
&lt;p&gt;So I nuked Windows and installed NixOS there instead. Set everything up, including the backup configuration. After NixOS was stable, I booted back into Void to back it up as well. Now I’m using NixOS as my main system.&lt;/p&gt;
&lt;p&gt;Here’s the actual setup. I’m presenting NixOS first since that’s my main system now, then the Void backup.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NixOS&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Setting up restic on NixOS is where the platform really shines. Instead of manually managing systemd services and timers, NixOS provides a declarative &lt;code&gt;services.restic.backups&lt;/code&gt; module that handles everything.&lt;/p&gt;
&lt;p&gt;I followed &lt;a href=&quot;https://imranmustafa.net/simple-restic-backup-on-nixos/&quot;&gt;this guide&lt;/a&gt; which breaks down the setup nicely. You can check out my config here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/thang-qt/nixcfg/blob/main/modules/nixos/restic.nix&quot;&gt;https://github.com/thang-qt/nixcfg/blob/main/modules/nixos/restic.nix&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A few things worth noting:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I’m using &lt;code&gt;sops-nix&lt;/code&gt; to manage secrets securely. The restic password and S3 credentials are encrypted and only decrypted at runtime.&lt;/li&gt;
&lt;li&gt;I’m keeping 7 daily snapshots, 4 weekly, 6 monthly, and 2 yearly. This gives me a good balance between storage usage and recovery options.&lt;/li&gt;
&lt;li&gt;The exclude list covers common cache directories, build artifacts, and temporary files. No point backing up &lt;code&gt;node_modules&lt;/code&gt; when I can just &lt;code&gt;npm install&lt;/code&gt; again.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;On Void&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Setting up restic on Void is more hands-on than NixOS, but it’s straightforward. First, install restic:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes rose-pine-dawn vitesse-dark&quot; style=&quot;--shiki-light:#575279;--shiki-dark:#dbd7caee;--shiki-light-bg:#faf4ed;--shiki-dark-bg:#121212; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D7827E;--shiki-dark:#80A665&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt; xbps-install&lt;/span&gt;&lt;span style=&quot;--shiki-light:#286983;--shiki-dark:#C99076&quot;&gt; -S&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt; restic&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then create a directory for secrets and configuration:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes rose-pine-dawn vitesse-dark&quot; style=&quot;--shiki-light:#575279;--shiki-dark:#dbd7caee;--shiki-light-bg:#faf4ed;--shiki-dark-bg:#121212; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D7827E;--shiki-dark:#80A665&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt; mkdir&lt;/span&gt;&lt;span style=&quot;--shiki-light:#286983;--shiki-dark:#C99076&quot;&gt; -p&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt; /etc/restic&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D7827E;--shiki-dark:#80A665&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt; chmod&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D7827E;--shiki-dark:#4C9A91&quot;&gt; 700&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt; /etc/restic&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Create the password file, environment variables for S3 credentials, and repository URL:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes rose-pine-dawn vitesse-dark&quot; style=&quot;--shiki-light:#575279;--shiki-dark:#dbd7caee;--shiki-light-bg:#faf4ed;--shiki-dark-bg:#121212; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#797593;--shiki-light-font-style:italic;--shiki-dark:#758575DD;--shiki-dark-font-style:inherit&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;--shiki-light:#9893A5;--shiki-light-font-style:italic;--shiki-dark:#758575DD;--shiki-dark-font-style:inherit&quot;&gt; Password for the restic repository&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D7827E;--shiki-dark:#80A665&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt; hx&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt; /etc/restic/password&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D7827E;--shiki-dark:#80A665&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt; chmod&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D7827E;--shiki-dark:#4C9A91&quot;&gt; 600&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt; /etc/restic/password&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#797593;--shiki-light-font-style:italic;--shiki-dark:#758575DD;--shiki-dark-font-style:inherit&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;--shiki-light:#9893A5;--shiki-light-font-style:italic;--shiki-dark:#758575DD;--shiki-dark-font-style:inherit&quot;&gt; S3 credentials&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D7827E;--shiki-dark:#80A665&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt; hx&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt; /etc/restic/env&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#797593;--shiki-light-font-style:italic;--shiki-dark:#758575DD;--shiki-dark-font-style:inherit&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;--shiki-light:#9893A5;--shiki-light-font-style:italic;--shiki-dark:#758575DD;--shiki-dark-font-style:inherit&quot;&gt; Contains:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#797593;--shiki-light-font-style:italic;--shiki-dark:#758575DD;--shiki-dark-font-style:inherit&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;--shiki-light:#9893A5;--shiki-light-font-style:italic;--shiki-dark:#758575DD;--shiki-dark-font-style:inherit&quot;&gt; AWS_ACCESS_KEY_ID=your_key&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#797593;--shiki-light-font-style:italic;--shiki-dark:#758575DD;--shiki-dark-font-style:inherit&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;--shiki-light:#9893A5;--shiki-light-font-style:italic;--shiki-dark:#758575DD;--shiki-dark-font-style:inherit&quot;&gt; AWS_SECRET_ACCESS_KEY=your_secret&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D7827E;--shiki-dark:#80A665&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt; chmod&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D7827E;--shiki-dark:#4C9A91&quot;&gt; 600&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt; /etc/restic/env&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#797593;--shiki-light-font-style:italic;--shiki-dark:#758575DD;--shiki-dark-font-style:inherit&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;--shiki-light:#9893A5;--shiki-light-font-style:italic;--shiki-dark:#758575DD;--shiki-dark-font-style:inherit&quot;&gt; Repository URL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D7827E;--shiki-dark:#80A665&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt; sh&lt;/span&gt;&lt;span style=&quot;--shiki-light:#286983;--shiki-dark:#C99076&quot;&gt; -c&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D77&quot;&gt; &apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt;echo &quot;s3:https://s3-hcm5-r1.longvan.net/backupqt/hostname/leaf&quot; &gt; /etc/restic/repo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D77&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D7827E;--shiki-dark:#80A665&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt; chmod&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D7827E;--shiki-dark:#4C9A91&quot;&gt; 600&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt; /etc/restic/repo&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Initialize the repository:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes rose-pine-dawn vitesse-dark&quot; style=&quot;--shiki-light:#575279;--shiki-dark:#dbd7caee;--shiki-light-bg:#faf4ed;--shiki-dark-bg:#121212; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D7827E;--shiki-dark:#80A665&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt; sh&lt;/span&gt;&lt;span style=&quot;--shiki-light:#286983;--shiki-dark:#C99076&quot;&gt; -c&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D77&quot;&gt; &apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt;export $(cat /etc/restic/env | xargs); restic -r &quot;$(cat /etc/restic/repo)&quot; --password-file /etc/restic/password init&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D77&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Create an excludes file with patterns for directories and files you don’t want backed up:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes rose-pine-dawn vitesse-dark&quot; style=&quot;--shiki-light:#575279;--shiki-dark:#dbd7caee;--shiki-light-bg:#faf4ed;--shiki-dark-bg:#121212; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D7827E;--shiki-dark:#80A665&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt; hx&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt; /etc/restic/excludes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D7827E;--shiki-dark:#80A665&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt; chmod&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D7827E;--shiki-dark:#4C9A91&quot;&gt; 600&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt; /etc/restic/excludes&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Mine looks mostly similar to the NixOS config, with a few tweaks.&lt;/p&gt;
&lt;p&gt;Create a backup script:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes rose-pine-dawn vitesse-dark&quot; style=&quot;--shiki-light:#575279;--shiki-dark:#dbd7caee;--shiki-light-bg:#faf4ed;--shiki-dark-bg:#121212; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D7827E;--shiki-dark:#80A665&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt; sh&lt;/span&gt;&lt;span style=&quot;--shiki-light:#286983;--shiki-dark:#C99076&quot;&gt; -c&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D77&quot;&gt; &apos;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt;cat &gt; /usr/local/bin/restic-backup &amp;#x3C;&amp;#x3C;EOF&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt;#!/bin/sh&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt;set -e&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt;export \$(cat /etc/restic/env | xargs)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt;restic -r &quot;\$(cat /etc/restic/repo)&quot; \\&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt;  --password-file /etc/restic/password \\&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt;  backup /home/thang \\&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt;  --exclude-caches \\&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt;  --exclude-if-present .nobackup \\&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt;  --exclude-file /etc/restic/excludes \\&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt;  --compression auto&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt;EOF&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D77&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D7827E;--shiki-dark:#80A665&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt; chmod&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D7827E;--shiki-dark:#4C9A91&quot;&gt; 700&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt; /usr/local/bin/restic-backup&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Before running the first backup, I cleaned up some junk that had accumulated in my home directory - old &lt;code&gt;node_modules&lt;/code&gt;, a &lt;code&gt;go&lt;/code&gt; directory I wasn’t using, and some leftover project folders. Then ran:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes rose-pine-dawn vitesse-dark&quot; style=&quot;--shiki-light:#575279;--shiki-dark:#dbd7caee;--shiki-light-bg:#faf4ed;--shiki-dark-bg:#121212; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D7827E;--shiki-dark:#80A665&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#EA9D34;--shiki-dark:#C98A7D&quot;&gt; /usr/local/bin/restic-backup&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first backup was… an iterative process. I kept stopping it (Ctrl+C) to refine the excludes file as I realized what else I didn’t need backed up - the Android SDK, more cache directories, temporary files. Each interrupted run uploaded some data before I cancelled it. After a few rounds of tweaking, the final successful run processed 551,006 files (48.39 GiB).&lt;/p&gt;
&lt;p&gt;It took over an hour, which was quite long. I suspect it’s because I have lots of small files scattered everywhere - config files, dotfiles, all those tiny things that accumulate over time.&lt;/p&gt;
&lt;p&gt;Unlike the NixOS setup, I’m not running automated daily backups or pruning here. Since I’m now using NixOS as my main system and will likely store all my data there going forward, this Void backup is just a one-time safety net. I probably won’t touch this partition much anymore, and will likely nuke it eventually once I’m fully settled on NixOS.&lt;/p&gt;</content:encoded><category>linux</category><category>personal</category><category>backup</category></item><item><title>On the new site</title><link>https://thangqt.com/writing/on-the-new-site/</link><guid isPermaLink="true">https://thangqt.com/writing/on-the-new-site/</guid><description>I rebuilt my personal site</description><pubDate>Tue, 13 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;If you’ve visited before, you might notice things look a bit different around here. If you’re new here, welcome.&lt;/p&gt;
&lt;p&gt;Anyway, my old site was built with &lt;a href=&quot;https://ter.kkga.me&quot;&gt;ter&lt;/a&gt;, a wiki-style site builder. I was initially hooked on its minimal, clean aesthetic and its unique approach to organizing content. Although I had some grievances when trying to customize it later on, I was still quite satisfied with what it offered.&lt;/p&gt;
&lt;p&gt;Recently, I came across &lt;a href=&quot;https://segundofdez.com&quot;&gt;Segundo Fdez’s site&lt;/a&gt;, stunning and minimal, exactly the vibe I was looking for. I was bored, procrastinating studying for an upcoming exam, so on impulse, I decided to rebuild my site using Astro, taking inspiration from his design.&lt;/p&gt;
&lt;p&gt;It was fun. Took about 3 days of staying up late into the morning. The hardest part was making it mobile responsive since I originally designed and tested everything on desktop only.&lt;/p&gt;
&lt;p&gt;I’m no designer, but I’m happy with how it turned out. I’ll be looking for work soon, so this serves as a good foundation to showcase what I do.&lt;/p&gt;
&lt;p&gt;The old site source is still available on &lt;a href=&quot;https://github.com/thang-qt/thangqt.com&quot;&gt;GitHub&lt;/a&gt; if anyone’s curious. This new one I’m keeping private for now.&lt;/p&gt;
&lt;p&gt;New year, new me, new site, I guess.&lt;/p&gt;</content:encoded><category>personal</category></item><item><title>MindForm: AI-powered document generation</title><link>https://thangqt.com/writing/mindform/</link><guid isPermaLink="true">https://thangqt.com/writing/mindform/</guid><description>Building an AI tool to convert images into polished PDF documents</description><pubDate>Fri, 20 Jun 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;original-inspiration&quot;&gt;Original inspiration&lt;/h2&gt;
&lt;p&gt;I was working on a study material sharing website. Often, when new exams come up, people capture the exam papers and upload them to Facebook. This works for those who just want a quick look at the questions. However, for people who want to actually solve the exams, a well-formatted document, usually a PDF, is much more useful.&lt;/p&gt;
&lt;p&gt;This made me realize there was a big opportunity for my website. If I could find a way to quickly convert images into polished PDF documents faster than my competitors, it could attract a lot of users.&lt;/p&gt;
&lt;h2 id=&quot;the-idea&quot;&gt;The idea&lt;/h2&gt;
&lt;p&gt;Manually creating a document from images is not only time-consuming but also requires a lot of effort to make it look professional. So, I thought, why not use AI to generate the document for me? But how could I do that?&lt;/p&gt;
&lt;p&gt;Most people use MS Word to compose documents and then export them to PDF. Unfortunately, there’s no straightforward way to use AI to generate documents in MS Word or PDF formats. Markdown is too basic and lacks advanced formatting options. LaTeX seemed promising, but it’s too complex for AI and not suitable for most document generation tasks.&lt;/p&gt;
&lt;p&gt;That’s when I thought of using HTML. Current models like GPT, Claude, and Gemini are already good at generating complex websites, so creating a simple HTML document should be manageable. Plus, HTML can be converted to PDF. I’ve used the browser’s built-in “print to PDF” feature to save webpages before, so I knew it was possible.&lt;/p&gt;
&lt;p&gt;This became the plan: use AI to generate HTML documents and then convert them to PDF. If implemented well, it could save a lot of time and effort.&lt;/p&gt;
&lt;h2 id=&quot;the-implementation&quot;&gt;The implementation&lt;/h2&gt;
&lt;p&gt;I started by experimenting with Google AI Studio’s build features, which helped me quickly create a prototype. However, the generated HTML wasn’t great and didn’t preserve the formatting of the original images. Pure JavaScript-based HTML-to-PDF conversion also didn’t work well, so I had to explore server-side solutions. Unfortunately, Google AI Studio didn’t allow me to change the model used in the prototype or support server-side code.&lt;/p&gt;
&lt;p&gt;This meant I had to build everything from scratch, with the help of LLMs, of course. The first step was designing the website. I used v0 to generate the frontend design. After several iterations, I finally had a design I was happy with.&lt;/p&gt;
&lt;p&gt;Before diving deeper, I researched efficient ways to convert HTML to PDF. That’s when I discovered WeasyPrint, a Python-based tool. Since I was already familiar with Python and had recently built a chess web app with FastAPI, it seemed like a good fit. I fired up VS Code, downloaded the code from v0, and started implementing. With GitHub Copilot’s help, I quickly had a working prototype.&lt;/p&gt;
&lt;p&gt;The quality of the generated HTML was hit or miss, but I decided to move forward. It wasn’t perfect, but it was better than nothing. I planned to turn this into a commercial product. Even if it failed, I’d learn a lot and have something to showcase my skills.&lt;/p&gt;
&lt;p&gt;To make it commercially viable, I added features like document generation from scratch based on user input. I also built a library of pre-made templates so users could pick one and customize it with AI. After some research, I realized there wasn’t a well-known product offering this, making it a niche with great potential. Despite having a few final exams coming up, I decided to keep working on it.&lt;/p&gt;
&lt;p&gt;Fast forward a few weeks, I had a beautiful website, a working backend, and a few templates. I even implemented usage tracking and a pricing model. The only thing missing was the billing system.&lt;/p&gt;
&lt;p&gt;Excitedly, I began testing the app thoroughly. Unfortunately, the generated documents weren’t very good. The biggest issue was PDF conversion, it often resulted in different styling from the original HTML, with misplaced page breaks and other problems. This seemed to be a limitation of current LLMs, partly because they can’t control layouts or see the final output.&lt;/p&gt;
&lt;h2 id=&quot;lessons-learned&quot;&gt;Lessons learned&lt;/h2&gt;
&lt;p&gt;The concept is solid, but I need a better way to handle PDF generation. After more research, I discovered Typst, which looked promising. However, I was disappointed to find very few libraries for it. Worse, current models don’t seem to have enough training data on Typst, leading to poor syntax generation.&lt;/p&gt;
&lt;p&gt;At this point, I decided to pause the project and treat it as an experiment. I can always revisit it later when better solutions become available.&lt;/p&gt;
&lt;h2 id=&quot;preview&quot;&gt;Preview&lt;/h2&gt;
&lt;p&gt;Below are some screenshots of the website. I hope to return to this project someday and turn it into a successful product.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Landing page&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;2734&quot; height=&quot;12032&quot; src=&quot;/_astro/landing.C25jCgsa_Z24RUAw.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Text generation&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;2734&quot; height=&quot;4224&quot; src=&quot;/_astro/text-generation.Djax3o-9_Z1XGI7u.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Document preview&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;2734&quot; height=&quot;3040&quot; src=&quot;/_astro/document-preview.CNwjjr6m_1WQaM8.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Image generation&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;2734&quot; height=&quot;3556&quot; src=&quot;/_astro/image-generation.C6W8VRDH_ZWqh0h.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Templates&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;2734&quot; height=&quot;5222&quot; src=&quot;/_astro/templates.15QCoZY1_Z1kBFJK.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;I still keep the code in a private repository. However, it’s quite messy, so I don’t plan to release it as an open-source project.&lt;/p&gt;</content:encoded><category>llm</category><category>project</category></item><item><title>My hometown</title><link>https://thangqt.com/writing/hometown/</link><guid isPermaLink="true">https://thangqt.com/writing/hometown/</guid><description>Some pics I took of my beloved hometown</description><pubDate>Sun, 15 Jun 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Some of the images I took when I got back to my hometown for a few days. I didn’t realize just how beautiful this place is until I moved to the city.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Tip: Click on any image to view it fullscreen. Use arrow keys to navigate and scroll to zoom.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img  loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;3072&quot; height=&quot;4080&quot; src=&quot;/_astro/PXL_20250613_112754305.BXwTwNDr_Z1jRrCh.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img  loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;3072&quot; height=&quot;4080&quot; src=&quot;/_astro/PXL_20250613_113409870.BcRldQbL_Z1rla5C.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img  loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;4080&quot; height=&quot;3072&quot; src=&quot;/_astro/PXL_20250613_113841275.mtSETOb0_2fD7WU.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img  loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;4080&quot; height=&quot;3072&quot; src=&quot;/_astro/PXL_20250613_114142363.B4b8XyqJ_4wwIc.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img  loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;3072&quot; height=&quot;4080&quot; src=&quot;/_astro/PXL_20250613_114340186.MP.CAZ_bDOD_rJdcL.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img  loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;4080&quot; height=&quot;3072&quot; src=&quot;/_astro/PXL_20250613_114531489.JEVPhSzn_ZzrOp.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img  loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;4080&quot; height=&quot;3072&quot; src=&quot;/_astro/PXL_20250613_114700540.C3L2UoXD_Zv9Wrw.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img  loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;3072&quot; height=&quot;4080&quot; src=&quot;/_astro/PXL_20250613_114733209.CaEbCLdk_1AwzXH.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img  loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;4080&quot; height=&quot;3072&quot; src=&quot;/_astro/PXL_20250613_114751953.CwaTu4ea_Z1isfLI.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img  loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;3072&quot; height=&quot;4080&quot; src=&quot;/_astro/PXL_20250613_114832098.BCAm7v-g_2mhjmN.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img  loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;3072&quot; height=&quot;4080&quot; src=&quot;/_astro/PXL_20250613_114914446.0R8CiHmf_18qVQ6.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img  loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;4080&quot; height=&quot;3072&quot; src=&quot;/_astro/PXL_20250613_115137167.p4apJuBy_Z1x7J1n.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img  loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;3072&quot; height=&quot;4080&quot; src=&quot;/_astro/PXL_20250613_115155412.DjUPdMb4_1YF3dc.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img  loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;4080&quot; height=&quot;3072&quot; src=&quot;/_astro/PXL_20250613_115309743.CQFMMfvK_2ndX9H.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img  loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;3072&quot; height=&quot;4080&quot; src=&quot;/_astro/PXL_20250613_115409847.D5RI363B_Z2gbIAJ.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img  loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;3072&quot; height=&quot;4080&quot; src=&quot;/_astro/PXL_20250613_115727418.dtGc3ED6_ZxmJHg.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img  loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;3072&quot; height=&quot;4080&quot; src=&quot;/_astro/PXL_20250613_115745282.KLoCbjvb_Z1BtBzg.webp&quot; &gt;&lt;/p&gt;
&lt;p&gt;&lt;img  loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;6144&quot; height=&quot;8160&quot; src=&quot;/_astro/PXL_20250614_092233273.1g8MlA_R_Z1Wpeag.webp&quot; &gt;&lt;/p&gt;</content:encoded><category>photography</category></item></channel></rss>