Tari Ibaba

Tari Ibaba is a software developer with years of experience building websites and apps. He has written extensively on a wide range of programming topics and has created dozens of apps and open-source libraries.

This is how functional try-catch transforms your JavaScript code

How common is this?

JavaScript
function writeTransactionsToFile(transactions) { let writeStatus; try { fs.writeFileSync('transactions.txt', transactions); writeStatus = 'success'; } catch (error) { writeStatus = 'error'; } // do something with writeStatus... }

It’s yet another instance where we want a value that depends on whether or not there’s an exception.

Normally, you’d most likely create a mutable variable outside the scope for error-free access within and after the try-catch.

But it doesn’t always have to be this way. Not with a functional try-catch.

A pure tryCatch() function avoids mutable variables and encourages maintainability and predictability in our codebase. No external states are modified – tryCatch() encapsulates the entire error-handling logic and produces a single output.

Our catch turns into a one-liner with no need for braces.

JavaScript
function writeTransactionsToFile(transactions) { // 👇 we can use const now const writeStatus = tryCatch({ tryFn: () => { fs.writeFileSync('transactions.txt', transactions); return 'success'; }, catchFn: (error) => 'error'; }); // do something with writeStatus... }

The tryCatch() function

So what does this tryCatch() function look like anyway?

From how we used it above you can already guess the definition:

JavaScript
function tryCatch({ tryFn, catchFn }) { try { return tryFn(); } catch (error) { return catchFn(error); } }

To properly tell the story of what the function does, we ensure explicit parameter names using an object argument – even though there are just two properties.

Because programming isn’t just a means to an end — we’re also telling a story of the objects and data in the codebase from start to finish.

TypeScript is great for cases like this, let’s see how a generically typed tryCatch() could look like:

TypeScript
type TryCatchProps<T> = { tryFn: () => T; catchFn: (error: any) => T; }; function tryCatch<T>({ tryFn, catchFn }: TryCatchProps<T>): T { try { return tryFn(); } catch (error) { return catchFn(error); } }

And we can take it for a spin, let’s rewrite the functional writeTransactionsToFile() in TypeScript:

JavaScript
function writeTransactionsToFile(transactions: string) { // 👇 returns either 'success' or 'error' const writeStatus = tryCatch<'success' | 'error'>({ tryFn: () => { fs.writeFileSync('transaction.txt', transactions); return 'success'; }, catchFn: (error) => return 'error'; }); // do something with writeStatus... }

We use the 'success' | 'error' union type to clamp down on the strings we can return from try and catch callbacks.

Asynchronous handling

No, we don’t need to worry about this at all – if tryFn or catchFn is async then writeTransactionToFile() automatically returns a Promise.

Here’s another try-catch situation most of us should be familiar with: making a network request and handling errors. Here we’re setting an external variable (outside the try-catch) based on whether the request succeeded or not – in a React app we could easily set state with it.

Obviously in a real-world app the request will be asynchronous to avoid blocking the UI thread:

JavaScript
async function comment(comment: string) { type Status = 'error' | 'success'; let commentStatus; try { const response = await fetch('https://api.mywebsite.com/comments', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ comment }), }); if (!response.ok) { commentStatus = 'error'; } else { commentStatus = 'success'; } } catch (error) { commentStatus = 'error'; } // do something with commentStatus... }

Once again we have to create a mutable variable here so it can go into the try-catch and come out victoriously with no scoping errors.

We refactor like before and this time, we async the try and catch functions thereby awaiting the tryCatch():

JavaScript
async function comment(comment: string) { type Status = 'error' | 'success'; // 👇 await because this returns Promise<Status> const commentStatus = await tryCatch<Status>({ tryFn: async () => { const response = await fetch<('https://api.mywebsite.com/comments', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ comment }), }); // 👇 functional conditional return response.ok ? 'success' : 'error'; }, catchFn: async (error) => 'error'; }); // do something with commentStatus... }

Readability, modularity, and single responsibility

Two try-catch rules of thumb to follow when handling exceptions:

  1. The try-catch should be as close to the source of the error as possible, and
  2. Only use one try-catch per function

They will make your code easier to read and maintain in the short- and long-term.

Look at processJSONFile() here, it respects rule 1. The 1st try-catch is solely responsible for handling file-reading errors and nothing else. No more logic will be added to try, so catch will also never change.

And next try-catch in line is just here to deal with JSON parsing.

JavaScript
function processJSONFile(filePath) { let contents; let jsonContents; // First try-catch block to handle file reading errors try { contents = fs.readFileSync(filePath, 'utf8'); } catch (error) { // log errors here contents = null; } // Second try-catch block to handle JSON parsing errors try { jsonContents = JSON.parse(contents); } catch (error) { // log errors here jsonContents = null; } return jsonContents; }

But processJsonFile() completely disregards rule 2, with both try-catch blocks in the same function.

So let’s fix this by refactoring them to their separate functions:

JavaScript
function processJSONFile(filePath) { const contents = getFileContents(filePath); const jsonContents = parseJSON(contents); return jsonContents; } function getFileContents(filePath) { let contents; try { contents = fs.readFileSync(filePath, 'utf8'); } catch (error) { contents = null; } return contents; } function parseJSON(content) { let json; try { json = JSON.parse(content); } catch (error) { json = null; } return json; }

But we have tryCatch() now – we can do better:

JavaScript
function processJSONFile(filePath) { return parseJSON(getFileContents(filePath)); } const getFileContents = (filePath) => tryCatch({ tryFn: () => fs.readFileSync(filePath, 'utf8'), catchFn: () => null, }); const parseJSON = (content) => tryCatch({ tryFn: () => JSON.parse(content), catchFn: () => null, });

We’re doing nothing more than silencing the exceptions – that’s the primary job these new functions have.

If this occurs frequently, why not even create a “silencer” version, returning the try function’s result on success, or nothing on error?

JavaScript
function tryCatch<T>(fn: () => T) { try { return fn(); } catch (error) { return null; } }

Further shortening our code to this:

JavaScript
function processJSONFile(filePath) { return parseJSON(getFileContents(filePath)); } const getFileContents = (filePath) => tryCatch(() => fs.readFileSync(filePath, 'utf8')); const parseJSON = (content) => tryCatch(() => JSON.parse(content));

Side note: When naming identifiers, I say we try as much as possible to use nouns for variables, adjectives for functions, and… adverbs for higher-order functions! Like a story, the code will read more naturally and could be better understood.

So instead of tryCatch, we could use silently:

JavaScript
const getFileContents = (filePath) => silently(() => fs.readFileSync(filePath, 'utf8')); const parseJSON = (content) => silently(() => JSON.parse(content));

If you’ve used @mui/styles or recompose, you’ll see how a ton of their higher-order functions are named with adverbial phrases — withStyles, withState, withProps, etc., and I doubt this was by chance.

Final thoughts

Of course try-catch works perfectly fine on its own.

We aren’t discarding it, but transforming it into a more maintainable and predictable tool. tryCatch() is even just one of the many declarative-friendly functions that use imperative constructs like try-catch under the hood.

If you prefer to stick with direct try-catch, do remember to use the 2 try-catch rules of thumb, to polish your code with valuable modularity and readability enhancements.

?? vs || in JavaScript: The little-known difference

At first glance you think you can just swap in anyone you like right?

JavaScript
let fastest = undefined; console.log(fastest ?? 'The Flash⚡'); // The Flash⚡ console.log(fastest || 'The Flash⚡'); // The Flash⚡

Wrong. They’re not what you think.

And we must learn the difference once and for all to avoid painful bugs down the line.

And what’s this difference?

It’s the incredible contrast in how they treat truthy and falsy values.

What are these?

Falsy: becomes false in a Boolean() or if:

  • 0
  • undefined
  • null
  • NaN
  • false
  • '' (empty string)

Truthy: every single thing else:

Now see what happens when you create a || chain like this:

JavaScript
const fruit = undefined || null || '' || 'banana🍌'; const color = '' || 'red🔴' || null; const num = 0 || NaN || 100 || false; console.log(fruit); // 'banana🍌' console.log(color); // 'red🔴 console.log(num); // 100

It keeps going until it hits the first truthy!

But what about a ?? chain? 👇

JavaScript
const fruit = undefined ?? null ?? '' ?? 'banana🍌'; const color = '' ?? 'red🔴' ?? null; const num = 0 ?? NaN ?? 100 ?? false; console.log(fruit); // '' (empty string) console.log(color); // '' console.log(num); // 0

Do you see the clear difference?

One looks for truthy, the other looks for anything that isn’t null or undefined.

When to use ?? vs ||

Initializing extra lives in a video game, where 0 means something?

?? 👇

JavaScript
const data = loadData(); const player = initPlayer(data); function initPlayer({ extraLives }) { const extraLives = extraLives ?? 20; console.log(`Player extra lives: ${extraLives}`); }

Paginating a response, where 0 limit makes no sense?

|| 👇

JavaScript
function paginate(options = {}) { return ['a', 'b', 'c', 'd', 'e'].splice(0, options.limit || 3); } paginate(1); // Output: ['a'] paginate(); // Output: ['a', 'b', 'c'] paginate(0); // Output: ['a', 'b', 'c']

User must have a name, so no spaces and definitely no empty strings?

|| 👇

JavaScript
function getUsername(userInput) { return userInput || 'Guest'; } function getProfilePic(userInput) { return userInput || 'profile-pic.png'; }

Did the user enter an invalid number or did they enter a number at all?

Find out with ?? 👇

JavaScript
function getUserAge(input) { if (!input) { return null; } else { return Number(input); } } console.log(getUserAge('') ?? '❌'); console.log(getUserAge('314') ?? '❌'); console.log(getUserAge('green🟢') ?? '❌');

?? and ?. are friends

Is someone there? not null or undefined?

Yes:

  • ?? — alright I’m done here
  • ?. — So let’s check out what you’ve gone

No:

  • ?? — So who’s next?
  • ?. — Um… bye!
JavaScript
console.log(''?.length); // 0 console.log('' ?? '❌'); // '' console.log('Tari Ibaba'?.length); // 10 console.log('Tari Ibaba' ?? '❌'); // 'Tari Ibaba' console.log(null?.length); // undefined console.log(null ?? '❌'); // '❌' console.log(undefined?.length); // undefined console.log(undefined ?? '❌'); // '❌'

Final thoughts

?? is a gullible child who will believe anything.

|| is a detective in search of the truthy and nothing but the truthy.

5 amazing new JavaScript features in ES15 (2024)

2024: Another incredible year of brand new JS feature upgrades with ES15.

From sophisticated async features to syntactic array sugar and modern regex, JavaScript coding is now easier and faster than ever.

1. Native array group-by is here

Object.groupBy():

JavaScript
const fruits = [ { name: 'pineapple🍍', color: '🟡' }, { name: 'apple🍎', color: '🔴' }, { name: 'banana🍌', color: '🟡' }, { name: 'strawberry🍓', color: '🔴' }, ]; const groupedByColor = Object.groupBy( fruits, (fruit, index) => fruit.color ); console.log(groupedByColor);

Literally the only thing keeping dinosaur Lodash alive — no more!

I was expecting a new instance method like Array.prototype.groupBy but they made it static for whatever reason.

Then we have Map.groupBy to group with object keys:

JavaScript
const array = [1, 2, 3, 4, 5]; const odd = { odd: true }; const even = { even: true }; Map.groupBy(array, (num, index) => { return num % 2 === 0 ? even: odd; }); // => Map { {odd: true}: [1, 3, 5], {even: true}: [2, 4] }

Almost no one ever groups arrays this way though, so will probably be far less popular.

2. Resolve promise from outside — modern way

With Promise.withResolvers().

It’s very common to externally resolve promises and before we had to do it with a Deferred class:

JavaScript
class Deferred { constructor() { this.promise = new Promise((resolve, reject) => { this.resolve = resolve; this.reject = reject; }); } } const deferred = new Deferred(); deferred.resolve();

Or install from NPM — one more dependency.

But now with Promise.withResolvers():

JavaScript
const { promise, resolve, reject } = Promise.withResolvers();

See how I use it to rapidly promisify an event stream — awaiting an observable:

JavaScript
// data-fetcher.js // ... const { promise, resolve, reject } = Promise.withResolvers(); export function startListening() { eventStream.on('data', (data) => { resolve(data); }); } export async function getData() { return await promise; } // client.js import { startListening, getData } from './data-fetcher.js'; startListening(); // ✅ listen for single stream event const data = await getData();

3. Buffer performance upgrades

Buffers are tiny data stores to store temporary data your app generates.

They make it incredible easy to transfer and process data across various stages in a pipeline.

Pipelines like:

  • File processing: Input file buffer process new buffer output file
  • Video streaming: Network response buffer display video frame
  • Restaurant queues: Receive customer queue/buffer serve customer
JavaScript
const fs = require('fs'); const { Transform } = require('stream'); const inputFile = 'input.txt'; const outputFile = 'output.txt'; const inputStream = fs.createReadStream(inputFile, 'utf-8'); const transformStream = new Transform({ transform(chunk) { // ✅ tranform chunks from buffer }, }); const outputStream = fs.createWriteStream(outputFile); // ✅ start pipeline inputStream.pipe(transformStream).pipe(outputStream);

With buffers, each stage process data at different speeds independent of each other.

But what happens when the data moving through the pipeline exceeds the buffers capacity?

Before we’d have to copy all the current data’s buffer to a bigger buffer.

Terrible for performance, especially when there’s gonna be a LOT of data in the pipeline.

ES15 gives us a solution to this problem: Resizable array buffers.

JavaScript
const resizableBuffer = new ArrayBuffer(1024, { maxByteLength: 1024 ** 2, }); // ✅ resize to 2048 bytes resizableBuffer.resize(1024 * 2);

4. Asynchronous upgrades

Atomics.waitAsync(): Another powerful async coding feature in ES2024:

It’s when 2 agents share a buffer…

And agent 1 “sleeps” and waits for agent 2 to complete a task.

When agent 2 is done, it notifies using the shared buffer as a channel.

JavaScript
const sharedBuffer = new SharedArrayBuffer(4096); const bufferLocation = new Int32Array(sharedBuffer); // ✅ initial value at buffer location bufferLocation[37] = 0x1330; async function doStuff() { // ✅ agent 1: wait on shared buffer location until notify Atomics.waitAsync(bufferLocation, 37, 0x1330).then((r) => {} /* handle arrival */); } function asyncTask() { // ✅ agent 2: notify on shared buffer location const bufferLocation = new Int32Array(sharedBuffer); Atomics.notify(bufferLocation, 37); }

You’d be absolutely right if you thought this similar to normal async/await.

But the biggest difference: The 2 agents can exist in completely different code contexts — they only need access to the same buffer.

And: multiple agents can access or wait on the shared buffer at different times — and any one of them can notify to “wake up” all the others.

It’s like a P2P network. async/await is like client-server request-response.

JavaScript
const sharedBuffer = new SharedArrayBuffer(4096); const bufferLocation = new Int32Array(sharedBuffer); bufferLocation[37] = 0x1330; // ✅ received shared buffer from postMessage() const code = ` var ia = null; onmessage = function (ev) { if (!ia) { postMessage("Aux worker is running"); ia = new Int32Array(ev.data); } postMessage("Aux worker is sleeping for a little bit"); setTimeout(function () { postMessage("Aux worker is waking"); Atomics.notify(ia, 37); }, 1000); }`; async function doStuff() { // ✅ agent 1: exists in a Worker context const worker = new Worker( 'data:application/javascript,' + encodeURIComponent(code) ); worker.onmessage = (event) => { /* log event */ }; worker.postMessage(sharedBuffer); Atomics.waitAsync(bufferLocation, 37, 0x1330).then( (r) => {} /* handle arrival */ ); } function asyncTask() { // ✅ agent 2: notify on shared buffer location const bufferLocation = new Int32Array(sharedBuffer); Atomics.notify(bufferLocation, 37); }

5. Regex v flag & set operations

A new feature to make regex patters much more intuitive.

Finding and manipulating complex strings using expressive patterns — with the help of set operations:

JavaScript
// A and B are character class, like [a-z] // difference: matches A but not B [A--B] // intersection: matches both A & b [A&&B] // nested character class [A--[0-9]]

To match ever-increasing sets of Unicode characters, like:

  • Emojis: 😀, ❤️, 👍, 🎉, etc.
  • Accented letters: é, à, ö, ñ, etc.
  • Symbols and non-Latin characters: ©, ®, €, £, µ, ¥, etc

So here we use Unicode regex and the v flag to match all Greek letters:

JavaScript
const regex = /[\p{Script_Extensions=Greek}&&\p{Letter}]/v;

Final thoughts

Overall ES15 is significant leap for JavaScript with several features essential for modern development.

Empowering you to write cleaner code with greater conciseness, expressiveness, and clarity.

structuredClone(): The easiest way to deep copy objects in JavaScript

Deep copying is a regular programming task for passing or storing data.

  • Shallow copy: Only copies the first level of the object
  • Deep copy: Copies all levels of the object
JavaScript
const obj = { name: 'Tari', friends: [{ name: 'Messi'}]}; const shallowCopy = { ...obj }; const deepCopy = dCopy(obj); console.log(obj.friends === shallowCopy.friends); // ❌ true console.log(obj.friends === deepCopy.friends); // ✅ false

But all this while we’ve never had a built-in way to perfectly deep copy objects and it’s been a pain.

We always had to lean on third-party libraries for deep copying and keeping circular references.

All that changes now with the new structuredClone() — an easy and efficient way to deep copy any object.

JavaScript
const obj = { name: 'Tari', friends: [{ name: 'Messi' }] }; const clonedObj = structuredClone(obj); console.log(obj.name === clonedObj); // false console.log(obj.friends === clonedObj.friends); // false

Cloning circular references with ease:

JavaScript
const car = { make: 'Toyota', }; // 👉 Circular reference car.basedOn = car; const cloned = structuredClone(car); console.log(car.basedOn === cloned.basedOn); // false // 👇 Circular reference is cloned console.log(car === car.basedOn); // true

Something you could never do with the JSON stringify/parse hack:

Go as deep as you want:

JavaScript
// ↘️ const obj = { a: { b: { c: { d: { e: 'Coding Beauty', }, }, }, }, }; const clone = structuredClone(obj); console.log(clone.a.b.c.d === obj.a.b.c.d); // ✅ false console.log(clone.a.b.c.d.e); // Coding Beauty

Limitations you should know

structuredClone() is very powerful but it has important weaknesses you should know:

Can’t clone functions or methods

Because of the special algorithm it uses.

Can’t clone DOM elements

Doesn’t preserve RegExp lastIndex property

I mean, no one’s cloning regexes but it’s one to note:

JavaScript
const regex = /beauty/g; const str = 'Coding Beauty: JS problems are solved at Coding Beauty'; console.log(regex.index); console.log(regex.lastIndex); // 7 const regexClone = structuredClone(regex); console.log(regexClone.lastIndex); // 0

Other limitations

Important to be aware of them to avoid unexpected behavior when using the function.

Clone some, move

This is a more sophisticated one.

You transfer inner objects from source to clone instead of copying.

Which means there’s nothing left in source to change:

JavaScript
const uInt8Array = Uint8Array.from({ length: 1024 * 1024 * 16 }, (v, i) => i); const transferred = structuredClone(uInt8Array, { transfer: [uInt8Array.buffer], }); console.log(uInt8Array.byteLength); // 0

Overall structuredClone() is a valuable addition to a developer’s toolkit and makes object cloning easier than ever in JavaScript

How to guarantee a coding job by writing the perfect cover letter

So who told you nobody reads cover letters?!

If you really believe that then prepare for a massive shock…

83% of hiring managers absolutely DO read cover letters.

And they’re not just skimming through — 60% of hiring managers spend at least 2 minutes reading your resume!

Cover letters are the unique selling point that gets you chosen over people with dangerously similar qualifications.

Learn the perfect to write them once and stand out in every job application. Every job platform: Upwork, Indeed, and so much more.

Blind mass applying leads to failure

Don’t behave like those irritating email spammers.

Sending the same old generic message to thousands of addresses hoping for 2 replies.

Your cover letter needs to be personalized to:

  • The job description
  • The company’s mission and values.

It shows you’re genuinely interested.

Make sure to include these gems

1. Attention-grabbing intro

If you mess up the intro everything that follows is automatically worthless.

Get straight to the point without using so much formal baggage.

Recommended: Quickly state your niche and intentions to “learn more” about the company 😉

Example:

I’m a passionate full-stack web developer with over 6 years of experience interested in learning more about the Coding Beauty team.

2. What have you achieved recently?

Solutions before features.

Recruiters care more about concrete real-world achievements than the dry technical details behind them.

Example — for the full-stack web developer role:

Over the past 3 years, I helped my company generate over $2 million in additional revenue by spearheading the development a new e-commerce web platform.

Wow, amazing achievement! Who is this guy?

Then leading up to your experience, you say:

And now I’m thrilled to continue my journey by contributing and growing with Coding Beauty. These are three things that make me a perfect fit for this position:

3. Experience

Alright, I’m now much more curious to see the skills & experience you gained to help you reach such majestic heights:

Firstly, at XYZ Corp, I spearheaded the migration from AngularJS to React, enhancing the user experience and improving performance by 30%. My focus was on creating reusable components, which streamlined the development process and fostered collaboration. I believe in writing clean, maintainable code and mentoring junior developers, which I did by conducting weekly code reviews and workshops.

Secondly, while at ABC Solutions, I led a project to integrate a Node.js backend with a MongoDB database, reducing data retrieval times by 50%. I am passionate about efficient architecture and robust security practices, which I implemented by designing a comprehensive API and setting up automated testing, ensuring a seamless and secure application.

Notice how they state something about themselves in relation to the experience they gained in both cases.

Making it unique to the individual — rather than some random generic rambling no one cares about.

4. Why this company?

Why do you want to work here?

Show how you resonate with the mission and values of the company:

Example:

Finally, I’m drawn to Coding Beauty’s mission because it aligns perfectly with my belief in empowering developers to reach their fullest potential. By fostering personal growth, promoting the enjoyment of coding, and facilitating avenues for financial success, Coding Beauty embodies values that resonate deeply with me.

5. Strong conclusion

Confident but not too brazen:

Example:

I’m sure my background aligns sufficiently with Coding Beauty and this role. I am enthusiastic about leveraging my expertise to contribute meaningfully to Coding Beauty’s objectives and look forward to hearing back.

Putting it together

I’m a passionate full-stack web developer with over 6 years of experience interested in learning more about the Coding Beauty team.

Over the past 3 years, I helped my company generate over $2 million in additional revenue by spearheading the development a new e-commerce web platform.

Firstly, at XYZ Corp, I spearheaded the migration from AngularJS to React, enhancing the user experience and improving performance by 30%. My focus was on creating reusable components, which streamlined the development process and fostered collaboration. I believe in writing clean, maintainable code and mentoring junior developers, which I did by conducting weekly code reviews and workshops.

Secondly, while at ABC Solutions, I led a project to integrate a Node.js backend with a MongoDB database, reducing data retrieval times by 50%. I am passionate about efficient architecture and robust security practices, which I implemented by designing a comprehensive API and setting up automated testing, ensuring a seamless and secure application.

Finally, I’m drawn to Coding Beauty’s mission because it aligns perfectly with my belief in empowering developers to reach their fullest potential. By fostering personal growth, promoting the enjoyment of coding, and facilitating avenues for financial success, Coding Beauty embodies values that resonate deeply with me.

I’m sure my background aligns sufficiently with Coding Beauty and this role. I am enthusiastic about leveraging my expertise to contribute meaningfully to Coding Beauty’s objectives and look forward to hearing back.

Thanks,

Coding Masters

Keep it short

Don’t write a book — everything we’ve gone should be done in 4 or 5 paragraphs.

No need to impress with fancy vocabulary or formal language.

Lean towards a conversational, semi-formal tone.

Follow these tips and tricks and you’ll drastically improve the quality of your cover letters for Upwork, Indeed or general job listings.

10 amazing tools that every web developer should know

10 fantastic web dev tools to level up your productivity and achieve your coding goals faster than ever.

From breathtaking animations to rapid project creation, these tools will boost your workflow and make a lot of things easier.

1. Fira Code

Most code editors’ default fonts are boring (like Consolas).

Use this beautiful, monospaced font instead:

Font ligatures have always been a genius, standout feature — merging common coding character groups in stylish, intuitive ways:

Changing your VS Code font is effortless; go to Settings you’ll see it up there among the “Commonly Used” options:

2. Barba JS

Add creative flair to your webpages and wow your users with delightful transitions:

It uses client-side routing of course, giving you that app-like experience:

3. Consola

I mean I just bashed Consolas, so no it’s not a typo.

It’s a beautiful, user-friendly console wrapper.

Perfect for making sophisticated looking CLI tools:

JavaScript
// ESM import { consola, createConsola } from "consola"; // CommonJS const { consola, createConsola } = require("consola"); consola.info("Using consola 3.0.0"); consola.start("Building project..."); consola.warn("A new version of consola is available: 3.0.1"); consola.success("Project built!"); consola.error(new Error("This is an example error. Everything is fine!")); consola.box("I am a simple box"); await consola.prompt("Deploy to the production?", { type: "confirm", });

4. Preact JS

A lightning-fast alternative to React — over 10 times lighter!

Dive in and you’ll find hooks, JSX, functional components… it’s essentially a drop-in replacement.

Just check this App component — I can literally count the differences with my right hand (or maybe left).

JavaScript
import { render, h } from 'preact'; import { useState } from 'preact/hooks'; /** @jsx h */ const App = () => { const [input, setInput] = useState(''); return ( <div> <p> Do you agree to the statement: "Preact is awesome"? </p> <input value={input} onInput={(e) => setInput(e.target.value)} /> </div> ); }; render(<App />, document.body);

And over 36,000 GitHub stars — they mean business.

5. Carbon

No need to bore people to death with dry dull-looking code snippets.

Spice things and bring beauty to the world with Carbon:

Multiple themes to choose from:

6. Firestore

Probably the best NoSQL database ever.

Generous free limits make it amazing for trying out new ideas, as I’ve done severally.

You’ll find it extremely easy and intuitive as a JS dev.

JavaScript
import { collection, addDoc } from "firebase/firestore"; try { const docRef = await addDoc(collection(db, "users"), { first: "Cristiano", last: "Ronaldo", born: 1985 }); console.log("Document written with ID: ", docRef.id); } catch (e) { console.error("Error adding document: ", e); }

You can even use it on the client side and skip server requests entirely — boosting cost savings and app performance.

I once used as a free web socket server and it worked perfectly — with server-side protections.

7. react-input-autosize

Input autosizing: An ubiqitious web design problem:

Which is why react-input-autosize started getting many millions of weekly downloads after it solved it:

Very easy to use UI component:

JavaScript
<AutosizeInput name="form-field-name" value={inputValue} onChange={function(event) { // event.target.value contains the new value }} />

8. Live Server for VS Code

Powerful tool for rapidly crafting static HTML pages — 48 million downloads!

No need to ever manually reload a webpage again — it loads it in the browser and syncs the display to the file contents.

9. Parcel

Parcel: a zero-config bundler with zero setup required — far more flexible than dinosaur Create React App.

Supports all the latest web technologies with excellent performance:

JavaScript
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <div id="root"></div> <!-- ✅ index.jsx directly --> <script src="index.jsx" type="module"></script> </body> </html>

We can rapidly create a React app from scratch with the index.jsx:

JavaScript
import React, { useState } from 'react'; import ReactDOM from 'react-dom/client'; ReactDOM.createRoot(document.getElementById('root')).render( <React.StrictMode> <App /> </React.StrictMode> ); function App() { const [count, setCount] = useState(0); return ( <div> <div>Count: {count}</div> <div> <button onClick={() => setCount(count + 1)}> Increment </button> </div> </div> ); }

10. SendGrid

A powerful, popular API to send marketing and transactional emails with a 99% delivery rate.

Design beautiful, engaging emails that land straight in inboxes — skipping spam folders.

Final thoughts

Use these awesome tools to level up your productivity and developer quality of life.

Recreate the Material Design text field with HTML, CSS, and JavaScript

No doubt you’ve seen the beautiful text field if you’re one of Gmail’s 2 billion active users:

It’s fluid, it’s intuitive, it’s colorful 🎨.

It’s Material Design: the wildly popular UI design system powering YouTube, WhatsApp, and many other apps with billions of users.

Let’s embark on a journey of recreating it from scratch with pure vanilla HTML, CSS, and JavaScript.

1. Start: Create basic input and label

As always we start with the critical HTML foundation, the skeleton:

The text input, a label, and a wrapper for both:

HTML
<!-- For text animation -- soon --> <div class="input-container"> <input type="text" id="fname" name="fname" value="" aria-labelledby="label-fname" /> <label class="label" for="fname" id="label-fname"> <div class="text">First Name</div> </label> </div>

2. Style input and label

I find it pretty satisfying: using CSS to gradually flesh out a stunning UI on the backs of a solid HTML foundation.

Let’s start:

Firs the <input> and its container:

CSS
.input-container { position: relative; /* parent of .label */ } input { height: 48px; width: 280px; border: 1px solid #c0c0c0; border-radius: 4px; box-sizing: border-box; padding: 16px; } .label { /* to stack on input */ position: absolute; top: 0; bottom: 0; left: 16px; /* match input padding */ /* center in .input-container */ display: flex; align-items: center; } .label .text { position: absolute; width: max-content; }

3. Remove pointer events

It resembles a text field now, but look what happens when I try focusing:

The label is part of the text field and the cursor should reflect that:

Solution? cursor: text

CSS
.label { ... cursor: text; /* Prevent blocking <input> focus */ pointer-events: none; }

4. Style input font

Now it’s time to customize font settings:

If you know Material Design well, you know Roboto is at the center of everything — much to the annoyance of some.

We’ll grab the embed code from Google Fonts:

Embed:

Use:

CSS
input, .label .text { font-family: 'Roboto'; font-size: 16px; }

5. Style input on focus

You’ll do this with the :focus selector:

CSS

input:focus {
  outline: none;
  border: 2px solid blue;
}

6. Fluidity magic: Style label on input focus

On focus the label does 3 things:

  1. Shrinks
  2. Move to top input border
  3. Match input border color

Of course we can do all these with CSS:

CSS
input:focus + .label .text { /* 1. Shrinks */ font-size: 12px; /* 2. Move to top input border */ transform: translate(0, -100%); top: 15%; padding-left: 4px; padding-right: 4px; /* 3. Match input border color */ background-color: white; color: #0b57d0; }

All we need to complete the fluidity is CSS transition:

CSS
label .text { transition: all 0.15s ease-out; }

7. One more thing

Small issue: The label always goes to the original position after the input loses focus:

Because it depends on CSS :focus which goes away on focus lost.

But this should only happen when there’s no input yet.

CSS can’t fix this alone, we’re going to deploy the entire 3-tiered army of web dev.

HTML: input value to zero.

HTML
<input type="text" id="fname" name="fname" value="" aria-labelledby="label-fname" />

CSS: :not selector to give unfocused input label same position and size when not empty:

JavaScript
input:focus + .label .text, /* ✅ no input yet */ :not(input[value='']) + .label .text { /* 1. Shrink */ font-size: 12px; transform: translate(0, -100%); /* 2. Move to top */ top: 15%; padding-left: 4px; padding-right: 4px; /* 3. Active color */ background-color: white; color: #0b57d0; }

And JavaScript: Sync initial input value attribute with user input

JavaScript
const input = document.getElementById('fname'); input.addEventListener('input', () => { input.setAttribute('value', input.value); });
JavaScript
const input = document.getElementById('fname'); input.addEventListener('input', () => { input.setAttribute('value', input.value); });

That’s it! We’ve successfully created an outlined Material Design text field.

With React or Vue it’ll be pretty easy to abstract everything we’ve done into a reusable component.

Here’s the link to the full demo: CodePen

Why [‘1’, ‘5, ’11’].map(parseInt) returns [1, NaN, 3] in JavaScript

Alex, the self-proclaimed coding whiz, prided himself on quick hacks and short code.

Despite being very new to the industry, he always saw himself as superior to the rest of the team, stubbornly doing whatever he felt like; all their well-meant advice falling on deaf ears.

But Alex was soon to meet his catastrophic downfall. A painful, humbling experience he would never forget.

It all started when Alex and Cody were assigned a project task. To let users view the products for the ongoing eCommerce website the team had been working on.

They were still in startup phase so all the data was stored and updated in a CSV file.

The product name, price, quantity… all the usual stuff you’d see on sites like Amazon.

Alex arrogantly scoffed when he learned of the planned collaboration.

“I don’t need to work with ANYONE okay?” He smirked at Jake, the good-natured head of engineering, as he typed on his PC. “It’s literally just to fetch from the DB and show in the JSX”.

“Alex you need to learn how to work with others, I keep telling you this.”, Jake responded with a patient, forced smile. He was used to this man’s self-obsessed antics.

“I don’t need to work with anyone, I can do this alone. Cody will only slow me down with all his nonsense talk about readable code”.

“Cody is one of our best and takes his time for a reason. I keep telling you it’s not all about writing code quickly or concisely…”.

“You always keep telling me things but you NEVER listen to me. I just want to work on my own this time, okay?”. “Please?”, Alex quickly added to avoid sounding too rude — keeping that snobbish smirk on his face of course.

Jake sighed.

“Alright, I’ll let you work you alone if you can convert this string array”, as he wrote on a nearby sheet of paper, “to the same array of numbers”.

Alex couldn’t believe it. On the paper was a simple array.

JavaScript
['1', '5', '11']

This had to be a trick question. He looked up at Jake suspiciously.

“Seriously? How dumb do you think I am that I can’t parse this?”

“Do it, you only get one chance”. Jake deserved a self-control medal for his astounding patience with this youngster.

With a smug look on his face, Alex opened up a new VS Code terminal and smugly typed out the seemingly obvious solution in Node:

JavaScript
['1', '5', '11'].map(parseInt)

He smirked triumphantly, only to turn and see a knowing smile on Jake’s face — he was thrown off balance instantly.

“You sure about that Alex? Why don’t you press Enter and let’s see what the resulting array actually is”.

A little unsure of himself, he scanned through the short CLI code to ensure absolute certainty, before the final moment.

What he saw next shook him to his very core.

How on earth was this possible? Was parseInt broken? Was there a bug in map()?

He looked up frantically, eliciting a sharp, unnerving laughter from Jake.

“Alex, you’re fired”.

“WHAT?!”, Alex screamed.

“Pack your things and get out of here before I close and open my eyes, you arrogant buffoon!”

You see, Alex’s downfall was NOT his failure to understand map and parseInt — though that could have helped.

It was his obsession with making code as short as possible, at the expense of readability and clarity…

The fact is in 99% of cases this is how we use map and parseInt

JavaScript
const doubles = ['1', '5', '11'].map((num) => num * 2); console.log(doubles); // [2, 10, 22] const num = parseInt('5'); console.log(num); // 👍 5 -- not NaN!

But you may be shocked at what happens when you use map with console.log:

JavaScript
const doubles = ['1', '2', '3'].map(console.log);

It logs 3 pairs of numbers for each item!

That’s because the map() callback actually takes 3 arguments:

So you’re actually calling parseInt with 3 args:

JavaScript
// parseInt take 2 args max but JS compiler doesn't complain ['1', '5', '11'].map(parseInt) // parseInt('1', '0', ['1', '5', '11']) // parseInt('5', '1', ['1', '5', '11']) // parseInt('11' '2', ['1', '5', '11'])

Alex never knew that parseInt takes either 1 or 2 arguments and behaves differently for each:

When there’s a 2nd arg it becomes a base for the 1st number arg:

JavaScript
// 👇 invalid positive number, ignore parseInt('1', '0'); // 1 ✅ parseInt('3', 'blah blah'); // 3 // 👇 invalid base (1) parseInt('2', '1'); // NaN parseInt('5', '1'); // NaN ✅ // 👇 '10' is 2 in base 2 (remember?) parseInt('10', '2'); // 2 parseInt('11', '2'); // 3 ✅

Despite his average knowledge of map and parseInt, he could have avoided all of these by simply being explicit:

JavaScript
['1', '5', '11'].map((num) => parseInt(num));

Shortening code can be great for reducing clutter but we should always prioritize clear and readable code:

Especially when the added length is not that big of a deal, you know?

JavaScript
async function setTimeout() { // ❌ await new Promise((resolve) => setTimeout(resolve, 1000)); console.log('Coding Beauty'); } async function setTimeout() { // // ✅ await new Promise((resolve) => setTimeout(() => resolve(), 1000)); console.log('Coding Beauty'); }

10 rare HTML tags that nobody ever uses

There’s way more to HTML than <div>, <a>, and <p>.

So much more sophisticated and powerful tags that you’ve probably never used.

From modern list visualization to 🎨 colorful highlights, let’s look at 10 little-known but capable HTML tags.

1. abbr

The <abbr> tag defines an abbreviation or acronym, like HTML, CSS, and JS.

And LOL too – though that’s more of a standalone word these days.

I'm reading about
<abbr title="Hypertext Markup Language">HTML</abbr>
tags at
<abbr title="Coding Beauty">CB</abbr>
The abbreviation is indicated with a dotted line by default.
Dotted line for abbreviation.

We use the title attribute of the <abbr> tag to show the description of the abbreviation/acronym when you hover over the element:

Hover over <abbr> to show the full form:

Hovering over the <abbr> element.

2. q

The <q> tag indicates that the text inside of it is a short inline quotation.

<q>Coding creates informative tutorials on Web Development technologies</q>

Modern browsers typically implement this tag by wrapping the enclosed text in quotation marks:

The text in the <q> tag is wrapped with quotation marks.

3. s

<s> strikes through.

To correct without destroying the change history.

Buy for <s>$200</s> $100
Indicating price change with the <s> tag.

The <del> and <ins> pair are similar but semantically meant for document updates instead of corrections.

<!DOCTYPE html>
<html lang="en">
  <head>
    <style>
      del {
        background-color: lightsalmon;
      }

      ins {
        text-decoration: none;
        background-color: lightgreen;
      }
    </style>
  </head>
  <body>
    My favorite programming language is <del>JavaScript</del>
    <ins>TypeScript</ins>
  </body>
</html>
Indicating editorial changes in a document with the <del> and <ins> tags.
Indicating editorial changes in a document with the <del> and <ins> tags.

4. mark

Marks or highlights text.

Coding <mark>Beauty</mark> Website

Yellow background color by default:

The <mark> tag applies a bright yellow background to its enclosed text.

Like how browsers show search results.

Display search results for the letter "e" with the <mark> tag.
e e e e e e ….

5. wbr

<wbr> tells browser, “You can only break text here and there”

So the browser doesn’t get lousy and start break crucial words all over the place.

That’s why it’s wbr — Word BReak Opportunity

<p>this-is-a-very-long-text-created-to-test-the-wbr-tag</p>
The text is broken at a location chosen by the browser.
Browser is joking around.

But now with <wbr />

<p>this-is-a-very-long-te<wbr />xt-created-to-test-the-wbr-tag</p>

Broken precisely after ...-te:

The text is broken at the location set with the <wbr> tag.
Obviously no reason to break there in real-world code though.

6. details

<details> is all about expanding and contracting — like the universe.

<details>
  <summary>Lorem Ipsum</summary>
  Lorem ipsum dolor sit, amet consectetur adipisicing elit. Deleniti eos
  quod fugiat quasi repudiandae, minus quae facere. Sed, quia? Quod
  cupiditate asperiores neque iste consectetur tempore eum repellat incidunt
  qui.
</details>

Contract:

A closed disclosure widget.
The disclosure widget is closed (default state).

Expand:

An open disclosure widget.
The disclosure widget is open.

7. optgroup

The name says it all — grouping options.

You can usually group gigantic option lists into clear hierarchies, and <outgroup> is here to help.

<select name="country" id="countries">
  <optgroup label="North America">
    <option value="us">United States</option>
    <option value="ca">Canada</option>
  </optgroup>
  <optgroup label="Europe">
    <option value="uk">United Kingdom</option>
    <option value="fr">France</option>
  </optgroup>
</select>

Countries → continents.

An open dropdown list contains grouped options.

8. datalist

<datalist> is all about making inputting text effortless.

With dropdown lists for autocomplete:

<form>
  <label for="lang">Choose a language:</label>
  <input list="langs" name="lang" id="lang" />

  <!-- 🔗<input> list to <datalist> id -->

  <datalist id="langs">
    <option value="English" />
    <option value="French" />
    <option value="Spanish" />
    <option value="Chinese" />
    <option value="German" />
  </datalist>
</form>
An input with an available list of options.
A list of available options for the input is displayed in a dropdown list.
An input with a responsive list of options.
The available options change according to what the user types in the input.

9. fieldset

A set of fields — farmers must find it useful.

Creating a clean visual separation to easily understand the forms.

<form>
  <fieldset>
    <legend>Name</legend>

    <label for="fname">First Name:</label>
    <input type="text" id="fname" name="fname" /><br />
    <label for="mname">Middle Name:</label>
    <input type="text" id="mname" name="mname" /><br />
    <label for="lname">Last Name:</label>
    <input type="text" id="lname" name="lname" />
  </fieldset>
  <br />
  <label for="email">Email:</label>
  <input type="email" id="email" name="email" />
  <br /><br />
  <label for="password">Password:</label>
  <input type="password" id="password" name="password" />
</form>

We use the <legend> tag to define a caption for the <fieldset> element.

Input elements, some grouped with a <fieldset> tag.

10. sup and sub

<sup> — superscript.

<sub> — subscript.

<p>This text contains <sub>subscript</sub> text</p>
<p>This text contains <sup>superscript</sup> text</p>
The text contains both subscript and superscript.

Something more intense: neutralization reaction 🧪

&#x1D465;<sup>2</sup> - 3&#x1D465; - 28 = 0. Solve for &#x1D465;. <br />
<br />
H<sub>2</sub>SO<sub>4</sub> + NaOH &#8594; Na<sub>2</sub>SO<sub>4</sub> +
H<sub>2</sub>O

Conclusion

In this article, we explored some of the least known and utilized tags in HTML. These rare tags can be quite useful in particular situations despite their low usage.

How to earn full or side income as a freelance developer in 2024

Don’t waste time cold applying to job listings.

Your success rate will be painfully low after all that time invested. There is a better way that many never use.

Many have used it to guarantee responses and interviews every single time. This is my #1 way to find clients.

I use LinkedIn as a case study, but the strategy applies to any place you interact with other people.

It’s all about referrals at its core.

Referrals drastically improve your chances of getting a job at any company.

But you need to do it right.

Follow this ultimate step-by-step guide to landing high-paying, flexible freelance + full-time jobs.

1. Plan: Know what you want

This is extremely important, especially for future jobs.

The broader your niche the more jobs for you — but there’s more competition.

Example: “Web developer”.

Smaller niche makes you the big fish in a small pond — less jobs but standing out takes far less time.

Example: “Next.js developer, implements social media integrations into web apps”. Super specific.

If you’re just starting without much experience, start small. Then you can slowly broaden your niche as you gain experience and social proof.

2. Find jobs in your niche the right way

Now start action.

Find jobs in your niche don’t apply directly.

What are the best places to find jobs?

Wellfound

I previously talked about the massive number of software jobs from rapidly growing startups on Wellfound.

It has over 49,000 jobs on there right now with not enough people to fill them — incredible opportunity.

LinkedIn Jobs

LinkedIn is full of the latest job listings from high-quality companies. Filter by your niche and add to your collection.

3. Create a unique LinkedIn profile

It’s the first thing anyone checking you out will see — make it incredible.

First impression matters everywhere and LinkedIn is no exception.

Great photo

Use a high-quality face photo with great lighting that shows confidence.

You can smile to appear friendly and approachable — not necessary though! Too fake for some.

Attention-grabbing bio

Forget about being quirky or cute here.

You mean business and the first piece of text describing you must show this.

What should you put in your bio?

1. Your niche

You know your ideal job type, now make it known to the world. Let people know you’re qualified.

2. Impressive achievement

Include a notable achievement to grab attention.

Example: 1,000+ stars on GitHub.

3. Open to work

Add “freelancer” if you’re specifically doing freelance.

Many won’t want to waste even a little energy to ask if you’re open to work; Let them be sure from the start.

Also use the #OpenToWork LinkedIn feature.

4. Start building your network with intent — like this

You’ve built up your LinkedIn profile beautifully, now it’s time to find valuable people.

Don’t just add any random person — focus on people who meet these criteria:

1. Connected to the target job

People who work at the companies of the job openings you found.

And people who know those people — 2nd-degree connections.

2. Something in common

  • Is their industry and niche similar to yours? More on this shortly.
  • Did they go to the same school as you?
  • Are you two from the same city? Or the same not-so-popular country?

We are tribal and more likely with people similar to us in an important way.

3. Creators

Target software developers like yourself. Then designers, writers, authors — creators in general. But prioritize people who code professionally.

Focus on quality AND quantity connections.

The more people in your network the more likely opportunities will come your way.

And you can add up to 30,000 connections!

5. Nurture your relationships

Adding people is NOT enough — You must patiently strengthen your connections with them.

And how do you do that?

Engage

If you don’t show up in people’s lives, they’ll forget about your existence.

Leave genuine thoughtful comments on their posts.

Like posts that resonate with you — but don’t just like every post or you’ll cheapen the value — like a chronic flatterer.

Send them personal messages offering value. Ask them for advice and make them feel valued and invested in you.

Create posts

Another great way to offer value and maintain the relationship.

Share what you know and what you’ve done. Don’t give us coding platitudes — everybody knows about <br /> tag. We all know about HTTP POST.

Try not to always share cold impersonal facts; sprinkle in your thoughts and opinions. Make jokes without causing painful cringe.

6. Ask for referrals

The best way to do this: Ask to meet them physically or virtually to learn more about the role or company.

Prepare engaging questions in advance to show genuine interest in the company — not just about getting a job.

If you’ve built a cordial relationship at this point, they’ll probably ask you if you want a referral — ✅.

If not, you can say something like, “This sounds like an amazing place to work! Would it be possible to get a referral if I applied?”.

You don’t even have to tie the referral to any specific role — you can ask them to keep you posted with job requests.

If they’re a great developer they’re probably high in demand and get more offers than they can handle. With a strong relationship, they’ll be more than happy to refer you.

People trust people they know. You’re far more likely to get the job with referrals than with cold job listings.

Final thoughts

Follow this strategy focus and intent, and you’ll start landing high-paying freelance jobs faster than you think with high certainty.