How to Build Runnable JavaScript Specifications

Share this article

How to Build Runnable JavaScript Specifications

Programming is not only about giving the computer instructions about how to accomplish a task, it’s also about communicating ideas in a precise way with other people, or even to your future self. Such communication can have multiple goals, maybe to share information or just to allow easier modifications—it’s hard to change something if you don’t understand it or if you don’t remember what you did long time ago. Documentation is key, either as simple comments in your code or as whole documents describing the overall functionality of a program.

A Simple JavaScript Specification File

When we write software we also need to make sure that the code has the intended functionality. While there are formal methods to define semantics, the easiest and quickest (but less rigorous) way is to put that functionality into use and see if it produces the expected results.

Most developers are familiar with these practices: code documentation as comments to make explicit the goal of a block of code, and a series of tests to make sure functions give the desired output.

But usually documentation and testing are done in different steps. By unifying these practices, we can offer a better experience for anyone involved in the development of a project. This article explores a simple implementation of a program to run JavaScript specifications that work for both documentation and testing.

We are going to build a command-line interface that finds all the specification files in a directory, extracts all the assertions found inside each specification and evaluates their result, finally showing the results of which assertions failed and which ones passed.

The Specification Format

Each specification file will export a single string from a template literal. The first line can be taken as the title of the specification. The template literal will allow us to embed JS expressions between the string and each expression will represent an assertion. To identify each assertion we can start the line with a distinctive character, in this case, we can use the combination of the bar character (|) and a dash (-), which resembles a turnstile symbol that can sometimes be found as a symbolic representation for logical assertions.

The following is an example with some explanations of its use:

const dependency = require('./dependency')

module.exports = `
  Example of a Specification File

  This project allows to test JavaScript programs using specification files.
  Every *.spec.js file exports a single template literal that includes a general
  explanation of the file being specified. Each file represents a logical
  component of a bigger system. Each logical component is composed of several
  units of functionality that can be tested for certain properties.
  Each one of this units of functionality may have one or more
  assertions. Each assertion is denoted by a line as the following:

  |- ${dependency} The dependency has been loaded and the first assert has
  been evaluated.

  Multiple assertions can be made for each file:

  |- ${false} This assertion will fail.

  |- ${2 + 2 === 4} This assertion will succeed.

  The combination of | and - will form a Turnstile ligature (|-) using the appropriate
  font. Fira Code is recommended. A Turnstile symbol was used by Gottlob Frege
  at the start of sentenses being asserted as true.

  The intended usage is for specification-first software. Where the programmer
  defines the high level structure of a program in terms of a specification,
  then progressively builds the parts conforming that specification until all
  the tests are passed. A desired side-effect is having a simple way to generate
  up-to-date documentation outside the code for API consumers.
`

Now let’s proceed with the high level structure of our program.

The Structure of Our Program

The whole structure of our program can be defined in a few lines of code, and without any dependencies other than two Node.js libraries to work with the filesystem (fs) and directory paths (path). In this section we define just the structure of our program, function definitions will come in the next sections.

#!/usr/bin/env node

const fs = require('fs')
const path = require('path')

const specRegExp = /\.spec\.js$/
const target = path.join(process.cwd(), process.argv[2])

// Get all the specification file paths
// If a specification file is provided then just test that file
// Otherwise find all the specification files in the target directory
const paths = specRegExp.test(target)
  ? [ target ]
  : findSpecifications(target, specRegExp).filter(x => x)

// Get the content of each specification file
// Get the assertions of each specification file
const assertionGroups = getAssertions(getSpecifications(paths))

// Log all the assertions
logAssertions(assertionGroups)

// Check for any failed assertions and return an appropriate exit code
process.exitCode = checkAssertions(assertionGroups)

Because this is also the entry point of our CLI (command-line interface), we need to add the first line, the shebang, that indicates that this file should be executed by the node program. There is no need to add a specific library to handle the command options, since we are only interested in a single parameter. However, you may consider other options if you plan to extend this program in a considerable manner.

To get the target testing file or directory, we have to join the path where the command was executed (using process.cwd()) with the argument provided by the user as the first argument when executing the command (using process.argv[2]). You can find a reference to these values in the Node.js documentation for the process object. In this way we obtain the absolute path of the target directory/file.

Now, the first thing that we have to do is to find all the JavaScript specification files. As seen in line 12, we can use the conditional operator to provide more flexibility: if the user provides a specification file as the target then we just use that file path directly, otherwise, if the user provides a directory path then we have to find all the files that match our pattern as defined by the specRegExp constant, we do this using a findSpecifications function that we will define later. This function will return an array of paths for each specification file in the target directory.

In line 18 we are defining the assertionGroups constant as the result of combining two functions getSpecifications() and getAssertions(). First we get the content of each specification file and then we extract the assertions from them. We will define those two functions later, for now just note that we use the output of the first function as the parameter of the second one, thus simplifying the procedure and making a direct connection between those two functions. While we could have just one function, by splitting them, we can get a better overview of what is the actual process, remember that a program should be clear to understand; just making it work is not enough.

The structure of the assertionsGroup constant would be as follows:

assertionGroup[specification][assertion]

Next, we log all those assertions to the user as a way to report the results using a logAssertions() function. Each assertion will contain the result (true or false) and a small description, we can use that information to give a special color for each type of result.

Finally, we define the exit code depending on the results of the assertions. This gives the process information about how the program ended: was the process successful or something failed?. An exit code of 0 means that the process exited successfully, or 1 if something failed, or in our case, when at least one assertion failed.

Finding All the Specification Files

To find all the JavaScript specification files we can use a recursive function that traverses the directory indicated by the user as a parameter to the CLI. While we search, each file should be checked with the regular expression that we defined at the beginning of the program (/\.spec\.js$/), which is going to match all file paths ending with .spec.js.

function findSpecifications (dir, matchPattern) {
  return fs.readdirSync(dir)
    .map(filePath => path.join(dir, filePath))
    .filter(filePath => matchPattern.test(filePath) && fs.statSync(filePath).isFile())
}

Our findSpecifications function takes a target directory (dir) and a regular expression that identifies the specification file (matchPattern).

Getting the Contents of Each Specification

Since we are exporting template literals, getting the content and the evaluated assertions is simple, we have to import each file and when it gets imported all the assertions get evaluated automatically.

function getSpecifications (paths) {
  return paths.map(path => require(path))
}

Using the map() function we replace the path of the array with the content of the file using the node’s require function.

Extracting the Assertions from the Text

At this point we have an array with the contents of each specification file and their assertions already evaluated. We use the turnstile indicator (|-) to find all those assertions and extract them.

function getAssertions (specifications) {
  return specifications.map(specification => ({
    title: specification.split('\n\n', 1)[0].trim(),
    assertions: specification.match(/^( |\t)*(\|-)(.|\n)*?\./gm).map(assertion => {
      const assertionFragments = /(?:\|-) (\w*) ((?:.|\n)*)/.exec(assertion)

      return {
        value: assertionFragments[1],
        description: assertionFragments[2].replace(/\n /, '')
      }
    })
  }))
}

This function will return a similar array, but replacing the content of each specification with an object following this structure:

{
  title: <String: Name of this particular specification>,
  assertions: [
    {
      value: <Boolean: The result of the assertion>,
      description: <String: The short description for the assertion>
    }
  ]
}

The title is set with the first line of the specification string. Then each assertion is stored as an array in the assertions key. The value represents the result of the assertion as a Boolean. We will use this value to know if the assertion was successful or not. Also, the description will be shown to the user as a way to identify which assertions succeeded and which ones failed. We use regular expressions in each case.

Logging Results

The array that we have built along the program now has a series of JavaScript specification files containing a list of found assertions with their result and description, so there is not much to do other than reporting the results to the user.

function logAssertions(assertionGroups) {
  // Methods to log text with colors
  const ansiColor = {
    blue: text => console.log(`\x1b[1m\x1b[34m${text}\x1b[39m\x1b[22m`),
    green: text => console.log(`\x1b[32m  ✔  ${text}\x1b[39m`),
    red: text => console.log(`\x1b[31m  ✖  ${text}\x1b[39m`)
  }

  // Log the results
  assertionGroups.forEach(group => {
    ansiColor.blue(group.title)

    group.assertions.forEach(assertion => {
      assertion.value === 'true'
        ? ansiColor.green(assertion.description)
        : ansiColor.red(assertion.description)
    })
  })

  console.log('\n')
}

We can format our input with colors depending on the results. To show colors on the terminal we need to add ANSI escape codes. To simplify their usage in the next block we have saved each color as methods of an ansiColor object.

First we want to show the title of the specification, remember that we are using the first dimension of the array for each specification, which we have named it as a group (of assertions.) Then we log all the assertions depending on their value using their respective color: green for assertions that evaluated as true and red for assertions that had another value. Note the comparison, we are checking for true, as a string, since we are receiving strings from each file.

Checking Results

Finally, the last step is to check if all the tests were successful or not.

function checkAssertions (assertionGroups) {
  return assertionGroups.some(
    group => group.assertions.some(assertion => assertion.value === 'false')
  ) ? 1 : 0
}

We check every assertion group (specification) to see if at least one value is '``false``' using the some() method of Array. We have nested two of them because we have a two dimensional array.

Running Our Program

At this point our CLI should be ready to run some JavaScript specifications and see if assertions are picked up and evaluated. In a test directory you can copy the specification example from the beginning of this article, and paste the following command inside your package.json file:

"scripts": {
  "test": "node index.js test"
}

… where test is the name of the directory where you have included the sample specification file.

When running the npm test command, you should see the results with their respective colors.

Last Words

We have implemented a very simple but useful command-line program that can help us to make better software. There are some lessons that we can gain from this:

  • Software can be simple and useful at the same time.
  • We can build our own tools if we want something different, there is no reason to conform.
  • Software is more than “making it work” but also about communicating ideas.
  • Some times we can improve something just by changing the point of view. In this case, the format of the specification files: just a simple string!

An example workflow for this program, would be to place one .spec.js file per module in your projects, describing in detail the intended functionality and properties that the program should have in form of assertions. You can sketch the idea of a new project in this way, and continuously improve until all the assertions have passed.

You can find the source code used in this article here.

Frequently Asked Questions (FAQs) about Runnable JavaScript Specifications

What is the significance of Runnable JavaScript Specifications?

Runnable JavaScript Specifications are crucial in the world of programming as they provide a clear and concise description of how a particular piece of code should behave. They are written in a language that both the computer and the developer can understand, making it easier to identify and fix any issues that may arise. These specifications serve as a guide, ensuring that the code performs as expected, thereby improving the overall quality of the software.

How do I write a Runnable JavaScript Specification?

Writing a Runnable JavaScript Specification involves defining the expected behavior of your code. You start by describing the function or method you’re testing, followed by defining the expected outcome. This is typically done using a testing framework like Jasmine or Mocha. These frameworks provide functions to help you define your specifications and check if your code meets them.

What are the benefits of using Runnable JavaScript Specifications?

Runnable JavaScript Specifications offer several benefits. They serve as documentation, providing a clear understanding of how the code works. They also make it easier to identify and fix bugs, as the specifications define the expected behavior of the code. Moreover, they facilitate collaboration among developers, as the specifications provide a common understanding of the code’s functionality.

How do Runnable JavaScript Specifications improve code quality?

Runnable JavaScript Specifications improve code quality by ensuring that the code behaves as expected. They provide a clear definition of the code’s behavior, making it easier to identify and fix any deviations. This leads to more reliable and robust software, as any issues are caught and addressed early in the development process.

Can Runnable JavaScript Specifications be used with any JavaScript testing framework?

Yes, Runnable JavaScript Specifications can be used with any JavaScript testing framework. These frameworks provide the necessary functions to define and check the specifications. Some popular JavaScript testing frameworks include Jasmine, Mocha, and Jest.

How do Runnable JavaScript Specifications facilitate collaboration among developers?

Runnable JavaScript Specifications facilitate collaboration by providing a common understanding of how the code works. They serve as a form of documentation, making it easier for developers to understand the code’s functionality and expected behavior. This makes it easier for multiple developers to work on the same codebase, as they all have a clear understanding of how the code should behave.

What is the role of ECMAScript in Runnable JavaScript Specifications?

ECMAScript is the standard that defines JavaScript, and it plays a crucial role in Runnable JavaScript Specifications. The specifications are written based on the ECMAScript standard, ensuring that they are compatible with any environment that supports JavaScript. This makes the specifications more reliable and robust, as they are based on a widely accepted standard.

How do I get results from a method into a spec.js testing file?

To get results from a method into a spec.js testing file, you need to call the method within a test case and then compare the result with the expected outcome. This is typically done using a function provided by your testing framework, such as expect in Jasmine or assert in Mocha.

How do I define method definitions in JavaScript?

Method definitions in JavaScript are defined within an object, using the methodName() {} syntax. The method name is followed by parentheses, which can include any parameters the method requires. The method’s functionality is then defined within the curly braces.

What is the ECMAScript 2023 spec for JavaScript?

The ECMAScript 2023 spec for JavaScript is the latest version of the ECMAScript standard, which defines JavaScript. It includes new features and improvements to the language, making it more powerful and easier to use. The spec is finalized by the TC39 committee, which is responsible for evolving JavaScript.

James KolceJames Kolce
View Author

Independent Web Developer, Designer and Technical Writer.

javascriptjoelfspecifications
Share this article
Read Next
Creating Fluid Typography with the CSS clamp() Function
Creating Fluid Typography with the CSS clamp() Function
Daine Mawer
Comparing Full Stack and Headless CMS Platforms
Comparing Full Stack and Headless CMS Platforms
Vultr
7 Easy Ways to Make a Magento 2 Website Faster
7 Easy Ways to Make a Magento 2 Website Faster
Konstantin Gerasimov
Powerful React Form Builders to Consider in 2024
Powerful React Form Builders to Consider in 2024
Femi Akinyemi
Quick Tip: How to Animate Text Gradients and Patterns in CSS
Quick Tip: How to Animate Text Gradients and Patterns in CSS
Ralph Mason
Sending Email Using Node.js
Sending Email Using Node.js
Craig Buckler
Creating a Navbar in React
Creating a Navbar in React
Vidura Senevirathne
A Complete Guide to CSS Logical Properties, with Cheat Sheet
A Complete Guide to CSS Logical Properties, with Cheat Sheet
Ralph Mason
Using JSON Web Tokens with Node.js
Using JSON Web Tokens with Node.js
Lakindu Hewawasam
How to Build a Simple Web Server with Node.js
How to Build a Simple Web Server with Node.js
Chameera Dulanga
Building a Digital Fortress: How to Strengthen DNS Against DDoS Attacks?
Building a Digital Fortress: How to Strengthen DNS Against DDoS Attacks?
Beloslava Petrova
Crafting Interactive Scatter Plots with Plotly
Crafting Interactive Scatter Plots with Plotly
Binara Prabhanga
GenAI: How to Reduce Cost with Prompt Compression Techniques
GenAI: How to Reduce Cost with Prompt Compression Techniques
Suvoraj Biswas
How to Use jQuery’s ajax() Function for Asynchronous HTTP Requests
How to Use jQuery’s ajax() Function for Asynchronous HTTP Requests
Aurelio De RosaMaria Antonietta Perna
Quick Tip: How to Align Column Rows with CSS Subgrid
Quick Tip: How to Align Column Rows with CSS Subgrid
Ralph Mason
15 Top Web Design Tools & Resources To Try in 2024
15 Top Web Design Tools & Resources To Try in 2024
SitePoint Sponsors
7 Simple Rules for Better Data Visualization
7 Simple Rules for Better Data Visualization
Mariia Merkulova
Cloudways Autonomous: Fully-Managed Scalable WordPress Hosting
Cloudways Autonomous: Fully-Managed Scalable WordPress Hosting
SitePoint Team
Best Programming Language for AI
Best Programming Language for AI
Lucero del Alba
Quick Tip: How to Add Gradient Effects and Patterns to Text
Quick Tip: How to Add Gradient Effects and Patterns to Text
Ralph Mason
Logging Made Easy: A Beginner’s Guide to Winston in Node.js
Logging Made Easy: A Beginner’s Guide to Winston in Node.js
Vultr
How to Optimize Website Content for Featured Snippets
How to Optimize Website Content for Featured Snippets
Dipen Visavadiya
Psychology and UX: Decoding the Science Behind User Clicks
Psychology and UX: Decoding the Science Behind User Clicks
Tanya Kumari
Build a Full-stack App with Node.js and htmx
Build a Full-stack App with Node.js and htmx
James Hibbard
Digital Transformation with AI: The Benefits and Challenges
Digital Transformation with AI: The Benefits and Challenges
Priyanka Prajapat
Quick Tip: Creating a Date Picker in React
Quick Tip: Creating a Date Picker in React
Dianne Pena
How to Create Interactive Animations Using React Spring
How to Create Interactive Animations Using React Spring
Yemi Ojedapo
10 Reasons to Love Google Docs
10 Reasons to Love Google Docs
Joshua KrausZain Zaidi
How to Use Magento 2 for International Ecommerce Success
How to Use Magento 2 for International Ecommerce Success
Mitul Patel
5 Exciting New JavaScript Features in 2024
5 Exciting New JavaScript Features in 2024
Olivia GibsonDarren Jones
Tools and Strategies for Efficient Web Project Management
Tools and Strategies for Efficient Web Project Management
Juliet Ofoegbu
Choosing the Best WordPress CRM Plugin for Your Business
Choosing the Best WordPress CRM Plugin for Your Business
Neve Wilkinson
ChatGPT Plugins for Marketing Success
ChatGPT Plugins for Marketing Success
Neil Jordan
Managing Static Files in Django: A Comprehensive Guide
Managing Static Files in Django: A Comprehensive Guide
Kabaki Antony
The Ultimate Guide to Choosing the Best React Website Builder
The Ultimate Guide to Choosing the Best React Website Builder
Dianne Pena
Exploring the Creative Power of CSS Filters and Blending
Exploring the Creative Power of CSS Filters and Blending
Joan Ayebola
How to Use WebSockets in Node.js to Create Real-time Apps
How to Use WebSockets in Node.js to Create Real-time Apps
Craig Buckler
Best Node.js Framework Choices for Modern App Development
Best Node.js Framework Choices for Modern App Development
Dianne Pena
SaaS Boilerplates: What They Are, And 10 of the Best
SaaS Boilerplates: What They Are, And 10 of the Best
Zain Zaidi
Understanding Cookies and Sessions in React
Understanding Cookies and Sessions in React
Blessing Ene Anyebe
Enhanced Internationalization (i18n) in Next.js 14
Enhanced Internationalization (i18n) in Next.js 14
Emmanuel Onyeyaforo
Essential React Native Performance Tips and Tricks
Essential React Native Performance Tips and Tricks
Shaik Mukthahar
How to Use Server-sent Events in Node.js
How to Use Server-sent Events in Node.js
Craig Buckler
Five Simple Ways to Boost a WooCommerce Site’s Performance
Five Simple Ways to Boost a WooCommerce Site’s Performance
Palash Ghosh
Elevate Your Online Store with Top WooCommerce Plugins
Elevate Your Online Store with Top WooCommerce Plugins
Dianne Pena
Unleash Your Website’s Potential: Top 5 SEO Tools of 2024
Unleash Your Website’s Potential: Top 5 SEO Tools of 2024
Dianne Pena
How to Build a Chat Interface using Gradio & Vultr Cloud GPU
How to Build a Chat Interface using Gradio & Vultr Cloud GPU
Vultr
Enhance Your React Apps with ShadCn Utilities and Components
Enhance Your React Apps with ShadCn Utilities and Components
David Jaja
10 Best Create React App Alternatives for Different Use Cases
10 Best Create React App Alternatives for Different Use Cases
Zain Zaidi
Control Lazy Load, Infinite Scroll and Animations in React
Control Lazy Load, Infinite Scroll and Animations in React
Blessing Ene Anyebe
Building a Research Assistant Tool with AI and JavaScript
Building a Research Assistant Tool with AI and JavaScript
Mahmud Adeleye
Understanding React useEffect
Understanding React useEffect
Dianne Pena
Web Design Trends to Watch in 2024
Web Design Trends to Watch in 2024
Juliet Ofoegbu
Building a 3D Card Flip Animation with CSS Houdini
Building a 3D Card Flip Animation with CSS Houdini
Fred Zugs
How to Use ChatGPT in an Unavailable Country
How to Use ChatGPT in an Unavailable Country
Dianne Pena
An Introduction to Node.js Multithreading
An Introduction to Node.js Multithreading
Craig Buckler
How to Boost WordPress Security and Protect Your SEO Ranking
How to Boost WordPress Security and Protect Your SEO Ranking
Jaya Iyer
Understanding How ChatGPT Maintains Context
Understanding How ChatGPT Maintains Context
Dianne Pena
Building Interactive Data Visualizations with D3.js and React
Building Interactive Data Visualizations with D3.js and React
Oluwabusayo Jacobs
JavaScript vs Python: Which One Should You Learn First?
JavaScript vs Python: Which One Should You Learn First?
Olivia GibsonDarren Jones
13 Best Books, Courses and Communities for Learning React
13 Best Books, Courses and Communities for Learning React
Zain Zaidi
5 jQuery.each() Function Examples
5 jQuery.each() Function Examples
Florian RapplJames Hibbard
Implementing User Authentication in React Apps with Appwrite
Implementing User Authentication in React Apps with Appwrite
Yemi Ojedapo
AI-Powered Search Engine With Milvus Vector Database on Vultr
AI-Powered Search Engine With Milvus Vector Database on Vultr
Vultr
Understanding Signals in Django
Understanding Signals in Django
Kabaki Antony
Why React Icons May Be the Only Icon Library You Need
Why React Icons May Be the Only Icon Library You Need
Zain Zaidi
View Transitions in Astro
View Transitions in Astro
Tamas Piros
Getting Started with Content Collections in Astro
Getting Started with Content Collections in Astro
Tamas Piros
What Does the Java Virtual Machine Do All Day?
What Does the Java Virtual Machine Do All Day?
Peter Kessler
Become a Freelance Web Developer on Fiverr: Ultimate Guide
Become a Freelance Web Developer on Fiverr: Ultimate Guide
Mayank Singh
Layouts in Astro
Layouts in Astro
Tamas Piros
.NET 8: Blazor Render Modes Explained
.NET 8: Blazor Render Modes Explained
Peter De Tender
Mastering Node CSV
Mastering Node CSV
Dianne Pena
A Beginner’s Guide to SvelteKit
A Beginner’s Guide to SvelteKit
Erik KückelheimSimon Holthausen
Brighten Up Your Astro Site with KwesForms and Rive
Brighten Up Your Astro Site with KwesForms and Rive
Paul Scanlon
Which Programming Language Should I Learn First in 2024?
Which Programming Language Should I Learn First in 2024?
Joel Falconer
Managing PHP Versions with Laravel Herd
Managing PHP Versions with Laravel Herd
Dianne Pena
Accelerating the Cloud: The Final Steps
Accelerating the Cloud: The Final Steps
Dave Neary
An Alphebetized List of MIME Types
An Alphebetized List of MIME Types
Dianne Pena
The Best PHP Frameworks for 2024
The Best PHP Frameworks for 2024
Claudio Ribeiro
11 Best WordPress Themes for Developers & Designers in 2024
11 Best WordPress Themes for Developers & Designers in 2024
SitePoint Sponsors
Top 10 Best WordPress AI Plugins of 2024
Top 10 Best WordPress AI Plugins of 2024
Dianne Pena
20+ Tools for Node.js Development in 2024
20+ Tools for Node.js Development in 2024
Dianne Pena
The Best Figma Plugins to Enhance Your Design Workflow in 2024
The Best Figma Plugins to Enhance Your Design Workflow in 2024
Dianne Pena
Harnessing the Power of Zenserp for Advanced Search Engine Parsing
Harnessing the Power of Zenserp for Advanced Search Engine Parsing
Christopher Collins
Build Your Own AI Tools in Python Using the OpenAI API
Build Your Own AI Tools in Python Using the OpenAI API
Zain Zaidi
The Best React Chart Libraries for Data Visualization in 2024
The Best React Chart Libraries for Data Visualization in 2024
Dianne Pena
7 Free AI Logo Generators to Get Started
7 Free AI Logo Generators to Get Started
Zain Zaidi
Turn Your Vue App into an Offline-ready Progressive Web App
Turn Your Vue App into an Offline-ready Progressive Web App
Imran Alam
Clean Architecture: Theming with Tailwind and CSS Variables
Clean Architecture: Theming with Tailwind and CSS Variables
Emmanuel Onyeyaforo
How to Analyze Large Text Datasets with LangChain and Python
How to Analyze Large Text Datasets with LangChain and Python
Matt Nikonorov
6 Techniques for Conditional Rendering in React, with Examples
6 Techniques for Conditional Rendering in React, with Examples
Yemi Ojedapo
Introducing STRICH: Barcode Scanning for Web Apps
Introducing STRICH: Barcode Scanning for Web Apps
Alex Suzuki
Using Nodemon and Watch in Node.js for Live Restarts
Using Nodemon and Watch in Node.js for Live Restarts
Craig Buckler
Task Automation and Debugging with AI-Powered Tools
Task Automation and Debugging with AI-Powered Tools
Timi Omoyeni
Quick Tip: Understanding React Tooltip
Quick Tip: Understanding React Tooltip
Dianne Pena
12 Outstanding AI Tools that Enhance Efficiency & Productivity
12 Outstanding AI Tools that Enhance Efficiency & Productivity
Ilija Sekulov
React Performance Optimization
React Performance Optimization
Blessing Ene Anyebe
Introducing Chatbots and Large Language Models (LLMs)
Introducing Chatbots and Large Language Models (LLMs)
Timi Omoyeni
Migrate to Ampere on OCI with Heterogeneous Kubernetes Clusters
Migrate to Ampere on OCI with Heterogeneous Kubernetes Clusters
Ampere Computing
Get the freshest news and resources for developers, designers and digital creators in your inbox each week