2025-07-31 08:00:00
Hi there! This month’s Cool Links are all about the web.
Draw a Fish Dot Com, by fifteen.games
This is what the web was made for. Just draw a fish. Then watch your creation swim with fishes from all over the world. Beautiful.
Netstuck, by Mark Pitblado
This article talks a bit about the Netstuck effect, when you feel forced to use a service or platform just because everyone is there, and how that’s different from a monopoly.
As someone with no commercial social media accounts, I relate to this a lot. And even though I can live without a Facebook or Instagram account, I tried not using WhatsApp in Brazil for a couple years and just had to concede at some point, because there’s just no way of getting in contact with anyone (especially businesses) in here without it.
This game tests your knowledge on JavaScript’s Date class. It’s funny because it’s sad.
Don’t animate height!, by Jim Fisher
Neat article in which Jim explains why a seemingly harmless CSS transition property (using height
) was spiking up CPU usage. It goes through the thought process of identifying the issue, understanding it, and solving it. (spoiler: animating transform
is much cheaper!)
A Friendly Introduction to SVG, by Josh W. Comeau
I know SVGs are amazing, and I’ve done some cool things with them. But I never really knew what I was doing. This fantastic post by Josh Comeau goes over the basics and focuses on SVGs you can create yourself through code, instead of relying on vector editing softwares like Figma or Illustrator.
I haven’t tried these tips in practice yet, but hopefully I’ll have a neat idea I can use them on soon 👀
(pt-br) Como eu salvo links e preservo conteúdos no mundo pós-Pocket, by Augusto Campos
This article (in Brazilian Portuguese) was a huge inspiration to me in reworking how I save my Cool Links, starting this month. I’m using the Obsidian Web Clipper instead of the custom solution the author had, but the principles are still the same.
Building up a weekly routine to organize things has also been a good change, as I don’t have a lot to do at the end of the month when I’m putting this post together.
I hope you enjoyed the links this month! Life’s been busy with all the move preppin’, but I’m glad I was still able to grab some links.
I’ve changed how I save the links to make it easier to organize them at the end of the month, and I’m planning to build an archive of all links I’ve posted so far, in a single page. No promises as to when though; my August looks really busy already 😵
Anyway, see you next month!
2025-07-21 20:00:00
Skeletá
2025, Ghost
My rating: Loved it!
Every single Ghost album improves on the last, and this is no exception. Every single song in this is a banger, with special mentions to Lachryma, Satanized, De Profundis Borealis and Umbra. These might just be the top 4 Ghost songs ever for me.
I gotta say though, the album as a whole is not as cohesive as IMPERA was. It has better songs individually, but IMPERA felt like a better album (at least on first listen) because every song complements each other. Skeletá doesn’t have a single musical identity like that, but whatever it’s doing, every song works individually.
2025-07-20 08:00:00
For a little over a year, I’ve been writing quick reviews of movies and TV shows I’ve watched. I was inspired by Matt Birchler on Mastodon and his own Quick Reviews web app, and while I initially used his app to write my own and post to social media, I decided to give my reviews a home in here.
So, after gathering my reviews as Markdown files in Obsidian, they’re now in a new section here. Meet Quick Reviews!
The review cards are not images, but just web elements like everything else. Which means they are responsive and lightweight. I made it as easy as possible to publish them on my side, and there’s even a download button to allow me to quickly post them to social media!
If you’re interested in how I made it work, it’s actually not that complicated.
This website already uses Markdown files for the blog posts, and since it uses Astro, fetching data for the Quick Reviews was as easy as declaring a new Content Collection, pointing to the right folder, and declaring its schema. It will all make sense in a bit.
First of all, I needed to define what a review would look like. Its main pieces of information are the movie/show’s name, the rating, and the content of my review. Some metadata is also nice to help tidy things up, like the date I reviewed it, the year the movie came out, and who the director was.
In Markdown, this kind of data is all part of the file’s Frontmatter, a special section at the top of the file. The only exception would be the review’s content, which is just pure Markdown, right below the frontmatter. It looks like this:
---
type: (movie/tv show)
metadata: (year, director, etc)
image: (movie poster)
rating: (my rating)
date: (when I reviewed it)
---
(what I have to say about it)
With just that, I’m able to display it however I want on my site. I added two extra properties that are specific to how I want to display them on my website: theme
, with a light an dark option that mainly control the color of the text, and customBg
, which allows me to set any color I want as the background.
On the Astro side of things, I declared this same schema, so Astro knows what data to look for:
import { z } from 'astro:content';
import { QuickReviewRating, QuickReviewType } from './quick-review-types'; // These are enums that match to what's in Obsidian
export const quickReviewSchema = z.object({
type: z.enum([QuickReviewType.Movie, QuickReviewType.TvShow, QuickReviewType.Game, QuickReviewType.Album]),
metadata: z.string().optional().nullable(),
image: z.string().optional().nullable(),
rating: z.enum([QuickReviewRating.DidntLikeIt, QuickReviewRating.Decent, QuickReviewRating.LikeIt, QuickReviewRating.LovedIt]),
date: z.coerce.date(),
theme: z.enum(['dark', 'light']),
customBg: z.string().optional().nullable()
});
And then, on content.config.ts
, I used that schema in my new Content Collection:
~filename content.config.ts
import { quickReviewSchema } from "@schemas/quick-review";
const quickReviews = defineCollection({
loader: glob({ pattern: "**/*.md", base: "./public/cms/quick-reviews" }),
schema: quickReviewSchema
});
export const collections = { quickReviews };
And with that, I can already use Astro’s getCollection
to fetch and use that data however I want!
This system is only as good as its ease of adding new reviews to. If adding reviews is too much of a hassle, then my lazy self will just stop doing it.
Obsidian has a built-in Template feature that allows you to quickly add a pre-set structure to a file, like the Frontmatter above. That already makes it better, since I can just create a file, apply the template, and just fill the missing fields. However, some steps were particularly annoying.
Finding a movie’s image, year and director usually required either a web search or opening its page in IMDB. That’s not really a big deal, but it’s still annoying to have to make that trip every time I want to write something.
Luckily, Obsidian has a gigantic ecosystem of plugins that can fill any possible niche. There is a community plugin called QuickAdd that adds a bunch of possibilities to templates. And, guess what, the plugin author even has an example of how to setup a template that automatically grabs info from IMDB into a note! I just followed the guide for the Movie & Series script and, voilà, I could have that info in my Quick Reviews in seconds!
I didn’t need all that data on my quick reviews, so I just added the ones I needed to my template. The end result looks like this:
~filename quick-review-template.md
---
type: "{{VALUE:type}}"
metadata: "{{VALUE:Year}}, {{VALUE:director}}"
image: "{{VALUE:Poster}}"
rating:
date: ""
theme: dark
customBg:
---
And this is what the flow looks like:
Honestly, I don’t want this section to be complicated at all. It is above all a place to dump my thoughts about specific pieces of media on. I added some quick filtering for media type, but that’s it. I might revisit the layout of the reviews at some point and maybe add a special RSS feed for them, but besides that, I think I’m done.
Let me know if there’s anything you think would be cool, though. As long as it’s fun, I’m not opposed to it!
2025-06-30 08:00:00
Hey there! Happy Pride 🏳️🌈!
I hope you’re comfortable and keeping chill/warm depending on which side of the world you are. This month, aside from finally launching v5 of my website, I’ve gathered up a few cool links for you to read.
Came across this website on Mastodon and oh wow, it’s so nice! I’ve seen a bunch of websites trying to mimic the old Windows vibes, but this one did it in a way that makes sense. Content is well laid-out and it doesn’t go too far into the “mimicking Windows” aspect.
The Internet Used to Be a Place, by Sarah Davis Baker (video)
Amazing video about the internet we’ve lost (or rather, was taken from us), and how we can rebuild it.
Absolute fan of Sarah’s storytelling here, the way she weaves through the topics and links (hah!) them to that Hypnospace game is amazing!
The New Separation of Concerns, by Brad Frost
I learned about separation of concerns over a decade ago, when I was still learning how to code. On the web side, it would very often be related to what language you were using; HTML is for markup, CSS for styles, JS for interactivity, whatever-backend-language-you-use for business logic. That made sense back then but now the lines have become much blurrier.
Brad Frost goes a bit into what a more modern version of that separation of concerns might look like. I haven’t tried out his course, so I can’t comment on how good it is. But I’m a big fan of his atomic design principles so I’d say it might be a good one!
Web Weekly newsletter, by Stefan Judis
I’ve been subscribed to this newsletter for over a year and it never occurred to me to recommend it here. Stefan Judis does a weekly roundup of web dev-related things and puts them out in a nice, easy-to-read, lighthearted newsletter. It’s been one of my favorites for a while and if you’re reading this, chances are you’ll enjoy his content too!
This is volume 12 of Cool Links, which means I’ve been gathering links like this for a year!
It was the first step in my plan to write more. I figured that by commenting on what other people wrote, I’d feel more comfortable with writing myself. Even though I haven’t actually written more posts here during the last year, I feel like it’s working. I have a few drafts that I haven’t developed enough to post, and some that I just discarded after a bit. But what matters is that I actually wrote something; posting it is just a consequence. 😅
Overall it’s been fun collecting links like these every month, and it’s a way of keeping the spirit of the web alive. It is, after all, a bunch of sites that link to each other. And if at least one person discovers a neat website because of posts like these, then it’s mission accomplished. 🫡
See you next month!
2025-06-29 20:00:00
Jojo Rabbit
2019, Taika Waititi
My rating: Loved it!
A beautiful movie about innocence during a time that wanted nothing but to prey on it. I’d love to say it’s all in the past.
2025-06-28 08:00:00
If you’re reading this and you’re not from a distant future, this means that you are right now on version 5 of fantinel.dev!
Over a year ago, after posting about my blog’s 5th anniversary, I posted about my wish to redesign it. First of all: time flies! I hadn’t realized it was over a year ago. Secondly, it’s finally here! That means it’s been a year of me working on the new design, building it, refining it, and above all, procrastinating!
Of course, I didn’t actually work on it for a year. It’s been a very on-and-off process, mostly off. A lot of things happened during this year and I got busy with work, travel and prepping for a big move (that still didn’t happen). A lot of the free time I had also went into other things I like - mostly videogames. That’s fine! I never want any personal project to be anything more than a hobby. So I don’t feel bad at all for how long it took.
So the biggest chunks of my work on the new website were in short burst of hyperfocusing on it. Focusing can be my superpower quite often. For one or two weeks at a time, I’d wake up thinking about it, have breakfast thinking about it, work thinking about it, and then finally work on it while thinking about it, usually during the evenings. I don’t recall any dreams about the website but I wouldn’t be surprised if that happened.
I think I started working on the design itself right after that blog post, at the end of March/beginning of April, 2024. I started out with something much more similar to what I had before. My initial plan was to use Figma to rebuild what I had, then start experimenting inside the tool.
However, after working on this for a bit, I reflected on what I said on that redesign post:
I want my personal website to reflect a bit of who I am. Am I the same person I was 3-4 years ago?
And the answer is: not really. While I’ve not completely changed as a person, I like to think I’ve improved quite a bit since then. Some tastes changed, a lot of opinions evolved, the hair got whiter, and the back pains are now an almost daily visitor. And more importantly, I got bored of the old design. It was fun for a while but I eventually got tired and felt restricted by it.
As I became an even bigger fan of pastel colors since then, I decided I’d take the colors of my favorite code theme, Catppuccin, and take them for a spin on my new design. I liked it so much that I just decided to use that color palette for everything!
The previous design was built with light mode in mind and then adapted to dark mode. However, I like the dark Catppuccin palette so much that this time I did the opposite: it was designed entirely in dark mode and I only got to work on the light mode after I already started building it. I still want to respect the user’s theme preference above everything, so I don’t default to the dark mode.
Overall, that worked, but to me it’s clear that the dark mode looks much better than the light one. To me, at least. But I’m continuing to tweak light mode here and there whenever I see things I can improve.
I decided to start with just the basics: the home page, the blog archive and the blog post pages. Once I got those to a place I liked, the rest would come naturally.
Once I was satisfied with the design, I let it simmer in my mind for a few months before I started building anything. After coming back to the new design a few months later, I still liked what I saw. Good sign! So it was time to start building it.
However… I’m a web developer. Not just that, web development is my hobby too. So I couldn’t simply implement the new design in the existing project. The horror! Why would I keep using the code that was working well, decently organized and that would save me time?
That’s why @@I rebuilt it from scratch!@@
I had been eyeing Astro for a while, and decided it was worth a shot to at least experiment. I could still reuse the code for my components, since Astro is fully compatible with Svelte. I’d just have to rework the part that did the routing, endpoints, build and data handling. Good thing that was really easy! Astro works similarly to SvelteKit (what I used before) and other popular ones like NextJS. So if you’ve worked with any of them, most of the principles stay the same. Just need a few implementation tweaks here and there.
You see, there was nothing wrong with SvelteKit, which I used before. It is very easy to understand, does a lot of things automatically and builds a really performant website. The thing that drew me to Astro is that it shares a lot of the same principles, but is framework-agnostic. That means I could bring over my Svelte components, which is great, but also that the knowledge I get from using it might be useful if I ever need to build a website that uses React, Vue or, I don’t know, even PHP components. Astro doesn’t care.
Something I noticed while developing is that I imported my Theme Toggle, a Svelte component that uses JavaScript to toggle the current theme into a page. It rendered correctly, but clicking on it wasn’t doing anything.
Turns out, ==Astro does not ship any JavaScript by default==, even from your JS framework components! That is an amazing default behavior, as it encourages progressive enhancement, decreases the size of the website (have you ever seen those 10MB+ NextJS landing pages???) and is just overall a good development pattern. If I really need JavaScript for this component, I have to explicitly add the client
directive to it.
In my case, that theme toggle does actually need JS to work. Which is why it hides itself if JS is not available, only showing up if it has what it needs to work. But some components don’t need JS, they’re just better with JS. The Table of Contents in this blog post is dynamic. As you scroll down it will highlight the current chapter you’re in, and if you’re on mobile it will stick to the bottom of the screen and do its best to get out of your way.
However, at the end of the day it’s still just a table of contents, a collection of anchor links that link to sections of this page. If JS is not available, it shouldn’t break, it shouldn’t hide. It just doesn’t do the dynamic stuff, but it’s still useful by letting you click on it. This is the kind of thought that I always have in mind when building something, and that Astro seems to encourage.
I’ve used Svelte since v3 and loved it. It just made a lot of sense to me, I always vibed with its goals and principles, the performance gains it offered were awesome, and it was always a breath of fresh air to work with it. My previous site was using Svelte 4, which was a refinement over Svelte 3. I loved it.
On this rebuild, I naturally upgraded to Svelte 5, which came out recently. Svelte 5 is a big update, bringing some syntax changes, performance gains, and big things under the hood.
… I’m not sure I like it.
You see, to me what was magical about Svelte is that its syntax was just some sugar on top of JS and HTML. Add a $
character here and there for reactivity, a {#each}
over there for looping over a list of items, and you’re done. Svelte 5 still supports that syntax and it seems to me they will keep supporting it for a while, but they’ve introduced a new syntax in the form of “Runes”. I wanted to give the new stuff I try so I built everything with the new syntax.
After the initial learning curve I got used to it so it’s not a big deal anymore, but the fact that there was a learning curve was a letdown. I still like it better than working with other frameworks, though.
Some notes I took during development:
<slot>s
😭;$props
syntax is way more intuitive than the previous export let
one, although more verbose;I used to use Histoire for developing components in isolation, but it doesn’t seem they support Svelte 5 and development is quite slow for my taste. So, begrudgingly, I started using Storybook for that.
I always have issues setting up Storybook, and it was no different this time. I wrote up an article about my journey to getting it to work.
So, with the redesign now live, what’s next for this website? Hopefully a lot, actually!
You might notice there’s a big “Under construction” banner on the home page, and for good reason: I’m not even close to finishing everything I want to do with it. Honestly, I never will. This is, after all, my playground to experiment with things and do whatever I feel like.
If you want some spoilers, here’s what I think I’ll work on next:
To be honest, I’ll probably come up with something else before I’m done with those three. Who knows?
Thanks for reading it all the way down here! If you’re interested in seeing the code to see how everything works, everything is open source and available on GitHub.