Nono.MA

JULY 2, 2022

Here is the fastest way to create a Next.js React app with TypeScript. For the step-by-step version, take a look at the longer version.

Create a Next.js App with TypeScript

Let's use npx and create-next-app.

npx \
create-next-app nextjs-app \
--use-npm \
--example \
"https://github.com/nonoesp/next-learn/tree/master/basics/typescript-final"

Run the app in development mode

# Enter the app's directory
cd nextjs-app
# Run the app in development
npm run dev
# ready - started server on 0.0.0.0:3000, url: http://localhost:3000

You should be able to access the site at http://localhost:3000.

Build & Run for Production

npm run build
npm start
# ready - started server on 0.0.0.0:3000, url: http://localhost:3000

Hands-on tutorial

You can watch my step-by-step video on How to build a Next.js app with React & TypeScript.

JUNE 18, 2022

Here are the simplified steps to create a Next.js React app and add TypeScript to the mix. This tutorial combines my Create a Next.js app and Add TypeScript to Next.js posts.

Create a Next.js App

Let's use npx and create-next-app.

npx \
create-next-app nextjs-app \
--use-npm \
--example \
"https://github.com/vercel/next-learn/tree/master/basics/learn-starter"

Add TypeScript

# Enter your app's directory
cd nextjs-app
# Create an empty TypeScript configuration file
touch tsconfig.json
# Install TypeScript, React Types, and Node Types
npm install --save-dev typescript @types/react @types/node

You can customize your TypeScript in tsconfig.json.

Run the app in development mode

npm run dev
# ready - started server on 0.0.0.0:3000, url: http://localhost:3000

You should be able to access the site at http://localhost:3000.

Build & Run for Production

npm run build
npm start
# ready - started server on 0.0.0.0:3000, url: http://localhost:3000

From index.js into index.tsx

Your application is now ready to be written in TypeScript. The example we've used only has one file named index.js. Rename it to index.tsx and re-write the JavaScript code (and any new code you add to the app) in TypeScript.

Hands-on tutorial

You can watch my step-by-step video on How to build a Next.js app with React & TypeScript.

JUNE 11, 2022

Here are the steps to add TypeScript to your Next.js React application.

I assume you have a Next.js React application that can run in development mode. If that's not the case, Create a Next.js app first.

# Enter the directory of your app
cd nextjs-app
# Run Next.js in development
npm run dev
# ready - started server on 0.0.0.0:3000, url: http://localhost:3000

If you can access your site at http://localhost:3000, you're good to go.

Create a tsconfig.json file

# Create an empty TypeScript configuration file
touch tsconfig.json

Simply by creating a tsconfig.json file and restarting the application, Next.js will warn us that we're trying to work with TypeScript and have to install a set of required dependencies.

# Stop the running app with `CMD + C` (or `CTRL + C` on Windows)
# Run Next.js in development once again
npm run dev

You should receive the following warning when restarting the app.

ready - started server on 0.0.0.0:3000, url: http://localhost:3000
It looks like you're trying to use TypeScript but do not have
the required package(s) installed.

Please install typescript, @types/react, and @types/node by running:

  npm install --save-dev typescript @types/react @types/node

If you are not trying to use TypeScript, please remove the
tsconfig.json file from your package root (and any TypeScript
files in your pages directory).

Install TypeScript, React Types, and Node Types

npm install --save-dev typescript @types/react @types/node

Run your app

npm run dev
# ready - started server on 0.0.0.0:3000, url: http://localhost:3000
# We detected TypeScript in your project and created a tsconfig.json
# file for you.

Note that Next.js detected the tsconfig.json file, verified our dependencies were installed, and then populated our empty TypeScript configuration file with a boilerplate JSON object.

// tsconfig.json
{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": false,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "incremental": true,
    "esModuleInterop": true,
    "module": "esnext",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve"
  },
  "include": [
    "next-env.d.ts",
    "**/*.ts",
    "**/*.tsx"
  ],
  "exclude": [
    "node_modules"
  ]
}

From index.js into index.tsx

Your application is now ready to be written in TypeScript. The example we've used only has one file named index.js. Rename it to index.tsx and re-write the JavaScript code (and any new code you add to the app) in TypeScript.

Learning More

If you want to learn more, you can watch my video on How to build a Next.js app with React & TypeScript and take a look at Next.js's official TypeScript tutorial.

JUNE 4, 2022

As the official Create a Next.js App tutorial says, "there are many important details you need to consider to build a complete web application with React from scratch," but here I'm trying to get started as fast as possible.

Create a Next.js App

Let's use npx and create-next-app.

npx \
create-next-app nextjs-app \
--use-npm \
--example \
"https://github.com/vercel/next-learn/tree/master/basics/learn-starter"

Your fresh Next.js app is now in the nextjs-app directory.

Run the App in Development

Now enter the directory and run the app in development mode.

cd nextjs-app
npm run dev
# ready - started server on 0.0.0.0:3000, url: http://localhost:3000

You should be able to access the site at http://localhost:3000.

Build & Run for Production

npm run build
npm start
ready - started server on 0.0.0.0:3000, url: http://localhost:3000

Add TypeScript to Next.js

If you want to use TypeScript instead of JavaScript on your Next.js React app, read how to Add TypeScript to Next.js. I also have a step-by-step video on How to build a Next.js app with React & TypeScript.

MAY 27, 2022

I'm writing a series of posts on how to create a Next.js React app with and without TypeScript, trying to summarize the required steps.

# Create a Next.js React JavaScript app with npx
npx \
create-next-app nextjs-app \
--use-npm \
--example \
"https://github.com/nonoesp/next-learn/tree/master/basics/learn-starter"
# Enter the app's directory
cd nextjs-app
# Start the app in development mode
npm run dev
# > dev
# > next dev
#
# ready - started server on 0.0.0.0:3000, url: http://localhost:3000
# wait  - compiling...
# event - compiled client and server successfully in 944 ms (113 modules)

You should be able to access the site at http://localhost:3000. =)

APRIL 6, 2022

My site parses Markdown posts into HTML and code blocks are syntax-highlighted with the highlight.js JavaScript library.

How does highlight.js work?

In a nutshell, Markdown code blocks—the content between a pair of three backticks—are parsed into <pre><code> HTML blocks.

If we take this Markdown input.

```
console.log(`Hello, highlight.js!`);
console.log(`Formatting Markdown code blocks!`);
const add = (a: number, b: number) => a + b
add(2, 3) // Returns 5
```

The Markdown parser converts it into a <pre><code> HTML block.

<pre><code>console.log(`Hello, highlight.js!`);
console.log(`Formatting Markdown code blocks!`);
const add = (a: number, b: number) => a + b
add(2, 3) // Returns 5
</code></pre>

Which is then highlighted by highlight.js.

console.log(`Hello, highlight.js!`);
console.log(`Formatting Markdown code blocks!`);
const add = (a: number, b: number) => a + b
add(2, 3) // Returns 5

How can you use highlight.js on your site?

This is all the HTML code you really need.

  • The HTML code block
  • Loading highlight.js
  • Optionally loading a highlight.js CSS style
  • Initialize highlight.js
<!-- Code block -->
<pre><code>console.log(`Hello, highlight.js!`);
console.log(`Formatting Markdown code blocks!`);
const add = (a: number, b: number) => a + b
add(2, 3) // Returns 5
</code></pre>

<!-- Load highlight.js from a CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.0/highlight.min.js"></script>

<!-- Optionally load a template from a CDN -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.0/styles/atom-one-light.min.css" integrity="sha512-o5v54Kh5PH0dgnf9ei0L+vMRsbm5fvIvnR/XkrZZjN4mqdaeH7PW66tumBoQVIaKNVrLCZiBEfHzRY4JJSMK/Q==" crossorigin="anonymous" referrerpolicy="no-referrer" />

<!-- Initialize highlight.js -->
<script>hljs.initHighlightingOnLoad();</script>

How can you add dark mode support to highlight.js?

In my case, I create custom templates or use the ones provided by highlight.js. The only tweak to support the system's appearance—light and dark mode—is to use CSS's prefers-color-scheme to target whether the user has the system's dark mode enabled.

/* highligh-styles.js */

/* Light mode highlight.js theme goes here */

@media screen and (prefers-color-scheme: dark) {
  /* Dark mode highlight.js theme goes here */
}

Thanks to Nino. This post is a reply to his question on Twitter.

MARCH 8, 2021

If you multiple Vue components of the same type throughout your application but they're not in the same parent DOM element, mounting them may not be as easy as calling their parent.

Mounting multiple Vue components with a shared parent

In this first example, we can mount all of our button-counter components by mounting their parent, #button-container.

<div id="button-container">
  <button-counter></button-counter>
  <button-counter></button-counter>
  <button-counter></button-counter>
</div>

We just need to make one call.

new Vue({ el: '#button-container' });

But what if our components are spread throughout different HTML elements?

Mount multiple Vue components without a shared parent

Imagine you have components of the same (or different) types spread throughout your website's DOM.

<div>
  <button-counter></button-counter>
  <button-counter></button-counter>
</div>

<div>
  <button-counter></button-counter>
</div>

<button-counter></button-counter>

We can iterate through the DOM elements and mount them one by one.

// Obtain all button-counter elements
let elements = document.getElementsByTagName('button-counter');

// Convert HTMLCollection to array
let arr = Array.prototype.slice.call( elements )

// Loop through array and mount all elements
arr.forEach((el) => {
    new Vue( { el });
});

Note that we had to convert the HTMLCollection to a JavaScript array before we could call the .forEach() function to iterate over the button-counter host DOM nodes.

This works with Vue 2, and Vue 3 recently released new features for multi-root components and optional TypeScript support.

MARCH 8, 2021

Change this.

window.Vue = require('vue');

For this.

window.Vue = require('vue').default;

Then this should work.

window.Vue = require('vue').default;
window.VueResource = require('vue-resource');
window.Vue.use(window.VueResource);

MARCH 31, 2020

Pretty impressed by ImgIX's JSON format. Long story short, it provides a JSON metadata file for each resource you are serving via ImgIX (say, an image or a video) as in the example below just by appending fm=json to any image request.

For this image.

https://nono.imgix.net/img/u/profile-nono-ma.jpg

You'd load the JSON at.

https://nono.imgix.net/img/u/profile-nono-ma.jpg?fm=json

What's nice is that with the imgix.js JavaScript library you can fetch the JSON file for each picture and—before loading any image data—decide how to deliver the image. In this CodePen provided by ImgIX, they crop a set of images to fit a certain aspect ratio (which ends up saving data as they cropped bits of each image are never loaded) avoiding also having to play with image background CSS tricks in order to fit an image to a given aspect ratio (as the image already has it!).

{
    "Exif": {
        "PixelXDimension": 1500,
        "DateTimeDigitized": "2019:11:20 10:43:28",
        "PixelYDimension": 1500,
        "ColorSpace": 65535
    },
    "Orientation": 1,
    "Output": {},
    "Content-Type": "image\/jpeg",
    "JFIF": {
        "IsProgressive": true
    },
    "DPIWidth": 144,
    "Content-Length": "180595",
    "Depth": 8,
    "ColorModel": "RGB",
    "DPIHeight": 144,
    "TIFF": {
        "ResolutionUnit": 2,
        "DateTime": "2019:11:20 11:17:40",
        "Orientation": 1,
        "Software": "Adobe Photoshop CC 2019 (Macintosh)",
        "YResolution": 144,
        "XResolution": 144
    },
    "PixelWidth": 1500,
    "PixelHeight": 1500,
    "ProfileName": "Display"
}

And here's the JavaScript included in that CodePen that does all the magic.

// Demonstrate the use of the `fm=json` parameter to resize images
// to a certain aspect ratio, using ES6.

let ratio = 16 / 9;
let maxSize = 300;

let placeImages = function () {
    jQuery('.imgix-item').each((i, value) => {
        let $elem = jQuery(value);
        // We pull down the image specific by the 'data-src' attribute
        // of each .imgix-item, but append the "?fm=json" query string to it.
        // This instructs imgix to return the JSON Output Format instead of 
        // a manipulated image.
        let url = new imgix.URL($elem.attr('data-src'), { fm: "json" }).getUrl();

        jQuery.ajax(url).success((data) => {
            let newWidth, newHeight;

            // Next, we compute the new height/width params for 
            // each of our images.
            if (data.PixelHeight > data.PixelWidth) {
                newHeight = maxSize;
                newWidth = Math.ceil(newHeight / ratio);
            } else {
                newWidth = maxSize;
                newHeight = Math.ceil(newWidth / ratio);
            }

            // Now, we apply these to our actual images, setting the 'src'
            // attribute for the first time.
            $elem.get(0).src = new imgix.URL($elem.attr('data-src'), {
                w: newWidth,
                h: newHeight,
                fit: "crop"
            }).getUrl();
        })
    });
}

jQuery(document).ready(placeImages);

MARCH 20, 2020

Maker.js: Parametric CNC Drawings Using JavaScript

Microsoft recently open sourced, twenty five days ago, Maker.js — a JavaScript library to create drawings on the browser for CNC and laser cutting.

I love the playground site they made to share parametric scripts (say, of a smiley face, a hello, world text, a floor plan, and more). See all demos.

From their website:

  • Drawings are a simple JavaScript object which can be serialized / deserialized conventionally with JSON. This also makes a drawing easy to clone.
  • Other people's Models can be required the Node.s way, modified, and re-exported.
  • Models can be scaled, distorted, measured, and converted to different unit systems.
  • Paths can be distorted.
  • Models can be rotated or mirrored.
  • Find intersection points or intersection angles of paths.
  • Traverse a model tree to reason over its children.
  • Detect chains formed by paths connecting end to end.
  • Get the points along a path or along a chain of paths.
  • Easily add a curvature at the joint between any 2 paths, using a traditional or a dogbone fillet.
  • Combine models with boolean operations to get unions, intersections, or punches.
  • Expand paths to simulate a stroke thickness, with the option to bevel joints.
  • Outline model to create a surrounding outline, with the option to bevel joints.
  • Layout clones into rows, columns, grids, bricks, or honeycombs.

Via @alfarok's GitHub stars.

SEPTEMBER 10, 2019

A cheat-sheet for mathematical notation in [JavaScript] code form.

Want to see older publications? Visit the archive.

Listen to Getting Simple .