As a way to learn React and exercise Typescript, I started building a recipe database application using PostgreSQL as the database, Express as the API server, and Vite/React as the client. This post will cover notes, observtions, design decisions and challenges I've faced while building the application. Why these tools? Before we start with specifics, let's talk about the tools I've chosen for this project: PostgreSQLhttps://www.postgresql.org/ is powerful, open-source, and has great support for JSON data types, which is useful for storing recipe data. I chose to use Prismahttps://www.prisma.io/ as the Object Relational Mappinghttps://www.freecodecamp.org/news/what-is-an-orm-the-meaning-of-object-relational-mapping-database-tools/ ORM because it provides a type-safe...
Temporal is a new API designed to handle dates and times in Javascript. It is designed as a replacement for the existing Date API, without taking over the Date namespace. Unfortunately, it is not yet available in all browsers, so we need to dynamically load it when it is not natively available. This post will explore how to dynamically load the Temporal API in a web application. It will also cover a subtlety in feature detection and how to use the temporal API once it's loaded. The problem I like the Temporal API better than the existing Date one so...
Homebrew is a powerful package manager for macOS that simplifies the installation and management of software. Migrating your Homebrew setup to a new Mac can be an easy process if you follow the right steps. This post will cover the steps to migrate your Homebrew setup from an old Mac to a new one, including how to create a Brewfile, and how to use it to restore your setup on the new machine. Migrating Homebrew to a New Mac: A Seamless Transition You can seamlessly transfer your entire Homebrew environment — from command-line utilities like git and node to GUI...
Managing monorepos, a single repository with multiple packages each with its own package.json and dependencies, can be challenging. This is where NPM workspaces come in. This post will cover what are NPM workspaces, how to use them, how they compare with Yarn and PNPM workspaces and how they interact with monorepo tools like Lerna and Nx. What are workspaces? NPM workspaces are a feature built into the npm CLI that allows you to manage multiple distinct packages from within a single, top-level root package. It's the native solution for creating a monorepo. You define a workspace by adding a workspaces...
I recently read two post that got me thinking about the value of learning a web development framework. These posts also align with my own experiences and thoughts on the subject. This post will explore my experiences, why I think learning a framework may be beneficial, and when do we learn to reach beyond frameworks and back to web standards. My Experience I've finally started to learn Reacthttps://react.dev/ and I can see the value in learning a framework but the value is tempered by the assumptions we all make when learning the framework. The Assumptions I see What do I...
One of my biggest frustrations in Node.js development is when your project works on your machine but breaks somewhere else. A common cause is package inconsistency between environments, even with a package.json file. Updating, removing, or installing packages can lead to a nodemodules directory that doesn't perfectly match what's defined. The standard fix — deleting nodemodules and package-lock.json before running npm install again — is cumbersome. This is the exact problem npm ci for clean install was designed to solve. This post will explain what npm ci is, how it differs from npm install, and how to use it effectively...
List comprehensions in Python allow you to create new lists by applying an expression to each item in an existing iterable, optionally filtering items based in a condition. I've always missed this feature in Javascript and later Typescript, but it wasn't until recently that I discovered there is a way to achieve similar array methods that are native to Javascript and available in Typescript. This post will explain list comprehensions in Python, and how they can be replicated in Typescript using the map and filter array methods. While there isn't a direct syntactic equivalent to Python's list comprehension in Typescript,...
One of the biggest pain in working with Node.js is dealing with dependency vulnerabilities that you can't fix because they are in a transitive dependency a dependency of your direct dependencies. This is where the overrideshttps://docs.npmjs.com/cli/v11/configuring-npm/package-jsonoverrides feature in npm comes to the rescue. This post will look at overrides, how they work, how you can use them to fix security audit issues, and What Are Overrides? Overrides allow you to install a specific version of a transitive dependency, providing a temporary fix for security audit issues, that you have no control over. You could brute force a fix by running...
Since the first CSS specification, web developers were limited to a handful of ways to define colors in the sRGB color space. With the finalization of the CSS Color Module Level 4https://www.w3.org/TR/css-color-4/ and the ongoing development of Level 5https://www.w3.org/TR/css-color-5/, we now have access to a vastly expanded universe of color, along with powerful tools to manipulate and mix them. This post will cover the new color spaces, functions, and syntaxes, with a focus on what's available, how to mix colors, and when to use each color space. What Colors Are Available? CSS now supports a wide range of color notations....
Top-level await in Javascript allows developers to use the await keyword at the top level of a module, outside of an async function. This simplifies code by enabling modules to act as if they are large async functions, making it easier to work with asynchronous operations like fetching data, connecting to databases, or initializing dependencies. How Top-Level await Works in Javascript Before top-level await, if you needed to perform an asynchronous operation within a module's initial execution, you had to wrap it in an async immediately invoked function expression IIFEhttps://developer.mozilla.org/en-US/docs/Glossary/IIFE, or use promise chaining with .then. This could make the...