vscodenextjs

Custom filenames in VS Code navbar

When App Router was released in Next.js I was not a big fan of the file structure. I thought that having multiple page.tsx, layout.tsx files make things a bit confusing in the code editor.

In March 2024's release ↗︎, VS Code included a feature that helps labeling the files currently opened in the editor. Here is my customization:

VS Code tabs

"workbench.editor.customLabels.patterns": {
  "**/app/**/page.{tsx,ts,jsx,js,mdx}": "${dirname} [page]",
  "**/app/**/index.{tsx,ts,jsx,js}": "${dirname} [index]",
  "**/app/**/layout.{tsx,ts,jsx,js}": "${dirname} [layout]",
  "**/app/**/template.{tsx,ts,jsx,js}": "${dirname} [template]",
  // For a second level route
  "**/app/**/[[]*[]]/page.{tsx,ts,jsx,js,mdx}": "${dirname(1)}/${dirname} [page]",
  "**/app/**/[[]*[]]/index.{tsx,ts,jsx,js}": "${dirname(1)}/${dirname} [index]",
  "**/app/**/[[]*[]]/layout.{tsx,ts,jsx,js}": "${dirname(1)}/${dirname} [layout]",
  "**/app/**/[[]*[]]/template.{tsx,ts,jsx,js}": "${dirname(1)}/${dirname} [template]",
  // For a third level route
  "**/app/**/[[]*[]]/**/[[]*[]]/page.{tsx,ts,jsx,js,mdx}": "${dirname(2)}/${dirname(1)}/${dirname} [page]",
  "**/app/**/[[]*[]]/**/[[]*[]]/index.{tsx,ts,jsx,js}": "${dirname(2)}/${dirname(1)}/${dirname} [index]",
  "**/app/**/[[]*[]]/**/[[]*[]]/layout.{tsx,ts,jsx,js}": "${dirname(2)}/${dirname(1)}/${dirname} [layout]",
  "**/app/**/[[]*[]]/**/[[]*[]]/template.{tsx,ts,jsx,js}": "${dirname(2)}/${dirname(1)}/${dirname} [template]",
  "**/app/**/route.ts": "${dirname} [route]",
  "**/components/**/index.{tsx,ts,jsx,js}": "${dirname} [component]", 
}

The configuration takes in consideration routes with nested subroutes, for example posts/[id]/page.tsx or posts/[id]/comments/[commentId]/page.tsx. I usually wouldn't expect the third level route labeling being needed, but I included in this micropost as an example of extensibility.

The last line of this config improves the navigability of many projects, especially component libraries: people often organize their components into separated folders and use a index.tsx for the main code (ex: button/index.tsx, modal/index.tsx). The change above will improve how these files are shown in the navbar.

youtube

Building a fake iPhone 15 Pro with an iPhone

Perfect for April Fools:

True story: a good friend of mine bought an iPhone 13 Pro via Facebook Marketplace. They didn't check the phone, everything seemed legit (including the box) and it turns out it was an iPhone X converted to look like an iPhone 13 Pro ↗︎.

The friend returned the phone (the scammer blocked them and we had to find a creative way to meet him) and they got their money back but I was wondered how trick was possible. Now we know.

javascriptcss

Poof

Nobody: ...
Me: remember that poof animation from the Mac OS dock?

.poof {
  width: 128px;
  height: 128px;
  opacity: 0.6;
  background-image: url('https://leonardofaria.net/wp-content/uploads/2024/03/poof.png');
  background-position: 0 0;
  background-repeat: repeat-x;
  animation: poof ease-out 300ms, fade 600ms ease-out 200ms forwards;
}

@keyframes poof {
  0% { background-position: 0 -512px; }
  1% { background-position: 0 -512px; }
  2% { background-position: 0 -512px; }
  3% { background-position: 0 -512px; }
  4% { background-position: 0 -512px; }
  5% { background-position: 0 -512px; }
  6% { background-position: 0 -512px; }
  7% { background-position: 0 -512px; }
  8% { background-position: 0 -512px; }
  9% { background-position: 0 -512px; }
  10% { background-position: 0 -512px; }
  11% { background-position: 0 -512px; }
  12% { background-position: 0 -512px; }
  13% { background-position: 0 -512px; }
  14% { background-position: 0 -512px; }
  15% { background-position: 0 -512px; }
  16% { background-position: 0 -512px; }
  17% { background-position: 0 -512px; }
  18% { background-position: 0 -512px; }
  19% { background-position: 0 -512px; }
  20% { background-position: 0 -384px; }
  21% { background-position: 0 -384px; }
  22% { background-position: 0 -384px; }
  23% { background-position: 0 -384px; }
  24% { background-position: 0 -384px; }
  25% { background-position: 0 -384px; }
  26% { background-position: 0 -384px; }
  27% { background-position: 0 -384px; }
  28% { background-position: 0 -384px; }
  29% { background-position: 0 -384px; }
  30% { background-position: 0 -384px; }
  31% { background-position: 0 -384px; }
  32% { background-position: 0 -384px; }
  33% { background-position: 0 -384px; }
  34% { background-position: 0 -384px; }
  35% { background-position: 0 -384px; }
  36% { background-position: 0 -384px; }
  37% { background-position: 0 -384px; }
  38% { background-position: 0 -384px; }
  39% { background-position: 0 -384px; }
  40% { background-position: 0 -256px; }
  41% { background-position: 0 -256px; }
  42% { background-position: 0 -256px; }
  43% { background-position: 0 -256px; }
  44% { background-position: 0 -256px; }
  45% { background-position: 0 -256px; }
  46% { background-position: 0 -256px; }
  47% { background-position: 0 -256px; }
  48% { background-position: 0 -256px; }
  49% { background-position: 0 -256px; }
  50% { background-position: 0 -256px; }
  51% { background-position: 0 -256px; }
  52% { background-position: 0 -256px; }
  53% { background-position: 0 -256px; }
  54% { background-position: 0 -256px; }
  55% { background-position: 0 -256px; }
  56% { background-position: 0 -256px; }
  57% { background-position: 0 -256px; }
  58% { background-position: 0 -256px; }
  59% { background-position: 0 -256px; }
  60% { background-position: 0 -128px; }
  61% { background-position: 0 -128px; }
  62% { background-position: 0 -128px; }
  63% { background-position: 0 -128px; }
  64% { background-position: 0 -128px; }
  65% { background-position: 0 -128px; }
  66% { background-position: 0 -128px; }
  67% { background-position: 0 -128px; }
  68% { background-position: 0 -128px; }
  69% { background-position: 0 -128px; }
  70% { background-position: 0 -128px; }
  71% { background-position: 0 -128px; }
  72% { background-position: 0 -128px; }
  73% { background-position: 0 -128px; }
  74% { background-position: 0 -128px; }
  75% { background-position: 0 -128px; }
  76% { background-position: 0 -128px; }
  77% { background-position: 0 -128px; }
  78% { background-position: 0 -128px; }
  79% { background-position: 0 -128px; }
  80% { background-position: 0 0; }
  81% { background-position: 0 0; }
  82% { background-position: 0 0; }
  83% { background-position: 0 0; }
  84% { background-position: 0 0; }
  85% { background-position: 0 0; }
  86% { background-position: 0 0; }
  87% { background-position: 0 0; }
  88% { background-position: 0 0; }
  89% { background-position: 0 0; }
  90% { background-position: 0 0; }
  91% { background-position: 0 0; }
  92% { background-position: 0 0; }
  93% { background-position: 0 0; }
  94% { background-position: 0 0; }
  95% { background-position: 0 0; }
  96% { background-position: 0 0; }
  97% { background-position: 0 0; }
  98% { background-position: 0 0; }
  99% { background-position: 0 0; }
  100% { background-position: 0 0; }  
}

@keyframes fade {
  from { opacity: 0.6; }
  to { opacity: 0; }
}


This animation would be great in a list of tags with a delete button. The delete button would trigger the animation and remove the item from the DOM. My pen in Codepen

book

My 2023 in books

What I read

Via Goodreads

When I was a child, I read a lot of books. I won (twice) a certificate from the mayor when I was 12 because I was one of the top readers from the only city library. Ironically, I also won a soccer ball from my school for the same reason.

Since learning programming, I have slowly decreased the number of books I read, but I am pretty happy with my books this year. My favourite topics these days are engineering, relationships, and psychology.

Earlier this year I posted about The Myth of Normal and after finishing this one I moved to When the Body Says No: The Cost of Hidden Stress. This book is already 20 years old, and we still don't see much of the concept of the body as a holistic organism, as Gabor Maté covers in the book.

How to Not Die Alone was an interesting read for me. I didn't know Logan Ury until seeing her in The Diary of a CEO and her interview convinced me to get the book

The book mixes a bit of behaviour science with dating and relationships, covering different stages of a person's life, from where/how to meet people to how to break up/marry someone.

Win Every Argument: The Art of Debating, Persuading, and Public Speaking focuses a lot on formal debates, using several examples from the British Parliament and American politicians. That said, the book is still helpful for anyone who wants to improve their communication skills or understand better how Ad Hominem works or how Trump dominates media and opponents in debates. Sidenote: This review on Goodreads has a good summary of the book.

The Righteous Mind: Why Good People Are Divided by Politics and Religion is my most recent read. Jonathan Haidt has several books about psychology and a very good newsletter covering, between many other topics, the impact of social media in teenagers.

Haidt shares research on how moral views are based on six factors (Care/Harm, Liberty/Oppression, Fairness/Cheating, Loyalty/Betrayal, Authority/Subversion, Sanctity/Degradation) and how people with different political views (liberal, conservative, libertarian, etc) have different weights for each factor. Using Americans as an example, he shows that liberals focus more on the first three moral factors while conservatives draw from all six. This book helps us understand how people vote based on their morals and not their interests, which is something that Democrats (or left-leaning people in general) don't understand, and that is why they are often surprised by the results of elections.

meta

New website behind the scenes

Last December I moved this website from Hugo to Next.js - hoping to write more - and in this micropost I'll share some quirks and features of this version. I also created a colophon page for the website.

🧨 TNT stack

I started the work by porting my Bento Hugo theme ↗︎ to Next.js (or TNT stack: TypeScript, Next.js, and Tailwind CSS), changing some design elements when possible.

ContentLayer

As I mentioned in the migration post, Contentlayer gave me MDX and TypeScript support simultaneously. With ContentLayer I was able to have more control of Markdown content, by injecting Tailwind CSS classes and then modifying the design of specific elements (ex. show YouTube videos wider than the text content).

Vercel Analytics

I have been using Umami for a while as a Google Analytics alternative but since I moved to Vercel, I decided to use their Analytics product, based on Splitbee ↗︎. It seems their Analytics can track more visitors than Umami - since it is not getting blocked by Adblockers - but I am still keeping Umami around. The reason is that Vercel acquired Splitbee last October and they say Analytics is "free while in beta" so I'm afraid this can become an upsell feature.

Sandpack

One advantage of having a blog built with React is that I can share code using Sandpack. I still want to make this editor prettier and more functional like Josh ↗︎, but it might not be that soon.

Design

I learned one or two things about design with this work - I know blobs are trending and I used a online generator ↗︎ to give my profile photo a nice touch. I also used a tool ↗︎ for the blurry gradient background image. I am also using React Wrap Balancer ↗︎ for better-looking titles.

Segmented Control

Segmented Control ↗︎ is a type of button group used in iOS. I found an implementation in Vue and Tailwind CSS ↗︎ and I ported it to React.

Fira Code

Since I'm using Fira Code in my VS Code and iTerm and I enjoy fonts with ligatures, I added it here using @next/font ↗︎. Doesn't know what are ligatures? Here is a sample:

# from https://github.com/tonsky/FiraCode/blob/master/extras/showcases.txt
      .= ..= := ::= =:= __
     == != === !== =/= =!=
<-< <<- <-- <- <-> -> --> ->> >->
        <~~ <~ ~~ ~> ~~>
     <<< << <= <> >= >> >>>
      </ <!--  </>  --> />
      0xF www Fl Tl Il fi fj

Animations and Parallax(es)

I want to use this website as an experiment center for animations and parallaxes (is that the right plural?). I initially thought about using AOS ↗︎ (something similar to the old wow.js ↗︎ but I might just stick with Framer Motion ↗︎. Parallax-wise, there are a few things with react-scroll-parallax, that I still want to improve.

Conclusion

I spent a lot of time on this website :D

bookreview

The Myth of Normal

“Trauma is perhaps the most avoided, ignored, belittled, denied, misunderstood, and untreated cause of human suffering.” - I recently finished reading The Myth of Normal ↗︎, from also Vancouverite Dr Gabor Maté.

Book and a snack

In the book, Dr Maté talks about how trauma is neglected by ourselves and our western medicine and how it impacts our body. It is a reflection about treatments that fix what is hurting today but it doesn't necessarily heal the core issue of the problem. By mentioning different real-life examples - including his own early childhood in Hungary during WWII - and research, the author provokes the reader to self-reflect on their own pain.

It is a long book and there were times that I thought the reading was too negative or too triggering but it is worth reading. It is a relevant book to the world after-2020. If you are intrigued by the book, check out one of his many interviews on YouTube, including this one:

off-topic

5 years of Wakatime

WakaTime is a plugin you install in your IDE that tracks your code stats. For the last five years I've been using the plugin and here are some fun stats:

WakaTime stats

The chart above is dynamic and it reflects my all-time activity. WakaTime also offers badges with your total time tracking or project-specific time traking. Here they are:

wakatime

wakatime

Does it matter? Nope, but it is fun to see how you spend your time over the years - and please don't make it use CoffeeScript again.

review

Luna Display review

I recently got a Luna Display ↗︎ for a reasonable price, and I really like it. This small review highlights the pros and cons, so you can decide if it is worth a shot.

My Mac with Luna

Luna Display is a small USB-C (or HDMI or Mini display port) dongle you connect to your host computer (Windows/Mac), and in another Mac or iPad, you install their app, which enables the device as a second screen. Apple released Sidecar ↗︎, transforming an iPad into a second display wirelessly. This is good, but Sidecar has two limitations: 1) it only works with iPads as second displays, and 2) both devices need to be connected to the same iCloud account. The second reason blocks you from using a work computer with your iPad.

Luna fixes the limitations above. It can be helpful if you carry two laptops around, enabling one to be a second screen, or it can help you use an old iMac as a second screen while you can still use the computer if needed. Also, if you are using an iPad as a second screen, you can connect it to USB, not requiring you to use wifi while keeping your iPad device charged.

One minor thing I wish that would be possible was to use the iPad camera as a macOS camera, like Epoccam ↗︎ or the recently released Continuity Camera ↗︎ do.

javascript

Using Sandpack, your custom CodeSandbox

For a while I wanted to embed code with previews in a good way in this website. I finally spent a couple of hours adding Sandpack ↗︎ to it.

export default function App() { 
  return (
    <>
      <h1>VANCOUVER</h1>
      <h2>CANADA</h2>
    </>
  );
};

Sandpack is the playground used by CodeSandbox ↗︎. It uses different templates (react, react-ts, vue, vanilla, etc) and it supports different themes (I'm a big fan of the GitHub light theme).

I am not going to write a tutorial about adding Sandpack in a React app because Joshua Comeau ↗︎ and Chris Nicholas ↗︎ already did a great job showing how to interact with the components. Their posts were very helpful to add to the good documentation of the project. Despite not writing a tutorial, I can still show what I did if you check this website repository. Or you can read the Pull Request.

I initially thought in creating something more elaborated with resizable panels ↗︎ and custom toolbars like Joshua did but I ended up with something smaller.

inspiration

Fast

A good inspiration ↗︎ on ambitious projects:

iPod. Tony Fadell was hired to create the iPod in late January 2001. Steve Jobs greenlit the project in March 2001. They hired a contract manufacturer in April 2001, announced the product in October 2001, and shipped the first production iPod to customers in November 2001, around 290 days after getting started. Source: Tony Fadell.

COVID-19 vaccines. On January 10 2020, the SARS-CoV-2 genome was published ↗︎. 3 days later, Moderna finalized ↗︎ the sequence for mRNA-1273 ↗︎, its mRNA vaccine candidate; the first batch was manufactured on February 7. On February 24 (45 days after genome publication), Moderna shipped the first batch of mRNA-1273 to the NIH for use in their Phase 1 clinical study. 266 days of clinical trials and regulatory coordination followed. On November 16, Moderna announced ↗︎ that the vaccine's efficacy was 94.5%. Source: linked materials. Note: the BioNTech vaccine was produced on a similarly impressive timeline but I haven't yet tracked down sufficiently granular information about its development—pointers appreciated.